Release 0.5

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	* [misc/file.c]
	SetErrorMode added

	* [misc/dos_fs.c]
	bug fixes.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

       	* [misc/int21.c]
       	Modified.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

       	* [misc/int21.c]
       	Modified.


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

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

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

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

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

	* [windows/dialog.c]
	Modified CreateDialogParam() to use Find/LoadResource().
diff --git a/ChangeLog b/ChangeLog
index ebf46f1..151f65b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,295 @@
+Sun Jan  2 12:38:53 1994  David Metcalfe <david@prism.demon.co.uk>
+
+	* [windows/class.c]
+	Implemented GetClassName and GetClassInfo.
+
+	* [windows/caret.c]
+	Various improvements to text caret code.
+
+Fri Dec 31 15:22:22 1993  John Brezak <brezak@apollo.hp.com>
+
+	* [misc/comm.c]
+	Patches to work with NetBSD.
+
+Thu Dec 30 12:11:55 1993  John Richardson <jrichard@cs.uml.edu>
+
+	* [objects/bitblt.c] Added StretchBlt().
+
+Tue Jan  4 05:22:07 1994  julliard@di.epfl.ch (Alexandre Julliard)
+
+	* [misc/user.c]
+	Added creation of system message queue.
+
+	* [objects/bitmap.c] [objects/dcvalues.c] [windows/dc.c]
+	Added DC size fields into DC structure.		
+
+	* [objects/clipping.c]
+	Bug fix in CLIPPING_IntersectRect().
+
+	* [windows/class.c]
+	Allocate a DCE instead of a DC for CS_CLASSDC classes.
+
+	* [windows/clipping.c]
+	Fixed GetUpdateRect() and GetUpdateRgn() to clip to the client area.
+
+	* [windows/dce.c]
+	Implemented GetDCEx() and GetWindowDC().
+
+	* [windows/defwnd.c]
+	Implemented WM_WINDOWPOSCHANGED handling.
+
+	* [windows/event.c]
+	Preliminary support for Xlib event handling instead of Xt callbacks.
+	Changed MSG_AddMsg() calls to hardware_event() or PostMessage().
+
+	* [windows/message.c]
+	Preliminary support for multiple message queues.
+	Implemented hardware_event() to store messages into the system queue.
+	Implemented Get/SetTaskQueue().
+	Better WM_PAINT and WM_TIMER handling.
+	Changes to use Xlib instead of Xt for events.
+
+	* [windows/painting.c]
+	Use GetDCEx() to retrieve the DC, to get a correct visible region.
+
+	* [windows/timer.c]
+	Moved the timer procedure callback into DispatchMessage().
+	Changed implementation to get rid of Xt timeouts.  Timer checking
+	is now done inside GetMessage().
+
+	* [windows/win.c]
+	Allocate a DCE instead of a DC for CS_OWNDC windows.
+	Replaced Xt calls with Xlib calls.
+	Moved window positioning functions into windows/winpos.c
+
+	* [windows/winpos.c]  (New file)
+	Rewritten most of the window positioning functions.
+	Implemented SetWindowPos() and MapWindowPoints().
+
+Jan 3, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+
+	* [if1632/user.spec]
+	Bad arguments description for function SetDlgItemText.
+
+	* [objects/text.c]
+	Function DrawText now handle DT_CALCRECT request.
+
+	* [misc/message.c]
+	Message boxes now use DrawText with DT_CALCRECT.
+
+	* [windows/graphics.c]
+	Bug fix in function FrameRect, (it was using PEN instead of BRUSH).
+
+	* [windows/win.c]
+	Bug fix for flags in function ShowWindow.
+	More accurate WM_SIZE generated by function ShowWindow.
+
+	* [controls/listbox.c]
+	More code for LBS_MULTIPLESEL.
+	More code for LBS_MULTICOLUMN.
+
+	* [include/windows.h]
+	Bad define for MF_SEPARATOR.
+
+	* [controls/menu.c]
+	New functions: PopMenuWndProc() with 'glues',
+	CreatePopupMenu(), AppendMenu(), InsertMenu(), RemoveMenu(), 
+	DeleteMenu(), ModifyMenu(), TrackPopupMenu().
+	Code in stubs: CreateMenu(), DestroyMenu(). 
+
+Sat Jan  1 10:22:43 1994  Bob Amstadt  (bob@pooh)
+
+	* loader/wine.c: Added support for relocation types 5 and 6.
+
+----------------------------------------------------------------------
+Mon Dec 27 11:06:03 1993  Erik Bos (erik@trashcan.hacktic.nl)
+
+	* [misc/comm.c]
+	new functions: BuildCommDCB(), OpenComm(), CloseComm(),
+	SetCommBreak(), ClearCommBreak(), EscapeCommFunction(), FlushComm(),
+	GetCommError(), SetCommEventMask(), GetCommEventMask(),
+	SetCommState(), GetCommState(), TransmitCommChar(), ReadComm(), 
+	WriteComm().
+
+Wed Dec 22 13:00:15 1993  David Metcalfe <david@prism.demon.co.uk>
+
+	* [windows/caret.c]
+	Implemented text caret functions.
+
+Tue Dec 21 06:13:58 1993  julliard@di.epfl.ch (Alexandre Julliard)
+
+	* [loader/wine.c]
+	Bug fix in LoadImage().
+
+	* [objects/bitblt.c] [objects/clipping.c] [objects/text.c]
+	  [windows/dc.c] [windows/dce.c] [windows/graphics.c]
+	Modified graphics calls to take into account the DC origin.
+
+	* [windows/defwnd.c]
+	Added preliminary WM_NCCALCSIZE handling.
+
+	* [windows/event.c]
+	Send WM_NCCALCSIZE message on resize event.
+
+	* [windows/win.c]
+	Send WM_NCCALCSIZE message in CreateWindow().
+	Realize widgets at creation time (should prevent problems with
+	unrealized widgets).
+
+Dec 19, 93 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+
+	* [controls/static.c]
+	Send mouse & keyboard message received to its parent.
+
+	* [controls/scroll.c]
+	Send keyboard message received to its parent.
+
+	* [controls/listbox.c]
+	Add Navigation keys .
+	ListBox now use VSCROLL & HSCROLL instead of children.
+	Alpha version of LBS_MULTIPLESEL.
+	Alpha version of LBS_MULTICOLUMN.
+
+	* [controls/combo.c]
+	Add Navigation keys on closed ComboBox.
+	Remove useless 'COMBOBOX_CreateComboBox' function.
+
+Mon Dec 19 20:39:34 1993  Erik Bos (erik@trashcan.hacktic.nl)
+
+	* [loader/wine.
+	LoadImage() modified to use FindFile().
+
+	* [misc/file.c]
+	SetErrorMode added
+
+	* [misc/dos_fs.c]
+	bug fixes.
+
+Dec 13, 93 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+
+	* [memory/global.c]
+	bug fix in GlobalGetFreeSegment : good ptr in 'g_prev'.
+
+	* [sysres.dll]
+	preliminary version of a 'glass of wine' bitmap
+
+	* [windows/event.c]
+	New function 'GetCapture'.
+
+	* [controls/scroll.c]
+	Remove useless 'SCROLLBAR_CreateScrollBar' function.
+
+	* [controls/listbox.c]
+	Remove useless 'LISTBOX_CreateListBox' function.
+
+Mon Dec 13 13:51:00 1993  David Metcalfe <david@prism.demon.co.uk>
+
+	* [objects/font.c]
+	Corrected bugs in GetCharWidth().
+
+	* [windows/event.c]
+	Modified EVENT_key to send Windows virtual key codes for
+	WM_KEYDOWN and WM_KEYUP messages, and a WM_CHAR message
+	for printable characters.
+
+Wed Dec 08 19:20:00 1993  Karl Guenter Wuensch (hn324wu@unidui.uni-duisburg.de)
+
+	* [windows/graphics.c]
+	Added Polyline and Polygon
+
+Mon Dec 13 14:51:54 1993  Erik Bos (erik@trashcan.hacktic.nl)
+
+	* [controls/listbox.c]
+	ListBoxDirectory() modified to use dos_fs.c's functions to
+	access files&|drives.
+
+Sat Dec 04 17:04:23 1993  Erik Bos (erik@trashcan.hacktic.nl)
+
+       	* [misc/dos_fs.c]
+       	Added FindFile() to search a file in a dos/unix style path.
+	
+	* [misc/file.c]
+	New Win31 functions: OpenFile, _lcreate, _llseek, GetTempDrive,
+	GetTempFileName, GetWindowsDirectory, GetSystemDirectory,
+	GetDriveType.			   
+
+       	* [misc/int21.c]
+       	Modified.
+
+Wed Dec  1 16:20:45 1993  Miguel de Icaza  (miguel@roxanne.nuclecu.unam.mx)
+
+        * [misc/profile.c]
+        The Profile functions now return the correct values. They now
+        implement all the features described in the SDK.
+
+Tue Nov 30 13:55:27 1993  Bob Amstadt  (bob at amscons)
+
+	* [loader/selector.c]
+	Rewrote selector aliasing routines to use System V IPC
+	routine to alias memory segments.
+
+Nov 28, 93 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+
+	* [controls/listbox.c]
+	More consistency in functions using wIndexes
+
+	* [controls/scroll.c]
+	New function : ShowScrollBar().
+
+	* [loader/cursor.c] ... New file
+	Move cursor functions from [loader/resource.c].
+	New function : ClipCursor().
+	New function : GetClipCursor().
+	New function : CreateCursor().
+	SetCursor() now working using gloabal variable 'winHasCursor'.
+
+	*[object/palette.c]
+	New stub only : SelectPalette().
+	New stub only : RealizePalette().
+
+	*[win/event.c]
+	New function : EVENT_enter_notify(),
+		update 'winHasCursor' and send WM_SETCURSOR.
+
+	*[win/defwnd.c]
+	Add processing of WM_SETCURSOR message.
+
+	*[win/win.c]
+	New members in WND structure : hCursor, hWndVScroll & hWndHScroll. 
+	CreateWindowEx() now create children for WM_HSCROLL & WM_VSCROLL.
+	New function ClientToScreen().
+	New function ScreenToClient().
+
+Mon Nov 25 18:25:40 1993  Erik Bos (erik@trashcan.hacktic.nl)
+
+       	* [files.h / regfunc.h / misc/dos.c]
+       	Removed.
+
+       	* [misc/dos_fs.c]
+       	Added support for loading dosdrive cfg from wine.ini.
+
+       	* [misc/int21.c]
+       	Modified.
+
+
+Wed Nov 24 11:37:33 1993  julliard@disuns2.epfl.ch (Alexandre Julliard)
+
+	* [include/atom.h] [memory/atom.c]
+	Implemented atoms.
+
+	* [windows/class.c]
+	Modified RegisterClass() to use atoms.
+	Implemented CS_GLOBALCLASS style.
+
+	* [windows/message.c]
+	Implemented RegisterWindowMessage().
+
+	* [loader/resource.c]
+	Bug fix in LoadResource().
+
+	* [windows/dialog.c]
+	Modified CreateDialogParam() to use Find/LoadResource().
+
 Mon Nov 22 13:58:56 1993  David Metcalfe <david@prism.demon.co.uk>
 
         * [windows/scroll.c]
@@ -37,7 +329,6 @@
 	* [sysres.dll]
 	Resources only 16bits DLL for System Resources, icons, etc...
 
-----------------------------------------------------------------------
 Sun Nov 14 14:39:06 1993  julliard@di.epfl.ch (Alexandre Julliard)
 
 	* [include/dialog.h] [windows/dialog.c]
diff --git a/Imakefile b/Imakefile
new file mode 100644
index 0000000..26b35f4
--- /dev/null
+++ b/Imakefile
@@ -0,0 +1,66 @@
+#include "Wine.tmpl"
+
+/*
+ * This is the first try at using Imakefiles. There are probably many
+ * problems and things I haven't even considered. I do not have a Linux
+ * system to test them on, just NetBSD, so you may need to change things
+ * like the the SYSLIBS definition below...
+ *
+ * Peter Galbavy, 5th Dec 1993 peter@wonderland.org
+ */
+
+#define IHaveSubDirs
+#define	PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)' 'CC=$(CC)'
+
+SUBDIRS = \
+	tools \
+	controls \
+	debugger \
+	etc \
+	if1632 \
+	include \
+	loader \
+	memory \
+	misc \
+	objects \
+	test \
+	windows
+
+WINEDIR = $(LIBDIR)/wine
+
+OBJS = \
+	if1632.o \
+	controls.o \
+	loader.o \
+	memory.o \
+	misc.o \
+	objects.o \
+	windows.o \
+	debugger.o \
+	readline.o
+
+#ifdef i386BsdArchitecture
+SYSLIBS = -ll -lm -li386 -lgnumalloc
+#else
+#ifdef LinuxArchitechture
+SYSLIBS = -lm
+#endif
+#endif
+
+AllTarget(wine)
+
+NamedTargetSubdirs($(OBJS),$(SUBDIRS),"making",PassCDebugFlags,all)
+MakefileSubdirs($(SUBDIRS))
+DependSubdirs($(SUBDIRS))
+IncludesSubdirs($(SUBDIRS))
+CleanSubdirs($(SUBDIRS))
+
+NormalProgramTarget(wine,$(OBJS),XawClientDepLibs,XawClientLibs,$(SYSLIBS))
+
+depend::
+
+install::
+
+includes::
+
+clean::
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..3854e93
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1 @@
+All code unless stated otherwise is covered by the GNU Pubic License.
diff --git a/Makefile b/Makefile
index 11a884a..1f7221c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 ######################################################################
 # These variables are inherited by the sub-makefiles
-DEBUGOPTS=
+DEBUGOPTS=-DUSE_XLIB
 COPTS=-O2 -m486
 INCLUDE_DIR=include
 LDFLAGS=
@@ -12,11 +12,17 @@
 OBJS=if1632/if1632.o controls/controls.o loader/loader.o \
 	memory/memory.o misc/misc.o objects/objects.o windows/windows.o debugger/debugger.o
 SUBDIRS=if1632 controls loader memory misc objects windows debugger
+TAGFILES=if1632/{*.c,*.S} controls/{*.c,*.S} loader/{*.c,*.S} \
+	memory/{*.c,*.S} misc/{*.c,*.S} objects/{*.c,*.S} \
+	windows/{*.c,*.S} debugger/{*.c,*.S}
 
 all: $(TARGET)
 
 dummy:
 
+tags:
+	etags $(TAGFILES)
+
 clean:
 	rm -f *~ *.o *#
 	@for i in tools $(SUBDIRS); do (cd $$i && $(MAKE) clean) || exit; done
diff --git a/PROPOSED_LICENSE b/PROPOSED_LICENSE
new file mode 100644
index 0000000..a7d2f7a
--- /dev/null
+++ b/PROPOSED_LICENSE
@@ -0,0 +1,29 @@
+You may without charge, royalty or other payment, copy and
+distribute copies of this work and derivative works of this work
+in source or binary form provided that: (1) 
+you appropriately publish on each copy an appropriate copyright
+notice; (2) faithfully reproduce all prior copyright notices
+included in the original work (you may also add your own
+copyright notice); and (3) agree to indemnify and hold all prior
+authors, copyright holders and licensors of the work harmless
+from and against all damages arising from use of the work.
+
+You may distribute sources of derivative works of the work
+provided that (1) (a) all source files of the original work that
+have been modified, (b) all source files of the derivative work
+that contain any party of the original work, and (c) all source
+files of the derivative work that are necessary to compile, link
+and run the derivative work without unresolved external calls and
+with the same functionality of the original work ("Necessary
+Sources") carry a prominent notice explaining the nature and date
+of the modification and/or creation.  You are encouraged to make
+the Necessary Sources available under this license in order to
+further the development and acceptance of the work.
+
+EXCEPT AS OTHERWISE RESTRICTED BY LAW, THIS WORK IS PROVIDED
+WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND, INCLUDING
+BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF FITNESS FOR A
+PARTICULAR PURPOSE, MERCHANTABILITY OR TITLE.  EXCEPT AS
+OTHERWISE PROVIDED BY LAW, NO AUTHOR, COPYRIGHT HOLDER OR
+LICENSOR SHALL BE LIABLE TO YOU FOR DAMAGES OF ANY KIND, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
diff --git a/README b/README
index ba0b81b..1b090d4 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
 Copyright  Robert J. Amstadt, 1993.  All code is provided without
-warranty.  It is my intent to cover this code with the Gnu Public
-License.
+warranty.  All code is covered by the license contained in the file
+LICENSE unless explicitly stated in the individual source file.
 
 INSTALLATION:
 
@@ -19,18 +19,56 @@
 
 To build Wine, first do a "make depend" and then a "make".  The
 executable "wine" will be built.  "wine" will load and run Windows'
-executables.  You must specify the entire path to the executable,
-have the executable in the current directory, or specify a load
-path with environment variable WINEPATH.
+executables.  You must have a file "wine.ini" in the current directory,
+your homedirectory, or in the path specified by the environment 
+variable WINEPATH. Multiple directories in WINEPATH should be seperated
+by semi-colons and NOT by colons!
 
-For example, to run Windows' solitaire:
+You must specify the entire path to the executable, or a filename only
+(using the path= statement in wine.ini as the search path)
 
-	export WINEPATH=/dos/windows;/dos/windows/system
-	wine sol
+For example: to run Windows' solitaire:
+
+	export WINEPATH=/etc;/usr/windows
+
+	wine sol		   (using the path= statement in wine.ini
+	wine sol.exe		    as the search path)
+
+	wine c:\\windows\\sol.exe  (using a dosfilename)
+
+	wine /usr/windows/sol.exe  (using a unixfilename)
 
 Have a nice game of solitaire, but be careful.  Emulation isn't perfect.
 So, occassionally it will crash.
 
+WHAT'S NEW with version 0.5: (see ChangeLog for details)
+	- Working towards elimination of Xt-dependent code.
+	- StretchBlt()
+	- GetClassName() & GetClassInfo()
+	- Implemented loader relocation types 5 and 6.
+
+WHAT'S NEW with version 0.4.14: (see ChangeLog for details)
+	- Bug fixes and enhancements
+	- Comm functions
+	- Text caret functions
+
+WHAT'S NEW with version 0.4.13: (see ChangeLog for details)
+	- Bug fixes
+	- GetCapture()
+	- More keyboard handling
+	- Polyline() and Polygon()
+
+WHAT'S NEW with version 0.4.12: (see ChangeLog for details)
+	- Bug fixes
+	- New DOS file functions
+	- Experimental Imakefiles
+
+WHAT'S NEW with version 0.4.11: (see ChangeLog for details)
+	- Bug fixes
+	- New cursor functions
+	- New file system handling
+	- Atoms
+
 WHAT'S NEW with version 0.4.10: (see ChangeLog for details)
 	- Bug fixes
 	- More scroll bar functions
diff --git a/WARRANTY b/WARRANTY
new file mode 100644
index 0000000..492af84
--- /dev/null
+++ b/WARRANTY
@@ -0,0 +1,7 @@
+EXCEPT AS OTHERWISE RESTRICTED BY LAW, THIS WORK IS PROVIDED
+WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES OF ANY KIND, INCLUDING
+BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF FITNESS FOR A
+PARTICULAR PURPOSE, MERCHANTABILITY OR TITLE.  EXCEPT AS
+OTHERWISE PROVIDED BY LAW, NO AUTHOR, COPYRIGHT HOLDER OR
+LICENSOR SHALL BE LIABLE TO YOU FOR DAMAGES OF ANY KIND, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
diff --git a/Wine.tmpl b/Wine.tmpl
new file mode 100644
index 0000000..3bb9466
--- /dev/null
+++ b/Wine.tmpl
@@ -0,0 +1,29 @@
+XCOMM $Id$
+
+INCLUDES = -I$(TOP)/include
+
+XCOMM Imake rules go here
+
+XCOMM First, dll description to files etc
+#ifndef MakeDllFromSpec
+#define MakeDllFromSpec(name,objfile)					@@\
+objfile.o: Concat(dll_,name.o) Concat3(dll_,name,_tab.o)		@@\
+									@@\
+Concat(dll_,name.S) Concat3(dll_,name,_tab.c): name.spec $(TOP)/tools/build  @@\
+	$(TOP)/tools/build name.spec					@@\
+
+#endif
+
+/*
+ * WineRelocatableTarget - generate rules to produce a relocatable object
+ * file instead of a library.  
+ */
+#ifndef WineRelocatableTarget
+#define WineRelocatableTarget(objname,objlist,depobj)				@@\
+AllTarget(objname.o)							@@\
+									@@\
+objname.o: depobj							@@\
+	$(RM) $@							@@\
+	$(LD) $(LDCOMBINEFLAGS) objlist depobj -o $@
+#endif /* WineRelocatableTarget */
+
diff --git a/bsdmake.patch b/bsdmake.patch
index 99fa57a..68fa157 100644
--- a/bsdmake.patch
+++ b/bsdmake.patch
@@ -6,7 +6,7 @@
  # These definitions are for the top level
  TARGET=wine
 -LIBS=-L. -L/usr/X386/lib -lXext -lXaw -lXt -lXmu -lX11 -lm
-+LIBS=-L. -L/usr/X386/lib -lXext -lXaw -lXt -lXmu -lX11 -lm -li386 -lgnumalloc
++LIBS=-L. -L/usr/X386/lib -lXext -lXaw -lXt -lXmu -lX11 -lm -li386 -lgnumalloc -ll
  OBJS=if1632/if1632.o controls/controls.o loader/loader.o \
  	memory/memory.o misc/misc.o objects/objects.o windows/windows.o
  SUBDIRS=if1632 controls loader memory misc objects windows
diff --git a/controls/Imakefile b/controls/Imakefile
new file mode 100644
index 0000000..aee3e14
--- /dev/null
+++ b/controls/Imakefile
@@ -0,0 +1,37 @@
+#include "../Wine.tmpl"
+
+MODULE = controls
+
+SRCS = \
+	menu.c \
+	widgets.c \
+	button.c \
+	scroll.c \
+	listbox.c \
+	combo.c \
+	static.c \
+	SmeMenuButto.c \
+	WinLabel.c \
+	WinCommand.c \
+	WinMenuButto.c
+
+OBJS = \
+	menu.o \
+	widgets.o \
+	button.o \
+	scroll.o \
+	listbox.o \
+	combo.o \
+	static.o \
+	SmeMenuButto.o \
+	WinLabel.o \
+	WinCommand.o \
+	WinMenuButto.o
+
+WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
+DependTarget()
+CleanTarget()
+
+includes::
+
+install::
diff --git a/controls/combo.c b/controls/combo.c
index e471589..c8e32b9 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -17,60 +17,24 @@
 #include "combo.h"
 #include "heap.h"
 #include "win.h"
-#include "dirent.h"
+#include <sys/types.h>
+#include <dirent.h>
 #include <sys/stat.h>
 
 LPHEADCOMBO ComboGetStorageHeader(HWND hwnd);
 int CreateComboStruct(HWND hwnd);
 
 
-void COMBOBOX_CreateComboBox(LPSTR className, LPSTR comboLabel, HWND hwnd)
-{
-    WND *wndPtr    = WIN_FindWndPtr(hwnd);
-    WND *parentPtr = WIN_FindWndPtr(wndPtr->hwndParent);
-    DWORD style;
-    char widgetName[15];
-
-#ifdef DEBUG_COMBO
-    printf("combo: label = %s, x = %d, y = %d\n", comboLabel,
-	   wndPtr->rectClient.left, wndPtr->rectClient.top);
-    printf("        width = %d, height = %d\n",
-	   wndPtr->rectClient.right - wndPtr->rectClient.left,
-	   wndPtr->rectClient.bottom - wndPtr->rectClient.top);
-#endif
-
-    if (!wndPtr)
-	return;
-
-    style = wndPtr->dwStyle & 0x0000FFFF;
-/*
-    if ((style & LBS_NOTIFY) == LBS_NOTIFY)
-*/    
-    sprintf(widgetName, "%s%d", className, wndPtr->wIDmenu);
-    wndPtr->winWidget = XtVaCreateManagedWidget(widgetName,
-				    compositeWidgetClass,
-				    parentPtr->winWidget,
-				    XtNx, wndPtr->rectClient.left,
-				    XtNy, wndPtr->rectClient.top,
-				    XtNwidth, wndPtr->rectClient.right -
-				        wndPtr->rectClient.left,
-				    XtNheight, 16,
-				    NULL );
-    GlobalUnlock(hwnd);
-    GlobalUnlock(wndPtr->hwndParent);
-}
-
-
 /***********************************************************************
- *           WIDGETS_ComboWndProc
+ *           ComboWndProc
  */
-LONG COMBOBOX_ComboBoxWndProc( HWND hwnd, WORD message,
-			   WORD wParam, LONG lParam )
+LONG ComboBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 {    
     WORD	wRet;
     RECT	rect;
-    int		y;
+    int		y, count;
     int		width, height;
+    int		AltState;
     WND  	*wndPtr;
     LPHEADCOMBO lphc;
     char	str[128];
@@ -106,17 +70,20 @@
     case WM_DESTROY:
 	lphc = ComboGetStorageHeader(hwnd);
 	if (lphc == 0) return 0;
+/*
 	DestroyWindow(lphc->hWndDrop);
 	DestroyWindow(lphc->hWndEdit);
-/*
-	DestroyWindow(lphc->hWndLBox);
 */
+	DestroyWindow(lphc->hWndLBox);
 	free(lphc);
-	*((LPHEADCOMBO *)&wndPtr->wExtra[1]) = 0;
+/*
+	*((LPHEADCOMBO *)&wndPtr->wExtra[1]) = 0; 
+        printf("Combo WM_DESTROY after clearing wExtra !\n");
+*/
 #ifdef DEBUG_COMBO
         printf("Combo WM_DESTROY %lX !\n", lphc);
 #endif
-	return 0;
+	return DefWindowProc( hwnd, message, wParam, lParam );
 	
     case WM_COMMAND:
 	wndPtr = WIN_FindWndPtr(hwnd);
@@ -169,9 +136,56 @@
 	break;
     case WM_LBUTTONDOWN:
         printf("Combo WM_LBUTTONDOWN wParam=%x lParam=%lX !\n", wParam, lParam);
+	wndPtr = WIN_FindWndPtr(hwnd);
+	lphc = ComboGetStorageHeader(hwnd);
+	lphc->dwState = lphc->dwState ^ CB_SHOWDROPDOWN;
+	if ((lphc->dwState & CB_SHOWDROPDOWN) == CB_SHOWDROPDOWN)
+	    ShowWindow(lphc->hWndLBox, SW_SHOW);
 	break;
     case WM_KEYDOWN:
-        printf("Combo WM_KEYDOWN wParam %X!\n", wParam);
+	wndPtr = WIN_FindWndPtr(hwnd);
+	lphc = ComboGetStorageHeader(hwnd);
+	y = SendMessage(lphc->hWndLBox, LB_GETCURSEL, 0, 0L);
+	count = SendMessage(lphc->hWndLBox, LB_GETCOUNT, 0, 0L);
+	printf("COMBOBOX // GetKeyState(VK_MENU)=%d\n", GetKeyState(VK_MENU));
+	if (GetKeyState(VK_MENU) < 0) {
+	    lphc->dwState = lphc->dwState ^ CB_SHOWDROPDOWN;
+	    if ((lphc->dwState & CB_SHOWDROPDOWN) == CB_SHOWDROPDOWN) {
+		ShowWindow(lphc->hWndLBox, SW_SHOW);
+		}
+	    else {
+		ShowWindow(lphc->hWndLBox, SW_HIDE);
+		y = SendMessage(lphc->hWndLBox, LB_GETCURSEL, 0, 0L);
+		if (y != LB_ERR) {
+		    SendMessage(lphc->hWndLBox, LB_GETTEXT, (WORD)y, (LPARAM)str);
+		    SendMessage(lphc->hWndEdit, WM_SETTEXT, (WORD)y, (LPARAM)str);
+		    }
+		}
+	    }
+	else
+	    {
+	    switch(wParam) {
+		case VK_HOME:
+		    y = 0;
+			break;
+		case VK_END:
+		    y = count - 1;
+		    break;
+		case VK_UP:
+		    y--;
+		    break;
+		case VK_DOWN:
+		    y++;
+		    break;
+		}
+	    if (y < 0) y = 0;
+	    if (y >= count) y = count - 1;
+	    SendMessage(lphc->hWndLBox, LB_SETCURSEL, y, 0L);
+	    SendMessage(lphc->hWndLBox, LB_GETTEXT, (WORD)y, (LPARAM)str);
+	    SendMessage(lphc->hWndEdit, WM_SETTEXT, (WORD)y, (LPARAM)str);
+	    SendMessage(GetParent(hwnd), WM_COMMAND, wndPtr->wIDmenu,
+				    MAKELONG(hwnd, CBN_SELCHANGE));
+	    }
 	break;
     case WM_CTLCOLOR:
     	return(SendMessage(GetParent(hwnd), WM_CTLCOLOR, wParam, lParam));
diff --git a/controls/listbox.c b/controls/listbox.c
index a71eb92..b1dfb73 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -11,16 +11,21 @@
 
 static char Copyright[] = "Copyright Martin Ayotte, 1993";
 
+#include <stdio.h>
 #include <X11/Intrinsic.h>
 #include <X11/StringDefs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
 #include "windows.h"
 #include "user.h"
 #include "heap.h"
 #include "win.h"
+#include "wine.h"
 #include "listbox.h"
 #include "scroll.h"
-#include "dirent.h"
-#include <sys/stat.h>
+#include "int21.h"
+#include "prototypes.h"
 
 #define GMEM_ZEROINIT 0x0040
 
@@ -38,7 +43,8 @@
 int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr);
 int ListBoxResetContent(HWND hwnd);
 int ListBoxSetCurSel(HWND hwnd, WORD wIndex);
-int ListBoxSetSel(HWND hwnd, WORD wIndex);
+int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state);
+int ListBoxGetSel(HWND hwnd, WORD wIndex);
 int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec);
 int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT rect);
 int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height);
@@ -47,59 +53,16 @@
 int ListBoxFindNextMatch(HWND hwnd, WORD wChar);
 
 
-
-void LISTBOX_CreateListBox(LPSTR className, LPSTR listboxLabel, HWND hwnd)
-{
-    WND *wndPtr    = WIN_FindWndPtr(hwnd);
-    WND *parentPtr = WIN_FindWndPtr(wndPtr->hwndParent);
-    DWORD style;
-    char widgetName[15];
-
-#ifdef DEBUG_LISTBOX
-    printf("listbox: label = %s, x = %d, y = %d\n", listboxLabel,
-	   wndPtr->rectClient.left, wndPtr->rectClient.top);
-    printf("        width = %d, height = %d\n",
-	   wndPtr->rectClient.right - wndPtr->rectClient.left,
-	   wndPtr->rectClient.bottom - wndPtr->rectClient.top);
-#endif
-
-    if (!wndPtr)
-	return;
-
-    style = wndPtr->dwStyle & 0x0000FFFF;
-/*
-    if ((style & LBS_NOTIFY) == LBS_NOTIFY)
-    if ((style & LBS_SORT) == LBS_SORT)
-*/    
-    sprintf(widgetName, "%s%d", className, wndPtr->wIDmenu);
-    wndPtr->winWidget = XtVaCreateManagedWidget(widgetName,
-				    compositeWidgetClass,
-				    parentPtr->winWidget,
-				    XtNx, wndPtr->rectClient.left,
-				    XtNy, wndPtr->rectClient.top,
-				    XtNwidth, wndPtr->rectClient.right -
-				        wndPtr->rectClient.left,
-				    XtNheight, wndPtr->rectClient.bottom -
-				        wndPtr->rectClient.top,
-				    NULL );
-    GlobalUnlock(hwnd);
-    GlobalUnlock(wndPtr->hwndParent);
-}
-
-
-
 /***********************************************************************
- *           WIDGETS_ListBoxWndProc
+ *           ListBoxWndProc 
  */
-LONG LISTBOX_ListBoxWndProc( HWND hwnd, WORD message,
-			   WORD wParam, LONG lParam )
+LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 {    
     WND  *wndPtr;
     LPHEADLIST  lphl;
     WORD	wRet;
     RECT	rect;
     int		y;
-    int		width, height;
     CREATESTRUCT *createStruct;
     static RECT rectsel;
     switch(message)
@@ -115,19 +78,23 @@
 	    lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
 	else
 	    lphl->hWndLogicParent = GetParent(hwnd);
-	width = wndPtr->rectClient.right - wndPtr->rectClient.left;
-	height = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
-	lphl->hWndScroll = CreateWindow("SCROLLBAR", "",
-		WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBS_VERT,
-		width - 17, 0, 16, height, hwnd, 1, wndPtr->hInstance, NULL);
-    	ShowWindow(lphl->hWndScroll, SW_HIDE);
-	SetScrollRange(lphl->hWndScroll, WM_VSCROLL, 1, lphl->ItemsCount, TRUE);
+	lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
+	if (wndPtr->hWndVScroll != (HWND)NULL) {
+	    SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
+	    ShowScrollBar(hwnd, SB_VERT, FALSE);
+	    }
+	if (wndPtr->hWndHScroll != (HWND)NULL) {
+	    SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
+	    ShowScrollBar(hwnd, SB_HORZ, FALSE);
+	    }
+	if (wndPtr->hCursor == (HCURSOR)NULL)
+	    wndPtr->hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
 	return 0;
     case WM_DESTROY:
-        lphl = ListBoxGetStorageHeader(hwnd);
+	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
         if (lphl == 0) return 0;
 	ListBoxResetContent(hwnd);
-	DestroyWindow(lphl->hWndScroll);
+	DestroyCursor(wndPtr->hCursor);
 	free(lphl);
 	*((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
 #ifdef DEBUG_LISTBOX
@@ -164,23 +131,74 @@
 	if (lphl->FirstVisible > lphl->ItemsCount)
 	    lphl->FirstVisible = lphl->ItemsCount;
 	if (y != lphl->FirstVisible) {
-	    SetScrollPos(lphl->hWndScroll, WM_VSCROLL, lphl->FirstVisible, TRUE);
+	    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 	    InvalidateRect(hwnd, NULL, TRUE);
 	    UpdateWindow(hwnd);
             }
 	return 0;
 	
+    case WM_HSCROLL:
+        lphl = ListBoxGetStorageHeader(hwnd);
+        if (lphl == NULL) return 0;
+        y = lphl->FirstVisible;
+        switch(wParam) {
+            case SB_LINEUP:
+		if (lphl->FirstVisible > 1)
+		    lphl->FirstVisible -= lphl->ItemsPerColumn;
+		break;
+            case SB_LINEDOWN:
+		if (lphl->FirstVisible < lphl->ItemsCount)
+		    lphl->FirstVisible += lphl->ItemsPerColumn;
+		break;
+	    case SB_PAGEUP:
+		if (lphl->FirstVisible > 1 && lphl->ItemsPerColumn != 0)  
+		    lphl->FirstVisible -= lphl->ItemsVisible /
+		    	lphl->ItemsPerColumn * lphl->ItemsPerColumn;
+		break;
+	    case SB_PAGEDOWN:
+		if (lphl->FirstVisible < lphl->ItemsCount &&
+			lphl->ItemsPerColumn != 0)  
+		    lphl->FirstVisible += lphl->ItemsVisible /
+		    	lphl->ItemsPerColumn * lphl->ItemsPerColumn;
+		break;
+	    case SB_THUMBTRACK:
+	    	lphl->FirstVisible = lphl->ItemsPerColumn * 
+			(LOWORD(lParam) - 1) + 1;
+		break;
+	    }
+	if (lphl->FirstVisible < 1)    lphl->FirstVisible = 1;
+	if (lphl->FirstVisible > lphl->ItemsCount)
+	    lphl->FirstVisible = lphl->ItemsCount;
+	if (lphl->ItemsPerColumn != 0) {
+	    lphl->FirstVisible = lphl->FirstVisible /
+		lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
+	    if (y != lphl->FirstVisible) {
+		SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible / 
+		    lphl->ItemsPerColumn + 1, TRUE);
+		InvalidateRect(hwnd, NULL, TRUE);
+		UpdateWindow(hwnd);
+		}
+            }
+	return 0;
+	
     case WM_LBUTTONDOWN:
 /*
 	SetFocus(hwnd);
 */
 	SetCapture(hwnd);
-        lphl = ListBoxGetStorageHeader(hwnd);
+	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
         if (lphl == NULL) return 0;
-	lphl->PrevSelected = lphl->ItemSelected;
-        wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
-	ListBoxSetCurSel(hwnd, wRet);
-	ListBoxGetItemRect(hwnd, wRet, &rectsel);
+	lphl->PrevFocused = lphl->ItemFocused;
+        y = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
+	if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
+	    lphl->ItemFocused = y;
+	    wRet = ListBoxGetSel(hwnd, y);
+	    ListBoxSetSel(hwnd, y, !wRet);
+	    }
+	else {
+	    ListBoxSetCurSel(hwnd, y);
+	    }
+	ListBoxGetItemRect(hwnd, y, &rectsel);
         InvalidateRect(hwnd, NULL, TRUE);
         UpdateWindow(hwnd);
 	return 0;
@@ -188,7 +206,7 @@
 	ReleaseCapture();
 	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
         if (lphl == NULL) return 0;
-	if (lphl->PrevSelected != lphl->ItemSelected)
+	if (lphl->PrevFocused != lphl->ItemFocused)
 	    SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
 		        	MAKELONG(hwnd, LBN_SELCHANGE));
 	return 0;
@@ -200,9 +218,102 @@
 		        	MAKELONG(hwnd, LBN_DBLCLK));
         printf("ListBox Send LBN_DBLCLK !\n");
 	return 0;
+    case WM_MOUSEMOVE:
+        if ((wParam & MK_LBUTTON) != 0) {
+            y = HIWORD(lParam);
+	    if (y < 4) {
+	        lphl = ListBoxGetStorageHeader(hwnd);
+		if (lphl->FirstVisible > 1) {
+		    lphl->FirstVisible--;
+		    if (wndPtr->hWndVScroll != (HWND)NULL)
+			SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+		    InvalidateRect(hwnd, NULL, TRUE);
+		    UpdateWindow(hwnd);
+		    break;
+		    }
+		}
+	    GetClientRect(hwnd, &rect);
+	    if (y > (rect.bottom - 4)) {
+	        lphl = ListBoxGetStorageHeader(hwnd);
+		if (lphl->FirstVisible < lphl->ItemsCount) {
+		    lphl->FirstVisible++;
+		    if (wndPtr->hWndVScroll != (HWND)NULL)
+			SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+		    InvalidateRect(hwnd, NULL, TRUE);
+		    UpdateWindow(hwnd);
+		    break;
+		    }
+		}
+	    if ((y > 0) && (y < (rect.bottom - 4))) {
+		if ((y < rectsel.top) || (y > rectsel.bottom)) {
+		    wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
+		    if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
+			lphl->ItemFocused = wRet;
+		        }
+		    else {
+		        ListBoxSetCurSel(hwnd, wRet);
+		        }
+		    ListBoxGetItemRect(hwnd, wRet, &rectsel);
+		    InvalidateRect(hwnd, NULL, TRUE);
+		    UpdateWindow(hwnd);
+		    }
+	        
+		}
+	    }
+	break;
     case WM_KEYDOWN:
-        printf("ListBox WM_KEYDOWN wParam %X!\n", wParam);
-	ListBoxFindNextMatch(hwnd, wParam);
+	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+        if (lphl == NULL) return 0;
+        switch(wParam) {
+	    case VK_HOME:
+	    	lphl->ItemFocused = 0;
+		break;
+	    case VK_END:
+	    	lphl->ItemFocused = lphl->ItemsCount - 1;
+		break;
+	    case VK_LEFT:
+	    	if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
+		    lphl->ItemFocused -= lphl->ItemsPerColumn;
+		    break;
+	    	    }
+	    case VK_UP:
+	    	lphl->ItemFocused--;
+		break;
+	    case VK_RIGHT:
+	    	if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
+		    lphl->ItemFocused += lphl->ItemsPerColumn;
+		    break;
+	    	    }
+	    case VK_DOWN:
+	    	lphl->ItemFocused++;
+		break;
+	    case VK_PRIOR:
+	    	lphl->ItemFocused -= lphl->ItemsVisible;
+		break;
+	    case VK_NEXT:
+	    	lphl->ItemFocused += lphl->ItemsVisible;
+		break;
+	    case VK_SPACE:
+		wRet = ListBoxGetSel(hwnd, lphl->ItemFocused);
+	    	ListBoxSetSel(hwnd, lphl->ItemFocused, !wRet);
+		break;
+	    default:
+		ListBoxFindNextMatch(hwnd, wParam);
+		return 0;
+	    }
+    	if (lphl->ItemFocused < 0) lphl->ItemFocused = 0;
+    	if (lphl->ItemFocused >= lphl->ItemsCount)
+	    lphl->ItemFocused = lphl->ItemsCount - 1;
+	lphl->FirstVisible = lphl->ItemFocused / lphl->ItemsVisible * 
+						lphl->ItemsVisible + 1;
+	if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
+	if ((wndPtr->dwStyle & LBS_MULTIPLESEL) != LBS_MULTIPLESEL) {
+	    ListBoxSetCurSel(hwnd, lphl->ItemFocused);
+	    }
+	if (wndPtr->hWndVScroll != (HWND)NULL)
+	    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+        InvalidateRect(hwnd, NULL, TRUE);
+        UpdateWindow(hwnd);
 	break;
     case WM_PAINT:
 	wndPtr = WIN_FindWndPtr(hwnd);
@@ -216,42 +327,6 @@
 	    }
 	StdDrawListBox(hwnd);
 	break;
-    case WM_MOUSEMOVE:
-        if ((wParam & MK_LBUTTON) != 0) {
-            y = HIWORD(lParam);
-	    if (y < 4) {
-	        lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl->FirstVisible > 1) {
-		    lphl->FirstVisible--;
-		    SetScrollPos(lphl->hWndScroll, WM_VSCROLL, lphl->FirstVisible, TRUE);
-		    InvalidateRect(hwnd, NULL, TRUE);
-		    UpdateWindow(hwnd);
-		    break;
-		    }
-		}
-	    GetClientRect(hwnd, &rect);
-	    if (y > (rect.bottom - 4)) {
-	        lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl->FirstVisible < lphl->ItemsCount) {
-		    lphl->FirstVisible++;
-		    SetScrollPos(lphl->hWndScroll, WM_VSCROLL, lphl->FirstVisible, TRUE);
-		    InvalidateRect(hwnd, NULL, TRUE);
-		    UpdateWindow(hwnd);
-		    break;
-		    }
-		}
-	    if ((y > 0) && (y < (rect.bottom - 4))) {
-		if ((y < rectsel.top) || (y > rectsel.bottom)) {
-		    wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
-		    ListBoxSetCurSel(hwnd, wRet);
-		    ListBoxGetItemRect(hwnd, wRet, &rectsel);
-		    InvalidateRect(hwnd, NULL, TRUE);
-		    UpdateWindow(hwnd);
-		    }
-	        
-		}
-	    }
-	break;
 
     case LB_RESETCONTENT:
         printf("ListBox LB_RESETCONTENT !\n");
@@ -260,17 +335,17 @@
     case LB_DIR:
         printf("ListBox LB_DIR !\n");
 	wRet = ListBoxDirectory(hwnd, wParam, (LPSTR)lParam);
-	if (IsWindowVisible(hwnd)) {
-	    InvalidateRect(hwnd, NULL, TRUE);
-	    UpdateWindow(hwnd);
-	    }
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
 	return wRet;
     case LB_ADDSTRING:
 	wRet = ListBoxAddString(hwnd, (LPSTR)lParam);
 	return wRet;
     case LB_GETTEXT:
 	wRet = ListBoxGetText(hwnd, wParam, (LPSTR)lParam);
+#ifdef DEBUG_LISTBOX
         printf("ListBox LB_GETTEXT #%u '%s' !\n", wParam, (LPSTR)lParam);
+#endif
 	return wRet;
     case LB_INSERTSTRING:
 	wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)lParam);
@@ -289,9 +364,8 @@
 	return lphl->ItemsCount;
     case LB_GETCURSEL:
 	lphl = ListBoxGetStorageHeader(hwnd);
-        printf("ListBox LB_GETCURSEL %u !\n", lphl->ItemSelected);
-	if (lphl->ItemSelected == 0) return LB_ERR;
-	return lphl->ItemSelected;
+        printf("ListBox LB_GETCURSEL %u !\n", lphl->ItemFocused);
+	return lphl->ItemFocused;
     case LB_GETHORIZONTALEXTENT:
 	return wRet;
     case LB_GETITEMDATA:
@@ -301,6 +375,7 @@
     case LB_GETITEMRECT:
 	return wRet;
     case LB_GETSEL:
+        wRet = ListBoxGetSel(hwnd, wParam);
 	return wRet;
     case LB_GETSELCOUNT:
 	return wRet;
@@ -317,7 +392,9 @@
     case LB_SETCARETINDEX:
 	return wRet;
     case LB_SETCOLUMNWIDTH:
-	return wRet;
+        lphl = ListBoxGetStorageHeader(hwnd);
+        lphl->ColumnsWidth = wParam;
+        break;
     case LB_SETHORIZONTALEXTENT:
 	return wRet;
     case LB_SETITEMDATA:
@@ -329,38 +406,29 @@
         printf("ListBox LB_SETCURSEL wParam=%x !\n", wParam);
 #endif
 	wRet = ListBoxSetCurSel(hwnd, wParam);
-	if (IsWindowVisible(hwnd)) {
-	    InvalidateRect(hwnd, NULL, TRUE);
-	    UpdateWindow(hwnd);
-	    }
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
 	return wRet;
     case LB_SETSEL:
         printf("ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
-	wRet = ListBoxSetSel(hwnd, wParam);
-	if (IsWindowVisible(hwnd)) {
-	    InvalidateRect(hwnd, NULL, TRUE);
-	    UpdateWindow(hwnd);
-	    }
+	wRet = ListBoxSetSel(hwnd, LOWORD(lParam), wParam);
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
 	return wRet;
     case LB_SETTOPINDEX:
         printf("ListBox LB_SETTOPINDEX wParam=%x !\n", wParam);
         lphl = ListBoxGetStorageHeader(hwnd);
 	lphl->FirstVisible = wParam;
-	SetScrollPos(lphl->hWndScroll, WM_VSCROLL, lphl->FirstVisible, TRUE);
-	if (IsWindowVisible(hwnd)) {
-	    InvalidateRect(hwnd, NULL, TRUE);
-	    UpdateWindow(hwnd);
-	    }
+	if (wndPtr->hWndVScroll != (HWND)NULL)
+	    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
 	break;
     case LB_SETITEMHEIGHT:
 #ifdef DEBUG_LISTBOX
         printf("ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
 #endif
 	wRet = ListBoxSetItemHeight(hwnd, wParam, lParam);
-	if (IsWindowVisible(hwnd)) {
-	    InvalidateRect(hwnd, NULL, TRUE);
-	    UpdateWindow(hwnd);
-	    }
 	return wRet;
 	
     default:
@@ -392,6 +460,7 @@
 
 void StdDrawListBox(HWND hwnd)
 {
+	WND 	*wndPtr;
 	LPHEADLIST  lphl;
 	LPLISTSTRUCT lpls;
 	PAINTSTRUCT ps;
@@ -399,7 +468,7 @@
 	HWND	hWndParent;
 	HDC hdc;
 	RECT rect;
-	UINT  i, h, h2;
+	UINT  i, h, h2, maxwidth, ipc;
 	char	C[128];
 	h = 0;
 	hdc = BeginPaint( hwnd, &ps );
@@ -407,41 +476,64 @@
 	    EndPaint( hwnd, &ps );
 	    return;
 	    }
-	GetClientRect(hwnd, &rect);
-        lphl = ListBoxGetStorageHeader(hwnd);
+	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
 	if (lphl == NULL) goto EndOfPaint;
 	hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
 		    MAKELONG(hwnd, CTLCOLOR_LISTBOX));
 	if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
-	if (lphl->ItemsCount > lphl->ItemsVisible) rect.right -= 16;
+	GetClientRect(hwnd, &rect);
+	if ((wndPtr->hWndVScroll != (HWND)NULL) &&
+	    IsWindowVisible(wndPtr->hWndVScroll)) rect.right -= 16;
+	if ((wndPtr->hWndHScroll != (HWND)NULL) &&
+	    IsWindowVisible(wndPtr->hWndHScroll)) rect.bottom -= 16;
 	FillRect(hdc, &rect, hBrush);
+	maxwidth = rect.right;
+	rect.right = lphl->ColumnsWidth;
 	if (lphl->ItemsCount == 0) goto EndOfPaint;
 	lpls = lphl->lpFirst;
 	if (lpls == NULL) goto EndOfPaint;
 	lphl->ItemsVisible = 0;
+	lphl->ItemsPerColumn = ipc = 0;
 	for(i = 1; i <= lphl->ItemsCount; i++) {
 	    if (i >= lphl->FirstVisible) {
 		h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
 		lpls->dis.rcItem.top = h;
 		lpls->dis.rcItem.bottom = h + h2;
+		lpls->dis.rcItem.left = rect.left;
 		lpls->dis.rcItem.right = rect.right;
-		TextOut(hdc, 5, h + 2, (char *)lpls->dis.itemData, 
+		TextOut(hdc, rect.left + 5, h + 2, (char *)lpls->dis.itemData, 
 			strlen((char *)lpls->dis.itemData));
 		if (lpls->dis.itemState != 0) {
 		    InvertRect(hdc, &lpls->dis.rcItem);
 		    }
+		if (lphl->ItemFocused == i - 1) {
+		    DrawFocusRect(hdc, &lpls->dis.rcItem);
+		    }
 		h += h2;
 		lphl->ItemsVisible++;
-		if (h > rect.bottom) break;
+		ipc++;
+		if (h > rect.bottom) {
+		    if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
+			lphl->ItemsPerColumn = max(lphl->ItemsPerColumn, ipc);
+			ipc = 0;
+			h = 0;
+			rect.left += lphl->ColumnsWidth;
+			rect.right += lphl->ColumnsWidth;
+			if (rect.left > maxwidth) break;
+			}
+		    else 
+			break;
+		    }
 		}
 	    if (lpls->lpNext == NULL) goto EndOfPaint;
 	    lpls = (LPLISTSTRUCT)lpls->lpNext;
 	}
 EndOfPaint:
     EndPaint( hwnd, &ps );
-    if (lphl->ItemsCount > lphl->ItemsVisible) {
-        InvalidateRect(lphl->hWndScroll, NULL, TRUE);
-        UpdateWindow(lphl->hWndScroll);
+    if ((lphl->ItemsCount > lphl->ItemsVisible) &
+	(wndPtr->hWndVScroll != (HWND)NULL)) {
+        InvalidateRect(wndPtr->hWndVScroll, NULL, TRUE);
+        UpdateWindow(wndPtr->hWndVScroll);
  	}
 }
 
@@ -449,6 +541,7 @@
 
 void OwnerDrawListBox(HWND hwnd)
 {
+	WND 	*wndPtr;
 	LPHEADLIST  lphl;
 	LPLISTSTRUCT lpls;
 	PAINTSTRUCT ps;
@@ -456,38 +549,47 @@
 	HWND	hWndParent;
 	HDC hdc;
 	RECT rect;
-	UINT  i, h, h2;
+	UINT  i, h, h2, maxwidth;
 	char	C[128];
 	h = 0;
-	hdc = BeginPaint( hwnd, &ps );
+	hdc = BeginPaint(hwnd, &ps);
     	if (!IsWindowVisible(hwnd)) {
 	    EndPaint( hwnd, &ps );
 	    return;
 	    }
-	GetClientRect(hwnd, &rect);
-        lphl = ListBoxGetStorageHeader(hwnd);
+	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
 	if (lphl == NULL) goto EndOfPaint;
 	hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
 		    MAKELONG(hwnd, CTLCOLOR_LISTBOX));
 	if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
-	if (lphl->ItemsCount > lphl->ItemsVisible) rect.right -= 16;
+	GetClientRect(hwnd, &rect);
+	if ((wndPtr->hWndVScroll != (HWND)NULL) &&
+	    IsWindowVisible(wndPtr->hWndVScroll)) rect.right -= 16;
+	if ((wndPtr->hWndHScroll != (HWND)NULL) &&
+	    IsWindowVisible(wndPtr->hWndHScroll)) rect.bottom -= 16;
 	FillRect(hdc, &rect, hBrush);
+	maxwidth = rect.right;
+	rect.right = lphl->ColumnsWidth;
 	if (lphl->ItemsCount == 0) goto EndOfPaint;
 	lpls = lphl->lpFirst;
 	if (lpls == NULL) goto EndOfPaint;
 	lphl->ItemsVisible = 0;
-	for(i = 1; i <= lphl->ItemsCount; i++) {
+	for (i = 1; i <= lphl->ItemsCount; i++) {
 	    if (i >= lphl->FirstVisible) {
 		lpls->dis.hDC = hdc;
-		lpls->dis.itemID = i;
+		lpls->dis.itemID = i - 1;
 		h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
 		lpls->dis.rcItem.top = h;
 		lpls->dis.rcItem.bottom = h + h2;
+		lpls->dis.rcItem.left = rect.left;
 		lpls->dis.rcItem.right = rect.right;
 		lpls->dis.itemAction = ODA_DRAWENTIRE;
 		if (lpls->dis.itemState != 0) {
 		    lpls->dis.itemAction |= ODA_SELECT;
 		    }
+		if (lphl->ItemFocused == i - 1) {
+		    lpls->dis.itemAction |= ODA_FOCUS;
+		    }
 #ifdef DEBUT_LISTBOX
 		printf("LBOX WM_DRAWITEM #%d left=%d top=%d right=%d bottom=%d !\n", 
 			i, lpls->dis.rcItem.left, lpls->dis.rcItem.top, 
@@ -502,16 +604,17 @@
 		    }
 		h += h2;
 		lphl->ItemsVisible++;
-		if (h > rect.bottom) break;
+		if (h > rect.bottom) goto EndOfPaint;
 		}
 	    if (lpls->lpNext == NULL) goto EndOfPaint;
 	    lpls = (LPLISTSTRUCT)lpls->lpNext;
 	}
 EndOfPaint:
     EndPaint( hwnd, &ps );
-    if (lphl->ItemsCount > lphl->ItemsVisible) {
-        InvalidateRect(lphl->hWndScroll, NULL, TRUE);
-        UpdateWindow(lphl->hWndScroll);
+    if ((lphl->ItemsCount > lphl->ItemsVisible) &
+	(wndPtr->hWndVScroll != (HWND)NULL)) {
+        InvalidateRect(wndPtr->hWndVScroll, NULL, TRUE);
+        UpdateWindow(wndPtr->hWndVScroll);
         }
 }
 
@@ -519,27 +622,42 @@
 
 int ListBoxFindMouse(HWND hwnd, int X, int Y)
 {
-LPHEADLIST 	lphl;
-LPLISTSTRUCT	lpls;
-RECT rect;
-UINT  i, h, h2;
-char	C[128];
-h = 0;
-lphl = ListBoxGetStorageHeader(hwnd);
-if (lphl == NULL) return LB_ERR;
-if (lphl->ItemsCount == 0) return LB_ERR;
-lpls = lphl->lpFirst;
-if (lpls == NULL) return LB_ERR;
-for(i = 1; i <= lphl->ItemsCount; i++) {
-    if (i >= lphl->FirstVisible) {
-	h2 = h;
-	h += lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
-	if ((Y > h2) && (Y < h)) return(i);
+	WND 	*wndPtr;
+    LPHEADLIST 		lphl;
+    LPLISTSTRUCT	lpls;
+    RECT 		rect;
+    UINT  		i, h, h2, w, w2;
+    char		C[128];
+    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+    if (lphl == NULL) return LB_ERR;
+    if (lphl->ItemsCount == 0) return LB_ERR;
+    lpls = lphl->lpFirst;
+    if (lpls == NULL) return LB_ERR;
+    GetClientRect(hwnd, &rect);
+    if ((wndPtr->hWndVScroll != (HWND)NULL) &&
+	IsWindowVisible(wndPtr->hWndVScroll)) rect.right -= 16;
+    if ((wndPtr->hWndHScroll != (HWND)NULL) &&
+	IsWindowVisible(wndPtr->hWndHScroll)) rect.bottom -= 16;
+    h = w2 = 0;
+    w = lphl->ColumnsWidth;
+    for(i = 1; i <= lphl->ItemsCount; i++) {
+	if (i >= lphl->FirstVisible) {
+	    h2 = h;
+	    h += lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
+	    if ((Y > h2) && (Y < h) &&
+		(X > w2) && (X < w)) return(i - 1);
+	    if (h > rect.bottom) {
+		if ((wndPtr->dwStyle & LBS_MULTICOLUMN) != LBS_MULTICOLUMN) return LB_ERR;
+		h = 0;
+		w2 = w;
+		w += lphl->ColumnsWidth;
+		if (w2 > rect.right) return LB_ERR;
+		}
+	    }
+	if (lpls->lpNext == NULL) return LB_ERR;
+	lpls = (LPLISTSTRUCT)lpls->lpNext;
 	}
-    if (lpls->lpNext == NULL) return LB_ERR;
-    lpls = (LPLISTSTRUCT)lpls->lpNext;
-    }
-return(LB_ERR);
+    return(LB_ERR);
 }
 
 
@@ -602,14 +720,22 @@
     lplsnew->dis.itemID = lphl->ItemsCount;
     lplsnew->dis.itemData = (DWORD)newstr;
     lplsnew->hData = hTemp;
-    SetScrollRange(lphl->hWndScroll, WM_VSCROLL, 1, lphl->ItemsCount, 
-    	(lphl->FirstVisible != 1));
+    if (wndPtr->hWndVScroll != (HWND)NULL)
+	SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, 
+	    (lphl->FirstVisible != 1));
+    if (wndPtr->hWndHScroll != (HWND)NULL && lphl->ItemsPerColumn != 0)
+	SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
+	    lphl->ItemsPerColumn + 1, (lphl->FirstVisible != 1));
     if (lphl->FirstVisible >= (lphl->ItemsCount - lphl->ItemsVisible)) {
         InvalidateRect(hwnd, NULL, TRUE);
         UpdateWindow(hwnd);
         }
-    if ((lphl->ItemsCount - lphl->FirstVisible) == lphl->ItemsVisible) 
-    	ShowWindow(lphl->hWndScroll, SW_NORMAL);
+    if ((lphl->ItemsCount - lphl->FirstVisible) == lphl->ItemsVisible) {
+	if (wndPtr->hWndVScroll != (HWND)NULL)
+	    ShowScrollBar(hwnd, SB_VERT, TRUE);
+	if (wndPtr->hWndHScroll != (HWND)NULL)
+	    ShowScrollBar(hwnd, SB_HORZ, TRUE);
+	}
     return lphl->ItemsCount;
 }
 
@@ -624,7 +750,7 @@
     UINT	Count;
     lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
     if (lphl == NULL) return LB_ERR;
-    if (uIndex < 1 || uIndex > lphl->ItemsCount) return LB_ERR;
+    if (uIndex >= lphl->ItemsCount) return LB_ERR;
     lpls = lphl->lpFirst;
     if (lpls == NULL) return LB_ERR;
     if (uIndex > lphl->ItemsCount) return LB_ERR;
@@ -653,11 +779,19 @@
     lplsnew->dis.itemID = lphl->ItemsCount;
     lplsnew->dis.itemData = (DWORD)newstr;
     lplsnew->hData = hTemp;
-    SetScrollRange(lphl->hWndScroll, WM_VSCROLL, 1, lphl->ItemsCount, 
-    	(lphl->FirstVisible != 1));
+   if (wndPtr->hWndVScroll != (HWND)NULL)
+	SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, 
+	    (lphl->FirstVisible != 1));
+    if (wndPtr->hWndHScroll != (HWND)NULL && lphl->ItemsPerColumn != 0)
+	SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
+	    lphl->ItemsPerColumn + 1, (lphl->FirstVisible != 1));
     if (((lphl->ItemsCount - lphl->FirstVisible) == lphl->ItemsVisible) && 
-        (lphl->ItemsVisible != 0)) 
-    	ShowWindow(lphl->hWndScroll, SW_NORMAL);
+        (lphl->ItemsVisible != 0)) {
+	if (wndPtr->hWndVScroll != (HWND)NULL)
+	    ShowScrollBar(hwnd, SB_VERT, TRUE);
+	if (wndPtr->hWndHScroll != (HWND)NULL)
+	    ShowScrollBar(hwnd, SB_HORZ, TRUE);
+	}
     if ((lphl->FirstVisible <= uIndex) &&
         ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
         InvalidateRect(hwnd, NULL, TRUE);
@@ -675,11 +809,11 @@
     UINT	Count;
     lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
     if (lphl == NULL) return LB_ERR;
-    if (uIndex < 1 || uIndex > lphl->ItemsCount) return LB_ERR;
+    if (uIndex >= lphl->ItemsCount) return LB_ERR;
     lpls = lphl->lpFirst;
     if (lpls == NULL) return LB_ERR;
     if (uIndex > lphl->ItemsCount) return LB_ERR;
-    for(Count = 1; Count < uIndex; Count++) {
+    for(Count = 0; Count < uIndex; Count++) {
 	if (lpls->lpNext == NULL) return LB_ERR;
 	lpls = (LPLISTSTRUCT)lpls->lpNext;
     }
@@ -698,12 +832,13 @@
 
 int ListBoxDeleteString(HWND hwnd, UINT uIndex)
 {
+    WND  	*wndPtr;
     LPHEADLIST 	lphl;
     LPLISTSTRUCT lpls, lpls2;
     UINT	Count;
-    lphl = ListBoxGetStorageHeader(hwnd);
+    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
     if (lphl == NULL) return LB_ERR;
-    if (uIndex < 1 || uIndex > lphl->ItemsCount) return LB_ERR;
+    if (uIndex >= lphl->ItemsCount) return LB_ERR;
     lpls = lphl->lpFirst;
     if (lpls == NULL) return LB_ERR;
     if (uIndex > lphl->ItemsCount) return LB_ERR;
@@ -716,9 +851,17 @@
     lphl->ItemsCount--;
     if (lpls->hData != 0) USER_HEAP_FREE(lpls->hData);
     if (lpls->hMem != 0) USER_HEAP_FREE(lpls->hMem);
-    SetScrollRange(lphl->hWndScroll, WM_VSCROLL, 1, lphl->ItemsCount, TRUE);
-    if (lphl->ItemsCount < lphl->ItemsVisible) 
-    	ShowWindow(lphl->hWndScroll, SW_HIDE);
+    if (wndPtr->hWndVScroll != (HWND)NULL)
+	SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
+    if (wndPtr->hWndHScroll != (HWND)NULL && lphl->ItemsPerColumn != 0)
+	SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
+	    lphl->ItemsPerColumn + 1, TRUE);
+    if (lphl->ItemsCount < lphl->ItemsVisible) {
+	if (wndPtr->hWndVScroll != (HWND)NULL)
+	    ShowScrollBar(hwnd, SB_VERT, FALSE);
+	if (wndPtr->hWndHScroll != (HWND)NULL)
+	    ShowScrollBar(hwnd, SB_HORZ, FALSE);
+	}
     if ((lphl->FirstVisible <= uIndex) &&
         ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
         InvalidateRect(hwnd, NULL, TRUE);
@@ -735,13 +878,12 @@
     UINT	Count;
     lphl = ListBoxGetStorageHeader(hwnd);
     if (lphl == NULL) return LB_ERR;
-    if (nFirst < 1 || nFirst > lphl->ItemsCount) return LB_ERR;
+    if (nFirst > lphl->ItemsCount) return LB_ERR;
     lpls = lphl->lpFirst;
     if (lpls == NULL) return LB_ERR;
-    Count = 1;
+    Count = 0;
     while(lpls != NULL) {
-    	if (strcmp((char *)lpls->dis.itemData, MatchStr) == 0)
-	    return Count;
+    	if (strcmp((char *)lpls->dis.itemData, MatchStr) == 0) return Count;
 	lpls = (LPLISTSTRUCT)lpls->lpNext;
 	Count++;
         }
@@ -774,14 +916,21 @@
     lphl->lpFirst = NULL;
     lphl->FirstVisible = 1;
     lphl->ItemsCount = 0;
-    lphl->ItemSelected = 0;
-    lphl->PrevSelected = 0;
+    lphl->ItemFocused = 0;
+    lphl->PrevFocused = 0;
     if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
 	SendMessage(wndPtr->hwndParent, WM_COMMAND, 
     	    wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
 
-    SetScrollRange(lphl->hWndScroll, WM_VSCROLL, 1, lphl->ItemsCount, TRUE);
-    ShowWindow(lphl->hWndScroll, SW_HIDE);
+    if (wndPtr->hWndVScroll != (HWND)NULL)
+	SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
+    if (wndPtr->hWndHScroll != (HWND)NULL && lphl->ItemsPerColumn != 0)
+	SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
+	    lphl->ItemsPerColumn + 1, TRUE);
+    if (wndPtr->hWndVScroll != (HWND)NULL)
+	ShowScrollBar(hwnd, SB_VERT, FALSE);
+    if (wndPtr->hWndHScroll != (HWND)NULL)
+	ShowScrollBar(hwnd, SB_HORZ, FALSE);
     InvalidateRect(hwnd, NULL, TRUE);
     UpdateWindow(hwnd);
     return TRUE;
@@ -796,8 +945,8 @@
     UINT	i;
     lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
     if (lphl == NULL) return LB_ERR;
-    lphl->ItemSelected = LB_ERR;
-    if (wIndex < 0 || wIndex >= lphl->ItemsCount) return LB_ERR;
+    lphl->ItemFocused = LB_ERR;
+    if (wIndex >= lphl->ItemsCount) return LB_ERR;
     lpls = lphl->lpFirst;
     if (lpls == NULL) return LB_ERR;
     for(i = 0; i < lphl->ItemsCount; i++) {
@@ -810,7 +959,7 @@
 	        lpls2->dis.itemState = 0;
 	if (lpls == NULL)  break;
     }
-    lphl->ItemSelected = wIndex;
+    lphl->ItemFocused = wIndex;
     if ((wndPtr->dwStyle && LBS_NOTIFY) != 0)
 	SendMessage(wndPtr->hwndParent, WM_COMMAND, 
     	    wndPtr->wIDmenu, MAKELONG(hwnd, LBN_SELCHANGE));
@@ -819,22 +968,44 @@
 
 
 
-int ListBoxSetSel(HWND hwnd, WORD wIndex)
+int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state)
 {
     LPHEADLIST 	lphl;
     LPLISTSTRUCT lpls, lpls2;
     UINT	i;
     lphl = ListBoxGetStorageHeader(hwnd);
     if (lphl == NULL) return LB_ERR;
-    if (wIndex < 0 || wIndex >= lphl->ItemsCount) return LB_ERR;
+    if (wIndex >= lphl->ItemsCount) return LB_ERR;
+    lpls = lphl->lpFirst;
+    if (lpls == NULL) return LB_ERR;
+    for(i = 0; i < lphl->ItemsCount; i++) {
+	lpls2 = lpls;
+	lpls = (LPLISTSTRUCT)lpls->lpNext;
+	if ((i == wIndex) || (wIndex == (WORD)-1)) {
+	    lpls2->dis.itemState = state;
+	    break;
+	    }  
+	if (lpls == NULL)  break;
+    }
+    return LB_ERR;
+}
+
+
+int ListBoxGetSel(HWND hwnd, WORD wIndex)
+{
+    LPHEADLIST 	lphl;
+    LPLISTSTRUCT lpls, lpls2;
+    UINT	i;
+    lphl = ListBoxGetStorageHeader(hwnd);
+    if (lphl == NULL) return LB_ERR;
+    if (wIndex >= lphl->ItemsCount) return LB_ERR;
     lpls = lphl->lpFirst;
     if (lpls == NULL) return LB_ERR;
     for(i = 0; i < lphl->ItemsCount; i++) {
 	lpls2 = lpls;
 	lpls = (LPLISTSTRUCT)lpls->lpNext;
 	if (i == wIndex) {
-	    lpls2->dis.itemState = 1;
-	    break;
+	    return lpls2->dis.itemState;
 	    }  
 	if (lpls == NULL)  break;
     }
@@ -844,28 +1015,56 @@
 
 int ListBoxDirectory(HWND hwnd, UINT attrib, LPSTR filespec)
 {
-DIR           	*dirp;
-struct dirent 	*dp;
-struct stat	st;
-char		str[128];
-int		wRet;
-dirp = opendir(".");
-while ( (dp = readdir(dirp)) != NULL) 
-    {
-    stat(dp->d_name, &st);
-#ifdef DEBUG_LBDIR
-    printf("LB_DIR : st_mode=%lX / d_name='%s'\n", st.st_mode, dp->d_name);
-#endif
-    if S_ISDIR(st.st_mode) {
-	sprintf(str, "[%s]", dp->d_name);
+	struct dosdirent *dp;
+	struct stat	st;
+	int	x, wRet;
+	char 	temp[256];
+
+	fprintf(stderr,"ListBoxDirectory: %s, %4x\n",filespec,attrib);
+
+
+	if ((dp = (struct dosdirent *)DOS_opendir(filespec)) ==NULL)
+		return 0;
+	
+	while (1)
+	{
+		dp = (struct dosdirent *)DOS_readdir(dp);
+		if (!dp->inuse)
+			break;
+
+		if (dp->attribute & 0x08)
+		{
+			if (attrib & DDL_DIRECTORY) {
+				sprintf(temp, "[%s]", dp->filename);
+				if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR)
+	    				break;
+			}
+		} else 
+		if (attrib & DDL_EXCLUSIVE) {
+	    		if (attrib & (DDL_READWRITE | DDL_READONLY | DDL_HIDDEN | DDL_SYSTEM) )
+		    		if ( (wRet = ListBoxAddString(hwnd, dp->filename)) == LB_ERR)
+		    			break;
+		} else {
+			if ( (wRet = ListBoxAddString(hwnd, dp->filename)) == LB_ERR)
+	    			break;
+		}
 	}
-    else
-	strcpy(str, dp->d_name);
-    wRet = ListBoxAddString(hwnd, str);
-    if (wRet == LB_ERR) break;
-    }
-closedir(dirp);	
-return wRet;
+	DOS_closedir(dp);
+	
+	if (attrib & DDL_DRIVES)
+	{
+		for (x=0;x!=MAX_DOS_DRIVES;x++)
+		{
+			if (DOS_ValidDrive(x))
+			{
+				sprintf(temp, "[-%c-]", 'A'+x);
+				if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR)
+	    				break;
+			}		
+		}
+	}
+
+	return wRet;
 }
 
 
@@ -876,10 +1075,10 @@
     UINT	i;
     lphl = ListBoxGetStorageHeader(hwnd);
     if (lphl == NULL) return LB_ERR;
-    if (wIndex < 1 || wIndex > lphl->ItemsCount) return LB_ERR;
+    if (wIndex > lphl->ItemsCount) return LB_ERR;
     lpls = lphl->lpFirst;
     if (lpls == NULL) return LB_ERR;
-    for(i = 0; i <= lphl->ItemsCount; i++) {
+    for(i = 0; i < lphl->ItemsCount; i++) {
 	lpls2 = lpls;
 	lpls = (LPLISTSTRUCT)lpls->lpNext;
 	if (i == wIndex) {
@@ -900,14 +1099,16 @@
     UINT	i;
     lphl = ListBoxGetStorageHeader(hwnd);
     if (lphl == NULL) return LB_ERR;
-    if (wIndex < 1 || wIndex > lphl->ItemsCount) return LB_ERR;
+    if (wIndex > lphl->ItemsCount) return LB_ERR;
     lpls = lphl->lpFirst;
     if (lpls == NULL) return LB_ERR;
-    for(i = 0; i <= lphl->ItemsCount; i++) {
+    for(i = 0; i < lphl->ItemsCount; i++) {
 	lpls2 = lpls;
 	lpls = (LPLISTSTRUCT)lpls->lpNext;
 	if (i == wIndex) {
 	    lpls2->dis.rcItem.bottom = lpls2->dis.rcItem.top + (short)height;
+	    InvalidateRect(hwnd, NULL, TRUE);
+	    UpdateWindow(hwnd);
 	    break;
 	    }  
 	if (lpls == NULL)  break;
@@ -954,14 +1155,19 @@
 	    return LB_ERR;
 	    }
 	}
-    Count = 1;
+    Count = 0;
     while(lpls != NULL) {
-        if (Count > lphl->ItemSelected) {
+        if (Count > lphl->ItemFocused) {
 	    if (*((char *)lpls->dis.itemData) == (char)wChar) {
 		lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
 		if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
-		ListBoxSetCurSel(hwnd, Count);
-		SetScrollPos(lphl->hWndScroll, WM_VSCROLL, lphl->FirstVisible, TRUE);
+		if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
+		    lphl->ItemFocused = Count;
+		    }
+		else {
+		    ListBoxSetCurSel(hwnd, Count);
+		    }
+		SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 	        InvalidateRect(hwnd, NULL, TRUE);
 	        UpdateWindow(hwnd);
 	        return Count;
@@ -970,15 +1176,20 @@
 	lpls = (LPLISTSTRUCT)lpls->lpNext;
 	Count++;
 	}
-    Count = 1;
+    Count = 0;
     lpls = lphl->lpFirst;
     while(lpls != NULL) {
 	if (*((char *)lpls->dis.itemData) == (char)wChar) {
-	    if (Count == lphl->ItemSelected)    return LB_ERR;
+	    if (Count == lphl->ItemFocused)    return LB_ERR;
 	    lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
 	    if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
-	    ListBoxSetCurSel(hwnd, Count);
-	    SetScrollPos(lphl->hWndScroll, WM_VSCROLL, lphl->FirstVisible, TRUE);
+	    if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
+		lphl->ItemFocused = Count;
+		}
+	    else {
+		ListBoxSetCurSel(hwnd, Count);
+		}
+	    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
 	    InvalidateRect(hwnd, NULL, TRUE);
 	    UpdateWindow(hwnd);
 	    return Count;
diff --git a/controls/menu.c b/controls/menu.c
index 2d22115..c1cd758 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -1,6 +1,8 @@
 static char RCSId[] = "$Id$";
 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 
+#define DEBUG_MENU
+
 #include <X11/Intrinsic.h>
 #include <X11/StringDefs.h>
 #include <X11/Xaw/SmeBSB.h>
@@ -22,7 +24,306 @@
 static int       menuId = 0;
 static Pixmap    checkBitmap = XtUnspecifiedPixmap;
 static Pixmap    nocheckBitmap = XtUnspecifiedPixmap;
-
+
+LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd);
+LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr);
+void StdDrawPopupMenu(HWND hwnd);
+LPMENUITEM PopupMenuFindItem(HWND hwnd, int x, int y, WORD *lpRet);
+LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos);
+
+/***********************************************************************
+ *           PopupMenuWndProc
+ */
+LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+{    
+    CREATESTRUCT *createStruct;
+    WORD	wRet;
+    short	x, y;
+    WND  	*wndPtr;
+    LPPOPUPMENU lppop;
+    LPMENUITEM	lpitem, lpitem2;
+    HMENU	hSubMenu;
+    RECT	rect;
+    HDC		hDC;
+    switch(message) 
+    {
+    case WM_CREATE:
+#ifdef DEBUG_MENU
+        printf("PopupMenu WM_CREATE lParam=%08X !\n", lParam);
+#endif
+	createStruct = (CREATESTRUCT *)lParam;
+     	lppop = (LPPOPUPMENU)createStruct->lpCreateParams;
+     	if (lppop == 0) break;
+	wndPtr = WIN_FindWndPtr(hwnd);
+	*((LPPOPUPMENU *)&wndPtr->wExtra[1]) = lppop;
+#ifdef DEBUG_MENU
+        printf("PopupMenu WM_CREATE lppop=%08X !\n", lppop);
+#endif
+	return 0;
+    case WM_DESTROY:
+	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+#ifdef DEBUG_MENU
+        printf("PopupMenu WM_DESTROY %lX !\n", lppop);
+#endif
+	return 0;
+	
+    case WM_LBUTTONDOWN:
+	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+	SetCapture(hwnd);
+	lpitem = PopupMenuFindItem(hwnd, LOWORD(lParam), HIWORD(lParam), &wRet);
+	printf("PopupMenu WM_LBUTTONDOWN wRet=%d lpitem=%08X !\n", wRet, lpitem);
+	if (lpitem != NULL) {
+	    lppop->FocusedItem = wRet;
+	    if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
+		((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
+	        hDC = GetDC(hwnd);
+	        InvertRect(hDC, &lpitem->rect);
+		ReleaseDC(hwnd, hDC);
+		}
+	    }
+	break;
+    case WM_LBUTTONUP:
+	lppop = PopupMenuGetStorageHeader(hwnd);
+	ReleaseCapture();
+	lpitem = PopupMenuFindItem(hwnd, LOWORD(lParam), HIWORD(lParam), &wRet);
+	printf("PopupMenu WM_LBUTTONUP wRet=%d lpitem=%08X !\n", wRet, lpitem);
+	if (lpitem != NULL) {
+	    if (lppop->FocusedItem != (WORD)-1) {
+		lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
+		if (((lpitem2->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
+		    ((lpitem2->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
+	            hDC = GetDC(hwnd);
+	            InvertRect(hDC, &lpitem2->rect);
+		    ReleaseDC(hwnd, hDC);
+		    }
+		}
+	    if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
+		hSubMenu = (HMENU)lpitem->item_id;
+		printf("ShowSubmenu hSubMenu=%04X !\n", hSubMenu);
+		GetClientRect(hwnd, &rect);
+		x = rect.right;
+		GetWindowRect(hwnd, &rect);
+		x += rect.left;
+		TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
+			x, rect.top + HIWORD(lParam), 
+			0, lppop->ownerWnd, (LPRECT)NULL);
+		break;
+		}
+	    if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
+		((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
+		SendMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
+		printf("PopupMenu // SendMessage WM_COMMAND wParam=%d !\n", 
+			lpitem->item_id);
+	    	ShowWindow(lppop->hWnd, SW_HIDE);
+	    	break;
+		}
+	    }
+	break;
+    case WM_MOUSEMOVE:
+        if ((wParam & MK_LBUTTON) != 0) {
+	    lppop = PopupMenuGetStorageHeader(hwnd);
+	    lpitem = PopupMenuFindItem(hwnd, LOWORD(lParam), HIWORD(lParam), &wRet);
+	    if ((lpitem != NULL) && (lppop->FocusedItem != wRet)) {
+		lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
+		hDC = GetDC(hwnd);
+		if (((lpitem2->item_flags & MF_POPUP) == MF_POPUP) ||
+		    ((lpitem2->item_flags & MF_STRING) == MF_STRING)) {
+		    InvertRect(hDC, &lpitem2->rect);
+		    }
+		lppop->FocusedItem = wRet;
+		printf("PopupMenu WM_MOUSEMOVE wRet=%d lpitem=%08X !\n", wRet, lpitem);
+		InvertRect(hDC, &lpitem->rect);
+		ReleaseDC(hwnd, hDC);
+		}
+            }
+	break;
+
+    case WM_KEYDOWN:
+    case WM_KEYUP:
+    case WM_CHAR:
+	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+	return(SendMessage(wndPtr->hwndParent, message, wParam, lParam));
+
+    case WM_PAINT:
+        printf("PopupMenu WM_PAINT !\n");
+	StdDrawPopupMenu(hwnd);
+	break;
+    default:
+	return DefWindowProc( hwnd, message, wParam, lParam );
+    }
+return(0);
+}
+
+
+
+LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr)
+{
+    WND  *Ptr;
+    LPPOPUPMENU lppop;
+    *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
+    if (Ptr == 0) {
+    	printf("Bad Window handle on PopupMenu !\n");
+    	return 0;
+    	}
+    lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
+    return lppop;
+}
+
+
+LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd)
+{
+    WND  *Ptr;
+    LPPOPUPMENU lppop;
+    Ptr = WIN_FindWndPtr(hwnd);
+    if (Ptr == 0) {
+    	printf("Bad Window handle on PopupMenu !\n");
+    	return 0;
+    	}
+    lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
+    return lppop;
+}
+
+
+void StdDrawPopupMenu(HWND hwnd)
+{
+    WND 	*wndPtr;
+    LPPOPUPMENU lppop;
+    LPMENUITEM 	lpitem;
+    PAINTSTRUCT ps;
+    HBRUSH 	hBrush;
+    HPEN	hOldPen;
+    HWND	hWndParent;
+    HDC 	hDC, hMemDC;
+    RECT 	rect, rect2, rect3;
+    HBITMAP	hBitMap;
+    BITMAP	bm;
+    UINT  	i;
+    hDC = BeginPaint( hwnd, &ps );
+    if (!IsWindowVisible(hwnd)) {
+	EndPaint( hwnd, &ps );
+	return;
+	}
+    lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+    if (lppop == NULL) goto EndOfPaint;
+    hBrush = SendMessage(lppop->ownerWnd, WM_CTLCOLOR, (WORD)hDC,
+		    MAKELONG(hwnd, CTLCOLOR_LISTBOX));
+    if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
+    GetClientRect(hwnd, &rect);
+    GetClientRect(hwnd, &rect2);
+    FillRect(hDC, &rect, hBrush);
+    if (lppop->nItems == 0) goto EndOfPaint;
+    lpitem = lppop->firstItem->next;
+    if (lpitem == NULL) goto EndOfPaint;
+    for(i = 0; i < lppop->nItems; i++) {
+	if ((lpitem->item_flags & MF_SEPARATOR) == MF_SEPARATOR) {
+	    rect2.bottom = rect2.top + 3;
+	    CopyRect(&lpitem->rect, &rect2);
+	    hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
+	    MoveTo(hDC, rect2.left, rect2.top + 1);
+	    LineTo(hDC, rect2.right, rect2.top + 1);
+	    SelectObject(hDC, hOldPen);
+	    rect2.top += 3;
+	    }
+	if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
+	    hBitMap = (HBITMAP)LOWORD(lpitem->item_text);
+	    rect2.bottom = rect2.top + bm.bmHeight;
+	    CopyRect(&lpitem->rect, &rect2);
+	    hMemDC = CreateCompatibleDC(hDC);
+	    SelectObject(hMemDC, hBitMap);
+	    GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
+	    BitBlt(hDC, rect2.left, rect2.top,
+		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+	    DeleteDC(hMemDC);
+	    rect2.top += bm.bmHeight;
+	    }
+	if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
+	    ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
+	    ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
+	    rect2.bottom = rect2.top + 15;
+	    CopyRect(&lpitem->rect, &rect2);
+	    TextOut(hDC, rect2.left + 5, rect2.top + 2, 
+		(char *)lpitem->item_text, strlen((char *)lpitem->item_text));
+	    rect2.top += 15;
+	    }
+	if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
+	    CopyRect(&rect3, &rect2);
+	    rect3.left = rect3.right - rect3.bottom + rect3.top;
+	    InvertRect(hDC, &rect3);
+	    }
+	if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
+	    CopyRect(&rect3, &rect2);
+	    rect3.left = rect3.right - rect3.bottom + rect3.top;
+	    FillRect(hDC, &rect3, GetStockObject(BLACK_BRUSH));
+	    }
+	if (lpitem->next == NULL) goto EndOfPaint;
+	lpitem = (LPMENUITEM)lpitem->next;
+    }
+EndOfPaint:
+    EndPaint( hwnd, &ps );
+}
+
+
+
+LPMENUITEM PopupMenuFindItem(HWND hwnd, int x, int y, WORD *lpRet)
+{
+    WND 	*wndPtr;
+    LPPOPUPMENU lppop;
+    LPMENUITEM 	lpitem;
+    RECT 	rect, rect2;
+    HBITMAP	hBitMap;
+    BITMAP	bm;
+    UINT  	i;
+    lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+    if (lppop == NULL) return NULL;
+    GetClientRect(hwnd, &rect);
+    if (lppop->nItems == 0) return NULL;
+    lpitem = lppop->firstItem->next;
+    if (lpitem == NULL) return NULL;
+    for(i = 0; i < lppop->nItems; i++) {
+	if (y < rect2.top) return NULL;
+	if ((lpitem->item_flags & MF_SEPARATOR) == MF_SEPARATOR) {
+	    rect2.bottom = rect2.top + 3;
+	    rect2.top += 3;
+	    }
+	if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
+	    hBitMap = (HBITMAP)LOWORD(lpitem->item_text);
+	    GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
+	    rect2.bottom = rect2.top + bm.bmHeight;
+	    rect2.top += bm.bmHeight;
+	    }
+	if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
+	    ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
+	    ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
+	    rect2.bottom = rect2.top + 15;
+	    rect2.top += 15;
+	    }
+	if (y < rect2.bottom) {
+	    if (lpRet != NULL) *lpRet = i;
+	    return lpitem;
+	    }
+	if (lpitem->next == NULL) return NULL;
+	lpitem = (LPMENUITEM)lpitem->next;
+    }
+    return NULL;
+}
+
+
+
+LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos)
+{
+    LPMENUITEM 	lpitem;
+    int		i;
+    if (menu == NULL) return NULL;
+    lpitem = menu->firstItem;
+    for (i = 0; i < menu->nItems; i++) {
+    	if (lpitem->next == NULL) return NULL;
+    	lpitem = (LPMENUITEM)lpitem->next;
+    	if (i == nPos) return(lpitem);
+    	}
+    return NULL;
+}
+
+
 /**********************************************************************
  *					MENU_CheckWidget
  */
@@ -565,3 +866,316 @@
     
     return GlobalHandleFromPointer(menu->firstItem);
 }
+
+
+/**********************************************************************
+ *			CheckMenuItem		[USER.154]
+ */
+BOOL CheckMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags)
+{
+}
+
+
+/**********************************************************************
+ *			EnableMenuItem		[USER.155]
+ */
+BOOL EnableMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags)
+{
+}
+
+
+/**********************************************************************
+ *			InsertMenu		[USER.410]
+ */
+BOOL InsertMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
+{
+    WND		*wndPtr;
+    LPPOPUPMENU	menu;
+    HANDLE	hNewItem;
+    LPMENUITEM 	lpitem, lpitem2;
+    int		i;
+#ifdef DEBUG_MENU
+    printf("InsertMenu (%04X, %04X, %04X, %04X, %08X) !\n",
+	hMenu, nPos, wFlags, wItemID, lpNewItem);
+#endif
+    menu = (LPPOPUPMENU) GlobalLock(hMenu);
+    if (menu == NULL) return FALSE;
+    lpitem = menu->firstItem;
+    for (i = 0; i < menu->nItems; i++) {
+    	if (lpitem->next == NULL) break;
+    	lpitem = (LPMENUITEM)lpitem->next;
+	printf("InsertMenu // during loop items !\n");
+    	}
+    printf("InsertMenu // after loop items !\n");
+    hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
+    if (hNewItem == 0) return FALSE;
+    lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
+    if (lpitem2 == 0) {
+	GlobalFree(hNewItem);
+	return FALSE;
+	}
+    lpitem2->item_flags = wFlags;
+    lpitem2->item_id = wItemID;
+    if ((wFlags & MF_STRING) == MF_STRING) {
+	lpitem2->item_text = lpNewItem;
+	}
+    else
+	lpitem2->item_text = lpNewItem;
+    lpitem2->prev = lpitem;
+    if (lpitem->next != NULL)
+	lpitem2->next = lpitem->next;
+    else
+	lpitem2->next = NULL;
+    lpitem->next = lpitem2;
+    lpitem2->child = NULL;
+    lpitem2->parent = NULL;
+    lpitem2->w = NULL;
+    lpitem2->menu_w = NULL;
+    menu->nItems++;
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *			AppendMenu		[USER.411]
+ */
+BOOL AppendMenu(HMENU hMenu, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
+{
+    WND		*wndPtr;
+    LPPOPUPMENU	menu;
+    HANDLE	hNewItem;
+    LPMENUITEM 	lpitem, lpitem2;
+#ifdef DEBUG_MENU
+    printf("AppendMenu (%04X, %04X, %04X, %08X) !\n",
+	hMenu, wFlags, wItemID, lpNewItem);
+#endif
+    menu = (LPPOPUPMENU) GlobalLock(hMenu);
+    if (menu == NULL) return FALSE;
+    lpitem = menu->firstItem;
+    while (lpitem->next != NULL) {
+    	lpitem = (LPMENUITEM)lpitem->next;
+	printf("AppendMenu // during loop items !\n");
+    	}
+    printf("AppendMenu // after loop items !\n");
+    hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
+    if (hNewItem == 0) return FALSE;
+    lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
+    if (lpitem2 == 0) {
+	GlobalFree(hNewItem);
+	return FALSE;
+	}
+    lpitem2->item_flags = wFlags;
+    lpitem2->item_id = wItemID;
+    if ((wFlags & MF_STRING) == MF_STRING) {
+	lpitem2->item_text = lpNewItem;
+	}
+    else
+	lpitem2->item_text = lpNewItem;
+    lpitem->next = lpitem2;
+    lpitem2->prev = lpitem;
+    lpitem2->next = NULL;
+    lpitem2->child = NULL;
+    lpitem2->parent = NULL;
+    lpitem2->w = NULL;
+    lpitem2->menu_w = NULL;
+    menu->nItems++;
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *			RemoveMenu		[USER.412]
+ */
+BOOL RemoveMenu(HMENU hMenu, WORD nPos, WORD wFlags)
+{
+    WND		*wndPtr;
+    LPPOPUPMENU	menu;
+    LPMENUITEM 	lpitem;
+    int		i;
+#ifdef DEBUG_MENU
+    printf("RemoveMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags);
+#endif
+    menu = (LPPOPUPMENU) GlobalLock(hMenu);
+    if (menu == NULL) return FALSE;
+    lpitem = menu->firstItem;
+    for (i = 0; i < menu->nItems; i++) {
+    	if (lpitem->next == NULL) break;
+    	lpitem = (LPMENUITEM)lpitem->next;
+    	if (i == nPos) {
+    	    lpitem->prev->next = lpitem->next;
+    	    lpitem->next->prev = lpitem->prev;
+    	    GlobalFree(HIWORD(lpitem));
+    	    return(TRUE);
+	    }
+	printf("RemoveMenu // during loop items !\n");
+    	}
+    printf("RemoveMenu // after loop items !\n");
+    return FALSE;
+}
+
+
+/**********************************************************************
+ *			DeleteMenu		[USER.413]
+ */
+BOOL DeleteMenu(HMENU hMenu, WORD nPos, WORD wFlags)
+{
+#ifdef DEBUG_MENU
+    printf("DeleteMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags);
+#endif
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *			ModifyMenu		[USER.414]
+ */
+BOOL ModifyMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
+{
+#ifdef DEBUG_MENU
+    printf("ModifyMenu (%04X, %04X, %04X, %04X, %08X) !\n",
+	hMenu, nPos, wFlags, wItemID, lpNewItem);
+#endif
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *			CreatePopupMenu		[USER.415]
+ */
+HMENU CreatePopupMenu()
+{
+    HANDLE	hItem;
+    HMENU	hMenu;
+    LPPOPUPMENU menu;
+#ifdef DEBUG_MENU
+    printf("CreatePopupMenu !\n");
+#endif
+    hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
+    menu = (LPPOPUPMENU) GlobalLock(hMenu);
+    if (menu == NULL) {
+	GlobalFree(hMenu);
+	return 0;
+ 	}
+    hItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
+    if (hItem == 0) {
+	GlobalFree(hMenu);
+	return 0;
+	}
+    menu->nItems 	  = 0;
+    menu->firstItem       = (LPMENUITEM)GlobalLock(hItem);
+    menu->ownerWnd	  = 0;
+    menu->hWnd		  = 0;
+
+    menu->firstItem->next 	= NULL;
+    menu->firstItem->prev 	= NULL;
+    menu->firstItem->child 	= NULL;
+    menu->firstItem->parent 	= NULL;
+    menu->firstItem->item_flags	= 0;
+    menu->firstItem->item_id 	= 0;
+    menu->firstItem->item_text 	= NULL;
+    menu->firstItem->w 		= NULL;
+    menu->firstItem->menu_w 	= NULL;
+    return hMenu;
+}
+
+
+/**********************************************************************
+ *			TrackPopupMenu		[USER.414]
+ */
+BOOL TrackPopupMenu(HMENU hMenu, WORD wFlags, short x, short y,
+	short nReserved, HWND hWnd, LPRECT lpRect)
+{
+    WND		*wndPtr;
+    LPPOPUPMENU	menu;
+#ifdef DEBUG_MENU
+    printf("TrackPopupMenu (%04X, %04X, %d, %d, %04X, %04X, %08X) !\n",
+	hMenu, wFlags, x, y, nReserved, hWnd, lpRect);
+#endif
+    menu = (LPPOPUPMENU) GlobalLock(hMenu);
+    if (menu == NULL) return FALSE;
+    wndPtr = WIN_FindWndPtr(hWnd);
+    menu->ownerWnd = hWnd;
+    if (menu->hWnd == NULL) {
+        menu->hWnd = CreateWindow("POPUPMENU", "", WS_CHILD | WS_VISIBLE,
+        	x, y, 100, 150, hWnd, 0, wndPtr->hInstance, (LPSTR)menu);
+        }
+    else 
+    	ShowWindow(menu->hWnd, SW_SHOW);
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *			CreateMenu		[USER.151]
+ */
+HMENU CreateMenu()
+{
+    HANDLE	hItem;
+    HMENU	hMenu;
+    LPMENUBAR	menu;
+#ifdef DEBUG_MENU
+    printf("CreateMenu !\n");
+#endif
+    hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUBAR));
+    menu = (LPMENUBAR) GlobalLock(hMenu);
+    if (menu == NULL) {
+	GlobalFree(hMenu);
+	return 0;
+ 	}
+    hItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
+    if (hItem == 0) {
+	GlobalFree(hMenu);
+	return 0;
+	}
+    menu->menuDescription = 0;
+    menu->nItems 	  = 0;
+    menu->parentWidget    = NULL;
+    menu->firstItem       = (LPMENUITEM) GlobalLock(hItem);
+    menu->ownerWnd	  = 0;
+    menu->menuBarWidget   = NULL;
+
+    menu->firstItem->next 	= NULL;
+    menu->firstItem->prev 	= NULL;
+    menu->firstItem->child 	= NULL;
+    menu->firstItem->parent 	= NULL;
+    menu->firstItem->item_flags	= 0;
+    menu->firstItem->item_id 	= 0;
+    menu->firstItem->item_text 	= NULL;
+    menu->firstItem->w 		= NULL;
+    menu->firstItem->menu_w 	= NULL;
+    return hMenu;
+}
+
+
+/**********************************************************************
+ *			DestroyMenu		[USER.152]
+ */
+BOOL DestroyMenu(HMENU hMenu)
+{
+    LPPOPUPMENU lppop;
+    LPMENUITEM 	lpitem, lpitem2;
+#ifdef DEBUG_MENU
+    printf("DestroyMenu (%04X) !\n", hMenu);
+#endif
+    if (hMenu == 0) return FALSE;
+    lppop = (LPPOPUPMENU) GlobalLock(hMenu);
+    if (lppop == NULL) return FALSE;
+    if (lppop->hWnd) DestroyWindow (lppop->hWnd);
+    lpitem = lppop->firstItem;
+    while (lpitem->next != NULL) {
+#ifdef DEBUG_MENU
+	printf("DestroyMenu (%04X) // during loop items !\n", hMenu);
+#endif
+	if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
+	    DestroyMenu((HMENU)lpitem->item_id);
+	    }
+    	lpitem = (LPMENUITEM)lpitem->next;
+    	}
+    GlobalFree(hMenu);
+#ifdef DEBUG_MENU
+    printf("DestroyMenu (%04X) // End !\n", hMenu);
+#endif
+    return TRUE;
+}
+
+
diff --git a/controls/scroll.c b/controls/scroll.c
index fd8e45a..9cfa550 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -17,7 +17,8 @@
 #include "scroll.h"
 #include "heap.h"
 #include "win.h"
-#include "dirent.h"
+#include <sys/types.h>
+#include <dirent.h>
 #include <sys/stat.h>
 
 LPHEADSCROLL ScrollBarGetWindowAndStorage(HWND hwnd, WND **wndPtr);
@@ -26,50 +27,10 @@
 int CreateScrollBarStruct(HWND hwnd);
 
 
-void SCROLLBAR_CreateScrollBar(LPSTR className, LPSTR scrollLabel, HWND hwnd)
-{
-    WND *wndPtr    = WIN_FindWndPtr(hwnd);
-    WND *parentPtr = WIN_FindWndPtr(wndPtr->hwndParent);
-    DWORD style;
-    char widgetName[15];
-
-#ifdef DEBUG_SCROLLBAR
-    printf("scroll: label = %s, x = %d, y = %d\n", scrollLabel,
-	   wndPtr->rectClient.left, wndPtr->rectClient.top);
-    printf("        width = %d, height = %d\n",
-	   wndPtr->rectClient.right - wndPtr->rectClient.left,
-	   wndPtr->rectClient.bottom - wndPtr->rectClient.top);
-#endif
-
-    if (!wndPtr)
-	return;
-
-    style = wndPtr->dwStyle & 0x0000FFFF;
-/*
-    if ((style & SBS_NOTIFY) == SBS_NOTIFY)
-*/    
-    sprintf(widgetName, "%s%d", className, wndPtr->wIDmenu);
-    wndPtr->winWidget = XtVaCreateManagedWidget(widgetName,
-				    compositeWidgetClass,
-				    parentPtr->winWidget,
-				    XtNx, wndPtr->rectClient.left,
-				    XtNy, wndPtr->rectClient.top,
-				    XtNwidth, wndPtr->rectClient.right -
-				        wndPtr->rectClient.left,
-				    XtNheight, wndPtr->rectClient.bottom -
-				        wndPtr->rectClient.top,
-				    NULL );
-    GlobalUnlock(hwnd);
-    GlobalUnlock(wndPtr->hwndParent);
-}
-
-
-
 /***********************************************************************
  *           WIDGETS_ScrollBarWndProc
  */
-LONG SCROLLBAR_ScrollBarWndProc( HWND hwnd, WORD message,
-			   WORD wParam, LONG lParam )
+LONG ScrollBarWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 {    
     WORD	wRet;
     short	x, y;
@@ -169,8 +130,11 @@
 	break;
 
     case WM_KEYDOWN:
-        printf("ScrollBar WM_KEYDOWN wParam %X !\n", wParam);
-	break;
+    case WM_KEYUP:
+    case WM_CHAR:
+	lphs = ScrollBarGetWindowAndStorage(hwnd, &wndPtr);
+	return(SendMessage(wndPtr->hwndParent, message, wParam, lParam));
+
     case WM_PAINT:
 	StdDrawScrollBar(hwnd);
 	break;
@@ -330,36 +294,36 @@
         	wndPtr->hInstance, 0L);
 	}
     if (lphs->MaxPix < 1)  lphs->MaxPix = 1;
+    if (wndPtr->hCursor == (HCURSOR)NULL)
+	wndPtr->hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
     return TRUE;
 }
 
 
-
-int GetScrollPos(HWND hwnd, int nBar)
+/*************************************************************************
+ *			GetScrollWindowHandle
+ */
+HWND GetScrollWindowHandle(HWND hWnd, int nBar)
 {
-    LPHEADSCROLL lphs;
-    lphs = ScrollBarGetStorageHeader(hwnd);
-    if (lphs == NULL) return 0;
-    return lphs->CurVal;
+    WND *wndPtr;
+    if (nBar != SB_CTL) {
+    wndPtr = WIN_FindWndPtr(hWnd);
+    	if (nBar == SB_VERT) return wndPtr->hWndVScroll;
+    	if (nBar == SB_HORZ) return wndPtr->hWndHScroll;
+    	return (HWND)NULL;
+	}
+    return hWnd;
 }
 
 
-
-void GetScrollRange(HWND hwnd, int nBar, LPINT lpMin, LPINT lpMax)
-{
-    LPHEADSCROLL lphs;
-    lphs = ScrollBarGetStorageHeader(hwnd);
-    if (lphs == NULL) return;
-    *lpMin = lphs->MinVal;
-    *lpMax = lphs->MaxVal;
-}
-
-
-
+/*************************************************************************
+ *			SetScrollPos [USER.62]
+ */
 int SetScrollPos(HWND hwnd, int nBar, int nPos, BOOL bRedraw)
 {
     int nRet;
     LPHEADSCROLL lphs;
+    hwnd = GetScrollWindowHandle(hwnd, nBar);
     lphs = ScrollBarGetStorageHeader(hwnd);
     if (lphs == NULL) return 0;
     nRet = lphs->CurVal;
@@ -383,9 +347,27 @@
 
 
 
+/*************************************************************************
+ *			GetScrollPos [USER.63]
+ */
+int GetScrollPos(HWND hwnd, int nBar)
+{
+    LPHEADSCROLL lphs;
+    hwnd = GetScrollWindowHandle(hwnd, nBar);
+    lphs = ScrollBarGetStorageHeader(hwnd);
+    if (lphs == NULL) return 0;
+    return lphs->CurVal;
+}
+
+
+
+/*************************************************************************
+ *			SetScrollRange [USER.64]
+ */
 void SetScrollRange(HWND hwnd, int nBar, int MinPos, int MaxPos, BOOL bRedraw)
 {
     LPHEADSCROLL lphs;
+    hwnd = GetScrollWindowHandle(hwnd, nBar);
     lphs = ScrollBarGetStorageHeader(hwnd);
     if (lphs == NULL) return;
     lphs->MinVal = (short)MinPos;
@@ -406,5 +388,50 @@
 
 
 
+/*************************************************************************
+ *			GetScrollRange [USER.65]
+ */
+void GetScrollRange(HWND hwnd, int nBar, LPINT lpMin, LPINT lpMax)
+{
+    LPHEADSCROLL lphs;
+    hwnd = GetScrollWindowHandle(hwnd, nBar);
+    lphs = ScrollBarGetStorageHeader(hwnd);
+    if (lphs == NULL) return;
+    *lpMin = lphs->MinVal;
+    *lpMax = lphs->MaxVal;
+}
+
+
+
+/*************************************************************************
+ *			ShowScrollBar [USER.267]
+ */
+void ShowScrollBar(HWND hWnd, WORD wBar, BOOL bFlag)
+{
+    WND  *wndPtr;
+#ifdef DEBUG_SCROLL
+    printf("ShowScrollBar hWnd=%04X wBar=%d bFlag=%d\n", hWnd, wBar, bFlag);
+#endif
+    if (wBar == SB_CTL) {
+    	if (bFlag)
+	    ShowWindow(hWnd, SW_SHOW);
+	else
+	    ShowWindow(hWnd, SW_HIDE);
+	return;
+	}
+    wndPtr = WIN_FindWndPtr(hWnd);
+    if ((wBar == SB_VERT) || (wBar == SB_BOTH)) {
+    	if (bFlag)
+	    ShowWindow(wndPtr->hWndVScroll, SW_SHOW);
+	else
+	    ShowWindow(wndPtr->hWndVScroll, SW_HIDE);
+	}
+    if ((wBar == SB_HORZ) || (wBar == SB_BOTH)) {
+    	if (bFlag)
+	    ShowWindow(wndPtr->hWndHScroll, SW_SHOW);
+	else
+	    ShowWindow(wndPtr->hWndHScroll, SW_HIDE);
+	}
+}
 
 
diff --git a/controls/static.c b/controls/static.c
index 6928139..558110b 100644
--- a/controls/static.c
+++ b/controls/static.c
@@ -109,6 +109,18 @@
 	    InvalidateRect(hWnd, NULL, TRUE);
 	    break;
 
+	case WM_KEYDOWN:
+	case WM_KEYUP:
+	case WM_CHAR:
+	case WM_LBUTTONDOWN:
+	case WM_LBUTTONUP:
+	case WM_MBUTTONDOWN:
+	case WM_MBUTTONUP:
+	case WM_RBUTTONDOWN:
+	case WM_RBUTTONUP:
+	case WM_MOUSEMOVE:
+	    return(SendMessage(wndPtr->hwndParent, uMsg, wParam, lParam));
+
 	default:
 		lResult = DefWindowProc(hWnd, uMsg, wParam, lParam);
 		break;
diff --git a/controls/widgets.c b/controls/widgets.c
index 6733486..c88ac44 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -13,23 +13,28 @@
 
 LONG ButtonWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam );
 LONG StaticWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam );
-
-LONG SCROLLBAR_ScrollBarWndProc( HWND hwnd, WORD message,
-				   WORD wParam, LONG lParam );
-LONG LISTBOX_ListBoxWndProc( HWND hwnd, WORD message,
-				   WORD wParam, LONG lParam );
-LONG COMBOBOX_ComboBoxWndProc( HWND hwnd, WORD message,
-				   WORD wParam, LONG lParam );
+LONG ScrollBarWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG ListBoxWndProc  ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG ComboBoxWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG PopupMenuWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
 
 
 static WNDCLASS WIDGETS_BuiltinClasses[] =
 {
-    { 0, (LONG(*)())ButtonWndProc, 0, 2, 0, 0, 0, 0, NULL, "BUTTON" },
-    { 0, (LONG(*)())StaticWndProc, 0, 0, 0, 0, 0, 0, NULL, "STATIC" },
-    { 0, (LONG(*)())SCROLLBAR_ScrollBarWndProc, 0, 8, 0, 0, 0, 0, NULL, "SCROLLBAR" },
-    { 0, (LONG(*)())LISTBOX_ListBoxWndProc, 0, 8, 0, 0, 0, 0, NULL, "LISTBOX" },
-    { 0, (LONG(*)())COMBOBOX_ComboBoxWndProc, 0, 8, 0, 0, 0, 0, NULL, "COMBOBOX" },
-    { 0, (LONG(*)())DefDlgProc, 0, DLGWINDOWEXTRA, 0, 0, 0, 0, NULL, DIALOG_CLASS_NAME }
+    { CS_GLOBALCLASS, (LONG(*)())ButtonWndProc, 0, 2, 
+      0, 0, 0, 0, NULL, "BUTTON" },
+    { CS_GLOBALCLASS, (LONG(*)())StaticWndProc, 0, 0,
+      0, 0, 0, 0, NULL, "STATIC" },
+    { CS_GLOBALCLASS, (LONG(*)())ScrollBarWndProc, 0, 8,
+      0, 0, 0, 0, NULL, "SCROLLBAR" },
+    { CS_GLOBALCLASS, (LONG(*)())ListBoxWndProc, 0, 8,
+      0, 0, 0, 0, NULL, "LISTBOX" },
+    { CS_GLOBALCLASS, (LONG(*)())ComboBoxWndProc, 0, 8,
+      0, 0, 0, 0, NULL, "COMBOBOX" },
+    { CS_GLOBALCLASS, (LONG(*)())PopupMenuWndProc, 0, 8,
+      0, 0, 0, 0, NULL, "POPUPMENU" },
+    { CS_GLOBALCLASS, (LONG(*)())DefDlgProc, 0, DLGWINDOWEXTRA,
+      0, 0, 0, 0, NULL, DIALOG_CLASS_NAME }
 };
 
 #define NB_BUILTIN_CLASSES \
diff --git a/debugger/Imakefile b/debugger/Imakefile
new file mode 100644
index 0000000..4b4ed04
--- /dev/null
+++ b/debugger/Imakefile
@@ -0,0 +1,62 @@
+#include "../Wine.tmpl"
+
+#define IHavSubDirs
+#define PassCDebugFlags 'CDEBUGFLAGS=$(CDEBUGFLAGS)' 'CC=$(CC)'
+
+MODULE = debugger
+
+DEFINES = -DUSE_READLINE
+
+SUBDIRS = readline
+
+/* Quick and dirt hack, since i386 is defined as 1. sigh */
+#define temp i386
+#undef i386
+
+SRCS = \
+	dbg.tab.c \
+	hash.c \
+	lex.yy.c \
+	info.c \
+	i386-pinsn.c
+
+OBJS = \
+	dbg.tab.o \
+	hash.o \
+	lex.yy.o \
+	info.o \
+	i386-pinsn.o
+
+#define i386 temp
+#undef temp
+
+/*
+ * All the SUBDIR stuff
+ */
+MakeSubdirs($(SUBDIRS))
+MakefileSubdirs($(SUBDIRS))
+DependSubdirs($(SUBDIRS))
+CleanSubdirs($(SUBDIRS))
+IncludesSubdirs($(SUBDIRS))
+
+/*
+ * The main act
+ */
+WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
+
+depend:: dbg.tab.c dbg.tab.h lex.yy.c
+
+DependTarget()
+
+includes::
+
+install::
+
+clean::
+	$(RM) lex.yy.c dbg.tab* y.tab.c
+
+dbg.tab.c dbg.tab.h: dbg.y
+	$(YACC) -b dbg -d dbg.y
+
+lex.yy.c: debug.l
+	$(LEX) -I debug.l
diff --git a/debugger/readline/Imakefile b/debugger/readline/Imakefile
new file mode 100644
index 0000000..817f4af
--- /dev/null
+++ b/debugger/readline/Imakefile
@@ -0,0 +1,25 @@
+#include "../../Wine.tmpl"
+
+MODULE = readline
+
+YACC = yacc -b dbg -d
+
+DEFINES	= -DANSI_ARROWS -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT -DSYS_UNIX
+
+SRCS = \
+	complete.c \
+	editline.c \
+	sysunix.c
+
+OBJS = \
+	complete.o \
+	editline.o \
+	sysunix.o
+
+WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
+DependTarget()
+CleanTarget()
+
+includes::
+
+install::
diff --git a/etc/Imakefile b/etc/Imakefile
new file mode 100644
index 0000000..b398809
--- /dev/null
+++ b/etc/Imakefile
@@ -0,0 +1,11 @@
+#include "../Wine.tmpl"
+
+MODULE = etc
+
+AllTarget()
+
+depend::
+
+CleanTarget()
+
+includes::
diff --git a/etc/Makefile b/etc/Makefile
new file mode 100644
index 0000000..87948b0
--- /dev/null
+++ b/etc/Makefile
@@ -0,0 +1,358 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+
+# -------------------------------------------------------------------------
+# Makefile generated from "Imake.tmpl" and <Imakefile>
+# $XFree86: mit/config/Imake.tmpl,v 1.17 1993/06/03 15:26:36 dawes Exp $
+# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
+#
+# Platform-specific parameters may be set in the appropriate <vendor>.cf
+# configuration files.  Site-specific parameters should be set in the file
+# site.def.  Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor does not define any unique symbols, you will need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make World" the first time).
+#
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that need to come before
+# the platform-specific parameters - edit site.def to change
+
+# $XFree86: mit/config/site.def,v 1.65 1993/06/04 16:02:47 dawes Exp $
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# obz: changes for making Linux distribution
+
+# -------------------------------------------------------------------------
+# platform-specific configuration parameters - edit x386.cf to change
+
+# $XFree86: mit/config/x386.cf,v 1.90 1993/06/04 16:02:50 dawes Exp $
+# platform:  $XConsortium: x386.cf,v 1.7 91/08/16 19:30:10 gildea Exp $
+
+# -------------------------------------------------------------------------
+# XFree86 version definition
+# $XFree86: mit/config/xf86_vers.def,v 1.5 1993/06/01 09:12:47 dawes Exp $
+
+# -------------------------------------------------------------------------
+# XFree86 version: 1300
+# -------------------------------------------------------------------------
+
+# $XFree86: mit/config/lnuxLib.rules,v 1.2 1993/06/02 13:48:12 dawes Exp $
+
+DLL_BINDIR = /usr/dll/bin
+
+# operating system:  		Linux
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that go after
+# the platform-specific parameters - edit site.def to change
+
+# $XFree86: mit/config/site.def,v 1.65 1993/06/04 16:02:47 dawes Exp $
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# obz: changes for making Linux distribution
+
+            SHELL = 	/bin/sh
+
+              TOP = ../.
+      CURRENT_DIR = ./etc
+
+               AR = ar clq
+  BOOTSTRAPCFLAGS =
+               CC = 		gcc
+               AS = as
+
+              LEX = 		flex
+
+             YACC = 		bison -y
+
+         COMPRESS = compress
+              CPP = 		/lib/cpp $(STD_CPP_DEFINES)
+    PREPROCESSCMD = 	/lib/cpp $(STD_CPP_DEFINES)
+          INSTALL = install
+               LD = ld
+             LINT = lint
+      LINTLIBFLAG = -C
+         LINTOPTS = -axz
+               LN = ln -s
+             MAKE = make
+               MV = mv
+               CP = cp
+
+           RANLIB = ranlib
+  RANLIBINSTFLAGS =
+
+               RM = rm -f
+            TROFF = psroff
+         MSMACROS = -ms
+              TBL = tbl
+              EQN = eqn
+     STD_INCLUDES =
+  STD_CPP_DEFINES = -traditional 		-D_POSIX_SOURCE -D_BSD_SOURCE -D_GNU_SOURCE 	-Dlinux
+      STD_DEFINES = 		-D_POSIX_SOURCE -D_BSD_SOURCE -D_GNU_SOURCE 	-Dlinux
+ EXTRA_LOAD_FLAGS =
+  EXTRA_LIBRARIES =
+     OS_LIBRARIES =
+             TAGS = ctags
+
+    SHAREDCODEDEF =
+         SHLIBDEF =
+
+    PROTO_DEFINES = -DFUNCPROTO=11 -DNARROWPROTO
+
+     INSTPGMFLAGS = -s
+
+     INSTBINFLAGS = -m 0755
+     INSTUIDFLAGS = -s -m 4755
+     INSTLIBFLAGS = -m 0644
+     INSTINCFLAGS = -m 0444
+     INSTMANFLAGS = -m 0444
+     INSTDATFLAGS = -m 0444
+    INSTKMEMFLAGS = -s -m 4755
+
+      PROJECTROOT = 	/usr/X386
+
+     TOP_INCLUDES = -I$(INCROOT)
+
+      CDEBUGFLAGS = -O2
+        CCOPTIONS = -m486 -DNO_ASM -fwritable-strings
+    ANSICCOPTIONS =
+
+      ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
+       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
+           CFLAGS = $(ANSICCOPTIONS) $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+
+           LDLIBS = $(OS_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+        LDOPTIONS = $(ANSICCOPTIONS) $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) -L$(USRLIBDIR)
+
+   LDCOMBINEFLAGS = 	-r
+      DEPENDFLAGS =
+
+        MACROFILE = x386.cf
+           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+    IMAKE_DEFINES =
+
+         IRULESRC = $(CONFIGDIR)
+        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules 			$(IRULESRC)/Project.tmpl $(IRULESRC)/site.def 			$(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# -------------------------------------------------------------------------
+# X Window System Build Parameters
+# $XFree86: mit/config/Project.tmpl,v 1.13 1993/03/27 03:32:45 dawes Exp $
+# $XConsortium: Project.tmpl,v 1.138.1.1 92/11/11 09:49:19 rws Exp $
+
+_percentC_ = %C
+
+# -------------------------------------------------------------------------
+# X Window System make variables; this need to be coordinated with rules
+
+          PATHSEP = /
+        USRLIBDIR = 	/usr/X386/lib
+           BINDIR = 	/usr/X386/bin
+          INCROOT = 	/usr/X386/include
+     BUILDINCROOT = $(TOP)
+      BUILDINCDIR = $(BUILDINCROOT)/X11
+      BUILDINCTOP = ..
+           INCDIR = $(INCROOT)/X11
+           ADMDIR = /usr/adm
+           LIBDIR = $(USRLIBDIR)/X11
+        CONFIGDIR = $(LIBDIR)/config
+       LINTLIBDIR = $(USRLIBDIR)/lint
+
+          FONTDIR = $(LIBDIR)/fonts
+         XINITDIR = $(LIBDIR)/xinit
+           XDMDIR = $(LIBDIR)/xdm
+           TWMDIR = $(LIBDIR)/twm
+          MANPATH = 	/usr/X386/man
+    MANSOURCEPATH = $(MANPATH)/man
+        MANSUFFIX = 1x
+     LIBMANSUFFIX = 3x
+           MANDIR = 	$(MANSOURCEPATH)1
+        LIBMANDIR = $(MANSOURCEPATH)3
+           NLSDIR = $(LIBDIR)/nls
+        PEXAPIDIR = $(LIBDIR)/PEX
+      XAPPLOADDIR = $(LIBDIR)/app-defaults
+       FONTCFLAGS = -t
+       LINKKITDIR = 	$(USRLIBDIR)/Server
+
+     INSTAPPFLAGS = $(INSTDATFLAGS)
+
+            IMAKE = imake
+           DEPEND = makedepend
+              RGB = rgb
+
+            FONTC = bdftopcf
+
+        MKFONTDIR = mkfontdir
+        MKDIRHIER = 	/bin/sh $(BINDIR)/mkdirhier
+
+        CONFIGSRC = $(TOP)/config
+       DOCUTILSRC = $(TOP)/doc/util
+        CLIENTSRC = $(TOP)/clients
+          DEMOSRC = $(TOP)/demos
+           LIBSRC = $(TOP)/lib
+          FONTSRC = $(TOP)/fonts
+       INCLUDESRC = $(TOP)/X11
+        SERVERSRC = $(TOP)/server
+          UTILSRC = $(TOP)/util
+        SCRIPTSRC = $(UTILSRC)/scripts
+       EXAMPLESRC = $(TOP)/examples
+       CONTRIBSRC = $(TOP)/../contrib
+           DOCSRC = $(TOP)/doc
+           RGBSRC = $(TOP)/rgb
+        DEPENDSRC = $(UTILSRC)/makedepend
+         IMAKESRC = $(CONFIGSRC)
+         XAUTHSRC = $(LIBSRC)/Xau
+          XLIBSRC = $(LIBSRC)/X
+           XMUSRC = $(LIBSRC)/Xmu
+       TOOLKITSRC = $(LIBSRC)/Xt
+       AWIDGETSRC = $(LIBSRC)/Xaw
+       OLDXLIBSRC = $(LIBSRC)/oldX
+      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+      BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
+      BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
+     MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
+         FSLIBSRC = $(FONTSRC)/lib/fs
+    FONTSERVERSRC = $(FONTSRC)/server
+     EXTENSIONSRC = $(TOP)/extensions
+         XILIBSRC = $(EXTENSIONSRC)/lib/xinput
+        PEXLIBSRC = $(EXTENSIONSRC)/lib/PEXlib
+      PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
+
+# $XFree86: mit/config/lnuxLib.tmpl,v 1.1 1993/04/16 14:06:06 dawes Exp $
+
+SHLIBLDFLAGS =
+PICFLAGS = -B/usr/dll/jump/
+
+  DEPEXTENSIONLIB =
+     EXTENSIONLIB = -lXext
+
+          DEPXLIB = $(DEPEXTENSIONLIB)
+             XLIB = $(EXTENSIONLIB) -lX11
+
+        DEPXMULIB =
+           XMULIB = -lXmu
+
+      DEPXTOOLLIB =
+         XTOOLLIB = -lXt
+
+        DEPXAWLIB =
+           XAWLIB = -lXaw
+
+        DEPXILIB =
+           XILIB = -lXi
+
+    DEPXTESTLIB =
+       XTESTLIB = -lXtst
+
+        DEPPEXLIB =
+         PEXLIB = -lPEX5
+
+        SOXLIBREV = 3.0.1
+          SOXTREV = 3.0.1
+         SOXAWREV = 3.0.1
+        SOOLDXREV = 3.0.1
+         SOXMUREV = 3.0.1
+        SOXEXTREV = 3.0.1
+      SOXINPUTREV = 3.0.1
+         SOPEXREV = 1.0.1
+
+      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+         XAUTHLIB = 			 -lXau
+      DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
+         XDMCPLIB = 			 -lXdmcp
+
+       DEPOLDXLIB = $(USRLIBDIR)/liboldX.a
+          OLDXLIB = 			 -loldX
+
+        DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
+           PHIGSLIB = 			 -lphigs
+
+       DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
+          XBSDLIB = 			 -lXbsd
+
+ LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
+         LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
+          LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
+        LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
+          LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
+           LINTXI = $(LINTLIBDIR)/llib-lXi.ln
+          LINTPEX = $(LINTLIBDIR)/llib-lPEX5.ln
+        LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
+
+          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+         DEPLIBS1 = $(DEPLIBS)
+         DEPLIBS2 = $(DEPLIBS)
+         DEPLIBS3 = $(DEPLIBS)
+
+# -------------------------------------------------------------------------
+# Imake rules for building libraries, programs, scripts, and data files
+# $XFree86: mit/config/Imake.rules,v 1.9 1993/03/23 12:56:27 dawes Exp $
+# rules:  $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+# -------------------------------------------------------------------------
+# start of Imakefile
+
+# $Id$
+
+INCLUDES = -I$(TOP)/include
+
+# Imake rules go here
+
+# First, dll description to files etc
+
+MODULE = etc
+
+all::
+
+depend::
+
+clean::
+	$(RM_CMD) "#"*
+
+includes::
+
+# -------------------------------------------------------------------------
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+	$(RM_CMD) "#"*
+
+Makefile::
+	-@if [ -f Makefile ]; then set -x; \
+	$(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+	else exit 0; fi
+	$(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+	$(TAGS) -w *.[ch]
+	$(TAGS) -xw *.[ch] > TAGS
+
+# -------------------------------------------------------------------------
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+	@echo "install in $(CURRENT_DIR) done"
+
+install.man::
+	@echo "install.man in $(CURRENT_DIR) done"
+
+install.linkkit::
+	@echo "install.linkkit in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+# -------------------------------------------------------------------------
+# dependencies generated by makedepend
+
diff --git a/if1632/Imakefile b/if1632/Imakefile
new file mode 100644
index 0000000..8c11afd
--- /dev/null
+++ b/if1632/Imakefile
@@ -0,0 +1,37 @@
+#include "../Wine.tmpl"
+
+MODULE = if1632
+
+SRCS = \
+	call.S \
+	callback.c \
+	relay.c
+
+OBJS = \
+	call.o \
+	callback.o \
+	relay.o
+
+/*
+ * If you add a new spec file, copy one of these lines
+ */
+MakeDllFromSpec(gdi,$(TOP)/$(MODULE))
+MakeDllFromSpec(kernel,$(TOP)/$(MODULE))
+MakeDllFromSpec(keyboard,$(TOP)/$(MODULE))
+MakeDllFromSpec(shell,$(TOP)/$(MODULE))
+MakeDllFromSpec(sound,$(TOP)/$(MODULE))
+MakeDllFromSpec(unixlib,$(TOP)/$(MODULE))
+MakeDllFromSpec(user,$(TOP)/$(MODULE))
+MakeDllFromSpec(win87em,$(TOP)/$(MODULE))
+
+/*
+ * Yes I know *.o is not veru clever, but can you do it cleaner ?
+ */
+WineRelocatableTarget($(TOP)/$(MODULE),*.o,$(OBJS))
+
+clean::
+	$(RM) dll*
+
+depend::
+
+includes::
diff --git a/if1632/callback.c b/if1632/callback.c
index 1852185..82c71de 100644
--- a/if1632/callback.c
+++ b/if1632/callback.c
@@ -7,7 +7,7 @@
 #include "segmem.h"
 #include <setjmp.h>
 
-extern unsigned short SelectorOwners[];
+extern SEGDESC Segments[];
 extern unsigned short IF1632_Saved16_ss;
 extern unsigned long  IF1632_Saved16_ebp;
 extern unsigned long  IF1632_Saved16_esp;
@@ -56,7 +56,7 @@
     unsigned int seg_idx;
     
     seg_idx = (unsigned short) (csip >> 19);
-    return SelectorOwners[seg_idx];
+    return Segments[seg_idx].owner;
 }
 
 /**********************************************************************
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index a1fc5c5..f2e2baa 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -43,6 +43,11 @@
 33  pascal TextOut(word s_word s_word ptr word) TextOut(1 2 3 4 5)
 34  pascal BitBlt( word s_word s_word s_word s_word word s_word s_word long)
 	   BitBlt(1 2 3 4 5 6 7 8 9)
+35  pascal StrechBlt( word s_word s_word s_word s_word word s_word s_word s_word s_word long)
+           StrechBlt(1 2 3 4 5 6 7 8 9 10 11)
+
+36  pascal Polygon (word ptr word) Polygon (1 2 3)
+37  pascal Polyline (word ptr word) Polyline (1 2 3)
 39  pascal RestoreDC(word s_word) RestoreDC(1 2)
 40  pascal FillRgn(word word word) FillRgn(1 2 3)
 43  pascal PaintRgn(word word) PaintRgn(1 2)
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 142f451..86a1508 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -28,6 +28,8 @@
 24  pascal UnlockSegment(s_word) KERNEL_UnlockSegment(1)
 25  pascal GlobalCompact(long) GlobalCompact(1)
 30  pascal WaitEvent(word) KERNEL_WaitEvent(1)
+34  pascal SetTaskQueue(word word) SetTaskQueue(1 2)
+35  pascal GetTaskQueue(word) GetTaskQueue(1)
 49  pascal GetModuleFileName(word ptr s_word) KERNEL_GetModuleFileName(1 2 3)
 50  pascal GetProcAddress(word ptr) GetProcAddress(1 2)
 51  pascal MakeProcInstance(ptr word) CALLBACK_MakeProcInstance(1 2)
@@ -43,6 +45,8 @@
 74  pascal OpenFile(ptr ptr word) KERNEL_OpenFile(1 2 3)
 81  pascal _lclose(word) KERNEL__lclose(1)
 82  pascal _lread(word ptr word) KERNEL__lread(1 2 3)
+83  pascal _lcreate(ptr word) KERNEL__lcreate(1 2)
+84  pascal _llseek(word long word) KERNEL__llseek(1 2 3)
 85  pascal _lopen(ptr word) KERNEL__lopen(1 2)
 86  pascal _lwrite(word ptr word) KERNEL__lwrite(1 2 3)
 88  pascal lstrcpy(ptr ptr) lstrcpy(1 2)
@@ -51,11 +55,14 @@
 91  register InitTask(word word word word word
 		      word word word word word) 
 	     KERNEL_InitTask()
+92  pascal GetTempDrive(byte) GetTempDrive(1)
 95  pascal LoadLibrary(ptr) LoadLibrary(1)
 96  pascal FreeLibrary(word) FreeLibrary(1)
+97  pascal GetTempFileName(byte ptr word ptr) GetTempDrive(1 2 3 4)
 102 register DOS3Call(word word word word word
 		      word word word word word) 
 	     KERNEL_DOS3Call()
+107 pascal SetErrorMode(word) SetErrorMode(1)
 111 pascal GlobalWire(word) GlobalLock(1)
 112 pascal GlobalUnWire(word) GlobalUnlock(1)
 115 pascal OutputDebugString(ptr) OutputDebugString(1)
@@ -68,6 +75,9 @@
 	   WritePrivateProfileString(1 2 3 4)
 131 pascal GetDOSEnvironment() GetDOSEnvironment()
 132 return GetWinFlags 0 0x413
+134 pascal GetWindowsDirectory(ptr word) GetWindowsDirectory(1 2)
+135 pascal GetSystemDirectory(ptr word) GetSystemDirectory(1 2)
+136 pascal GetDriveType(byte) GetWindowsDirectory(1)
 154 return GlobalNotify 4 0
 163 pascal GlobalLRUOldest(word) ReturnArg(1)
 164 pascal GlobalLRUNewest(word) ReturnArg(1)
diff --git a/if1632/relay.c b/if1632/relay.c
index 859144c..d6ad335 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -173,7 +173,7 @@
 	  case DLL_ARGTYPE_FARPTR:
 	    ip = (int *) ((char *) arg_ptr + offset);
 	    if (*ip & 0xffff0000)
-		arg_table[i] = SAFEMAKEPTR((unsigned) *ip >> 16, *ip);
+		arg_table[i] = FIXPTR(*ip);
 	    else
 		arg_table[i] = *ip;
 	    break;
diff --git a/if1632/user.spec b/if1632/user.spec
index bf032d6..86682f1 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -13,12 +13,16 @@
 13  pascal GetTickCount() GetTickCount()
 14  return GetTimerResolution 0 1000
 15  pascal GetCurrentTime() GetTickCount()
+16  pascal ClipCursor(ptr) ClipCursor(1)
+17  pascal GetCursorPos(ptr) GetCursorPos(1)
 18  pascal SetCapture(word) SetCapture(1)
 19  pascal ReleaseCapture() ReleaseCapture()
 20  pascal SetDoubleClickTime(word) SetDoubleClickTime(1)
 21  pascal GetDoubleClickTime() GetDoubleClickTime()
 22  pascal SetFocus(word) SetFocus(1)
 23  pascal GetFocus() GetFocus()
+28  pascal ClientToScreen(word ptr) ClientToScreen(1 2)
+29  pascal ScreenToClient(word ptr) ScreenToClient(1 2)
 31  pascal IsIconic(word) IsIconic(1)
 32  pascal GetWindowRect(word ptr) GetWindowRect(1 2)
 33  pascal GetClientRect(word ptr) GetClientRect(1 2)
@@ -41,13 +45,18 @@
 56  pascal MoveWindow(word word word word word word) 
            MoveWindow(1 2 3 4 5 6)
 57  pascal RegisterClass(ptr) RegisterClass(1)
+58  pascal GetClassName(word ptr word) GetClassName(1 2 3)
 61  pascal ScrollWindow(word s_word s_word ptr ptr) ScrollWindow(1 2 3 4 5)
 62  pascal SetScrollPos(word word word word) SetScrollPos(1 2 3 4)
+63  pascal GetScrollPos(word word) GetScrollPos(1 2)
 64  pascal SetScrollRange(word word word word word) SetScrollRange(1 2 3 4 5)
+65  pascal GetScrollRange(word word ptr ptr) GetScrollRange(1 2 3 4)
 66  pascal GetDC(word) GetDC(1)
+67  pascal GetWindowDC(word) GetWindowDC(1)
 68  pascal ReleaseDC(word word) ReleaseDC(1 2)
-69  pascal SetCursor(word word) SetCursor(1 2)
-71  pascal ShowCursor(word word) ShowCursor(1 2)
+69  pascal SetCursor(word) SetCursor(1)
+70  pascal SetCursorPos(word word) SetCursorPos(1 2)
+71  pascal ShowCursor(word) ShowCursor(1)
 72  pascal SetRect(ptr s_word s_word s_word s_word) SetRect(1 2 3 4 5)
 73  pascal SetRectEmpty(ptr) SetRectEmpty(1)
 74  pascal CopyRect(ptr ptr) CopyRect(1 2)
@@ -67,7 +76,7 @@
 89  pascal CreateDialog(word ptr word ptr) CreateDialog(1 2 3 4)
 90  pascal IsDialogMessage(word ptr) IsDialogMessage(1 2)
 91  pascal GetDlgItem(word word) GetDlgItem(1 2)
-92  pascal SetDlgItemText(word ptr) SetDlgItemText(1 2)
+92  pascal SetDlgItemText(word word ptr) SetDlgItemText(1 2 3)
 93  pascal GetDlgItemText(word word ptr word) GetDlgItemText(1 2 3 4)
 94  pascal SetDlgItemInt(word word word word) SetDlgItemInt(1 2 3 4)
 95  pascal GetDlgItemInt(word word ptr word) GetDlgItemInt(1 2 3 4)
@@ -106,9 +115,18 @@
 136 pascal SetWindowLong(word s_word long) SetWindowLong(1 2 3)
 150 pascal LoadMenu(word ptr) LoadMenu(1 2)
 151 pascal CreateMenu() CreateMenu()
-154 pascal CheckMenu(word word word) CheckMenu(1 2 3)
+152 pascal DestroyMenu(word) DestroyMenu(1)
+154 pascal CheckMenuItem(word word word) CheckMenuItem(1 2 3)
+155 pascal EnableMenuItem(word word word) EnableMenuItem(1 2 3)
 157 pascal GetMenu(word) GetMenu(1)
 158 pascal SetMenu(word word) SetMenu(1 2)
+163 pascal CreateCaret(word word word word) CreateCaret(1 2 3 4)
+164 pascal DestroyCaret() DestroyCaret()
+165 pascal SetCaretPos(word word) SetCaretPos(1 2)
+166 pascal HideCaret(word) HideCaret(1)
+167 pascal ShowCaret(word) ShowCaret(1)
+166 pascal SetCaretBlinkTime(word) SetCaretBlinkTime(1)
+169 pascal GetCaretBlinkTime() GetCaretBlinkTime()
 171 pascal WinHelp(word word long) WinHelp(1 2 3)
 173 pascal LoadCursor(word ptr) LoadCursor(1 2)
 174 pascal LoadIcon(word ptr) LoadIcon(1 2)
@@ -119,7 +137,24 @@
 180 pascal GetSysColor(word) GetSysColor(1)
 181 pascal SetSysColors(word ptr ptr) SetSysColors(1 2 3)
 182 pascal KillSystemTimer(word word) KillSystemTimer(1 2)
+183 pascal GetCaretPos(ptr) GetCaretPos(1)
 190 pascal GetUpdateRect(word ptr word) GetUpdateRect(1 2 3)
+200 pascal OpenComm(ptr word word) OpenComm(1 2 3)
+201 pascal SetCommState(ptr) SetCommState(1)
+202 pascal GetCommState(word ptr) GetCommState(1 2)
+203 pascal GetCommError(word ptr) GetCommError(1 2)
+204 pascal ReadComm(word ptr word) ReadComm(1 2 3)
+205 pascal WriteComm(word ptr word) WriteComm(1 2 3)
+206 pascal TransmitCommChar(word byte) TransmitCommChar (1 2)
+207 pascal CloseComm(word) CloseComm(1)
+208 pascal SetCommEventMask(word word) SetCommEventMask(1 2)
+209 pascal GetCommEventMask(word word) GetCommEventMask(1 2)
+210 pascal SetCommBreak(word) SetCommBreak(1)
+211 pascal ClearCommBreak(word) ClearCommBreak(1)
+212 pascal UngetCommChar(word byte) UngetCommChar(1 2)
+213 pascal BuildCommDCB(ptr ptr) BuildCommDCB(1 2)
+214 pascal EscapeCommFunction(word word) EscapeCommFunction(1 2)
+215 pascal FlushComm(word word) FlushComm(1 2)
 218 pascal DialogBoxIndirect(word word word ptr) DialogBoxIndirect(1 2 3 4)
 219 pascal CreateDialogIndirect(word ptr word ptr)
 	   CreateDialogIndirect(1 2 3 4)
@@ -131,6 +166,7 @@
 230 pascal GetNextWindow(word word) GetNextWindow(1 2)
 232 pascal SetWindowPos(word word word word word word word) 
            SetWindowPos(1 2 3 4 5 6 7)
+236 pascal GetCapture() GetCapture()
 237 pascal GetUpdateRgn(word word word) GetUpdateRgn(1 2 3)
 239 pascal DialogBoxParam(word ptr word ptr long) DialogBoxParam(1 2 3 4 5)
 240 pascal DialogBoxIndirectParam(word word word ptr long)
@@ -140,9 +176,14 @@
 242 pascal CreateDialogIndirectParam(word ptr word ptr long)
 	   CreateDialogIndirectParam(1 2 3 4 5)
 244 pascal EqualRect(ptr ptr) EqualRect(1 2)
+258 pascal MapWindowPoints(word word ptr word) MapWindowPoints(1 2 3 4)
 262 pascal GetWindow(word word) GetWindow(1 2)
 266 pascal SetMessageQueue(word) SetMessageQueue(1)
+267 pascal ShowScrollBar(word word word) ShowScrollBar(1 2 3)
+272 pascal IsZoomed(word) IsZoomed(1)
 277 pascal GetDlgCtrlID(word) GetDlgCtrlID(1)
+282 pascal SelectPalette(word word word) SelectPalette(1 2 3)
+283 pascal RealizePalette(word) RealizePalette(1)
 286 pascal GetDesktopWindow() GetDesktopWindow()
 288 pascal GetMessageExtraInfo() GetMessageExtraInfo()
 319 pascal ScrollWindowEx(word s_word s_word ptr ptr word ptr word) 
@@ -151,9 +192,20 @@
 325 pascal PaintRect(word word word word ptr) PaintRect(1 2 3 4 5)
 334 pascal GetQueueStatus(word) GetQueueStatus(1)
 335 pascal GetInputState() GetInputState()
+359 pascal GetDCEx(word word long) GetDCEx(1 2 3)
 373 pascal SubtractRect(ptr ptr ptr) SubtractRect(1 2 3)
 403 pascal UnregisterClass(ptr word) UnregisterClass(1 2)
+404 pascal GetClassInfo(word ptr ptr) GetClassInfo(1 2 3)
+406 pascal CreateCursor(word word word word word ptr ptr) 
+	CreateCursor(1 2 3 4 5 6 7)
+410 pascal InsertMenu(word word word word ptr) InsertMenu(1 2 3 4 5)
 411 pascal AppendMenu(word word word ptr) AppendMenu(1 2 3 4)
+412 pascal RemoveMenu(word word word) RemoveMenu(1 2 3)
+413 pascal DeleteMenu(word word word) DeleteMenu(1 2 3)
+414 pascal ModifyMenu(word word word word ptr) ModifyMenu(1 2 3 4 5)
+415 pascal CreatePopupMenu() CreatePopupMenu()
+416 pascal TrackPopupMenu(word word word word word word ptr) 
+	   TrackPopupMenu(1 2 3 4 5 6 7)
 420 pascal wsprintf(ptr ptr) wsprintf(1 2)
 421 pascal wvsprintf(ptr ptr ptr) wvsprintf(1 2 3)
 430 pascal lstrcmp(ptr ptr) lstrcmp(1 2)
diff --git a/include/Imakefile b/include/Imakefile
new file mode 100644
index 0000000..4e37987
--- /dev/null
+++ b/include/Imakefile
@@ -0,0 +1,38 @@
+#include "../Wine.tmpl"
+
+MODULE = include
+
+HEADERS = \
+	atom.h \
+	callback.h \
+	class.h \
+	combo.h \
+	cursor.h \
+	dce.h \
+	dialog.h \
+	dlls.h \
+	files.h \
+	gdi.h \
+	heap.h \
+	icon.h \
+	int21.h \
+	listbox.h \
+	menu.h \
+	message.h \
+	neexe.h \
+	prototypes.h \
+	regfunc.h \
+	scroll.h \
+	segmem.h \
+	user.h \
+	win.h \
+	windows.h \
+	wine.h
+
+AllTarget()
+
+depend::
+
+CleanTarget()
+
+includes::
diff --git a/include/Makefile b/include/Makefile
new file mode 100644
index 0000000..97bc6f4
--- /dev/null
+++ b/include/Makefile
@@ -0,0 +1,360 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+
+# -------------------------------------------------------------------------
+# Makefile generated from "Imake.tmpl" and <Imakefile>
+# $XFree86: mit/config/Imake.tmpl,v 1.17 1993/06/03 15:26:36 dawes Exp $
+# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
+#
+# Platform-specific parameters may be set in the appropriate <vendor>.cf
+# configuration files.  Site-specific parameters should be set in the file
+# site.def.  Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor does not define any unique symbols, you will need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make World" the first time).
+#
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that need to come before
+# the platform-specific parameters - edit site.def to change
+
+# $XFree86: mit/config/site.def,v 1.65 1993/06/04 16:02:47 dawes Exp $
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# obz: changes for making Linux distribution
+
+# -------------------------------------------------------------------------
+# platform-specific configuration parameters - edit x386.cf to change
+
+# $XFree86: mit/config/x386.cf,v 1.90 1993/06/04 16:02:50 dawes Exp $
+# platform:  $XConsortium: x386.cf,v 1.7 91/08/16 19:30:10 gildea Exp $
+
+# -------------------------------------------------------------------------
+# XFree86 version definition
+# $XFree86: mit/config/xf86_vers.def,v 1.5 1993/06/01 09:12:47 dawes Exp $
+
+# -------------------------------------------------------------------------
+# XFree86 version: 1300
+# -------------------------------------------------------------------------
+
+# $XFree86: mit/config/lnuxLib.rules,v 1.2 1993/06/02 13:48:12 dawes Exp $
+
+DLL_BINDIR = /usr/dll/bin
+
+# operating system:  		Linux
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that go after
+# the platform-specific parameters - edit site.def to change
+
+# $XFree86: mit/config/site.def,v 1.65 1993/06/04 16:02:47 dawes Exp $
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# obz: changes for making Linux distribution
+
+            SHELL = 	/bin/sh
+
+              TOP = ../.
+      CURRENT_DIR = ./include
+
+               AR = ar clq
+  BOOTSTRAPCFLAGS =
+               CC = 		gcc
+               AS = as
+
+              LEX = 		flex
+
+             YACC = 		bison -y
+
+         COMPRESS = compress
+              CPP = 		/lib/cpp $(STD_CPP_DEFINES)
+    PREPROCESSCMD = 	/lib/cpp $(STD_CPP_DEFINES)
+          INSTALL = install
+               LD = ld
+             LINT = lint
+      LINTLIBFLAG = -C
+         LINTOPTS = -axz
+               LN = ln -s
+             MAKE = make
+               MV = mv
+               CP = cp
+
+           RANLIB = ranlib
+  RANLIBINSTFLAGS =
+
+               RM = rm -f
+            TROFF = psroff
+         MSMACROS = -ms
+              TBL = tbl
+              EQN = eqn
+     STD_INCLUDES =
+  STD_CPP_DEFINES = -traditional 		-D_POSIX_SOURCE -D_BSD_SOURCE -D_GNU_SOURCE 	-Dlinux
+      STD_DEFINES = 		-D_POSIX_SOURCE -D_BSD_SOURCE -D_GNU_SOURCE 	-Dlinux
+ EXTRA_LOAD_FLAGS =
+  EXTRA_LIBRARIES =
+     OS_LIBRARIES =
+             TAGS = ctags
+
+    SHAREDCODEDEF =
+         SHLIBDEF =
+
+    PROTO_DEFINES = -DFUNCPROTO=11 -DNARROWPROTO
+
+     INSTPGMFLAGS = -s
+
+     INSTBINFLAGS = -m 0755
+     INSTUIDFLAGS = -s -m 4755
+     INSTLIBFLAGS = -m 0644
+     INSTINCFLAGS = -m 0444
+     INSTMANFLAGS = -m 0444
+     INSTDATFLAGS = -m 0444
+    INSTKMEMFLAGS = -s -m 4755
+
+      PROJECTROOT = 	/usr/X386
+
+     TOP_INCLUDES = -I$(INCROOT)
+
+      CDEBUGFLAGS = -O2
+        CCOPTIONS = -m486 -DNO_ASM -fwritable-strings
+    ANSICCOPTIONS =
+
+      ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
+       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
+           CFLAGS = $(ANSICCOPTIONS) $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+
+           LDLIBS = $(OS_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+        LDOPTIONS = $(ANSICCOPTIONS) $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) -L$(USRLIBDIR)
+
+   LDCOMBINEFLAGS = 	-r
+      DEPENDFLAGS =
+
+        MACROFILE = x386.cf
+           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+    IMAKE_DEFINES =
+
+         IRULESRC = $(CONFIGDIR)
+        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules 			$(IRULESRC)/Project.tmpl $(IRULESRC)/site.def 			$(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# -------------------------------------------------------------------------
+# X Window System Build Parameters
+# $XFree86: mit/config/Project.tmpl,v 1.13 1993/03/27 03:32:45 dawes Exp $
+# $XConsortium: Project.tmpl,v 1.138.1.1 92/11/11 09:49:19 rws Exp $
+
+_percentC_ = %C
+
+# -------------------------------------------------------------------------
+# X Window System make variables; this need to be coordinated with rules
+
+          PATHSEP = /
+        USRLIBDIR = 	/usr/X386/lib
+           BINDIR = 	/usr/X386/bin
+          INCROOT = 	/usr/X386/include
+     BUILDINCROOT = $(TOP)
+      BUILDINCDIR = $(BUILDINCROOT)/X11
+      BUILDINCTOP = ..
+           INCDIR = $(INCROOT)/X11
+           ADMDIR = /usr/adm
+           LIBDIR = $(USRLIBDIR)/X11
+        CONFIGDIR = $(LIBDIR)/config
+       LINTLIBDIR = $(USRLIBDIR)/lint
+
+          FONTDIR = $(LIBDIR)/fonts
+         XINITDIR = $(LIBDIR)/xinit
+           XDMDIR = $(LIBDIR)/xdm
+           TWMDIR = $(LIBDIR)/twm
+          MANPATH = 	/usr/X386/man
+    MANSOURCEPATH = $(MANPATH)/man
+        MANSUFFIX = 1x
+     LIBMANSUFFIX = 3x
+           MANDIR = 	$(MANSOURCEPATH)1
+        LIBMANDIR = $(MANSOURCEPATH)3
+           NLSDIR = $(LIBDIR)/nls
+        PEXAPIDIR = $(LIBDIR)/PEX
+      XAPPLOADDIR = $(LIBDIR)/app-defaults
+       FONTCFLAGS = -t
+       LINKKITDIR = 	$(USRLIBDIR)/Server
+
+     INSTAPPFLAGS = $(INSTDATFLAGS)
+
+            IMAKE = imake
+           DEPEND = makedepend
+              RGB = rgb
+
+            FONTC = bdftopcf
+
+        MKFONTDIR = mkfontdir
+        MKDIRHIER = 	/bin/sh $(BINDIR)/mkdirhier
+
+        CONFIGSRC = $(TOP)/config
+       DOCUTILSRC = $(TOP)/doc/util
+        CLIENTSRC = $(TOP)/clients
+          DEMOSRC = $(TOP)/demos
+           LIBSRC = $(TOP)/lib
+          FONTSRC = $(TOP)/fonts
+       INCLUDESRC = $(TOP)/X11
+        SERVERSRC = $(TOP)/server
+          UTILSRC = $(TOP)/util
+        SCRIPTSRC = $(UTILSRC)/scripts
+       EXAMPLESRC = $(TOP)/examples
+       CONTRIBSRC = $(TOP)/../contrib
+           DOCSRC = $(TOP)/doc
+           RGBSRC = $(TOP)/rgb
+        DEPENDSRC = $(UTILSRC)/makedepend
+         IMAKESRC = $(CONFIGSRC)
+         XAUTHSRC = $(LIBSRC)/Xau
+          XLIBSRC = $(LIBSRC)/X
+           XMUSRC = $(LIBSRC)/Xmu
+       TOOLKITSRC = $(LIBSRC)/Xt
+       AWIDGETSRC = $(LIBSRC)/Xaw
+       OLDXLIBSRC = $(LIBSRC)/oldX
+      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+      BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
+      BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
+     MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
+         FSLIBSRC = $(FONTSRC)/lib/fs
+    FONTSERVERSRC = $(FONTSRC)/server
+     EXTENSIONSRC = $(TOP)/extensions
+         XILIBSRC = $(EXTENSIONSRC)/lib/xinput
+        PEXLIBSRC = $(EXTENSIONSRC)/lib/PEXlib
+      PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
+
+# $XFree86: mit/config/lnuxLib.tmpl,v 1.1 1993/04/16 14:06:06 dawes Exp $
+
+SHLIBLDFLAGS =
+PICFLAGS = -B/usr/dll/jump/
+
+  DEPEXTENSIONLIB =
+     EXTENSIONLIB = -lXext
+
+          DEPXLIB = $(DEPEXTENSIONLIB)
+             XLIB = $(EXTENSIONLIB) -lX11
+
+        DEPXMULIB =
+           XMULIB = -lXmu
+
+      DEPXTOOLLIB =
+         XTOOLLIB = -lXt
+
+        DEPXAWLIB =
+           XAWLIB = -lXaw
+
+        DEPXILIB =
+           XILIB = -lXi
+
+    DEPXTESTLIB =
+       XTESTLIB = -lXtst
+
+        DEPPEXLIB =
+         PEXLIB = -lPEX5
+
+        SOXLIBREV = 3.0.1
+          SOXTREV = 3.0.1
+         SOXAWREV = 3.0.1
+        SOOLDXREV = 3.0.1
+         SOXMUREV = 3.0.1
+        SOXEXTREV = 3.0.1
+      SOXINPUTREV = 3.0.1
+         SOPEXREV = 1.0.1
+
+      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+         XAUTHLIB = 			 -lXau
+      DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
+         XDMCPLIB = 			 -lXdmcp
+
+       DEPOLDXLIB = $(USRLIBDIR)/liboldX.a
+          OLDXLIB = 			 -loldX
+
+        DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
+           PHIGSLIB = 			 -lphigs
+
+       DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
+          XBSDLIB = 			 -lXbsd
+
+ LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
+         LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
+          LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
+        LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
+          LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
+           LINTXI = $(LINTLIBDIR)/llib-lXi.ln
+          LINTPEX = $(LINTLIBDIR)/llib-lPEX5.ln
+        LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
+
+          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+         DEPLIBS1 = $(DEPLIBS)
+         DEPLIBS2 = $(DEPLIBS)
+         DEPLIBS3 = $(DEPLIBS)
+
+# -------------------------------------------------------------------------
+# Imake rules for building libraries, programs, scripts, and data files
+# $XFree86: mit/config/Imake.rules,v 1.9 1993/03/23 12:56:27 dawes Exp $
+# rules:  $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+# -------------------------------------------------------------------------
+# start of Imakefile
+
+# $Id$
+
+INCLUDES = -I$(TOP)/include
+
+# Imake rules go here
+
+# First, dll description to files etc
+
+MODULE = include
+
+HEADERS = 	atom.h 	callback.h 	class.h 	combo.h 	cursor.h 	dce.h 	dialog.h 	dlls.h 	files.h 	gdi.h 	heap.h 	icon.h 	int21.h 	listbox.h 	menu.h 	message.h 	neexe.h 	prototypes.h 	regfunc.h 	scroll.h 	segmem.h 	user.h 	win.h 	windows.h 	wine.h
+
+all::
+
+depend::
+
+clean::
+	$(RM_CMD) "#"*
+
+includes::
+
+# -------------------------------------------------------------------------
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+	$(RM_CMD) "#"*
+
+Makefile::
+	-@if [ -f Makefile ]; then set -x; \
+	$(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+	else exit 0; fi
+	$(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+	$(TAGS) -w *.[ch]
+	$(TAGS) -xw *.[ch] > TAGS
+
+# -------------------------------------------------------------------------
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+	@echo "install in $(CURRENT_DIR) done"
+
+install.man::
+	@echo "install.man in $(CURRENT_DIR) done"
+
+install.linkkit::
+	@echo "install.linkkit in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+# -------------------------------------------------------------------------
+# dependencies generated by makedepend
+
diff --git a/include/atom.h b/include/atom.h
new file mode 100644
index 0000000..61cf6b1
--- /dev/null
+++ b/include/atom.h
@@ -0,0 +1,27 @@
+/*
+ * Atom table definitions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#ifndef ATOM_H
+#define ATOM_H
+
+#include "windows.h"
+
+
+typedef struct
+{
+    HANDLE      next;
+    WORD        refCount;
+    BYTE        length;
+    BYTE        str[1];
+} ATOMENTRY;
+
+typedef struct
+{
+    WORD        size;
+    HANDLE      entries[1];
+} ATOMTABLE;
+
+#endif  /* ATOM_H */
diff --git a/include/class.h b/include/class.h
index 9ab50e4..285e81b 100644
--- a/include/class.h
+++ b/include/class.h
@@ -17,7 +17,7 @@
     HCLASS       hNext;         /* Next class */
     WORD         wMagic;        /* Magic number (must be CLASS_MAGIC) */
     ATOM         atomName;      /* Name of the class */
-    HDC          hdc;           /* Class DC (if CS_CLASSDC) */
+    HANDLE       hdce;          /* Class DCE (if CS_CLASSDC) */
     WORD         cWindows;      /* Count of existing windows of this class */
     WNDCLASS     wc __attribute__ ((packed));  /* Class information */
     WORD         wExtra[1];     /* Class extra bytes */
diff --git a/include/dce.h b/include/dce.h
index eff58a5..d95c781 100644
--- a/include/dce.h
+++ b/include/dce.h
@@ -9,16 +9,27 @@
 
 #include "windows.h"
 
+typedef enum
+{
+    DCE_CACHE_DC,   /* This is a cached DC (allocated by USER) */
+    DCE_CLASS_DC,   /* This is a class DC (style CS_CLASSDC) */
+    DCE_WINDOW_DC   /* This is a window DC (style CS_OWNDC) */
+} DCE_TYPE;
+
+
 typedef struct tagDCE
 {
     HANDLE     hNext;
     HWND       hwndCurrent;
     HDC        hdc;
-    BYTE       flags;
+    DCE_TYPE   type;
     BOOL       inUse;
     WORD       xOrigin;
     WORD       yOrigin;
 } DCE;
 
 
+extern HANDLE DCE_AllocDCE( DCE_TYPE type );
+extern void DCE_FreeDCE( HANDLE hdce );
+
 #endif  /* DCE_H */
diff --git a/include/files.h b/include/files.h
deleted file mode 100644
index 1b628a2..0000000
--- a/include/files.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef _FILES_H
-#define _FILES_H
-
-#define OPEN_MAX 256
-
-/***************************************************************************
- This structure stores the infomation needed for a single DOS drive
- ***************************************************************************/
-struct DosDriveStruct
-{
-  char RootDirectory [256];    /* Unix base for this drive letter */
-  char CurrentDirectory [256]; /* Current directory for this drive */
-  char VolumeLabel [11];
-  unsigned long	serialnumber;
-};
-
-#endif /*_FILES_H*/
diff --git a/include/gdi.h b/include/gdi.h
index bb5b632..aade98d 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -7,7 +7,7 @@
 #ifndef GDI_H
 #define GDI_H
 
-#include <X11/Intrinsic.h>
+#include <X11/Xlib.h>
 
 #include "windows.h"
 #include "segmem.h"
@@ -158,6 +158,8 @@
     WORD          MapMode;
     short         DCOrgX;            /* DC origin */
     short         DCOrgY;
+    short         DCSizeX;           /* DC dimensions */
+    short         DCSizeY;
     short         CursPosX;          /* Current position */
     short         CursPosY;
     short         WndOrgX;
@@ -200,7 +202,6 @@
 {
     GC            gc;          /* X Window GC */
     Drawable      drawable;
-    Widget        widget;
     X_PHYSFONT    font;
     X_PHYSPEN     pen;
     X_PHYSBRUSH   brush;
diff --git a/include/int21.h b/include/int21.h
index 92cabc5..f44c9a4 100644
--- a/include/int21.h
+++ b/include/int21.h
@@ -1,15 +1,40 @@
 #ifndef INT21_H
 #define INT21_H
+#include <dirent.h>
+
+struct dosdirent {
+	int  inuse;
+	DIR *ds;
+	char unixpath[256];
+	char filename[256];
+	char attribute;
+	long filesize;
+	long filetime;
+	long filedate;
+};
+
+struct diskinfo {
+	unsigned int infolevel;
+	unsigned long serialnumber;
+	char	label[11];
+	char	fstype[8];
+};
 
 #define DosVersion 	  0x0303;
 
 #define SectorSize 	  0x200;
 #define SectorsPerCluster 0x04;
 
-#define AX context->sc_eax
-#define BX context->sc_ebx
-#define CX context->sc_ecx
-#define DX context->sc_edx
+#define EAX context->sc_eax
+#define EBX context->sc_ebx
+#define ECX context->sc_ecx
+#define EDX context->sc_edx
+
+#define AX (context->sc_eax & 0x0000ffffL)
+#define BX (context->sc_ebx & 0x0000ffffL)
+#define CX (context->sc_ecx & 0x0000ffffL)
+#define DX (context->sc_edx & 0x0000ffffL)
+
 #define ES context->sc_es
 #define DS context->sc_ds
 #define DI context->sc_edi
@@ -22,13 +47,6 @@
 #define SetCflag	(context->sc_efl |= 0x00000001L)
 #define ResetCflag	(context->sc_efl &= 0xfffffffeL)
 
-struct diskinfo {
-	WORD	infolevel;
-	DWORD	serialnumber;
-	char	label[11];
-	char	fstype[8];
-};
-
 /* extended error codes */
 
 #define NoError		0x00
diff --git a/include/listbox.h b/include/listbox.h
index f44cf8c..5d89f9e 100644
--- a/include/listbox.h
+++ b/include/listbox.h
@@ -14,16 +14,17 @@
 
 typedef struct tagHEADLIST {
     short	FirstVisible;
-    short	ItemSelect;
     short	ItemsCount;
     short	ItemsVisible;
-    short	ItemSelected;
-    short	PrevSelected;
+    short	ColumnsVisible;
+    short	ItemsPerColumn;
+    short	ItemFocused;
+    short	PrevFocused;
     short 	StdItemHeight;
+    short	ColumnsWidth;
     short	DrawCtlType;
     void	*lpFirst; 
     DWORD	dwStyle;
-    HWND	hWndScroll;
     HWND	hWndLogicParent;
 } HEADLIST;
 typedef HEADLIST FAR* LPHEADLIST;
diff --git a/include/menu.h b/include/menu.h
index 15d251a..edc0bec 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -27,7 +27,10 @@
     Widget	w;
     Widget	menu_w;
     char	menu_name[10];
-} MENUITEM;
+    RECT	rect;
+    HBITMAP	hCheckBit;
+    HBITMAP	hUnCheckBit;
+} MENUITEM, *LPMENUITEM;
 
 typedef struct tagMENUBAR
 {
@@ -40,6 +43,16 @@
     MENUITEM   *firstItem;
 } MENUBAR, *LPMENUBAR;
 
+typedef struct tagPOPUPMENU
+{
+    HWND	hWnd;			/* PopupMenu window handle	  */
+    HWND	ownerWnd;		/* Owner window			  */
+    WORD	nItems;    		/* Number of items on menu	  */
+    MENUITEM   *firstItem;
+    WORD	FocusedItem;
+    WORD	MouseFlags;
+} POPUPMENU, *LPPOPUPMENU;
+
 typedef struct
 {
     WORD	version;		/* Should be zero		  */
diff --git a/include/message.h b/include/message.h
index 0bbfc9a..d64b4fc 100644
--- a/include/message.h
+++ b/include/message.h
@@ -12,8 +12,8 @@
   /* Message as stored in the queue (contains the extraInfo field) */
 typedef struct tagQMSG
 {
+    DWORD   extraInfo;  /* Only in 3.1 */
     MSG     msg;
-    DWORD   extraInfo __attribute__ ((packed));  /* Only in 3.1 */
 } QMSG;
 
 
@@ -28,17 +28,28 @@
   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    */
+  DWORD     GetMessageExtraInfoVal; /* Value returned by GetMessageExtraInfo */
+  DWORD     lParam;                 /* Next four values set by SendMessage   */
   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      wPaintCount;            /* Number of WM_PAINT needed             */
+  WORD      wTimerCount;            /* Number of timers for this application */
   WORD      tempStatus;             /* State reset by GetQueueStatus         */
   WORD      status;                 /* Queue state                           */
   QMSG      messages[1];            /* Queue messages                        */
 } MESSAGEQUEUE;
 
+
+extern void MSG_IncPaintCount( HANDLE hQueue );
+extern void MSG_DecPaintCount( HANDLE hQueue );
+extern void MSG_IncTimerCount( HANDLE hQueue );
+extern void MSG_DecTimerCount( HANDLE hQueue );
+extern BOOL MSG_CreateSysMsgQueue( int size );
+extern void hardware_event(HWND hwnd, WORD message, WORD wParam, LONG lParam,
+			   WORD xPos, WORD yPos, DWORD time, DWORD extraInfo);
+
 #endif  /* MESSAGE_H */
diff --git a/include/neexe.h b/include/neexe.h
index e610ba4..58e67cc 100644
--- a/include/neexe.h
+++ b/include/neexe.h
@@ -136,7 +136,9 @@
 /* Used by Windows 3.0 programs, like when getting selector to be
    given to makeprocinst */
 #define NE_RELTYPE_INT1		4
-#define NE_RELTYPE_OFFSET16	5
+#define NE_RELTYPE_ORDINALADD	5
+#define NE_RELTYPE_NAMEADD	6
+
 /*
  * DOS PSP
  */
diff --git a/include/prototypes.h b/include/prototypes.h
index c1c7bf9..69fc97b 100644
--- a/include/prototypes.h
+++ b/include/prototypes.h
@@ -10,6 +10,7 @@
 #include "neexe.h"
 #include "segmem.h"
 #include "wine.h"
+#include "int21.h"
 
 extern struct segment_descriptor_s *
     CreateSelectors(struct w_files *);
@@ -33,5 +34,15 @@
 extern do_int1A(struct sigcontext_struct * context);
 extern do_int21(struct sigcontext_struct * context);
 
-#endif /* PROTOTYPES_H */
+extern void GetUnixDirName(char *rootdir, char *name);
+extern char *GetDirectUnixFileName(char *dosfilename);
+extern char *GetUnixFileName(char *dosfilename);
 
+extern char *FindFile(char *buffer, int buflen, char *rootname, char **extensions, char *path);
+extern char *WineIniFileName(void);
+extern char *WinIniFileName(void);
+extern struct dosdirent *DOS_opendir(char *dosdirname);
+extern struct dosdirent *DOS_readdir(struct dosdirent *de);
+extern void DOS_closedir(struct dosdirent *de);
+
+#endif /* PROTOTYPES_H */
diff --git a/include/segmem.h b/include/segmem.h
index ea9f851..437dfd9 100644
--- a/include/segmem.h
+++ b/include/segmem.h
@@ -6,6 +6,12 @@
 #ifndef SEGMEM_H
 #define SEGMEM_H
 
+#ifdef __linux__
+#define HAVE_IPC
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#endif
+
 /*
  * Array to track selector allocation.
  */
@@ -15,21 +21,32 @@
 
 extern unsigned short SelectorMap[MAX_SELECTORS];
 
+#ifdef HAVE_IPC
+#define SAFEMAKEPTR(s, o) (((int) (s) << 16) | ((o) & 0xffff))
+#define FIXPTR(p)	  (p)
+#else
 #define SAFEMAKEPTR(s, o) \
     (((int) SelectorMap[SelectorMap[(s) >> 3] & SELECTOR_INDEXMASK] << 19) \
      | 0x70000 | ((o) & 0xffff))
+#define FIXPTR(p)	  SAFEMAKEPTR((unsigned long) (p) >> 16, (p))
+#endif
 
 /*
  * Structure to hold info about each selector we create.
  */
 
-struct segment_descriptor_s
+typedef struct segment_descriptor_s
 {
     void          *base_addr;	/* Pointer to segment in flat memory	*/
     unsigned int   length;	/* Length of segment			*/
     unsigned int   flags;	/* Segment flags (see neexe.h and below)*/
     unsigned short selector;	/* Selector used to access this segment */
-};
+    unsigned short owner;	/* Handle of owner program		*/
+    unsigned char  type;	/* DATA or CODE				*/
+#ifdef HAVE_IPC
+    key_t	   shm_key;	/* Shared memory key or IPC_PRIVATE     */
+#endif
+} SEGDESC;
 
 /*
  * Additional flags
diff --git a/include/user.h b/include/user.h
index 3db21d2..3b9867d 100644
--- a/include/user.h
+++ b/include/user.h
@@ -15,6 +15,8 @@
 extern MDESC *USER_Heap;
 
 #define USER_HEAP_ALLOC(f,size) ((int)HEAP_Alloc(&USER_Heap,f,size) & 0xffff)
+#define USER_HEAP_REALLOC(handle,size,f) ((int)HEAP_ReAlloc(&USER_Heap, \
+				       USER_HEAP_ADDR(handle),size,f) & 0xffff)
 #define USER_HEAP_ADDR(handle) ((void *)(handle|((int)USER_Heap & 0xffff0000)))
 #define USER_HEAP_FREE(handle) (HEAP_Free(&USER_Heap,USER_HEAP_ADDR(handle)))
 
diff --git a/include/win.h b/include/win.h
index 894da98..b90675d 100644
--- a/include/win.h
+++ b/include/win.h
@@ -8,8 +8,6 @@
 #define WIN_H
 
 #include <X11/Intrinsic.h>
-#include <X11/StringDefs.h>
-#include <X11/Core.h>
 
 #include "windows.h"
 #include "menu.h"
@@ -26,31 +24,41 @@
     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 */
+    RECT         rectClient;     /* Client area rel. to parent client area */
+    RECT         rectWindow;     /* Whole window rel. to parent client area */
+    HANDLE       hmemTaskQ;      /* Task queue global memory handle */
     HRGN         hrgnUpdate;     /* Update region */
     HWND         hwndLastActive; /* Last active popup hwnd */
     FARPROC      lpfnWndProc;    /* Window procedure */
     DWORD        dwStyle;        /* Window style (from CreateWindow) */
     DWORD        dwExStyle;      /* Extended style (from CreateWindowEx) */
-    HDC          hdc;            /* Window DC (if CS_OWNDC) */
+    HANDLE       hdce;           /* Window DCE (if CS_OWNDC or CS_CLASSDC) */
     HMENU        hmenuSystem;    /* System menu */
+    HCURSOR      hCursor;    	 /* Window Current Cursor */
+    HWND         hWndVScroll;    /* Verti. ScrollBar handle of the window */
+    HWND         hWndHScroll;    /* Horiz. ScrollBar handle of the window */
     WORD         wIDmenu;        /* ID or hmenu (from CreateWindow) */
     HANDLE       hText;          /* Handle of window text */
     WORD         flags;          /* Misc. flags */
     Widget       shellWidget;    /* For top-level windows */
     Widget       winWidget;      /* For all windows */
     Widget       compositeWidget;/* For top-level windows */
+    Window       window;         /* X window */
     LPMENUBAR	 menuBarPtr;	 /* Menu bar */
     WORD         wExtra[1];      /* Window extra bytes */
 } WND;
 
   /* WND flags values */
-#define WIN_ERASE_UPDATERGN       1   /* Update region needs erasing */
-
+#define WIN_ERASE_UPDATERGN     0x01  /* Update region needs erasing */
+#define WIN_NEEDS_BEGINPAINT    0x02  /* WM_PAINT sent to window */
+#define WIN_GOT_SIZEMSG         0x04  /* WM_SIZE has been sent to the window */
+#define WIN_OWN_DC              0x08  /* Win class has style CS_OWNDC */
+#define WIN_CLASS_DC            0x10  /* Win class has style CS_CLASSDC */
 
   /* Window functions */
-WND * WIN_FindWndPtr( HWND hwnd );
+WND *WIN_FindWndPtr( HWND hwnd );
+BOOL WIN_UnlinkWindow( HWND hwnd );
+BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter );
 HWND WIN_FindWinToRepaint( HWND hwnd );
 
 
diff --git a/include/windows.h b/include/windows.h
index 9d3eaf3..ae37d54 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -64,7 +64,8 @@
 #define LOWORD(l)           ((WORD)(l))
 #define HIWORD(l)           ((WORD)((DWORD)(l) >> 16))
 
-#define MAKELONG(low, high) ((LONG)(((WORD)(low)) | (((DWORD)((WORD)(high))) << 16)))
+#define MAKELONG(low, high) ((LONG)(((WORD)(low)) | \
+				    (((DWORD)((WORD)(high))) << 16)))
 
 #ifndef max
 #define max(a,b) (((a) > (b)) ? (a) : (b))
@@ -208,6 +209,36 @@
 #define GW_OWNER	4
 #define GW_CHILD	5
 
+  /* WM_WINDOWPOSCHANGING/CHANGED struct */
+typedef struct
+{
+    HWND    hwnd;
+    HWND    hwndInsertAfter;
+    int     x;
+    int     y;
+    int     cx;
+    int     cy;
+    UINT    flags;
+} WINDOWPOS;
+
+  /* WM_NCCALCSIZE parameter structure */
+typedef struct
+{
+    RECT	   rgrc[3];
+    WINDOWPOS FAR* lppos;
+} NCCALCSIZE_PARAMS;
+
+  /* WM_NCCALCSIZE return flags */
+#define WVR_ALIGNTOP        0x0010
+#define WVR_ALIGNLEFT       0x0020
+#define WVR_ALIGNBOTTOM     0x0040
+#define WVR_ALIGNRIGHT      0x0080
+#define WVR_HREDRAW         0x0100
+#define WVR_VREDRAW         0x0200
+#define WVR_REDRAW          (WVR_HREDRAW | WVR_VREDRAW)
+#define WVR_VALIDRECTS      0x0400
+
+
   /* Dialogs */
 
   /* cbWndExtra bytes for dialog class */
@@ -275,6 +306,9 @@
 	
 typedef WORD ATOM;
 
+#define MAKEINTATOM(i)     ((LPCSTR)MAKELP(0, (i)))
+
+
   /* Raster operations */
 
 #define R2_BLACK         1
@@ -558,6 +592,19 @@
 #define RGN_DIFF          4
 #define RGN_COPY          5
 
+  /* Device contexts */
+
+/* GetDCEx flags */
+#define DCX_WINDOW           0x00000001
+#define DCX_CACHE            0x00000002
+#define DCX_CLIPCHILDREN     0x00000008
+#define DCX_CLIPSIBLINGS     0x00000010
+#define DCX_PARENTCLIP       0x00000020
+#define DCX_EXCLUDERGN       0x00000040
+#define DCX_INTERSECTRGN     0x00000080
+#define DCX_LOCKWINDOWUPDATE 0x00000400
+#define DCX_USESTYLE         0x00010000
+
   /* Polygon modes */
 #define ALTERNATE         1
 #define WINDING           2
@@ -797,18 +844,6 @@
 #define DIB_PAL_COLORS   1
 #define CBM_INIT         4
 
-
-/* Unimplemented structs */
-typedef struct {
-	BYTE Id;  /* much more .... */
-} DCB;
-
-typedef struct {
-	BYTE i;  /* much more .... */
-} COMSTAT;
-
-
-
 typedef struct {
 	BYTE i;  /* much more .... */
 } KANJISTRUCT;
@@ -842,6 +877,160 @@
 #define OF_SHARE_EXCLUSIVE 0x0010
 #define OF_VERIFY 0x0400
 
+#define DRIVE_REMOVABLE	2
+#define DRIVE_FIXED	3
+#define DRIVE_REMOTE	4
+
+#define HFILE_ERROR	-1
+
+#define DDL_READWRITE	0x0000
+#define DDL_READONLY	0x0001
+#define DDL_HIDDEN	0x0002
+#define DDL_SYSTEM	0x0004
+#define DDL_DIRECTORY	0x0010
+#define DDL_ARCHIVE	0x0020
+
+#define DDL_POSTMSGS	0x2000
+#define DDL_DRIVES	0x4000
+#define DDL_EXCLUSIVE	0x8000
+
+/* comm */
+
+#define CBR_110	0xFF10
+#define CBR_300	0xFF11
+#define CBR_600	0xFF12
+#define CBR_1200	0xFF13
+#define CBR_2400	0xFF14
+#define CBR_4800	0xFF15
+#define CBR_9600	0xFF16
+#define CBR_14400	0xFF17
+#define CBR_19200	0xFF18
+#define CBR_38400	0xFF1B
+#define CBR_56000	0xFF1F
+#define CBR_128000	0xFF23
+#define CBR_256000	0xFF27
+
+#define NOPARITY	0
+#define ODDPARITY	1
+#define EVENPARITY	2
+#define MARKPARITY	3
+#define SPACEPARITY	4
+#define ONESTOPBIT	0
+#define ONE5STOPBITS	1
+#define TWOSTOPBITS	2
+#define IGNORE		0
+#define INFINITE	0xFFFF
+
+#define CE_RXOVER	0x0001
+#define CE_OVERRUN	0x0002
+#define CE_RXPARITY	0x0004
+#define CE_FRAME	0x0008
+#define CE_BREAK	0x0010
+#define CE_CTSTO	0x0020
+#define CE_DSRTO	0x0040
+#define CE_RLSDTO	0x0080
+#define CE_TXFULL	0x0100
+#define CE_PTO		0x0200
+#define CE_IOE		0x0400
+#define CE_DNS		0x0800
+#define CE_OOP		0x1000
+#define CE_MODE	0x8000
+
+#define IE_BADID	-1
+#define IE_OPEN	-2
+#define IE_NOPEN	-3
+#define IE_MEMORY	-4
+#define IE_DEFAULT	-5
+#define IE_HARDWARE	-10
+#define IE_BYTESIZE	-11
+#define IE_BAUDRATE	-12
+
+#define EV_RXCHAR	0x0001
+#define EV_RXFLAG	0x0002
+#define EV_TXEMPTY	0x0004
+#define EV_CTS		0x0008
+#define EV_DSR		0x0010
+#define EV_RLSD	0x0020
+#define EV_BREAK	0x0040
+#define EV_ERR		0x0080
+#define EV_RING	0x0100
+#define EV_PERR	0x0200
+#define EV_CTSS	0x0400
+#define EV_DSRS	0x0800
+#define EV_RLSDS	0x1000
+#define EV_RINGTE	0x2000
+#define EV_RingTe	EV_RINGTE
+
+#define SETXOFF	1
+#define SETXON		2
+#define SETRTS		3
+#define CLRRTS		4
+#define SETDTR		5
+#define CLRDTR		6
+#define RESETDEV	7
+#define GETMAXLPT	8
+#define GETMAXCOM	9
+#define GETBASEIRQ	10
+
+#define CN_RECEIVE	0x0001
+#define CN_TRANSMIT	0x0002
+#define CN_EVENT	0x0004
+
+typedef struct tagDCB
+{
+    BYTE Id;
+    UINT BaudRate;
+    BYTE ByteSize;
+    BYTE Parity;
+    BYTE StopBits;
+    UINT RlsTimeout;
+    UINT CtsTimeout;
+    UINT DsrTimeout;
+
+    UINT fBinary        :1;
+    UINT fRtsDisable    :1;
+    UINT fParity        :1;
+    UINT fOutxCtsFlow   :1;
+    UINT fOutxDsrFlow   :1;
+    UINT fDummy         :2;
+    UINT fDtrDisable    :1;
+
+    UINT fOutX          :1;
+    UINT fInX           :1;
+    UINT fPeChar        :1;
+    UINT fNull          :1;
+    UINT fChEvt         :1;
+    UINT fDtrflow       :1;
+    UINT fRtsflow       :1;
+    UINT fDummy2        :1;
+
+    char XonChar;
+    char XoffChar;
+    UINT XonLim;
+    UINT XoffLim;
+    char PeChar;
+    char EofChar;
+    char EvtChar;
+    UINT TxDelay;
+} DCB;
+typedef DCB FAR* LPDCB;
+
+typedef struct tagCOMSTAT
+{
+    BYTE status;
+    UINT cbInQue;
+    UINT cbOutQue;
+} COMSTAT;
+
+#define CSTF_CTSHOLD	0x01
+#define CSTF_DSRHOLD	0x02
+#define CSTF_RLSDHOLD	0x04
+#define CSTF_XOFFHOLD	0x08
+#define CSTF_XOFFSENT	0x10
+#define CSTF_EOF	0x20
+#define CSTF_TXIM	0x40
+
+/* */
 
 typedef struct 
 {
@@ -903,8 +1092,12 @@
 	WM_DELETEITEM, WM_VKEYTOITEM,
 	WM_CHARTOITEM, WM_SETFONT, WM_GETFONT };
 
+#define WM_WINDOWPOSCHANGING 0x0046
+#define WM_WINDOWPOSCHANGED 0x0047
+
 #define WM_NCCREATE         0x0081
 #define WM_NCDESTROY        0x0082
+#define WM_NCCALCSIZE	    0x0083
 
 #define WM_GETDLGCODE	    0x0087
 
@@ -1008,6 +1201,12 @@
 #define HWND_TOPMOST        ((HWND)-1)
 #define HWND_NOTOPMOST      ((HWND)-2)
 
+/* Flags for TrackPopupMenu */
+#define TPM_LEFTBUTTON  0x0000
+#define TPM_RIGHTBUTTON 0x0002
+#define TPM_LEFTALIGN   0x0000
+#define TPM_CENTERALIGN 0x0004
+#define TPM_RIGHTALIGN  0x0008
 
 #define MF_INSERT 0
 #define MF_CHANGE 0x0080
@@ -1016,7 +1215,7 @@
 #define MF_REMOVE 0x1000
 #define MF_BYCOMMAND 0
 #define MF_BYPOSITION 0x0400
-#define MF_SEPARATOR 0x080
+#define MF_SEPARATOR 0x0800
 #define MF_ENABLED 0
 #define MF_GRAYED 0x0001
 #define MF_DISABLED 0x0002
@@ -1492,6 +1691,80 @@
 typedef COMPAREITEMSTRUCT NEAR* PCOMPAREITEMSTRUCT;
 typedef COMPAREITEMSTRUCT FAR* LPCOMPAREITEMSTRUCT;
 
+/* Virtual key codes */
+#define VK_LBUTTON          0x01
+#define VK_RBUTTON          0x02
+#define VK_CANCEL           0x03
+#define VK_MBUTTON          0x04
+#define VK_BACK             0x08
+#define VK_TAB              0x09
+#define VK_CLEAR            0x0C
+#define VK_RETURN           0x0D
+#define VK_SHIFT            0x10
+#define VK_CONTROL          0x11
+#define VK_MENU             0x12
+#define VK_PAUSE            0x13
+#define VK_CAPITAL          0x14
+#define VK_ESCAPE           0x1B
+#define VK_SPACE            0x20
+#define VK_PRIOR            0x21
+#define VK_NEXT             0x22
+#define VK_END              0x23
+#define VK_HOME             0x24
+#define VK_LEFT             0x25
+#define VK_UP               0x26
+#define VK_RIGHT            0x27
+#define VK_DOWN             0x28
+#define VK_SELECT           0x29
+#define VK_PRINT            0x2A
+#define VK_EXECUTE          0x2B
+#define VK_SNAPSHOT         0x2C
+#define VK_INSERT           0x2D
+#define VK_DELETE           0x2E
+#define VK_HELP             0x2F
+#define VK_NUMPAD0          0x60
+#define VK_NUMPAD1          0x61
+#define VK_NUMPAD2          0x62
+#define VK_NUMPAD3          0x63
+#define VK_NUMPAD4          0x64
+#define VK_NUMPAD5          0x65
+#define VK_NUMPAD6          0x66
+#define VK_NUMPAD7          0x67
+#define VK_NUMPAD8          0x68
+#define VK_NUMPAD9          0x69
+#define VK_MULTIPLY         0x6A
+#define VK_ADD              0x6B
+#define VK_SEPARATOR        0x6C
+#define VK_SUBTRACT         0x6D
+#define VK_DECIMAL          0x6E
+#define VK_DIVIDE           0x6F
+#define VK_F1               0x70
+#define VK_F2               0x71
+#define VK_F3               0x72
+#define VK_F4               0x73
+#define VK_F5               0x74
+#define VK_F6               0x75
+#define VK_F7               0x76
+#define VK_F8               0x77
+#define VK_F9               0x78
+#define VK_F10              0x79
+#define VK_F11              0x7A
+#define VK_F12              0x7B
+#define VK_F13              0x7C
+#define VK_F14              0x7D
+#define VK_F15              0x7E
+#define VK_F16              0x7F
+#define VK_F17              0x80
+#define VK_F18              0x81
+#define VK_F19              0x82
+#define VK_F20              0x83
+#define VK_F21              0x84
+#define VK_F22              0x85
+#define VK_F23              0x86
+#define VK_F24              0x87
+#define VK_NUMLOCK          0x90
+#define VK_SCROLL           0x91
+
   
 #define LMEM_MOVEABLE   0x0002
 
@@ -1719,6 +1992,7 @@
 Fa(WORD,FreeSelector,WORD,a)
 Fa(WORD,GetDriveType,int,a)
 Fa(WORD,GetMenuItemCount,HMENU,a)
+Fa(WORD,GetTaskQueue,HANDLE,a)
 Fa(WORD,GetTextAlign,HDC,a)
 Fa(WORD,GlobalFlags,HANDLE,a)
 Fa(WORD,GlobalPageLock,HANDLE,a)
@@ -1726,9 +2000,9 @@
 Fa(WORD,LocalCompact,WORD,a)
 Fa(WORD,LocalFlags,HANDLE,a)
 Fa(WORD,LocalSize,HANDLE,a)
-Fa(WORD,RealizePalette,HDC,a)
-Fa(WORD,RegisterClipboardFormat,LPSTR,a)
-Fa(WORD,RegisterWindowMessage,LPSTR,a)
+Fa(int,RealizePalette,HDC,a)
+Fa(WORD,RegisterClipboardFormat,LPCSTR,a)
+Fa(WORD,RegisterWindowMessage,LPCSTR,a)
 Fa(WORD,SetHandleCount,WORD,a)
 Fa(WORD,VkKeyScan,WORD,a)
 Fa(char NEAR*,LocalLock,HANDLE,a)
@@ -1872,6 +2146,7 @@
 Fb(WORD,LocalShrink,HANDLE,a,WORD,b)
 Fb(WORD,MapVirtualKey,WORD,a,WORD,b)
 Fb(WORD,SetSystemPaletteUse,HDC,a,WORD,b)
+Fb(WORD,SetTaskQueue,HANDLE,a,HANDLE,b)
 Fb(WORD,SetTextAlign,HDC,a,WORD,b)
 Fb(WORD,SizeofResource,HANDLE,a,HANDLE,b)
 Fb(WORD,WinExec,LPSTR,a,WORD,b)
@@ -1881,7 +2156,7 @@
 Fb(int,ConvertRequest,HWND,a,LPKANJISTRUCT,b)
 Fb(void,CopyRect,LPRECT,a,LPRECT,b)
 Fb(int,EnumProps,HWND,a,FARPROC,b)
-Fb(int,EscapeCommFunction,int,a,int,b)
+Fb(LONG,EscapeCommFunction,int,a,int,b)
 Fb(int,ExcludeUpdateRgn,HDC,a,HWND,b)
 Fb(int,FlushComm,int,a,int,b)
 Fb(int,GetClipBox,HDC,a,LPRECT,b)
@@ -1910,8 +2185,8 @@
 Fb(void,ProfSampRate,int,a,int,b)
 Fb(void,ProfSetup,int,a,int,b)
 Fb(void,ScreenToClient,HWND,a,LPPOINT,b)
-Fb(void,SetCaretPos,int,a,int,b)
-Fb(void,SetCursorPos,int,a,int,b)
+Fb(void,SetCaretPos,short,a,short,b)
+Fb(void,SetCursorPos,short,a,short,b)
 Fb(void,SetWindowText,HWND,a,LPSTR,b)
 Fb(void,ShowOwnedPopups,HWND,a,BOOL,b)
 Fb(void,Throw,LPCATCHBUF,a,int,b)
@@ -1963,6 +2238,7 @@
 Fc(HANDLE,LocalReAlloc,HANDLE,a,WORD,b,WORD,c)
 Fc(HBITMAP,CreateCompatibleBitmap,HDC,a,short,b,short,c)
 Fc(HBITMAP,CreateDiscardableBitmap,HDC,a,short,b,short,c)
+Fc(HDC,GetDCEx,HWND,a,HRGN,b,DWORD,c)
 Fc(HPALETTE,SelectPalette,HDC,a,HPALETTE,b,BOOL,c)
 Fc(HPEN,CreatePen,short,a,short,b,COLORREF,c)
 Fc(HRGN,CreatePolygonRgn,LPPOINT,a,short,b,short,c)
@@ -1985,7 +2261,7 @@
 Fb(WORD,SetROP2,HDC,a,WORD,b)
 Fb(WORD,SetStretchBltMode,HDC,a,WORD,b)
 Fc(int,FrameRect,HDC,a,LPRECT,b,HBRUSH,c)
-Fc(int,GetClassName,HWND,a,LPSTR,b,int,c)
+Fc(int,GetClassName,HWND,a,LPSTR,b,short,c)
 Fc(int,GetClipboardFormatName,WORD,a,LPSTR,b,int,c)
 Fc(int,GetEnvironment,LPSTR,a,LPSTR,b,WORD,c)
 Fc(int,GetInstanceData,HANDLE,a,NPSTR,b,int,c)
@@ -2066,7 +2342,7 @@
 Fd(int,EnumFonts,HDC,a,LPSTR,b,FARPROC,c,LPSTR,d)
 Fd(int,EnumObjects,HDC,a,int,b,FARPROC,c,LPSTR,d)
 Fd(int,GetDlgItemText,HWND,a,WORD,b,LPSTR,c,WORD,d)
-Fd(int,GetTempFileName,BYTE,a,LPSTR,b,WORD,c,LPSTR,d)
+Fd(int,GetTempFileName,BYTE,a,LPCSTR,b,UINT,c,LPSTR,d)
 Fd(int,LoadString,HANDLE,a,WORD,b,LPSTR,c,int,d)
 Fd(int,MessageBox,HWND,a,LPSTR,b,LPSTR,c,WORD,d)
 Fd(int,SetScrollPos,HWND,a,int,b,int,c,BOOL,d)
@@ -2074,9 +2350,10 @@
 Fd(void,AdjustWindowRectEx,LPRECT,a,LONG,b,BOOL,c,DWORD,d)
 Fd(void,AnimatePalette,HPALETTE,a,WORD,b,WORD,c,LPPALETTEENTRY,d)
 Fd(void,CheckRadioButton,HWND,a,WORD,b,WORD,c,WORD,d)
-Fd(void,CreateCaret,HWND,a,HBITMAP,b,int,c,int,d)
+Fd(void,CreateCaret,HWND,a,HBITMAP,b,short,c,short,d)
 Fd(void,FillWindow,HWND,a,HWND,b,HDC,c,HBRUSH,d)
 Fd(void,GetScrollRange,HWND,a,int,b,LPINT,c,LPINT,d)
+Fd(void,MapWindowPoints,HWND,a,HWND,b,LPPOINT,c,WORD,d)
 Fd(void,PlayMetaFileRecord,HDC,a,LPHANDLETABLE,b,LPMETARECORD,c,WORD,d)
 Fd(void,SetDlgItemInt,HWND,a,WORD,b,WORD,c,BOOL,d)
 Fe(BOOL,Rectangle,HDC,a,int,xLeft,int,yTop,int,xRight,int,yBottom)
@@ -2122,17 +2399,17 @@
 Ff(HRGN,CreateRoundRectRgn,short,a,short,b,short,c,short,d,short,e,short,f)
 Ff(short,GetPrivateProfileString,LPSTR,a,LPSTR,b,LPSTR,c,LPSTR,d,short,e,LPSTR,f)
 Ff(void,LineDDA,short,a,short,b,short,c,short,d,FARPROC,e,long,f)
-Ff(void,MoveWindow,HWND,a,short,b,short,c,short,d,short,e,BOOL,f)
+Ff(BOOL,MoveWindow,HWND,a,short,b,short,c,short,d,short,e,BOOL,f)
 Ff(BOOL,ScaleViewportExtEx,HDC,a,short,b,short,c,short,d,short,e,LPSIZE,f)
 Ff(BOOL,ScaleWindowExtEx,HDC,a,short,b,short,c,short,d,short,e,LPSIZE,f)
 Fg(BOOL,RoundRect,HDC,a,short,b,short,c,short,d,short,e,short,f,short,g)
 Fg(BOOL,ScrollDC,HDC,a,short,b,short,c,LPRECT,d,LPRECT,e,HRGN,f,LPRECT,g)
-Fg(BOOL,TrackPopupMenu,HMENU,a,WORD,b,int,c,int,d,int,e,HWND,f,LPRECT,g)
-Fg(HCURSOR,CreateCursor,HANDLE,a,int,b,int,c,int,d,int,e,LPSTR,f,LPSTR,g)
+Fg(BOOL,TrackPopupMenu,HMENU,a,WORD,b,short,c,short,d,short,e,HWND,f,LPRECT,g)
+Fg(HCURSOR,CreateCursor,HANDLE,a,short,b,short,c,short,d,short,e,LPSTR,f,LPSTR,g)
 Fg(HICON,CreateIcon,HANDLE,a,int,b,int,c,BYTE,d,BYTE,e,LPSTR,f,LPSTR,g)
 Fg(int,GetDIBits,HDC,a,HANDLE,a2,WORD,b,WORD,c,LPSTR,d,LPBITMAPINFO,e,WORD,f)
 Fg(int,SetDIBits,HDC,a,HANDLE,a2,WORD,b,WORD,c,LPSTR,d,LPBITMAPINFO,e,WORD,f)
-Fg(void,SetWindowPos,HWND,a,HWND,b,short,c,short,d,short,e,short,f,WORD,g)
+Fg(BOOL,SetWindowPos,HWND,a,HWND,b,short,c,short,d,short,e,short,f,WORD,g)
 Fh(BOOL,ExtTextOut,HDC,a,int,b,int,c,WORD,d,LPRECT,e,LPSTR,f,WORD,g,LPINT,h)
 Fh(HANDLE,DeferWindowPos,HANDLE,hWinPosInfo,HWND,hWnd,HWND,hWndInsertAfter,int,x,int,y,int,cx,int,cy,WORD,wFlags)
 Fh(LONG,TabbedTextOut,HDC,a,int,b,int,c,LPSTR,d,int,e,int,f,LPINT,g,int,h)
diff --git a/include/wine.h b/include/wine.h
index 6a602e9..dbc034c 100644
--- a/include/wine.h
+++ b/include/wine.h
@@ -22,9 +22,14 @@
 
 extern char *GetFilenameFromInstance(unsigned short instance);
 extern struct w_files *GetFileInfo(unsigned short instance);
-extern char *FindFileInPath(char *buffer, int buflen, char *rootname, 
-			    char **extensions, char *path);
-extern char *GetSystemIniFilename(void);
+extern char *WineIniFileName(void);
+extern char *WinIniFileName(void);
+
+#define MAX_DOS_DRIVES	26
+
+#define WINE_INI WineIniFileName()
+#define WIN_INI WinIniFileName()
+
 #ifdef linux
 struct sigcontext_struct {
 	unsigned short sc_gs, __gsh;
diff --git a/loader/Imakefile b/loader/Imakefile
new file mode 100644
index 0000000..9c5130a
--- /dev/null
+++ b/loader/Imakefile
@@ -0,0 +1,35 @@
+#include "../Wine.tmpl"
+
+MODULE = loader
+
+SRCS = \
+	dump.c \
+	files.c \
+	ldt.c \
+	ldtlib.c \
+	resource.c \
+	selector.c \
+	signal.c \
+	library.c \
+	wine.c \
+	cursor.c
+
+OBJS = \
+	dump.o \
+	files.o \
+	ldt.o \
+	ldtlib.o \
+	resource.o \
+	selector.o \
+	signal.o \
+	library.o \
+	wine.o \
+	cursor.o
+
+WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
+DependTarget()
+CleanTarget()
+
+includes::
+
+install::
diff --git a/loader/Makefile b/loader/Makefile
index 873a6ac..083d8f6 100644
--- a/loader/Makefile
+++ b/loader/Makefile
@@ -1,7 +1,7 @@
 CFLAGS=$(COPTS) $(DEBUGOPTS) -I../include
 
-OBJS=dump.o files.o ldt.o ldtlib.o resource.o selector.o signal.o int1a.o \
-     int21.o wine.o library.o
+OBJS=dump.o ldt.o ldtlib.o resource.o selector.o signal.o library.o \
+     wine.o cursor.o
 
 default: loader.o
 
diff --git a/loader/cursor.c b/loader/cursor.c
new file mode 100644
index 0000000..039c1c3
--- /dev/null
+++ b/loader/cursor.c
@@ -0,0 +1,385 @@
+/*
+ *    WINE
+*/
+static char Copyright[] = "Copyright  Martin Ayotte, 1993";
+
+/*
+#define DEBUG_CURSOR
+*/
+
+#include <X11/Intrinsic.h>
+#include <X11/cursorfont.h>
+#include <X11/Xlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "prototypes.h"
+#include "windows.h"
+#include "win.h"
+#include "gdi.h"
+#include "wine.h"
+#include "cursor.h"
+
+static int ShowCursCount = 0;
+static HCURSOR hActiveCursor;
+static HCURSOR hEmptyCursor = 0;
+RECT	ClipCursorRect;
+extern HINSTANCE hSysRes;
+extern Window winHasCursor;
+
+/**********************************************************************
+ *			LoadCursor [USER.173]
+ */
+HCURSOR LoadCursor(HANDLE instance, LPSTR cursor_name)
+{
+    XColor	bkcolor;
+    XColor	fgcolor;
+    HCURSOR 	hCursor;
+    HANDLE 	rsc_mem;
+    WORD 	*lp;
+    CURSORDESCRIP *lpcurdesc;
+    CURSORALLOC	  *lpcur;
+    BITMAP 	BitMap;
+    HBITMAP 	hBitMap;
+    HDC 	hMemDC;
+    HDC 	hdc;
+    int i, j, image_size;
+#ifdef DEBUG_RESOURCE
+    printf("LoadCursor: instance = %04x, name = %08x\n",
+	   instance, cursor_name);
+#endif    
+    hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L); 
+    if (hCursor == (HCURSOR)NULL) return 0;
+#ifdef DEBUG_CURSOR
+    printf("LoadCursor Alloc hCursor=%X\n", hCursor);
+#endif    
+    lpcur = (CURSORALLOC *)GlobalLock(hCursor);
+    memset(lpcur, 0, sizeof(CURSORALLOC));
+    if (instance == (HANDLE)NULL) {
+	instance = hSysRes;
+	switch((LONG)cursor_name) {
+	    case IDC_ARROW:
+		lpcur->xcursor = XCreateFontCursor(XT_display, XC_top_left_arrow);
+		GlobalUnlock(hCursor);
+	    	return hCursor;
+	    case IDC_CROSS:
+		lpcur->xcursor = XCreateFontCursor(XT_display, XC_crosshair);
+		GlobalUnlock(hCursor);
+	    	return hCursor;
+	    case IDC_IBEAM:
+		lpcur->xcursor = XCreateFontCursor(XT_display, XC_xterm);
+		GlobalUnlock(hCursor);
+	    	return hCursor;
+	    case IDC_WAIT:
+		lpcur->xcursor = XCreateFontCursor(XT_display, XC_watch);
+		GlobalUnlock(hCursor);
+	    	return hCursor;
+	    default:
+		break;
+	    }
+	}
+    if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
+    rsc_mem = RSC_LoadResource(instance, cursor_name, NE_RSCTYPE_GROUP_CURSOR, 
+			       &image_size);
+    if (rsc_mem == (HANDLE)NULL) {
+	printf("LoadCursor / Cursor %08X not Found !\n", cursor_name);
+	ReleaseDC(GetDesktopWindow(), hdc); 
+	return 0;
+	}
+    lp = (WORD *)GlobalLock(rsc_mem);
+    if (lp == NULL) {
+	GlobalFree(rsc_mem);
+	ReleaseDC(GetDesktopWindow(), hdc); 
+	return 0;
+	}
+    lpcurdesc = (CURSORDESCRIP *)(lp + 3);
+#ifdef DEBUG_CURSOR
+    printf("LoadCursor / image_size=%d\n", image_size);
+    printf("LoadCursor / curReserved=%X\n", *lp);
+    printf("LoadCursor / curResourceType=%X\n", *(lp + 1));
+    printf("LoadCursor / curResourceCount=%X\n", *(lp + 2));
+    printf("LoadCursor / cursor Width=%d\n", (int)lpcurdesc->Width);
+    printf("LoadCursor / cursor Height=%d\n", (int)lpcurdesc->Height);
+    printf("LoadCursor / cursor curXHotspot=%d\n", (int)lpcurdesc->curXHotspot);
+    printf("LoadCursor / cursor curYHotspot=%d\n", (int)lpcurdesc->curYHotspot);
+    printf("LoadCursor / cursor curDIBSize=%lX\n", (DWORD)lpcurdesc->curDIBSize);
+    printf("LoadCursor / cursor curDIBOffset=%lX\n", (DWORD)lpcurdesc->curDIBOffset);
+#endif
+    lpcur->descriptor = *lpcurdesc;
+    GlobalUnlock(rsc_mem);
+    GlobalFree(rsc_mem);
+    rsc_mem = RSC_LoadResource(instance, 
+    	MAKEINTRESOURCE(lpcurdesc->curDIBOffset), 
+    	NE_RSCTYPE_CURSOR, &image_size);
+    if (rsc_mem == (HANDLE)NULL) {
+	printf("LoadCursor / Cursor %08X Bitmap not Found !\n", cursor_name);
+	ReleaseDC(GetDesktopWindow(), hdc); 
+	return 0;
+	}
+    lp = (WORD *)GlobalLock(rsc_mem);
+    if (lp == NULL) {
+	GlobalFree(rsc_mem);
+	ReleaseDC(GetDesktopWindow(), hdc); 
+	return 0;
+ 	}
+    lp += 2;
+    for (j = 0; j < 16; j++)
+    	printf("%04X ", *(lp + j));
+/*
+    if (*lp == sizeof(BITMAPINFOHEADER))
+	lpcur->hBitmap = ConvertInfoBitmap(hdc, (BITMAPINFO *)lp);
+    else
+*/
+        lpcur->hBitmap = 0;
+    lp += sizeof(BITMAP);
+    for (i = 0; i < 81; i++) {
+	char temp = *((char *)lp + 162 + i);
+	*((char *)lp + 162 + i) = *((char *)lp + 324 - i);
+	*((char *)lp + 324 - i) = temp;
+	}
+    lpcur->pixshape = XCreatePixmapFromBitmapData(
+    	XT_display, DefaultRootWindow(XT_display), 
+        ((char *)lp + 211), 32, 32,
+/*
+        lpcurdesc->Width / 2, lpcurdesc->Height / 4, 
+*/
+        WhitePixel(XT_display, DefaultScreen(XT_display)), 
+        BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
+    lpcur->pixmask = XCreatePixmapFromBitmapData(
+    	XT_display, DefaultRootWindow(XT_display), 
+        ((char *)lp + 211), 32, 32,
+        WhitePixel(XT_display, DefaultScreen(XT_display)), 
+        BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
+    memset(&bkcolor, 0, sizeof(XColor));
+    memset(&fgcolor, 0, sizeof(XColor));
+    bkcolor.pixel = WhitePixel(XT_display, DefaultScreen(XT_display)); 
+    fgcolor.pixel = BlackPixel(XT_display, DefaultScreen(XT_display));
+printf("LoadCursor / before XCreatePixmapCursor !\n");
+    lpcur->xcursor = XCreatePixmapCursor(XT_display,
+ 	lpcur->pixshape, lpcur->pixmask, 
+ 	&fgcolor, &bkcolor, lpcur->descriptor.curXHotspot, 
+ 	lpcur->descriptor.curYHotspot);
+    GlobalUnlock(rsc_mem);
+    GlobalFree(rsc_mem);
+/*
+    hCursor = CreateCursor(instance, lpcur->descriptor.curXHotspot, 
+ 	lpcur->descriptor.curYHotspot, 32, 32,
+	(LPSTR)lp + 211, , (LPSTR)lp + 211);
+*/
+    XFreePixmap(XT_display, lpcur->pixshape);
+    XFreePixmap(XT_display, lpcur->pixmask);
+    ReleaseDC(GetDesktopWindow(), hdc); 
+    GlobalUnlock(hCursor);
+    return hCursor;
+}
+
+
+
+/**********************************************************************
+ *			CreateCursor [USER.406]
+ */
+HCURSOR CreateCursor(HANDLE instance, short nXhotspot, short nYhotspot, 
+	short nWidth, short nHeight, LPSTR lpANDbitPlane, LPSTR lpXORbitPlane)
+{
+    XColor	bkcolor;
+    XColor	fgcolor;
+    HCURSOR 	hCursor;
+    CURSORALLOC	  *lpcur;
+    BITMAP 	BitMap;
+    HBITMAP 	hBitMap;
+    HDC 	hMemDC;
+    HDC 	hdc;
+    int i, j;
+#ifdef DEBUG_RESOURCE
+    printf("CreateCursor: inst=%04x nXhotspot=%d  nYhotspot=%d nWidth=%d nHeight=%d\n",  
+	nXhotspot, nYhotspot, nWidth, nHeight);
+    printf("CreateCursor: inst=%04x lpANDbitPlane=%08X lpXORbitPlane=%08X\n",
+	LPSTR lpANDbitPlane, LPSTR lpXORbitPlane);
+#endif    
+    if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
+    hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L); 
+    if (hCursor == (HCURSOR)NULL) {
+	ReleaseDC(GetDesktopWindow(), hdc); 
+	return 0;
+	}
+    printf("CreateCursor Alloc hCursor=%X\n", hCursor);
+    lpcur = (CURSORALLOC *)GlobalLock(hCursor);
+    memset(lpcur, 0, sizeof(CURSORALLOC));
+    lpcur->descriptor.curXHotspot = nXhotspot;
+    lpcur->descriptor.curYHotspot = nYhotspot;
+    lpcur->pixshape = XCreatePixmapFromBitmapData(
+    	XT_display, DefaultRootWindow(XT_display), 
+        lpXORbitPlane, nWidth, nHeight,
+        WhitePixel(XT_display, DefaultScreen(XT_display)), 
+        BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
+    lpcur->pixmask = XCreatePixmapFromBitmapData(
+    	XT_display, DefaultRootWindow(XT_display), 
+        lpANDbitPlane, nWidth, nHeight,
+        WhitePixel(XT_display, DefaultScreen(XT_display)), 
+        BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
+    memset(&bkcolor, 0, sizeof(XColor));
+    memset(&fgcolor, 0, sizeof(XColor));
+    bkcolor.pixel = WhitePixel(XT_display, DefaultScreen(XT_display)); 
+    fgcolor.pixel = BlackPixel(XT_display, DefaultScreen(XT_display));
+    lpcur->xcursor = XCreatePixmapCursor(XT_display,
+ 	lpcur->pixshape, lpcur->pixmask, 
+ 	&fgcolor, &bkcolor, lpcur->descriptor.curXHotspot, 
+ 	lpcur->descriptor.curYHotspot);
+    XFreePixmap(XT_display, lpcur->pixshape);
+    XFreePixmap(XT_display, lpcur->pixmask);
+    ReleaseDC(GetDesktopWindow(), hdc); 
+    GlobalUnlock(hCursor);
+    return hCursor;
+}
+
+
+
+/**********************************************************************
+ *			DestroyCursor [USER.458]
+ */
+BOOL DestroyCursor(HCURSOR hCursor)
+{
+    CURSORALLOC	*lpcur;
+    if (hCursor == (HCURSOR)NULL) return FALSE;
+    lpcur = (CURSORALLOC *)GlobalLock(hCursor);
+    if (lpcur->hBitmap != (HBITMAP)NULL) DeleteObject(lpcur->hBitmap);
+    GlobalUnlock(hCursor);
+    GlobalFree(hCursor);
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *			SetCursor [USER.69]
+ */
+HCURSOR SetCursor(HCURSOR hCursor)
+{
+    HDC		hDC;
+    HDC		hMemDC;
+    BITMAP	bm;
+    CURSORALLOC	*lpcur;
+    HCURSOR	hOldCursor;
+    Window 	root, child;
+    int		rootX, rootY;
+    int		childX, childY;
+    unsigned int mousebut;
+#ifdef DEBUG_CURSOR
+    printf("SetCursor / hCursor=%04X !\n", hCursor);
+#endif
+    if (hCursor == (HCURSOR)NULL) return FALSE;
+    lpcur = (CURSORALLOC *)GlobalLock(hCursor);
+    hOldCursor = hActiveCursor;
+#ifdef DEBUG_CURSOR
+    printf("SetCursor / lpcur->xcursor=%08X !\n", &lpcur->xcursor);
+    XQueryPointer(XT_display, DefaultRootWindow(XT_display),
+	&root, &child, &rootX, &rootY, &childX, &childY, &mousebut);
+    printf("SetCursor / winHasCursor=%08X !\n", winHasCursor);
+    printf("SetCursor / child=%08X !\n", child);
+#endif
+    if (hActiveCursor != hCursor) ShowCursCount = 0;
+    if ((ShowCursCount >= 0) & (winHasCursor != 0)) {
+/*	XUndefineCursor(XT_display, winHasCursor); */
+	XDefineCursor(XT_display, winHasCursor, lpcur->xcursor);
+	}
+    GlobalUnlock(hCursor);
+    hActiveCursor = hCursor;
+    return hOldCursor;
+}
+
+
+/**********************************************************************
+ *                        SetCursorPos [USER.70]
+ */
+void SetCursorPos(short x, short y)
+{
+    Window 	root, child;
+    int		rootX, rootY;
+    int		childX, childY;
+    unsigned int mousebut;
+#ifdef DEBUG_CURSOR
+    printf("SetCursorPos // x=%d y=%d\n", x, y);
+#endif
+    XQueryPointer(XT_display, DefaultRootWindow(XT_display),
+	&root, &child, &rootX, &rootY, &childX, &childY, &mousebut);
+    XWarpPointer(XT_display, child, root, 0, 0, 
+    DisplayWidth(XT_display, DefaultScreen(XT_display)), 
+    DisplayHeight(XT_display, DefaultScreen(XT_display)), 
+    (int)x, (int)y);
+}
+
+
+/**********************************************************************
+ *                        GetCursorPos [USER.17]
+ */
+void GetCursorPos(LPPOINT lpRetPoint)
+{
+    Window 	root, child;
+    int		rootX, rootY;
+    int		childX, childY;
+    unsigned int mousebut;
+    if (lpRetPoint != NULL) {
+	XQueryPointer(XT_display, DefaultRootWindow(XT_display),
+	    &root, &child, &rootX, &rootY, &childX, &childY, &mousebut);
+#ifdef DEBUG_CURSOR
+	printf("GetCursorPos // x=%d y=%d\n", rootX, rootY);
+#endif
+	lpRetPoint->x = rootX;
+	lpRetPoint->y = rootY;
+    	}
+}
+
+
+/**********************************************************************
+ *			ShowCursor [USER.71]
+ */
+int ShowCursor(BOOL bShow)
+{
+    HCURSOR	hCursor;
+#ifdef DEBUG_CURSOR
+	printf("ShowCursor bShow=%d ShowCount=%d !\n", bShow, ShowCursCount);
+#endif
+    if (bShow)
+	ShowCursCount++;
+    else
+	ShowCursCount--;
+    if (ShowCursCount >= 0) {
+/*    	if (hCursor == (HCURSOR)NULL) */
+    	    hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
+	SetCursor(hCursor);
+	}
+    else {
+/*	XUndefineCursor(XT_display, winHasCursor); */
+	if (hEmptyCursor == (HCURSOR)NULL)
+	    hEmptyCursor = CreateCursor((HINSTANCE)NULL, 1, 1, 1, 1, 
+	    				"\xFF\xFF", "\xFF\xFF");
+	hCursor = SetCursor(hEmptyCursor);
+	hActiveCursor = hCursor;
+	}
+    return 0;
+}
+
+
+/**********************************************************************
+ *                        ClipCursor [USER.16]
+ */
+void ClipCursor(LPRECT lpNewClipRect)
+{
+    CopyRect(&ClipCursorRect, lpNewClipRect);
+}
+
+
+/**********************************************************************
+ *                        GetClipCursor [USER.309]
+ */
+void GetClipCursor(LPRECT lpRetClipRect)
+{
+    if (lpRetClipRect != NULL)
+	CopyRect(lpRetClipRect, &ClipCursorRect);
+}
+
+
+
+
diff --git a/loader/files.c b/loader/files.c
deleted file mode 100644
index a4371c6..0000000
--- a/loader/files.c
+++ /dev/null
@@ -1,109 +0,0 @@
-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 <stdlib.h>
-#include <dirent.h>
-#include <string.h>
-
-/**********************************************************************
- *					FindFileInPath
- */
-char *
-FindFileInPath(char *buffer, int buflen, char *rootname, 
-	       char **extensions, char *path)
-{
-    char *workingpath;
-    char *dirname;
-    DIR *d;
-    struct dirent *f;
-    char **e;
-    int rootnamelen;
-    int found = 0;
-
-    if (strchr(rootname, '/') != NULL)
-    {
-	strncpy(buffer, rootname, buflen);
-	return buffer;
-    }
-
-    rootnamelen = strlen(rootname);
-    workingpath = malloc(strlen(path) + 1);
-    if (workingpath == NULL)
-	return NULL;
-    strcpy(workingpath, path);
-    
-    for(dirname = strtok(workingpath, ":;"); 
-	dirname != NULL;
-	dirname = strtok(NULL, ":;"))
-    {
-	d = opendir(dirname);
-	if (d != NULL)
-	{
-	    while ((f = readdir(d)) != NULL)
-	    {
-		if (strncasecmp(rootname, f->d_name, rootnamelen) == 0)
-		{
-		    if (extensions == NULL || 
-			strcasecmp(rootname, f->d_name) == 0)
-		    {
-			found = 1;
-		    }
-		    else if (f->d_name[rootnamelen] == '.')
-		    {
-			for (e = extensions; *e != NULL; e++)
-			{
-			    if (strcasecmp(*e, f->d_name + rootnamelen + 1) 
-				== 0)
-			    {
-				found = 1;
-				break;
-			    }
-			}
-		    }
-		    
-		    if (found)
-		    {
-			strncpy(buffer, dirname, buflen);
-			strncat(buffer, "/", buflen - strlen(buffer));
-			strncat(buffer, f->d_name, buflen - strlen(buffer));
-			closedir(d);
-			return buffer;
-		    }
-		}
-	    }
-	    closedir(d);
-	}
-    }
-
-    return NULL;
-}
-
-/**********************************************************************
- *					GetSystemIniFilename
- */
-char *
-GetSystemIniFilename()
-{
-    static char *IniName = NULL;
-    char inipath[256];
-    
-    if (IniName)
-	return IniName;
-
-    getcwd(inipath, 256);
-    strcat(inipath, ":");
-    strcat(inipath, getenv("HOME"));
-    strcat(inipath, ":");
-    strcat(inipath, getenv("WINEPATH"));
-    
-    IniName = malloc(1024);
-    if (FindFileInPath(IniName, 1024, "wine.ini", NULL, inipath) == NULL)
-    {
-	free(IniName);
-	IniName = NULL;
-	return NULL;
-    }
-    
-    IniName = realloc(IniName, strlen(IniName) + 1);
-    return IniName;
-}
diff --git a/loader/int21.c b/loader/int21.c
deleted file mode 100644
index fdf506a..0000000
--- a/loader/int21.c
+++ /dev/null
@@ -1,1206 +0,0 @@
-#include <time.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#ifdef linux
-#include <sys/vfs.h>
-#endif
-#ifdef __NetBSD__
-#include <sys/mount.h>
-#endif
-#include <time.h>
-#include <unistd.h>
-#include <utime.h>
-
-#include "windows.h"
-#include "wine.h"
-#include "int21.h"
-#include "files.h"
-
-#define MAX_DRIVES 26
-
-static char Copyright[] = "int21.c, copyright Erik Bos, 1993";
-
-extern struct DosDriveStruct DosDrives[];
-extern int CurrentDrive;
-extern void ParseDOSFileName();
-
-int ValidDrive(int);
-
-WORD ExtendedError, CodePage = 437;
-BYTE ErrorClass, Action, ErrorLocus;
-
-void Error(int e, int class, int el)
-{
-	ExtendedError = e;
-	ErrorClass = class;
-	Action = SA_Ask4Retry;
-	ErrorLocus = el;
-}
-
-void GetFreeDiskSpace(struct sigcontext_struct *context)
-{
-	int drive;
-	struct statfs info;
-	long size,avail;
-
-	if (!(DX & 0xff))
-		drive = CurrentDrive;
-	else
-		drive = (DX & 0xff) - 1;
-	
-	if (!ValidDrive(drive)) {
-		Error(InvalidDrive, EC_MediaError , EL_Disk);
-		AX = 0xffff;	
-		return;
-	}
-	
-	{
-		if (statfs(DosDrives[drive].RootDirectory, &info) < 0) {
-			fprintf(stderr,"cannot do statfs(%s)\n",DosDrives[drive].RootDirectory);
-			Error(GeneralFailure, EC_MediaError , EL_Disk);
-			AX = 0xffff;
-			return;
-		}
-
-		size = info.f_bsize * info.f_blocks / 1024;
-		avail = info.f_bavail * info.f_bsize / 1024;
-	
-		#ifdef DOSDEBUG
-		fprintf(stderr,"statfs: size: %8d avail: %8d\n",size,avail);
-		#endif
-
-		AX = SectorsPerCluster;	
-		CX = SectorSize;
-		
-		BX = (avail / (CX * AX));
-		DX = (size / (CX * AX));
-		Error (0,0,0);
-	}
-}
-
-void SetDefaultDrive(struct sigcontext_struct *context)
-{
-	if ((DX & 0xff) < MAX_DRIVES) {
-		CurrentDrive = DX & 0xff;
-		AX &= 0xff00;
-		AX |= MAX_DRIVES; /* # of valid drive letters */
-		Error (0,0,0);
-	} else
-		Error (InvalidDrive, EC_MediaError, EL_Disk);
-}
-
-void GetDefaultDrive(struct sigcontext_struct *context)
-{
-	AX &= 0xff00;
-	AX |= CurrentDrive;
-	Error (0,0,0);
-}
-
-void GetDriveAllocInfo(struct sigcontext_struct *context)
-{
-	int drive;
-	long size;
-	BYTE mediaID;
-	struct statfs info;
-	
-	drive = DX & 0xff;
-	
-	if (!ValidDrive(drive)) {
-		AX = SectorsPerCluster;
-		CX = SectorSize;
-		DX = 0;
-		Error (InvalidDrive, EC_MediaError, EL_Disk);
-		return;
-	}
-
-	{
-		if (statfs(DosDrives[drive].RootDirectory, &info) < 0) {
-			fprintf(stderr,"cannot do statfs(%s)\n",DosDrives[drive].RootDirectory);
-			Error(GeneralFailure, EC_MediaError , EL_Disk);
-			AX = 0xffff;
-			return;
-		}
-
-		size = info.f_bsize * info.f_blocks / 1024;
-	
-		#ifdef DOSDEBUG
-		fprintf(stderr,"statfs: size: %8d\n",size);
-		#endif
-
-		AX = SectorsPerCluster;	
-		CX = SectorSize;
-		DX = (size / (CX * AX));
-
-		mediaID = 0xf0;
-
-		DS = segment(mediaID);
-		BX = offset(mediaID);	
-		Error (0,0,0);
-	}
-}
-
-void GetDefDriveAllocInfo(struct sigcontext_struct *context)
-{
-	DX = CurrentDrive;
-	GetDriveAllocInfo(context);
-}
-
-void GetDrivePB(struct sigcontext_struct *context)
-{
-	Error (InvalidDrive, EC_MediaError, EL_Disk);
-	AX = 0xff; /* I'm sorry but I only got networked drives :-) */
-}
-
-void ReadFile(struct sigcontext_struct *context)
-{
-	char *ptr;
-	int size;
-
-	/* can't read from stdout / stderr */
-
-	if (((BX & 0xffff) == 1) ||((BX & 0xffff) == 2)) {
-		Error (InvalidHandle, EL_Unknown, EC_Unknown);
-		AX = InvalidHandle;
-		SetCflag;
-		return;
-	}
-
-	ptr = (char *) pointer (DS,DX);
-
-	if ((BX & 0xffff) == 0) {
-		*ptr = EOF;
-		Error (0,0,0);
-		AX = 1;
-		ResetCflag;
-		return;
-	} else {
-		size = read(BX, ptr, CX);
-		if (size == 0) {
-			Error (ReadFault, EC_Unknown, EL_Unknown);
-			AX = ExtendedError;
-			return;
-		}
-
-		if (size == -1) {
-			switch (errno) {
-				case EAGAIN:
-					Error (ShareViolation, EC_Temporary, EL_Unknown);
-					break;
-				case EBADF:
-					Error (InvalidHandle, EC_AppError, EL_Unknown);
-					break;
-				default:
-					Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
-					break;
-			}
-			AX = ExtendedError;
-			SetCflag;
-			return;
-		}		
-		Error (0,0,0);
-		AX = size;
-		ResetCflag;
-	}
-}
-
-void WriteFile(struct sigcontext_struct *context)
-{
-	char *ptr;
-	int x,size;
-	
-	ptr = (char *) pointer (DS,DX);
-	
-	if ((BX & 0xffff) == 0) {
-		Error (InvalidHandle, EC_Unknown, EL_Unknown);
-		AX = InvalidHandle;
-		SetCflag;
-		return;
-	}
-
-	if ((BX & 0xffff) < 3) {
-		for (x = 0;x != CX;x++) {
-			fprintf(stderr, "%c", *ptr++);
-		}
-		fflush(stderr);
-
-		Error (0,0,0);
-		AX = CX;
-		ResetCflag;
-	} else {
-		size = write(BX, ptr , CX);
-		if (size == 0) {
-			Error (WriteFault, EC_Unknown, EL_Unknown);
-			AX = ExtendedError;
-			return;
-		}
-
-		if (size == -1) {
-			switch (errno) {
-				case EAGAIN:
-					Error (ShareViolation, EC_Temporary, EL_Unknown);
-					break;
-				case EBADF:
-					Error (InvalidHandle, EC_AppError, EL_Unknown);
-					break;
-				case ENOSPC:
-					Error (DiskFull, EC_MediaError, EL_Disk);
-					break;				
-				default:
-					Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
-					break;
-			}
-			AX = ExtendedError;
-			SetCflag;
-			return;
-		}		
-		Error (0,0,0);
-		AX = size;
-		ResetCflag;
-	}
-}
-
-void UnlinkFile(struct sigcontext_struct *context)
-{
-	char UnixFileName[256];
-	int drive, status;
-	
-	ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
-
-	{
-		status = unlink((char *) pointer(DS,DX));
-		if (status == -1) {
-			switch (errno) {
-				case EACCES:
-				case EPERM:
-				case EROFS:
-					Error (WriteProtected, EC_AccessDenied, EL_Unknown);
-					break;
-				case EBUSY:
-					Error (LockViolation, EC_AccessDenied, EL_Unknown);
-					break;		
-				case EAGAIN:
-					Error (ShareViolation, EC_Temporary, EL_Unknown);
-					break;
-				case ENOENT:
-					Error (FileNotFound, EC_NotFound, EL_Unknown);
-					break;				
-				default:
-					Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
-					break;
-			}
-			AX = ExtendedError;
-			SetCflag;
-			return;
-		}		
-		Error (0,0,0);
-		ResetCflag;
-	}
-}
-
-void SeekFile(struct sigcontext_struct *context)
-{
-	char UnixFileName[256];
-	int drive, handle, status, fileoffset;
-	
-	
-	ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
-	
-	{
-		switch (AX & 0xff) {
-			case 1: fileoffset = SEEK_CUR;
-				break;
-			case 2: fileoffset = SEEK_END;
-				break;
-			default:
-			case 0: fileoffset = SEEK_SET;
-				break;
-		}
-		status = lseek(BX, (CX * 0x100) + DX, fileoffset);
-		if (status == -1) {
-			switch (errno) {
-				case EBADF:
-					Error (InvalidHandle, EC_AppError, EL_Unknown);
-					break;
-				case EINVAL:
-					Error (DataInvalid, EC_AppError, EL_Unknown);
-					break;
-				default:
-					Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
-					break;
-			}
-			AX = ExtendedError;
-			SetCflag;
-			return;
-		}		
-		Error (0,0,0);
-		ResetCflag;
-	}
-}
-
-void GetFileAttributes(struct sigcontext_struct *context)
-{
-	char UnixFileName[256];
-	int drive,handle;
-	
-	ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
-
-	{
-		CX = 0x0;
-		ResetCflag;
-	}
-}
-
-void SetFileAttributes(struct sigcontext_struct *context)
-{
-	ResetCflag;
-}
-
-void DosIOCTL(struct sigcontext_struct *context)
-{
-	AX = UnknownUnit;
-	SetCflag;
-}
-
-void DupeFileHandle(struct sigcontext_struct *context)
-{
-	AX = dup(BX);
-	ResetCflag;
-}
-
-void GetSystemDate(struct sigcontext_struct *context)
-{
-	struct tm *now;
-	time_t ltime;
-
-	ltime = time(NULL);
-	now = localtime(&ltime);
-
-	CX = now->tm_year + 1900;
-	DX = ((now->tm_mon + 1) << 8) | now->tm_mday;
-	AX &= 0xff00;
-	AX |= now->tm_wday;
-}
-
-void GetSystemTime(struct sigcontext_struct *context)
-{
-	struct tm *now;
-	time_t ltime;
-
-	ltime = time(NULL);
-	now = localtime(&ltime);
-	 
-	CX = (now->tm_hour << 8) | now->tm_min;
-	DX = now->tm_sec << 8;
-}
-
-void GetExtendedErrorInfo(struct sigcontext_struct *context)
-{
-	AX = ExtendedError;
-	BX = (0x100 * ErrorClass) | Action;
-	CX &= 0x00ff;
-	CX |= (0x100 * ErrorLocus);
-}
-
-void GetInDosFlag(struct sigcontext_struct *context)
-{
-	const BYTE InDosFlag = 0;
-	
-	ES = segment(InDosFlag);
-	BX = offset(InDosFlag);
-}
-
-void CreateFile(struct sigcontext_struct *context)
-{
-	char UnixFileName[256];
-	int drive,handle;
-	
-	ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
-
-	{
-		handle = open(UnixFileName, O_CREAT | O_TRUNC);
-
-		if (handle == -1) {
-			switch (errno) {
-				case EACCES:
-				case EPERM:
-				case EROFS:
-					Error (WriteProtected, EC_AccessDenied, EL_Unknown);
-					break;
-				case EISDIR:
-					Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown);
-					break;
-				case ENFILE:
-				case EMFILE:
-					Error (NoMoreFiles, EC_MediaError, EL_Unknown);
-				case EEXIST:
-					Error (FileExists, EC_Exists, EL_Disk);
-					break;				
-				case ENOSPC:
-					Error (DiskFull, EC_MediaError, EL_Disk);
-					break;				
-				default:
-					Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
-					break;
-			}
-			AX = ExtendedError;
-			SetCflag;
-			return;
-		}		
-		Error (0,0,0);
-		BX = handle;
-		AX = NoError;
-		ResetCflag;
-	}
-}
-
-void OpenExistingFile(struct sigcontext_struct *context)
-{
-	char UnixFileName[256];
-	int drive, handle;
-	
-	ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
-	
-	{
-		handle = open(UnixFileName, O_RDWR);
-
-		if (handle == -1) {
-			switch (errno) {
-				case EACCES:
-				case EPERM:
-				case EROFS:
-					Error (WriteProtected, EC_AccessDenied, EL_Unknown);
-					break;
-				case EISDIR:
-					Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown);
-					break;
-				case ENFILE:
-				case EMFILE:
-					Error (NoMoreFiles, EC_MediaError, EL_Unknown);
-				case EEXIST:
-					Error (FileExists, EC_Exists, EL_Disk);
-					break;				
-				case ENOSPC:
-					Error (DiskFull, EC_MediaError, EL_Disk);
-					break;				
-				case ENOENT:
-					Error (FileNotFound, EC_MediaError, EL_Disk);
-					break;
-				default:
-					Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
-					break;
-			}
-			AX = ExtendedError;
-			SetCflag;
-			return;
-		}		
-		Error (0,0,0);
-		BX = handle;
-		AX = NoError;
-		ResetCflag;
-	}
-}
-
-void CloseFile(struct sigcontext_struct *context)
-{
-	if (close(BX) == -1) {
-		switch (errno) {
-			case EBADF:
-				Error (InvalidHandle, EC_AppError, EL_Unknown);
-				break;
-			default:
-				Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
-				break;
-		}
-		AX = ExtendedError;
-		SetCflag;
-		return;
-	}		
-	Error (0,0,0);
-	AX = NoError;
-	ResetCflag;
-}
-
-void RenameFile(struct sigcontext_struct *context)
-{
-	rename((char *) pointer(DS,DX), (char *) pointer(ES,DI));
-	ResetCflag;
-}
-
-void GetTrueFileName(struct sigcontext_struct *context)
-{ 
-	strncpy((char *) pointer(ES,DI), (char *) pointer(DS,SI), strlen((char *) pointer(DS,SI)) & 0x7f);
-	ResetCflag;
-}
-
-void MakeDir(struct sigcontext_struct *context)
-{
-	int drive;
-	char *dirname;
-	char unixname[256];
-	
-	dirname = (char *) pointer(DS,DX);
-
-	ParseDOSFileName(unixname,dirname,&drive);
-
-	{
-		if (mkdir(unixname,0) == -1) {
-			AX = CanNotMakeDir;
-			SetCflag;
-		}
-		ResetCflag;
-	}
-}
-
-void ChangeDir(struct sigcontext_struct *context)
-{
-	int drive;
-	char *dirname;
-	char unixname[256];
-	
-	dirname = (char *) pointer(DS,DX);
-
-	ParseDOSFileName(unixname,dirname,&drive);
-
-	{
-		strcpy(unixname,DosDrives[drive].CurrentDirectory);
-		ResetCflag;
-	}
-}
-
-void RemoveDir(struct sigcontext_struct *context)
-{
-	int drive;
-	char *dirname;
-	char unixname[256];
-	
-	dirname = (char *) pointer(DS,DX);
-
-	ParseDOSFileName(unixname,dirname,&drive);
-
-	{
-		if (strcmp(unixname,DosDrives[drive].CurrentDirectory)) {
-			AX = CanNotRemoveCwd;
-			SetCflag;
-		}
-	
-		#ifdef DOSDEBUG
-		fprintf(stderr,"rmdir %s\n",unixname);
-		#endif
-		
-		if (rmdir(unixname) == -1) {
-			AX = CanNotMakeDir; /* HUH ?*/
-			SetCflag;
-		} 
-		ResetCflag;
-	}
-}
-
-void AllocateMemory(struct sigcontext_struct *context)
-{
-	char *ptr;
-	
-	if ((ptr = (void *) memalign((size_t) (BX * 0x10), 0x10)) == NULL) {
-		AX = OutOfMemory;
-		BX = 0x0; /* out of memory */
-		SetCflag;
-	}
-	AX = segment((unsigned long) ptr);
-	ResetCflag;
-}
-
-void FreeMemory(struct sigcontext_struct *context)
-{
-	free((void *)(ES * 0x10));
-	ResetCflag;
-}
-
-void ResizeMemoryBlock(struct sigcontext_struct *context)
-{
-	char *ptr;
-	
-	if ((ptr = (void *) realloc((void *)(ES * 0x10), (size_t) BX * 0x10)) == NULL) {
-		AX = OutOfMemory;
-		BX = 0x0; /* out of memory */
-		SetCflag;
-	}
-	BX = segment((unsigned long) ptr);
-	ResetCflag;
-}
-
-void ExecProgram(struct sigcontext_struct *context)
-{
-	execl("wine",(char *) pointer(DS,DX));
-}
-
-void GetReturnCode(struct sigcontext_struct *context)
-{
-	AX = NoError; /* normal exit */
-}
-
-void FindFirst(struct sigcontext_struct *context)
-{
-
-}
-
-void FindNext(struct sigcontext_struct *context)
-{
-
-}
-
-void GetSysVars(struct sigcontext_struct *context)
-{
-	ES = 0x0;
-	BX = 0x0;
-}
-
-void GetFileDateTime(struct sigcontext_struct *context)
-{
-	int drive;
-	char *dirname;
-	char unixname[256];
-	struct stat filestat;
-	struct tm *now;
-
-	dirname = (char *) pointer(DS,DX);
-	ParseDOSFileName(unixname, dirname, &drive);
-
-	{
-		stat(unixname, &filestat);
-	 	
-		now = localtime (&filestat.st_mtime);
-	
-		CX = (now->tm_hour * 0x2000) + (now->tm_min * 0x20) + now->tm_sec/2;
-		DX = (now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday;
-
-		ResetCflag;
-	}
-}
-
-void SetFileDateTime(struct sigcontext_struct *context)
-{
-	int drive;
-	char *dirname;
-	char unixname[256];
-	struct utimbuf filetime;
-	
-	dirname = (char *) pointer(DS,DX);
-
-	ParseDOSFileName(unixname, dirname, &drive);
-
-	{
-		filetime.actime = 0L;
-		filetime.modtime = filetime.actime;
-
-		utime(unixname,&filetime);
-		ResetCflag;
-	}
-}
-
-void CreateTempFile(struct sigcontext_struct *context)
-{
-	char UnixFileName[256],TempString[256];
-	int drive,handle;
-	
-	ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
-	
-	sprintf(TempString,"%s%s%d",UnixFileName,"eb",(int) getpid());
-
-	{
-		handle = open(TempString, O_CREAT | O_TRUNC | O_RDWR);
-
-		if (handle == -1) {
-			AX = WriteProtected;
-			SetCflag;
-			return;
-		}
-		
-		strcpy((char *) pointer(DS,DX), UnixFileName);
-	
-		AX = handle;
-		ResetCflag;
-	}
-}
-
-void CreateNewFile(struct sigcontext_struct *context)
-{
-	char UnixFileName[256];
-	int drive,handle;
-	
-	ParseDOSFileName(UnixFileName, (char *) pointer(DS,DX), &drive);
-	
-	{
-		handle = open(UnixFileName, O_CREAT | O_TRUNC | O_RDWR);
-
-		if (handle == -1) {
-			AX = WriteProtected;
-			SetCflag;
-			return;
-		}
-
-		AX = handle;
-		ResetCflag;
-	}
-}
-
-void FileLock(struct sigcontext_struct *context)
-{
-
-}
-
-void GetExtendedCountryInfo(struct sigcontext_struct *context)
-{
-	ResetCflag;
-}
-
-int ValidDrive(int d)
-{
-	return 1;
-}
-
-void GetCurrentDirectory(struct sigcontext_struct *context)
-{
-	int drive;
-	char *ptr;
-
-	if ((DX & 0xff) == 0)
-		drive = CurrentDrive;
-	else
-		drive = (DX & 0xff)-1;
-
-	if (!ValidDrive(drive)) {
-		AX = InvalidDrive;
-		SetCflag;
-		return;
-	}
-	
-	strcpy((char *) pointer(DS,SI), DosDrives[drive].CurrentDirectory);
-	ResetCflag;
-	AX = 0x0100;
-}
-
-void GetCurrentPSP(struct sigcontext_struct *context)
-{
-
-}
-
-void GetDiskSerialNumber(struct sigcontext_struct *context)
-{
-	int drive;
-	struct diskinfo *ptr;
-	
-	if ((BX & 0xff)== 0)
-		drive = CurrentDrive;
-	else
-		drive = (BX & 0xff)-1;
-
-	if (!ValidDrive(drive)) {
-		AX = InvalidDrive;
-		SetCflag;
-		return;
-	}
-
-	{
-		ptr =(struct diskinfo *) pointer(DS,SI);
-
-		ptr->infolevel = 0;
-		ptr->serialnumber = 0xEBEBEB00 | drive;
-		strcpy(ptr->label,"NO NAME    ");
-		strcpy(ptr->fstype,"FAT16   ");
-	
-		AX = NoError;
-		ResetCflag;
-	}
-}
-
-void SetDiskSerialNumber(struct sigcontext_struct *context)
-{
-	AX &= 0xff00;
-	AX |= 1;
-	ResetCflag;
-}
-
-void CommitFile(struct sigcontext_struct *context)
-{
-
-}
-
-/************************************************************************/
-
-int do_int21(struct sigcontext_struct * context){
-	int ah;
-
-	fprintf(stderr,"int21: doing AX=%4x BX=%4x CX=%4x DX=%4x\n",
-		AX & 0xffff,BX & 0xffff,CX & 0xffff,DX & 0xffff);
-
-	ah = (AX >> 8) & 0xff;
-
-	if (ah == 0x59) {
-		GetExtendedErrorInfo(context);
-		return 1;
-	} else {
-	
-	Error (0,0,0);
-	
-	switch(ah) {
-
-	case 0x00: /* TERMINATE PROGRAM */
-		exit(0);
-
-	case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
-	case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
-	case 0x03: /* READ CHARACTER FROM STDAUX  */
-	case 0x04: /* WRITE CHARACTER TO STDAUX */
-	case 0x05: /* WRITE CHARACTER TO PRINTER */
-	case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
-	case 0x07: /* DIRECT CHARACTER INPUT, WITHOUT ECHO */
-	case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
-	case 0x09: /* WRITE STRING TO STANDARD OUTPUT */
-	case 0x0a: /* BUFFERED INPUT */
-	case 0x0b: /* GET STDIN STATUS */
-	case 0x0c: /* FLUSH BUFFER AND READ STANDARD INPUT */
-	case 0x0d: /* DISK BUFFER FLUSH */
-		break;
-
-	/* no FCB support for CP/M hackers */
-	
-	case 0x0f: /* OPEN FILE USING FCB */
-	case 0x10: /* CLOSE FILE USING FCB */
-	case 0x11: /* FIND FIRST MATCHING FILE USING FCB */
-	case 0x12: /* FIND NEXT MATCHING FILE USING FCB */
-	case 0x13: /* DELETE FILE USING FCB */
-	case 0x14: /* SEQUENTIAL READ FROM FCB FILE */		
-	case 0x15: /* SEQUENTIAL WRITE TO FCB FILE */
-	case 0x16: /* CREATE OR TRUNCATE FILE USING FCB */
-	case 0x17: /* RENAME FILE USING FCB */
-	case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
-	case 0x21: /* READ RANDOM RECORD FROM FCB FILE */
-	case 0x22: /* WRITE RANDOM RECORD TO FCB FILE */
-	case 0x23: /* GET FILE SIZE FOR FCB */
-	case 0x24: /* SET RANDOM RECORD NUMBER FOR FCB */
-	case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */
-	case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */
-	case 0x29: /* PARSE FILENAME INTO FCB */
-	case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */
-
-	case 0x2e: /* SET VERIFY FLAG */
-		break;
-
-	case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */
-	case 0x1d:
-	case 0x1e:
-	case 0x20:
-	case 0x2b: /* SET SYSTEM DATE */
-	case 0x2d: /* SET SYSTEM TIME */
-	case 0x37: /* "SWITCHAR" - GET SWITCH CHARACTER
-		      "SWITCHAR" - SET SWITCH CHARACTER
-		      "AVAILDEV" - SPECIFY \DEV\ PREFIX USE */
-	case 0x54: /* GET VERIFY FLAG */
-	case 0x61: /* UNUSED */
-	case 0x6b: /* NULL FUNCTION */
-	        AX &= 0xff00;
-		break;
-	
-	case 0x67: /* SET HANDLE COUNT */			
-		ResetCflag;
-		break;
-	
-	case 0x0e: /* SELECT DEFAULT DRIVE */
-		SetDefaultDrive(context);
-		break;
-
-	case 0x19: /* GET CURRENT DEFAULT DRIVE */
-		GetDefaultDrive(context);
-		break;
-		
-	case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
-		GetDefDriveAllocInfo(context);
-		break;
-	
-	case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */
-		GetDriveAllocInfo(context);
-		break;
-
-	case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
-	case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
-		GetDrivePB(context);
-		break;
-		
-	case 0x25: /* SET INTERRUPT VECTOR */
-		/* Ignore any attempt to set a segment vector */
-		return 1;
-
-	case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */
-		break;
-
-	case 0x2a: /* GET SYSTEM DATE */
-		GetSystemDate(context);
-		break;
-
-	case 0x2c: /* GET SYSTEM TIME */
-		GetSystemTime(context);
-                break;
-
-	case 0x30: /* GET DOS VERSION */
-	        AX = DosVersion; /* Hey folks, this is DOS V3.3! */
-		BX = 0x0012;     /* 0x123456 is Wine's serial # */
-		CX = 0x3456;
-		break;
-
-	case 0x31: /* TERMINATE AND STAY RESIDENT */
-		break;
-
-	case 0x33: /* MULTIPLEXED */
-		switch (AX & 0xff) {
-			case 0x00: /* GET CURRENT EXTENDED BREAK STATE */
-				if (!(AX & 0xff)) 
-					DX &= 0xff00;
-				break;
-
-			case 0x01: /* SET EXTENDED BREAK STATE */
-				break;		
-		
-			case 0x02: /* GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE */
-				DX &= 0xff00;
-				break;
-
-			case 0x05: /* GET BOOT DRIVE */
-				DX &= 0xff00;
-				DX |= 2; /* c: is Wine's bootdrive */
-				break;
-				
-			case 0x06: /* GET TRUE VERSION NUMBER */
-				BX = DosVersion;
-				DX = 0x00;
-				break;
-			default:
-				break;			
-		}
-		break;	
-
-	case 0x34: /* GET ADDRESS OF INDOS FLAG */
-		GetInDosFlag(context);
-		break;
-
-	case 0x35: /* GET INTERRUPT VECTOR */
- 		   /* Return a NULL segment selector - this will bomb, 
- 		              if anyone ever tries to use it */
-		ES = 0;
-		BX = 0;
-		break;
-
-	case 0x36: /* GET FREE DISK SPACE */
-		GetFreeDiskSpace(context);
-		break;
-
-	case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */
-		AX &= 0xff00;
-		AX |= 0x02; /* no country support available */
-		SetCflag;
-		break;
-		
-	case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */
-		MakeDir(context);
-		break;
-	
-	case 0x3a: /* "RMDIR" - REMOVE SUBDIRECTORY */
-		RemoveDir(context);
-		break;
-	
-	case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */
-		ChangeDir(context);
-		break;
-	
-	case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */
-		CreateFile(context);
-		break;
-
-	case 0x3d: /* "OPEN" - OPEN EXISTING FILE */
-		OpenExistingFile(context);
-		break;
-	
-	case 0x3e: /* "CLOSE" - CLOSE FILE */
-	case 0x68: /* "FFLUSH" - COMMIT FILE */
-	case 0x6a: /* COMMIT FILE */
-
-		CloseFile(context);
-		break;
-	
-	case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
-		ReadFile(context);
-		break;
-	
-	case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */
-		WriteFile(context);
-		break;
-	
-	case 0x41: /* "UNLINK" - DELETE FILE */
-		UnlinkFile(context);
-		break;
-	
-	case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */
-		SeekFile(context);
-		break;
-			
-	case 0x43: /* FILE ATTRIBUTES */
-		switch (AX & 0xff) {
-			case 0x00:
-				GetFileAttributes(context);
-				break;
-			case 0x01:
-				SetFileAttributes(context);
-				break;
-		}
-		break;
-		
-	case 0x44: /* IOCTL */
-		DosIOCTL(context);
-		break;
-
-	case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
-	case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
-		DupeFileHandle(context);
-		break;
-	
-	case 0x47: /* "CWD" - GET CURRENT DIRECTORY */	
-		GetCurrentDirectory(context);
-		AX = 0x0100; /* many Microsoft products for Windows rely
-				on this */
-		break;
-	
-	case 0x48: /* ALLOCATE MEMORY */
-		AllocateMemory(context);
-		break;
-	
-	case 0x49: /* FREE MEMORY */
-		FreeMemory(context);
-		break;
-	
-	case 0x4a: /* RESIZE MEMORY BLOCK */
-		ResizeMemoryBlock(context);
-		break;
-	
-	case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
-		ExecProgram(context);
-		break;		
-	
-	case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
-		exit(AX & 0xff);
-
-	case 0x4d: /* GET RETURN CODE */
-		GetReturnCode(context);
-		break;
-
-	case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
-		FindFirst(context);
-		break;
-
-	case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
-		FindNext(context);
-		break;
-			
-	case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
-		GetSysVars(context);
-		break;
-		
-	case 0x56: /* "RENAME" - RENAME FILE */
-		RenameFile(context);
-		break;
-	
-	case 0x57: /* FILE DATE AND TIME */
-		switch (AX & 0xff) {
-			case 0x00:
-				GetFileDateTime(context);
-				break;
-			case 0x01:
-				SetFileDateTime(context);
-				break;
-		}
-		break;
-
-	case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */
-		switch (AX & 0xff) {
-			case 0x00:
-				AX = 0x01;
-				break;
-			case 0x02:
-				AX &= 0xff00;
-				break;
-			case 0x01:
-			case 0x03:
-				break;
-		}
-		ResetCflag;
-		break;
-	
-	case 0x59: /* GET EXTENDED ERROR INFO */
-		GetExtendedErrorInfo(context);
-		break;
-		
-	case 0x5a: /* CREATE TEMPORARY FILE */
-		CreateTempFile(context);
-		break;
-	
-	case 0x5b: /* CREATE NEW FILE */
-		CreateNewFile(context);
-		break;
-	
-	case 0x5c: /* "FLOCK" - RECORD LOCKING */
-		FileLock(context);
-		break;	
-
-	case 0x5d: /* NETWORK */
-	case 0x5e:
-	case 0x5f:
-		AX &= 0xff00;
-		AX |= NoNetwork; /* network software not installed */
-		SetCflag;
-		break;
-
-	case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */
-		GetTrueFileName(context);
-		break;
-
-	case 0x62: /* GET CURRENT PSP ADDRESS */
-		GetCurrentPSP(context);
-		break;
-	
-	case 0x65: /* GET EXTENDED COUNTRY INFORMATION */
-		GetExtendedCountryInfo(context);
-		break;
-	
-	case 0x66: /* GLOBAL CODE PAGE TABLE */
-		switch (AX & 0xff) {
-			case 0x01:
-				BX = CodePage;
-				DX = BX;
-				ResetCflag;
-				break;			
-			case 0x02: 
-				CodePage = BX;
-				ResetCflag;
-				break;
-		}
-		break;
-	
-	case 0x69: /* DISK SERIAL NUMBER */
-		switch (AX & 0xff) {
-			case 0x00:
-				GetDiskSerialNumber(context);
-				break;			
-			case 0x01: 
-				SetDiskSerialNumber(context);
-				break;
-		}
-		break;
-
-	default:
-		fprintf(stderr,"Unable to handle int 0x21 %x\n", context->sc_eax);
-		return 1;
-	};
-	}
-	return 1;
-}
diff --git a/loader/library.c b/loader/library.c
index 6e96351..fe7813e 100644
--- a/loader/library.c
+++ b/loader/library.c
@@ -20,7 +20,7 @@
 {
     HANDLE hRet;
     printf("LoadLibrary '%s'\n", libname);
-    hRet = LoadImage(libname, NULL);
+    hRet = LoadImage(libname);
     printf("after LoadLibrary hRet=%04X\n", hRet);
     return hRet;
 }
diff --git a/loader/resource.c b/loader/resource.c
index a0c986c..9d97305 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -14,7 +14,6 @@
 #include "gdi.h"
 #include "wine.h"
 #include "icon.h"
-#include "cursor.h"
 
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 
@@ -31,7 +30,6 @@
 static HANDLE ResourceInst = 0;
 static struct w_files *ResourceFileInfo = NULL;
 static RESOURCE *Top = NULL;
-static HCURSOR hActiveCursor;
 extern HINSTANCE hSysRes;
 
 HANDLE RSC_LoadResource(int instance, char *rsc_name, int type, int *image_size_ret);
@@ -313,23 +311,26 @@
 	   instance, icon_name);
 #endif
     
-    if (instance == (HANDLE)NULL)  instance = hSysRes;
     if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
+    if (instance == (HANDLE)NULL)  instance = hSysRes;
     rsc_mem = RSC_LoadResource(instance, icon_name, NE_RSCTYPE_GROUP_ICON, 
 			       &image_size);
     if (rsc_mem == (HANDLE)NULL) {
 	printf("LoadIcon / Icon %04X not Found !\n", icon_name);
+	ReleaseDC(GetDesktopWindow(), hdc); 
 	return 0;
 	}
     lp = (WORD *)GlobalLock(rsc_mem);
     if (lp == NULL) {
 	GlobalFree(rsc_mem);
+	ReleaseDC(GetDesktopWindow(), hdc); 
 	return 0;
 	}
     lpicodesc = (ICONDESCRIP *)(lp + 3);
     hIcon = GlobalAlloc(GMEM_MOVEABLE, sizeof(ICONALLOC) + 1024);
     if (hIcon == (HICON)NULL) {
 	GlobalFree(rsc_mem);
+	ReleaseDC(GetDesktopWindow(), hdc); 
 	return 0;
 	}
     printf("LoadIcon Alloc hIcon=%X\n", hIcon);
@@ -344,11 +345,13 @@
     	NE_RSCTYPE_ICON, &image_size);
     if (rsc_mem == (HANDLE)NULL) {
 	printf("LoadIcon / Icon %04X Bitmaps not Found !\n", icon_name);
+	ReleaseDC(GetDesktopWindow(), hdc); 
 	return 0;
 	}
     lp = (WORD *)GlobalLock(rsc_mem);
     if (lp == NULL) {
 	GlobalFree(rsc_mem);
+	ReleaseDC(GetDesktopWindow(), hdc); 
 	return 0;
  	}
     bmi = (BITMAPINFO *)lp;
@@ -378,7 +381,6 @@
 	(BITMAPINFO *)bih, DIB_RGB_COLORS );
     GlobalUnlock(rsc_mem);
     GlobalFree(rsc_mem);
-    
     hMemDC = CreateCompatibleDC(hdc);
     hMemDC2 = CreateCompatibleDC(hdc);
     SelectObject(hMemDC, lpico->hBitmap);
@@ -386,8 +388,7 @@
     BitBlt(hMemDC, 0, 0, bih->biWidth, bih->biHeight, hMemDC2, 0, 0, SRCINVERT);
     DeleteDC(hMemDC);
     DeleteDC(hMemDC2);
-
-    ReleaseDC(0, hdc);
+    ReleaseDC(GetDesktopWindow(), hdc);
     return hIcon;
 }
 
@@ -407,165 +408,6 @@
 
 
 /**********************************************************************
- *			LoadCursor [USER.173]
- */
-HCURSOR LoadCursor(HANDLE instance, LPSTR cursor_name)
-{
-    XColor	bkcolor;
-    XColor	fgcolor;
-    HCURSOR 	hCursor;
-    HANDLE 	rsc_mem;
-    WORD 	*lp;
-    CURSORDESCRIP *lpcurdesc;
-    CURSORALLOC	  *lpcur;
-    BITMAP 	BitMap;
-    HBITMAP 	hBitMap;
-    HDC 	hMemDC;
-    HDC 	hdc;
-    int i, j, image_size;
-#ifdef DEBUG_RESOURCE
-    printf("LoadCursor: instance = %04x, name = %08x\n",
-	   instance, cursor_name);
-#endif    
-    if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
-    if (instance == (HANDLE)NULL)  instance = hSysRes;
-    rsc_mem = RSC_LoadResource(instance, cursor_name, NE_RSCTYPE_GROUP_CURSOR, 
-			       &image_size);
-    if (rsc_mem == (HANDLE)NULL) {
-	printf("LoadCursor / Cursor %08X not Found !\n", cursor_name);
-	return 0;
-	}
-    lp = (WORD *)GlobalLock(rsc_mem);
-    if (lp == NULL) {
-	GlobalFree(rsc_mem);
-	return 0;
-	}
-    lpcurdesc = (CURSORDESCRIP *)(lp + 3);
-#ifdef DEBUG_CURSOR
-    printf("LoadCursor / image_size=%d\n", image_size);
-    printf("LoadCursor / curReserved=%X\n", *lp);
-    printf("LoadCursor / curResourceType=%X\n", *(lp + 1));
-    printf("LoadCursor / curResourceCount=%X\n", *(lp + 2));
-    printf("LoadCursor / cursor Width=%d\n", (int)lpcurdesc->Width);
-    printf("LoadCursor / cursor Height=%d\n", (int)lpcurdesc->Height);
-    printf("LoadCursor / cursor curXHotspot=%d\n", (int)lpcurdesc->curXHotspot);
-    printf("LoadCursor / cursor curYHotspot=%d\n", (int)lpcurdesc->curYHotspot);
-    printf("LoadCursor / cursor curDIBSize=%lX\n", (DWORD)lpcurdesc->curDIBSize);
-    printf("LoadCursor / cursor curDIBOffset=%lX\n", (DWORD)lpcurdesc->curDIBOffset);
-#endif
-    hCursor = GlobalAlloc(GMEM_MOVEABLE, sizeof(CURSORALLOC) + 1024L); 
-    if (hCursor == (HCURSOR)NULL) {
-	GlobalFree(rsc_mem);
-	return 0;
-	}
-    printf("LoadCursor Alloc hCursor=%X\n", hCursor);
-    lpcur = (CURSORALLOC *)GlobalLock(hCursor);
-    lpcur->descriptor = *lpcurdesc;
-    GlobalUnlock(rsc_mem);
-    GlobalFree(rsc_mem);
-    rsc_mem = RSC_LoadResource(instance, 
-    	MAKEINTRESOURCE(lpcurdesc->curDIBOffset), 
-    	NE_RSCTYPE_CURSOR, &image_size);
-    if (rsc_mem == (HANDLE)NULL) {
-	printf("LoadCursor / Cursor %08X Bitmap not Found !\n", cursor_name);
-	return 0;
-	}
-    lp = (WORD *)GlobalLock(rsc_mem);
-    if (lp == NULL) {
-	GlobalFree(rsc_mem);
-	return 0;
- 	}
-    lp += 2;
-    for (j = 0; j < 16; j++)
-    	printf("%04X ", *(lp + j));
-    if (*lp == sizeof(BITMAPINFOHEADER))
-	lpcur->hBitmap = ConvertInfoBitmap(hdc, (BITMAPINFO *)lp);
-    else
-        lpcur->hBitmap = 0;
-    lp += sizeof(BITMAP);
-    for (i = 0; i < 81; i++) {
-	char temp = *((char *)lp + 162 + i);
-	*((char *)lp + 162 + i) = *((char *)lp + 324 - i);
-	*((char *)lp + 324 - i) = temp;
-	}
-printf("LoadCursor / before XCreatePixmapFromBitmapData !\n");
-    lpcur->pixshape = XCreatePixmapFromBitmapData(
-    	XT_display, DefaultRootWindow(XT_display), 
-        ((char *)lp + 211), 32, 32,
-/*
-        lpcurdesc->Width / 2, lpcurdesc->Height / 4, 
-*/
-        WhitePixel(XT_display, DefaultScreen(XT_display)), 
-        BlackPixel(XT_display, DefaultScreen(XT_display)), 1);
-    lpcur->pixmask = lpcur->pixshape;
-    bkcolor.pixel = WhitePixel(XT_display, DefaultScreen(XT_display)); 
-    fgcolor.pixel = BlackPixel(XT_display, DefaultScreen(XT_display));
-printf("LoadCursor / before XCreatePixmapCursor !\n");
-    lpcur->xcursor = XCreatePixmapCursor(XT_display,
- 	lpcur->pixshape, lpcur->pixmask, 
- 	&fgcolor, &bkcolor, lpcur->descriptor.curXHotspot, 
- 	lpcur->descriptor.curYHotspot);
-
-    ReleaseDC(0, hdc); 
-    GlobalUnlock(rsc_mem);
-    GlobalFree(rsc_mem);
-    return hCursor;
-}
-
-
-
-/**********************************************************************
- *			DestroyCursor [USER.458]
- */
-BOOL DestroyCursor(HCURSOR hCursor)
-{
-    CURSORALLOC	*lpcur;
-    if (hCursor == (HCURSOR)NULL) return FALSE;
-    lpcur = (CURSORALLOC *)GlobalLock(hCursor);
-    if (lpcur->hBitmap != (HBITMAP)NULL) DeleteObject(lpcur->hBitmap);
-    GlobalUnlock(hCursor);
-    GlobalFree(hCursor);
-    return TRUE;
-}
-
-
-/**********************************************************************
- *			SetCursor [USER.69]
- */
-HCURSOR SetCursor(HCURSOR hCursor)
-{
-    HDC		hDC;
-    HDC		hMemDC;
-    BITMAP	bm;
-    CURSORALLOC	*lpcur;
-    HCURSOR	hOldCursor;
-#ifdef DEBUG_CURSOR
-    printf("SetCursor / hCursor=%04X !\n", hCursor);
-#endif
-    if (hCursor == (HCURSOR)NULL) return FALSE;
-    lpcur = (CURSORALLOC *)GlobalLock(hCursor);
-    hOldCursor = hActiveCursor;
-    
-printf("SetCursor / before XDefineCursor !\n");
-    XDefineCursor(XT_display, DefaultRootWindow(XT_display), lpcur->xcursor);
-    GlobalUnlock(hCursor);
-    hActiveCursor = hCursor;
-    return hOldCursor;
-}
-
-
-/**********************************************************************
- *			ShowCursor [USER.71]
- */
-int ShowCursor(BOOL bShow)
-{
-    if (bShow) {
-    	}
-    return 0;
-}
-
-
-/**********************************************************************
  *					LoadAccelerators
  */
 HANDLE
@@ -586,6 +428,10 @@
     if (instance == 0)
 	return 0;
     
+#ifdef DEBUG_RESOURCE
+    printf("FindResource hInst=%04X typename=%08X resname=%08X\n", 
+		instance, type_name, resource_name);
+#endif
     if (OpenResourceFile(instance) < 0)
 	return 0;
     
@@ -644,6 +490,8 @@
     h = r->rsc_mem = GlobalAlloc(GMEM_MOVEABLE, image_size);
     image = GlobalLock(h);
 
+    lseek(ResourceFd, ((int) r->nameinfo.offset << r->size_shift), SEEK_SET);
+
     if (image == NULL || read(ResourceFd, image, image_size) != image_size)
     {
 	GlobalFree(h);
diff --git a/loader/selector.c b/loader/selector.c
index f091d1d..5edee7fa 100644
--- a/loader/selector.c
+++ b/loader/selector.c
@@ -7,7 +7,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
-#ifdef linux
+#ifdef __linux__
 #include <linux/unistd.h>
 #include <linux/head.h>
 #include <linux/mman.h>
@@ -38,17 +38,16 @@
 #define UTEXTSEL 0x1f
 #endif
 
-static struct segment_descriptor_s * EnvironmentSelector =  NULL;
-static struct segment_descriptor_s * PSP_Selector = NULL;
-struct segment_descriptor_s * MakeProcThunks = NULL;
+static SEGDESC * EnvironmentSelector =  NULL;
+static SEGDESC * PSP_Selector = NULL;
+SEGDESC * MakeProcThunks = NULL;
 unsigned short PSPSelector;
 unsigned char ran_out = 0;
-unsigned short SelectorOwners[MAX_SELECTORS];
-unsigned short SelectorMap[MAX_SELECTORS];
-unsigned short SelectorLimits[MAX_SELECTORS];
-unsigned char  SelectorTypes[MAX_SELECTORS];
 int LastUsedSelector = FIRST_SELECTOR - 1;
 
+unsigned short SelectorMap[MAX_SELECTORS];
+SEGDESC Segments[MAX_SELECTORS];
+
 #ifdef DEV_ZERO
     static FILE *zfile = NULL;
 #endif    
@@ -83,6 +82,74 @@
     return i;
 }
 
+#ifdef HAVE_IPC
+/**********************************************************************
+ *					IPCCopySelector
+ */
+int
+IPCCopySelector(int i_old, int i_new, int swap_type)
+{
+    SEGDESC *s_new, *s_old;
+
+    s_old = &Segments[i_old];
+    s_new = &Segments[i_new];
+
+    SelectorMap[i_new] = i_new;
+    
+    s_new->selector  = (i_new << 3) | 0x0007;
+    s_new->base_addr = (void *) ((long) s_new->selector << 16);
+    s_new->length    = s_old->length;
+    s_new->flags     = s_old->flags;
+    s_new->owner     = s_old->owner;
+    if (swap_type)
+    {
+	if (s_old->type == MODIFY_LDT_CONTENTS_DATA)
+	    s_new->type = MODIFY_LDT_CONTENTS_CODE;
+	else
+	    s_new->type = MODIFY_LDT_CONTENTS_DATA;
+    }
+    else
+	s_new->type      = s_old->type;
+	
+    if (s_old->shm_key == 0)
+    {
+	s_old->shm_key = shmget(IPC_PRIVATE, s_old->length, 0600);
+	if (s_old->shm_key == 0)
+	{
+	    memset(s_new, 0, sizeof(*s_new));
+	    return 0;
+	}
+	if (shmat(s_old->shm_key, s_new->base_addr, 0) == NULL)
+	{
+	    memset(s_new, 0, sizeof(*s_new));
+	    shmctl(s_old->shm_key, IPC_RMID, NULL);
+	    return 0;
+	}
+	memcpy(s_new->base_addr, s_old->base_addr, s_new->length);
+	munmap(s_old->base_addr, 
+	       ((s_old->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
+	shmat(s_old->shm_key, s_old->base_addr, 0);
+    }
+    else
+    {
+	if (shmat(s_old->shm_key, s_new->base_addr, 0) == NULL)
+	{
+	    memset(s_new, 0, sizeof(*s_new));
+	    return 0;
+	}
+    }
+    s_new->shm_key = s_old->shm_key;
+
+    if (set_ldt_entry(i_new, (unsigned long) s_new->base_addr, 
+		      s_new->length - 1, 0, s_new->type, 0, 0) < 0)
+    {
+	return 0;
+    }
+
+    return s_new->selector;
+}
+#endif
+
 /**********************************************************************
  *					AllocSelector
  *
@@ -92,32 +159,38 @@
 unsigned int
 AllocSelector(unsigned int old_selector)
 {
+    SEGDESC *s_new, *s_old;
     int i_new, i_old;
-    long base;
     
     i_new = FindUnusedSelector();
+    s_new = &Segments[i_new];
+    
     if (old_selector)
     {
 	i_old = (old_selector >> 3);
-	SelectorMap[i_new] = i_old;
-	base = SAFEMAKEPTR(old_selector, 0);
-	if (set_ldt_entry(i_new, base, 
-			  SelectorLimits[i_old], 0, 
-			  SelectorTypes[i_old], 0, 0) < 0)
+#ifdef HAVE_IPC
+	return IPCCopySelector(i_old, i_new, 0);
+#else
+	s_old = &Segments[i_old];
+	s_new->selector = (i_new << 3) | 0x0007;
+	*s_new = *s_old;
+	SelectorMap[i_new] = SelectorMap[i_old];
+
+	if (set_ldt_entry(i_new, s_new->base_addr, 
+			  s_new->length - 1, 0, 
+			  s_new->type, 0, 0) < 0)
 	{
 	    return 0;
 	}
-
-	SelectorLimits[i_new] = SelectorLimits[i_old];
-	SelectorTypes[i_new]  = SelectorTypes[i_old];
-	SelectorMap[i_new]    = SelectorMap[i_old];
+#endif
     }
     else
     {
+	memset(s_new, 0, sizeof(*s_new));
 	SelectorMap[i_new] = i_new;
     }
 
-    return i_new;
+    return (i_new << 3) | 0x0007;
 }
 
 /**********************************************************************
@@ -128,35 +201,64 @@
  */
 unsigned int PrestoChangoSelector(unsigned src_selector, unsigned dst_selector)
 {
-    long dst_base, src_base;
+#ifdef HAVE_IPC
+    SEGDESC *src_s;
+    int src_idx, dst_idx;
+
+    src_idx = src_selector >> 3;
+    dst_idx = dst_selector >> 3;
+
+    if (src_idx == dst_idx)
+    {
+	src_s = &Segments[src_idx];
+	
+	if (src_s->type == MODIFY_LDT_CONTENTS_DATA)
+	    src_s->type = MODIFY_LDT_CONTENTS_CODE;
+	else
+	    src_s->type = MODIFY_LDT_CONTENTS_DATA;
+
+	if (set_ldt_entry(src_idx, (long) src_s->base_addr,
+			  src_s->length - 1, 0, src_s->type, 0, 0) < 0)
+	{
+	    return 0;
+	}
+
+	return src_s->selector;
+    }
+    else
+    {
+	return IPCCopySelector(src_idx, dst_idx, 1);
+    }
+#else /* HAVE_IPC */
+    SEGDESC *src_s, *dst_s;
     char *p;
     int src_idx, dst_idx;
     int alias_count;
     int i;
-    
+
     src_idx = (SelectorMap[src_selector >> 3]);
     dst_idx = dst_selector >> 3;
-    src_base = (src_idx << 19) | 0x70000;
-    dst_base = (dst_idx << 19) | 0x70000;
+    src_s = &Segments[src_idx];
+    dst_s = &Segments[dst_idx];
 
     alias_count = 0;
     for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
 	if (SelectorMap[i] == src_idx)
 	    alias_count++;
     
-    if (SelectorTypes[src_idx] == MODIFY_LDT_CONTENTS_DATA 
+    if (src_s->type == MODIFY_LDT_CONTENTS_DATA 
 	|| alias_count > 1 || src_idx == dst_idx)
     {
-	if (SelectorTypes[src_idx] == MODIFY_LDT_CONTENTS_DATA)
-	    SelectorTypes[dst_idx] = MODIFY_LDT_CONTENTS_CODE;
+	*dst_s = *src_s;
+	
+	if (src_s->type == MODIFY_LDT_CONTENTS_DATA)
+	    dst_s->type = MODIFY_LDT_CONTENTS_CODE;
 	else
-	    SelectorTypes[dst_idx] = MODIFY_LDT_CONTENTS_DATA;
+	    dst_s->type = MODIFY_LDT_CONTENTS_DATA;
 
 	SelectorMap[dst_idx] = SelectorMap[src_idx];
-	SelectorLimits[dst_idx] = SelectorLimits[src_idx];
-	if (set_ldt_entry(dst_idx, src_base,
-			  SelectorLimits[dst_idx], 0, 
-			  SelectorTypes[dst_idx], 0, 0) < 0)
+	if (set_ldt_entry(dst_idx, (long) dst_s->base_addr,
+			  dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
 	{
 	    return 0;
 	}
@@ -168,20 +270,22 @@
 	 * segment.  The SAFEST (but ugliest) way to deal with 
 	 * this is to map the new segment and copy all the contents.
 	 */
-	SelectorTypes[dst_idx] = MODIFY_LDT_CONTENTS_DATA;
-	SelectorMap[dst_idx] = SelectorMap[src_idx];
-	SelectorLimits[dst_idx] = SelectorLimits[src_idx];
+	SelectorMap[dst_idx] = dst_idx;
+	*dst_s = *src_s;
+	dst_s->selector  = (dst_idx << 3) | 0x0007;
+	dst_s->base_addr = (void *) ((unsigned int) dst_s->selector << 16);
+	dst_s->type      = MODIFY_LDT_CONTENTS_DATA;
 #ifdef DEV_ZERO
 	if (zfile == NULL)
 	    zfile = fopen("/dev/zero","r");
-	p = (void *) mmap((char *) dst_base,
-			  ((SelectorLimits[dst_idx] + PAGE_SIZE) 
+	p = (void *) mmap((char *) dst_s->base_addr,
+			  ((dst_s->length + PAGE_SIZE) 
 			   & ~(PAGE_SIZE - 1)),
 			  PROT_EXEC | PROT_READ | PROT_WRITE,
 			  MAP_FIXED | MAP_PRIVATE, fileno(zfile), 0);
 #else
-	p = (void *) mmap((char *) dst_base,
-			  ((SelectorLimits[dst_idx] + PAGE_SIZE) 
+	p = (void *) mmap((char *) dst_s->base_addr,
+			  ((dst_s->length + PAGE_SIZE) 
 			   & ~(PAGE_SIZE - 1)),
 			  PROT_EXEC | PROT_READ | PROT_WRITE,
 			  MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
@@ -189,23 +293,27 @@
 	if (p == NULL)
 	    return 0;
 	
-	memcpy((void *) dst_base, (void *) src_base, 
-	       SelectorLimits[dst_idx] + 1);
-	if (set_ldt_entry(src_idx, dst_base,
-			  SelectorLimits[dst_idx], 0, 
-			  SelectorTypes[dst_idx], 0, 0) < 0)
+	memcpy((void *) dst_s->base_addr, (void *) src_s->base_addr, 
+	       dst_s->length);
+	if (set_ldt_entry(src_idx, dst_s->base_addr,
+			  dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
 	{
 	    return 0;
 	}
-	if (set_ldt_entry(dst_idx, dst_base,
-			  SelectorLimits[dst_idx], 0, 
-			  SelectorTypes[dst_idx], 0, 0) < 0)
+	if (set_ldt_entry(dst_idx, dst_s->base_addr,
+			  dst_s->length - 1, 0, dst_s->type, 0, 0) < 0)
 	{
 	    return 0;
 	}
+
+	munmap(src_s->base_addr,
+	       (src_s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1));
+	SelectorMap[src_idx] = dst_idx;
+	src_s->base_addr = dst_s->base_addr;
     }
 
-    return (dst_idx << 3) | 0x0007;
+    return dst_s->selector;
+#endif /* HAVE_IPC */
 }
 
 /**********************************************************************
@@ -227,12 +335,46 @@
  */
 unsigned int FreeSelector(unsigned int sel)
 {
+    SEGDESC *s;
     int sel_idx;
     int alias_count;
     int i;
+
+#ifdef HAVE_IPC
+    sel_idx = sel >> 3;
+
+    if (sel_idx < FIRST_SELECTOR || sel_idx >= MAX_SELECTORS)
+	return 0;
     
+    s = &Segments[sel_idx];
+    if (s->shm_key == 0)
+    {
+	munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
+	memcpy(s, 0, sizeof(*s));
+	SelectorMap[sel_idx] = 0;
+    }
+    else
+    {
+	shmdt(s->base_addr);
+
+	alias_count = 0;
+	for (i = FIRST_SELECTOR; i < MAX_SELECTORS; i++)
+	    if (SelectorMap[i] && Segments[i].shm_key == s->shm_key)
+		alias_count++;
+	
+	if (alias_count == 1)
+	    shmctl(s->shm_key, IPC_RMID, NULL);
+	    
+	memcpy(s, 0, sizeof(*s));
+	SelectorMap[sel_idx] = 0;
+    }
+    
+#else /* HAVE_IPC */
     sel_idx = SelectorMap[sel >> 3];
 
+    if (sel_idx < FIRST_SELECTOR || sel_idx >= MAX_SELECTORS)
+	return 0;
+    
     if (sel_idx != (sel >> 3))
     {
 	SelectorMap[sel >> 3] = 0;
@@ -246,10 +388,12 @@
 
     if (alias_count == 1)
     {
-	munmap((char *) (sel << 16), 
-	       ((SelectorLimits[sel_idx] + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
+	s = &Segments[sel_idx];
+	munmap(s->base_addr, ((s->length + PAGE_SIZE) & ~(PAGE_SIZE - 1)));
+	memcpy(s, 0, sizeof(*s));
 	SelectorMap[sel >> 3] = 0;
     }
+#endif /* HAVE_IPC */
 
     return 0;
 }
@@ -257,10 +401,10 @@
 /**********************************************************************
  *					CreateNewSegment
  */
-struct segment_descriptor_s *
+SEGDESC *
 CreateNewSegment(int code_flag, int read_only, int length)
 {
-    struct segment_descriptor_s *s;
+    SEGDESC *s;
     int contents;
     int i;
     
@@ -269,7 +413,7 @@
     /*
      * Fill in selector info.
      */
-    s = malloc(sizeof(*s));
+    s = &Segments[i];
     if (code_flag)
     {
 	contents = MODIFY_LDT_CONTENTS_CODE;
@@ -305,13 +449,12 @@
 		      (s->length - 1) & 0xffff, 0, 
 		      contents, read_only, 0) < 0)
     {
-	free(s);
+	memset(s, 0, sizeof(*s));
 	return NULL;
     }
 
     SelectorMap[i] = (unsigned short) i;
-    SelectorLimits[i] = s->length - 1;
-    SelectorTypes[i] = contents;
+    s->type = contents;
     
     return s;
 }
@@ -319,7 +462,7 @@
 /**********************************************************************
  *					GetNextSegment
  */
-struct segment_descriptor_s *
+SEGDESC *
 GetNextSegment(unsigned int flags, unsigned int limit)
 {
     return CreateNewSegment(0, 0, limit);
@@ -494,11 +637,11 @@
 /**********************************************************************
  *					CreateEnvironment
  */
-static struct segment_descriptor_s *
+static SEGDESC *
 CreateEnvironment(void)
 {
     char *p;
-    struct segment_descriptor_s * s;
+    SEGDESC * s;
 
     s = CreateNewSegment(0, 0, PAGE_SIZE);
     if (s == NULL)
@@ -521,12 +664,12 @@
 /**********************************************************************
  *					CreatePSP
  */
-static struct segment_descriptor_s *
+static SEGDESC *
 CreatePSP(void)
 {
     struct dos_psp_s *psp;
     unsigned short *usp;
-    struct segment_descriptor_s * s;
+    SEGDESC * s;
     char *p1, *p2;
     int i;
 
@@ -572,13 +715,13 @@
 /**********************************************************************
  *					CreateSelectors
  */
-struct segment_descriptor_s *
+SEGDESC *
 CreateSelectors(struct  w_files * wpnt)
 {
     int fd = wpnt->fd;
     struct ne_segment_table_entry_s *seg_table = wpnt->seg_table;
     struct ne_header_s *ne_header = wpnt->ne_header;
-    struct segment_descriptor_s *selectors, *s, *stmp;
+    SEGDESC *selectors, *s, *stmp;
     unsigned short auto_data_sel;
     int contents, read_only;
     int SelectorTableLength;
@@ -692,7 +835,7 @@
 
     s = selectors;
     for (i = 0; i < ne_header->n_segment_tab; i++, s++)
-	SelectorOwners[s->selector >> 3] = auto_data_sel;
+	Segments[s->selector >> 3].owner = auto_data_sel;
 
     if(!EnvironmentSelector) {
 	    EnvironmentSelector = CreateEnvironment();
diff --git a/loader/signal.c b/loader/signal.c
index 7b2727c..b2a492e 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -3,7 +3,11 @@
 #include <stdlib.h>
 #include <time.h>
 
+#ifdef __NetBSD__
+#include <sys/syscall.h>
+#else
 #include <syscall.h>
+#endif
 #include <signal.h>
 #include <errno.h>
 #ifdef linux
@@ -85,11 +89,11 @@
 		if(!do_int21(scp)) goto oops;
 		break;
         case 0x11:  
-  		scp->sc_eax = 0x00000000;  /* get equipment list: we haven't */
-         	break;                                       /* got anything */
+  		scp->sc_eax = (scp->sc_eax & 0xffff0000L) | DOS_GetEquipment();
+		break;
         case 0x12:               
-          	scp->sc_eax = 640L; /* get base mem size */                
-                break;
+          	scp->sc_eax = (scp->sc_eax & 0xffff0000L) | 640L; 
+          	break;				/* get base mem size */                
 	case 0x1A:
 		if(!do_int1A(scp)) goto oops;
 		break;
diff --git a/loader/wine.c b/loader/wine.c
index 7124317..60b606b 100644
--- a/loader/wine.c
+++ b/loader/wine.c
@@ -28,11 +28,14 @@
 
 char * GetModuleName(struct w_files * wpnt, int index, char *buffer);
 extern unsigned char ran_out;
+extern char WindowsPath[256];
 unsigned short WIN_StackSize;
 unsigned short WIN_HeapSize;
 
 struct  w_files * wine_files = NULL;
 
+int WineForceFail = 0;
+
 char **Argv;
 int Argc;
 struct mz_header_s *CurrentMZHeader;
@@ -40,11 +43,9 @@
 int CurrentNEFile;
 HINSTANCE hSysRes;
 
-static char *dllExtensions[] = { "dll", "exe", NULL };
-static char *exeExtensions[] = { "exe", NULL };
+static char *Extensions[] = { "dll", "exe", NULL };
 static char *WinePath = NULL;
 
-
 /**********************************************************************
  *					DebugPrintString
  */
@@ -101,12 +102,13 @@
  *					LoadImage
  * Load one NE format executable into memory
  */
-HINSTANCE LoadImage(char * filename,  char * modulename)
+HINSTANCE LoadImage(char *modulename)
 {
     unsigned int read_size;
     int i;
     struct w_files * wpnt, *wpnt1;
     unsigned int status;
+    char buffer[256];
 
     /* First allocate a spot to store the info we collect, and add it to
      * our linked list.
@@ -123,9 +125,23 @@
     wpnt->next = NULL;
 
     /*
+     * search file
+     */
+
+    if (FindFile(buffer, sizeof(buffer), modulename, Extensions, WindowsPath)
+    	==NULL)
+    {
+    	char temp[256];
+    	
+    	sprintf(temp,"LoadImage: I can't find %s !\n",modulename);
+    	myerror(temp);
+    }
+	fprintf(stderr,"LoadImage: loading %s (%s)\n", modulename, buffer);
+
+    /*
      * Open file for reading.
      */
-    wpnt->fd = open(filename, O_RDONLY);
+    wpnt->fd = open(buffer, O_RDONLY);
     if (wpnt->fd < 0)
     {
 	myerror(NULL);
@@ -133,7 +149,7 @@
     /*
      * Establish header pointers.
      */
-    wpnt->filename = strdup(filename);
+    wpnt->filename = strdup(buffer);
     wpnt->name = NULL;
     if(modulename)  wpnt->name = strdup(modulename);
 
@@ -181,7 +197,7 @@
     wpnt->selector_table = CreateSelectors(wpnt);
     wpnt->hinstance 
 	= wpnt->
-	    selector_table[wine_files->ne_header->auto_data_seg-1].selector;
+	    selector_table[wpnt->ne_header->auto_data_seg-1].selector;
 
     /* Get the lookup  table.  This is used for looking up the addresses
        of functions that are exported */
@@ -227,16 +243,10 @@
       
       if(FindDLLTable(buff)) continue;  /* This module already loaded */
 
-      if (FindFileInPath(buff2, sizeof(buff2), 
-			 buff, dllExtensions, WinePath) != NULL &&
-	  (fd = open(buff2, O_RDONLY)) >= 0)
-      {
-	  close(fd);
-	  LoadImage(buff2, buff);
-	  continue;
-      }
-
+      LoadImage(buff);
+/*
       fprintf(stderr,"Unable to load:%s\n",  buff);
+*/
     }
 return(wpnt->hinstance);
 }
@@ -249,6 +259,8 @@
 {
 	int segment;
 	char *p;
+	char *sysresname;
+	char syspath[256];
 	char exe_path[256];
 #ifdef WINESTAT
 	char * cp;
@@ -273,19 +285,20 @@
 	strcat(WinePath, ";");
 	strcat(WinePath, p);
 
-	if (FindFileInPath(exe_path, 256, argv[1], exeExtensions, WinePath)
-	    == NULL)
-	{
-	    fprintf(stderr, "Could not find file '%s'\n", argv[1]);
-	    exit(1);
-	}
-	
-	LoadImage(exe_path, NULL);
-    	hSysRes = LoadImage("sysres.dll", NULL);
+	LoadImage(argv[1]);
+	hSysRes = LoadImage("sysres.dll");
+	if (hSysRes == (HINSTANCE)NULL)
+ 	    printf("Error Loading System Resources !!!\n");
+ 	else
+ 	    printf("System Resources Loaded // hSysRes='%04X'\n", hSysRes);
 	
 	if(ran_out) exit(1);
 #ifdef DEBUG
-	GetEntryDLLName("USER", "INITAPP", 0, 0);
+	{
+	    int dummy1, dummy2;
+
+	    GetEntryDLLName("USER", "INITAPP", &dummy1, &dummy2);
+	}
 	for(i=0; i<1024; i++) {
 		int j;
 		j = GetEntryPointFromOrdinal(wine_files, i);
@@ -327,6 +340,21 @@
 
     init_wine_signals();
 
+    if (WineForceFail)
+    {
+	p = (char *) ((cs_reg << 16) | ip_reg);
+	
+	*p++ = 0xcd;
+	*p++ = 0x20;
+    }
+
+    if (ss_reg == 0)
+    {
+	fprintf(stderr, "SS is 0.  Send email to bob@amscons.com.\n");
+	fprintf(stderr, "    No. Really.  I want to know what programs\n");
+	fprintf(stderr, "    do this.\n");
+    }
+
     rv = CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
     printf ("rv = %x\n", rv);
 }
@@ -392,12 +420,11 @@
 int
 FixupSegment(struct w_files * wpnt, int segment_num)
 {
-  int fd =  wpnt->fd;
-  struct mz_header_s * mz_header = wpnt->mz_header;
-  struct ne_header_s *ne_header =  wpnt->ne_header;
-  struct ne_segment_table_entry_s *seg_table = wpnt->seg_table;
-  struct segment_descriptor_s *selector_table = wpnt->selector_table;
-
+    int fd =  wpnt->fd;
+    struct mz_header_s * mz_header = wpnt->mz_header;
+    struct ne_header_s *ne_header =  wpnt->ne_header;
+    struct ne_segment_table_entry_s *seg_table = wpnt->seg_table;
+    struct segment_descriptor_s *selector_table = wpnt->selector_table;
     struct relocation_entry_s *rep, *rep1;
     struct ne_segment_table_entry_s *seg;
     struct segment_descriptor_s *sel;
@@ -410,10 +437,14 @@
     char dll_name[257];
     char func_name[257];
     int i, n_entries;
+    int additive;
 
     seg = &seg_table[segment_num];
     sel = &selector_table[segment_num];
 
+    fprintf(stderr, "Segment fixups for %s, segment %d, selector %x\n", 
+	    wpnt->name, segment_num, (int) sel->base_addr >> 16);
+
     if ((seg->seg_data_offset == 0) ||
 	!(seg->seg_flags & NE_SEGFLAGS_RELOC_DATA))
 	return 0;
@@ -445,8 +476,13 @@
 	/*
 	 * Get the target address corresponding to this entry.
 	 */
+	additive = 0;
+	
 	switch (rep->relocation_type)
 	{
+	  case NE_RELTYPE_ORDINALADD:
+	    additive = 1;
+	    
 	  case NE_RELTYPE_ORDINAL:
 	    if (GetModuleName(wpnt, rep->target1,
 			      dll_name) == NULL)
@@ -474,6 +510,9 @@
 #endif
 	    break;
 	    
+	  case NE_RELTYPE_NAMEADD:
+	    additive = 1;
+	    
 	  case NE_RELTYPE_NAME:
 	    if (GetModuleName(wpnt, rep->target1, dll_name)
 		== NULL)
@@ -543,30 +582,50 @@
 	    continue;
 	    
 	  default:
-#ifndef DEBUG_FIXUP
 	    fprintf(stderr,"%d: ADDR TYPE %d,  TYPE %d,  OFFSET %04.4x,  ",
 		   i + 1, rep->address_type, rep->relocation_type, 
 		   rep->offset);
-	    fprintf(stderr,"TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
-#endif
+	    fprintf(stderr,"TARGET %04.4x %04.4x\n", 
+		    rep->target1, rep->target2);
 	    free(rep1);
-
 	    return -1;
+#if 0
+	    sp = (unsigned short *) ((char *) sel->base_addr + rep->offset);
+	    fprintf(stderr, "  FIXUP ADDRESS %04.4x:%04.4x\n",
+		    (int) sel->base_addr >> 16, rep->offset);
+	    WineForceFail = 1;
+	    continue;
+#endif
 	}
 
 	/*
 	 * Stuff the right size result in.
 	 */
 	sp = (unsigned short *) ((char *) sel->base_addr + rep->offset);
+	if (additive)
+	{
+	    if (FindDLLTable(dll_name) == NULL)
+		additive = 2;
+
+	    fprintf(stderr,"%d: ADDR TYPE %d,  TYPE %d,  OFFSET %04.4x,  ",
+		   i + 1, rep->address_type, rep->relocation_type, 
+		   rep->offset);
+	    fprintf(stderr,"TARGET %04.4x %04.4x\n", 
+		    rep->target1, rep->target2);
+	    fprintf(stderr, "    Additive = %d\n", additive);
+	}
+	
 	switch (rep->address_type)
 	{
 	  case NE_RADDR_OFFSET16:
 	    do {
 		next_addr = *sp;
 		*sp = (unsigned short) address;
+		if (additive == 2)
+		    *sp += next_addr;
 		sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
 	    } 
-	    while (next_addr != 0xffff);
+	    while (next_addr != 0xffff && !additive);
 
 	    break;
 	    
@@ -574,10 +633,12 @@
 	    do {
 		next_addr = *sp;
 		*sp     = (unsigned short) address;
+		if (additive == 2)
+		    *sp += next_addr;
 		*(sp+1) = (unsigned short) selector;
 		sp = (unsigned short *) ((char *) sel->base_addr + next_addr);
 	    } 
-	    while (next_addr != 0xffff);
+	    while (next_addr != 0xffff && !additive);
 
 	    break;
 	    
@@ -589,17 +650,15 @@
 		if (rep->relocation_type == NE_RELTYPE_INT1) break;
 
 	    } 
-	    while (next_addr != 0xffff);
+	    while (next_addr != 0xffff && !additive);
 
 	    break;
 	    
 	  default:
-#ifndef DEBUG_FIXUP
 	    printf("%d: ADDR TYPE %d,  TYPE %d,  OFFSET %04.4x,  ",
 		   i + 1, rep->address_type, rep->relocation_type, 
 		   rep->offset);
 	    printf("TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
-#endif
 	    free(rep1);
 	    return -1;
 	}
diff --git a/memory/Imakefile b/memory/Imakefile
new file mode 100644
index 0000000..edf4b6d
--- /dev/null
+++ b/memory/Imakefile
@@ -0,0 +1,21 @@
+#include "../Wine.tmpl"
+
+MODULE = memory
+
+SRCS = \
+	global.c \
+	heap.c \
+	atom.c
+
+OBJS = \
+	global.o \
+	heap.o \
+	atom.o
+
+WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
+DependTarget()
+CleanTarget()
+
+includes::
+
+install::
diff --git a/memory/Makefile b/memory/Makefile
index b624e09..f3ff2c7 100644
--- a/memory/Makefile
+++ b/memory/Makefile
@@ -1,6 +1,6 @@
 CFLAGS=$(COPTS) $(DEBUGOPTS) -I$(INCLUDE_DIR)
 
-OBJS=global.o heap.o
+OBJS=global.o heap.o atom.o
 
 default: memory.o
 
diff --git a/memory/atom.c b/memory/atom.c
new file mode 100644
index 0000000..1fd5f48
--- /dev/null
+++ b/memory/atom.c
@@ -0,0 +1,328 @@
+/*
+ * Atom table functions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+/*
+ * Current limitations:
+ *
+ * - This code should work fine when called from the emulation library,
+ * but probably not when called from the Windows program.  The reason
+ * is that everything is allocated on the current local heap, instead
+ * of taking into account the DS register.  Correcting this will also
+ * require some changes in the local heap management to bring it closer
+ * to Windows.
+ *
+ * - The code assumes that LocalAlloc() returns a block aligned on a
+ * 4-bytes boundary (because of the shifting done in HANDLETOATOM).
+ * If this is not the case, the allocation code will have to be changed.
+ *
+ * - Integer atoms created with MAKEINTATOM are not supported.  This is
+ * because they can't generally be differentiated from string constants
+ * located below 0x10000 in the emulation library.  If you need
+ * integer atoms, use the "#1234" form.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "atom.h"
+
+
+#define DEFAULT_ATOMTABLE_SIZE    37
+#define MIN_STR_ATOM              0xc000
+
+#define ATOMTOHANDLE(atom)        ((HANDLE)(atom) << 2)
+#define HANDLETOATOM(handle)      ((ATOM)(0xc000 | ((handle) >> 2)))
+
+
+static ATOMTABLE * localTable = NULL;
+static ATOMTABLE * globalTable = NULL;
+
+
+/***********************************************************************
+ *           ATOM_InitTable
+ */
+static BOOL ATOM_InitTable( ATOMTABLE ** table, WORD entries )
+{
+    int i;
+    HANDLE handle;
+    
+    handle = LocalAlloc( LMEM_MOVEABLE, sizeof(ATOMTABLE) +
+			 (entries-1) * sizeof(HANDLE) );
+    if (!handle) return FALSE;
+    *table = (ATOMTABLE *) LocalLock( handle );
+    (*table)->size = entries;
+    for (i = 0; i < entries; i++) (*table)->entries[i] = 0;
+    return TRUE;
+    
+}
+
+
+/***********************************************************************
+ *           ATOM_Init
+ *
+ * Global table initialisation.
+ */
+BOOL ATOM_Init()
+{
+    return ATOM_InitTable( &globalTable, DEFAULT_ATOMTABLE_SIZE );
+}
+
+
+/***********************************************************************
+ *           ATOM_MakePtr
+ *
+ * Make an ATOMENTRY pointer from a handle (obtained from GetAtomHandle()).
+ * Is is assumed that the atom is in the same segment as the table.
+ */
+static ATOMENTRY * ATOM_MakePtr( ATOMTABLE * table, HANDLE handle )
+{
+    return (ATOMENTRY *) (((int)table & 0xffff0000) | (int)handle);
+}
+
+
+/***********************************************************************
+ *           ATOM_Hash
+ */
+static WORD ATOM_Hash( WORD entries, LPCSTR str, WORD len )
+{
+    WORD i, hash = 0;
+
+    for (i = 0; i < len; i++) hash ^= str[i] + i;
+    return hash % entries;
+}
+
+
+/***********************************************************************
+ *           ATOM_AddAtom
+ */
+static ATOM ATOM_AddAtom( ATOMTABLE * table, LPCSTR str )
+{
+    WORD hash;
+    HANDLE entry;
+    ATOMENTRY * entryPtr;
+    int len;
+    
+    if ((len = strlen( str )) > 255) len = 255;
+
+      /* Check for integer atom */
+/*    if (!((int)str & 0xffff0000)) return (ATOM)((int)str & 0xffff); */
+    if (str[0] == '#') return atoi( &str[1] );
+
+    hash = ATOM_Hash( table->size, str, len );
+    entry = table->entries[hash];
+    while (entry)
+    {
+	entryPtr = ATOM_MakePtr( table, entry );
+	if ((entryPtr->length == len) && 
+	    (!strncasecmp( entryPtr->str, str, len )))
+	{
+	    entryPtr->refCount++;
+	    return HANDLETOATOM( entry );
+	}
+	entry = entryPtr->next;
+    }
+    
+    entry = (int)LocalAlloc( LMEM_MOVEABLE, sizeof(ATOMENTRY)+len-1 ) & 0xffff;
+    if (!entry) return 0;
+    entryPtr = ATOM_MakePtr( table, entry );
+    entryPtr->next = table->entries[hash];
+    entryPtr->refCount = 1;
+    entryPtr->length = len;
+    memcpy( entryPtr->str, str, len );
+    table->entries[hash] = entry;
+    return HANDLETOATOM( entry );
+}
+
+
+/***********************************************************************
+ *           ATOM_DeleteAtom
+ */
+static ATOM ATOM_DeleteAtom( ATOMTABLE * table, ATOM atom )
+{
+    ATOMENTRY * entryPtr;
+    HANDLE entry, *prevEntry;
+    WORD hash;
+    
+    if (atom < MIN_STR_ATOM) return 0;  /* Integer atom */
+
+    entry = ATOMTOHANDLE( atom );
+    entryPtr = ATOM_MakePtr( table, entry );
+
+      /* Find previous atom */
+    hash = ATOM_Hash( table->size, entryPtr->str, entryPtr->length );
+    prevEntry = &table->entries[hash];
+    while (*prevEntry && *prevEntry != entry)
+    {
+	ATOMENTRY * prevEntryPtr = ATOM_MakePtr( table, *prevEntry );
+	prevEntry = &prevEntryPtr->next;
+    }    
+    if (!*prevEntry) return atom;
+
+      /* Delete atom */
+    if (--entryPtr->refCount == 0)
+    {
+	*prevEntry = entryPtr->next;	
+	LocalFree( entry );
+    }    
+    return 0;
+}
+
+
+/***********************************************************************
+ *           ATOM_FindAtom
+ */
+static ATOM ATOM_FindAtom( ATOMTABLE * table, LPCSTR str )
+{
+    WORD hash;
+    HANDLE entry;
+    int len;
+    
+    if ((len = strlen( str )) > 255) len = 255;
+    
+      /* Check for integer atom */
+/*    if (!((int)str & 0xffff0000)) return (ATOM)((int)str & 0xffff); */
+    if (str[0] == '#') return atoi( &str[1] );
+
+    hash = ATOM_Hash( table->size, str, len );
+    entry = table->entries[hash];
+    while (entry)
+    {
+	ATOMENTRY * entryPtr = ATOM_MakePtr( table, entry );
+	if ((entryPtr->length == len) && 
+	    (!strncasecmp( entryPtr->str, str, len )))
+	    return HANDLETOATOM( entry );
+	entry = entryPtr->next;
+    }
+    return 0;
+}
+
+
+/***********************************************************************
+ *           ATOM_GetAtomName
+ */
+static WORD ATOM_GetAtomName( ATOMTABLE * table, ATOM atom,
+			      LPSTR buffer, short count )
+{
+    ATOMENTRY * entryPtr;
+    HANDLE entry;
+    char * strPtr;
+    int len;
+    char text[8];
+    
+    if (!count) return 0;
+    if (atom < MIN_STR_ATOM)
+    {
+	sprintf( text, "#%d", atom );
+	len = strlen(text);
+	strPtr = text;
+    }
+    else
+    {
+	entry = ATOMTOHANDLE( atom );
+	entryPtr = ATOM_MakePtr( table, entry );
+	len = entryPtr->length;
+	strPtr = entryPtr->str;
+    }
+    if (len >= count) len = count-1;
+    memcpy( buffer, strPtr, len );
+    buffer[len] = '\0';
+    return len;
+}
+
+
+/***********************************************************************
+ *           InitAtomTable   (KERNEL.68)
+ */
+BOOL InitAtomTable( WORD entries )
+{
+    return ATOM_InitTable( &localTable, entries );
+}
+
+
+/***********************************************************************
+ *           GetAtomHandle   (KERNEL.73)
+ */
+HANDLE GetAtomHandle( ATOM atom )
+{
+    if (atom < MIN_STR_ATOM) return 0;
+    return ATOMTOHANDLE( atom );
+}
+
+
+/***********************************************************************
+ *           AddAtom   (KERNEL.70)
+ */
+ATOM AddAtom( LPCSTR str )
+{
+    if (!localTable) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
+    return ATOM_AddAtom( localTable, str );
+}
+
+
+/***********************************************************************
+ *           DeleteAtom   (KERNEL.71)
+ */
+ATOM DeleteAtom( ATOM atom )
+{
+    if (!localTable) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
+    return ATOM_DeleteAtom( localTable, atom );
+}
+
+
+/***********************************************************************
+ *           FindAtom   (KERNEL.69)
+ */
+ATOM FindAtom( LPCSTR str )
+{
+    if (!localTable) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
+    return ATOM_FindAtom( localTable, str );
+}
+
+
+/***********************************************************************
+ *           GetAtomName   (KERNEL.72)
+ */
+WORD GetAtomName( ATOM atom, LPSTR buffer, short count )
+{
+    if (!localTable) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
+    return ATOM_GetAtomName( localTable, atom, buffer, count );
+}
+
+
+/***********************************************************************
+ *           GlobalAddAtom   (USER.268)
+ */
+ATOM GlobalAddAtom( LPCSTR str )
+{
+    return ATOM_AddAtom( globalTable, str );
+}
+
+
+/***********************************************************************
+ *           GlobalDeleteAtom   (USER.269)
+ */
+ATOM GlobalDeleteAtom( ATOM atom )
+{
+    return ATOM_DeleteAtom( globalTable, atom );
+}
+
+
+/***********************************************************************
+ *           GlobalFindAtom   (USER.270)
+ */
+ATOM GlobalFindAtom( LPCSTR str )
+{
+    return ATOM_FindAtom( globalTable, str );
+}
+
+
+/***********************************************************************
+ *           GlobalGetAtomName   (USER.271)
+ */
+WORD GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
+{
+    return ATOM_GetAtomName( globalTable, atom, buffer, count );
+}
diff --git a/memory/global.c b/memory/global.c
index 169ebc3..bf11b37 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -75,7 +75,7 @@
 	else if (count)
 	    count = 0;
     }
-
+    
     /*
      * If we couldn't find enough segments, then we need to create some.
      */
@@ -87,18 +87,22 @@
 	g_prev = NULL;
 	for (g = GlobalList; g != NULL; g = g->next)
 	    g_prev = g;
-
+	    
 	/*
 	 * Allocate segments.
 	 */
 	for (count = 0; count < n_segments; count++)
 	{
 	    s = GetNextSegment(flags, 0x10000);
-	    if (s == NULL)
+	    if (s == NULL) {
+		printf("GlobalGetFreeSegments // bad GetNextSegment !\n");
 		return NULL;
-
+		}
 	    g = (GDESC *) malloc(sizeof(*g));
-	    
+	    if (g == NULL) {
+		printf("GlobalGetFreeSegments // bad GDESC malloc !\n");
+		return NULL;
+		}
 	    g->prev = g_prev;
 	    g->next = NULL;
 	    g->handle = s->selector;
@@ -110,18 +114,15 @@
 	    else
 		g->lock_count = 0;
 	    
-	    free(s);
-
-	    if (count == 0)
-		g_start = g;
+	    if (count == 0) g_start = g;
 
 	    if (g_prev != NULL)
 	    {
 		g_prev->next = g;
-		g->prev = g_prev;
 	    }
 	    else
 		GlobalList = g;
+	    g_prev = g;
 	}
     }
 
@@ -131,6 +132,10 @@
     g = g_start;
     for (i = 0; i < n_segments; i++, g = g->next)
     {
+	if (g == NULL) {
+	    printf("GlobalGetFreeSegments // bad Segments chain !\n");
+	    return NULL;
+	    }
 	g->sequence = i + 1;
 	g->length = n_segments;
     }
diff --git a/misc/Imakefile b/misc/Imakefile
new file mode 100644
index 0000000..53eda76
--- /dev/null
+++ b/misc/Imakefile
@@ -0,0 +1,45 @@
+#include "../Wine.tmpl"
+
+MODULE = misc
+
+SRCS = \
+	kernel.c \
+	user.c \
+	rect.c \
+	file.c \
+	sound.c \
+	emulate.c \
+	keyboard.c \
+	profile.c \
+	lstr.c \
+	exec.c \
+	message.c \
+	int1a.c \
+	int21.c \
+	dos_fs.c \
+	xt.c
+
+OBJS = \
+	kernel.o \
+	user.o \
+	rect.o \
+	file.o \
+	sound.o \
+	emulate.o \
+	keyboard.o \
+	profile.o \
+	lstr.o \
+	exec.o \
+	message.o \
+	int1a.o \
+	int21.o \
+	dos_fs.o \
+	xt.o
+
+WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
+DependTarget()
+CleanTarget()
+
+includes::
+
+install::
diff --git a/misc/Makefile b/misc/Makefile
index 12180d0..8cdcee9 100644
--- a/misc/Makefile
+++ b/misc/Makefile
@@ -1,7 +1,8 @@
-CFLAGS=$(COPTS) $(DEBUGOPTS) -I$(INCLUDE_DIR)
+CFLAGS=$(COPTS) $(DEBUGOPTS) -I../include
 
-OBJS=dos.o kernel.o user.o xt.o rect.o file.o sound.o emulate.o \
-     keyboard.o profile.o lstr.o exec.o message.o
+OBJS=kernel.o user.o xt.o rect.o file.o sound.o emulate.o \
+     keyboard.o profile.o lstr.o exec.o message.o int1a.o int21.o \
+     dos_fs.o comm.o
 
 default: misc.o
 
diff --git a/misc/comm.c b/misc/comm.c
new file mode 100644
index 0000000..c0db9d5
--- /dev/null
+++ b/misc/comm.c
@@ -0,0 +1,872 @@
+/*
+ * DEC 93 Erik Bos (erik@trashcan.hacktic.nl)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+#ifdef __NetBSD__
+#include <errno.h>
+#include <sys/ioctl.h>
+#endif
+#include "wine.h"
+#include "windows.h"
+
+#define DEBUG_COMM
+
+#define MAX_PORTS	16
+
+int commerror = 0, eventmask = 0;
+
+struct DosDeviceStruct {
+	char *devicename;	/* /dev/cua1 */
+	int fd;
+	int suspended;
+};
+
+struct DosDeviceStruct COM[MAX_PORTS];
+struct DosDeviceStruct LPT[MAX_PORTS];
+
+void Comm_DeInit(void);
+
+void Comm_Init(void)
+{
+	int x, serial = 0, parallel = 0;
+	char option[10], temp[256], *ptr;
+	struct stat st;
+
+	for (x=0; x!=MAX_PORTS; x++) {
+		strcpy(option,"COMx");
+		option[3] = '0' + x;
+		option[4] = '\0';
+
+		GetPrivateProfileString("serialports", option, "*", temp, sizeof(temp), WINE_INI);
+		if (!strcmp(temp, "*") || *temp == '\0') 
+			COM[serial].devicename = NULL;
+		else {
+			stat(temp, &st);
+			if (!S_ISCHR(st.st_mode)) 
+				fprintf(stderr,"comm: can 't use `%s' as COM%d !\n", temp, x);
+			else
+				if ((ptr = malloc(strlen(temp)+1)) == NULL) 
+					fprintf(stderr,"comm: can't malloc for device info!\n");
+				else {
+					COM[serial].fd = 0;
+					COM[serial].devicename = ptr;
+					strcpy(COM[serial++].devicename, temp);
+				}
+		}
+
+		strcpy(option, "LPTx");
+		option[3] = '0' + x;
+		option[4] = '\0';
+
+		GetPrivateProfileString("parallelports", option, "*", temp, sizeof(temp), WINE_INI);
+		if (!strcmp(temp, "*") || *temp == '\0')
+			LPT[parallel].devicename = NULL;
+		else {
+			stat(temp, &st);
+			if (!S_ISCHR(st.st_mode)) 
+				fprintf(stderr,"comm: can 't use `%s' as LPT%d !\n", temp, x);
+			else 
+				if ((ptr = malloc(strlen(temp)+1)) == NULL) 
+					fprintf(stderr,"comm: can't malloc for device info!\n");
+				else {
+					LPT[serial].fd = 0;
+					LPT[serial].devicename = ptr;
+					strcpy(LPT[serial++].devicename, temp);
+				}
+		}
+
+	}
+	atexit(Comm_DeInit);
+
+#ifdef DEBUG_COMM
+	for (x=0; x!=MAX_PORTS; x++) {
+	    if (COM[x].devicename)
+		fprintf(stderr, "comm: COM%d = %s\n", x, COM[x].devicename);
+	    if (LPT[x].devicename)
+		fprintf(stderr, "comm: LPT%d = %s\n", x, LPT[x].devicename);
+	}
+#endif
+}
+
+void Comm_DeInit(void)
+{
+	int x;
+
+	for (x=0; x!=MAX_PORTS; x++) {
+
+		if (COM[x].devicename) {
+			if (COM[x].fd)
+	    			close(COM[x].fd);
+			fprintf(stderr, "comm: COM%d = %s\n",x,COM[x].devicename);
+	        	free(COM[x].devicename);
+	    	}
+		if (LPT[x].devicename) {
+			if (LPT[x].fd)
+		    		close(LPT[x].fd);
+			fprintf(stderr, "comm: LPT%d = %s\n",x,LPT[x].devicename);
+			free(LPT[x].devicename);
+		}
+	}
+}
+
+struct DosDeviceStruct *GetDeviceStruct(int fd)
+{
+	int x;
+	
+	for (x=0; x!=MAX_PORTS; x++) {
+	    if (COM[x].fd == fd)
+		return &COM[x];
+	    if (LPT[x].fd == fd)
+		return &LPT[x];
+	}
+
+	return NULL;
+}
+
+int ValidCOMPort(int x)
+{
+	return(x < MAX_PORTS ? (int) COM[x].devicename : 0); 
+}
+
+int ValidLPTPort(int x)
+{
+	return(x < MAX_PORTS ? (int) LPT[x].devicename : 0); 
+}
+
+int WinError(void)
+{
+	perror("comm");
+	switch (errno) {
+		default:
+			return CE_IOE;
+		}
+}
+
+int BuildCommDCB(LPSTR device, DCB FAR *lpdcb)
+{
+	/* "COM1:9600,n,8,1"	*/
+	/*  012345		*/
+
+	int port;
+	char *ptr, *ptr2, temp[256],temp2[10];
+
+#ifdef DEBUG_COMM
+fprintf(stderr,"BuildCommDCB: (%s), ptr %d\n", device, lpdcb);
+#endif
+	commerror = 0;
+
+	if (!strncmp(device,"COM",3)) {
+		port = device[3] - '0';
+	
+		if (!ValidCOMPort(port)) {
+			commerror = IE_BADID;
+			return -1;
+		}
+		
+		if (!COM[port].fd) {
+			commerror = IE_NOPEN;
+			return -1;
+		}
+		lpdcb->Id = COM[port].fd;
+		
+		if (!*(device+4))
+			return 0;
+
+		if (*(device+4) != ':')
+			return -1;
+		
+		strcpy(temp,device+5);
+		ptr = strtok(temp, ","); 
+
+		fprintf(stderr,"BuildCommDCB: baudrate (%s)\n", ptr);
+		lpdcb->BaudRate = atoi(ptr);
+
+		ptr = strtok(NULL, ",");
+		if (islower(*ptr))
+			*ptr = toupper(*ptr);
+
+		fprintf(stderr,"BuildCommDCB: parity (%c)\n", *ptr);
+		switch (*ptr) {
+			case 'N':
+				lpdcb->Parity = NOPARITY;
+				lpdcb->fParity = 0;
+				break;			
+			
+			lpdcb->fParity = 1;
+			
+			case 'E':
+				lpdcb->Parity = EVENPARITY;
+				break;			
+			case 'M':
+				lpdcb->Parity = MARKPARITY;
+				break;			
+			case 'O':
+				lpdcb->Parity = ODDPARITY;
+				break;			
+			default:
+				fprintf(stderr,"comm: unknown parity `%c'!\n", *ptr);
+				return -1;
+		}
+
+		ptr = strtok(NULL, ","); 
+		fprintf(stderr, "BuildCommDCB: charsize (%c)\n", *ptr);
+		lpdcb->ByteSize = *ptr - '0';
+
+		ptr = strtok(NULL, ",");
+		fprintf(stderr, "BuildCommDCB: stopbits (%c)\n", *ptr);
+		switch (*ptr) {
+			case '1':
+				lpdcb->StopBits = ONESTOPBIT;
+				break;			
+			case '2':
+				lpdcb->StopBits = TWOSTOPBITS;
+				break;			
+			default:
+				fprintf(stderr,"comm: unknown # of stopbits `%c'!\n", *ptr);
+				return -1;
+		}
+	}	
+
+	return 0;
+}
+
+int OpenComm(LPSTR device, UINT cbInQueue, UINT cbOutQueue)
+{
+	int port, fd;
+
+#ifdef DEBUG_COMM
+fprintf(stderr,"OpenComm: %s, %d, %d\n", device, cbInQueue, cbOutQueue);
+#endif	
+	
+	commerror = 0;
+
+	if (!strncmp(device,"COM",3)) {
+		port = device[3] - '0';
+
+		if (!ValidCOMPort(port)) {
+			commerror = IE_BADID;
+			return -1;
+		}
+		if (COM[port].fd) {
+			commerror = IE_OPEN;
+			return -1;
+		}
+
+		fd = open(COM[port].devicename, O_RDWR | O_NONBLOCK, 0);
+		if (fd == -1) {
+			commerror = WinError();
+			return -1;	
+		} else {
+			COM[port].fd = fd;	
+			return fd;
+		}
+	} 
+	else 
+	if (!strncmp(device,"LPT",3)) {
+		port = device[3] - '0';
+	
+		if (!ValidLPTPort(port)) {
+			commerror = IE_BADID;
+			return -1;
+		}		
+		if (LPT[port].fd) {
+			commerror = IE_OPEN;
+			return -1;
+		}
+
+		fd = open(LPT[port].devicename, O_RDWR | O_NONBLOCK, 0);
+		if (fd == -1) {
+			commerror = WinError();
+			return -1;	
+		} else {
+			LPT[port].fd = fd;
+			return fd;
+		}
+	}
+	return 0;
+}
+
+int CloseComm(int fd)
+{
+	int status;
+
+#ifdef DEBUG_COMM
+fprintf(stderr,"CloseComm: fd %d\n", fd);
+#endif	
+
+	if (close(fd) == -1) {
+		commerror = WinError();
+		return -1;
+	} else {
+		commerror = 0;
+		return 0;
+	}
+}
+
+int SetCommBreak(int fd)
+{
+	struct DosDeviceStruct *ptr;
+
+#ifdef DEBUG_COMM
+fprintf(stderr,"SetCommBreak: fd: %d\n", fd);
+#endif	
+
+	if ((ptr = GetDeviceStruct(fd)) == NULL) {
+		commerror = IE_BADID;
+		return -1;
+	}
+
+	ptr->suspended = 1;
+	commerror = 0;
+	return 0;
+}
+
+int ClearCommBreak(int fd)
+{
+	struct DosDeviceStruct *ptr;
+
+#ifdef DEBUG_COMM
+fprintf(stderr,"ClearCommBreak: fd: %d\n", fd);
+#endif	
+
+	if ((ptr = GetDeviceStruct(fd)) == NULL) {
+		commerror = IE_BADID;
+		return -1;
+	}
+
+	ptr->suspended = 0;
+	commerror = 0;
+	return 0;
+}
+
+LONG EscapeCommFunction(int fd, int nFunction)
+{
+	int max;
+	struct termios port;
+
+#ifdef DEBUG_COMM
+fprintf(stderr,"EscapeCommFunction fd: %d, function: %d\n", fd, nFunction);
+#endif
+
+	if (tcgetattr(fd, &port) == -1) {
+		commerror = WinError();	
+		return -1;
+	}
+
+	switch (nFunction) {
+		case RESETDEV:
+			break;					
+
+		case GETMAXCOM:
+			for (max = 0;COM[max].devicename;max++)
+				;		
+			return max;
+			break;
+
+		case GETMAXLPT:
+			for (max = 0;LPT[max].devicename;max++)
+				;		
+			return 0x80 + max;
+			break;
+
+		case CLRDTR:
+			port.c_cflag &= TIOCM_DTR;
+			break;
+
+		case CLRRTS:
+			port.c_cflag &= TIOCM_RTS;
+			break;
+	
+		case SETDTR:
+			port.c_cflag |= CRTSCTS;
+			break;
+
+		case SETRTS:
+			port.c_cflag |= CRTSCTS;
+			break;
+
+		case SETXOFF:
+			port.c_iflag |= IXOFF;
+			break;
+
+		case SETXON:
+			port.c_iflag |= IXON;
+			break;
+
+		default:
+			fprintf(stderr,"EscapeCommFunction fd: %d, unknown function: %d\n", fd, nFunction);
+			break;				
+	}
+	
+	if (tcsetattr(fd, TCSADRAIN, &port) == -1) {
+		commerror = WinError();
+		return -1;	
+	} else {
+		commerror = 0;
+		return 0;
+	}
+}
+
+int FlushComm(int fd, int fnQueue)
+{
+	int queue;
+
+#ifdef DEBUG_COMM
+fprintf(stderr,"FlushComm fd: %d, queue: %d\n", fd, fnQueue);
+#endif	
+
+	switch (fnQueue) {
+		case 0:
+			queue = TCOFLUSH;
+			break;
+		case 1:
+			queue = TCIFLUSH;
+			break;
+		default:
+			fprintf(stderr,"FlushComm fd: %d, UNKNOWN queue: %d\n", fd, fnQueue);
+			return -1;
+		}
+	
+	if (tcflush(fd, fnQueue)) {
+		commerror = WinError();
+		return -1;	
+	} else {
+		commerror = 0;
+		return 0;
+	}
+}  
+
+int GetCommError(int fd, COMSTAT FAR *lpStat)
+{
+#ifdef DEBUG_COMM
+fprintf(stderr,"GetCommError: fd %d (current error %d)\n", fd, commerror);
+#endif	
+
+	return(commerror);
+}
+
+UINT FAR* SetCommEventMask(int fd, UINT fuEvtMask)
+{
+#ifdef DEBUG_COMM
+fprintf(stderr,"SetCommEventMask: fd %d, mask %d\n", fd, fuEvtMask);
+#endif	
+	
+	eventmask |= fuEvtMask;
+	return (UINT *)&eventmask;
+}
+
+UINT GetCommEventMask(int fd, int fnEvtClear)
+{
+#ifdef DEBUG_COMM
+fprintf(stderr,"GetCommEventMask: fd %d, mask %d\n", fd, fnEvtClear);
+#endif	
+	eventmask &= ~fnEvtClear;
+	return eventmask;
+}
+
+int SetCommState(DCB FAR *lpdcb)
+{
+	struct termios port;
+
+#ifdef DEBUG_COMM
+fprintf(stderr,"SetCommState: fd %d, ptr %d\n", lpdcb->Id, lpdcb);
+#endif	
+
+	if (tcgetattr(lpdcb->Id, &port) == -1) {
+		commerror = WinError();	
+		return -1;
+	}
+	cfmakeraw(&port);
+	port.c_cc[VMIN] = 0;
+	port.c_cc[VTIME] = 0;
+
+	fprintf(stderr,"SetCommState: baudrate %d\n",lpdcb->BaudRate);
+#ifdef CBAUD
+	port.c_cflag &= ~CBAUD;
+	switch (lpdcb->BaudRate) {
+		case 110:
+		case CBR_110:
+			port.c_cflag |= B110;
+			break;		
+		case 300:
+		case CBR_300:
+			port.c_cflag |= B300;
+			break;		
+		case 600:
+		case CBR_600:
+			port.c_cflag |= B600;
+			break;		
+		case 1200:
+		case CBR_1200:
+			port.c_cflag |= B1200;
+			break;		
+		case 2400:
+		case CBR_2400:
+			port.c_cflag |= B2400;
+			break;		
+		case 4800:
+		case CBR_4800:
+			port.c_cflag |= B4800;
+			break;		
+		case 9600:
+		case CBR_9600:
+			port.c_cflag |= B9600;
+			break;		
+		case 19200:
+		case CBR_19200:
+			port.c_cflag |= B19200;
+			break;		
+		case 38400:
+		case CBR_38400:
+			port.c_cflag |= B38400;
+			break;		
+		default:
+			commerror = IE_BAUDRATE;
+			return -1;
+	}
+#else
+        switch (lpdcb->BaudRate) {
+                case 110:
+                case CBR_110:
+                        port.c_ospeed = B110;
+                        break;
+                case 300:
+                case CBR_300:
+                        port.c_ospeed = B300;
+                        break;
+                case 600:
+                case CBR_600:
+                        port.c_ospeed = B600;
+                        break;
+                case 1200:
+                case CBR_1200:
+                        port.c_ospeed = B1200;
+                        break;
+                case 2400:
+                case CBR_2400:
+                        port.c_ospeed = B2400;
+                        break;
+                case 4800:
+                case CBR_4800:
+                        port.c_ospeed = B4800;
+                        break;
+                case 9600:
+                case CBR_9600:
+                        port.c_ospeed = B9600;
+                        break;
+                case 19200:
+                case CBR_19200:
+                        port.c_ospeed = B19200;
+                        break;
+                case 38400:
+                case CBR_38400:
+                        port.c_ospeed = B38400;
+                        break;
+                default:
+                        commerror = IE_BAUDRATE;
+                        return -1;
+        }
+        port.c_ispeed = port.c_ospeed;
+#endif
+	fprintf(stderr,"SetCommState: bytesize %d\n",lpdcb->ByteSize);
+	port.c_cflag &= ~CSIZE;
+	switch (lpdcb->ByteSize) {
+		case 5:
+			port.c_cflag |= CS5;
+			break;
+		case 6:
+			port.c_cflag |= CS6;
+			break;
+		case 7:
+			port.c_cflag |= CS7;
+			break;
+		case 8:
+			port.c_cflag |= CS8;
+			break;
+		default:
+			commerror = IE_BYTESIZE;
+			return -1;
+	}
+
+	fprintf(stderr,"SetCommState: parity %d\n",lpdcb->Parity);
+	port.c_cflag &= ~(PARENB | PARODD);
+	if (lpdcb->fParity)
+		switch (lpdcb->Parity) {
+			case NOPARITY:
+				port.c_iflag &= ~INPCK;
+				break;
+			case ODDPARITY:
+				port.c_cflag |= (PARENB | PARODD);
+				port.c_iflag |= INPCK;
+				break;
+			case EVENPARITY:
+				port.c_cflag |= PARENB;
+				port.c_iflag |= INPCK;
+				break;
+			default:
+				commerror = IE_BYTESIZE;
+				return -1;
+		}
+	
+
+	fprintf(stderr,"SetCommState: stopbits %d\n",lpdcb->StopBits);
+	switch (lpdcb->StopBits) {
+		case ONESTOPBIT:
+				port.c_cflag &= ~CSTOPB;
+				break;
+		case TWOSTOPBITS:
+				port.c_cflag |= CSTOPB;
+				break;
+		default:
+			commerror = IE_BYTESIZE;
+			return -1;
+	}
+
+	if (lpdcb->fDtrflow || lpdcb->fRtsflow || lpdcb->fOutxCtsFlow)
+		port.c_cflag |= CRTSCTS;
+
+	if (lpdcb->fDtrDisable) 
+		port.c_cflag &= ~CRTSCTS;
+	
+	if (lpdcb->fInX)
+		port.c_iflag |= IXON;
+	if (lpdcb->fOutX)
+		port.c_iflag |= IXOFF;
+
+	if (tcsetattr(lpdcb->Id, TCSADRAIN, &port) == -1) {
+		commerror = WinError();	
+		return -1;
+	} else {
+		commerror = 0;
+		return 0;
+	}
+}
+
+int GetCommState(int fd, DCB FAR *lpdcb)
+{
+	struct termios port;
+
+#ifdef DEBUG_COMM
+fprintf(stderr,"GetCommState: fd %d, ptr %d\n", fd, lpdcb);
+#endif
+
+	if (tcgetattr(fd, &port) == -1) {
+		commerror = WinError();	
+		return -1;
+	}
+
+	lpdcb->Id = fd;
+
+#ifdef CBAUD
+        switch (port.c_cflag & CBAUD) {
+#else
+        switch (port.c_ospeed) {
+#endif
+		case B110:
+			lpdcb->BaudRate = 110;
+			break;
+		case B300:
+			lpdcb->BaudRate = 300;
+			break;
+		case B600:
+			lpdcb->BaudRate = 600;
+			break;
+		case B1200:
+			lpdcb->BaudRate = 1200;
+			break;
+		case B2400:
+			lpdcb->BaudRate = 2400;
+			break;
+		case B4800:
+			lpdcb->BaudRate = 4800;
+			break;
+		case B9600:
+			lpdcb->BaudRate = 9600;
+			break;
+		case B19200:
+			lpdcb->BaudRate = 19200;
+			break;
+		case B38400:
+			lpdcb->BaudRate = 38400;
+			break;
+	}
+
+	switch (port.c_cflag & CSIZE) {
+		case CS5:
+			lpdcb->ByteSize = 5;
+			break;
+		case CS6:
+			lpdcb->ByteSize = 6;
+			break;
+		case CS7:
+			lpdcb->ByteSize = 7;
+			break;
+		case CS8:
+			lpdcb->ByteSize = 8;
+			break;
+	}	
+	
+	switch (port.c_cflag & ~(PARENB | PARODD)) {
+		case 0:
+			lpdcb->fParity = NOPARITY;
+			break;
+		case PARENB:
+			lpdcb->fParity = EVENPARITY;
+			break;
+		case (PARENB | PARODD):
+			lpdcb->fParity = ODDPARITY;		
+			break;
+	}
+
+	if (port.c_cflag & CSTOPB)
+		lpdcb->StopBits = TWOSTOPBITS;
+	else
+		lpdcb->StopBits = ONESTOPBIT;
+
+	lpdcb->RlsTimeout = 50;
+	lpdcb->CtsTimeout = 50; 
+	lpdcb->DsrTimeout = 50;
+	lpdcb->fNull = 0;
+	lpdcb->fChEvt = 0;
+	lpdcb->fBinary = 1;
+
+	lpdcb->fDtrDisable = 0;
+	if (port.c_cflag & CRTSCTS) {
+		lpdcb->fDtrflow = 1;
+		lpdcb->fRtsflow = 1;
+		lpdcb->fOutxCtsFlow = 1;
+		lpdcb->fOutxDsrFlow = 1;
+	} else 
+		lpdcb->fDtrDisable = 1;
+
+	if (port.c_iflag & IXON)
+		lpdcb->fInX = 1;
+	else
+		lpdcb->fInX = 0;
+
+	if (port.c_iflag & IXOFF)
+		lpdcb->fOutX = 1;
+	else
+		lpdcb->fOutX = 0;
+/*
+	lpdcb->XonChar = 
+	lpdcb->XoffChar = 
+ */
+	lpdcb->XonLim = 10;
+	lpdcb->XoffLim = 10;
+
+	commerror = 0;
+	return 0;
+}
+
+int TransmitCommChar(int fd, char chTransmit)
+{
+	struct DosDeviceStruct *ptr;
+
+#ifdef DEBUG_COMM
+fprintf(stderr,"TransmitCommChar: fd %d, data %d \n", fd, chTransmit);
+#endif	
+
+	if ((ptr = GetDeviceStruct(fd)) == NULL) {
+		commerror = IE_BADID;
+		return -1;
+	}
+
+	if (ptr->suspended) {
+		commerror = IE_HARDWARE;
+		return -1;
+	}	
+
+	if (write(fd, (void *) &chTransmit, 1) == -1) {
+		commerror = WinError();
+		return -1;	
+	}  else {
+		commerror = 0;
+		return 0;
+	}
+}
+
+int UngetCommChar(int fd, char chUnget)
+{
+	struct DosDeviceStruct *ptr;
+
+#ifdef DEBUG_COMM
+fprintf(stderr,"UngetCommChar: fd %d (char %d)\n", fd, chUnget);
+#endif	
+	fprintf(stderr,"NOT implemented!\n");
+
+	if ((ptr = GetDeviceStruct(fd)) == NULL) {
+		commerror = IE_BADID;
+		return -1;
+	}
+
+	if (ptr->suspended) {
+		commerror = IE_HARDWARE;
+		return -1;
+	}	
+
+	commerror = 0;
+	return 0;
+}
+
+int ReadComm(int fd, LPSTR lpvBuf, int cbRead)
+{
+	struct DosDeviceStruct *ptr;
+#ifdef DEBUG_COMM
+fprintf(stderr,"ReadComm: fd %d, ptr %d, length %d\n", fd, lpvBuf, cbRead);
+#endif	
+	if ((ptr = GetDeviceStruct(fd)) == NULL) {
+		commerror = IE_BADID;
+		return -1;
+	}
+
+	if (ptr->suspended) {
+		commerror = IE_HARDWARE;
+		return -1;
+	}	
+
+	if (read(fd, (void *) lpvBuf, cbRead) == -1) {
+		commerror = WinError();
+		return -1;	
+	} else {
+		commerror = 0;
+		return 0;
+	}
+}
+
+int WriteComm(int fd, LPSTR lpvBuf, int cbWrite)
+{
+	int x;
+	struct DosDeviceStruct *ptr;
+
+#ifdef DEBUG_COMM
+fprintf(stderr,"WriteComm: fd %d, ptr %d, length %d\n", fd, lpvBuf, cbWrite);
+#endif
+	
+	if ((ptr = GetDeviceStruct(fd)) == NULL) {
+		commerror = IE_BADID;
+		return -1;
+	}
+
+	if (ptr->suspended) {
+		commerror = IE_HARDWARE;
+		return -1;
+	}	
+	
+	for (x=0; x != cbWrite ; x++)
+		fprintf(stderr,"%c", *(lpvBuf + x) );
+
+	if (write(fd, (void *) lpvBuf, cbWrite) == -1) {
+		commerror = WinError();
+		return -1;	
+	} else {
+		commerror = 0;	
+		return 0;
+	}
+}
diff --git a/misc/dos.c b/misc/dos.c
deleted file mode 100644
index f5f80fc..0000000
--- a/misc/dos.c
+++ /dev/null
@@ -1,76 +0,0 @@
-static char RCSId[] = "$Id$";
-static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include "prototypes.h"
-#include "regfunc.h"
-
-static void
-GetTimeDate(int time_flag)
-{
-    struct tm *now;
-    time_t ltime;
-    
-    ltime = time(NULL);
-    now = localtime(&ltime);
-    if (time_flag)
-    {
-	_CX = (now->tm_hour << 8) | now->tm_min;
-	_DX = now->tm_sec << 8;
-    }
-    else
-    {
-	_CX = now->tm_year + 1900;
-	_DX = ((now->tm_mon + 1) << 8) | now->tm_mday;
-	_AX &= 0xff00;
-	_AX |= now->tm_wday;
-    }
-#ifdef DEBUG_DOS
-    printf("GetTimeDate: AX = %04x, CX = %04x, DX = %04x\n", _AX, _CX, _DX);
-#endif
-    
-    ReturnFromRegisterFunc();
-    /* Function does not return */
-}
-
-/**********************************************************************
- *					KERNEL_DOS3Call
- */
-int
-KERNEL_DOS3Call()
-{
-    switch ((_AX >> 8) & 0xff)
-    {
-      case 0x30:
-	_AX = 0x0303;
-	ReturnFromRegisterFunc();
-	/* Function does not return */
-	
-      case 0x25:
-      case 0x35:
-	return 0;
-
-      case 0x2a:
-	GetTimeDate(0);
-	/* Function does not return */
-	
-      case 0x2c:
-	GetTimeDate(1);
-	/* Function does not return */
-
-      case 0x4c:
-	exit(_AX & 0xff);
-
-      default:
-	fprintf(stderr, "DOS: AX %04x, BX %04x, CX %04x, DX %04x\n",
-		_AX, _BX, _CX, _DX);
-	fprintf(stderr, "     SP %04x, BP %04x, SI %04x, DI %04x\n",
-		_SP, _BP, _SI, _DI);
-	fprintf(stderr, "     DS %04x, ES %04x\n",
-		_DS, _ES);
-    }
-    
-    return 0;
-}
diff --git a/misc/dos_fs.c b/misc/dos_fs.c
new file mode 100644
index 0000000..e072274
--- /dev/null
+++ b/misc/dos_fs.c
@@ -0,0 +1,756 @@
+/*
+ * DOS-FS
+ * NOV 1993 Erik Bos (erik@(trashcan.)hacktic.nl)
+ *
+ * FindFile by Bob, hacked for dos & unixpaths by Erik.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#ifdef __linux__
+#include <sys/vfs.h>
+#endif
+#ifdef __NetBSD__
+#include <sys/types.h>
+#include <sys/mount.h>
+#endif
+#include <dirent.h>
+#include "windows.h"
+#include "wine.h"
+#include "int21.h"
+
+/*
+ #define DEBUG 
+*/
+#define MAX_OPEN_DIRS 16
+
+extern char WindowsDirectory[256], SystemDirectory[256],TempDirectory[256];
+
+char WindowsPath[256];
+
+void DOS_DeInitFS(void);
+int DOS_SetDefaultDrive(int);
+char *GetDirectUnixFileName(char *);
+void ToDos(char *);
+void ToUnix(char *);
+
+int CurrentDrive = 2;
+
+struct DosDriveStruct {			/*  eg: */
+	char 		*rootdir;	/*  /usr/windows 	*/
+	char 		cwd[256];	/*  /			*/
+	char 		label[13];	/*  DRIVE-A		*/		
+	unsigned int	serialnumber;	/*  ABCD5678		*/
+	int 		disabled;	/*  0			*/
+};
+
+struct DosDriveStruct DosDrives[MAX_DOS_DRIVES];
+
+struct dosdirent DosDirs[MAX_OPEN_DIRS];
+
+void DOS_InitFS(void)
+{
+	int x;
+	char drive[2], temp[256], *ptr;
+
+	GetPrivateProfileString("wine", "windows", "c:\\windows", 
+		WindowsDirectory, sizeof(WindowsDirectory), WINE_INI);
+
+	GetPrivateProfileString("wine", "system", "c:\\windows\\system", 
+		SystemDirectory, sizeof(SystemDirectory), WINE_INI);
+
+	GetPrivateProfileString("wine", "temp", "c:\\windows", 
+		TempDirectory, sizeof(TempDirectory), WINE_INI);
+
+	GetPrivateProfileString("wine", "path", "c:\\windows;c:\\windows\\system", 
+		WindowsPath, sizeof(WindowsPath), WINE_INI);
+
+	ToDos(WindowsDirectory);
+	ToDos(SystemDirectory);
+	ToDos(TempDirectory);
+	ToDos(WindowsPath);
+
+#ifdef DEBUG
+	fprintf(stderr,"wine.ini = %s\n",WINE_INI);
+	fprintf(stderr,"win.ini = %s\n",WIN_INI);
+	fprintf(stderr,"windir = %s\n",WindowsDirectory);
+	fprintf(stderr,"sysdir = %s\n",SystemDirectory);
+	fprintf(stderr,"tempdir = %s\n",TempDirectory);
+	fprintf(stderr,"path = %s\n",WindowsPath);
+#endif
+
+	for (x=0; x!=MAX_DOS_DRIVES; x++) {
+		DosDrives[x].serialnumber = (0xEB0500L | x);
+		
+		drive[0] = 'A' + x;
+		drive[1] = '\0';
+		GetPrivateProfileString("drives", drive, "*", temp, sizeof(temp), WINE_INI);
+		if (!strcmp(temp, "*") || *temp == '\0') {
+			DosDrives[x].rootdir = NULL;		
+			DosDrives[x].cwd[0] = '\0';
+			DosDrives[x].label[0] = '\0';
+			DosDrives[x].disabled = 1;
+			continue;
+		}
+
+		if ((ptr = (char *) malloc(strlen(temp)+1)) == NULL) {
+			fprintf(stderr,"DOSFS: can't malloc for drive info!");
+			continue;
+		}
+			if (temp[strlen(temp)-1] == '/')
+				temp[strlen(temp)] = '\0';
+			DosDrives[x].rootdir = ptr;
+			strcpy(DosDrives[x].rootdir, temp);
+			strcpy(DosDrives[x].cwd, "/windows/");
+			strcpy(DosDrives[x].label, "DRIVE-");
+			strcat(DosDrives[x].label, drive);
+			DosDrives[x].disabled = 0;
+	}
+
+	atexit(DOS_DeInitFS);
+
+	DOS_SetDefaultDrive(2);
+
+	for (x=0; x!=MAX_DOS_DRIVES; x++) {
+		if (DosDrives[x].rootdir != NULL) {
+#ifdef DEBUG
+			fprintf(stderr, "DOSFS: %c: => %-40s %s %s %X %d\n",
+			'A'+x,
+			DosDrives[x].rootdir,
+			DosDrives[x].cwd,
+			DosDrives[x].label,
+			DosDrives[x].serialnumber,
+			DosDrives[x].disabled
+			);	
+#endif
+		}
+	}
+
+	for (x=0; x!=MAX_OPEN_DIRS ; x++)
+		DosDirs[x].inuse = 0;
+
+}
+
+void DOS_DeInitFS(void)
+{
+	int x;
+
+	for (x=0; x!=MAX_DOS_DRIVES ; x++)
+		if (DosDrives[x].rootdir != NULL) {
+#ifdef DEBUG
+
+			fprintf(stderr, "DOSFS: %c: => %s %s %s %X %d\n",
+			'A'+x,
+			DosDrives[x].rootdir,
+			DosDrives[x].cwd,
+			DosDrives[x].label,
+			DosDrives[x].serialnumber,
+			DosDrives[x].disabled
+			);	
+			free(DosDrives[x].rootdir);
+#endif
+		}
+}
+
+WORD DOS_GetEquipment(void)
+{
+	WORD equipment;
+	int diskdrives = 0;
+
+/* borrowed from Ralph Brown's interrupt lists 
+
+		    bits 15-14: number of parallel devices
+		    bit     13: [Conv] Internal modem
+		    bit     12: reserved
+		    bits 11- 9: number of serial devices
+		    bit      8: reserved
+		    bits  7- 6: number of diskette drives minus one
+		    bits  5- 4: Initial video mode:
+				    00b = EGA,VGA,PGA
+				    01b = 40 x 25 color
+				    10b = 80 x 25 color
+				    11b = 80 x 25 mono
+		    bit      3: reserved
+		    bit      2: [PS] =1 if pointing device
+				[non-PS] reserved
+		    bit      1: =1 if math co-processor
+		    bit      0: =1 if diskette available for boot
+*/
+
+	if (DosDrives[0].rootdir != NULL)
+		diskdrives++;
+	if (DosDrives[1].rootdir != NULL)
+		diskdrives++;
+	if (diskdrives)
+		diskdrives--;
+
+	equipment = diskdrives << 6;
+
+	return (equipment);
+}
+
+int DOS_ValidDrive(int drive)
+{
+/*
+#ifdef DEBUG
+	fprintf(stderr,"ValidDrive %c (%d)\n",'A'+drive,drive);
+#endif
+*/
+	if (drive >= MAX_DOS_DRIVES)
+		return 0;
+	if (DosDrives[drive].rootdir == NULL)
+		return 0;
+	if (DosDrives[drive].disabled)
+		return 0;
+
+	return 1;
+}
+
+int DOS_GetDefaultDrive(void)
+{
+#ifdef DEBUG
+	fprintf(stderr,"GetDefaultDrive (%c)\n",'A'+CurrentDrive);
+#endif
+
+	return( CurrentDrive);
+}
+
+int DOS_SetDefaultDrive(int drive)
+{
+#ifdef DEBUG
+	fprintf(stderr,"SetDefaultDrive to %c:\n",'A'+drive);
+#endif
+
+	if (!DOS_ValidDrive(drive))
+		return 1;
+		
+	CurrentDrive = drive;
+}
+
+void ToUnix(char *s)
+{
+	while (*s) {
+	        if (*s == '/')
+		    break;
+ 		if (*s == '\\')
+			*s = '/';		
+		if (isupper(*s))
+			*s = tolower(*s);
+	s++;
+	}
+}
+
+void ToDos(char *s)
+{
+	while (*s) {
+		if (*s == '/')
+			*s = '\\';		
+		if (islower(*s))
+			*s = toupper(*s);
+	s++;
+	}
+}
+
+int DOS_DisableDrive(int drive)
+{
+	if (drive >= MAX_DOS_DRIVES)
+		return 0;
+	if (DosDrives[drive].rootdir == NULL)
+		return 0;
+
+	DosDrives[drive].disabled = 1;
+	return 1;
+}
+
+int DOS_EnableDrive(int drive)
+{
+	if (drive >= MAX_DOS_DRIVES)
+		return 0;
+	if (DosDrives[drive].rootdir == NULL)
+		return 0;
+
+	DosDrives[drive].disabled = 0;
+	return 1;
+}
+
+void GetUnixDirName(char *rootdir, char *name)
+{
+	int filename;
+	char *nameptr, *cwdptr;
+	
+	cwdptr = rootdir + strlen(rootdir);
+	nameptr = name;
+/*
+#ifdef DEBUG
+	fprintf(stderr,"GetUnixDirName: %s <=> %s => ",rootdir, name);
+#endif
+*/	
+	while (*nameptr) {
+		if (*nameptr == '.' & !filename) {
+			nameptr++;
+			if (*nameptr == '\0') {
+				cwdptr--;
+				break;
+			}
+			if (*nameptr == '.') {
+				cwdptr--;
+				while (cwdptr != rootdir) {
+					cwdptr--;
+					if (*cwdptr == '/') {
+						*(cwdptr+1) = '\0';
+						goto next;
+					}
+					
+				}
+				goto next;
+			}
+			if (*nameptr == '\\' || *nameptr == '/') {
+			next:	nameptr++;		
+				filename = 0;
+				continue;
+			}
+		}
+		if (*nameptr == '\\' || *nameptr == '/') {
+			filename = 0;
+			if (nameptr == name)
+				cwdptr = rootdir;
+			*cwdptr++='/';		
+			nameptr++;
+			continue;
+		}
+		filename = 1;
+		*cwdptr++ = *nameptr++;
+	}
+	*cwdptr = '\0';
+
+	ToUnix(rootdir);
+/*
+#ifdef DEBUG
+	fprintf(stderr,"%s\n", rootdir);
+#endif
+*/
+}
+
+char *GetDirectUnixFileName(char *dosfilename)
+{ 
+	/*   a:\windows\system.ini  =>  /dos/windows/system.ini   */
+	
+	int drive;
+	char x, temp[256];
+
+	if (dosfilename[1] == ':') 
+	{
+		drive = (islower(*dosfilename) ? toupper(*dosfilename) : *dosfilename) - 'A';
+		
+		if (!DOS_ValidDrive(drive))		
+			return NULL;
+		else
+			dosfilename+=2;
+	} else
+		drive = CurrentDrive;
+
+	strcpy(temp,DosDrives[drive].rootdir);
+	strcat(temp, DosDrives[drive].cwd);
+	GetUnixDirName(temp + strlen(DosDrives[drive].rootdir), dosfilename);
+
+	ToUnix(temp);
+
+#ifdef DEBUG
+	fprintf(stderr,"GetDirectUnixFileName: %c:%s => %s\n",'A'+ drive, dosfilename, temp);
+#endif
+
+	return(temp);
+}
+
+char *GetUnixFileName(char *dosfilename)
+{
+	char *dirname, *unixname, workingpath[256], temp[256];
+
+	/* check if program specified a path */
+
+	if (*dosfilename == '.' || *dosfilename == '\\')
+		return( GetDirectUnixFileName(dosfilename) );	
+
+	/* nope, lets find it */
+
+#ifdef DEBUG
+	fprintf(stderr,"GetUnixFileName: %s\n",dosfilename);
+#endif
+
+    	strcpy(workingpath, WindowsPath);
+    
+    	for(dirname = strtok(workingpath, ";") ;
+    		dirname != NULL;
+		dirname = strtok(NULL, ";"))
+    	{
+		strcpy(temp,dirname);	
+		if (temp[strlen(temp)-1] != '\\')
+			strcat(temp,"\\");
+		strcat(temp,dosfilename);
+
+#ifdef DEBUG
+		fprintf(stderr,"trying %s\n",temp);
+#endif
+
+		if ( (unixname = GetDirectUnixFileName(temp)) != NULL)
+			return unixname;
+	}
+	puts("FAILED!");
+	return NULL;
+}
+
+char *DOS_GetCurrentDir(int drive, char *dirname)
+{ 
+	/* should return 'windows\system' */
+
+	char temp[256];
+
+	if (!DOS_ValidDrive(drive)) 
+		return 0;
+	
+	strcpy(temp, DosDrives[drive].cwd);
+	ToDos(temp);
+
+	if (temp[strlen(temp)-1] == '\\')
+		temp[strlen(temp)] = '\0';	
+
+#ifdef DEBUG
+	fprintf(stderr,"DOS_GetCWD: %c:\%s",'A'+drive, temp+1);
+#endif
+	return (temp+1);
+}
+
+int DOS_ChangeDir(int drive, char *dirname)
+{
+	if (!DOS_ValidDrive(drive)) 
+		return 0;
+
+	GetUnixDirName(DosDrives[drive].cwd, dirname);
+	strcat(DosDrives[drive].cwd,"/");
+#ifdef DEBUG
+	fprintf(stderr,"DOS_SetCWD: %c:\%s",'A'+drive, DosDrives[drive].cwd);
+#endif
+	return 1;
+}
+
+int DOS_MakeDir(int drive, char *dirname)
+{
+	char temp[256];
+	
+	if (!DOS_ValidDrive(drive))
+		return 0;	
+
+	strcpy(temp, DosDrives[drive].cwd);
+	GetUnixDirName(temp, dirname);
+	strcat(DosDrives[drive].cwd,"/");
+
+	ToUnix(temp);
+	mkdir(temp,0);	
+
+#ifdef DEBUG
+	fprintf(stderr,"DOS_MakeDir: %c:\%s => %s",'A'+drive, dirname, temp);
+#endif
+}
+
+/*
+void main(void)
+{
+	strcpy(DosDrives[0].cwd, "1/2/3/");	
+	
+	puts(DosDrives[0].cwd);
+	ChangeDir(0,"..");
+	puts(DosDrives[0].cwd);
+	
+	ChangeDir(0,"..\\..");
+	puts(DosDrives[0].cwd);
+
+	ChangeDir(0,".");
+	puts(DosDrives[0].cwd);
+
+	ChangeDir(0,"test");
+	puts(DosDrives[0].cwd);
+
+	ChangeDir(0,"\\qwerty\\ab");
+	puts(DosDrives[0].cwd);
+
+	ChangeDir(0,"erik\\.\\bos\\..\\24");
+	puts(DosDrives[0].cwd);
+
+}
+*/
+
+int DOS_GetSerialNumber(int drive, unsigned long *serialnumber)
+{
+	if (!DOS_ValidDrive(drive)) 
+		return 0;
+
+	*serialnumber = DosDrives[drive].serialnumber;
+	return 1;
+}
+
+int DOS_SetSerialNumber(int drive, unsigned long serialnumber)
+{
+	if (!DOS_ValidDrive(drive)) 
+		return 0;
+
+	DosDrives[drive].serialnumber = serialnumber;
+	return 1;
+}
+
+int DOS_GetFreeSpace(int drive, long *size, long *available)
+{
+	struct statfs info;
+
+	if (!DOS_ValidDrive(drive))
+		return 0;
+
+	if (statfs(DosDrives[drive].rootdir, &info) < 0) {
+		fprintf(stderr,"dosfs: cannot do statfs(%s)\n",DosDrives[drive].rootdir);
+		return 0;
+	}
+
+	*size = info.f_bsize * info.f_blocks / 1024;
+	*available = info.f_bavail * info.f_bsize / 1024;
+	
+	return 1;
+}
+
+char *FindFile(char *buffer, int buflen, char *rootname, char **extensions, 
+		char *path)
+{
+    char *workingpath;
+    char *dirname;
+    DIR *d;
+    struct dirent *f;
+    char **e;
+    int rootnamelen;
+    int found = 0;
+
+
+    if (strchr(rootname, '\\') != NULL)
+    {
+	strncpy(buffer, GetDirectUnixFileName(rootname), buflen);
+	ToUnix(buffer);
+	
+#ifdef DEBUG
+fprintf(stderr,"FindFile: %s -> %s\n",rootname,buffer);
+#endif
+
+	return buffer;
+    }
+
+    if (strchr(rootname, '/') != NULL)
+    {
+	strncpy(buffer, rootname, buflen);
+
+#ifdef DEBUG
+fprintf(stderr,"FindFile: %s -> %s\n",rootname,buffer);
+#endif
+
+	return buffer;
+    }
+
+#ifdef DEBUG
+fprintf(stderr,"FindFile: looking for %s\n",rootname);
+#endif
+
+    ToUnix(rootname);
+
+    rootnamelen = strlen(rootname);
+    workingpath = malloc(strlen(path) + 1);
+    if (workingpath == NULL)
+	return NULL;
+    strcpy(workingpath, path);
+
+    for(dirname = strtok(workingpath, ";"); 
+	dirname != NULL;
+	dirname = strtok(NULL, ";"))
+    {
+	if (strchr(dirname, '\\')!=NULL)
+		d = opendir( GetDirectUnixFileName(dirname) );
+	else
+		d = opendir( dirname );
+
+#ifdef DEBUG
+	fprintf(stderr,"in %s\n",dirname);
+#endif
+	
+	if (d != NULL)
+	{
+	    while ((f = readdir(d)) != NULL)
+	    {
+		if (strncasecmp(rootname, f->d_name, rootnamelen) == 0)
+		{
+		    if (extensions == NULL || 
+			strcasecmp(rootname, f->d_name) == 0)
+		    {
+			found = 1;
+		    }
+		    else if (f->d_name[rootnamelen] == '.')
+		    {
+			for (e = extensions; *e != NULL; e++)
+			{
+			    if (strcasecmp(*e, f->d_name + rootnamelen + 1) 
+				== 0)
+			    {
+				found = 1;
+				break;
+			    }
+			}
+		    }
+		    
+		    if (found)
+		    {
+			if (strchr(dirname, '\\')!=NULL)
+				strncpy(buffer, GetDirectUnixFileName(dirname), buflen);
+			 else
+				strncpy(buffer, dirname, buflen);
+
+			if (buffer[strlen(buffer)-1]!='/')			
+				strncat(buffer, "/", buflen - strlen(buffer));
+			
+			strncat(buffer, f->d_name, buflen - strlen(buffer));
+			closedir(d);
+
+			ToUnix(buffer);
+
+			return buffer;
+		    }
+		}
+	    }
+	    closedir(d);
+	}
+    }
+    return NULL;
+}
+
+/**********************************************************************
+ *		WineIniFileName
+ */
+char *WineIniFileName(void)
+{
+    static char *IniName = NULL;
+    char inipath[256];
+    
+    if (IniName)
+	return IniName;
+
+    getcwd(inipath, 256);
+    strcat(inipath, ";");
+    strcat(inipath, getenv("HOME"));
+    strcat(inipath, ";");
+    strcat(inipath, getenv("WINEPATH"));
+
+    IniName = malloc(1024);
+    if (FindFile(IniName, 1024, "wine.ini", NULL, inipath) == NULL)
+    {
+	free(IniName);
+	IniName = NULL;
+	return NULL;
+    }
+    
+    IniName = realloc(IniName, strlen(IniName) + 1);
+
+    ToUnix(IniName);
+	
+    return IniName;
+}
+
+char *WinIniFileName()
+{
+	char name[256];
+	
+	strcpy(name,GetDirectUnixFileName(WindowsDirectory));	
+	strcat(name,"win.ini");
+
+	ToUnix(name);
+	
+	return name;
+}
+
+struct dosdirent *DOS_opendir(char *dosdirname)
+{
+	int x,y;
+	char *unixdirname;
+	char temp[256];
+	
+	for (x=0; x != MAX_OPEN_DIRS && DosDirs[x].inuse; x++)
+		;
+
+	if (x == MAX_OPEN_DIRS)
+		return NULL;
+
+	if ((unixdirname = GetDirectUnixFileName(dosdirname)) == NULL)
+		return NULL;
+
+	strcpy(temp,unixdirname);
+
+
+	y = strlen(temp);
+
+	while (y--)
+	{
+		if (temp[y] == '/') 
+		{
+			temp[y] = '\0';
+			break;
+		}
+	}
+
+	fprintf(stderr,"%s -> %s\n",unixdirname,temp);
+
+	DosDirs[x].inuse = 1;
+	strcpy(DosDirs[x].unixpath, temp);
+
+	if ((DosDirs[x].ds = opendir(temp)) == NULL)
+		return NULL;
+
+	return &DosDirs[x];
+}
+
+
+struct dosdirent *DOS_readdir(struct dosdirent *de)
+{
+	char temp[256];
+	struct dirent *d;
+	struct stat st;
+
+	if (!de->inuse)
+		return NULL;
+	
+	if ((d = readdir(de->ds)) == NULL) 
+	{
+		closedir(de->ds);
+		de->inuse = 0;
+		return de;
+	}
+
+	strcpy(de->filename, d->d_name);
+	if (d->d_reclen > 12)
+		de->filename[12] = '\0';
+	ToDos (de->filename);
+
+	de->attribute = 0x0;
+
+	strcpy(temp,de->unixpath);
+	strcat(temp,"/");
+	strcat(temp,de->filename);
+	ToUnix(temp);
+	stat (temp, &st);
+	if S_ISDIR(st.st_mode)
+		de->attribute |= 0x08;
+
+	return de;
+}
+
+void DOS_closedir(struct dosdirent *de)
+{
+	if (de->inuse)
+	{
+		closedir(de->ds);
+		de->inuse = 0;
+	}
+}
diff --git a/misc/file.c b/misc/file.c
index 559fac0..adc4368 100644
--- a/misc/file.c
+++ b/misc/file.c
@@ -3,98 +3,29 @@
  *
  * File I/O routines for the Linux Wine Project.
  *
- * There are two main parts to this module - first there are the
- * actual emulation functions, and secondly a routine for translating
- * DOS filenames into UNIX style filenames.
- *
- * For each DOS drive letter, we need to store the location in the unix
- * file system to map that drive to, and the current directory for that
- * drive.
- *
- * Finally we need to store the current drive letter in this module.
- *
  * WARNING : Many options of OpenFile are not yet implemeted.
  *
- * 
+ * NOV 93 Erik Bos (erik@(trashcan.)hacktic.nl
+ *		- removed ParseDosFileName, and DosDrive structures.
+ *		- structures dynamically configured at runtime.
+ *		- _lopen modified to use GetUnixFileName.
+ *
+ * DEC 93 Erik Bos (erik@(trashcan.)hacktic.nl)
+ *		- Existing functions modified to use dosfs functions.
+ *		- Added _llseek, _lcreate, GetDriveType, GetTempDrive, 
+ *		  GetWindowsDirectory, GetSystemDirectory, GetTempFileName.
+ *
  ************************************************************************/
 
+#define DEBUG_FILE
+
 #include <windows.h>
-#include <assert.h>
 #include <stdio.h>
 #include <fcntl.h>
-#include <string.h>
 #include <limits.h>
+#include "prototypes.h"
 
-#define OPEN_MAX 256
-
-/***************************************************************************
- This structure stores the infomation needed for a single DOS drive
- ***************************************************************************/
-struct DosDriveStruct
-{
-  char RootDirectory [256];    /* Unix base for this drive letter */
-  char CurrentDirectory [256]; /* Current directory for this drive */
-};
-
-/***************************************************************************
- Table for DOS drives
- ***************************************************************************/
-struct DosDriveStruct DosDrives[] = 
-{
-  {"/mnt/floppy1" , ""},
-  {"/mnt/floppy2" , ""},
-  {"/mnt/HardDisk", "/wine"},
-  {""             , "/wine/Wine"}
-};
-
-#define NUM_DRIVES (sizeof (DosDrives) / sizeof (struct DosDriveStruct))
-
-
-/**************************************************************************
- Global variable to store current drive letter (0 = A, 1 = B etc)
- **************************************************************************/
-int CurrentDrive = 2;
-
-/**************************************************************************
- ParseDOSFileName
-
- Return a fully specified DOS filename with the disk letter separated from
- the path information.
- **************************************************************************/
-void ParseDOSFileName (char *UnixFileName, char *DosFileName, int *Drive)
-{
-  int character;
-
-  for (character = 0; character < strlen(DosFileName); character++)
-    {
-      if (DosFileName[character] == '\\')
-	DosFileName[character] = '/';
-    }
-
-
-  if (DosFileName[1] == ':')
-    {
-      *Drive = DosFileName[0] - 'A';
-      if (*Drive > 26)
-	*Drive = *Drive - 'a' + 'A';
-      DosFileName = DosFileName + 2;
-    }
-  else
-    *Drive = CurrentDrive;
-
-  if (DosFileName[0] == '/')
-    {
-      strcpy (UnixFileName, DosDrives[*Drive].RootDirectory);
-      strcat (UnixFileName, DosFileName);
-      return;
-    }
-
-  strcpy (UnixFileName, DosDrives[*Drive].RootDirectory);
-  strcat (UnixFileName, DosDrives[*Drive].CurrentDirectory);
-  strcat (UnixFileName, "/");
-  strcat (UnixFileName, DosFileName);
-  return;
-}
+char WindowsDirectory[256], SystemDirectory[256], TempDirectory[256];
 
 
 /***************************************************************************
@@ -104,20 +35,26 @@
  ***************************************************************************/
 WORD KERNEL__lopen (LPSTR lpPathName, WORD iReadWrite)
 {
-  char UnixFileName[256];
-  int  Drive;
   int  handle;
+  char *UnixFileName;
 
-  ParseDOSFileName (UnixFileName, lpPathName, &Drive);
+#ifdef DEBUG_FILE
+  fprintf (stderr, "_lopen: open %s\n", lpPathName);
+#endif
 
-
+  if ((UnixFileName = GetUnixFileName(lpPathName)) == NULL)
+  	return HFILE_ERROR;
 
   handle =  open (UnixFileName, iReadWrite);
 
 #ifdef DEBUG_FILE
-  fprintf (stderr, "_lopen: %s (Handle = %d)\n", UnixFileName, handle);
+  fprintf (stderr, "_lopen: open: %s (handle %d)\n", UnixFileName, handle);
 #endif
-  return handle;
+
+  if (handle == -1)
+  	return HFILE_ERROR;
+  else
+  	return handle;
 }
 
 /***************************************************************************
@@ -126,26 +63,37 @@
 WORD KERNEL__lread (WORD hFile, LPSTR lpBuffer, WORD wBytes)
 {
   int result;
+
+#ifdef DEBUG_FILE
+  fprintf(stderr, "_lread: handle %d, buffer = %ld, length = %d\n",
+	  		hFile, lpBuffer, wBytes);
+#endif
   
   result = read (hFile, lpBuffer, wBytes);
-#ifdef DEBUG_FILE
-  fprintf(stderr, "_lread: hFile = %d, lpBuffer = %s, wBytes = %d\n",
-	  hFile, lpBuffer, wBytes);
-#endif
-  return result;
-}
 
+  if (result == -1)
+  	return HFILE_ERROR;
+  else
+  	return result;
+}
 
 /****************************************************************************
  _lwrite
 ****************************************************************************/
 WORD KERNEL__lwrite (WORD hFile, LPSTR lpBuffer, WORD wBytes)
 {
+	int result;
+
 #ifdef DEBUG_FILE
-  fprintf(stderr, "_lwrite: hFile = %d, lpBuffer = %s, wBytes = %d\n",
-	  hFile, lpBuffer, wBytes);
+  fprintf(stderr, "_lwrite: handle %d, buffer = %ld, length = %d\n",
+	  		hFile, lpBuffer, wBytes);
 #endif
-  return write (hFile, lpBuffer, wBytes);
+	result = write (hFile, lpBuffer, wBytes);
+
+	if (result == -1)
+  		return HFILE_ERROR;
+  	else
+  		return result;
 }
 
 /***************************************************************************
@@ -153,6 +101,10 @@
  ***************************************************************************/
 WORD KERNEL__lclose (WORD hFile)
 {
+#ifdef DEBUG_FILE
+  fprintf(stderr, "_lclose: handle %d\n", hFile);
+#endif
+  
   close (hFile);
 }
 
@@ -166,7 +118,9 @@
 {
   int base,flags;
 
+#ifdef DEBUG_FILE
   fprintf(stderr,"Openfile(%s,<struct>,%d) ",lpFileName,wStyle);
+#endif
 
   base=wStyle&0xF;
   flags=wStyle&0xFFF0;
@@ -204,7 +158,148 @@
   return((wNumber<OPEN_MAX) ? wNumber : OPEN_MAX);
 }
 
+/***************************************************************************
+ _llseek
+ ***************************************************************************/
+LONG KERNEL__llseek (WORD hFile, LONG lOffset, int nOrigin)
+{
+	int origin;
+	
+#ifdef DEBUG_FILE
+  fprintf(stderr, "_llseek: handle %d, offset %ld, origin %d\n", hFile, lOffset, nOrigin);
+#endif
 
+	switch (nOrigin) {
+		case 1: origin = SEEK_CUR;
+			break;
+		case 2: origin = SEEK_END;
+			break;
+		default: origin = SEEK_SET;
+			break;
+		}
 
+	return ( lseek(hFile, lOffset, origin) );
+}
 
+/***************************************************************************
+ _lcreate
+ ***************************************************************************/
+LONG KERNEL__lcreate (LPSTR lpszFilename, int fnAttribute)
+{
+	int handle;
+	char *UnixFileName;
 
+#ifdef DEBUG_FILE
+	fprintf(stderr, "_lcreate: filename %s, attributes %d\n",lpszFilename, 
+  			fnAttribute);
+#endif
+
+	if ((UnixFileName = GetUnixFileName(lpszFilename)) == NULL)
+  		return HFILE_ERROR;
+
+	handle =  open (UnixFileName, O_CREAT | O_TRUNC | O_WRONLY );
+
+	if (handle == -1)
+		return HFILE_ERROR;
+	else
+		return handle;
+}
+
+/***************************************************************************
+ GetDriveType
+ ***************************************************************************/
+UINT GetDriveType(int drive)
+{
+
+#ifdef DEBUG_FILE
+	fprintf(stderr,"GetDriveType %c:\n",'A'+drive);
+#endif
+
+	if (!DOS_ValidDrive(drive))
+		return 0;
+
+	if (drive == 0 || drive == 1)
+		return DRIVE_REMOVABLE;
+		 
+	return DRIVE_REMOTE;
+}
+
+/***************************************************************************
+ GetTempDrive
+ ***************************************************************************/
+BYTE GetTempDrive(BYTE chDriveLetter)
+{
+#ifdef DEBUG_FILE
+	fprintf(stderr,"GetTempDrive (%d)\n",chDriveLetter);
+#endif
+	return('C');
+}
+
+/***************************************************************************
+ GetWindowsDirectory
+ ***************************************************************************/
+UINT GetWindowsDirectory(LPSTR lpszSysPath, UINT cbSysPath)
+{
+	if (cbSysPath < strlen(WindowsDirectory)) 
+		*lpszSysPath = 0;
+	else
+		strcpy(lpszSysPath, WindowsDirectory);
+	
+#ifdef DEBUG_FILE
+	fprintf(stderr,"GetWindowsDirectory (%s)\n",lpszSysPath);
+#endif
+
+	return(strlen(lpszSysPath));
+}
+/***************************************************************************
+ GetSystemDirectory
+ ***************************************************************************/
+UINT GetSystemDirectory(LPSTR lpszSysPath, UINT cbSysPath)
+{
+	if (cbSysPath < strlen(SystemDirectory))
+		*lpszSysPath = 0;
+	else
+		strcpy(lpszSysPath, SystemDirectory);
+
+#ifdef DEBUG_FILE
+	fprintf(stderr,"GetSystemDirectory (%s)\n",lpszSysPath);
+#endif
+
+	return(strlen(lpszSysPath));
+}
+/***************************************************************************
+ GetTempFileName
+ ***************************************************************************/
+int GetTempFileName(BYTE bDriveLetter, LPCSTR lpszPrefixString, UINT uUnique, LPSTR lpszTempFileName)
+{
+	int unique;
+	char tempname[256];
+	
+	if (uUnique == 0)
+		unique = time(NULL)%99999L;
+	else
+		unique = uUnique%99999L;
+
+	strcpy(tempname,lpszPrefixString);
+	tempname[3]='\0';
+
+	sprintf(lpszTempFileName,"%s\%s%d.tmp",WindowsDirectory, tempname, 
+		unique);
+
+	ToDos(lpszTempFileName);
+
+#ifdef DEBUG_FILE
+	fprintf(stderr,"GetTempFilename: %c %s %d => %s\n",bDriveLetter,
+		lpszPrefixString,uUnique,lpszTempFileName);
+#endif
+
+	return unique;
+}
+
+/***************************************************************************
+ SetErrorMode
+ ***************************************************************************/
+WORD SetErrorMode(WORD x)
+{
+	fprintf(stderr,"wine: SetErrorMode %4x (ignored)\n",x);
+}
diff --git a/loader/int1a.c b/misc/int1a.c
similarity index 93%
rename from loader/int1a.c
rename to misc/int1a.c
index 2441d77..addfdbc 100644
--- a/loader/int1a.c
+++ b/misc/int1a.c
@@ -51,7 +51,7 @@
 		break;
 
 	default:
-		fprintf(stderr,"Unable to handle int 0x1A AX %x\n", context->sc_eax);
+		fprintf(stderr,"Unable to handle int 0x1A AX %04x\n", context->sc_eax & 0xffffL);
 		return 1;
 	};
 	return 1;
diff --git a/misc/int21.c b/misc/int21.c
new file mode 100644
index 0000000..4d1ae70
--- /dev/null
+++ b/misc/int21.c
@@ -0,0 +1,1227 @@
+#include <time.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+#include <utime.h>
+
+#include "prototypes.h"
+#include "regfunc.h"
+#include "windows.h"
+#include "wine.h"
+#include "int21.h"
+
+static char Copyright[] = "copyright Erik Bos, 1993";
+
+WORD ExtendedError, CodePage = 437;
+BYTE ErrorClass, Action, ErrorLocus;
+
+extern char *TempDirectory;
+
+void Error(int e, int class, int el)
+{
+	ExtendedError = e;
+	ErrorClass = class;
+	Action = SA_Ask4Retry;
+	ErrorLocus = el;
+}
+
+void GetFreeDiskSpace(struct sigcontext_struct *context)
+{
+	int drive;
+	long size,available;
+
+	if (!(EDX & 0xffL))
+		drive = DOS_GetDefaultDrive();
+	else
+		drive = (EDX & 0xffL) - 1;
+	
+	if (!DOS_ValidDrive(drive)) {
+		Error(InvalidDrive, EC_MediaError , EL_Disk);
+		EAX |= 0xffffL;	
+		return;
+	}
+	
+	if (!DOS_GetFreeSpace(drive, &size, &available)) {
+		Error(GeneralFailure, EC_MediaError , EL_Disk);
+		EAX |= 0xffffL;
+		return;
+	}
+
+	EAX = (EAX & 0xffff0000L) | SectorsPerCluster;	
+	ECX = (ECX & 0xffff0000L) | SectorSize;
+
+	EBX = (EBX & 0xffff0000L) | (available / (CX * AX));
+	EDX = (EDX & 0xffff0000L) | (size / (CX * AX));
+	Error (0,0,0);
+}
+
+void SetDefaultDrive(struct sigcontext_struct *context)
+{
+	int drive;
+
+	drive = EDX & 0xffL;
+
+	if (!DOS_ValidDrive(drive)) {
+		Error (InvalidDrive, EC_MediaError, EL_Disk);
+		return;
+	} else {
+		DOS_SetDefaultDrive(drive);
+		EAX = (EAX &0xffffff00L) | MAX_DOS_DRIVES; 
+		Error (0,0,0);
+	}
+}
+
+void GetDefaultDrive(struct sigcontext_struct *context)
+{
+	EAX = (EAX & 0xffffff00L) | DOS_GetDefaultDrive();
+	Error (0,0,0);
+}
+
+void GetDriveAllocInfo(struct sigcontext_struct *context)
+{
+	int drive;
+	long size, available;
+	BYTE mediaID;
+	
+	drive = EDX & 0xffL;
+	
+	if (!DOS_ValidDrive(drive)) {
+		EAX = (EAX & 0xffff0000L) | SectorsPerCluster;	
+		ECX = (ECX & 0xffff0000L) | SectorSize;
+		EDX = (EDX & 0xffff0000L);
+		Error (InvalidDrive, EC_MediaError, EL_Disk);
+		return;
+	}
+
+	if (!DOS_GetFreeSpace(drive, &size, &available)) {
+		Error(GeneralFailure, EC_MediaError , EL_Disk);
+		EAX |= 0xffffL;
+		return;
+	}
+	
+	EAX = (EAX & 0xffff0000L) | SectorsPerCluster;	
+	ECX = (ECX & 0xffff0000L) | SectorSize;
+	EDX = (EDX & 0xffff0000L) | (size / (CX * AX));
+
+	mediaID = 0xf0;
+
+	DS = segment(mediaID);
+	EBX = offset(mediaID);	
+	Error (0,0,0);
+}
+
+void GetDefDriveAllocInfo(struct sigcontext_struct *context)
+{
+	EDX = DOS_GetDefaultDrive();
+	GetDriveAllocInfo(context);
+}
+
+void GetDrivePB(struct sigcontext_struct *context)
+{
+	Error (InvalidDrive, EC_MediaError, EL_Disk);
+	EAX = (EAX & 0xffff0000L) | 0xffL; 
+		/* I'm sorry but I only got networked drives :-) */
+}
+
+void ReadFile(struct sigcontext_struct *context)
+{
+	char *ptr;
+	int size;
+
+	/* can't read from stdout / stderr */
+
+	if ((BX == 1) || (BX == 2)) {
+		Error (InvalidHandle, EL_Unknown, EC_Unknown);
+		EAX = (EAX & 0xffff0000L) | InvalidHandle;
+		SetCflag;
+		return;
+	}
+
+	ptr = (char *) pointer (DS,DX);
+
+	if (BX == 0) {
+		*ptr = EOF;
+		Error (0,0,0);
+		EAX = (EAX & 0xffff0000L) | 1;
+		ResetCflag;
+		return;
+	} else {
+		size = read(BX, ptr, CX);
+		if (size == 0) {
+			Error (ReadFault, EC_Unknown, EL_Unknown);
+			EAX = (EAX & 0xffffff00L) | ExtendedError;
+			return;
+		}
+
+		if (size == -1) {
+			switch (errno) {
+				case EAGAIN:
+					Error (ShareViolation, EC_Temporary, EL_Unknown);
+					break;
+				case EBADF:
+					Error (InvalidHandle, EC_AppError, EL_Unknown);
+					break;
+				default:
+					Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
+					break;
+			}
+			EAX = (EAX & 0xffffff00L) | ExtendedError;
+			SetCflag;
+			return;
+		}		
+		Error (0,0,0);
+		EAX = (EAX & 0xffff0000L) | size;
+		ResetCflag;
+	}
+}
+
+void WriteFile(struct sigcontext_struct *context)
+{
+	char *ptr;
+	int x,size;
+	
+	ptr = (char *) pointer (DS,DX);
+	
+	if (BX == 0) {
+		Error (InvalidHandle, EC_Unknown, EL_Unknown);
+		EAX = InvalidHandle;
+		SetCflag;
+		return;
+	}
+
+	if (BX < 3) {
+		for (x = 0;x != CX;x++) {
+			fprintf(stderr, "%c", *ptr++);
+		}
+		fflush(stderr);
+
+		Error (0,0,0);
+		EAX = (EAX & 0xffffff00L) | CX;
+		ResetCflag;
+	} else {
+		size = write(BX, ptr , CX);
+		if (size == 0) {
+			Error (WriteFault, EC_Unknown, EL_Unknown);
+			EAX = (EAX & 0xffffff00L) | ExtendedError;
+			return;
+		}
+
+		if (size == -1) {
+			switch (errno) {
+				case EAGAIN:
+					Error (ShareViolation, EC_Temporary, EL_Unknown);
+					break;
+				case EBADF:
+					Error (InvalidHandle, EC_AppError, EL_Unknown);
+					break;
+				case ENOSPC:
+					Error (DiskFull, EC_MediaError, EL_Disk);
+					break;				
+				default:
+					Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
+					break;
+			}
+			EAX = (EAX & 0xffffff00L) | ExtendedError;
+			SetCflag;
+			return;
+		}		
+		Error (0,0,0);
+		EAX = (EAX & 0xffff0000L) | size;
+		ResetCflag;
+	}
+}
+
+void UnlinkFile(struct sigcontext_struct *context)
+{
+	if (unlink( GetUnixFileName((char *) pointer(DS,DX)) ) == -1) {
+		switch (errno) {
+			case EACCES:
+			case EPERM:
+			case EROFS:
+				Error (WriteProtected, EC_AccessDenied, EL_Unknown);
+				break;
+			case EBUSY:
+				Error (LockViolation, EC_AccessDenied, EL_Unknown);
+				break;		
+			case EAGAIN:
+				Error (ShareViolation, EC_Temporary, EL_Unknown);
+				break;
+			case ENOENT:
+				Error (FileNotFound, EC_NotFound, EL_Unknown);
+				break;				
+			default:
+				Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
+				break;
+		}
+		EAX = (EAX & 0xffffff00L) | ExtendedError;			SetCflag;
+		return;
+	}		
+	Error (0,0,0);
+	ResetCflag;
+}
+
+void SeekFile(struct sigcontext_struct *context)
+{
+	int handle, status, fileoffset;
+	
+	switch (EAX & 0xffL) {
+		case 1: fileoffset = SEEK_CUR;
+			break;
+		case 2: fileoffset = SEEK_END;
+			break;
+		default:
+		case 0: fileoffset = SEEK_SET;
+			break;
+		}
+	status = lseek(BX, (CX * 0x100) + DX, fileoffset);
+	if (status == -1) {
+		switch (errno) {
+			case EBADF:
+				Error (InvalidHandle, EC_AppError, EL_Unknown);
+				break;
+			case EINVAL:
+				Error (DataInvalid, EC_AppError, EL_Unknown);
+				break;
+			default:
+				Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
+				break;
+		}
+		EAX = (EAX & 0xffffff00L) | ExtendedError;			SetCflag;
+		return;
+	}		
+	Error (0,0,0);
+	ResetCflag;
+}
+
+void GetFileAttributes(struct sigcontext_struct *context)
+{
+	EAX &= 0xfffff00L;
+	ResetCflag;
+}
+
+void SetFileAttributes(struct sigcontext_struct *context)
+{
+	ResetCflag;
+}
+
+void DosIOCTL(struct sigcontext_struct *context)
+{
+	fprintf(stderr,"int21: IOCTL\n");
+	EAX = (EAX & 0xfffff00L) | UnknownUnit;
+	SetCflag;
+}
+
+void DupeFileHandle(struct sigcontext_struct *context)
+{
+	EAX = (EAX & 0xffff0000L) | dup(BX);
+	ResetCflag;
+}
+
+void GetSystemDate(struct sigcontext_struct *context)
+{
+	struct tm *now;
+	time_t ltime;
+
+	ltime = time(NULL);
+	now = localtime(&ltime);
+
+	ECX = (ECX & 0xffff0000L) | now->tm_year + 1900;
+	EDX = (EDX & 0xffff0000L) | ((now->tm_mon + 1) << 8) | now->tm_mday;
+	EAX = (EAX & 0xffff0000L) | now->tm_wday;
+}
+
+void GetSystemTime(struct sigcontext_struct *context)
+{
+	struct tm *now;
+	time_t ltime;
+
+	ltime = time(NULL);
+	now = localtime(&ltime);
+	 
+	ECX = (ECX & 0xffffff00L) | (now->tm_hour << 8) | now->tm_min;
+	EDX = (EDX & 0xffffff00L) | now->tm_sec << 8;
+}
+
+void GetExtendedErrorInfo(struct sigcontext_struct *context)
+{
+	EAX = (EAX & 0xffffff00L) | ExtendedError;
+	EBX = (EBX & 0xffff0000L) | (0x100 * ErrorClass) | Action;
+	ECX = (ECX & 0xffff00ffL) | (0x100 * ErrorLocus);
+}
+
+void GetInDosFlag(struct sigcontext_struct *context)
+{
+	const BYTE InDosFlag = 0;
+	
+	ES  = (ES & 0xffff0000L) | segment(InDosFlag);
+	EBX = (EBX & 0xffff0000L) | offset(InDosFlag);
+}
+
+void CreateFile(struct sigcontext_struct *context)
+{
+	int handle;
+
+	if ((handle = open(GetUnixFileName((char *) pointer(DS,DX)), O_CREAT | O_TRUNC)) == -1) {
+		switch (errno) {
+			case EACCES:
+			case EPERM:
+			case EROFS:
+				Error (WriteProtected, EC_AccessDenied, EL_Unknown);
+				break;
+			case EISDIR:
+				Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown);
+				break;
+			case ENFILE:
+			case EMFILE:
+				Error (NoMoreFiles, EC_MediaError, EL_Unknown);
+			case EEXIST:
+				Error (FileExists, EC_Exists, EL_Disk);
+				break;				
+			case ENOSPC:
+				Error (DiskFull, EC_MediaError, EL_Disk);
+				break;				
+			default:
+				Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
+				break;
+			}			
+		EAX = (EAX & 0xffffff00L) | ExtendedError;
+		SetCflag;
+		return;
+		}			
+	Error (0,0,0);
+	EBX = (EBX & 0xffff0000L) | handle;
+	EAX = (EAX & 0xffffff00L) | NoError;
+	ResetCflag;
+}
+
+void OpenExistingFile(struct sigcontext_struct *context)
+{
+	int handle;
+
+	fprintf(stderr,"OpenExistingFile (%s)\n",(char *) pointer(DS,DX));
+	
+	if ((handle = open(GetUnixFileName((char*) pointer(DS,DX)), O_RDWR)) == -1) {
+		switch (errno) {
+			case EACCES:
+			case EPERM:
+			case EROFS:
+				Error (WriteProtected, EC_AccessDenied, EL_Unknown);
+				break;
+			case EISDIR:
+				Error (CanNotMakeDir, EC_AccessDenied, EL_Unknown);
+				break;
+			case ENFILE:
+			case EMFILE:
+				Error (NoMoreFiles, EC_MediaError, EL_Unknown);
+			case EEXIST:
+				Error (FileExists, EC_Exists, EL_Disk);
+				break;				
+			case ENOSPC:
+				Error (DiskFull, EC_MediaError, EL_Disk);
+				break;				
+			case ENOENT:
+				Error (FileNotFound, EC_MediaError, EL_Disk);
+				break;
+			default:
+				Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
+				break;
+		}
+		EAX = (EAX & 0xffffff00L) | ExtendedError;
+		SetCflag;
+		return;
+	}		
+	Error (0,0,0);
+	EBX = (EBX & 0xffff0000L) | handle;
+	EAX = (EAX & 0xffffff00L) | NoError;
+	ResetCflag;
+}
+
+void CloseFile(struct sigcontext_struct *context)
+{
+	if (close(BX) == -1) {
+		switch (errno) {
+			case EBADF:
+				Error (InvalidHandle, EC_AppError, EL_Unknown);
+				break;
+			default:
+				Error (GeneralFailure, EC_SystemFailure, EL_Unknown);
+				break;
+		}
+		EAX = (EAX & 0xffffff00L) | ExtendedError;
+		SetCflag;
+		return;
+	}		
+	Error (0,0,0);
+	EAX = (EAX & 0xffffff00L) | NoError;
+	ResetCflag;
+}
+
+void RenameFile(struct sigcontext_struct *context)
+{
+	char *newname, *oldname;
+
+	fprintf(stderr,"int21: renaming %s to %s\n",(char *) pointer(DS,DX), pointer(ES,DI) );
+	
+	oldname = GetUnixFileName( (char *) pointer(DS,DX) );
+	newname = GetUnixFileName( (char *) pointer(ES,DI) );
+
+	rename( oldname, newname);
+	ResetCflag;
+}
+
+void GetTrueFileName(struct sigcontext_struct *context)
+{
+	fprintf(stderr,"int21: GetTrueFileName of %s\n",(char *) pointer(DS,SI));
+	
+	strncpy((char *) pointer(ES,DI), (char *) pointer(DS,SI), strlen((char *) pointer(DS,SI)) & 0x7f);
+	ResetCflag;
+}
+
+void MakeDir(struct sigcontext_struct *context)
+{
+	char *dirname;
+
+	fprintf(stderr,"int21: makedir %s\n",(char *) pointer(DS,DX) );
+	
+	if ((dirname = GetUnixFileName( (char *) pointer(DS,DX) ))== NULL) {
+		EAX = (EAX & 0xffffff00L) | CanNotMakeDir;
+		SetCflag;
+		return;
+	}
+
+	if (mkdir(dirname,0) == -1) {
+		EAX = (EAX & 0xffffff00L) | CanNotMakeDir;
+		SetCflag;
+		return;
+	}
+	ResetCflag;
+}
+
+void ChangeDir(struct sigcontext_struct *context)
+{
+	fprintf(stderr,"int21: changedir %s\n",(char *) pointer(DS,DX) );
+
+	DOS_ChangeDir(DOS_GetDefaultDrive(), (char *) pointer (DS,DX));
+}
+
+void RemoveDir(struct sigcontext_struct *context)
+{
+	char *dirname;
+
+	fprintf(stderr,"int21: removedir %s\n",(char *) pointer(DS,DX) );
+
+	if ((dirname = GetUnixFileName( (char *) pointer(DS,DX) ))== NULL) {
+		EAX = (EAX & 0xffffff00L) | CanNotMakeDir;
+		SetCflag;
+		return;
+	}
+
+/*
+	if (strcmp(unixname,DosDrives[drive].CurrentDirectory)) {
+		EAX = (EAX & 0xffffff00L) | CanNotRemoveCwd;
+		SetCflag;
+	}
+*/	
+	if (rmdir(dirname) == -1) {
+		EAX = (EAX & 0xffffff00L) | CanNotMakeDir; 
+		SetCflag;
+	} 
+	ResetCflag;
+}
+
+void AllocateMemory(struct sigcontext_struct *context)
+{
+	char *ptr;
+	
+	fprintf(stderr,"int21: malloc %d bytes\n", BX * 0x10 );
+	
+	if ((ptr = (void *) memalign((size_t) (BX * 0x10), 0x10)) == NULL) {
+		EAX = (EAX & 0xffffff00L) | OutOfMemory;
+		EBX = (EBX & 0xffffff00L); /* out of memory */
+		SetCflag;
+	}
+	fprintf(stderr,"int21: malloc (ptr = %d)\n", ptr );
+
+	EAX = (EAX & 0xffff0000L) | segment((unsigned long) ptr);
+	ResetCflag;
+}
+
+void FreeMemory(struct sigcontext_struct *context)
+{
+	fprintf(stderr,"int21: freemem (ptr = %d)\n", ES * 0x10 );
+
+	free((void *)(ES * 0x10));
+	ResetCflag;
+}
+
+void ResizeMemoryBlock(struct sigcontext_struct *context)
+{
+	char *ptr;
+
+	fprintf(stderr,"int21: realloc (ptr = %d)\n", ES * 0x10 );
+	
+	if ((ptr = (void *) realloc((void *)(ES * 0x10), (size_t) BX * 0x10)) == NULL) {
+		EAX = (EAX & 0xffffff00L) | OutOfMemory;
+		EBX = (EBX & 0xffffff00L); /* out of memory */
+		SetCflag;
+	}
+	EBX = (EBX & 0xffff0000L) | segment((unsigned long) ptr);
+	ResetCflag;
+}
+
+void ExecProgram(struct sigcontext_struct *context)
+{
+	execl("wine", GetUnixFileName((char *) pointer(DS,DX)) );
+}
+
+void GetReturnCode(struct sigcontext_struct *context)
+{
+	EAX = (EAX & 0xffffff00L) | NoError; /* normal exit */
+}
+
+void FindFirst(struct sigcontext_struct *context)
+{
+
+}
+
+void FindNext(struct sigcontext_struct *context)
+{
+
+}
+
+void GetSysVars(struct sigcontext_struct *context)
+{
+	/* return a null pointer, to encourage anyone who tries to
+	   use the pointer */
+
+	ES = 0x0;
+	EBX = (EBX & 0xffff0000L);
+}
+
+void GetFileDateTime(struct sigcontext_struct *context)
+{
+	char *filename;
+	struct stat filestat;
+	struct tm *now;
+
+	if ((filename = GetUnixFileName( (char *) pointer(DS,DX) ))== NULL) {
+		EAX = (EAX & 0xffffff00L) | FileNotFound;
+		SetCflag;
+		return;
+	}
+	stat(filename, &filestat);
+	 	
+	now = localtime (&filestat.st_mtime);
+	
+	ECX = (ECX & 0xffff0000L) | (now->tm_hour * 0x2000) + (now->tm_min * 0x20) + now->tm_sec/2;
+	EDX = (EDX & 0xffff0000L) | (now->tm_year * 0x200) + (now->tm_mon * 0x20) + now->tm_mday;
+
+	ResetCflag;
+}
+
+void SetFileDateTime(struct sigcontext_struct *context)
+{
+	char *filename;
+	struct utimbuf filetime;
+	
+	filename = GetUnixFileName((char *) pointer(DS,DX));
+
+	filetime.actime = 0L;
+	filetime.modtime = filetime.actime;
+
+	utime(filename, &filetime);
+	ResetCflag;
+}
+
+void CreateTempFile(struct sigcontext_struct *context)
+{
+	char *filename, temp[256];
+	int drive, handle;
+	
+	sprintf(temp,"%s\\win%d.tmp",TempDirectory,(int) getpid());
+
+	fprintf(stderr,"CreateTempFile %s\n",temp);
+
+	handle = open(GetUnixFileName(temp), O_CREAT | O_TRUNC | O_RDWR);
+
+	if (handle == -1) {
+		EAX = (EAX & 0xffffff00L) | WriteProtected;
+		SetCflag;
+		return;
+	}
+
+	strcpy((char *) pointer(DS,DX), temp);
+	
+	EAX = (EAX & 0xffff0000L) | handle;
+	ResetCflag;
+}
+
+void CreateNewFile(struct sigcontext_struct *context)
+{
+	int handle;
+	
+	if ((handle = open(GetUnixFileName((char *) pointer(DS,DX)), O_CREAT | O_TRUNC | O_RDWR)) == -1) {
+		EAX = (EAX & 0xffffff00L) | WriteProtected;
+		SetCflag;
+		return;
+	}
+
+	EAX = (EAX & 0xffff0000L) | handle;
+	ResetCflag;
+}
+
+void FileLock(struct sigcontext_struct *context)
+{
+
+}
+
+void GetExtendedCountryInfo(struct sigcontext_struct *context)
+{
+	ResetCflag;
+}
+
+void GetCurrentDirectory(struct sigcontext_struct *context)
+{
+	int drive;
+
+	if ((EDX & 0xffL) == 0)
+		drive = DOS_GetDefaultDrive();
+	else
+		drive = (EDX & 0xffL)-1;
+
+	if (!DOS_ValidDrive(drive)) {
+		EAX = (EAX & 0xffffff00L) | InvalidDrive;
+		SetCflag;
+		return;
+	}
+
+	DOS_GetCurrentDir(drive, (char *) pointer(DS,SI) );
+	ResetCflag;
+}
+
+void GetCurrentPSP(struct sigcontext_struct *context)
+{
+
+}
+
+void GetDiskSerialNumber(struct sigcontext_struct *context)
+{
+	int drive;
+	unsigned long serialnumber;
+	struct diskinfo *ptr;
+	
+	if ((EBX & 0xffL) == 0)
+		drive = DOS_GetDefaultDrive();
+	else
+		drive = (EBX & 0xffL) - 1;
+
+	if (!DOS_ValidDrive(drive)) {
+		EAX = (EAX & 0xffffff00L) |InvalidDrive;
+		SetCflag;
+		return;
+	}
+
+	DOS_GetSerialNumber(drive,&serialnumber);
+
+	ptr = (struct diskinfo *) pointer(DS,SI);
+
+	ptr->infolevel = 0;
+	ptr->serialnumber = serialnumber;
+	strcpy(ptr->label,"NO NAME    ");
+	strcpy(ptr->fstype,"FAT16   ");
+	
+	EAX = (EAX & 0xffffff00L) | NoError;
+	ResetCflag;
+}
+
+void SetDiskSerialNumber(struct sigcontext_struct *context)
+{
+	EAX = (EAX & 0xffffff00L) | 1L;
+	ResetCflag;
+}
+
+/************************************************************************/
+
+int do_int21(struct sigcontext_struct * context){
+	int ah;
+
+	fprintf(stderr,"int21: doing AX=%04x BX=%04x CX=%04x DX=%04x\n",
+		EAX & 0xffffL,EBX & 0xffffL,ECX & 0xffffL,EDX & 0xffffL);
+
+	ah = (EAX >> 8) & 0xffL;
+
+	if (ah == 0x59) {
+		GetExtendedErrorInfo(context);
+		return 1;
+	} else {
+	
+	Error (0,0,0);
+	
+	switch(ah) {
+
+	case 0x00: /* TERMINATE PROGRAM */
+		exit(0);
+
+	case 0x01: /* READ CHARACTER FROM STANDARD INPUT, WITH ECHO */
+	case 0x02: /* WRITE CHARACTER TO STANDARD OUTPUT */
+	case 0x03: /* READ CHARACTER FROM STDAUX  */
+	case 0x04: /* WRITE CHARACTER TO STDAUX */
+	case 0x05: /* WRITE CHARACTER TO PRINTER */
+	case 0x06: /* DIRECT CONSOLE IN/OUTPUT */
+	case 0x07: /* DIRECT CHARACTER INPUT, WITHOUT ECHO */
+	case 0x08: /* CHARACTER INPUT WITHOUT ECHO */
+	case 0x09: /* WRITE STRING TO STANDARD OUTPUT */
+	case 0x0a: /* BUFFERED INPUT */
+	case 0x0b: /* GET STDIN STATUS */
+	case 0x0c: /* FLUSH BUFFER AND READ STANDARD INPUT */
+	case 0x0d: /* DISK BUFFER FLUSH */
+		break;
+
+	/* no FCB support for CP/M hackers */
+	
+	case 0x0f: /* OPEN FILE USING FCB */
+	case 0x10: /* CLOSE FILE USING FCB */
+	case 0x11: /* FIND FIRST MATCHING FILE USING FCB */
+	case 0x12: /* FIND NEXT MATCHING FILE USING FCB */
+	case 0x13: /* DELETE FILE USING FCB */
+	case 0x14: /* SEQUENTIAL READ FROM FCB FILE */		
+	case 0x15: /* SEQUENTIAL WRITE TO FCB FILE */
+	case 0x16: /* CREATE OR TRUNCATE FILE USING FCB */
+	case 0x17: /* RENAME FILE USING FCB */
+	case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
+	case 0x21: /* READ RANDOM RECORD FROM FCB FILE */
+	case 0x22: /* WRITE RANDOM RECORD TO FCB FILE */
+	case 0x23: /* GET FILE SIZE FOR FCB */
+	case 0x24: /* SET RANDOM RECORD NUMBER FOR FCB */
+	case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */
+	case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */
+	case 0x29: /* PARSE FILENAME INTO FCB */
+	case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */
+
+	case 0x2e: /* SET VERIFY FLAG */
+		break;
+
+	case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */
+	case 0x1d:
+	case 0x1e:
+	case 0x20:
+	case 0x2b: /* SET SYSTEM DATE */
+	case 0x2d: /* SET SYSTEM TIME */
+	case 0x37: /* "SWITCHAR" - GET SWITCH CHARACTER
+		      "SWITCHAR" - SET SWITCH CHARACTER
+		      "AVAILDEV" - SPECIFY \DEV\ PREFIX USE */
+	case 0x54: /* GET VERIFY FLAG */
+	case 0x61: /* UNUSED */
+	case 0x6b: /* NULL FUNCTION */
+	        EAX &= 0xff00;
+		break;
+	
+	case 0x67: /* SET HANDLE COUNT */			
+		ResetCflag;
+		break;
+	
+	case 0x0e: /* SELECT DEFAULT DRIVE */
+		SetDefaultDrive(context);
+		break;
+
+	case 0x19: /* GET CURRENT DEFAULT DRIVE */
+		GetDefaultDrive(context);
+		break;
+		
+	case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
+		GetDefDriveAllocInfo(context);
+		break;
+	
+	case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */
+		GetDriveAllocInfo(context);
+		break;
+
+	case 0x1f: /* GET DRIVE PARAMETER BLOCK FOR DEFAULT DRIVE */
+	case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
+		GetDrivePB(context);
+		break;
+		
+	case 0x25: /* SET INTERRUPT VECTOR */
+		/* Ignore any attempt to set a segment vector */
+		return 1;
+
+	case 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */
+		break;
+
+	case 0x2a: /* GET SYSTEM DATE */
+		GetSystemDate(context);
+		break;
+
+	case 0x2c: /* GET SYSTEM TIME */
+		GetSystemTime(context);
+                break;
+
+	case 0x30: /* GET DOS VERSION */
+		fprintf(stderr,"int21: GetDosVersion\n");
+	        EAX = DosVersion; /* Hey folks, this is DOS V3.3! */
+		EBX = 0x0012;     /* 0x123456 is Wine's serial # */
+		ECX = 0x3456;
+		break;
+
+	case 0x31: /* TERMINATE AND STAY RESIDENT */
+		break;
+
+	case 0x33: /* MULTIPLEXED */
+		switch (EAX & 0xff) {
+			case 0x00: /* GET CURRENT EXTENDED BREAK STATE */
+				if (!(EAX & 0xffL)) 
+					EDX &= 0xff00L;
+				break;
+
+			case 0x01: /* SET EXTENDED BREAK STATE */
+				break;		
+		
+			case 0x02: /* GET AND SET EXTENDED CONTROL-BREAK CHECKING STATE */
+				EDX &= 0xff00L;
+				break;
+
+			case 0x05: /* GET BOOT DRIVE */
+				EDX = (EDX & 0xff00L) | 2;
+					/* c: is Wine's bootdrive */
+				break;
+				
+			case 0x06: /* GET TRUE VERSION NUMBER */
+				EBX = DosVersion;
+				EDX = 0x00;
+				break;
+			default:
+				break;			
+		}
+		break;	
+
+	case 0x34: /* GET ADDRESS OF INDOS FLAG */
+		GetInDosFlag(context);
+		break;
+
+	case 0x35: /* GET INTERRUPT VECTOR */
+ 		   /* Return a NULL segment selector - this will bomb, 
+ 		              if anyone ever tries to use it */
+		ES = 0;
+		EBX = 0;
+		break;
+
+	case 0x36: /* GET FREE DISK SPACE */
+		GetFreeDiskSpace(context);
+		break;
+
+	case 0x38: /* GET COUNTRY-SPECIFIC INFORMATION */
+		EAX &= 0xff00;
+		EAX |= 0x02; /* no country support available */
+		SetCflag;
+		break;
+		
+	case 0x39: /* "MKDIR" - CREATE SUBDIRECTORY */
+		MakeDir(context);
+		break;
+	
+	case 0x3a: /* "RMDIR" - REMOVE SUBDIRECTORY */
+		RemoveDir(context);
+		break;
+	
+	case 0x3b: /* "CHDIR" - SET CURRENT DIRECTORY */
+		ChangeDir(context);
+		break;
+	
+	case 0x3c: /* "CREAT" - CREATE OR TRUNCATE FILE */
+		CreateFile(context);
+		break;
+
+	case 0x3d: /* "OPEN" - OPEN EXISTING FILE */
+		OpenExistingFile(context);
+		break;
+	
+	case 0x3e: /* "CLOSE" - CLOSE FILE */
+		CloseFile(context);
+		break;
+	
+	case 0x3f: /* "READ" - READ FROM FILE OR DEVICE */
+		ReadFile(context);
+		break;
+	
+	case 0x40: /* "WRITE" - WRITE TO FILE OR DEVICE */
+		WriteFile(context);
+		break;
+	
+	case 0x41: /* "UNLINK" - DELETE FILE */
+		UnlinkFile(context);
+		break;
+	
+	case 0x42: /* "LSEEK" - SET CURRENT FILE POSITION */
+		SeekFile(context);
+		break;
+			
+	case 0x43: /* FILE ATTRIBUTES */
+		switch (EAX & 0xff) {
+			case 0x00:
+				GetFileAttributes(context);
+				break;
+			case 0x01:
+				SetFileAttributes(context);
+				break;
+		}
+		break;
+		
+	case 0x44: /* IOCTL */
+		DosIOCTL(context);
+		break;
+
+	case 0x45: /* "DUP" - DUPLICATE FILE HANDLE */
+	case 0x46: /* "DUP2", "FORCEDUP" - FORCE DUPLICATE FILE HANDLE */
+		DupeFileHandle(context);
+		break;
+	
+	case 0x47: /* "CWD" - GET CURRENT DIRECTORY */	
+		GetCurrentDirectory(context);
+		EAX = (EAX & 0xffff0000L) | 0x0100; 
+		/* many Microsoft products for Windows rely on this */
+		break;
+	
+	case 0x48: /* ALLOCATE MEMORY */
+		AllocateMemory(context);
+		break;
+	
+	case 0x49: /* FREE MEMORY */
+		FreeMemory(context);
+		break;
+	
+	case 0x4a: /* RESIZE MEMORY BLOCK */
+		ResizeMemoryBlock(context);
+		break;
+	
+	case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
+		ExecProgram(context);
+		break;		
+	
+	case 0x4c: /* "EXIT" - TERMINATE WITH RETURN CODE */
+		fprintf(stderr,"int21: DosExit\n");
+		exit(EAX & 0xff);
+		break;
+		
+	case 0x4d: /* GET RETURN CODE */
+		GetReturnCode(context);
+		break;
+
+	case 0x4e: /* "FINDFIRST" - FIND FIRST MATCHING FILE */
+		FindFirst(context);
+		break;
+
+	case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
+		FindNext(context);
+		break;
+			
+	case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
+		GetSysVars(context);
+		break;
+		
+	case 0x56: /* "RENAME" - RENAME FILE */
+		RenameFile(context);
+		break;
+	
+	case 0x57: /* FILE DATE AND TIME */
+		switch (EAX & 0xff) {
+			case 0x00:
+				GetFileDateTime(context);
+				break;
+			case 0x01:
+				SetFileDateTime(context);
+				break;
+		}
+		break;
+
+	case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */
+		switch (EAX & 0xff) {
+			case 0x00:
+				EAX = (EAX & 0xffffff00L) | 0x01L;
+				break;
+			case 0x02:
+				EAX &= 0xff00L;
+				break;
+			case 0x01:
+			case 0x03:
+				break;
+		}
+		ResetCflag;
+		break;
+	
+	case 0x59: /* GET EXTENDED ERROR INFO */
+		GetExtendedErrorInfo(context);
+		break;
+		
+	case 0x5a: /* CREATE TEMPORARY FILE */
+		CreateTempFile(context);
+		break;
+	
+	case 0x5b: /* CREATE NEW FILE */
+		CreateNewFile(context);
+		break;
+	
+	case 0x5c: /* "FLOCK" - RECORD LOCKING */
+		FileLock(context);
+		break;	
+
+	case 0x5d: /* NETWORK */
+	case 0x5e:
+		EAX = (EAX & 0xfffff00L) | NoNetwork; /* network software not installed */
+		SetCflag;
+		break;
+	
+	case 0x5f: /* NETWORK */
+		switch (EAX & 0xffL) {
+			case 0x07: /* ENABLE DRIVE */
+				if (!DOS_EnableDrive(EDX & 0xffL)) {
+					Error(InvalidDrive, EC_MediaError , EL_Disk);
+					EAX = (EAX & 0xfffff00L) | InvalidDrive;
+					SetCflag;
+					break;
+				} else {
+					ResetCflag;
+					break;
+				}
+			case 0x08: /* DISABLE DRIVE */
+				if (!DOS_DisableDrive(EDX & 0xffL)) {
+					Error(InvalidDrive, EC_MediaError , EL_Disk);
+					EAX = (EAX & 0xfffff00L) | InvalidDrive;
+					SetCflag;
+					break;
+				} else {
+					ResetCflag;
+					break;
+				}
+			default:
+				EAX = (EAX & 0xfffff00L) | NoNetwork; /* network software not installed */
+				SetCflag;
+				break;
+		}
+		break;
+
+	case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */
+		GetTrueFileName(context);
+		break;
+
+	case 0x62: /* GET CURRENT PSP ADDRESS */
+		GetCurrentPSP(context);
+		break;
+	
+	case 0x65: /* GET EXTENDED COUNTRY INFORMATION */
+		GetExtendedCountryInfo(context);
+		break;
+	
+	case 0x66: /* GLOBAL CODE PAGE TABLE */
+		switch (EAX & 0xffL) {
+			case 0x01:
+				EBX = CodePage;
+				EDX = EBX;
+				ResetCflag;
+				break;			
+			case 0x02: 
+				CodePage = EBX;
+				ResetCflag;
+				break;
+		}
+		break;
+
+	case 0x68: /* "FFLUSH" - COMMIT FILE */
+		ResetCflag;
+		break;		
+	
+	case 0x69: /* DISK SERIAL NUMBER */
+		switch (EAX & 0xff) {
+			case 0x00:
+				GetDiskSerialNumber(context);
+				break;			
+			case 0x01: 
+				SetDiskSerialNumber(context);
+				break;
+		}
+		break;
+
+	case 0x6a: /* COMMIT FILE */
+		ResetCflag;
+		break;		
+
+	default:
+		fprintf(stderr,"Unable to handle int 0x21 %x\n", context->sc_eax);
+		return 1;
+	};
+	}
+	return 1;
+}
+
+/********************************************************************/
+
+static void
+GetTimeDate(int time_flag)
+{
+    struct tm *now;
+    time_t ltime;
+    
+    ltime = time(NULL);
+    now = localtime(&ltime);
+    if (time_flag)
+    {
+	_CX = (now->tm_hour << 8) | now->tm_min;
+	_DX = now->tm_sec << 8;
+    }
+    else
+    {
+	_CX = now->tm_year + 1900;
+	_DX = ((now->tm_mon + 1) << 8) | now->tm_mday;
+	_AX &= 0xff00;
+	_AX |= now->tm_wday;
+    }
+#ifdef DEBUG_DOS
+    printf("GetTimeDate: AX = %04x, CX = %04x, DX = %04x\n", _AX, _CX, _DX);
+#endif
+    
+    ReturnFromRegisterFunc();
+    /* Function does not return */
+}
+
+/**********************************************************************
+ *					KERNEL_DOS3Call
+ */
+int KERNEL_DOS3Call()
+{
+    switch ((_AX >> 8) & 0xff)
+    {
+      case 0x30:
+	_AX = 0x0303;
+	ReturnFromRegisterFunc();
+	/* Function does not return */
+	
+      case 0x25:
+      case 0x35:
+	return 0;
+
+      case 0x2a:
+	GetTimeDate(0);
+	/* Function does not return */
+	
+      case 0x2c:
+	GetTimeDate(1);
+	/* Function does not return */
+
+      case 0x4c:
+	exit(_AX & 0xff);
+
+      default:
+	fprintf(stderr, "DOS: AX %04x, BX %04x, CX %04x, DX %04x\n",
+		_AX, _BX, _CX, _DX);
+	fprintf(stderr, "     SP %04x, BP %04x, SI %04x, DI %04x\n",
+		_SP, _BP, _SI, _DI);
+	fprintf(stderr, "     DS %04x, ES %04x\n",
+		_DS, _ES);
+    }
+    
+    return 0;
+}
diff --git a/misc/message.c b/misc/message.c
index 281b012..cde5164 100644
--- a/misc/message.c
+++ b/misc/message.c
@@ -21,6 +21,8 @@
     HWND	hWndNo;
     HWND	hWndCancel;
     HICON	hIcon;
+    RECT	rectIcon;
+    RECT	rectStr;
 } MSGBOX;
 typedef MSGBOX FAR* LPMSGBOX;
 
@@ -46,7 +48,7 @@
     wndClass.cbWndExtra      = 0;
     wndClass.hInstance       = wndPtr->hInstance;
     wndClass.hIcon           = (HICON)NULL;
-    wndClass.hCursor         = LoadCursor((HANDLE)NULL, IDC_ARROW);
+    wndClass.hCursor         = LoadCursor((HANDLE)NULL, IDC_ARROW); 
     wndClass.hbrBackground   = GetStockObject(WHITE_BRUSH);
     wndClass.lpszMenuName    = NULL;
     wndClass.lpszClassName   = "MESSAGEBOX";
@@ -57,7 +59,7 @@
     mb.wType = type;
     mb.ActiveFlg = TRUE;
     hDlg = CreateWindow("MESSAGEBOX", title, 
-    	WS_POPUP | WS_DLGFRAME | WS_VISIBLE, 100, 150, 320, 120,
+    	WS_POPUP | WS_DLGFRAME | WS_VISIBLE, 100, 150, 400, 120,
     	(HWND)NULL, (HMENU)NULL, wndPtr->hInstance, (LPSTR)&mb);
     if (hDlg == 0) return 0;
     while(TRUE) {
@@ -113,47 +115,63 @@
 	    *((LPMSGBOX *)&wndPtr->wExtra[1]) = lpmbInit;
 	    lpmb = MsgBoxGetStorageHeader(hWnd);
 	    GetClientRect(hWnd, &rect);
+	    CopyRect(&lpmb->rectStr, &rect);
+	    lpmb->rectStr.bottom -= 32;
 	    switch(lpmb->wType & MB_TYPEMASK) {
 		case MB_OK :
 		    lpmb->hWndYes = CreateWindow("BUTTON", "&Ok", 
 			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 - 70, rect.bottom - 25, 
+			rect.right / 2 - 30, rect.bottom - 25, 
 			60, 18, hWnd, 1, wndPtr->hInstance, 0L);
 		    break;
 		case MB_OKCANCEL :
 		    lpmb->hWndYes = CreateWindow("BUTTON", "&Ok", 
 			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 - 70, rect.bottom - 25, 
+			rect.right / 2 - 65, rect.bottom - 25, 
 			60, 18, hWnd, 1, wndPtr->hInstance, 0L);
 		    lpmb->hWndCancel = CreateWindow("BUTTON", "&Cancel", 
 			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 + 10, rect.bottom - 25, 
+			rect.right / 2 + 5, rect.bottom - 25, 
 			60, 18, hWnd, 2, wndPtr->hInstance, 0L);
 		    break;
 		case MB_ABORTRETRYIGNORE :
 		    lpmb->hWndYes = CreateWindow("BUTTON", "&Retry", 
 			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 - 70, rect.bottom - 25, 
+			rect.right / 2 - 100, rect.bottom - 25, 
 			60, 18, hWnd, 1, wndPtr->hInstance, 0L);
 		    lpmb->hWndNo = CreateWindow("BUTTON", "&Ignore", 
 			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 + 10, rect.bottom - 25, 
+			rect.right / 2 - 30, rect.bottom - 25, 
 			60, 18, hWnd, 2, wndPtr->hInstance, 0L);
 		    lpmb->hWndCancel = CreateWindow("BUTTON", "&Abort", 
 			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 + 80, rect.bottom - 25, 
+			rect.right / 2 + 40, rect.bottom - 25, 
 			60, 18, hWnd, 3, wndPtr->hInstance, 0L);
 		    break;
 		case MB_YESNO :
 		    lpmb->hWndYes = CreateWindow("BUTTON", "&Yes", 
 			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 - 70, rect.bottom - 25, 
+			rect.right / 2 - 65, rect.bottom - 25, 
 			60, 18, hWnd, 1, wndPtr->hInstance, 0L);
 		    lpmb->hWndNo = CreateWindow("BUTTON", "&No", 
 			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 + 10, rect.bottom - 25, 
+			rect.right / 2 + 5, rect.bottom - 25, 
 			60, 18, hWnd, 2, wndPtr->hInstance, 0L);
 		    break;
+		case MB_YESNOCANCEL :
+		    lpmb->hWndYes = CreateWindow("BUTTON", "&Yes", 
+			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
+			rect.right / 2 - 100, rect.bottom - 25, 
+			60, 18, hWnd, 1, wndPtr->hInstance, 0L);
+		    lpmb->hWndNo = CreateWindow("BUTTON", "&No", 
+			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
+			rect.right / 2 - 30, rect.bottom - 25, 
+			60, 18, hWnd, 2, wndPtr->hInstance, 0L);
+		    lpmb->hWndCancel = CreateWindow("BUTTON", "&Cancel", 
+			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
+			rect.right / 2 + 40, rect.bottom - 25, 
+			60, 18, hWnd, 3, wndPtr->hInstance, 0L);
+		    break;
 		}
 	    switch(lpmb->wType & MB_ICONMASK) {
 		case MB_ICONEXCLAMATION:
@@ -173,16 +191,25 @@
 		    lpmb->hIcon = LoadIcon((HINSTANCE)NULL, IDI_HAND);
 		    break;
 	    	}
+	    if (lpmb->hIcon != (HICON)NULL) {
+		SetRect(&lpmb->rectIcon, 16,
+		    lpmb->rectStr.bottom / 2 - 16, 48,
+		    lpmb->rectStr.bottom / 2 + 16);
+		lpmb->rectStr.left += 64;
+		}
 	    break;
 	case WM_PAINT:
 	    lpmb = MsgBoxGetStorageHeader(hWnd);
-	    GetClientRect(hWnd, &rect);
+	    CopyRect(&rect, &lpmb->rectStr);
 	    hDC = BeginPaint(hWnd, &ps);
-	    if (lpmb->hIcon) DrawIcon(hDC, 30, 20, lpmb->hIcon);
-	    TextOut(hDC, rect.right / 2, 15, 
-	    	lpmb->Title, strlen(lpmb->Title));
-	    TextOut(hDC, rect.right / 2, 30, 
-	    	lpmb->Str, strlen(lpmb->Str));
+	    if (lpmb->hIcon) 
+		DrawIcon(hDC, lpmb->rectIcon.left,
+		    lpmb->rectIcon.top, lpmb->hIcon);
+	    DrawText(hDC, lpmb->Str, -1, &rect, 
+		DT_CALCRECT | DT_CENTER | DT_WORDBREAK);
+	    rect.top = lpmb->rectStr.bottom / 2 - rect.bottom / 2;
+	    rect.bottom = lpmb->rectStr.bottom / 2 + rect.bottom / 2;
+	    DrawText(hDC, lpmb->Str, -1, &rect, DT_CENTER | DT_WORDBREAK);
 	    EndPaint(hWnd, &ps);
 	    break;
 	case WM_DESTROY:
@@ -216,7 +243,7 @@
 			DeleteDC(hMemDC);
 			}
 */
-		    hBitMap = LoadBitmap((HINSTANCE)NULL, "SMILE");
+		    hBitMap = LoadBitmap((HINSTANCE)NULL, "WINELOGO");
 		    GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
 		    printf("bm.bmWidth=%d bm.bmHeight=%d\n",
 		    	bm.bmWidth, bm.bmHeight);  
@@ -234,12 +261,15 @@
 		    break;
 		case 3:
 		    hDC = GetDC(hWnd);
-		    hInst2 = LoadImage("ev3lite.exe", NULL);
+		    hInst2 = LoadImage("ev3lite.exe");
+		    printf("hInst2=%04X\n", hInst2);
 		    hIcon = LoadIcon(hInst2, "EV3LITE");
 		    DrawIcon(hDC, 20, 20, hIcon);
 		    DestroyIcon(hIcon);
-		    hInst2 = LoadImage("sysres.dll", NULL);
-		    hIcon = LoadIcon(hInst2, "WINEICON");
+		    hInst2 = LoadImage("moricons.dll");
+		    printf("hInst2=%04X\n", hInst2);
+		    hIcon = LoadIcon(hInst2, MAKEINTRESOURCE(1));
+/*		    hIcon = LoadIcon(hInst2, "WINEICON"); */
 		    DrawIcon(hDC, 60, 20, hIcon);
 		    DestroyIcon(hIcon);
 		    hIcon = LoadIcon((HINSTANCE)NULL, IDI_EXCLAMATION);
diff --git a/misc/profile.c b/misc/profile.c
index ac50d86..12d12fe 100644
--- a/misc/profile.c
+++ b/misc/profile.c
@@ -3,6 +3,12 @@
  *
  * Copyright (c) 1993 Miguel de Icaza
  *
+ * 1/Dec o Corrected return values for Get*ProfileString
+ *
+ *       o Now, if AppName == NULL in Get*ProfileString it returns a list
+ *            of the KeyNames (as documented in the MS-SDK).
+ *
+ *       o if KeyValue == NULL now clears the value in Get*ProfileString
  */
 
 static char Copyright [] = "Copyright (C) 1993 Miguel de Icaza";
@@ -12,7 +18,8 @@
 #include "windows.h"
 #include "wine.h"
 
-#define INIFILE	GetSystemIniFilename()
+/* #define DEBUG */
+
 #define STRSIZE 255
 #define xmalloc(x) malloc(x)
 #define overflow (next == &CharBuffer [STRSIZE-1])
@@ -63,9 +70,15 @@
     char *next;
     char c;
     
+#ifdef DEBUG
+    printf("Load %s\n", file);
+#endif		
     if ((f = fopen (file, "r"))==NULL)
 	return NULL;
 
+#ifdef DEBUG
+    printf("Loading %s\n", file);
+#endif		
     state = FirstBrace;
     while ((c = getc (f)) != EOF){
 	if (c == '\r')		/* Ignore Carriage Return */
@@ -79,6 +92,9 @@
 		next = CharBuffer;
 		SecHeader->AppName = strdup (CharBuffer);
 		state = IgnoreToEOL;
+#ifdef DEBUG
+		printf("%s: section %s\n", file, CharBuffer);
+#endif		
 	    } else
 		*next++ = c;
 	    break;
@@ -122,6 +138,9 @@
 		SecHeader->Keys->KeyName = strdup (CharBuffer);
 		state = KeyValue;
 		next = CharBuffer;
+#ifdef DEBUG
+		printf("%s:   key %s\n", file, CharBuffer);
+#endif		
 	    } else
 		*next++ = c;
 	    break;
@@ -175,22 +194,36 @@
 	section = New->Section;
 	Current = New;
     }
-    
     /* Start search */
     for (; section; section = section->link){
 	if (strcasecmp (section->AppName, AppName))
 	    continue;
+
+	/* If no key value given, then list all the keys */
+	if ((!AppName) && (!set)){
+	    char *p = ReturnedString;
+	    int left = Size - 1;
+	    int slen;
+	    
+	    for (key = section->Keys; key; key = key->link){
+		strncpy (p, key->KeyName, left);
+		slen = strlen (key->KeyName) + 1;
+		left -= slen+1;
+		p += slen;
+	    }
+	    return left;
+	}
 	for (key = section->Keys; key; key = key->link){
 	    if (strcasecmp (key->KeyName, KeyName))
 		continue;
 	    if (set){
 		free (key->Value);
-		key->Value = strdup (Default);
+		key->Value = strdup (Default ? Default : "");
 		return 1;
 	    }
 	    ReturnedString [Size-1] = 0;
 	    strncpy (ReturnedString, key->Value, Size-1);
-	    return 1;
+	    return 1; 
 	}
 	/* If Getting the information, then don't write the information
 	   to the INI file, need to run a couple of tests with windog */
@@ -222,14 +255,20 @@
 			       LPSTR Default, LPSTR ReturnedString,
 			       short Size, LPSTR FileName)
 {
-    return (GetSetProfile (0, AppName, KeyName, Default, ReturnedString, Size, FileName));
+    int v;
+    
+    v = GetSetProfile (0,AppName,KeyName,Default,ReturnedString,Size,FileName);
+    if (AppName)
+	return strlen (ReturnedString);
+    else
+	return Size - v;
 }
 
 int GetProfileString (LPSTR AppName, LPSTR KeyName, LPSTR Default, 
 		      LPSTR ReturnedString, int Size)
 {
     return GetPrivateProfileString (AppName, KeyName, Default,
-				    ReturnedString, Size, INIFILE);
+				    ReturnedString, Size, WIN_INI);
 }
 
 WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default,
@@ -251,7 +290,7 @@
 
 WORD GetProfileInt (LPSTR AppName, LPSTR KeyName, int Default)
 {
-    return GetPrivateProfileInt (AppName, KeyName, Default, INIFILE);
+    return GetPrivateProfileInt (AppName, KeyName, Default, WIN_INI);
 }
 
 BOOL WritePrivateProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String,
@@ -262,7 +301,7 @@
 
 BOOL WriteProfileString (LPSTR AppName, LPSTR KeyName, LPSTR String)
 {
-    return (WritePrivateProfileString (AppName, KeyName, String, INIFILE));
+    return (WritePrivateProfileString (AppName, KeyName, String, WIN_INI));
 }
 
 static void dump_keys (FILE *profile, TKeys *p)
diff --git a/misc/user.c b/misc/user.c
index 58087ee..501448c 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -6,8 +6,7 @@
 #include "prototypes.h"
 #include "windows.h"
 #include "user.h"
-
-#define DEFAULT_MSG_QUEUE_SIZE  8
+#include "message.h"
 
 #define USER_HEAP_SIZE          0x10000
 
@@ -15,6 +14,9 @@
 MDESC *USER_Heap = NULL;
 
 
+extern BOOL ATOM_Init();
+extern BOOL GDI_Init();
+
 /***********************************************************************
  *           USER_HeapInit
  */
@@ -24,7 +26,6 @@
     s = GetNextSegment( 0, 0x10000 );
     if (s == NULL) return FALSE;
     HEAP_Init( &USER_Heap, s->base_addr, USER_HEAP_SIZE );
-    free(s);
     return TRUE;
 }
 
@@ -37,6 +38,11 @@
 int
 USER_InitApp(int hInstance)
 {
+    int queueSize;
+
+      /* Global atom table initialisation */
+    if (!ATOM_Init()) return 0;
+    
       /* GDI initialisation */
     if (!GDI_Init()) return 0;
 
@@ -54,9 +60,14 @@
 
       /* Initialize dialog manager */
     if (!DIALOG_Init()) return 0;
-    
+
+      /* Create system message queue */
+    queueSize = GetProfileInt( "windows", "TypeAhead", 120 );
+    if (!MSG_CreateSysMsgQueue( queueSize )) return 0;
+
       /* Create task message queue */
-    if (!SetMessageQueue( DEFAULT_MSG_QUEUE_SIZE )) return 0;
+    queueSize = GetProfileInt( "windows", "DefaultQueueSize", 8 );
+    if (!SetMessageQueue( queueSize )) return 0;
         
     return 1;
 }
diff --git a/misc/xt.c b/misc/xt.c
index 8d386ae..a829a5b 100644
--- a/misc/xt.c
+++ b/misc/xt.c
@@ -41,6 +41,8 @@
     XT_display = XtDisplay( topLevelWidget );
     XT_screen  = XtScreen( topLevelWidget );
     
+    DOS_InitFS();
+    Comm_Init();
     _WinMain( argc, argv );
 }
 
@@ -58,12 +60,6 @@
     XBell(XT_display, 100);
 }
 
-WORD RegisterWindowMessage( LPSTR str )
-{
-    printf( "RegisterWindowMessage: '%s'\n", str );
-    return 0xc000;
-}
-
 /***********************************************************************
  *           GetTickCount    (USER.13)
  */
@@ -94,11 +90,10 @@
 {
     printf( "AdjustWindowRect: (%d,%d)-(%d,%d) %d %d\n", rect->left, rect->top,
 	   rect->right, rect->bottom, style, menu );
+#ifdef USE_XLIB
+    rect->right += 8;
+    rect->bottom += 34;
+#endif
 }
 
 
-HMENU CreateMenu() { return 0; }
-
-BOOL AppendMenu( HMENU hmenu, WORD flags, WORD id, LPSTR text ) { return TRUE;}
-
-BOOL DestroyMenu( HMENU hmenu ) { return TRUE; }
diff --git a/objects/Imakefile b/objects/Imakefile
new file mode 100644
index 0000000..458761d
--- /dev/null
+++ b/objects/Imakefile
@@ -0,0 +1,43 @@
+#include "../Wine.tmpl"
+
+MODULE = objects
+
+SRCS = \
+	bitmap.c \
+	brush.c \
+	font.c \
+	gdiobj.c \
+	palette.c \
+	pen.c \
+	dib.c \
+	region.c \
+	text.c \
+	dcvalues.c \
+	clipping.c \
+	bitblt.c \
+	linedda.c \
+	color.c
+
+OBJS = \
+	bitmap.o \
+	brush.o \
+	font.o \
+	gdiobj.o \
+	palette.o \
+	pen.o \
+	dib.o \
+	region.o \
+	text.o \
+	dcvalues.o \
+	clipping.o \
+	bitblt.o \
+	linedda.o \
+	color.o
+
+WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
+DependTarget()
+CleanTarget()
+
+includes::
+
+install::
diff --git a/objects/bitblt.c b/objects/bitblt.c
index 53e9ba1..c4ed6bc 100644
--- a/objects/bitblt.c
+++ b/objects/bitblt.c
@@ -38,10 +38,10 @@
     else rop = (rop & 0x03) | ((rop >> 4) & 0x0c);
     XSetFunction( XT_display, dc->u.x.gc, DC_XROPfunction[rop] );
 
-    x1 = XLPTODP( dc, left );
-    x2 = XLPTODP( dc, left + width );
-    y1 = YLPTODP( dc, top );
-    y2 = YLPTODP( dc, top + height );
+    x1 = dc->w.DCOrgX + XLPTODP( dc, left );
+    x2 = dc->w.DCOrgX + XLPTODP( dc, left + width );
+    y1 = dc->w.DCOrgY + YLPTODP( dc, top );
+    y2 = dc->w.DCOrgY + YLPTODP( dc, top + height );
     XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
 		   MIN(x1,x2), MIN(y1,y2), abs(x2-x1), abs(y2-y1) );
     return TRUE;
@@ -78,14 +78,14 @@
     dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC );
     if (!dcSrc) return FALSE;
 
-    xs1 = XLPTODP( dcSrc, xSrc );
-    xs2 = XLPTODP( dcSrc, xSrc + width );
-    ys1 = YLPTODP( dcSrc, ySrc );
-    ys2 = YLPTODP( dcSrc, ySrc + height );
-    xd1 = XLPTODP( dcDest, xDest );
-    xd2 = XLPTODP( dcDest, xDest + width );
-    yd1 = YLPTODP( dcDest, yDest );
-    yd2 = YLPTODP( dcDest, yDest + height );
+    xs1 = dcSrc->w.DCOrgX + XLPTODP( dcSrc, xSrc );
+    xs2 = dcSrc->w.DCOrgX + XLPTODP( dcSrc, xSrc + width );
+    ys1 = dcSrc->w.DCOrgY + YLPTODP( dcSrc, ySrc );
+    ys2 = dcSrc->w.DCOrgY + YLPTODP( dcSrc, ySrc + height );
+    xd1 = dcDest->w.DCOrgX + XLPTODP( dcDest, xDest );
+    xd2 = dcDest->w.DCOrgX + XLPTODP( dcDest, xDest + width );
+    yd1 = dcDest->w.DCOrgY + YLPTODP( dcDest, yDest );
+    yd2 = dcDest->w.DCOrgY + YLPTODP( dcDest, yDest + height );
 
     if ((abs(xs2-xs1) != abs(xd2-xd1)) || (abs(ys2-ys1) != abs(yd2-yd1)))
 	return FALSE;  /* Should call StretchBlt here */
@@ -109,3 +109,78 @@
     }
     return TRUE;
 }
+
+
+
+/***********************************************************************
+ *           StrechBlt    (GDI.35)
+ */
+BOOL StrechBlt( HDC hdcDest, short xDest, short yDest, short widthDest, short heightDest,
+               HDC hdcSrc, short xSrc, short ySrc, short widthSrc, short heightSrc, DWORD rop )
+{
+    int xs1, xs2, ys1, ys2;
+    int xd1, xd2, yd1, yd2;
+    DC *dcDest, *dcSrc;
+
+/*#ifdef DEBUG_GDI     */
+
+    printf( "StrechBlt: %d %d,%d %dx%d %d %d,%d %dx%d %08x\n",
+           hdcDest, xDest, yDest, widthDest, heightDest, hdcSrc, xSrc, 
+           ySrc, widthSrc, heightSrc, rop );
+/*#endif */
+
+
+
+    if ((rop & 0xcc0000) == ((rop & 0x330000) << 2))
+        return PatBlt( hdcDest, xDest, yDest, widthDest, heightDest, rop );
+
+    printf("here\n");
+
+    rop >>= 16;
+    if ((rop & 0x0f) != (rop >> 4))
+    {
+        printf( "BitBlt: Unimplemented ROP %02x\n", rop );
+        return FALSE;
+    }
+
+    printf("here2\n");
+    
+    dcDest = (DC *) GDI_GetObjPtr( hdcDest, DC_MAGIC );
+    if (!dcDest) return FALSE;
+    dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC );
+    if (!dcSrc) return FALSE;
+
+    xs1 = XLPTODP( dcSrc, xSrc );
+    xs2 = XLPTODP( dcSrc, xSrc + widthSrc );
+    ys1 = YLPTODP( dcSrc, ySrc );
+    ys2 = YLPTODP( dcSrc, ySrc + heightSrc );
+    xd1 = XLPTODP( dcDest, xDest );
+    xd2 = XLPTODP( dcDest, xDest + widthDest );
+    yd1 = YLPTODP( dcDest, yDest );
+    yd2 = YLPTODP( dcDest, yDest + heightDest );
+
+    DC_SetupGCForText( dcDest );
+    XSetFunction( XT_display, dcDest->u.x.gc, DC_XROPfunction[rop & 0x0f] );
+
+    if (dcSrc->w.bitsPerPixel == dcDest->w.bitsPerPixel)
+    {
+            printf("XCopyArea\n");
+        XCopyArea( XT_display, dcSrc->u.x.drawable,
+                   dcDest->u.x.drawable, dcDest->u.x.gc,
+                   MIN(xs1,xs2), MIN(ys1,ys2), abs(xd2-xd1), abs(yd2-yd1),
+                   MIN(xd1,xd2), MIN(yd1,yd2) );
+    }
+    else
+    {
+            printf("XCopyPlane\n");
+        if (dcSrc->w.bitsPerPixel != 1) return FALSE;
+        XCopyPlane( XT_display, dcSrc->u.x.drawable,
+                    dcDest->u.x.drawable, dcDest->u.x.gc,
+                    MIN(xs1,xs2), MIN(ys1,ys2), abs(xd2-xd1), abs(yd2-yd1),
+                    MIN(xd1,xd2), MIN(yd1,yd2), 1 );
+    }
+    return TRUE;
+
+
+}
+
diff --git a/objects/bitmap.c b/objects/bitmap.c
index 9de4c1c..ffec3e9 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -46,6 +46,7 @@
 	if (tmpPixmap)
 	{
 	    bitmapGC[i] = XCreateGC( XT_display, tmpPixmap, 0, NULL );
+	    XSetGraphicsExposures( XT_display, bitmapGC[i], False );
 	    XFreePixmap( XT_display, tmpPixmap );
 	}
 	else bitmapGC[i] = 0;
@@ -355,6 +356,8 @@
 				        DefaultRootWindow( XT_display ), 
 				        bmp->bmWidth, bmp->bmHeight,
 				        bmp->bmBitsPixel );
+    dc->w.DCSizeX      = bmp->bmWidth;
+    dc->w.DCSizeY      = bmp->bmHeight;
     BITMAP_CopyToPixmap( bmp, dc->u.x.drawable,
 			 0, 0, bmp->bmWidth, bmp->bmHeight );
 
diff --git a/objects/clipping.c b/objects/clipping.c
index ec9de9c..5776eb8 100644
--- a/objects/clipping.c
+++ b/objects/clipping.c
@@ -11,9 +11,32 @@
 
 
 /***********************************************************************
+ *           CLIPPING_SetDeviceClipping
+ *
+ * Set the clip region of the physical device.
+ */
+void CLIPPING_SetDeviceClipping( DC * dc )
+{
+    if (dc->w.hGCClipRgn)
+    {
+	RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr(dc->w.hGCClipRgn, REGION_MAGIC);
+	XSetClipMask( XT_display, dc->u.x.gc, obj->region.pixmap );
+	XSetClipOrigin( XT_display, dc->u.x.gc,
+		        dc->w.DCOrgX + obj->region.box.left,
+		        dc->w.DCOrgY + obj->region.box.top );
+    }
+    else
+    {
+	XSetClipMask( XT_display, dc->u.x.gc, None );
+	XSetClipOrigin( XT_display, dc->u.x.gc, dc->w.DCOrgX, dc->w.DCOrgY );
+    }
+}
+
+
+/***********************************************************************
  *           CLIPPING_UpdateGCRegion
  *
- * Update the GC clip region when the ClipRgn of VisRgn have changed.
+ * Update the GC clip region when the ClipRgn or VisRgn have changed.
  */
 static void CLIPPING_UpdateGCRegion( DC * dc )
 {
@@ -36,19 +59,7 @@
 	else
 	    CombineRgn( dc->w.hGCClipRgn, dc->w.hClipRgn, dc->w.hVisRgn, RGN_AND );
     }
-    
-    if (dc->w.hGCClipRgn)
-    {
-	RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr( dc->w.hGCClipRgn, REGION_MAGIC );
-	XSetClipMask( XT_display, dc->u.x.gc, obj->region.pixmap );
-	XSetClipOrigin( XT_display, dc->u.x.gc,
-		        obj->region.box.left, obj->region.box.top );
-    }
-    else
-    {
-	XSetClipMask( XT_display, dc->u.x.gc, None );
-	XSetClipOrigin( XT_display, dc->u.x.gc, 0, 0 );
-    }	
+    CLIPPING_SetDeviceClipping( dc );
 }
 
 
@@ -157,26 +168,40 @@
 int CLIPPING_IntersectRect( DC * dc, HRGN * hrgn, short left, short top,
 			    short right, short bottom, int exclude )
 {
-    HRGN tempRgn, newRgn;
+    HRGN tempRgn = 0, prevRgn = 0, newRgn = 0;
     RGNOBJ *newObj, *prevObj;
     int retval;
 
-    if (!*hrgn) return NULLREGION;
-    if (!(newRgn = CreateRectRgn( 0, 0, 0, 0))) return ERROR;
-    if (!(tempRgn = CreateRectRgn( left, top, right, bottom )))
+    if (!*hrgn)
     {
-	DeleteObject( newRgn );
-	return ERROR;
+	if (!(*hrgn = CreateRectRgn( 0, 0, dc->w.DCSizeX, dc->w.DCSizeY )))
+	    goto Error;
+	prevRgn = *hrgn;
     }
+    if (!(newRgn = CreateRectRgn( 0, 0, 0, 0))) goto Error;
+    if (!(tempRgn = CreateRectRgn( left, top, right, bottom ))) goto Error;
+
     retval = CombineRgn( newRgn, *hrgn, tempRgn, exclude ? RGN_DIFF : RGN_AND);
+    if (retval == ERROR) goto Error;
+
     newObj = (RGNOBJ *) GDI_GetObjPtr( newRgn, REGION_MAGIC );
     prevObj = (RGNOBJ *) GDI_GetObjPtr( *hrgn, REGION_MAGIC );
     if (newObj && prevObj) newObj->header.hNext = prevObj->header.hNext;
     DeleteObject( tempRgn );
-    DeleteObject( *hrgn );
+    if (*hrgn) DeleteObject( *hrgn );
     *hrgn = newRgn;    
     CLIPPING_UpdateGCRegion( dc );
     return retval;
+
+ Error:
+    if (tempRgn) DeleteObject( tempRgn );
+    if (newRgn) DeleteObject( newRgn );
+    if (prevRgn)
+    {
+	DeleteObject( prevRgn );
+	*hrgn = 0;
+    }
+    return ERROR;
 }
 
 
@@ -292,13 +317,9 @@
     if (dc->w.hGCClipRgn) return GetRgnBox( dc->w.hGCClipRgn, rect );
     else
     {
-	Window root;
-	int width, height, x, y, border, depth;
-	XGetGeometry( XT_display, dc->u.x.drawable, &root, &x, &y, 
-		      &width, &height, &border, &depth );
 	rect->top = rect->left = 0;
-	rect->right  = width & 0xffff;
-	rect->bottom = height & 0xffff;
+	rect->right = dc->w.DCSizeX;
+	rect->bottom = dc->w.DCSizeY;
 	return SIMPLEREGION;
     }
 }
diff --git a/objects/dcvalues.c b/objects/dcvalues.c
index b496e2e..73c98aa 100644
--- a/objects/dcvalues.c
+++ b/objects/dcvalues.c
@@ -45,6 +45,8 @@
     MM_TEXT,                /* MapMode */
     0,                      /* DCOrgX */
     0,                      /* DCOrgY */
+    0,                      /* DCSizeX */
+    0,                      /* DCSizeY */
     0,                      /* CursPosX */
     0,                      /* CursPosY */
     0,                      /* WndOrgX */
diff --git a/objects/font.c b/objects/font.c
index 1299a26..10bc76b 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -331,6 +331,36 @@
 }
 
 
+/***********************************************************************/
+
+#define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
+			     (((cs)->rbearing|(cs)->lbearing| \
+			       (cs)->ascent|(cs)->descent) == 0))
+
+/* 
+ * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
+ * character.  If the character is in the column and exists, then return the
+ * appropriate metrics (note that fonts with common per-character metrics will
+ * return min_bounds).  If none of these hold true, try again with the default
+ * char.
+ */
+#define CI_GET_CHAR_INFO(fs,col,def,cs) \
+{ \
+    cs = def; \
+    if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
+	if (fs->per_char == NULL) { \
+	    cs = &fs->min_bounds; \
+	} else { \
+	    cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
+	    if (CI_NONEXISTCHAR(cs)) cs = def; \
+	} \
+    } \
+}
+
+#define CI_GET_DEFAULT_INFO(fs,cs) \
+  CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
+
+
 /***********************************************************************
  *           GetCharWidth    (GDI.350)
  */
@@ -338,8 +368,7 @@
 {
     int i, j;
     XFontStruct *xfont;
-    XCharStruct *charPtr;
-    int default_width;
+    XCharStruct *cs, *def;
 
     DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
     if (!dc) return FALSE;
@@ -353,15 +382,12 @@
 	return TRUE;
     }
 
-    charPtr = xfont->per_char;
-    default_width = (charPtr + xfont->default_char)->width;
+    CI_GET_DEFAULT_INFO(xfont, def);
 	
     for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
     {
-	if (i < xfont->min_char_or_byte2 || i > xfont->max_char_or_byte2)
-	    *(lpBuffer + j) = default_width;
-	else
-	    *(lpBuffer + j) = charPtr->width;
+	CI_GET_CHAR_INFO(xfont, i, def, cs);
+	*(lpBuffer + j) = cs->width;
     }
     return TRUE;
 }
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index 32bb4b8..cc539a4 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -153,7 +153,6 @@
     s = (struct segment_descriptor_s *)GetNextSegment( 0, 0x10000 );
     if (s == NULL) return FALSE;
     HEAP_Init( &GDI_Heap, s->base_addr, GDI_HEAP_SIZE );
-    free(s);
 
       /* Create default palette */
 
@@ -200,8 +199,11 @@
     GDIOBJHDR * obj;
     HANDLE handle = GDI_HEAP_ALLOC( GMEM_MOVEABLE, size );
     if (!handle) return 0;
-    
     obj = (GDIOBJHDR *) GDI_HEAP_ADDR( handle );
+    if (obj == NULL) {
+    	printf("GDI_AllocObject // Error trying to get GDI_HEAD_ADDR !\n");
+    	return 0;
+    	}
     obj->hNext   = 0;
     obj->wMagic  = magic;
     obj->dwCount = ++count;
diff --git a/objects/palette.c b/objects/palette.c
index 3b101b2..511cf3f 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -177,3 +177,21 @@
     memcpy( buffer, &palette->logpalette.palNumEntries, count );
     return count;
 }
+
+
+/***********************************************************************
+ *           SelectPalette    (USER.282)
+ */
+HPALETTE SelectPalette(HDC hDC, HPALETTE hPal, BOOL bForceBackground)
+{
+    return (HPALETTE)NULL;
+}
+
+/***********************************************************************
+ *           RealizePalette    (USER.283)
+ */
+int RealizePalette(HDC hDC)
+{
+    return 0;
+}
+
diff --git a/objects/region.c b/objects/region.c
index 08274ca..3a7b9ef 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -31,6 +31,7 @@
 	XFreePixmap( XT_display, tmpPixmap );
 	if (!regionGC) return FALSE;
 	XSetForeground( XT_display, regionGC, 1 );
+	XSetGraphicsExposures( XT_display, regionGC, False );
 	return TRUE;
     }
     else return FALSE;
diff --git a/objects/text.c b/objects/text.c
index bbb2740..07aef58 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -229,7 +229,8 @@
 	    else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
 	}
 
-	if (!TextOut(hdc, x, y, line, len)) return 0;
+	if (!(flags & DT_CALCRECT))
+	    if (!TextOut(hdc, x, y, line, len)) return 0;
 	if (prefix_offset != -1)
 	{
 	    MoveTo(hdc, x + prefix_x, y + size.cy);
@@ -247,7 +248,7 @@
 	}
     }
     while (strPtr);
-
+    if (flags & DT_CALCRECT) rect->bottom = y;
     return 1;
 }
 
@@ -314,10 +315,10 @@
     {
 	if (dc->w.backgroundMode == TRANSPARENT)
 	    XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc, 
-			 x, y, str, count );
+			 dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
 	else
 	    XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
-			      x, y, str, count );
+			      dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
     }
     else
     {
@@ -340,14 +341,15 @@
 
 	    if (dc->w.backgroundMode == TRANSPARENT)
 		XDrawString( XT_display, dc->u.x.drawable, dc->u.x.gc,
-			     xchar, y, p, 1 );
+			     dc->w.DCOrgX + xchar, dc->w.DCOrgY + y, p, 1 );
 	    else
 	    {
 		XDrawImageString( XT_display, dc->u.x.drawable, dc->u.x.gc,
-				  xchar, y, p, 1 );
+				  dc->w.DCOrgX + xchar, dc->w.DCOrgY + y, p, 1 );
 		XSetForeground( XT_display, dc->u.x.gc, dc->w.backgroundPixel);
 		XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
-			        xchar + charStr->width, y - font->ascent,
+			        dc->w.DCOrgX + xchar + charStr->width,
+			        dc->w.DCOrgY + y - font->ascent,
 			        extraWidth, font->ascent + font->descent );
 		XSetForeground( XT_display, dc->u.x.gc, dc->w.textPixel );
 	    }
@@ -368,7 +370,8 @@
 	XSetLineAttributes( XT_display, dc->u.x.gc, lineWidth,
 			    LineSolid, CapRound, JoinBevel ); 
 	XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		   x, y + linePos, x + info.width, y + linePos );
+		   dc->w.DCOrgX + x, dc->w.DCOrgY + y + linePos,
+		   dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y + linePos );
     }
     if (dc->u.x.font.metrics.tmStruckOut)
     {
@@ -380,7 +383,8 @@
 	XSetLineAttributes( XT_display, dc->u.x.gc, lineAscent + lineDescent,
 			    LineSolid, CapRound, JoinBevel ); 
 	XDrawLine( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		   x, y - lineAscent, x + info.width, y - lineAscent );
+		   dc->w.DCOrgX + x, dc->w.DCOrgY + y - lineAscent,
+		   dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y - lineAscent );
     }
     
     return TRUE;
diff --git a/sysres.dll b/sysres.dll
index 44a53ab..38c7ca9 100755
--- a/sysres.dll
+++ b/sysres.dll
Binary files differ
diff --git a/test/Imakefile b/test/Imakefile
new file mode 100644
index 0000000..d45263d
--- /dev/null
+++ b/test/Imakefile
@@ -0,0 +1,8 @@
+all::
+
+depend::
+
+clean::
+
+includes::
+
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..535cc47
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,347 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+
+# -------------------------------------------------------------------------
+# Makefile generated from "Imake.tmpl" and <Imakefile>
+# $XFree86: mit/config/Imake.tmpl,v 1.17 1993/06/03 15:26:36 dawes Exp $
+# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
+#
+# Platform-specific parameters may be set in the appropriate <vendor>.cf
+# configuration files.  Site-specific parameters should be set in the file
+# site.def.  Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor does not define any unique symbols, you will need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make World" the first time).
+#
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that need to come before
+# the platform-specific parameters - edit site.def to change
+
+# $XFree86: mit/config/site.def,v 1.65 1993/06/04 16:02:47 dawes Exp $
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# obz: changes for making Linux distribution
+
+# -------------------------------------------------------------------------
+# platform-specific configuration parameters - edit x386.cf to change
+
+# $XFree86: mit/config/x386.cf,v 1.90 1993/06/04 16:02:50 dawes Exp $
+# platform:  $XConsortium: x386.cf,v 1.7 91/08/16 19:30:10 gildea Exp $
+
+# -------------------------------------------------------------------------
+# XFree86 version definition
+# $XFree86: mit/config/xf86_vers.def,v 1.5 1993/06/01 09:12:47 dawes Exp $
+
+# -------------------------------------------------------------------------
+# XFree86 version: 1300
+# -------------------------------------------------------------------------
+
+# $XFree86: mit/config/lnuxLib.rules,v 1.2 1993/06/02 13:48:12 dawes Exp $
+
+DLL_BINDIR = /usr/dll/bin
+
+# operating system:  		Linux
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that go after
+# the platform-specific parameters - edit site.def to change
+
+# $XFree86: mit/config/site.def,v 1.65 1993/06/04 16:02:47 dawes Exp $
+# site:  $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# obz: changes for making Linux distribution
+
+            SHELL = 	/bin/sh
+
+              TOP = ../.
+      CURRENT_DIR = ./test
+
+               AR = ar clq
+  BOOTSTRAPCFLAGS =
+               CC = 		gcc
+               AS = as
+
+              LEX = 		flex
+
+             YACC = 		bison -y
+
+         COMPRESS = compress
+              CPP = 		/lib/cpp $(STD_CPP_DEFINES)
+    PREPROCESSCMD = 	/lib/cpp $(STD_CPP_DEFINES)
+          INSTALL = install
+               LD = ld
+             LINT = lint
+      LINTLIBFLAG = -C
+         LINTOPTS = -axz
+               LN = ln -s
+             MAKE = make
+               MV = mv
+               CP = cp
+
+           RANLIB = ranlib
+  RANLIBINSTFLAGS =
+
+               RM = rm -f
+            TROFF = psroff
+         MSMACROS = -ms
+              TBL = tbl
+              EQN = eqn
+     STD_INCLUDES =
+  STD_CPP_DEFINES = -traditional 		-D_POSIX_SOURCE -D_BSD_SOURCE -D_GNU_SOURCE 	-Dlinux
+      STD_DEFINES = 		-D_POSIX_SOURCE -D_BSD_SOURCE -D_GNU_SOURCE 	-Dlinux
+ EXTRA_LOAD_FLAGS =
+  EXTRA_LIBRARIES =
+     OS_LIBRARIES =
+             TAGS = ctags
+
+    SHAREDCODEDEF =
+         SHLIBDEF =
+
+    PROTO_DEFINES = -DFUNCPROTO=11 -DNARROWPROTO
+
+     INSTPGMFLAGS = -s
+
+     INSTBINFLAGS = -m 0755
+     INSTUIDFLAGS = -s -m 4755
+     INSTLIBFLAGS = -m 0644
+     INSTINCFLAGS = -m 0444
+     INSTMANFLAGS = -m 0444
+     INSTDATFLAGS = -m 0444
+    INSTKMEMFLAGS = -s -m 4755
+
+      PROJECTROOT = 	/usr/X386
+
+     TOP_INCLUDES = -I$(INCROOT)
+
+      CDEBUGFLAGS = -O2
+        CCOPTIONS = -m486 -DNO_ASM -fwritable-strings
+    ANSICCOPTIONS =
+
+      ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
+       ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
+           CFLAGS = $(ANSICCOPTIONS) $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+        LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+
+           LDLIBS = $(OS_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+        LDOPTIONS = $(ANSICCOPTIONS) $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) -L$(USRLIBDIR)
+
+   LDCOMBINEFLAGS = 	-r
+      DEPENDFLAGS =
+
+        MACROFILE = x386.cf
+           RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+    IMAKE_DEFINES =
+
+         IRULESRC = $(CONFIGDIR)
+        IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+     ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules 			$(IRULESRC)/Project.tmpl $(IRULESRC)/site.def 			$(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# -------------------------------------------------------------------------
+# X Window System Build Parameters
+# $XFree86: mit/config/Project.tmpl,v 1.13 1993/03/27 03:32:45 dawes Exp $
+# $XConsortium: Project.tmpl,v 1.138.1.1 92/11/11 09:49:19 rws Exp $
+
+_percentC_ = %C
+
+# -------------------------------------------------------------------------
+# X Window System make variables; this need to be coordinated with rules
+
+          PATHSEP = /
+        USRLIBDIR = 	/usr/X386/lib
+           BINDIR = 	/usr/X386/bin
+          INCROOT = 	/usr/X386/include
+     BUILDINCROOT = $(TOP)
+      BUILDINCDIR = $(BUILDINCROOT)/X11
+      BUILDINCTOP = ..
+           INCDIR = $(INCROOT)/X11
+           ADMDIR = /usr/adm
+           LIBDIR = $(USRLIBDIR)/X11
+        CONFIGDIR = $(LIBDIR)/config
+       LINTLIBDIR = $(USRLIBDIR)/lint
+
+          FONTDIR = $(LIBDIR)/fonts
+         XINITDIR = $(LIBDIR)/xinit
+           XDMDIR = $(LIBDIR)/xdm
+           TWMDIR = $(LIBDIR)/twm
+          MANPATH = 	/usr/X386/man
+    MANSOURCEPATH = $(MANPATH)/man
+        MANSUFFIX = 1x
+     LIBMANSUFFIX = 3x
+           MANDIR = 	$(MANSOURCEPATH)1
+        LIBMANDIR = $(MANSOURCEPATH)3
+           NLSDIR = $(LIBDIR)/nls
+        PEXAPIDIR = $(LIBDIR)/PEX
+      XAPPLOADDIR = $(LIBDIR)/app-defaults
+       FONTCFLAGS = -t
+       LINKKITDIR = 	$(USRLIBDIR)/Server
+
+     INSTAPPFLAGS = $(INSTDATFLAGS)
+
+            IMAKE = imake
+           DEPEND = makedepend
+              RGB = rgb
+
+            FONTC = bdftopcf
+
+        MKFONTDIR = mkfontdir
+        MKDIRHIER = 	/bin/sh $(BINDIR)/mkdirhier
+
+        CONFIGSRC = $(TOP)/config
+       DOCUTILSRC = $(TOP)/doc/util
+        CLIENTSRC = $(TOP)/clients
+          DEMOSRC = $(TOP)/demos
+           LIBSRC = $(TOP)/lib
+          FONTSRC = $(TOP)/fonts
+       INCLUDESRC = $(TOP)/X11
+        SERVERSRC = $(TOP)/server
+          UTILSRC = $(TOP)/util
+        SCRIPTSRC = $(UTILSRC)/scripts
+       EXAMPLESRC = $(TOP)/examples
+       CONTRIBSRC = $(TOP)/../contrib
+           DOCSRC = $(TOP)/doc
+           RGBSRC = $(TOP)/rgb
+        DEPENDSRC = $(UTILSRC)/makedepend
+         IMAKESRC = $(CONFIGSRC)
+         XAUTHSRC = $(LIBSRC)/Xau
+          XLIBSRC = $(LIBSRC)/X
+           XMUSRC = $(LIBSRC)/Xmu
+       TOOLKITSRC = $(LIBSRC)/Xt
+       AWIDGETSRC = $(LIBSRC)/Xaw
+       OLDXLIBSRC = $(LIBSRC)/oldX
+      XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+      BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+      BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
+      BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
+     MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
+         FSLIBSRC = $(FONTSRC)/lib/fs
+    FONTSERVERSRC = $(FONTSRC)/server
+     EXTENSIONSRC = $(TOP)/extensions
+         XILIBSRC = $(EXTENSIONSRC)/lib/xinput
+        PEXLIBSRC = $(EXTENSIONSRC)/lib/PEXlib
+      PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
+
+# $XFree86: mit/config/lnuxLib.tmpl,v 1.1 1993/04/16 14:06:06 dawes Exp $
+
+SHLIBLDFLAGS =
+PICFLAGS = -B/usr/dll/jump/
+
+  DEPEXTENSIONLIB =
+     EXTENSIONLIB = -lXext
+
+          DEPXLIB = $(DEPEXTENSIONLIB)
+             XLIB = $(EXTENSIONLIB) -lX11
+
+        DEPXMULIB =
+           XMULIB = -lXmu
+
+      DEPXTOOLLIB =
+         XTOOLLIB = -lXt
+
+        DEPXAWLIB =
+           XAWLIB = -lXaw
+
+        DEPXILIB =
+           XILIB = -lXi
+
+    DEPXTESTLIB =
+       XTESTLIB = -lXtst
+
+        DEPPEXLIB =
+         PEXLIB = -lPEX5
+
+        SOXLIBREV = 3.0.1
+          SOXTREV = 3.0.1
+         SOXAWREV = 3.0.1
+        SOOLDXREV = 3.0.1
+         SOXMUREV = 3.0.1
+        SOXEXTREV = 3.0.1
+      SOXINPUTREV = 3.0.1
+         SOPEXREV = 1.0.1
+
+      DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+         XAUTHLIB = 			 -lXau
+      DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
+         XDMCPLIB = 			 -lXdmcp
+
+       DEPOLDXLIB = $(USRLIBDIR)/liboldX.a
+          OLDXLIB = 			 -loldX
+
+        DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
+           PHIGSLIB = 			 -lphigs
+
+       DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
+          XBSDLIB = 			 -lXbsd
+
+ LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
+         LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
+          LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
+        LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
+          LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
+           LINTXI = $(LINTLIBDIR)/llib-lXi.ln
+          LINTPEX = $(LINTLIBDIR)/llib-lPEX5.ln
+        LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
+
+          DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+         DEPLIBS1 = $(DEPLIBS)
+         DEPLIBS2 = $(DEPLIBS)
+         DEPLIBS3 = $(DEPLIBS)
+
+# -------------------------------------------------------------------------
+# Imake rules for building libraries, programs, scripts, and data files
+# $XFree86: mit/config/Imake.rules,v 1.9 1993/03/23 12:56:27 dawes Exp $
+# rules:  $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+# -------------------------------------------------------------------------
+# start of Imakefile
+
+all::
+
+depend::
+
+clean::
+
+includes::
+
+# -------------------------------------------------------------------------
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+	$(RM_CMD) "#"*
+
+Makefile::
+	-@if [ -f Makefile ]; then set -x; \
+	$(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+	else exit 0; fi
+	$(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+	$(TAGS) -w *.[ch]
+	$(TAGS) -xw *.[ch] > TAGS
+
+# -------------------------------------------------------------------------
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+	@echo "install in $(CURRENT_DIR) done"
+
+install.man::
+	@echo "install.man in $(CURRENT_DIR) done"
+
+install.linkkit::
+	@echo "install.linkkit in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+# -------------------------------------------------------------------------
+# dependencies generated by makedepend
+
diff --git a/test/widget.exe b/test/widget.exe
index 6afbf24..ea5dc2f 100755
--- a/test/widget.exe
+++ b/test/widget.exe
Binary files differ
diff --git a/tools/Imakefile b/tools/Imakefile
new file mode 100644
index 0000000..7b739a1
--- /dev/null
+++ b/tools/Imakefile
@@ -0,0 +1,5 @@
+#include "../Wine.tmpl"
+
+MODULE = tools
+
+SimpleProgramTarget(build)
diff --git a/windows/Imakefile b/windows/Imakefile
new file mode 100644
index 0000000..b16652f
--- /dev/null
+++ b/windows/Imakefile
@@ -0,0 +1,53 @@
+#include "../Wine.tmpl"
+
+MODULE = windows
+
+SRCS = \
+	class.c \
+	dc.c \
+	dce.c \
+	event.c \
+	message.c \
+	win.c \
+	timer.c \
+	graphics.c \
+	clipping.c \
+	mapping.c \
+	painting.c \
+	keyboard.c \
+	utility.c \
+	syscolor.c \
+	defwnd.c \
+	defdlg.c \
+	dialog.c \
+	focus.c \
+	scroll.c
+
+OBJS = \
+	class.o \
+	dc.o \
+	dce.o \
+	event.o \
+	message.o \
+	win.o \
+	timer.o \
+	graphics.o \
+	clipping.o \
+	mapping.o \
+	painting.o \
+	keyboard.o \
+	utility.o \
+	syscolor.o \
+	defwnd.o \
+	defdlg.o \
+	dialog.o \
+	focus.o \
+	scroll.o
+
+WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
+DependTarget()
+CleanTarget()
+
+includes::
+
+install::
diff --git a/windows/Makefile b/windows/Makefile
index 0c5d34a..30570a1 100644
--- a/windows/Makefile
+++ b/windows/Makefile
@@ -2,7 +2,7 @@
 
 OBJS=class.o dc.o dce.o event.o message.o win.o timer.o graphics.o \
     	clipping.o mapping.o painting.o keyboard.o utility.o syscolor.o \
-	defwnd.o defdlg.o dialog.o focus.o scroll.o
+	defwnd.o defdlg.o dialog.o focus.o scroll.o caret.o winpos.o
 
 default: windows.o
 
diff --git a/windows/caret.c b/windows/caret.c
new file mode 100644
index 0000000..eb78dc8
--- /dev/null
+++ b/windows/caret.c
@@ -0,0 +1,250 @@
+/*
+ * Caret functions
+ *
+ * Copyright 1993 David Metcalfe
+ */
+
+static char Copyright[] = "Copyright  David Metcalfe, 1993";
+
+#include <X11/Intrinsic.h>
+
+#include "windows.h"
+
+extern XtAppContext XT_app_context;
+
+typedef struct
+{
+    HWND          hwnd;
+    short         hidden;
+    BOOL          on;
+    short         x;
+    short         y;
+    short         width;
+    short         height;
+    COLORREF      color;
+    WORD          timeout;
+    XtIntervalId  xtid;
+} CARET;
+
+static CARET Caret;
+static BOOL LockCaret;
+
+static void CARET_Callback(XtPointer data, XtIntervalId *xtid);
+static void CARET_HideCaret(CARET *pCaret);
+
+
+/*****************************************************************
+ *               CARET_Callback
+ */
+
+static void CARET_Callback(XtPointer data, XtIntervalId *xtid)
+{
+    CARET *pCaret = (CARET *)data;
+    HDC hdc;
+    HBRUSH hBrush;
+    HRGN rgn;
+
+#ifdef DEBUG_CARET
+    printf("CARET_Callback: LockCaret=%d, hidden=%d, on=%d\n",
+	   LockCaret, pCaret->hidden, pCaret->on);
+#endif
+    if (!LockCaret && (!pCaret->hidden || pCaret->on))
+    {
+	pCaret->on = (pCaret->on ? FALSE : TRUE);
+	hdc = GetDC(pCaret->hwnd);
+	hBrush = CreateSolidBrush(pCaret->color);
+	SelectObject(hdc, (HANDLE)hBrush);
+	SetROP2(hdc, R2_XORPEN);
+	rgn = CreateRectRgn(pCaret->x, pCaret->y, 
+			    pCaret->x + pCaret->width,
+			    pCaret->y + pCaret->height);
+	FillRgn(hdc, rgn, hBrush);
+	DeleteObject((HANDLE)rgn);
+	DeleteObject((HANDLE)hBrush);
+	ReleaseDC(pCaret->hwnd, hdc);
+    }
+
+    pCaret->xtid = XtAppAddTimeOut(XT_app_context, pCaret->timeout,
+				   CARET_Callback, pCaret);
+}
+
+
+/*****************************************************************
+ *               CARET_HideCaret
+ */
+
+static void CARET_HideCaret(CARET *pCaret)
+{
+    HDC hdc;
+    HBRUSH hBrush;
+    HRGN rgn;
+
+    pCaret->on = FALSE;
+    hdc = GetDC(pCaret->hwnd);
+    hBrush = CreateSolidBrush(pCaret->color);
+    SelectObject(hdc, (HANDLE)hBrush);
+    SetROP2(hdc, R2_XORPEN);
+    rgn = CreateRectRgn(pCaret->x, pCaret->y, 
+			pCaret->x + pCaret->width,
+			pCaret->y + pCaret->height);
+    FillRgn(hdc, rgn, hBrush);
+    DeleteObject((HANDLE)rgn);
+    DeleteObject((HANDLE)hBrush);
+    ReleaseDC(pCaret->hwnd, hdc);
+}
+
+
+/*****************************************************************
+ *               CreateCaret          (USER.163)
+ */
+
+void CreateCaret(HWND hwnd, HBITMAP bitmap, short width, short height)
+{
+    if (!hwnd) return;
+
+    /* if cursor already exists, destroy it */
+/*    if (Caret.hwnd)
+	DestroyCaret();
+*/
+    if (bitmap)
+    {
+	printf("CreateCaret: Bitmaps are currently not supported\n");
+	return;
+    }
+
+    if (width)
+	Caret.width = width;
+    else
+	Caret.width = 3;              /* should be SM_CXBORDER */
+
+    if (height)
+	Caret.height = height;
+    else
+	Caret.height = 3;             /* should be SM_CYBORDER */
+
+    Caret.hwnd = hwnd;
+    Caret.hidden = 1;
+    Caret.on = FALSE;
+    Caret.x = 0;
+    Caret.y = 0;
+    Caret.color = GetSysColor(COLOR_WINDOWTEXT);
+    Caret.timeout = 750;
+    LockCaret = FALSE;
+
+    Caret.xtid = XtAppAddTimeOut(XT_app_context, Caret.timeout,
+				 CARET_Callback, &Caret);
+}
+   
+
+/*****************************************************************
+ *               DestroyCaret         (USER.164)
+ */
+
+void DestroyCaret()
+{
+/*    if (!Caret.hwnd) return;
+*/
+    XtRemoveTimeOut(Caret.xtid);
+
+    if (Caret.on)
+	CARET_HideCaret(&Caret);
+
+    Caret.hwnd = 0;          /* cursor marked as not existing */
+}
+
+
+/*****************************************************************
+ *               SetCaretPos          (USER.165)
+ */
+
+void SetCaretPos(short x, short y)
+{
+    HDC hdc;
+    HBRUSH hBrush;
+    HRGN rgn;
+
+    if (!Caret.hwnd) return;
+
+#ifdef DEBUG_CARET
+    printf("SetCaretPos: x=%d, y=%d\n", x, y);
+#endif
+
+    LockCaret = TRUE;
+    if (Caret.on)
+	CARET_HideCaret(&Caret);
+
+    Caret.x = x;
+    Caret.y = y;
+    LockCaret = FALSE;
+}
+
+/*****************************************************************
+ *               HideCaret            (USER.166)
+ */
+
+void HideCaret(HWND hwnd)
+{
+    if (!Caret.hwnd) return;
+    if (hwnd && (Caret.hwnd != hwnd)) return;
+
+    LockCaret = TRUE;
+    if (Caret.on)
+	CARET_HideCaret(&Caret);
+
+    ++Caret.hidden;
+    LockCaret = FALSE;
+}
+
+
+/*****************************************************************
+ *               ShowCaret            (USER.167)
+ */
+
+void ShowCaret(HWND hwnd)
+{
+    if (!Caret.hwnd) return;
+    if (hwnd && (Caret.hwnd != hwnd)) return;
+
+#ifdef DEBUG_CARET
+    printf("ShowCaret: hidden=%d\n", Caret.hidden);
+#endif
+    if (Caret.hidden)
+	--Caret.hidden;
+}
+
+
+/*****************************************************************
+ *               SetCaretBlinkTime    (USER.168)
+ */
+
+void SetCaretBlinkTime(WORD msecs)
+{
+    if (!Caret.hwnd) return;
+
+    Caret.timeout = msecs;
+}
+
+
+/*****************************************************************
+ *               GetCaretBlinkTime    (USER.169)
+ */
+
+WORD GetCaretBlinkTime()
+{
+    if (!Caret.hwnd) return;
+
+    return Caret.timeout;
+}
+
+
+/*****************************************************************
+ *               GetCaretPos          (USER.183)
+ */
+
+void GetCaretPos(LPPOINT pt)
+{
+    if (!Caret.hwnd || !pt) return;
+
+    pt->x = Caret.x;
+    pt->y = Caret.y;
+}
diff --git a/windows/class.c b/windows/class.c
index 23a2c49..4ca2d9f 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -9,6 +9,7 @@
 #include "class.h"
 #include "user.h"
 #include "win.h"
+#include "dce.h"
 
 
 static HCLASS firstClass = 0;
@@ -18,19 +19,50 @@
  *           CLASS_FindClassByName
  *
  * Return a handle and a pointer to the class.
+ * 'ptr' can be NULL if the pointer is not needed.
  */
 HCLASS CLASS_FindClassByName( char * name, CLASS **ptr )
 {
-    HCLASS class = firstClass;
-    while(class)
+    ATOM atom;
+    HCLASS class;
+    CLASS * classPtr;
+
+      /* First search task-specific classes */
+
+    if ((atom = FindAtom( name )) != 0)
     {
-	*ptr = (CLASS *) USER_HEAP_ADDR(class);
-	if (!strcasecmp( (*ptr)->wc.lpszClassName, name )) return class;
-	class = (*ptr)->hNext;
+	for (class = firstClass; (class); class = classPtr->hNext)
+	{
+	    classPtr = (CLASS *) USER_HEAP_ADDR(class);
+	    if (classPtr->wc.style & CS_GLOBALCLASS) continue;
+	    if (classPtr->atomName == atom)
+	    {
+		if (ptr) *ptr = classPtr;
+		return class;
+	    }
+	}
     }
+    
+      /* Then search global classes */
+
+    if ((atom = GlobalFindAtom( name )) != 0)
+    {
+	for (class = firstClass; (class); class = classPtr->hNext)
+	{
+	    classPtr = (CLASS *) USER_HEAP_ADDR(class);
+	    if (!(classPtr->wc.style & CS_GLOBALCLASS)) continue;
+	    if (classPtr->atomName == atom)
+	    {
+		if (ptr) *ptr = classPtr;
+		return class;
+	    }
+	}
+    }
+
     return 0;
 }
 
+
 /***********************************************************************
  *           CLASS_FindClassPtr
  *
@@ -52,37 +84,50 @@
  */
 ATOM RegisterClass( LPWNDCLASS class )
 {
-    CLASS * newClass;
-    HCLASS handle;
+    CLASS * newClass, * prevClassPtr;
+    HCLASS handle, prevClass;
     
 #ifdef DEBUG_CLASS
     printf( "RegisterClass: wndproc=%08x hinst=%d name='%s'\n", 
 	    class->lpfnWndProc, class->hInstance, class->lpszClassName );
 #endif
 
+      /* Check if a class with this name already exists */
+
+    prevClass = CLASS_FindClassByName( class->lpszClassName, &prevClassPtr );
+    if (prevClass)
+    {
+	  /* Class can be created only if it is local and */
+	  /* if the class with the same name is global.   */
+
+	if (class->style & CS_GLOBALCLASS) return 0;
+	if (!(prevClassPtr->wc.style & CS_GLOBALCLASS)) return 0;
+    }
+
+      /* Create class */
+
     handle = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(CLASS)+class->cbClsExtra );
     if (!handle) return 0;
     newClass = (CLASS *) USER_HEAP_ADDR( handle );
     newClass->hNext      = firstClass;
     newClass->wMagic     = CLASS_MAGIC;
-    newClass->atomName   = handle;  /* Should be an atom */
     newClass->cWindows   = 0;  
     newClass->wc         = *class;
 
-    if (newClass->wc.style & CS_CLASSDC)
-	newClass->hdc = CreateDC( "DISPLAY", NULL, NULL, NULL );
-    else newClass->hdc = 0;
+    if (newClass->wc.style & CS_GLOBALCLASS)
+	newClass->atomName = GlobalAddAtom( class->lpszClassName );
+    else newClass->atomName = AddAtom( class->lpszClassName );
 
-      /* Class name should also be set to zero. For now we need the
-       * name because we don't have atoms.
-       */
-    newClass->wc.lpszClassName = (char *)malloc(strlen(class->lpszClassName)+1);
-    strcpy( newClass->wc.lpszClassName, class->lpszClassName );
+    if (newClass->wc.style & CS_CLASSDC)
+	newClass->hdce = DCE_AllocDCE( DCE_CLASS_DC );
+    else newClass->hdce = 0;
+
+      /* Menu name should also be set to zero. */
+    newClass->wc.lpszClassName = NULL;
     
     if (class->cbClsExtra) memset( newClass->wExtra, 0, class->cbClsExtra );
-    
     firstClass = handle;
-    return handle;  /* Should be an atom */
+    return newClass->atomName;
 }
 
 
@@ -118,8 +163,10 @@
     }
 
       /* Delete the class */
-    if (classPtr->hdc) DeleteDC( classPtr->hdc );
+    if (classPtr->hdce) DCE_FreeDCE( classPtr->hdce );
     if (classPtr->wc.hbrBackground) DeleteObject( classPtr->wc.hbrBackground );
+    if (classPtr->wc.style & CS_GLOBALCLASS) GlobalDeleteAtom( classPtr->atomName );
+    else DeleteAtom( classPtr->atomName );
     USER_HEAP_FREE( class );
     return TRUE;
 }
@@ -182,3 +229,34 @@
     *ptr = newval;
     return retval;
 }
+
+
+/***********************************************************************
+ *           GetClassName      (USER.58)
+ */
+int GetClassName(HWND hwnd, LPSTR lpClassName, short maxCount)
+{
+    WND *wndPtr;
+    CLASS *classPtr;
+
+    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+    if (!(classPtr = CLASS_FindClassPtr(wndPtr->hClass))) return 0;
+
+    return (GetAtomName(classPtr->atomName, lpClassName, maxCount));
+}
+
+
+/***********************************************************************
+ *           GetClassInfo      (USER.404)
+ */
+BOOL GetClassInfo(HANDLE hInstance, LPSTR lpClassName, 
+		                    LPWNDCLASS lpWndClass)
+{
+    CLASS *classPtr;
+
+    if (!(CLASS_FindClassByName(lpClassName, &classPtr))) return FALSE;
+    if (hInstance && (hInstance != classPtr->wc.hInstance)) return FALSE;
+
+    memcpy(lpWndClass, &(classPtr->wc), sizeof(WNDCLASS));
+    return TRUE;
+}
diff --git a/windows/clipping.c b/windows/clipping.c
index 2126c28..3c759a6 100644
--- a/windows/clipping.c
+++ b/windows/clipping.c
@@ -10,6 +10,7 @@
 
 #include "windows.h"
 #include "win.h"
+#include "message.h"
 
 
 /***********************************************************************
@@ -34,6 +35,7 @@
 	else CombineRgn( newRgn, wndPtr->hrgnUpdate, hrgn, RGN_OR );
     }
     if (wndPtr->hrgnUpdate) DeleteObject( wndPtr->hrgnUpdate );
+    else MSG_IncPaintCount( wndPtr->hmemTaskQ );
     wndPtr->hrgnUpdate = newRgn;
     if (erase) wndPtr->flags |= WIN_ERASE_UPDATERGN;
 }
@@ -112,17 +114,14 @@
 
     if (rect)
     {
-        if (wndPtr->hrgnUpdate) GetRgnBox( wndPtr->hrgnUpdate, rect );
-	else SetRectEmpty( rect );
-	if (erase && wndPtr->hrgnUpdate)
+	if (wndPtr->hrgnUpdate)
 	{
-	    HDC hdc = GetDC( hwnd );
-	    if (hdc)
-	    {
-		SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
-		ReleaseDC( hwnd, hdc );
-	    }
+	    HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
+	    if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR) return FALSE;
+	    GetRgnBox( hrgn, rect );
+	    DeleteObject( hrgn );
 	}
+	else SetRectEmpty( rect );
     }
     return (wndPtr->hrgnUpdate != 0);
 }
@@ -133,17 +132,34 @@
  */
 int GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
 {
+    HRGN hrgnClip;
+    int retval;
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return ERROR;
 
-    if (erase && wndPtr->hrgnUpdate)
+    if (!wndPtr->hrgnUpdate)
     {
-	HDC hdc = GetDC( hwnd );
-	if (hdc)
-	{
-	    SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
-	    ReleaseDC( hwnd, hdc );
-	}
+	if (!(hrgnClip = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
+	retval = CombineRgn( hrgn, hrgnClip, 0, RGN_COPY );
     }
-    return CombineRgn( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
+    else
+    {
+	hrgnClip = CreateRectRgn( 0, 0,
+			   wndPtr->rectClient.right-wndPtr->rectClient.left,
+			   wndPtr->rectClient.bottom-wndPtr->rectClient.top );
+	if (!hrgnClip) return ERROR;
+	retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, hrgnClip, RGN_AND );
+	if (erase)
+	{
+	    HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
+			      DCX_INTERSECTRGN | DCX_USESTYLE );
+	    if (hdc)
+	    {
+		SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
+		ReleaseDC( hwnd, hdc );
+	    }
+	}	
+    }
+    DeleteObject( hrgnClip );
+    return retval;
 }
diff --git a/windows/dc.c b/windows/dc.c
index 1a65b41..4224b3a 100644
--- a/windows/dc.c
+++ b/windows/dc.c
@@ -7,7 +7,6 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 #include <stdlib.h>
-#include <X11/Intrinsic.h>
 
 #include "gdi.h"
 
@@ -17,6 +16,8 @@
 
 extern const WIN_DC_INFO DCVAL_defaultValues;
 
+extern void CLIPPING_SetDeviceClipping( DC * dc );  /* in objects/clipping.c */
+
 
   /* ROP code to GC function conversion */
 const int DC_XROPfunction[16] =
@@ -100,18 +101,8 @@
     SelectObject( hdc, dc->w.hBrush );
     SelectObject( hdc, dc->w.hFont );
     
-    if (dc->w.hGCClipRgn)
-    {
-	RGNOBJ *obj = (RGNOBJ *) GDI_GetObjPtr(dc->w.hGCClipRgn, REGION_MAGIC);
-	XSetClipMask( XT_display, dc->u.x.gc, obj->region.pixmap );
-	XSetClipOrigin( XT_display, dc->u.x.gc,
-		        obj->region.box.left, obj->region.box.top );
-    }
-    else
-    {
-	XSetClipMask( XT_display, dc->u.x.gc, None );
-	XSetClipOrigin( XT_display, dc->u.x.gc, 0, 0 );
-    }
+    XSetGraphicsExposures( XT_display, dc->u.x.gc, False );
+    CLIPPING_SetDeviceClipping( dc );
 }
 
 
@@ -145,8 +136,11 @@
 	XSetFillStyle( XT_display, dc->u.x.gc,
 		       (dc->w.backgroundMode == OPAQUE) ? 
 		          FillOpaqueStippled : FillStippled );
-    XSetTSOrigin( XT_display, dc->u.x.gc, dc->w.brushOrgX, dc->w.brushOrgY );
+    XSetTSOrigin( XT_display, dc->u.x.gc, dc->w.DCOrgX + dc->w.brushOrgX,
+		  dc->w.DCOrgY + dc->w.brushOrgY );
     XSetFunction( XT_display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
+    XSetFillRule( XT_display, dc->u.x.gc, 
+		 (dc->w.polyFillMode == WINDING) ? WindingRule : EvenOddRule );
     return 1;
 }
 
@@ -226,8 +220,7 @@
     if (dc->w.hVisRgn)
     {
 	newdc->w.hVisRgn = CreateRectRgn( 0, 0, 0, 0 );
-	CombineRgn( newdc->w.hVisRgn, dc->w.hVisRgn, 0, RGN_COPY );
-	
+	CombineRgn( newdc->w.hVisRgn, dc->w.hVisRgn, 0, RGN_COPY );	
     }
     newdc->w.hGCClipRgn = 0;
     return handle;
@@ -255,7 +248,7 @@
     dc->w.flags &= ~DC_SAVED;
     DC_SetDeviceInfo( hdc, dc );
     SelectClipRgn( hdc, dcs->w.hClipRgn );
-    SelectVisRgn( hdc, dcs->w.hGCClipRgn );
+    SelectVisRgn( hdc, dcs->w.hVisRgn );
 }
 
 
@@ -337,6 +330,8 @@
     dc->w.devCaps      = displayDevCaps;
     dc->w.planes       = displayDevCaps->planes;
     dc->w.bitsPerPixel = displayDevCaps->bitsPixel;
+    dc->w.DCSizeX      = displayDevCaps->horzRes;
+    dc->w.DCSizeY      = displayDevCaps->vertRes;
 
     DC_SetDeviceInfo( handle, dc );
 
@@ -372,6 +367,8 @@
     dc->w.planes       = 1;
     dc->w.bitsPerPixel = 1;
     dc->w.devCaps      = displayDevCaps;
+    dc->w.DCSizeX      = 1;
+    dc->w.DCSizeY      = 1;
 
     SelectObject( handle, BITMAP_hbitmapMemDC );
     DC_SetDeviceInfo( handle, dc );
diff --git a/windows/dce.c b/windows/dce.c
index aaea4b0..7b24f1d 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -23,6 +23,53 @@
 
 
 /***********************************************************************
+ *           DCE_AllocDCE
+ *
+ * Allocate a new DCE.
+ */
+HANDLE DCE_AllocDCE( DCE_TYPE type )
+{
+    DCE * dce;
+    HANDLE handle = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(DCE) );
+    if (!handle) return 0;
+    dce = (DCE *) USER_HEAP_ADDR( handle );
+    if (!(dce->hdc = CreateDC( "DISPLAY", NULL, NULL, NULL )))
+    {
+	USER_HEAP_FREE( handle );
+	return 0;
+    }
+    dce->hwndCurrent = 0;
+    dce->type  = type;
+    dce->inUse = (type != DCE_CACHE_DC);
+    dce->xOrigin = 0;
+    dce->yOrigin = 0;
+    dce->hNext = firstDCE;
+    firstDCE = handle;
+    return handle;
+}
+
+
+/***********************************************************************
+ *           DCE_FreeDCE
+ */
+void DCE_FreeDCE( HANDLE hdce )
+{
+    DCE * dce;
+    HANDLE *handle = &firstDCE;
+
+    if (!(dce = (DCE *) USER_HEAP_ADDR( hdce ))) return;
+    while (*handle && (*handle != hdce))
+    {
+	DCE * prev = (DCE *) USER_HEAP_ADDR( *handle );	
+	handle = &prev->hNext;
+    }
+    if (*handle == hdce) *handle = dce->hNext;
+    DeleteDC( dce->hdc );
+    USER_HEAP_FREE( hdce );
+}
+
+
+/***********************************************************************
  *           DCE_Init
  */
 void DCE_Init()
@@ -33,84 +80,133 @@
         
     for (i = 0; i < NB_DCE; i++)
     {
-	handle = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(DCE) );
-	if (!handle) return;
-	dce = (DCE *) USER_HEAP_ADDR( handle );
-	dce->hdc = CreateDC( "DISPLAY", NULL, NULL, NULL );
-	if (!dce->hdc)
-	{
-	    USER_HEAP_FREE( handle );
-	    return;
-	}
-	dce->hwndCurrent = 0;
-	dce->flags = 0;
-	dce->inUse = FALSE;
-	dce->xOrigin = 0;
-	dce->yOrigin = 0;
-	dce->hNext = firstDCE;
-	firstDCE = handle;
+	if (!(handle = DCE_AllocDCE( DCE_CACHE_DC ))) return;
+	dce = (DCE *) USER_HEAP_ADDR( handle );	
 	if (!defaultDCstate) defaultDCstate = GetDCState( dce->hdc );
     }
 }
 
 
 /***********************************************************************
+ *           GetDCEx    (USER.359)
+ */
+/* Unimplemented flags: DCX_CLIPSIBLINGS, DCX_LOCKWINDOWUPDATE, DCX_PARENTCLIP
+ */
+HDC GetDCEx( HWND hwnd, HRGN hrgnClip, DWORD flags )
+{
+    HANDLE hdce;
+    HDC hdc = 0;
+    DCE * dce;
+    DC * dc;
+    WND * wndPtr;
+    
+    if (hwnd)
+    {
+	if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+    }
+    else wndPtr = NULL;
+
+    if (flags & DCX_USESTYLE)
+    {
+	/* Not sure if this is the real meaning of the DCX_USESTYLE flag... */
+	flags &= ~(DCX_CACHE | DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS);
+	if (wndPtr)
+	{
+	    if (!(wndPtr->flags & (WIN_CLASS_DC | WIN_OWN_DC)))
+		flags |= DCX_CACHE;
+	    if (wndPtr->dwStyle & WS_CLIPCHILDREN) flags |= DCX_CLIPCHILDREN;
+	    if (wndPtr->dwStyle & WS_CLIPSIBLINGS) flags |= DCX_CLIPSIBLINGS;
+	}
+	else flags |= DCX_CACHE;
+    }
+
+    if (flags & DCX_CACHE)
+    {
+	for (hdce = firstDCE; (hdce); hdce = dce->hNext)
+	{
+	    if (!(dce = (DCE *) USER_HEAP_ADDR( hdce ))) return 0;
+	    if ((dce->type == DCE_CACHE_DC) && (!dce->inUse)) break;
+	}
+    }
+    else hdce = wndPtr->hdce;
+
+    if (!hdce) return 0;
+    dce = (DCE *) USER_HEAP_ADDR( hdce );
+    dce->hwndCurrent = hwnd;
+    dce->inUse       = TRUE;
+    hdc = dce->hdc;
+    
+      /* Initialize DC */
+    
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+
+    if (wndPtr)
+    {
+	dc->u.x.drawable = wndPtr->window;
+	if (flags & DCX_WINDOW)
+	{
+	    dc->w.DCOrgX  = 0;
+	    dc->w.DCOrgY  = 0;
+	    dc->w.DCSizeX = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
+	    dc->w.DCSizeY = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
+	}
+	else
+	{
+	    dc->w.DCOrgX  = wndPtr->rectClient.left - wndPtr->rectWindow.left;
+	    dc->w.DCOrgY  = wndPtr->rectClient.top - wndPtr->rectWindow.top;
+	    dc->w.DCSizeX = wndPtr->rectClient.right - wndPtr->rectClient.left;
+	    dc->w.DCSizeY = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
+	    IntersectVisRect( hdc, 0, 0, dc->w.DCSizeX, dc->w.DCSizeY );
+	}	
+    }
+    else dc->u.x.drawable = DefaultRootWindow( XT_display );
+
+    if (flags & DCX_CLIPCHILDREN)
+	XSetSubwindowMode( XT_display, dc->u.x.gc, ClipByChildren );
+    else XSetSubwindowMode( XT_display, dc->u.x.gc, IncludeInferiors);
+
+    if ((flags & DCX_INTERSECTRGN) || (flags & DCX_EXCLUDERGN))
+    {
+	HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
+	if (hrgn)
+	{
+	    if (CombineRgn( hrgn, InquireVisRgn(hdc), hrgnClip,
+			    (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF ))
+		SelectVisRgn( hdc, hrgn );
+	    DeleteObject( hrgn );
+	}
+    }
+
+#ifdef DEBUG_DC
+    printf( "GetDCEx(%d,%d,0x%x): returning %d\n", hwnd, hrgnClip, flags, hdc);
+#endif
+    return hdc;
+}
+
+
+/***********************************************************************
  *           GetDC    (USER.66)
  */
 HDC GetDC( HWND hwnd )
 {
-    HANDLE hdce;
-    HDC hdc = 0;
-    DCE * dce;
-    DC * dc;
-    WND * wndPtr = NULL;
-    CLASS * classPtr;
-    
+    return GetDCEx( hwnd, 0, DCX_USESTYLE );
+}
+
+
+/***********************************************************************
+ *           GetWindowDC    (USER.67)
+ */
+HDC GetWindowDC( HWND hwnd )
+{
+    int flags = DCX_CACHE | DCX_WINDOW;
     if (hwnd)
     {
+	WND * wndPtr;
 	if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-	if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
-	if (wndPtr->hdc) hdc = wndPtr->hdc;
-	else if (classPtr->hdc) hdc = classPtr->hdc;
+	if (wndPtr->dwStyle & WS_CLIPCHILDREN) flags |= DCX_CLIPCHILDREN;
+	if (wndPtr->dwStyle & WS_CLIPSIBLINGS) flags |= DCX_CLIPSIBLINGS;
     }
-        
-    if (!hdc)
-    {
-	for (hdce = firstDCE; (hdce); hdce = dce->hNext)
-	{
-	    dce = (DCE *) USER_HEAP_ADDR( hdce );
-	    if (!dce) return 0;
-	    if (!dce->inUse) break;
-	}
-	if (!hdce) return 0;
-	dce->hwndCurrent = hwnd;
-	dce->inUse       = TRUE;
-	hdc = dce->hdc;
-    }
-    
-      /* Initialize DC */
-    
-    if (!(dc = (DC *) GDI_GetObjPtr( dce->hdc, DC_MAGIC ))) return 0;
-
-    if (wndPtr)
-    {
-	dc->u.x.drawable = XtWindow( wndPtr->winWidget );
-    	dc->u.x.widget   = wndPtr->winWidget;
-	if (wndPtr->dwStyle & WS_CLIPCHILDREN)
-	    XSetSubwindowMode( XT_display, dc->u.x.gc, ClipByChildren );
-	else XSetSubwindowMode( XT_display, dc->u.x.gc, IncludeInferiors);
-    }
-    else
-    {
-	dc->u.x.drawable = DefaultRootWindow( XT_display );
-	dc->u.x.widget   = 0;
-	XSetSubwindowMode( XT_display, dc->u.x.gc, IncludeInferiors );    
-    }   
-
-#ifdef DEBUG_WIN
-    printf( "GetDC(%d): returning %d\n", hwnd, hdc );
-#endif
-    return hdc;
+    return GetDCEx( hwnd, 0, flags );
 }
 
 
@@ -119,33 +215,23 @@
  */
 int ReleaseDC( HWND hwnd, HDC hdc )
 {
-    HANDLE hdce, next;
+    HANDLE hdce;
     DCE * dce;
-    WND * wndPtr = NULL;
-    CLASS * classPtr;
     
-#ifdef DEBUG_WIN
+#ifdef DEBUG_DC
     printf( "ReleaseDC: %d %d\n", hwnd, hdc );
 #endif
         
-    if (hwnd)
-    {
-	if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-	if (wndPtr->hdc && (wndPtr->hdc == hdc)) return 1;
-	if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 0;
-	if (classPtr->hdc && (classPtr->hdc == hdc)) return 1;
-    }
-
     for (hdce = firstDCE; (hdce); hdce = dce->hNext)
     {
 	if (!(dce = (DCE *) USER_HEAP_ADDR( hdce ))) return 0;
 	if (dce->inUse && (dce->hdc == hdc)) break;
     }
 
-    if (hdce)
+    if (dce->type == DCE_CACHE_DC)
     {
 	SetDCState( dce->hdc, defaultDCstate );
 	dce->inUse = FALSE;
-    }    
+    }
     return (hdce != 0);
 }
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 3d3a280..e2f9a39 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -6,24 +6,27 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
+#ifndef USE_XLIB
 #include <X11/Intrinsic.h>
 #include <X11/Shell.h>
+#endif
 
 #include "windows.h"
 #include "win.h"
 #include "class.h"
 #include "user.h"
 
+extern Display * XT_display;
 
 /***********************************************************************
  *           DefWindowProc   (USER.107)
  */
 LONG DefWindowProc( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
 {
-    WND * wndPtr;
     CLASS * classPtr;
     LPSTR textPtr;
     int len;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
     
 #ifdef DEBUG_MESSAGE
     printf( "DefWindowProc: %d %d %d %08x\n", hwnd, msg, wParam, lParam );
@@ -34,24 +37,57 @@
     case WM_NCCREATE:
 	{
 	    CREATESTRUCT * createStruct = (CREATESTRUCT *)lParam;
-	    wndPtr = WIN_FindWndPtr(hwnd);
 	    if (createStruct->lpszName)
 	    {
 		  /* Allocate space for window text */
 		wndPtr->hText = USER_HEAP_ALLOC(GMEM_MOVEABLE, 
-					strlen(createStruct->lpszName) + 1);
+					strlen(createStruct->lpszName) + 2);
 		textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
 		strcpy(textPtr, createStruct->lpszName);
+		*(textPtr + strlen(createStruct->lpszName) + 1) = '\0';
+		                         /* for use by edit control */
 	    }
 	    return 1;
 	}
+
+    case WM_NCCALCSIZE:
+	{
+#ifdef USE_XLIB
+	    NCCALCSIZE_PARAMS *params = (NCCALCSIZE_PARAMS *)lParam;
+	    if (wndPtr->dwStyle & WS_CHILD)
+	    {
+		if (wndPtr->dwStyle & WS_BORDER)
+		{
+		    params->rgrc[0].left   += 1; /* SM_CXBORDER */
+		    params->rgrc[0].top    += 1; /* SM_CYBORDER */
+		    params->rgrc[0].right  -= 1; /* SM_CXBORDER */
+		    params->rgrc[0].bottom -= 1; /* SM_CYBORDER */
+		}
+	    }
+	    else
+	    {
+		params->rgrc[0].left   += 4; /* SM_CXFRAME */
+		params->rgrc[0].top    += 30; /* SM_CYFRAME+SM_CYCAPTION */
+		params->rgrc[0].right  -= 4; /* SM_CXFRAME */
+		params->rgrc[0].bottom -= 4; /* SM_CYFRAME */
+		if (wndPtr->dwStyle & WS_VSCROLL)
+		{
+		    params->rgrc[0].right -= 16; /* SM_CXVSCROLL */
+		}
+		if (wndPtr->dwStyle & WS_HSCROLL)
+		{
+		    params->rgrc[0].bottom += 16;  /* SM_CYHSCROLL */
+		}
+	    }
+#endif
+	    return 0;
+	}
 	
     case WM_CREATE:
 	return 0;
 
     case WM_NCDESTROY:
 	{
-	    wndPtr = WIN_FindWndPtr(hwnd);
 	    if (wndPtr->hText) USER_HEAP_FREE(wndPtr->hText);
 	    wndPtr->hText = 0;
 	    return 0;
@@ -69,10 +105,23 @@
 	DestroyWindow( hwnd );
 	return 0;
 
+    case WM_WINDOWPOSCHANGED:
+	{
+	    WINDOWPOS * winPos = (WINDOWPOS *)lParam;
+	    if (!(winPos->flags & SWP_NOMOVE))
+		SendMessage( hwnd, WM_MOVE, 0,
+		             MAKELONG( wndPtr->rectClient.left,
+				       wndPtr->rectClient.top ));
+	    if (!(winPos->flags & SWP_NOSIZE))
+		SendMessage( hwnd, WM_SIZE, SIZE_RESTORED,
+		   MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
+			    wndPtr->rectClient.bottom-wndPtr->rectClient.top));
+	    return 0;
+	}
+
     case WM_ERASEBKGND:
     case WM_ICONERASEBKGND:
 	{
-	    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 1;
 	    if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return 1;
 	    if (!classPtr->wc.hbrBackground) return 1;
 	    FillWindow( GetParent(hwnd), hwnd, (HDC)wParam,
@@ -106,7 +155,6 @@
 	{
 	    if (wParam)
 	    {
-		wndPtr = WIN_FindWndPtr(hwnd);
 		if (wndPtr->hText)
 		{
 		    textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
@@ -123,7 +171,6 @@
 
     case WM_GETTEXTLENGTH:
 	{
-	    wndPtr = WIN_FindWndPtr(hwnd);
 	    if (wndPtr->hText)
 	    {
 		textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
@@ -134,7 +181,6 @@
 
     case WM_SETTEXT:
 	{
-	    wndPtr = WIN_FindWndPtr(hwnd);
 	    if (wndPtr->hText)
 		USER_HEAP_FREE(wndPtr->hText);
 
@@ -142,10 +188,18 @@
 					    strlen((LPSTR)lParam) + 1);
 	    textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
 	    strcpy(textPtr, (LPSTR)lParam);
+#ifdef USE_XLIB
+	    XStoreName( XT_display, wndPtr->window, textPtr );
+#else
 	    if (wndPtr->shellWidget)
 		XtVaSetValues( wndPtr->shellWidget, XtNtitle, textPtr, NULL );
+#endif
 	    return (0L);
 	}
+    case WM_SETCURSOR:
+	if (wndPtr->hCursor != (HCURSOR)NULL)
+	    SetCursor(wndPtr->hCursor);
+	return 0L;
     }
     return 0;
 }
diff --git a/windows/dialog.c b/windows/dialog.c
index 108c964..83a0389 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -8,7 +8,6 @@
 
 #include "windows.h"
 #include "dialog.h"
-#include "prototypes.h"
 #include "win.h"
 
 
@@ -149,25 +148,19 @@
     HWND hwnd = 0;
     HANDLE hres, hmem;
     LPCSTR data;
-    int size;
 
 #ifdef DEBUG_DIALOG
     printf( "CreateDialogParam: %d,'%s',%d,%p,%d\n",
 	    hInst, dlgTemplate, owner, dlgProc, param );
 #endif
-    
-#if 0
-    if (!(hres = FindResource( hInst, dlgTemplate, RT_DIALOG ))) return 0;
+     
+      /* FIXME: MAKEINTRESOURCE should be replaced by RT_DIALOG */
+    if (!(hres = FindResource( hInst, dlgTemplate, MAKEINTRESOURCE(0x8005) )))
+	return 0;
     if (!(hmem = LoadResource( hInst, hres ))) return 0;
     if (!(data = LockResource( hmem ))) hwnd = 0;
     else hwnd = CreateDialogIndirectParam(hInst, data, owner, dlgProc, param);
     FreeResource( hmem );
-#else
-    hmem = RSC_LoadResource( hInst, dlgTemplate, NE_RSCTYPE_DIALOG, &size );
-    data = (LPCSTR) GlobalLock( hmem );
-    hwnd = CreateDialogIndirectParam( hInst, data, owner, dlgProc, param );
-    GlobalFree( hmem );
-#endif
     return hwnd;
 }
 
@@ -314,8 +307,8 @@
     if (dlgInfo->hUserFont) 
 	SendMessage( hwnd, WM_SETFONT, dlgInfo->hUserFont, 0);
     SendMessage( hwnd, WM_INITDIALOG, dlgInfo->hwndFocus, param );
-    if (SendMessage( hwnd, WM_INITDIALOG, dlgInfo->hwndFocus, param ))
-	SetFocus( dlgInfo->hwndFocus );
+/*    if (SendMessage( hwnd, WM_INITDIALOG, dlgInfo->hwndFocus, param ))
+	SetFocus( dlgInfo->hwndFocus ); */
 
     return hwnd;
 }
diff --git a/windows/event.c b/windows/event.c
index 3130189..5f3aa3d 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -18,6 +18,8 @@
 #define NB_BUTTONS      3     /* Windows can handle 3 buttons */
 static WORD dblclick_time = 300; /* Max. time for a double click (milliseconds) */
 
+extern Display * XT_display;
+
   /* Event handlers */
 static void EVENT_expose();
 static void EVENT_key();
@@ -25,17 +27,175 @@
 static void EVENT_mouse_button();
 static void EVENT_structure();
 static void EVENT_focus_change();
+static void EVENT_enter_notify();
+
+  /* X context to associate a hwnd to an X window */
+static XContext winContext = 0;
 
   /* State variables */
 static HWND captureWnd = 0;
-
+Window winHasCursor = 0;
 extern HWND hWndFocus;
 
+/* Keyboard translation tables */
+static int special_key[] =
+{
+    VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0,           /* FF08 */
+    0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0,                      /* FF10 */
+    0, 0, 0, VK_ESCAPE                                          /* FF18 */
+};
+
+static cursor_key[] =
+{
+    VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR, 
+                                       VK_NEXT, VK_END          /* FF50 */
+};
+
+static misc_key[] =
+{
+    VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0,  /* FF60 */
+    VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU                      /* FF68 */
+};
+
+static keypad_key[] =
+{
+    VK_MENU, VK_NUMLOCK,                                        /* FF7E */
+    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF80 */
+    0, 0, 0, 0, 0, VK_RETURN, 0, 0,                             /* FF88 */
+    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF90 */
+    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF98 */
+    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFA0 */
+    0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT, 
+                               VK_DECIMAL, VK_DIVIDE,           /* FFA8 */
+    VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
+                            VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
+    VK_NUMPAD8, VK_NUMPAD9                                      /* FFB8 */
+};
+    
+static function_key[] =
+{
+    VK_F1, VK_F2,                                               /* FFBE */
+    VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,    /* FFC0 */
+    VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16              /* FFC8 */
+};
+
+static modifier_key[] =
+{
+    VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
+                                                0, 0,           /* FFE1 */
+    0, VK_MENU, VK_MENU                                         /* FFE8 */
+};
+
+typedef union
+{
+    struct
+    {
+	unsigned long count : 16;
+	unsigned long code : 8;
+	unsigned long extended : 1;
+	unsigned long : 4;
+	unsigned long context : 1;
+	unsigned long previous : 1;
+	unsigned long transition : 1;
+    } lp1;
+    unsigned long lp2;
+} KEYLP;
+
+static BOOL KeyDown = FALSE;
+
+
+#ifdef DEBUG_EVENT
+static char *event_names[] =
+{
+    "", "", "KeyPress", "KeyRelease", "ButtonPress", "ButtonRelease",
+    "MotionNotify", "EnterNotify", "LeaveNotify", "FocusIn", "FocusOut",
+    "KeymapNotify", "Expose", "GraphicsExpose", "NoExpose", "VisibilityNotify",
+    "CreateNotify", "DestroyNotify", "UnmapNotify", "MapNotify", "MapRequest",
+    "ReparentNotify", "ConfigureNotify", "ConfigureRequest", "GravityNotify",
+    "ResizeRequest", "CirculateNotify", "CirculateRequest", "PropertyNotify",
+    "SelectionClear", "SelectionRequest", "SelectionNotify", "ColormapNotify",
+    "ClientMessage", "MappingNotify"
+};
+#endif
+
+
+/***********************************************************************
+ *           EVENT_ProcessEvent
+ *
+ * Process an X event.
+ */
+void EVENT_ProcessEvent( XEvent *event )
+{
+    HWND hwnd;
+    XPointer ptr;
+    Boolean cont_dispatch = TRUE;
+    
+    XFindContext( XT_display, ((XAnyEvent *)event)->window, winContext, &ptr );
+    hwnd = (HWND)ptr & 0xffff;
+
+#ifdef DEBUG_EVENT
+    printf( "Got event %s for hwnd %d\n", 
+	    event_names[event->type], hwnd );
+#endif
+
+    switch(event->type)
+    {
+        case Expose:
+	    EVENT_expose( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+	case KeyPress:
+	case KeyRelease:
+	    EVENT_key( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+	case MotionNotify:
+	    EVENT_mouse_motion( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+	case ButtonPress:
+	case ButtonRelease:
+	    EVENT_mouse_button( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+	case CirculateNotify:
+	case ConfigureNotify:
+	case MapNotify:
+	case UnmapNotify:
+	    EVENT_structure( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+	case FocusIn:
+	case FocusOut:
+	    EVENT_focus_change( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+	case EnterNotify:
+	    EVENT_enter_notify( 0, hwnd, event, &cont_dispatch );
+	    break;
+
+#ifdef DEBUG_EVENT
+	default:
+	    printf( "Unprocessed event %s for hwnd %d\n", 
+		    event_names[event->type], hwnd );
+	    break;
+#endif
+    }
+}
+
+
 /***********************************************************************
  *           EVENT_AddHandlers
  *
  * Add the event handlers to the given window
  */
+#ifdef USE_XLIB
+void EVENT_AddHandlers( Window w, int hwnd )
+{
+    if (!winContext) winContext = XUniqueContext();
+    XSaveContext( XT_display, w, winContext, (XPointer)hwnd );
+}
+#else
 void EVENT_AddHandlers( Widget w, int hwnd )
 {
     XtAddEventHandler(w, ExposureMask, FALSE,
@@ -50,7 +210,10 @@
 		      EVENT_structure, (XtPointer)hwnd );
     XtAddEventHandler(w, FocusChangeMask, FALSE,
 		      EVENT_focus_change, (XtPointer)hwnd );
+    XtAddEventHandler(w, EnterWindowMask, FALSE,
+		      EVENT_enter_notify, (XtPointer)hwnd );
 }
+#endif
 
 
 /***********************************************************************
@@ -60,6 +223,7 @@
  */
 void EVENT_RemoveHandlers( Widget w, int hwnd )
 {
+#ifndef USE_XLIB
     XtRemoveEventHandler(w, ExposureMask, FALSE,
 			 EVENT_expose, (XtPointer)hwnd );
     XtRemoveEventHandler(w, KeyPressMask | KeyReleaseMask, FALSE, 
@@ -72,6 +236,9 @@
 			 EVENT_structure, (XtPointer)hwnd );
     XtRemoveEventHandler(w, FocusChangeMask, FALSE,
 			 EVENT_focus_change, (XtPointer)hwnd );
+    XtRemoveEventHandler(w, EnterWindowMask, FALSE,
+			 EVENT_enter_notify, (XtPointer)hwnd );
+#endif
 }
 
 
@@ -103,10 +270,14 @@
 			  Boolean *cont_dispatch )
 {
     RECT rect;
-    rect.left   = event->x;
-    rect.top    = event->y;
-    rect.right  = event->x + event->width;
-    rect.bottom = event->y + event->height;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr) return;
+      /* Make position relative to client area instead of window */
+    rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
+    rect.top  = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
+    rect.right  = rect.left + event->width;
+    rect.bottom = rect.top + event->height;
+    winHasCursor = event->window;
     
     InvalidateRect( hwnd, &rect, TRUE );
 }
@@ -121,24 +292,128 @@
 		       Boolean *cont_dispatch )
 {
     MSG msg;
-
     char Str[24]; 
     XComposeStatus cs; 
-    KeySym key;
-    int count = XLookupString(event, Str, 1, &key, &cs);
+    KeySym keysym;
+    WORD xkey, vkey, key_type, key;
+    KEYLP keylp;
+    BOOL extended = FALSE;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    int count = XLookupString(event, Str, 1, &keysym, &cs);
     Str[count] = '\0';
 #ifdef DEBUG_KEY
-    printf("WM_KEY??? : count=%u / %X / '%s'\n",count, Str[0], Str);
-#endif    
-    msg.hwnd    = hwnd;
-    msg.message = (event->type == KeyRelease) ? WM_KEYUP : WM_KEYDOWN;
-    msg.wParam  = Str[0];
-    msg.lParam  = (event->x & 0xffff) | (event->y << 16);
-    msg.time = event->time;
-    msg.pt.x = event->x & 0xffff;
-    msg.pt.y = event->y & 0xffff;
+    printf("WM_KEY??? : keysym=%lX, count=%u / %X / '%s'\n", 
+	   keysym, count, Str[0], Str);
+#endif
+
+    xkey = LOWORD(keysym);
+    key_type = HIBYTE(xkey);
+    key = LOBYTE(xkey);
+#ifdef DEBUG_KEY
+    printf("            key_type=%X, key=%X\n", key_type, key);
+#endif
+
+      /* Position must be relative to client area */
+    event->x -= wndPtr->rectClient.left - wndPtr->rectWindow.left;
+    event->y -= wndPtr->rectClient.top - wndPtr->rectWindow.top;
+
+    if (key_type == 0xFF)                          /* non-character key */
+    {
+	if (key >= 0x08 && key <= 0x1B)            /* special key */
+	    vkey = special_key[key - 0x08];
+	else if (key >= 0x50 && key <= 0x57)       /* cursor key */
+	    vkey = cursor_key[key - 0x50];
+	else if (key >= 0x60 && key <= 0x6B)       /* miscellaneous key */
+	    vkey = misc_key[key - 0x60];
+	else if (key >= 0x7E && key <= 0xB9)       /* keypad key */
+	{
+	    vkey = keypad_key[key - 0x7E];
+	    extended = TRUE;
+	}
+	else if (key >= 0xBE && key <= 0xCD)       /* function key */
+	{
+	    vkey = function_key[key - 0xBE];
+	    extended = TRUE;
+	}
+	else if (key >= 0xE1 && key <= 0xEA)       /* modifier key */
+	    vkey = modifier_key[key - 0xE1];
+	else if (key == 0xFF)                      /* DEL key */
+	    vkey = VK_DELETE;
+    }
+    else if (key_type == 0)                        /* character key */
+    {
+	if (key >= 0x61 && key <= 0x7A)
+	    vkey = key - 0x20;                 /* convert lower to uppercase */
+	else
+	    vkey = key;
+    }
+
+    if (event->type == KeyPress)
+    {
+	msg.hwnd    = hwnd;
+	msg.message = WM_KEYDOWN;
+	msg.wParam  = vkey;
+	keylp.lp1.count = 1;
+	keylp.lp1.code = LOBYTE(event->keycode);
+	keylp.lp1.extended = (extended ? 1 : 0);
+	keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
+	keylp.lp1.previous = (KeyDown ? 0 : 1);
+	keylp.lp1.transition = 0;
+	msg.lParam  = keylp.lp2;
+#ifdef DEBUG_KEY
+	printf("            wParam=%X, lParam=%lX\n", msg.wParam, msg.lParam);
+#endif
+	msg.time = event->time;
+	msg.pt.x = event->x & 0xffff;
+	msg.pt.y = event->y & 0xffff;
     
-    MSG_AddMsg( &msg );    
+	hardware_event( hwnd, WM_KEYDOWN, vkey, keylp.lp2,
+		        event->x & 0xffff, event->y & 0xffff, event->time, 0 );
+	KeyDown = TRUE;
+
+	/* The key translation ought to take place in TranslateMessage().
+	 * However, there is no way of passing the required information 
+	 * in a Windows message, so TranslateMessage does not currently
+	 * do anything and the translation is done here.
+	 */
+	if (count == 1)                /* key has an ASCII representation */
+	{
+	    msg.hwnd    = hwnd;
+	    msg.message = WM_CHAR;
+	    msg.wParam  = (WORD)Str[0];
+	    msg.lParam  = keylp.lp2;
+#ifdef DEBUG_KEY
+	printf("WM_CHAR :   wParam=%X\n", msg.wParam);
+#endif
+	    msg.time = event->time;
+	    msg.pt.x = event->x & 0xffff;
+	    msg.pt.y = event->y & 0xffff;
+	    PostMessage( hwnd, WM_CHAR, (WORD)Str[0], keylp.lp2 );
+	}
+    }
+    else
+    {
+	msg.hwnd    = hwnd;
+	msg.message = WM_KEYUP;
+	msg.wParam  = vkey;
+	keylp.lp1.count = 1;
+	keylp.lp1.code = LOBYTE(event->keycode);
+	keylp.lp1.extended = (extended ? 1 : 0);
+	keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
+	keylp.lp1.previous = 1;
+	keylp.lp1.transition = 1;
+	msg.lParam  = keylp.lp2;
+#ifdef DEBUG_KEY
+	printf("            wParam=%X, lParam=%lX\n", msg.wParam, msg.lParam);
+#endif
+	msg.time = event->time;
+	msg.pt.x = event->x & 0xffff;
+	msg.pt.y = event->y & 0xffff;
+    
+	hardware_event( hwnd, WM_KEYUP, vkey, keylp.lp2,
+		        event->x & 0xffff, event->y & 0xffff, event->time, 0 );
+	KeyDown = FALSE;
+    }
 }
 
 
@@ -150,17 +425,17 @@
 static void EVENT_mouse_motion( Widget w, int hwnd, XMotionEvent *event, 
 			        Boolean *cont_dispatch )
 {
-    MSG msg;
-    
-    msg.hwnd    = hwnd;
-    msg.message = WM_MOUSEMOVE;
-    msg.wParam  = EVENT_XStateToKeyState( event->state );
-    msg.lParam  = (event->x & 0xffff) | (event->y << 16);
-    msg.time = event->time;
-    msg.pt.x = event->x & 0xffff;
-    msg.pt.y = event->y & 0xffff;
-    
-    MSG_AddMsg( &msg );    
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr) return;
+
+      /* Position must be relative to client area */
+    event->x -= wndPtr->rectClient.left - wndPtr->rectWindow.left;
+    event->y -= wndPtr->rectClient.top - wndPtr->rectWindow.top;
+
+    hardware_event( hwnd, WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ),
+		    (event->x & 0xffff) | (event->y << 16),
+		    event->x & 0xffff, event->y & 0xffff,
+		    event->time, 0 );		    
 }
 
 
@@ -180,9 +455,15 @@
     };
     static unsigned long lastClickTime[NB_BUTTONS] = { 0, 0, 0 };
         
-    MSG msg;
     int buttonNum, prevTime, type;
-    
+
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr) return;
+
+      /* Position must be relative to client area */
+    event->x -= wndPtr->rectClient.left - wndPtr->rectWindow.left;
+    event->y -= wndPtr->rectClient.top - wndPtr->rectWindow.top;
+
     buttonNum = event->button-1;
     if (buttonNum >= NB_BUTTONS) return;
     if (event->type == ButtonRelease) type = 1;
@@ -201,15 +482,13 @@
 	else type = 0;
     }	
     
-    msg.hwnd    = hwnd;
-    msg.message = messages[type][buttonNum];
-    msg.wParam  = EVENT_XStateToKeyState( event->state );
-    msg.lParam  = (event->x & 0xffff) | (event->y << 16);
-    msg.time = event->time;
-    msg.pt.x = event->x & 0xffff;
-    msg.pt.y = event->y & 0xffff;
+    winHasCursor = event->window;
 
-    MSG_AddMsg( &msg );    
+    hardware_event( hwnd, messages[type][buttonNum],
+		    EVENT_XStateToKeyState( event->state ),
+		    (event->x & 0xffff) | (event->y << 16),
+		    event->x & 0xffff, event->y & 0xffff,
+		    event->time, 0 );		    
 }
 
 
@@ -232,13 +511,31 @@
     {
       case ConfigureNotify:
 	{
+	    HANDLE handle;
+	    NCCALCSIZE_PARAMS *params;	    
 	    XConfigureEvent * evt = (XConfigureEvent *)event;
 	    WND * wndPtr = WIN_FindWndPtr( hwnd );
 	    if (!wndPtr) return;
-	    wndPtr->rectClient.right  = wndPtr->rectClient.left + evt->width;
-	    wndPtr->rectClient.bottom = wndPtr->rectClient.top + evt->height;
+	    wndPtr->rectWindow.left   = evt->x;
+	    wndPtr->rectWindow.top    = evt->y;
+	    wndPtr->rectWindow.right  = evt->x + evt->width;
+	    wndPtr->rectWindow.bottom = evt->y + evt->height;
+
+	      /* Send WM_NCCALCSIZE message */
+	    handle = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) );
+	    params = (NCCALCSIZE_PARAMS *)GlobalLock( handle );
+	    params->rgrc[0] = wndPtr->rectWindow;
+	    params->lppos   = NULL;  /* Should be WINDOWPOS struct */
+	    SendMessage( hwnd, WM_NCCALCSIZE, FALSE, params );
+	    wndPtr->rectClient = params->rgrc[0];
+	    PostMessage( hwnd, WM_MOVE, 0,
+		             MAKELONG( wndPtr->rectClient.left,
+				       wndPtr->rectClient.top ));
 	    PostMessage( hwnd, WM_SIZE, SIZE_RESTORED,
-			 (evt->width & 0xffff) | (evt->height << 16) );
+		   MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
+			    wndPtr->rectClient.bottom-wndPtr->rectClient.top));
+	    GlobalUnlock( handle );
+	    GlobalFree( handle );
 	}
 	break;
 	
@@ -254,21 +551,12 @@
 static void EVENT_focus_change( Widget w, int hwnd, XEvent *event, 
 			       Boolean *cont_dispatch )
 {
-    MSG msg;
-    
-    msg.hwnd = hwnd;
-    msg.time = GetTickCount();
-    msg.pt.x = 0;
-    msg.pt.y = 0;
-
     switch(event->type)
     {
       case FocusIn:
 	{
-	    msg.message = WM_SETFOCUS;
-	    msg.wParam = hwnd;
+	    PostMessage( hwnd, WM_SETFOCUS, hwnd, 0 );
 	    hWndFocus = hwnd;
-
 	}
 	break;
 	
@@ -276,13 +564,32 @@
 	{
 	    if (hWndFocus)
 	    {
-		msg.message = WM_KILLFOCUS;
-		msg.wParam = hwnd;
+		PostMessage( hwnd, WM_KILLFOCUS, hwnd, 0 );
 		hWndFocus = 0;
 	    }
 	}
     }    
-    MSG_AddMsg( &msg );
+}
+
+
+/**********************************************************************
+ *              EVENT_enter_notify
+ *
+ * Handle an X EnterNotify event
+ */
+static void EVENT_enter_notify( Widget w, int hwnd, XCrossingEvent *event, 
+			       Boolean *cont_dispatch )
+{
+    if (captureWnd != 0) return;
+
+    winHasCursor = event->window;
+
+    switch(event->type)
+    {
+      case EnterNotify:
+	PostMessage( hwnd, WM_SETCURSOR, hwnd, 0 );
+	break;
+    }    
 }
 
 
@@ -297,9 +604,15 @@
     if (wnd_p == NULL)
 	return 0;
     
+#ifdef USE_XLIB
+    rv = XGrabPointer(XT_display, wnd_p->window, False, 
+		      ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
+		      GrabModeAsync, GrabModeSync, None, None, CurrentTime);
+#else
     rv = XtGrabPointer(wnd_p->winWidget, False, 
 		       ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
 		       GrabModeAsync, GrabModeSync, None, None, CurrentTime);
+#endif
 
     if (rv == GrabSuccess)
     {
@@ -324,12 +637,24 @@
     if (wnd_p == NULL)
 	return;
     
+#ifdef USE_XLIB
+    XUngrabPointer( XT_display, CurrentTime );
+#else
     XtUngrabPointer(wnd_p->winWidget, CurrentTime);
+#endif
 
     captureWnd = 0;
 }
 
 /**********************************************************************
+ *		GetCapture 	(USER.236)
+ */
+HWND GetCapture()
+{
+    return captureWnd;
+}
+ 
+/**********************************************************************
  *		SetDoubleClickTime  (USER.20)
  */
 void SetDoubleClickTime (WORD interval)
diff --git a/windows/focus.c b/windows/focus.c
index ce1a91a2..639b2df 100644
--- a/windows/focus.c
+++ b/windows/focus.c
@@ -32,7 +32,7 @@
     else
     {
 	wndPtr = WIN_FindWndPtr(hwnd);
-	XSetInputFocus(XT_display, XtWindow(wndPtr->winWidget),
+	XSetInputFocus(XT_display, wndPtr->window,
 		       RevertToParent, CurrentTime);
     }
 
diff --git a/windows/graphics.c b/windows/graphics.c
index a2a1e32..9fd5d27 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -23,8 +23,10 @@
     if (!dc) return FALSE;
     if (DC_SetupGCForPen( dc ))
 	XDrawLine(XT_display, dc->u.x.drawable, dc->u.x.gc, 
-		  XLPTODP( dc, dc->w.CursPosX ), YLPTODP( dc, dc->w.CursPosY ),
-		  XLPTODP( dc, x ), YLPTODP( dc, y ) );
+		  dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
+		  dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
+		  dc->w.DCOrgX + XLPTODP( dc, x ),
+		  dc->w.DCOrgY + YLPTODP( dc, y ) );
     dc->w.CursPosX = x;
     dc->w.CursPosY = y;
     return TRUE;
@@ -97,20 +99,21 @@
     if (diff_angle < 0.0) diff_angle += 2*PI;
 
     XDrawArc( XT_display, dc->u.x.drawable, dc->u.x.gc,
-	      left, top, right-left-1, bottom-top-1,
+	      dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+	      right-left-1, bottom-top-1,
 	      (int)(start_angle * 180 * 64 / PI),
 	      (int)(diff_angle * 180 * 64 / PI) );
     if (!lines) return TRUE;
 
-    points[0].x = xcenter + (int)(cos(start_angle) * (right-left) / 2);
-    points[0].y = ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
-    points[1].x = xcenter + (int)(cos(end_angle) * (right-left) / 2);
-    points[1].y = ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
+    points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
+    points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
+    points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
+    points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
     if (lines == 2)
     {
 	points[2] = points[1];
-	points[1].x = xcenter;
-	points[1].y = ycenter;
+	points[1].x = dc->w.DCOrgX + xcenter;
+	points[1].y = dc->w.DCOrgY + ycenter;
     }
     XDrawLines( XT_display, dc->u.x.drawable, dc->u.x.gc,
 	        points, lines+1, CoordModeOrigin );
@@ -167,10 +170,12 @@
     
     if (DC_SetupGCForBrush( dc ))
 	XFillArc( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		  left, top, right-left-1, bottom-top-1, 0, 360*64 );
+		  dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		  right-left-1, bottom-top-1, 0, 360*64 );
     if (DC_SetupGCForPen( dc ))
 	XDrawArc( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		  left, top, right-left-1, bottom-top-1, 0, 360*64 );
+		  dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		  right-left-1, bottom-top-1, 0, 360*64 );
     return TRUE;
 }
 
@@ -190,10 +195,12 @@
     
     if (DC_SetupGCForBrush( dc ))
 	XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		        left, top, right-left-1, bottom-top-1 );
+		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		        right-left-1, bottom-top-1 );
     if (DC_SetupGCForPen( dc ))
 	XDrawRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		        left, top, right-left-1, bottom-top-1 );
+		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		        right-left-1, bottom-top-1 );
     return TRUE;
 }
 
@@ -244,10 +251,16 @@
     right  = XLPTODP( dc, rect->right );
     bottom = YLPTODP( dc, rect->bottom );
     
-    if (DC_SetupGCForBrush( dc ))
-	XDrawRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		        left, top, right-left-1, bottom-top-1 );
-	    
+    if (DC_SetupGCForBrush( dc )) {
+   	PatBlt( hdc, rect->left, rect->top, 1,
+	    rect->bottom - rect->top, PATCOPY );
+	PatBlt( hdc, rect->right - 1, rect->top, 1,
+	    rect->bottom - rect->top, PATCOPY );
+	PatBlt( hdc, rect->left, rect->top,
+	    rect->right - rect->left, 1, PATCOPY );
+	PatBlt( hdc, rect->left, rect->bottom - 1,
+	    rect->right - rect->left, 1, PATCOPY );
+	}    
     SelectObject( hdc, prevBrush );
     return 1;
 }
@@ -264,8 +277,8 @@
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return 0;
 
-    x = XLPTODP( dc, x );
-    y = YLPTODP( dc, y );
+    x = dc->w.DCOrgX + XLPTODP( dc, x );
+    y = dc->w.DCOrgY + YLPTODP( dc, y );
     pixel = GetNearestPaletteIndex( dc->w.hPalette, color );
     GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
     
@@ -288,15 +301,14 @@
     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return 0;
 
-    x = XLPTODP( dc, x );
-    y = YLPTODP( dc, y );
+    x = dc->w.DCOrgX + XLPTODP( dc, x );
+    y = dc->w.DCOrgY + YLPTODP( dc, y );
     if ((x < 0) || (y < 0)) return 0;
     
-    if (dc->u.x.widget)
+    if (!(dc->w.flags & DC_MEMORY))
     {
 	XWindowAttributes win_attr;
 	
-	if (!XtIsRealized(dc->u.x.widget)) return 0;
 	if (!XGetWindowAttributes( XT_display, dc->u.x.drawable, &win_attr ))
 	    return 0;
 	if (win_attr.map_state != IsViewable) return 0;
@@ -342,7 +354,7 @@
     GetClipBox( hdc, &box );
     if (DC_SetupGCForBrush( dc ))
 	XFillRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		        box.left, box.top,
+		        dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
 		        box.right-box.left, box.bottom-box.top );
 
       /* Restore the visible region */
@@ -385,15 +397,16 @@
     
     hPen = CreatePen(PS_DOT, 1, GetSysColor(COLOR_WINDOWTEXT)); 
     hOldPen = (HPEN)SelectObject(hdc, (HANDLE)hPen);
-/*    oldDrawMode = SetROP2(hdc, R2_XORPEN);  */
+    oldDrawMode = SetROP2(hdc, R2_XORPEN);
     oldBkMode = SetBkMode(hdc, TRANSPARENT);
 
     if (DC_SetupGCForPen( dc ))
 	XDrawRectangle( XT_display, dc->u.x.drawable, dc->u.x.gc,
-		        left, top, right-left-1, bottom-top-1 );
+		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		        right-left-1, bottom-top-1 );
 
     SetBkMode(hdc, oldBkMode);
-/*    SetROP2(hdc, oldDrawMode);  */
+    SetROP2(hdc, oldDrawMode);
     SelectObject(hdc, (HANDLE)hOldPen);
     DeleteObject((HANDLE)hPen);
 }
@@ -441,3 +454,64 @@
 SelectObject(hDC, hOldPen);
 DeleteObject(hDKGRAYPen);
 }
+
+/**********************************************************************
+ *          Polyline  (GDI.37)
+ */
+BOOL Polyline (HDC hdc, LPPOINT pt, int count)
+{
+	register int i;
+    	DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+
+    	if (DC_SetupGCForPen( dc ))
+    	{
+		for (i = 0; i < count-1; i ++)
+			XDrawLine (XT_display, dc->u.x.drawable, dc->u.x.gc,  
+				   dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
+				   dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
+				   dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
+				   dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
+		XDrawLine (XT_display, dc->u.x.drawable, dc->u.x.gc,  
+			   dc->w.DCOrgX + XLPTODP(dc, pt [count-1].x),
+			   dc->w.DCOrgY + YLPTODP(dc, pt [count-1].y),
+			   dc->w.DCOrgX + XLPTODP(dc, pt [0].x),
+			   dc->w.DCOrgY + YLPTODP(dc, pt [0].y));
+	} 
+	
+	return (TRUE);
+}
+
+
+/**********************************************************************
+ *          Polygon  (GDI.36)
+ */
+BOOL Polygon (HDC hdc, LPPOINT pt, int count)
+{
+	register int i;
+    	DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+	XPoint *points = (XPoint *) malloc (sizeof (XPoint) * count+1);
+
+    	if (DC_SetupGCForBrush( dc ))
+    	{
+    		
+		for (i = 0; i < count; i++)
+		{
+			points [i].x = dc->w.DCOrgX + XLPTODP(dc, pt [i].x);
+			points [i].y = dc->w.DCOrgY + YLPTODP(dc, pt [i].y);
+		}
+		points [count] = points [0];
+		
+		XFillPolygon( XT_display, dc->u.x.drawable, dc->u.x.gc,
+		  	points, count, Complex, CoordModeOrigin);
+		
+		if (DC_SetupGCForPen ( dc ))
+		{
+		    XDrawLines( XT_display, dc->u.x.drawable, dc->u.x.gc,
+			        points, count, CoordModeOrigin );
+		}
+	}
+    	free ((void *) points);
+	return (TRUE);
+}
+ 
+
diff --git a/windows/message.c b/windows/message.c
index 7307461..09b49e7 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -12,10 +12,8 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 #include <stdlib.h>
-
-#ifdef __NetBSD__
-#define HZ 100
-#endif
+#include <sys/time.h>
+#include <sys/types.h>
 
 #include "message.h"
 #include "win.h"
@@ -23,30 +21,72 @@
 
 #define MAX_QUEUE_SIZE   120  /* Max. size of a message queue */
 
-extern HWND WIN_FindWinToRepaint( HWND hwnd );
+extern BOOL TIMER_CheckTimer( DWORD *next );    /* timer.c */
 
 extern Display * XT_display;
 extern Screen * XT_screen;
 extern XtAppContext XT_app_context;
 
-static MESSAGEQUEUE * msgQueue = NULL;
+  /* System message queue (for hardware events) */
+static HANDLE hmemSysMsgQueue = 0;
+static MESSAGEQUEUE * sysMsgQueue = NULL;
+
+  /* Application message queue (should be a list, one queue per task) */
+static HANDLE hmemAppMsgQueue = 0;
+static MESSAGEQUEUE * appMsgQueue = NULL;
+
+/***********************************************************************
+ *           MSG_CreateMsgQueue
+ *
+ * Create a message queue.
+ */
+static HANDLE MSG_CreateMsgQueue( int size )
+{
+    HANDLE hQueue;
+    MESSAGEQUEUE * msgQueue;
+    int queueSize;
+
+    queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
+    if (!(hQueue = GlobalAlloc( GMEM_FIXED, queueSize ))) return 0;
+    msgQueue = (MESSAGEQUEUE *) GlobalLock( hQueue );
+    msgQueue->next = 0;
+    msgQueue->hTask = 0;
+    msgQueue->msgSize = sizeof(QMSG);
+    msgQueue->msgCount = 0;
+    msgQueue->nextMessage = 0;
+    msgQueue->nextFreeMessage = 0;
+    msgQueue->queueSize = size;
+    msgQueue->GetMessageTimeVal = 0;
+    msgQueue->GetMessagePosVal = 0;
+    msgQueue->GetMessageExtraInfoVal = 0;
+    msgQueue->lParam = 0;
+    msgQueue->wParam = 0;
+    msgQueue->msg = 0;
+    msgQueue->hWnd = 0;
+    msgQueue->wPostQMsg = 0;
+    msgQueue->wExitCode = 0;
+    msgQueue->InSendMessageHandle = 0;
+    msgQueue->wPaintCount = 0;
+    msgQueue->wTimerCount = 0;
+    msgQueue->tempStatus = 0;
+    msgQueue->status = 0;
+    GlobalUnlock( hQueue );
+    return hQueue;
+}
 
 
 /***********************************************************************
- *           MSG_GetMessageType
+ *           MSG_CreateSysMsgQueue
  *
+ * Create the system message queue. Must be called only once.
  */
-int MSG_GetMessageType( int msg )
+BOOL MSG_CreateSysMsgQueue( int size )
 {
-    if ((msg >= WM_KEYFIRST) && (msg <= WM_KEYLAST)) return QS_KEY;
-    else if ((msg >= WM_MOUSEFIRST) && (msg <= WM_MOUSELAST))
-    {
-	if (msg == WM_MOUSEMOVE) return QS_MOUSEMOVE;
-	else return QS_MOUSEBUTTON;
-    }
-    else if (msg == WM_PAINT) return QS_PAINT;
-    else if (msg == WM_TIMER) return QS_TIMER;
-    return QS_POSTMESSAGE;
+    if (size > MAX_QUEUE_SIZE) size = MAX_QUEUE_SIZE;
+    else if (size <= 0) size = 1;
+    if (!(hmemSysMsgQueue = MSG_CreateMsgQueue( size ))) return FALSE;
+    sysMsgQueue = (MESSAGEQUEUE *) GlobalLock( hmemSysMsgQueue );
+    return TRUE;
 }
 
 
@@ -55,16 +95,13 @@
  *
  * Add a message to the queue. Return FALSE if queue is full.
  */
-int MSG_AddMsg( MSG * msg, DWORD extraInfo )
+static int MSG_AddMsg( MESSAGEQUEUE * msgQueue, MSG * msg, DWORD extraInfo )
 {
-    int pos, type;
+    int pos;
   
     if (!msgQueue) return FALSE;
     pos = msgQueue->nextFreeMessage;
 
-      /* No need to store WM_PAINT messages */
-    if (msg->message == WM_PAINT) return TRUE;
-        
       /* Check if queue is full */
     if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
 	return FALSE;
@@ -72,17 +109,12 @@
       /* Store message */
     msgQueue->messages[pos].msg = *msg;
     msgQueue->messages[pos].extraInfo = extraInfo;
-
-      /* Store message type */
-    type = MSG_GetMessageType( msg->message );   
-    msgQueue->status |= type;
-    msgQueue->tempStatus |= type;
-    
     if (pos < msgQueue->queueSize-1) pos++;
     else pos = 0;
     msgQueue->nextFreeMessage = pos;
     msgQueue->msgCount++;
-    
+    msgQueue->status |= QS_POSTMESSAGE;
+    msgQueue->tempStatus |= QS_POSTMESSAGE;
     return TRUE;
 }
 
@@ -92,7 +124,7 @@
  *
  * Find a message matching the given parameters. Return -1 if none available.
  */
-int MSG_FindMsg( HWND hwnd, int first, int last )
+static int MSG_FindMsg(MESSAGEQUEUE * msgQueue, HWND hwnd, int first, int last)
 {
     int i, pos = msgQueue->nextMessage;
 
@@ -120,9 +152,8 @@
  *
  * Remove a message from the queue (pos must be a valid position).
  */
-void MSG_RemoveMsg( int pos )
+static void MSG_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos )
 {
-    int i, type;
     QMSG * qmsg;
     
     if (!msgQueue) return;
@@ -147,56 +178,118 @@
 	else msgQueue->nextFreeMessage = msgQueue->queueSize-1;
     }
     msgQueue->msgCount--;
-
-      /* Recalc status */
-    type = 0;
-    pos = msgQueue->nextMessage;
-    for (i = 0; i < msgQueue->msgCount; i++)
-    {
-	type |= MSG_GetMessageType( msgQueue->messages[pos].msg.message );
-	if (++pos >= msgQueue->queueSize-1) pos = 0;
-    }
-    msgQueue->status = (msgQueue->status & QS_SENDMESSAGE) | type;
+    if (!msgQueue->msgCount) msgQueue->status &= ~QS_POSTMESSAGE;
     msgQueue->tempStatus = 0;
 }
 
 
 /***********************************************************************
+ *           MSG_IncPaintCount
+ */
+void MSG_IncPaintCount( HANDLE hQueue )
+{
+    if (hQueue != hmemAppMsgQueue) return;
+    appMsgQueue->wPaintCount++;
+    appMsgQueue->status |= QS_PAINT;
+    appMsgQueue->tempStatus |= QS_PAINT;    
+}
+
+
+/***********************************************************************
+ *           MSG_DecPaintCount
+ */
+void MSG_DecPaintCount( HANDLE hQueue )
+{
+    if (hQueue != hmemAppMsgQueue) return;
+    appMsgQueue->wPaintCount--;
+    if (!appMsgQueue->wPaintCount) appMsgQueue->status &= ~QS_PAINT;
+}
+
+
+/***********************************************************************
+ *           MSG_IncTimerCount
+ */
+void MSG_IncTimerCount( HANDLE hQueue )
+{
+    if (hQueue != hmemAppMsgQueue) return;
+    appMsgQueue->wTimerCount++;
+    appMsgQueue->status |= QS_TIMER;
+    appMsgQueue->tempStatus |= QS_TIMER;
+}
+
+
+/***********************************************************************
+ *           MSG_DecTimerCount
+ */
+void MSG_DecTimerCount( HANDLE hQueue )
+{
+    if (hQueue != hmemAppMsgQueue) return;
+    appMsgQueue->wTimerCount--;
+    if (!appMsgQueue->wTimerCount) appMsgQueue->status &= ~QS_TIMER;
+}
+
+
+/***********************************************************************
+ *           hardware_event
+ *
+ * Add an event to the system message queue.
+ */
+void hardware_event( HWND hwnd, WORD message, WORD wParam, LONG lParam,
+		     WORD xPos, WORD yPos, DWORD time, DWORD extraInfo )
+{
+    MSG msg;
+
+    msg.hwnd    = hwnd;
+    msg.message = message;
+    msg.wParam  = wParam;
+    msg.lParam  = lParam;
+    msg.time    = time;
+    msg.pt.x    = xPos;
+    msg.pt.y    = yPos;    
+    if (!MSG_AddMsg( sysMsgQueue, &msg, extraInfo ))
+	printf( "hardware_event: Queue is full\n" );
+}
+
+		    
+/***********************************************************************
+ *           SetTaskQueue  (KERNEL.34)
+ */
+WORD SetTaskQueue( HANDLE hTask, HANDLE hQueue )
+{
+    HANDLE prev = hmemAppMsgQueue;
+    hmemAppMsgQueue = hQueue;
+    return prev;
+}
+
+
+/***********************************************************************
+ *           GetTaskQueue  (KERNEL.35)
+ */
+WORD GetTaskQueue( HANDLE hTask )
+{
+    return hmemAppMsgQueue;
+}
+
+
+/***********************************************************************
  *           SetMessageQueue  (USER.266)
  */
 BOOL SetMessageQueue( int size )
 {
-    int queueSize;
-  
+    HANDLE hQueue;
+
+    if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return TRUE;
+
       /* Free the old message queue */
-    if (msgQueue) free(msgQueue);
+    if ((hQueue = GetTaskQueue(0)) != 0)
+    {
+	GlobalUnlock( hQueue );
+	GlobalFree( hQueue );
+    }
   
-    if ((size > MAX_QUEUE_SIZE) || (size <= 0)) return FALSE;
-  
-    queueSize = sizeof(MESSAGEQUEUE) + size * sizeof(QMSG);
-    msgQueue = (MESSAGEQUEUE *) malloc(queueSize);
-    if (!msgQueue) return FALSE;
-
-    msgQueue->next = 0;
-    msgQueue->hTask = 0;
-    msgQueue->msgSize = sizeof(QMSG);
-    msgQueue->msgCount = 0;
-    msgQueue->nextMessage = 0;
-    msgQueue->nextFreeMessage = 0;
-    msgQueue->queueSize = size;
-    msgQueue->GetMessageTimeVal = 0;
-    msgQueue->GetMessagePosVal = 0;
-    msgQueue->GetMessageExtraInfoVal = 0;
-    msgQueue->lParam = 0;
-    msgQueue->wParam = 0;
-    msgQueue->msg = 0;
-    msgQueue->hWnd = 0;
-    msgQueue->wPostQMsg = 0;
-    msgQueue->wExitCode = 0;
-    msgQueue->InSendMessageHandle = 0;
-    msgQueue->tempStatus = 0;
-    msgQueue->status = 0;
-
+    if (!(hQueue = MSG_CreateMsgQueue( size ))) return FALSE;
+    SetTaskQueue( 0, hQueue );
+    appMsgQueue = (MESSAGEQUEUE *)GlobalLock( hQueue );
     return TRUE;
 }
 
@@ -206,9 +299,9 @@
  */
 void PostQuitMessage( int exitCode )
 {
-    if (!msgQueue) return;
-    msgQueue->wPostQMsg = TRUE;
-    msgQueue->wExitCode = exitCode;
+    if (!appMsgQueue) return;
+    appMsgQueue->wPostQMsg = TRUE;
+    appMsgQueue->wExitCode = exitCode;
 }
 
 
@@ -217,12 +310,8 @@
  */
 DWORD GetQueueStatus( int flags )
 {
-    unsigned long ret = (msgQueue->status << 16) | msgQueue->tempStatus;
-    if (flags & QS_PAINT)
-    {
-	if (WIN_FindWinToRepaint(0)) ret |= QS_PAINT | (QS_PAINT << 16);
-    }
-    msgQueue->tempStatus = 0;
+    unsigned long ret = (appMsgQueue->status << 16) | appMsgQueue->tempStatus;
+    appMsgQueue->tempStatus = 0;
     return ret & ((flags << 16) | flags);
 }
 
@@ -232,70 +321,169 @@
  */
 BOOL GetInputState()
 {
-    return msgQueue->status & (QS_KEY | QS_MOUSEBUTTON);
+    return appMsgQueue->status & (QS_KEY | QS_MOUSEBUTTON);
 }
 
 
+#ifndef USE_XLIB
+static XtIntervalId xt_timer = 0;
+
+/***********************************************************************
+ *           MSG_TimerCallback
+ */
+static void MSG_TimerCallback( XtPointer data, XtIntervalId * xtid )
+{
+    DWORD nextExp;
+    TIMER_CheckTimer( &nextExp );
+    if (nextExp != (DWORD)-1)
+	xt_timer = XtAppAddTimeOut( XT_app_context, nextExp,
+				    MSG_TimerCallback, NULL );
+    else xt_timer = 0;
+}
+#endif  /* USE_XLIB */
+
+
 /***********************************************************************
  *           MSG_PeekMessage
  */
-BOOL MSG_PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
+static BOOL MSG_PeekMessage( MESSAGEQUEUE * msgQueue, LPMSG msg, HWND hwnd,
+			     WORD first, WORD last, WORD flags, BOOL peek )
 {
-    int pos;
+    int pos, mask;
+    DWORD nextExp;  /* Next timer expiration time */
+#ifdef USE_XLIB
+    XEvent event;
+#endif
 
-      /* First handle a WM_QUIT message */
-    if (msgQueue->wPostQMsg)
+    if (first || last)
     {
-	msg->hwnd    = hwnd;
-	msg->message = WM_QUIT;
-	msg->wParam  = msgQueue->wExitCode;
-	msg->lParam  = 0;
-	return TRUE;
+	mask = QS_POSTMESSAGE;  /* Always selectioned */
+	if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
+	if ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) mask |= QS_MOUSE;
+	if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= WM_TIMER;
+	if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= WM_TIMER;
+	if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= WM_PAINT;
     }
+    else mask = QS_MOUSE | QS_KEY | QS_POSTMESSAGE | QS_TIMER | QS_PAINT;
 
-      /* Then handle a message put by SendMessage() */
-    if (msgQueue->status & QS_SENDMESSAGE)
+#ifdef USE_XLIB
+    while (XPending( XT_display ))
     {
-	if (!hwnd || (msgQueue->hWnd == hwnd))
+	XNextEvent( XT_display, &event );
+	EVENT_ProcessEvent( &event );
+    }    
+#else
+    while (XtAppPending( XT_app_context ))
+	XtAppProcessEvent( XT_app_context, XtIMAll );
+#endif
+
+    while(1)
+    {    
+	  /* First handle a WM_QUIT message */
+	if (msgQueue->wPostQMsg)
 	{
-	    if ((!first && !last) || 
-		((msgQueue->msg >= first) && (msgQueue->msg <= last)))
+	    msg->hwnd    = hwnd;
+	    msg->message = WM_QUIT;
+	    msg->wParam  = msgQueue->wExitCode;
+	    msg->lParam  = 0;
+	    break;
+	}
+
+	  /* Then handle a message put by SendMessage() */
+	if (msgQueue->status & QS_SENDMESSAGE)
+	{
+	    if (!hwnd || (msgQueue->hWnd == hwnd))
 	    {
-		msg->hwnd    = msgQueue->hWnd;
-		msg->message = msgQueue->msg;
-		msg->wParam  = msgQueue->wParam;
-		msg->lParam  = msgQueue->lParam;
-		if (flags & PM_REMOVE) msgQueue->status &= ~QS_SENDMESSAGE;
-		return TRUE;
+		if ((!first && !last) || 
+		    ((msgQueue->msg >= first) && (msgQueue->msg <= last)))
+		{
+		    msg->hwnd    = msgQueue->hWnd;
+		    msg->message = msgQueue->msg;
+		    msg->wParam  = msgQueue->wParam;
+		    msg->lParam  = msgQueue->lParam;
+		    if (flags & PM_REMOVE) msgQueue->status &= ~QS_SENDMESSAGE;
+		    break;
+		}
 	    }
 	}
-	
-    }
     
-      /* Now find a normal message */
-    pos = MSG_FindMsg( hwnd, first, last );
-    if (pos != -1)
-    {
-	QMSG *qmsg = &msgQueue->messages[pos];
-	*msg = qmsg->msg;
-	msgQueue->GetMessageTimeVal      = msg->time;
-	msgQueue->GetMessagePosVal       = *(DWORD *)&msg->pt;
-	msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
+	  /* Now find a normal message */
+	pos = MSG_FindMsg( msgQueue, hwnd, first, last );
+	if (pos != -1)
+	{
+	    QMSG *qmsg = &msgQueue->messages[pos];
+	    *msg = qmsg->msg;
+	    msgQueue->GetMessageTimeVal      = msg->time;
+	    msgQueue->GetMessagePosVal       = *(DWORD *)&msg->pt;
+	    msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
 
-	if (flags & PM_REMOVE) MSG_RemoveMsg(pos);
-    	return TRUE;
+	    if (flags & PM_REMOVE) MSG_RemoveMsg( msgQueue, pos );
+	    break;
+	}
+
+	  /* Now find a hardware event */
+	pos = MSG_FindMsg( sysMsgQueue, hwnd, first, last );
+	if (pos != -1)
+	{
+	    QMSG *qmsg = &sysMsgQueue->messages[pos];
+	    *msg = qmsg->msg;
+	    msgQueue->GetMessageTimeVal      = msg->time;
+	    msgQueue->GetMessagePosVal       = *(DWORD *)&msg->pt;
+	    msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
+
+	    if (flags & PM_REMOVE) MSG_RemoveMsg( sysMsgQueue, pos );
+	    break;
+	}
+
+	  /* Now find a WM_PAINT message */
+	if ((msgQueue->status & QS_PAINT) && (mask & QS_PAINT))
+	{
+	    msg->hwnd = WIN_FindWinToRepaint( hwnd );
+	    msg->message = WM_PAINT;
+	    msg->wParam = 0;
+	    msg->lParam = 0;
+	    if (msg->hwnd != 0) break;
+	}
+
+	  /* Finally handle WM_TIMER messages */
+	if ((msgQueue->status & QS_TIMER) && (mask & QS_TIMER))
+	{
+	    BOOL posted = TIMER_CheckTimer( &nextExp );
+#ifndef USE_XLIB
+	    if (xt_timer) XtRemoveTimeOut( xt_timer );
+	    if (nextExp != (DWORD)-1)
+		xt_timer = XtAppAddTimeOut( XT_app_context, nextExp,
+					    MSG_TimerCallback, NULL );
+	    else xt_timer = 0;
+#endif
+	    if (posted) continue;  /* Restart the whole thing */
+	}
+
+	  /* Wait until something happens */
+	if (peek) return FALSE;
+#ifdef USE_XLIB
+	if (!XPending( XT_display ) && (nextExp != -1))
+	{
+	    fd_set read_set;
+	    struct timeval timeout;
+	    int fd = ConnectionNumber(XT_display);
+	    FD_ZERO( &read_set );
+	    FD_SET( fd, &read_set );
+	    timeout.tv_sec = nextExp / 1000;
+	    timeout.tv_usec = (nextExp % 1000) * 1000;
+	    if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
+		continue;  /* On timeout or error, restart from the start */
+	}
+	XNextEvent( XT_display, &event );
+	EVENT_ProcessEvent( &event );
+#else       
+	XtAppProcessEvent( XT_app_context, XtIMAll );
+#endif	
     }
 
-      /* If nothing else, return a WM_PAINT message */
-    if ((!first && !last) || ((first <= WM_PAINT) && (last >= WM_PAINT)))
-    {
-	msg->hwnd = WIN_FindWinToRepaint( hwnd );
-	msg->message = WM_PAINT;
-	msg->wParam = 0;
-	msg->lParam = 0;
-	return (msg->hwnd != 0);
-    }	
-    return FALSE;
+      /* We got a message */
+    if (peek) return TRUE;
+    else return (msg->message != WM_QUIT);
 }
 
 
@@ -304,10 +492,7 @@
  */
 BOOL PeekMessage( LPMSG msg, HWND hwnd, WORD first, WORD last, WORD flags )
 {
-    while (XtAppPending( XT_app_context ))
-	XtAppProcessEvent( XT_app_context, XtIMAll );
-
-    return MSG_PeekMessage( msg, hwnd, first, last, flags );
+    return MSG_PeekMessage( appMsgQueue, msg, hwnd, first, last, flags, TRUE );
 }
 
 
@@ -316,13 +501,7 @@
  */
 BOOL GetMessage( LPMSG msg, HWND hwnd, WORD first, WORD last ) 
 {
-    while(1)
-    {
-	if (MSG_PeekMessage( msg, hwnd, first, last, PM_REMOVE )) break;
-	XtAppProcessEvent( XT_app_context, XtIMAll );
-    }
-
-    return (msg->message != WM_QUIT);
+    return MSG_PeekMessage( appMsgQueue, msg, hwnd, first, last, PM_REMOVE, FALSE );
 }
 
 
@@ -341,7 +520,7 @@
     msg.pt.x    = 0;
     msg.pt.y    = 0;
     
-    return MSG_AddMsg( &msg, 0 );
+    return MSG_AddMsg( appMsgQueue, &msg, 0 );
 }
 
 
@@ -380,16 +559,39 @@
  */
 LONG DispatchMessage( LPMSG msg )
 {
-    WND * wndPtr = WIN_FindWndPtr( msg->hwnd );
-
+    WND * wndPtr;
+    LONG retval;
+    int painting;
+    
 #ifdef DEBUG_MSG
     printf( "Dispatch message hwnd=%08x msg=%d w=%d l=%d time=%u pt=%d,%d\n",
 	    msg->hwnd, msg->message, msg->wParam, msg->lParam, 
 	    msg->time, msg->pt.x, msg->pt.y );
 #endif
-    if (!wndPtr)  return 0;
-    return CallWindowProc( wndPtr->lpfnWndProc, msg->hwnd, msg->message,
-			   msg->wParam, msg->lParam );
+
+      /* Process timer messages */
+    if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
+    {
+	if (msg->lParam)
+	    return CallWindowProc( (FARPROC)msg->lParam, msg->hwnd,
+				   msg->message, msg->wParam, GetTickCount() );
+    }
+
+    if (!msg->hwnd) return 0;
+    if (!(wndPtr = WIN_FindWndPtr( msg->hwnd ))) return 0;
+    if (!wndPtr->lpfnWndProc) return 0;
+    painting = (msg->message == WM_PAINT);
+    if (painting) wndPtr->flags |= WIN_NEEDS_BEGINPAINT;
+    retval = CallWindowProc( wndPtr->lpfnWndProc, msg->hwnd, msg->message,
+			     msg->wParam, msg->lParam );
+    if (painting && (wndPtr->flags & WIN_NEEDS_BEGINPAINT))
+    {
+#ifdef DEBUG_WIN
+	printf( "BeginPaint not called on WM_PAINT!\n" );
+#endif
+	wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
+    }
+    return retval;
 }
 
 
@@ -398,7 +600,7 @@
  */
 DWORD GetMessagePos(void)
 {
-    return msgQueue->GetMessagePosVal;
+    return appMsgQueue->GetMessagePosVal;
 }
 
 
@@ -407,14 +609,27 @@
  */
 LONG GetMessageTime(void)
 {
-    return msgQueue->GetMessageTimeVal;
+    return appMsgQueue->GetMessageTimeVal;
 }
 
+
 /***********************************************************************
  *           GetMessageExtraInfo   (USER.288)
  */
 LONG GetMessageExtraInfo(void)
 {
-    return msgQueue->GetMessageExtraInfoVal;
+    return appMsgQueue->GetMessageExtraInfoVal;
+}
+
+
+/***********************************************************************
+ *           RegisterWindowMessage   (USER.118)
+ */
+WORD RegisterWindowMessage( LPCSTR str )
+{
+#ifdef DEBUG_MSG
+    printf( "RegisterWindowMessage: '%s'\n", str );
+#endif
+    return GlobalAddAtom( str );
 }
 
diff --git a/windows/painting.c b/windows/painting.c
index 4f21b13..5a8e60a 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -10,6 +10,7 @@
 #include <X11/Xlib.h>
 
 #include "win.h"
+#include "message.h"
 
   /* Last CTLCOLOR id */
 #define CTLCOLOR_MAX   CTLCOLOR_STATIC
@@ -23,27 +24,21 @@
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return 0;
 
-    lps->hdc = GetDC( hwnd );
-    if (!lps->hdc) return 0;
-    
-    SelectVisRgn( lps->hdc, wndPtr->hrgnUpdate );
+    if (!(lps->hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
+			      DCX_INTERSECTRGN | DCX_USESTYLE ))) return 0;
+    GetRgnBox( InquireVisRgn(lps->hdc), &lps->rcPaint );
+
     if (wndPtr->hrgnUpdate)
     {
-	GetRgnBox( wndPtr->hrgnUpdate, &lps->rcPaint );
 	DeleteObject( wndPtr->hrgnUpdate );
 	wndPtr->hrgnUpdate = 0;
+	MSG_DecPaintCount( wndPtr->hmemTaskQ );
     }
-    else
-    {
-	lps->rcPaint.left   = 0;
-	lps->rcPaint.top    = 0;
-	lps->rcPaint.right  = wndPtr->rectClient.right-wndPtr->rectClient.left;
-	lps->rcPaint.bottom = wndPtr->rectClient.bottom-wndPtr->rectClient.top;
-    }    
-
+    wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
+    
     if (!(wndPtr->flags & WIN_ERASE_UPDATERGN)) lps->fErase = TRUE;
     else lps->fErase = !SendMessage( hwnd, WM_ERASEBKGND, lps->hdc, 0 );
-
+    
     return lps->hdc;
 }
 
@@ -63,12 +58,7 @@
 void FillWindow( HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush )
 {
     RECT rect;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    if (!wndPtr) return;
-    rect.left   = 0;
-    rect.top    = 0;
-    rect.right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
-    rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
+    GetClientRect( hwnd, &rect );
     PaintRect( hwndParent, hwnd, hdc, hbrush, &rect );
 }
 
diff --git a/windows/timer.c b/windows/timer.c
index 2aeb88ee..da64961 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -6,21 +6,19 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
-#include <X11/Intrinsic.h>
-
 #include "windows.h"
-
-extern XtAppContext XT_app_context;
+#include "message.h"
 
 
-typedef struct
+typedef struct tagTIMER
 {
-    HWND          hwnd;
-    WORD          msg;  /* WM_TIMER or WM_SYSTIMER */
-    WORD          id;
-    WORD          timeout;
-    FARPROC       proc;
-    XtIntervalId  xtid;
+    HWND             hwnd;
+    WORD             msg;  /* WM_TIMER or WM_SYSTIMER */
+    WORD             id;
+    WORD             timeout;
+    struct tagTIMER *next;
+    DWORD            expires;
+    FARPROC          proc;
 } TIMER;
 
 #define NB_TIMERS            34
@@ -28,39 +26,100 @@
 
 static TIMER TimersArray[NB_TIMERS];
 
+static TIMER * pNextTimer = NULL;  /* Next timer to expire */
+
 
 /***********************************************************************
- *           TIMER_callback
+ *           TIMER_InsertTimer
+ *
+ * Insert the timer at its place in the chain.
  */
-static void TIMER_callback( XtPointer data, XtIntervalId * xtid )
+static void TIMER_InsertTimer( TIMER * pTimer )
 {
-    TIMER * pTimer = (TIMER *) data;
-    
-    pTimer->xtid = 0;  /* In case the timer procedure calls KillTimer */
-    
-    if (pTimer->proc)
+    if (!pNextTimer || (pTimer->expires < pNextTimer->expires))
     {
-	CallWindowProc(pTimer->proc, pTimer->hwnd, pTimer->msg, 
-		       pTimer->id, GetTickCount());
+	pTimer->next = pNextTimer;
+	pNextTimer = pTimer;
     }
-    else 
-	PostMessage( pTimer->hwnd, pTimer->msg, pTimer->id, 0 );
+    else
+    {
+        TIMER * ptr = pNextTimer;	
+	while (ptr->next && (pTimer->expires >= ptr->next->expires))
+	    ptr = ptr->next;
+	pTimer->next = ptr;
+	ptr->next = pTimer;
+    }
+}
+
+
+/***********************************************************************
+ *           TIMER_RemoveTimer
+ *
+ * Remove the timer from the chain.
+ */
+static void TIMER_RemoveTimer( TIMER * pTimer )
+{
+    if (pTimer == pNextTimer) pNextTimer = pTimer->next;
+    else
+    {
+	TIMER * ptr = pNextTimer;
+	while (ptr && (ptr->next != pTimer)) ptr = ptr->next;
+	if (ptr) ptr->next = pTimer->next;
+    }
+    pTimer->next = NULL;
+}
+
+
+/***********************************************************************
+ *           TIMER_NextExpire
+ *
+ * Return time until next timer expiration (-1 if none).
+ */
+static DWORD TIMER_NextExpire( DWORD curTime )
+{
+    if (!pNextTimer) return -1;
+    if (pNextTimer->expires <= curTime) return 0;
+    return pNextTimer->expires - curTime;
+}
+
+
+/***********************************************************************
+ *           TIMER_CheckTimer
+ *
+ * Check whether a timer has expired, and post a message if necessary.
+ * Return TRUE if msg posted, and return time until next expiration in 'next'.
+ */
+BOOL TIMER_CheckTimer( DWORD *next )
+{
+    TIMER * pTimer = pNextTimer;
+    DWORD curTime = GetTickCount();
+    
+    if ((*next = TIMER_NextExpire( curTime )) != 0) return FALSE;
+
+    PostMessage( pTimer->hwnd, pTimer->msg, pTimer->id, (LONG)pTimer->proc );
+    TIMER_RemoveTimer( pTimer );
 
       /* If timeout == 0, the timer has been removed by KillTimer */
     if (pTimer->timeout)
-	pTimer->xtid = XtAppAddTimeOut( XT_app_context, pTimer->timeout,
-				        TIMER_callback, pTimer );
+    {
+	  /* Restart the timer */
+	pTimer->expires = curTime + pTimer->timeout;
+	TIMER_InsertTimer( pTimer );
+    }
+    *next = TIMER_NextExpire( curTime );
+    return TRUE;
 }
 
 
 /***********************************************************************
  *           TIMER_SetTimer
  */
-WORD TIMER_SetTimer( HWND hwnd, WORD id, WORD timeout, FARPROC proc, BOOL sys )
+static WORD TIMER_SetTimer( HWND hwnd, WORD id, WORD timeout,
+			    FARPROC proc, BOOL sys )
 {
     int i;
     TIMER * pTimer;
-    
+
     if (!timeout) return 0;
     if (!hwnd && !proc) return 0;
     
@@ -79,9 +138,10 @@
     pTimer->msg     = sys ? WM_SYSTIMER : WM_TIMER;
     pTimer->id      = id;
     pTimer->timeout = timeout;
+    pTimer->expires = GetTickCount() + timeout;
     pTimer->proc    = proc;
-    pTimer->xtid    = XtAppAddTimeOut( XT_app_context, timeout,
-				       TIMER_callback, pTimer );
+    TIMER_InsertTimer( pTimer );
+    MSG_IncTimerCount( GetTaskQueue(0) );
     return id;
 }
 
@@ -89,7 +149,7 @@
 /***********************************************************************
  *           TIMER_KillTimer
  */
-BOOL TIMER_KillTimer( HWND hwnd, WORD id, BOOL sys )
+static BOOL TIMER_KillTimer( HWND hwnd, WORD id, BOOL sys )
 {
     int i;
     TIMER * pTimer;
@@ -106,13 +166,13 @@
 
       /* Delete the timer */
 
-    if (pTimer->xtid) XtRemoveTimeOut( pTimer->xtid );
     pTimer->hwnd    = 0;
     pTimer->msg     = 0;
     pTimer->id      = 0;
     pTimer->timeout = 0;
     pTimer->proc    = 0;
-    pTimer->xtid    = 0;
+    TIMER_RemoveTimer( pTimer );
+    MSG_DecTimerCount( GetTaskQueue(0) );
     return TRUE;
 }
 
@@ -123,7 +183,7 @@
 WORD SetTimer( HWND hwnd, WORD id, WORD timeout, FARPROC proc )
 {
 #ifdef DEBUG_TIMER    
-    printf( "SetTimer: %d %d %d %08x\n", hwnd, id, timeout, proc );
+    printf( "SetTimer: %d %d %d %p\n", hwnd, id, timeout, proc );
 #endif
     return TIMER_SetTimer( hwnd, id, timeout, proc, FALSE );
 }
@@ -135,7 +195,7 @@
 WORD SetSystemTimer( HWND hwnd, WORD id, WORD timeout, FARPROC proc )
 {
 #ifdef DEBUG_TIMER    
-    printf( "SetSystemTimer: %d %d %d %08x\n", hwnd, id, timeout, proc );
+    printf( "SetSystemTimer: %d %d %d %p\n", hwnd, id, timeout, proc );
 #endif
     return TIMER_SetTimer( hwnd, id, timeout, proc, TRUE );
 }
diff --git a/windows/win.c b/windows/win.c
index d7fe3a2..8411e48 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -10,11 +10,11 @@
 #include <X11/StringDefs.h>
 #include <X11/Core.h>
 #include <X11/Shell.h>
-#include <X11/Xaw/Box.h>
 
 #include "class.h"
 #include "win.h"
 #include "user.h"
+#include "dce.h"
 
 extern Display * XT_display;
 extern Screen * XT_screen;
@@ -22,10 +22,6 @@
 
 static HWND firstWindow = 0;
 
-void SCROLLBAR_CreateScrollBar(LPSTR className, LPSTR Label, HWND hwnd);
-void LISTBOX_CreateListBox(LPSTR className, LPSTR Label, HWND hwnd);
-void COMBOBOX_CreateComboBox(LPSTR className, LPSTR Label, HWND hwnd);
-
 /***********************************************************************
  *           WIN_FindWndPtr
  *
@@ -43,6 +39,76 @@
 
 
 /***********************************************************************
+ *           WIN_UnlinkWindow
+ *
+ * Remove a window from the siblings linked list.
+ */
+BOOL WIN_UnlinkWindow( HWND hwnd )
+{    
+    HWND * curWndPtr;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+
+    if (!wndPtr) return FALSE;
+    if (wndPtr->hwndParent)
+    {
+	WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
+	curWndPtr = &parentPtr->hwndChild;
+    }    
+    else curWndPtr = &firstWindow;
+
+    while (*curWndPtr != hwnd)
+    {
+	WND * curPtr = WIN_FindWndPtr( *curWndPtr );
+	curWndPtr = &curPtr->hwndNext;
+    }
+    *curWndPtr = wndPtr->hwndNext;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           WIN_LinkWindow
+ *
+ * Insert a window into the siblings linked list.
+ * The window is inserted after the specified window, which can also
+ * be specified as HWND_TOP or HWND_BOTTOM.
+ */
+BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter )
+{    
+    HWND * hwndPtr = NULL;  /* pointer to hwnd to change */
+
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr) return FALSE;
+    
+    if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM))
+    {
+	  /* Make hwndPtr point to the first sibling hwnd */
+	if (wndPtr->hwndParent)
+	{
+	    WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
+	    if (parentPtr) hwndPtr = &parentPtr->hwndChild;
+	}
+	else hwndPtr = &firstWindow;
+	if (hwndInsertAfter == HWND_BOTTOM)  /* Find last sibling hwnd */
+	    while (*hwndPtr)
+	    {
+		WND * nextPtr = WIN_FindWndPtr( *hwndPtr );
+		hwndPtr = &nextPtr->hwndNext;
+	    }
+    }
+    else  /* Normal case */
+    {
+	WND * afterPtr = WIN_FindWndPtr( hwndInsertAfter );
+	if (afterPtr) hwndPtr = &afterPtr->hwndNext;
+    }
+    if (!hwndPtr) return FALSE;
+    wndPtr->hwndNext = *hwndPtr;
+    *hwndPtr = hwnd;
+    return TRUE;
+}
+
+
+/***********************************************************************
  *           WIN_FindWinToRepaint
  *
  * Find a window that needs repaint.
@@ -55,8 +121,6 @@
     for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
     {
 	if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
-	if (!wndPtr || !wndPtr->winWidget) continue;
-	if (!XtIsRealized( wndPtr->winWidget )) continue;
 	if (wndPtr->hrgnUpdate) return hwnd;
 	if (wndPtr->hwndChild)
 	{
@@ -114,9 +178,11 @@
     CREATESTRUCT *createStruct;
     HANDLE hcreateStruct;
     int wmcreate;
+    short newwidth, newheight;
 
 #ifdef DEBUG_WIN
-    printf( "CreateWindowEx: %s %s %d,%d %dx%d\n", className, windowName, x, y, width, height );
+    printf( "CreateWindowEx: %s %s %d,%d %dx%d %08x\n",
+	    className, windowName, x, y, width, height, style );
 #endif
 
     if (x == CW_USEDEFAULT) x = 0;
@@ -155,11 +221,12 @@
     wndPtr->hwndOwner  = parent;  /* What else? */
     wndPtr->hClass     = class;
     wndPtr->hInstance  = instance;
-    wndPtr->rectClient.left   = x;
-    wndPtr->rectClient.top    = y;
-    wndPtr->rectClient.right  = x + width;
-    wndPtr->rectClient.bottom = y + height;
-    wndPtr->rectWindow        = wndPtr->rectClient;
+    wndPtr->rectWindow.left   = x;
+    wndPtr->rectWindow.top    = y;
+    wndPtr->rectWindow.right  = x + width;
+    wndPtr->rectWindow.bottom = y + height;
+    wndPtr->rectClient        = wndPtr->rectWindow;
+    wndPtr->hmemTaskQ         = GetTaskQueue(0);
     wndPtr->hrgnUpdate        = 0;
     wndPtr->hwndLastActive    = 0;
     wndPtr->lpfnWndProc       = classPtr->wc.lpfnWndProc;
@@ -169,43 +236,70 @@
     wndPtr->wIDmenu           = menu;
     wndPtr->hText             = 0;
     wndPtr->flags             = 0;
+    wndPtr->hCursor           = 0;
+    wndPtr->hWndVScroll       = 0;
+    wndPtr->hWndHScroll       = 0;
 
     if (classPtr->wc.cbWndExtra)
 	memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
-    if (classPtr->wc.style & CS_OWNDC)
-	wndPtr->hdc = CreateDC( "DISPLAY", NULL, NULL, NULL);
-    else wndPtr->hdc = 0;
     classPtr->cWindows++;
 
+      /* Get class or window DC if needed */
+    if (classPtr->wc.style & CS_OWNDC)
+    {
+	wndPtr->flags |= WIN_OWN_DC;
+	wndPtr->hdce = DCE_AllocDCE( DCE_WINDOW_DC );
+    }
+    else if (classPtr->wc.style & CS_CLASSDC)
+    {
+	wndPtr->flags |= WIN_CLASS_DC;
+	wndPtr->hdce = classPtr->hdce;
+    }
+    else wndPtr->hdce = 0;
+
       /* Insert the window in the linked list */
 
-    if (parent)
-    {
-	wndPtr->hwndNext = parentPtr->hwndChild;
-	parentPtr->hwndChild = hwnd;
-    }
-    else  /* Top-level window */
-    {
-	wndPtr->hwndNext = firstWindow;
-	firstWindow = hwnd;
-    }
-    
-    if (!strcasecmp(className, "SCROLLBAR"))
-    {
-	SCROLLBAR_CreateScrollBar(className, windowName, hwnd);
-	goto WinCreated;
-    }
-    if (!strcasecmp(className, "LISTBOX"))
-    {
-	LISTBOX_CreateListBox(className, windowName, hwnd);
-	goto WinCreated;
-    }
+    WIN_LinkWindow( hwnd, HWND_TOP );
+
     if (!strcasecmp(className, "COMBOBOX"))
     {
-	COMBOBOX_CreateComboBox(className, windowName, hwnd);
-	goto WinCreated;
+	height = 16;
     }
-      /* Create the widgets */
+
+#ifdef USE_XLIB
+    {
+	XSetWindowAttributes win_attr;
+	Window parentWindow;
+	int x_rel, y_rel;
+	
+	win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
+	                      PointerMotionMask | ButtonPressMask |
+			      ButtonReleaseMask | StructureNotifyMask |
+			      FocusChangeMask | EnterWindowMask;
+	win_attr.override_redirect = /*True*/ False;
+	win_attr.colormap = COLOR_WinColormap;
+	if (style & WS_CHILD)
+	{
+	    parentWindow = parentPtr->window;
+	    x_rel = x + parentPtr->rectClient.left-parentPtr->rectWindow.left;
+	    y_rel = y + parentPtr->rectClient.top-parentPtr->rectWindow.top;
+	}
+	else
+	{
+	    parentWindow = DefaultRootWindow( XT_display );
+	    x_rel = x;
+	    y_rel = y;
+	}
+	wndPtr->window = XCreateWindow( XT_display, parentWindow,
+				        x_rel, y_rel, width, height, 0,
+				        CopyFromParent, InputOutput,
+				        CopyFromParent,
+				        CWEventMask | CWOverrideRedirect |
+				        CWColormap, &win_attr );
+	XStoreName( XT_display, wndPtr->window, windowName );
+    }
+#else
+    /* Create the widgets */
 
     if (style & WS_CHILD)
     {
@@ -223,6 +317,7 @@
 						    XtNwidth, width,
 						    XtNheight, height,
 						    XtNborderColor, borderCol,
+						    XtNmappedWhenManaged, FALSE,
 						    NULL );
 	}
 	else
@@ -235,6 +330,7 @@
 						    XtNwidth, width,
 						    XtNheight, height,
 						    XtNborderWidth, 0,
+						    XtNmappedWhenManaged, FALSE,
 						    NULL );
 	}
     }
@@ -247,6 +343,7 @@
 						 XtNx, x,
 						 XtNy, y,
 						 XtNcolormap, COLOR_WinColormap,
+						 XtNmappedWhenManaged, FALSE,
 						 NULL );
 	wndPtr->compositeWidget = XtVaCreateManagedWidget(className,
 						    formWidgetClass,
@@ -296,8 +393,24 @@
 					NULL );
 	}
     }
+    if (wndPtr->shellWidget) XtRealizeWidget( wndPtr->shellWidget );
+    if (wndPtr->compositeWidget) XtRealizeWidget( wndPtr->compositeWidget );
+    XtRealizeWidget( wndPtr->winWidget );
+    wndPtr->window = XtWindow( wndPtr->winWidget );
+#endif  /* USE_XLIB */
 
-WinCreated:
+    if ((style & WS_VSCROLL) == WS_VSCROLL) {
+    	newheight = height - (((style & WS_HSCROLL) == WS_HSCROLL) ? 16 : 0);
+	wndPtr->hWndVScroll = CreateWindow("SCROLLBAR", "",
+		WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBS_VERT,
+		width - 16, 0, 16, newheight, hwnd, 2, instance, 0L);
+	}
+    if ((style & WS_HSCROLL) == WS_HSCROLL) {
+    	newwidth = width - (((style & WS_VSCROLL) == WS_VSCROLL) ? 16 : 0);
+	wndPtr->hWndHScroll = CreateWindow("SCROLLBAR", "",
+		WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBS_HORZ,
+		0, height - 16, newwidth, 16, hwnd, 3, instance, 0L);
+	}
 
       /* Send the WM_CREATE message */
 	
@@ -318,7 +431,24 @@
 
     wmcreate = SendMessage( hwnd, WM_NCCREATE, 0, (LONG)createStruct );
     if (!wmcreate) wmcreate = -1;
-    else wmcreate = SendMessage( hwnd, WM_CREATE, 0, (LONG)createStruct );
+    else
+    {
+	  /* Send WM_NCCALCSIZE message */
+	NCCALCSIZE_PARAMS *params;
+	HANDLE hparams;
+	hparams = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) );
+	if (hparams)
+	{
+	    params = (NCCALCSIZE_PARAMS *) GlobalLock( hparams );
+	    params->rgrc[0] = wndPtr->rectWindow;
+	    params->lppos = NULL;
+	    SendMessage( hwnd, WM_NCCALCSIZE, FALSE, (LONG)params );
+	    wndPtr->rectClient = params->rgrc[0];
+	    GlobalUnlock( hparams );
+	    GlobalFree( hparams );
+	}	
+	wmcreate = SendMessage( hwnd, WM_CREATE, 0, (LONG)createStruct );
+    }
 
     GlobalUnlock( hcreateStruct );
     GlobalFree( hcreateStruct );
@@ -329,18 +459,27 @@
 
 	if (parent) parentPtr->hwndChild = wndPtr->hwndNext;
 	else firstWindow = wndPtr->hwndNext;
+#ifdef USE_XLIB
+	XDestroyWindow( XT_display, wndPtr->window );
+#else	
 	if (wndPtr->shellWidget) XtDestroyWidget( wndPtr->shellWidget );
 	else XtDestroyWidget( wndPtr->winWidget );
-	if (wndPtr->hdc) DeleteDC( wndPtr->hdc );
+#endif
+	if (wndPtr->flags & WIN_OWN_DC) DCE_FreeDCE( wndPtr->hdce );
 	classPtr->cWindows--;
 	USER_HEAP_FREE( hwnd );
 	return 0;
     }
-    
-    EVENT_AddHandlers( wndPtr->winWidget, hwnd );
 
-    if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
+#ifdef USE_XLIB    
+    EVENT_AddHandlers( wndPtr->window, hwnd );
+#else
+    EVENT_AddHandlers( wndPtr->winWidget, hwnd );
+#endif
+
     WIN_SendParentNotify( hwnd, wndPtr, WM_CREATE );
+    
+    if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
     return hwnd;
 }
 
@@ -350,7 +489,6 @@
 BOOL DestroyWindow( HWND hwnd )
 {
     WND * wndPtr;
-    HWND * curWndPtr;
     CLASS * classPtr;
     
       /* Initialisation */
@@ -366,30 +504,24 @@
     
       /* Destroy all children */
 
+    if (wndPtr->hWndVScroll) DestroyWindow(wndPtr->hWndVScroll);
+    if (wndPtr->hWndHScroll) DestroyWindow(wndPtr->hWndHScroll);
     while (wndPtr->hwndChild)  /* The child removes itself from the list */
 	DestroyWindow( wndPtr->hwndChild );
 
       /* Remove the window from the linked list */
 
-    if (wndPtr->hwndParent)
-    {
-	WND * parentPtr = WIN_FindWndPtr( wndPtr->hwndParent );
-	curWndPtr = &parentPtr->hwndChild;
-    }    
-    else curWndPtr = &firstWindow;
-
-    while (*curWndPtr != hwnd)
-    {
-	WND * curPtr = WIN_FindWndPtr( *curWndPtr );
-	curWndPtr = &curPtr->hwndNext;
-    }
-    *curWndPtr = wndPtr->hwndNext;
+    WIN_UnlinkWindow( hwnd );
 
       /* Destroy the window */
 
+#ifdef USE_XLIB
+    XDestroyWindow( XT_display, wndPtr->window );
+#else
     if (wndPtr->shellWidget) XtDestroyWidget( wndPtr->shellWidget );
     else XtDestroyWidget( wndPtr->winWidget );
-    if (wndPtr->hdc) DeleteDC( wndPtr->hdc );
+#endif
+    if (wndPtr->flags & WIN_OWN_DC) DCE_FreeDCE( wndPtr->hdce );
     classPtr->cWindows--;
     USER_HEAP_FREE( hwnd );
     return TRUE;
@@ -397,100 +529,6 @@
 
 
 /***********************************************************************
- *           GetWindowRect   (USER.32)
- */
-void GetWindowRect( HWND hwnd, LPRECT rect ) 
-{
-    int x, y, width, height;  
-    WND * wndPtr = WIN_FindWndPtr( hwnd ); 
-
-    if (wndPtr) 
-    {
-	XtVaGetValues(wndPtr->winWidget,
-		      XtNx, &x, XtNy, &y,
-		      XtNwidth, &width,
-		      XtNheight, &height,
-		      NULL );
-	rect->left  = x & 0xffff;
-	rect->top = y & 0xffff;
-	rect->right  = width & 0xffff;
-	rect->bottom = height & 0xffff;
-    }
-}
-
-
-/***********************************************************************
- *           GetClientRect   (USER.33)
- */
-void GetClientRect( HWND hwnd, LPRECT rect ) 
-{
-    int width, height;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-
-    rect->left = rect->top = rect->right = rect->bottom = 0;
-    if (wndPtr) 
-    {
-	XtVaGetValues(wndPtr->winWidget,
-		      XtNwidth, &width,
-		      XtNheight, &height,
-		      NULL );
-	rect->right  = width & 0xffff;
-	rect->bottom = height & 0xffff;
-    }
-}
-
-
-/***********************************************************************
- *           ShowWindow   (USER.42)
- */
-BOOL ShowWindow( HWND hwnd, int cmd ) 
-{    
-    int width, height;
-    
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    if (wndPtr) 
-    {
-	if (wndPtr->shellWidget) XtRealizeWidget( wndPtr->shellWidget );
-	XtVaGetValues(wndPtr->winWidget, 
-		      XtNwidth, &width,
-		      XtNheight, &height,
-		      NULL );
-	switch(cmd)
-	    {
-	    case SW_HIDE:
-		XtSetMappedWhenManaged(wndPtr->winWidget, FALSE);
-	    	wndPtr->dwStyle &= (WS_VISIBLE ^ 0xFFFFFFFL);
-		SendMessage( hwnd, WM_SHOWWINDOW, FALSE, 0 );
-		break;
-	    case SW_SHOWMINNOACTIVE:
-	    case SW_SHOWMINIMIZED:
-	    case SW_MINIMIZE:
-	    	wndPtr->dwStyle |= WS_ICONIC;
-	    	goto WINVisible;
-	    case SW_SHOWNA:
-	    case SW_SHOWNOACTIVATE:
-	    case SW_MAXIMIZE:
-	    case SW_SHOWMAXIMIZED:
-	    case SW_SHOW:
-	    case SW_NORMAL:
-	    case SW_SHOWNORMAL:
-	    	wndPtr->dwStyle &= (WS_ICONIC ^ 0xFFFFFFFL);
-WINVisible:
-		XtSetMappedWhenManaged(wndPtr->winWidget, TRUE);
-	    	wndPtr->dwStyle |= WS_VISIBLE;
-		SendMessage( hwnd, WM_SIZE, SIZE_RESTORED, 
-			(width & 0xffff) | (height << 16) );
-		SendMessage( hwnd, WM_SHOWWINDOW, TRUE, 0 );
-		break;
-	    default:
-		break;
-	    }
-    }
-    return TRUE;
-}
-
-
-/***********************************************************************
  *           CloseWindow   (USER.43)
  */
 void CloseWindow(HWND hWnd)
@@ -498,7 +536,6 @@
     WND * wndPtr = WIN_FindWndPtr(hWnd);
     if (wndPtr->dwStyle & WS_CHILD) return;
     ShowWindow(hWnd, SW_MINIMIZE);
-    PostMessage(hWnd, WM_CLOSE, 0, 0L);
 }
 
  
@@ -508,7 +545,6 @@
  */
 BOOL OpenIcon(HWND hWnd)
 {
-    WND * wndPtr = WIN_FindWndPtr(hWnd);
     if (!IsIconic(hWnd)) return FALSE;
     ShowWindow(hWnd, SW_SHOWNORMAL);
     return(TRUE);
@@ -523,35 +559,9 @@
 {
     return((HWND)NULL);
 }
-
  
  
 /***********************************************************************
- *           MoveWindow   (USER.56)
- */
-void MoveWindow(HWND hWnd, short x, short y, short w, short h, BOOL bRepaint)
-{    
-    WND * wndPtr = WIN_FindWndPtr( hWnd );
-    if (wndPtr) 
-    {
-	wndPtr->rectClient.left   = x;
-	wndPtr->rectClient.top    = y;
-	wndPtr->rectClient.right  = x + w;
-	wndPtr->rectClient.bottom = y + h;
-	XtVaSetValues(wndPtr->winWidget, XtNx, x, XtNy, y,
-		      XtNwidth, w, XtNheight, h, NULL );
-	SendMessage(hWnd, WM_MOVE, 0, MAKELONG(x, y)); 
-	printf("MoveWindow(%X, %d, %d, %d, %d, %d); !\n", 
-			hWnd, x, y, w, h, bRepaint);
-	if (bRepaint) {
-	    InvalidateRect(hWnd, NULL, TRUE);
-	    UpdateWindow(hWnd);
-	    }
-    }
-}
-
-
-/***********************************************************************
  *           UpdateWindow   (USER.124)
  */
 void UpdateWindow( HWND hwnd )
@@ -578,8 +588,10 @@
  */
 BOOL SetMenu(HWND hwnd, HMENU hmenu)
 {
+#ifdef USE_XLIB
+    return FALSE;
+#else
     WND *wndPtr;
-    
     wndPtr = WIN_FindWndPtr(hwnd);
     if (wndPtr == NULL)
 	return FALSE;
@@ -618,44 +630,7 @@
     }
 
     return TRUE;
-}
-
-
-/***********************************************************************
- *           SetWindowPos   (USER.232)
- */
-void SetWindowPos(HWND hWnd, HWND hWndInsertAfter, short x, short y, short w, short h, WORD wFlag)
-{    
-    WND * wndPtr = WIN_FindWndPtr( hWnd );
-    if (wndPtr) 
-    {
-	if ((wFlag & SWP_NOMOVE) != SWP_NOMOVE) {
-	    wndPtr->rectClient.left   = x;
-	    wndPtr->rectClient.top    = y;
-	    XtVaSetValues(wndPtr->winWidget, XtNx, x, XtNy, y, NULL );
-	    }
-	if ((wFlag & SWP_NOSIZE) != SWP_NOSIZE) {
-	    wndPtr->rectClient.right  = x + w;
-	    wndPtr->rectClient.bottom = y + h;
-	    XtVaSetValues(wndPtr->winWidget, XtNwidth, w, XtNheight, h, NULL );
-	    }
-	if ((wFlag & SWP_NOREDRAW) != SWP_NOREDRAW) {
-	    InvalidateRect(hWnd, NULL, TRUE);
-	    UpdateWindow(hWnd);
-	    }
-	if ((wFlag & SWP_HIDEWINDOW) == SWP_HIDEWINDOW) 
-	    ShowWindow(hWnd, SW_HIDE);
-	if ((wFlag & SWP_SHOWWINDOW) == SWP_SHOWWINDOW) 
-	    ShowWindow(hWnd, SW_SHOW);
-/*
-	if ((wFlag & SWP_NOACTIVATE) != SWP_NOACTIVATE) 
-	    SetActiveWindow(hWnd);
-	if ((wFlag & SWP_NOZORDER) != SWP_NOZORDER) 
-	    { }
-*/
-	printf("SetWindowPos(%X, %X, %d, %d, %d, %d, %X); !\n", 
-		hWnd, hWndInsertAfter, x, y, w, h, wFlag);
-    }
+#endif  /* USE_XLIB */
 }
 
 
@@ -748,21 +723,6 @@
 }
 
 
-/***********************************************************************
- *           IsIconic   (USER.31)
- */
-BOOL IsIconic(HWND hWnd)
-{
-    WND * wndPtr; 
-    if (hWnd == 0) return(FALSE);
-    wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr == 0) return(FALSE);
-    if (wndPtr->dwStyle & WS_ICONIC) return(TRUE);
-    return(FALSE);
-}
-
- 
- 
 /*******************************************************************
  *         GetWindowText          (USER.36)
  */
@@ -796,7 +756,7 @@
 BOOL IsWindow( HWND hwnd )
 {
     WND * wndPtr = WIN_FindWndPtr( hwnd );
-    return (wndPtr->dwMagic == WND_MAGIC);
+    return ((wndPtr != NULL) && (wndPtr->dwMagic == WND_MAGIC));
 }
 
 
@@ -806,6 +766,7 @@
 HWND GetParent(HWND hwnd)
 {
     WND *wndPtr = WIN_FindWndPtr(hwnd);
+    if (!wndPtr) return 0;
     return wndPtr->hwndParent;
 }
 
@@ -838,14 +799,9 @@
  */
 BOOL IsWindowVisible(HWND hWnd)
 {
-    WND * wndPtr; 
-    if (hWnd == 0) return(FALSE);
-    wndPtr = WIN_FindWndPtr(hWnd);
+    WND * wndPtr = WIN_FindWndPtr(hWnd);
     if (wndPtr == 0) return(FALSE);
-    if (wndPtr->dwStyle & WS_VISIBLE) {
-	if (XtIsRealized(wndPtr->winWidget))  return(TRUE);
-    	}
-    return(FALSE);
+    else return ((wndPtr->dwStyle & WS_VISIBLE) != 0);
 }
 
  
diff --git a/windows/winpos.c b/windows/winpos.c
new file mode 100644
index 0000000..0b474e2
--- /dev/null
+++ b/windows/winpos.c
@@ -0,0 +1,389 @@
+/*
+ * Window position related functions.
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+
+#include "win.h"
+
+extern Display * XT_display;
+extern Screen * XT_screen;
+
+
+/***********************************************************************
+ *           GetWindowRect   (USER.32)
+ */
+void GetWindowRect( HWND hwnd, LPRECT rect ) 
+{
+    WND * wndPtr = WIN_FindWndPtr( hwnd ); 
+    if (!wndPtr) return;
+    
+    *rect = wndPtr->rectWindow;
+    if (wndPtr->hwndParent)
+	MapWindowPoints( wndPtr->hwndParent, 0, (POINT *)rect, 2 );
+}
+
+
+/***********************************************************************
+ *           GetClientRect   (USER.33)
+ */
+void GetClientRect( HWND hwnd, LPRECT rect ) 
+{
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+
+    rect->left = rect->top = rect->right = rect->bottom = 0;
+    if (wndPtr) 
+    {
+	rect->right  = wndPtr->rectClient.right - wndPtr->rectClient.left;
+	rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
+    }
+}
+
+
+/*******************************************************************
+ *         ClientToScreen   (USER.28)
+ */
+void ClientToScreen( HWND hwnd, LPPOINT lppnt )
+{
+    MapWindowPoints( hwnd, 0, lppnt, 1 );
+}
+
+
+/*******************************************************************
+ *         ScreenToClient   (USER.29)
+ */
+void ScreenToClient( HWND hwnd, LPPOINT lppnt )
+{
+    MapWindowPoints( 0, hwnd, lppnt, 1 );
+}
+
+
+/*******************************************************************
+ *         MapWindowPoints   (USER.258)
+ */
+void MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, WORD count )
+{
+    WND * wndPtr;
+    POINT * curpt;
+    POINT origin = { 0, 0 };
+    WORD i;
+
+      /* Translate source window origin to screen coords */
+    while(hwndFrom)
+    {
+	wndPtr = WIN_FindWndPtr( hwndFrom );
+	origin.x += wndPtr->rectClient.left;
+	origin.y += wndPtr->rectClient.top;
+	hwndFrom = wndPtr->hwndParent;
+    }
+
+      /* Translate origin to destination window coords */
+    while(hwndTo)
+    {
+	wndPtr = WIN_FindWndPtr( hwndTo );
+	origin.x -= wndPtr->rectClient.left;
+	origin.y -= wndPtr->rectClient.top;
+	hwndTo = wndPtr->hwndParent;
+    }    
+
+      /* Translate points */
+    for (i = 0, curpt = lppt; i < count; i++, curpt++)
+    {
+	curpt->x += origin.x;
+	curpt->y += origin.y;
+    }
+}
+
+
+/***********************************************************************
+ *           IsIconic   (USER.31)
+ */
+BOOL IsIconic(HWND hWnd)
+{
+    WND * wndPtr = WIN_FindWndPtr(hWnd);
+    if (wndPtr == NULL) return FALSE;
+    return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
+}
+ 
+ 
+/***********************************************************************
+ *           IsZoomed   (USER.272)
+ */
+BOOL IsZoomed(HWND hWnd)
+{
+    WND * wndPtr = WIN_FindWndPtr(hWnd);
+    if (wndPtr == NULL) return FALSE;
+    return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
+}
+
+
+/***********************************************************************
+ *           MoveWindow   (USER.56)
+ */
+BOOL MoveWindow( HWND hwnd, short x, short y, short cx, short cy, BOOL repaint)
+{    
+    int flags = SWP_NOZORDER | SWP_NOACTIVATE;
+    if (!repaint) flags |= SWP_NOREDRAW;
+#ifdef DEBUG_WIN    
+    printf( "MoveWindow: %d %d,%d %dx%d %d\n", hwnd, x, y, cx, cy, repaint );
+#endif
+    return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
+}
+
+
+/***********************************************************************
+ *           ShowWindow   (USER.42)
+ */
+BOOL ShowWindow( HWND hwnd, int cmd ) 
+{    
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+    BOOL wasVisible;
+    int swpflags = 0;
+
+#ifdef DEBUG_WIN
+    printf("ShowWindow: hwnd=%d, cmd=%d\n", hwnd, cmd);
+#endif
+    
+    if (!wndPtr) return FALSE;
+    wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
+    switch(cmd)
+    {
+        case SW_HIDE:
+	    if (!wasVisible) return FALSE;  /* Nothing to do */
+	    swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
+		        SWP_NOACTIVATE | SWP_NOZORDER;
+	    break;
+
+	case SW_SHOWMINNOACTIVE:
+	case SW_SHOWMINIMIZED:
+	case SW_MINIMIZE:
+	    wndPtr->dwStyle |= WS_MINIMIZE;
+	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
+		        SWP_NOACTIVATE | SWP_NOZORDER;
+	    break;
+
+	case SW_SHOWNA:
+	case SW_SHOWNOACTIVATE:
+	case SW_MAXIMIZE:
+	case SW_SHOWMAXIMIZED:
+	case SW_SHOW:
+	case SW_NORMAL:
+	case SW_SHOWNORMAL:
+	    wndPtr->dwStyle &= ~WS_MINIMIZE;
+	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
+		        SWP_NOACTIVATE | SWP_NOZORDER;
+	    break;
+    }
+    SendMessage( hwnd, WM_SHOWWINDOW, (cmd != SW_HIDE), 0 );
+    SetWindowPos( hwnd, 0, 0, 0, 0, 0, swpflags );
+
+      /* Send WM_SIZE and WM_MOVE messages if not already done */
+    if (!(wndPtr->flags & WIN_GOT_SIZEMSG))
+    {
+	int wParam = SIZE_RESTORED;
+	if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
+	else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
+	wndPtr->flags |= WIN_GOT_SIZEMSG;
+	SendMessage( hwnd, WM_SIZE, wParam,
+		     MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
+			    wndPtr->rectClient.bottom-wndPtr->rectClient.top));
+	SendMessage( hwnd, WM_MOVE, 0,
+		   MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
+    }
+    return wasVisible;
+}
+
+
+/***********************************************************************
+ *           SetWindowPos   (USER.232)
+ */
+/* Unimplemented flags: SWP_NOREDRAW, SWP_NOACTIVATE
+ */
+/* Note: all this code should be in the DeferWindowPos() routines,
+ * and SetWindowPos() should simply call them.  This will be implemented
+ * some day...
+ */
+BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, short x, short y,
+		   short cx, short cy, WORD flags )
+{
+    WINDOWPOS *winPos;
+    HANDLE hmem = 0;
+    RECT newWindowRect, newClientRect;
+    WND *wndPtr;
+    int calcsize_result = 0;
+#ifdef USE_XLIB
+    XWindowChanges winChanges;
+    int changeMask = 0;
+#endif
+
+#ifdef DEBUG_WIN
+    printf( "SetWindowPos: %d %d %d,%d %dx%d 0x%x\n",
+	    hwnd, hwndInsertAfter, x, y, cx, cy, flags );
+#endif
+
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
+    if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW))
+	flags |= SWP_NOMOVE | SWP_NOSIZE;
+
+      /* Send WM_WINDOWPOSCHANGING message */
+
+    if (!(hmem = GlobalAlloc( GMEM_MOVEABLE,sizeof(WINDOWPOS) ))) return FALSE;
+    winPos = (WINDOWPOS *)GlobalLock( hmem );
+    winPos->hwnd = hwnd;
+    winPos->hwndInsertAfter = hwndInsertAfter;
+    winPos->x = x;
+    winPos->y = y;
+    winPos->cx = cx;
+    winPos->cy = cy;
+    winPos->flags = flags;
+    SendMessage( hwnd, WM_WINDOWPOSCHANGING, 0, (LONG)winPos );
+
+      /* Calculate new position and size */
+
+    newWindowRect = wndPtr->rectWindow;
+    newClientRect = wndPtr->rectClient;
+
+    if (!(winPos->flags & SWP_NOSIZE))
+    {
+	newWindowRect.right  = newWindowRect.left + winPos->cx;
+	newWindowRect.bottom = newWindowRect.top + winPos->cy;
+    }
+
+    if (!(winPos->flags & SWP_NOMOVE))
+    {
+	newWindowRect.left    = winPos->x;
+	newWindowRect.top     = winPos->y;
+	newWindowRect.right  += winPos->x - wndPtr->rectWindow.left;
+	newWindowRect.bottom += winPos->y - wndPtr->rectWindow.top;
+    }
+
+      /* Reposition window in Z order */
+
+    if (!(winPos->flags & SWP_NOZORDER))
+    {
+	hwndInsertAfter = winPos->hwndInsertAfter;
+
+	  /* TOPMOST not supported yet */
+	if ((hwndInsertAfter == HWND_TOPMOST) ||
+	    (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
+
+	  /* Make sure hwndInsertAfter is a sibling of hwnd */
+	if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
+	    if (wndPtr->hwndParent != GetParent(hwndInsertAfter)) goto Abort;
+
+	WIN_UnlinkWindow( hwnd );
+	WIN_LinkWindow( hwnd, hwndInsertAfter );
+    }
+
+      /* Recalculate client area position */
+
+    if (winPos->flags & SWP_FRAMECHANGED)
+    {
+	  /* Send WM_NCCALCSIZE message */
+	NCCALCSIZE_PARAMS *params;
+	HANDLE hparams;
+	
+	if (!(hparams = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) )))
+	    goto Abort;
+	params = (NCCALCSIZE_PARAMS *) GlobalLock( hparams );
+	params->rgrc[0] = newWindowRect;
+	params->rgrc[1] = wndPtr->rectWindow;
+	params->rgrc[2] = wndPtr->rectClient;
+	params->lppos = winPos;
+	calcsize_result = SendMessage(hwnd, WM_NCCALCSIZE, TRUE, (LONG)params);
+	GlobalUnlock( hparams );
+	GlobalFree( hparams );
+	newClientRect = params->rgrc[0];
+	/* Handle result here */
+    }
+    else
+    {
+	newClientRect.left   = newWindowRect.left + wndPtr->rectClient.left
+	                       - wndPtr->rectWindow.left;
+	newClientRect.top    = newWindowRect.top + wndPtr->rectClient.top
+	                       - wndPtr->rectWindow.top;
+	newClientRect.right  = newWindowRect.right + wndPtr->rectClient.right
+	                       - wndPtr->rectWindow.right;
+	newClientRect.bottom = newWindowRect.bottom + wndPtr->rectClient.bottom
+	                       - wndPtr->rectWindow.bottom;
+    }
+    
+      /* Perform the moving and resizing */
+#ifdef USE_XLIB
+    if (!(winPos->flags & SWP_NOMOVE))
+    {
+	WND * parentPtr;
+	winChanges.x = newWindowRect.left;
+	winChanges.y = newWindowRect.top;
+	if (wndPtr->hwndParent)
+	{
+	    parentPtr = WIN_FindWndPtr(wndPtr->hwndParent);
+	    winChanges.x += parentPtr->rectClient.left-parentPtr->rectWindow.left;
+	    winChanges.y += parentPtr->rectClient.top-parentPtr->rectWindow.top;
+	}
+	changeMask |= CWX | CWY;
+    }
+    if (!(winPos->flags & SWP_NOSIZE))
+    {
+	winChanges.width  = newWindowRect.right - newWindowRect.left;
+	winChanges.height = newWindowRect.bottom - newWindowRect.top;
+	changeMask |= CWWidth | CWHeight;
+    }
+    if (!(winPos->flags & SWP_NOZORDER))
+    {
+	if (hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
+	else winChanges.stack_mode = Below;
+	if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
+	{
+	    WND * insertPtr = WIN_FindWndPtr( hwndInsertAfter );
+	    winChanges.sibling = insertPtr->window;
+	    changeMask |= CWSibling;
+	}
+	changeMask |= CWStackMode;
+    }
+    if (changeMask) XConfigureWindow( XT_display, wndPtr->window,
+				      changeMask, &winChanges );
+#endif
+
+    if (winPos->flags & SWP_SHOWWINDOW)
+    {
+	wndPtr->dwStyle |= WS_VISIBLE;
+#ifdef USE_XLIB
+	XMapWindow( XT_display, wndPtr->window );
+#else		
+	if (wndPtr->shellWidget) XtMapWidget( wndPtr->shellWidget );
+	else XtMapWidget( wndPtr->winWidget );
+#endif
+    }
+    else if (winPos->flags & SWP_HIDEWINDOW)
+    {
+	wndPtr->dwStyle &= ~WS_VISIBLE;
+#ifdef USE_XLIB
+	XUnmapWindow( XT_display, wndPtr->window );
+#else		
+	if (wndPtr->shellWidget) XtUnmapWidget( wndPtr->shellWidget );
+	else XtUnmapWidget( wndPtr->winWidget );
+#endif	
+    }
+
+      /* Finally send the WM_WINDOWPOSCHANGED message */
+    wndPtr->rectWindow = newWindowRect;
+    wndPtr->rectClient = newClientRect;
+    SendMessage( hwnd, WM_WINDOWPOSCHANGED, 0, (LONG)winPos );
+    GlobalUnlock( hmem );
+    GlobalFree( hmem );
+
+    return TRUE;
+
+ Abort:  /* Fatal error encountered */
+    if (hmem)
+    {
+	GlobalUnlock( hmem );
+	GlobalFree( hmem );
+    }
+    return FALSE;
+}
+
+
diff --git a/wine.ini b/wine.ini
new file mode 100644
index 0000000..d9958be
--- /dev/null
+++ b/wine.ini
@@ -0,0 +1,19 @@
+[drives]
+a=/mnt/fd0
+c=/dos
+d=/usr/windows
+e=/home/bob/Wine/work
+f=/home/bob/test
+
+[wine]
+windows=c:\windows
+system=c:\windows\system
+temp=c:\temp
+path=c:\windows;c:\windows\system;e:\;e:\test;f:\
+
+[serialports]
+com1=/dev/cua0
+com2=/dev/cua1
+
+[parallelports]
+lpt1=/dev/lp0