Release 940405

Tue Apr  5 14:36:59 1994  Bob Amstadt  (bob@pooh)

	* [include/mdi.h] [windows/mdi.c]
	Use WM_PARENTNOTIFY messages to activate children.
	Generate WM_CHILDACTIVATE messages.
	Beginnings handler for maxmized child window.
	Clean up when children are destroyed.

	* [windows/message.c] [windows/nonclient.c] [windows/winpos.c]
	Removed code add 94/03/26.

Apr 4, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [control/menu.c]
	Make mouse menu navigation working again. :-))
	(be carefull, clicking outside menus (ie.: clientrect) 
	not resolved yet)

	* [windows/nonclient.c]  [controls/scroll.c]
	Bugs fix in NCTrackScrollBars().

	* [misc/dos_fs.c]
	Bug fix in 'ToDos()' in conversion for '/',
		(example: '/window/' was translated to 'WINDOWs').

	* [miscemu/int21.c]
	Function ChangeDir() extract possible drive before DOS_ChangeDir().

	* [loader/library.c]  [loader/wine.c]
	Playing around moving function GetProcAddress() and put some code in.

Mon Apr  4 21:39:07 1994  Alexandre Julliard (julliard@lamisun.epfl.ch)

	* [misc/main.c]
	Better explanation of command-line options.

	* [objects/dib.c]
	Implemented SetDIBitsToDevice().

	* [windows/dc.c]
	Bug fix in SetDCState().

	* [windows/event.c]
	Removed WS_DISABLED handling (now done in message.c).

	* [windows/message.c]
	Added sending a WM_PARENTNOTIFY message in MSG_TranslateMouseMsg().
	Use WindowFromPoint() to find the window for mouse events, taking
	into account disabled windows.

	* [windows/painting.c]
	Bug fix in BeginPaint() to allow calling it at other times than
	on WM_PAINT (Solitaire needs it...)

	* [windows/win.c]
	Implemented FindWindow().
	Rewritten EnableWindow() to behave more like Windows.

	* [windows/winpos.c]
	Rewritten WindowFromPoint() to also search child windows.

Mon Apr  4 17:36:32 1994  Erik Bos (erik@trashcan.hacktic.nl)

	* [include/int21.h] -> [msdos.h]
	renamed.

	* [miscemu/int10.h] [miscemu/int25.h] [miscemu/int26.h] 
	new, added for int 10, 25 and 26.

	* [miscemu/ioports.c]
	new, added to allow win apps to use ioports.

	* [loader/signal.c]
	Added support for in, inb, out, outb instructions.

Sun Mar 27 13:40:25 1994  Bob Amstadt  (bob@pooh)

	* controls/menu.c (InsertMenu): Changed to use FindMenuItem().

Sat Mar 26 21:23:55 1994  Bob Amstadt  (bob@pooh)

	* [windows/mdi.c]
	Window list properly updated.

	* [windows/message.c]
	Call WINPOS_ChildActivate() when mouse pressed.

	* [windows/nonclient.c]
	Use WINPOS_IsAnActiveWindow() instead of GetActiveWindow() in
	NC_HandleNCPaint().

	* [windows/winpos.c]
	Created functions WINPOS_IsAnActiveWindow() and WINPOS_ActivateChild()

Thu Mar 24 14:49:17 1994  Bob Amstadt  (bob@pooh)

	* controls/menu.c (DeleteMenu): Changed to use FindMenuItem
	(DeleteMenu): Many bug fixes.

	* [controls/menu.c]
	Created function FindMenuItem().

Thu Mar 24 14:17:24 1994  Bob Amstadt  (bob@pooh)

	* [windows/win.c]
	Removed incorrect MDI handling code from CreateWindowEx().

	* [controls/menu.c]
	MF_STRING items needed to allocate a private copy of string.

	* [controls/menu.c]
	Fixed buggy calls to GlobalFree().

	* [memory/global.c]
	Eliminated some redundant code with function call.

Wed Mar 23 1994 Pentti Moilanen (pentti.moilanen@ntc.nokia.com)

	* [windows/timer.c]
	timer list pointers looped in InsertTimer

Tue Mar 29 13:32:08 MET DST 1994  julliard@di.epfl.ch (Alexandre Julliard)

	* [misc/cursor.c]
	A few changes for desktop window support.

	* [misc/main.c]
	Added -depth option.

	* [misc/rect.c]
	Yet another bug fix in SubtractRect().

	* [objects/bitmap.c]
	Changes to use only one depth (specified with -depth)
	for color bitmaps.

	* [objects/brush.c]
	Added support for dithered solid brushes.

	* [objects/color.c]
	Use the same 20 system colors as in Windows.
	System palette initialisation now done in COLOR_InitPalette().
	Added support for a color mapping table to map logical color
	indexes to X colormap entries.
	Implemented GetNearestColor() and RealizeDefaultPalette().

	* [objects/dib.c]
	Added support for color mapping table.

	* [objects/dither.c]  (New file)
	Implemented solid color dithering.

	* [objects/palette.c]
	Implemented GetSystemPaletteEntries() and SelectPalette().

	* [windows/class.c]
	Make a copy of the menu name in RegisterClass().

	* [windows/dc.c]
	Fixed device caps when using a desktop window.
	Added support for the color mapping table in DCs.

	* [windows/event.c]
	Added ConfigureNotify handler on desktop window.

	* [windows/message.c]
	Removed call to XTranslateCoordinates() on every mouse motion
	New function MSG_Synchronize() to synchronize with the X server.

	* [windows/syscolor.c]
	Rewritten SYSCOLOR_Init() to read the system colors from WIN.INI.

	* [windows/winpos.c]
	Added synchronization on window mapping. Solves the double redraw
	problem when starting Solitaire.

Mar 27, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [control/menu.c]	* [windows/defwnd.c]
	Make keyboard navigation working with menubar,
	but temporarely inserted a bug in menubar mouse handling ... :-((
	(it will be fix next week !)

	* [windows/defwnd.c]
	Connect VK_MENU to menubar navigation.

	* [loader/library.c]
	GetModuleHandle() return 'fictive 0xF000+ handles' for built-in DLLs.

Sun Mar 20 22:32:13 1994 Erik Bos (erik@trashcan.hacktic.nl)

	* [misc/main.c]
	Added Copy(). Added a check for `-h' to show usage.

	* [misc/dos_fs.c]
	Fixed bug in FindFile(), to load directories as dlls.

	* [misc/dos_fs.c]
	Fixed ToUnix() and ToDos() again, as my previous patch
	didn't make it.

	* [misc/dos_fs.c] [miscemu/int21.c]
	Bug fixes, should be able to handle all winfile and progman int21
	requests now except for a few small things.

Tue Mar 29 06:25:54 1994  crw@harris.mlb.semi.harris.com (Carl Williams)

	* [memory/heap.c]
	Implemented GetFreeSystemResources().

Mon Mar 21 17:32:25 1994  Bob Amstadt  (bob@pooh)

	* controls/menu.c (GetSubMenu): Function did not return correct value

	* [windows/mdi.c]
	Beginnings of menu handling.

Thu Mar 10 11:32:06 1994  Stefan (SAM) Muenzel  (muenzel@tat.physik.uni-tuebingen.de)

	* [objects/font.c]
	if font.width equals zero use asterix instead.

Mon Mar 21 17:23:37 MET 1994  julliard@di.epfl.ch (Alexandre Julliard)

	* [objects/bitmap.c]
	Rewritten bitmap code to use exclusively X pixmaps; *much* faster.

	* [objects/brush.c]
	Some changes with pattern brushes because of the new bitmap code.

	* [objects/color.c]
	Added function COLOR_ToPhysical for better color mapping.

	* [objects/dib.c]
	Heavily optimized SetDIBits().

	* [windows/dc.c]
	Opimized SetDCState() and DC_SetupGC*() functions.
	Added stub for CreateIC().

Mar 20, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [misc/message.c]
	Call SetFocus() after closing box to give back focus to previous owner.

	* [misc/files.c]
	Small bug fix in GetTempFilename() : replace a '\' to '\\'.

	* [control/scroll.c]
	Calls to BitBlt() replace by StretchBlt().

	* [control/menu.c]
	Call SetFocus() to previous owner after closing Popups.	
	Fill stub DeleteMenu().

	* [control/listbox.c]
	* [control/combo.c]
	Use SetFocus() in WM_LBUTTONDOWN.
	Close ComboBox List upon WM_KILLFOCUS.
	Early development of WM_MEASUREITEM mecanism.

	* [windows/defwnd.c]
	Early development of WM_MEASUREITEM mecanism.

Tue Mar 22 10:44:57 1994  Miguel de Icaza  (miguel@xochitl)

	* [misc/atom.c]
	Fixed sintaxis problem when building the library.

Tue Mar 15 13:11:56 1994  Bob Amstadt  (bob@pooh)

	* [include/windows.h]
	Added message types and structures for MDI

	* [include/mdi.h]
	Created internal structures for handling MDI

	* [windows/mdi.c]
	Began creating MDI support

Thu Mar 10 16:51:46 1994  Bob Amstadt  (bob@pooh)

	* [loader/wine.c] [include/wine.h]
	Added new field to "struct w_files" to hold the "name table"
	resource for Windows 3.0 programs

	* [loader/resource.c]
	Added code to handle programs with a "name table" resource.
	LoadResourceByName() modified to check for the existence of
	this resource.

Mon Mar 14 22:31:42 MET 1994  julliard@di.epfl.ch (Alexandre Julliard)

	* [objects/color.c]
	Added installing the private colormap on the desktop window.

	* [windows/event.c]
	Cleaned up focus event handling (see focus.c).
	Use GetFocus() to direct key events to the correct window.

	* [windows/focus.c]
	Rewritten SetFocus() to:
	- only set X focus on top-level windows
	- send WM_SETFOCUS and WM_KILLFOCUS messages (was done in event.c)
	- prevent setting focus to disabled windows
	- install private colormap so -privatemap option works again

	* [windows/message.c] [windows/timer.c]
	Changed timer management to no longer use PostMessage(), but
	to generate timer messages on the fly. Also fixed a related bug
	in GetMessage() which could cause busy-waiting.

	* [windows/win.c]
	Only select focus events on top-level windows.

	* [windows/winpos.c]
	Added some sanity checks for desktop window.

Fri Mar  4 20:42:01 1994  Erik Bos (erik@trashcan.hacktic.nl)

	* [misc/dos_fs.c]
	bug fixes in ToUnix(), WinIniFileName(), GetUnixFileName(). 
	Support for tilde symbol added for rootdirectories in [drives]
	section of wine's configfile.

	* [misc/file.c]
	hread(), hwrite() added.

	* [misc/main.c]
	hmemcpy() added.

	* [if1632/stress.spec] [include/stress.h] [misc/stress.c]
	Added STRESS.DLL, an useless dll used to stress a windows system.

	* [*/*]
	Added missing #includes, fixed prototypes for prototype checking.

	* [include/prototypes.h]

	Added prototypes for loader/*c, if1632/*c.

Tue Mar  8 09:54:34 1994  Bob Amstadt  (bob@pooh)

	* [Configure]
	Added reminder to set WINEPATH, if it is not set.

	* [Imakefile]
	Removed #elif's

	* [controls/button.c]
	Added BN_CLICKED notification for owner-draw buttons.

	* [if1632/kernel.spec] [memory/heap.c]
	Changed Local* functions to WIN16_Local* to prevent unconcious use
	of these functions.

	* [if1632/relay.c]
	Push old Stack16Frame on stack before setting.

	* [include/atom.h] [misc/atom.c] [include/heap.h] [memory/local.c]
	Added multiple local heap handling in Atom* functions.

	* [include/regfunc.h] [miscemu/int21.c]
	Rewrote DOS3Call() use context frame that is already on the stack.

	* [misc/profile.c]
	Fixed to allow leading ";" to mark comments.

	* [misc/spy.c]
	Fixed bugs and added support for "include" and "exclude" filters.

	* [misc/user.c]
	Rearranged calls in InitApp().

	* [misc/font.c]
	Fixed font handling to create system fonts, if they are used.

	* [windows/dc.c]
	If text drawn on window with no font specified, then default the
	font to the system font.

Mon Mar  7 20:32:09 MET 1994  julliard@di.epfl.ch (Alexandre Julliard)

	* [controls/desktop.c]
	Added handling of WM_NCCREATE and WM_ERASEBKGND functions.
	Implemented SetDeskPattern().

	* [misc/main.c]
	Added -desktop option to get a large desktop window with
	everything inside it.
	Added -name option.

	* [misc/rect.c]
	Bug fix in SubtractRect().

	* [objects/*.c]
	Replaced the DefaultRootWindow() macro by the rootWindow variable.

	* [windows/event.c] [windows/message.c]
	  [windows/nonclient.c] [windows/win.c]
	A few changes to accomodate the new desktop window.

 Tue Mar  8 11:13:03 1994  Miguel de Icaza  (miguel@xochitl.nuclecu.unam.mx)
 
 	* [toolkit/arch.c] --New file-- 
 	Routines for converting little endian data structures to
 	big-endian data structures, currently only BITMAP structures are 
 	converted.
 
 	* [misc/atom.c]
 	When used as part of the WineLib, the code is much simpler.
 	Doesn't depend on alignement.
 
 	* [loader/wine.c]
 	Ifdefed Emulator dependent code if compiling WineLib.
 
 	* [loader/resource.c]
 	Moved misc/resource.c to loader/resource.c.
 
 	* [loader/dump.c,ldt.c,ldtlib.c,library,c,selector.c,signal.c]
 	Ifdefed whole code if compiling WINELIB.
 
 	* [include/winsock.h]
 	Added compilation define to allow compilation on SunOS.
 
 	* [include/wine.h]
 	Removed load_typeinfo and load_nameinfo prototypes, they belong
 	to neexe.h
 
 	* [include/neexe.h]
 	Added load_typeinfo and load_nameinfo prototypes.
 
 	* [include/arch.h]
 	Fixed some bugs in the conversion routines.
 	Added macros for Bitmap loading.

Tue Mar  8 12:52:05 1994  crw@maniac.mlb.semi.harris.com (Carl Williams)
 	
	* [if1632/kernel.spec] [memory/global.c]
	Implemented GetFreeSpace()

	* [if1632/user.spec] [loader/resource.c]
	Implemented CreateIcon()
diff --git a/BUGS b/BUGS
index 1e43469..d005f85 100644
--- a/BUGS
+++ b/BUGS
@@ -1 +1,5 @@
 - EBP and ESP are sometimes corrupted while running 16-bit code.
+- Dialog Boxes created by WM_CREATE handler aren't visible
+- RegisterClass() with hbrBackground = COLOR_APPWORKSPACE+1 does not work.
+- MDI client area needs to resize when frame does
+- Need to generate WM_CHILDACTIVATE
\ No newline at end of file
diff --git a/ChangeLog b/ChangeLog
index 5533bfc..c69135a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,453 @@
 ----------------------------------------------------------------------
+Tue Apr  5 14:36:59 1994  Bob Amstadt  (bob@pooh)
+
+	* [include/mdi.h] [windows/mdi.c]
+	Use WM_PARENTNOTIFY messages to activate children.
+	Generate WM_CHILDACTIVATE messages.
+	Beginnings handler for maxmized child window.
+	Clean up when children are destroyed.
+
+	* [windows/message.c] [windows/nonclient.c] [windows/winpos.c]
+	Removed code add 94/03/26.
+
+Apr 4, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+
+	* [control/menu.c]
+	Make mouse menu navigation working again. :-))
+	(be carefull, clicking outside menus (ie.: clientrect) 
+	not resolved yet)
+
+	* [windows/nonclient.c]  [controls/scroll.c]
+	Bugs fix in NCTrackScrollBars().
+
+	* [misc/dos_fs.c]
+	Bug fix in 'ToDos()' in conversion for '/',
+		(example: '/window/' was translated to 'WINDOWs').
+
+	* [miscemu/int21.c]
+	Function ChangeDir() extract possible drive before DOS_ChangeDir().
+
+	* [loader/library.c]  [loader/wine.c]
+	Playing around moving function GetProcAddress() and put some code in.
+
+Mon Apr  4 21:39:07 1994  Alexandre Julliard (julliard@lamisun.epfl.ch)
+
+	* [misc/main.c]
+	Better explanation of command-line options.
+
+	* [objects/dib.c]
+	Implemented SetDIBitsToDevice().
+
+	* [windows/dc.c]
+	Bug fix in SetDCState().
+
+	* [windows/event.c]
+	Removed WS_DISABLED handling (now done in message.c).
+
+	* [windows/message.c]
+	Added sending a WM_PARENTNOTIFY message in MSG_TranslateMouseMsg().
+	Use WindowFromPoint() to find the window for mouse events, taking
+	into account disabled windows.
+
+	* [windows/painting.c]
+	Bug fix in BeginPaint() to allow calling it at other times than
+	on WM_PAINT (Solitaire needs it...)
+
+	* [windows/win.c]
+	Implemented FindWindow().
+	Rewritten EnableWindow() to behave more like Windows.
+
+	* [windows/winpos.c]
+	Rewritten WindowFromPoint() to also search child windows.
+
+Mon Apr  4 17:36:32 1994  Erik Bos (erik@trashcan.hacktic.nl)
+
+	* [include/int21.h] -> [msdos.h]
+	renamed.
+
+	* [miscemu/int10.h] [miscemu/int25.h] [miscemu/int26.h] 
+	new, added for int 10, 25 and 26.
+
+	* [miscemu/ioports.c]
+	new, added to allow win apps to use ioports.
+
+	* [loader/signal.c]
+	Added support for in, inb, out, outb instructions.
+
+----------------------------------------------------------------------
+Sun Mar 27 13:40:25 1994  Bob Amstadt  (bob@pooh)
+
+	* controls/menu.c (InsertMenu): Changed to use FindMenuItem().
+
+Sat Mar 26 21:23:55 1994  Bob Amstadt  (bob@pooh)
+
+	* [windows/mdi.c]
+	Window list properly updated.
+
+	* [windows/message.c]
+	Call WINPOS_ChildActivate() when mouse pressed.
+
+	* [windows/nonclient.c]
+	Use WINPOS_IsAnActiveWindow() instead of GetActiveWindow() in
+	NC_HandleNCPaint().
+
+	* [windows/winpos.c]
+	Created functions WINPOS_IsAnActiveWindow() and WINPOS_ActivateChild()
+
+Thu Mar 24 14:49:17 1994  Bob Amstadt  (bob@pooh)
+
+	* controls/menu.c (DeleteMenu): Changed to use FindMenuItem
+	(DeleteMenu): Many bug fixes.
+
+	* [controls/menu.c]
+	Created function FindMenuItem().
+
+Thu Mar 24 14:17:24 1994  Bob Amstadt  (bob@pooh)
+
+	* [windows/win.c]
+	Removed incorrect MDI handling code from CreateWindowEx().
+
+	* [controls/menu.c]
+	MF_STRING items needed to allocate a private copy of string.
+
+	* [controls/menu.c]
+	Fixed buggy calls to GlobalFree().
+
+	* [memory/global.c]
+	Eliminated some redundant code with function call.
+
+Wed Mar 23 1994 Pentti Moilanen (pentti.moilanen@ntc.nokia.com)
+
+	* [windows/timer.c]
+	timer list pointers looped in InsertTimer
+
+Tue Mar 29 13:32:08 MET DST 1994  julliard@di.epfl.ch (Alexandre Julliard)
+
+	* [misc/cursor.c]
+	A few changes for desktop window support.
+
+	* [misc/main.c]
+	Added -depth option.
+
+	* [misc/rect.c]
+	Yet another bug fix in SubtractRect().
+
+	* [objects/bitmap.c]
+	Changes to use only one depth (specified with -depth)
+	for color bitmaps.
+
+	* [objects/brush.c]
+	Added support for dithered solid brushes.
+
+	* [objects/color.c]
+	Use the same 20 system colors as in Windows.
+	System palette initialisation now done in COLOR_InitPalette().
+	Added support for a color mapping table to map logical color
+	indexes to X colormap entries.
+	Implemented GetNearestColor() and RealizeDefaultPalette().
+
+	* [objects/dib.c]
+	Added support for color mapping table.
+
+	* [objects/dither.c]  (New file)
+	Implemented solid color dithering.
+
+	* [objects/palette.c]
+	Implemented GetSystemPaletteEntries() and SelectPalette().
+
+	* [windows/class.c]
+	Make a copy of the menu name in RegisterClass().
+
+	* [windows/dc.c]
+	Fixed device caps when using a desktop window.
+	Added support for the color mapping table in DCs.
+
+	* [windows/event.c]
+	Added ConfigureNotify handler on desktop window.
+
+	* [windows/message.c]
+	Removed call to XTranslateCoordinates() on every mouse motion
+	New function MSG_Synchronize() to synchronize with the X server.
+
+	* [windows/syscolor.c]
+	Rewritten SYSCOLOR_Init() to read the system colors from WIN.INI.
+
+	* [windows/winpos.c]
+	Added synchronization on window mapping. Solves the double redraw
+	problem when starting Solitaire.
+
+Mar 27, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+
+	* [control/menu.c]	* [windows/defwnd.c]
+	Make keyboard navigation working with menubar,
+	but temporarely inserted a bug in menubar mouse handling ... :-((
+	(it will be fix next week !)
+
+	* [windows/defwnd.c]
+	Connect VK_MENU to menubar navigation.
+
+	* [loader/library.c]
+	GetModuleHandle() return 'fictive 0xF000+ handles' for built-in DLLs.
+
+Sun Mar 20 22:32:13 1994 Erik Bos (erik@trashcan.hacktic.nl)
+
+	* [misc/main.c]
+	Added Copy(). Added a check for `-h' to show usage.
+
+	* [misc/dos_fs.c]
+	Fixed bug in FindFile(), to load directories as dlls.
+
+	* [misc/dos_fs.c]
+	Fixed ToUnix() and ToDos() again, as my previous patch
+	didn't make it.
+
+	* [misc/dos_fs.c] [miscemu/int21.c]
+	Bug fixes, should be able to handle all winfile and progman int21
+	requests now except for a few small things.
+
+Tue Mar 29 06:25:54 1994  crw@harris.mlb.semi.harris.com (Carl Williams)
+
+	* [memory/heap.c]
+	Implemented GetFreeSystemResources().
+
+----------------------------------------------------------------------
+Mon Mar 21 17:32:25 1994  Bob Amstadt  (bob@pooh)
+
+	* controls/menu.c (GetSubMenu): Function did not return correct value
+
+	* [windows/mdi.c]
+	Beginnings of menu handling.
+
+Thu Mar 10 11:32:06 1994  Stefan (SAM) Muenzel  (muenzel@tat.physik.uni-tuebingen.de)
+
+	* [objects/font.c]
+	if font.width equals zero use asterix instead.
+
+Mon Mar 21 17:23:37 MET 1994  julliard@di.epfl.ch (Alexandre Julliard)
+
+	* [objects/bitmap.c]
+	Rewritten bitmap code to use exclusively X pixmaps; *much* faster.
+
+	* [objects/brush.c]
+	Some changes with pattern brushes because of the new bitmap code.
+
+	* [objects/color.c]
+	Added function COLOR_ToPhysical for better color mapping.
+
+	* [objects/dib.c]
+	Heavily optimized SetDIBits().
+
+	* [windows/dc.c]
+	Opimized SetDCState() and DC_SetupGC*() functions.
+	Added stub for CreateIC().
+
+Mar 20, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+
+	* [misc/message.c]
+	Call SetFocus() after closing box to give back focus to previous owner.
+
+	* [misc/files.c]
+	Small bug fix in GetTempFilename() : replace a '\' to '\\'.
+
+	* [control/scroll.c]
+	Calls to BitBlt() replace by StretchBlt().
+
+	* [control/menu.c]
+	Call SetFocus() to previous owner after closing Popups.	
+	Fill stub DeleteMenu().
+
+	* [control/listbox.c]
+	* [control/combo.c]
+	Use SetFocus() in WM_LBUTTONDOWN.
+	Close ComboBox List upon WM_KILLFOCUS.
+	Early development of WM_MEASUREITEM mecanism.
+
+	* [windows/defwnd.c]
+	Early development of WM_MEASUREITEM mecanism.
+
+Tue Mar 22 10:44:57 1994  Miguel de Icaza  (miguel@xochitl)
+
+	* [misc/atom.c]
+	Fixed sintaxis problem when building the library.
+
+----------------------------------------------------------------------
+Tue Mar 15 13:11:56 1994  Bob Amstadt  (bob@pooh)
+
+	* [include/windows.h]
+	Added message types and structures for MDI
+
+	* [include/mdi.h]
+	Created internal structures for handling MDI
+
+	* [windows/mdi.c]
+	Began creating MDI support
+
+Thu Mar 10 16:51:46 1994  Bob Amstadt  (bob@pooh)
+
+	* [loader/wine.c] [include/wine.h]
+	Added new field to "struct w_files" to hold the "name table"
+	resource for Windows 3.0 programs
+
+	* [loader/resource.c]
+	Added code to handle programs with a "name table" resource.
+	LoadResourceByName() modified to check for the existence of
+	this resource.
+
+Mon Mar 14 22:31:42 MET 1994  julliard@di.epfl.ch (Alexandre Julliard)
+
+	* [objects/color.c]
+	Added installing the private colormap on the desktop window.
+
+	* [windows/event.c]
+	Cleaned up focus event handling (see focus.c).
+	Use GetFocus() to direct key events to the correct window.
+
+	* [windows/focus.c]
+	Rewritten SetFocus() to:
+	- only set X focus on top-level windows
+	- send WM_SETFOCUS and WM_KILLFOCUS messages (was done in event.c)
+	- prevent setting focus to disabled windows
+	- install private colormap so -privatemap option works again
+
+	* [windows/message.c] [windows/timer.c]
+	Changed timer management to no longer use PostMessage(), but
+	to generate timer messages on the fly. Also fixed a related bug
+	in GetMessage() which could cause busy-waiting.
+
+	* [windows/win.c]
+	Only select focus events on top-level windows.
+
+	* [windows/winpos.c]
+	Added some sanity checks for desktop window.
+
+Fri Mar  4 20:42:01 1994  Erik Bos (erik@trashcan.hacktic.nl)
+
+	* [misc/dos_fs.c]
+	bug fixes in ToUnix(), WinIniFileName(), GetUnixFileName(). 
+	Support for tilde symbol added for rootdirectories in [drives]
+	section of wine's configfile.
+
+	* [misc/file.c]
+	hread(), hwrite() added.
+
+	* [misc/main.c]
+	hmemcpy() added.
+
+	* [if1632/stress.spec] [include/stress.h] [misc/stress.c]
+	Added STRESS.DLL, an useless dll used to stress a windows system.
+
+	* [*/*]
+	Added missing #includes, fixed prototypes for prototype checking.
+
+	* [include/prototypes.h]
+
+	Added prototypes for loader/*c, if1632/*c.
+
+----------------------------------------------------------------------
+Tue Mar  8 09:54:34 1994  Bob Amstadt  (bob@pooh)
+
+	* [Configure]
+	Added reminder to set WINEPATH, if it is not set.
+
+	* [Imakefile]
+	Removed #elif's
+
+	* [controls/button.c]
+	Added BN_CLICKED notification for owner-draw buttons.
+
+	* [if1632/kernel.spec] [memory/heap.c]
+	Changed Local* functions to WIN16_Local* to prevent unconcious use
+	of these functions.
+
+	* [if1632/relay.c]
+	Push old Stack16Frame on stack before setting.
+
+	* [include/atom.h] [misc/atom.c] [include/heap.h] [memory/local.c]
+	Added multiple local heap handling in Atom* functions.
+
+	* [include/regfunc.h] [miscemu/int21.c]
+	Rewrote DOS3Call() use context frame that is already on the stack.
+
+	* [misc/profile.c]
+	Fixed to allow leading ";" to mark comments.
+
+	* [misc/spy.c]
+	Fixed bugs and added support for "include" and "exclude" filters.
+
+	* [misc/user.c]
+	Rearranged calls in InitApp().
+
+	* [misc/font.c]
+	Fixed font handling to create system fonts, if they are used.
+
+	* [windows/dc.c]
+	If text drawn on window with no font specified, then default the
+	font to the system font.
+
+Mon Mar  7 20:32:09 MET 1994  julliard@di.epfl.ch (Alexandre Julliard)
+
+	* [controls/desktop.c]
+	Added handling of WM_NCCREATE and WM_ERASEBKGND functions.
+	Implemented SetDeskPattern().
+
+	* [misc/main.c]
+	Added -desktop option to get a large desktop window with
+	everything inside it.
+	Added -name option.
+
+	* [misc/rect.c]
+	Bug fix in SubtractRect().
+
+	* [objects/*.c]
+	Replaced the DefaultRootWindow() macro by the rootWindow variable.
+
+	* [windows/event.c] [windows/message.c]
+	  [windows/nonclient.c] [windows/win.c]
+	A few changes to accomodate the new desktop window.
+
+ Tue Mar  8 11:13:03 1994  Miguel de Icaza  (miguel@xochitl.nuclecu.unam.mx)
+ 
+ 	* [toolkit/arch.c] --New file-- 
+ 	Routines for converting little endian data structures to
+ 	big-endian data structures, currently only BITMAP structures are 
+ 	converted.
+ 
+ 	* [misc/atom.c]
+ 	When used as part of the WineLib, the code is much simpler.
+ 	Doesn't depend on alignement.
+ 
+ 	* [loader/wine.c]
+ 	Ifdefed Emulator dependent code if compiling WineLib.
+ 
+ 	* [loader/resource.c]
+ 	Moved misc/resource.c to loader/resource.c.
+ 
+ 	* [loader/dump.c,ldt.c,ldtlib.c,library,c,selector.c,signal.c]
+ 	Ifdefed whole code if compiling WINELIB.
+ 
+ 	* [include/winsock.h]
+ 	Added compilation define to allow compilation on SunOS.
+ 
+ 	* [include/wine.h]
+ 	Removed load_typeinfo and load_nameinfo prototypes, they belong
+ 	to neexe.h
+ 
+ 	* [include/neexe.h]
+ 	Added load_typeinfo and load_nameinfo prototypes.
+ 
+ 	* [include/arch.h]
+ 	Fixed some bugs in the conversion routines.
+ 	Added macros for Bitmap loading.
+
+Tue Mar  8 12:52:05 1994  crw@maniac.mlb.semi.harris.com (Carl Williams)
+ 	
+	* [if1632/kernel.spec] [memory/global.c]
+	Implemented GetFreeSpace()
+
+	* [if1632/user.spec] [loader/resource.c]
+	Implemented CreateIcon()
+
+----------------------------------------------------------------------
 Tue Mar  1 11:30:21 1994  Bob Amstadt  (bob@pooh)
 
 	* [Configure] [*/Imakefile]
diff --git a/Configure b/Configure
index c6bf097..15c7c31 100755
--- a/Configure
+++ b/Configure
@@ -2,12 +2,13 @@
 
 ALLDEFINES=''
 
+echo
 echo -n 'Build Wine as emulator or library (E/L) [E]? '
 read input
 if [ "$input" = 'l' -o "$input" = 'L' ]
 then
-    WINELIB='#define WineLib -DWINELIB'
-    ALLDEFINES=$ALLDEFINES -DWINELIB
+    WINELIB='#define WINELIB -DWINELIB'
+    ALLDEFINES="$ALLDEFINES -DWINELIB"
 else
     WINELIB=''
 fi
@@ -17,14 +18,40 @@
 if [ "$input" = 'y' -o "$input" = 'Y' ]
 then
     SHORTNAMES='#define ShortNames -DSHORTNAMES'
-    ALLDEFINES=$ALLDEFINES -DSHORTNAMES
+    ALLDEFINES="$ALLDEFINES -DSHORTNAMES"
 else
     SHORTNAMES=''
 fi
 
+echo -n 'Global configfile name [/usr/local/etc/wine.conf]? '
+read input
+if [ "$input" = '' ]
+then
+    WINE_INI_GLOBAL='#define WINE_INI_GLOBAL "/usr/local/etc/wine.conf"'
+else
+    WINE_INI_GLOBAL='#define WINE_INI_GLOBAL "'$input'"'
+fi
+
+if [ "`(domainname)`" = 'amscons.com' ]
+then
+    echo -n 'New build program (Y/N) [N]? '
+    read input
+    if [ "$input" = 'y' -o "$input" = 'Y' ]
+    then
+	NEWBUILD='#define NewBuild -DNEWBUILD'
+	ALLDEFINES="$ALLDEFINES -DNEWBUILD"
+    else
+	NEWBUILD=''
+    fi
+else
+    NEWBUILD=''
+fi
+
 echo '/* autoconf.h generated automatically.  Run Configure. */' > autoconf.h
 echo $WINELIB >> autoconf.h
 echo $SHORTNAMES >> autoconf.h
+echo $NEWBUILD >> autoconf.h
+echo $WINE_INI_GLOBAL >> autoconf.h
 echo "#define AutoDefines  $ALLDEFINES" >> autoconf.h
 
 xmkmf -a
diff --git a/DEVELOPERS-HINTS b/DEVELOPERS-HINTS
index 3321aa9..da8a598 100644
--- a/DEVELOPERS-HINTS
+++ b/DEVELOPERS-HINTS
@@ -12,8 +12,9 @@
 Submissions of code for inclussion into Wine should be sent to
 bob@amscons.com (Bob Amstadt).  You MUST provide a suitable
 ChangeLog entry for any work that you submit.  I prefer new code
-to be submitted as diffs off of the latest release.  Releases are
-every Tuesday evening (approximately 19:00 PST or Wednesday 03:00 GMT).
+to be submitted as unified diffs (diff -u) off of the latest release.  
+Releases are every Tuesday evening (approximately 17:00 PST or 
+Wednesday 01:00 GMT).
 
 MEMORY AND SEGMENTS:
 
@@ -78,4 +79,11 @@
 files contain the entry point code for each API call, and the dll_tab_*.s
 files contain tables used by relay.c to translate arguments and transfer
 control to the proper handler.  The format of the *.spec files is
-documented in the file "tools/build-spec.txt".
\ No newline at end of file
+documented in the file "tools/build-spec.txt".
+
+REGISTER FUNCTIONS:
+
+Some functions are defined as type "register" in the DLL specification files.
+Inorder to return values in the registers to the WIN16 program, the handler
+function must exit by calling ReturnFromRegisterFunc().  Look at the function
+DOS3Call() for an example of how this works.
diff --git a/Imakefile b/Imakefile
index e0662aa..89039f0 100644
--- a/Imakefile
+++ b/Imakefile
@@ -27,6 +27,7 @@
 	controls \
 	etc \
 	include \
+	loader \
 	misc \
 	objects \
 	test \
@@ -36,7 +37,6 @@
 	tools \
 	debugger \
 	if1632 \
-	loader \
 	memory \
 	miscemu
 
@@ -47,6 +47,7 @@
 
 COMMONOBJS = \
 	controls.o \
+	loader.o \
 	misc.o \
 	objects.o \
 	windows.o
@@ -58,7 +59,6 @@
 EMUOBJS = \
 	if1632.o \
 	debugger.o \
-	loader.o \
 	memory.o \
 	miscemu.o \
 	readline.o
@@ -74,11 +74,13 @@
 OBJS = $(COMMONOBJS) $(LIBOBJS)
 #endif
 
-#if defined(i386BsdArchitecture)
+#ifdef i386BsdArchitecture
 SYSLIBS = -ll -lm -li386 -lgnumalloc
-#elif defined(i386FreeBsd)
+#endif
+#ifdef i386FreeBsd
 SYSLIBS = -ll -lm -lgnumalloc
-#elif defined(LinuxArchitecture)
+#endif
+#ifdef LinuxArchitecture
 SYSLIBS = -lm -lg
 #endif
 
diff --git a/README b/README
index c7ff6b4..abc84a9 100644
--- a/README
+++ b/README
@@ -2,7 +2,9 @@
 warranty.  All code is covered by the license contained in the file
 LICENSE unless explicitly stated in the individual source file.
 
-INSTALLATION:
+
+
+1. COMPILATION:
 
 You must have one of:
 
@@ -11,21 +13,103 @@
 	FreeBSD-current or FreeBSD 1.1
 
 To build Wine, first do a "./Configure" and then a "make".  The
-executable "wine" will be built.  "wine" will load and run Windows'
-executables.  You must have a file "wine.ini" in the current directory,
-your home directory, or in the path specified by the environment 
-variable WINEPATH. Multiple directories in WINEPATH should be seperated
-by semi-colons and NOT by colons!
+executable "wine" will be built.  "wine" will load and run 16-bit
+Windows' executables. 
 
-You must specify the entire path to the executable, or a filename only
-(using the path= statement in wine.ini as the search path)
+
+
+2. SETUP:
+
+Wine requires you to have a file /usr/local/etc/wine.conf (you can
+supply a different name when configuring wine) or a file called .winerc
+in your homedirectory.
+
+The formatstyle of this config file is just like a windows .ini file.
+
+Here's an explanation of each section:
+
+* [drives]
+
+format: <driveletter> = <rootdirectory>
+default: none
+
+This section is used to specify the root directory of each `dos'drive 
+as windows' applications require a dos/mswindows based diskdrive & 
+directory scheme. 
+
+If you mounted you dos-partition as /dos and installed microsoft windows 
+in c:\windows than you should specify c=/dos in the drives section.
+
+* [wine]
+
+format: windows = <directory>
+default: c:\windows
+
+Used to specify an different windows directory.
+
+format: system = <directory>
+default: c:\windows\system
+
+Used to specify an different system directory.
+
+format: temp = <directory>
+default: c:\temp
+
+Used to specify a directory where windows applications can store temporary
+files.
+
+format: path = <directories separated by semi-colons>
+default: c:\windows;c:\windows\system
+
+Used to specify the path which will be used to find executables and DLL's.
+
+format: systemresources = <filename>
+default: c:\temp
+
+Used to specify the name of sysres.dll, a dll which is used by wine itself.
+
+* [serialports]
+
+format: com[12345678] = <devicename>
+default: none
+
+Used to specify the devices which are used as com1 - com8.
+
+* [parallelports]
+
+format: lpt[12345678] = <devicename>
+default: none
+
+Used to specify the devices which are used as lpt1 - lpt8.
+
+* [spy]
+
+format: file = <filename or CON when logging to stdout>
+default: none
+
+used to specify the file which will be used as logfile.
+
+format: exclude = <message names separated by semicolons>
+default: none
+
+Used to specify which messages will be excluded from the logfile.
+
+format: include = <message names separated by semicolons>
+default: none
+
+Used to specify which messages will be included in the logfile.
+
+
+
+3. RUNNING PROGRAMS
+
+When invoking wine, you must specify the entire path to the executable,
+or a filename only.
 
 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 sol		   (using the searchpath to locate the file)
+	wine sol.exe
 
 	wine c:\\windows\\sol.exe  (using a dosfilename)
 
@@ -34,6 +118,93 @@
 Have a nice game of solitaire, but be careful.  Emulation isn't perfect.
 So, occassionally it will crash.
 
+
+
+4. EXAMPLE CONFIGFILE
+
+----------------------------------------------------------------------------
+[drives]
+a=/mnt/fd0
+c=/dos
+d=~/Wine
+
+[wine]
+windows=c:\windows
+system=c:\windows\system
+temp=c:\temp
+path=c:\windows;c:\windows\system;c:\winapps\word\;c:\winapps\pctools
+systemresources=./sysres.dll
+
+[serialports]
+com1=/dev/cua1
+com2=/dev/cua1
+
+[parallelports]
+lpt1=/dev/lp0
+
+[spy]
+;File=CON
+;File=spy.log
+Exclude=WM_TIMER;WM_SETCURSOR;WM_MOUSEMOVE;WM_NCHITTEST;WM_NCACTIVATE;WM_GETDLGCODE;
+Include=WM_COMMAND;
+
+----------------------------------------------------------------------------
+
+
+5. BUILD:
+
+    The documentation for the build program is in the file build-spec.txt
+
+
+6. FINALE:
+
+Good luck,
+
+	If you successfully add anything, please send me a copy.
+
+Bob Amstadt
+bob@amscons.com
+
+
+7. WHAT'S NEW
+
+WHAT'S NEW with Wine-940405: (see ChangeLog for details)
+	- Mouse activation of menus working again
+	- GetprocAddress()
+	- SetDIBitsToDevice()
+	- FindWindow()
+	- int 10hm 25h and 26h
+	- in, inb, out, outb emulation
+	- and many many bug fixes!
+
+WHAT'S NEW with Wine-940329: (see ChangeLog for details)
+	- MDI: child windows can be created, activated and cascaded.
+	- -depth option
+	- support for dithered brushes
+	- GetNearestColor(), RealizeDefaultPalette(), 
+	  GetSystemPaletteEntries(), and SelectPalette()
+	- System colors read from WIN.INI
+	- Keyboard menu manipulation (mouse is temporarily broken)
+	- GetFreeSystemResources()
+	- and many many bug fixes!
+
+WHAT'S NEW with Wine-940322: (see ChangeLog for details)
+	- Speed improvements in bitmaps and mouse messages
+	- More MDI support.  More to come next week...
+	- and many many bug fixes!
+
+WHAT'S NEW with Wine-940315: (see ChangeLog for details)
+	- Beginnings of MDI support.  More to come next week...
+	- Stress DLL
+	- and many many bug fixes!
+
+WHAT'S NEW with Wine-940309: (see ChangeLog for details)
+	- New "exclude" and "include" filters for spy feature.  See sample
+	  wine.ini for details.
+	- -desktop and -name options (see ChangeLog)
+	- GetFreeSpace() and CreateIcon()
+	- and many many bug fixes!
+
 WHAT'S NEW with Wine-940301: (see ChangeLog for details)
 	- NEW Configure script to set compile time options!
 	- Support for filesystems with short (less than 14 chars) filenames.
@@ -299,27 +470,3 @@
       library routines.  A brief description of how to build these
       specifications is included in the file "build-spec.txt".
     - The code to dispatch builtin DLL calls is complete, but untested.
-
-TODO:
-
-    - Segment fixup code completion.
-    - Trap and handle DOS and DPMI calls.
-    - GlobalAlloc of code segments.
-    - Rewrite global memory support including kernel mods to allow
-      application to mess with page map.
-    - Handle self-loading applications.
-    - Resource loading
-    - Lots and lots of API fiunctions.
-
-BUILD:
-
-    The documentation for the build program is in the file build-spec.txt
-
-FINALE:
-
-Good luck,
-
-	If you successfully add anything, please send me a copy.
-
-Bob Amstadt
-bob@amscons.com
diff --git a/Wine.tmpl b/Wine.tmpl
index 7740d32..13a84cc 100644
--- a/Wine.tmpl
+++ b/Wine.tmpl
@@ -1,26 +1,36 @@
 XCOMM $Id$
 
-INCLUDES = -I$(TOP)/include
+INCLUDES = -I$(TOP)/include -I$(TOP)
 
 XCOMM Imake rules go here
 
 XCOMM First, dll description to files etc
 #ifndef MakeDllFromSpec
+#ifndef NewBuild
 #ifndef ShortNames
 #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					@@\
 
-#else
+#else /* ShortNames */
 #define MakeDllFromSpec(name,objfile)					@@\
-objfile.o: Concat(dll_,name.o) Concat(dtb_,name.o)		@@\
-									@@\
-Concat(dll_,name.S) Concat(dtb_,name.c): name.spec $(TOP)/tools/build  @@\
+Concat(dll_,name.S) Concat(dtb_,name.c): name.spec $(TOP)/tools/build   @@\
 	$(TOP)/tools/build name.spec					@@\
 
-#endif /* SHORTNAMES */
+#endif /* ShortNames */
+#else /* NewBuild */
+#ifndef ShortNames
+#define MakeDllFromSpec(name,objfile)					@@\
+Concat(dll_,name.S) Concat(rly_,name.S) Concat3(dll_,name,_tab.c): name.spec $(TOP)/tools/newbuild  @@\
+	$(TOP)/tools/newbuild name.spec					@@\
+
+#else /* ShortNames */
+#define MakeDllFromSpec(name,objfile)					@@\
+Concat(dll_,name.S) Concat(rly_,name.S) Concat(dtb_,name.c): name.spec $(TOP)/tools/newbuild   @@\
+	$(TOP)/tools/newbuild name.spec					@@\
+
+#endif /* ShortNames */
+#endif /* NewBuild */
 #endif /* MakeDllFromSpec */
 
 /*
diff --git a/controls/button.c b/controls/button.c
index 7ecd9db..f58057b 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -963,7 +963,10 @@
     ReleaseCapture();
     GetClientRect(hWnd, &rc);
     if (PtInRect(&rc, MAKEPOINT(lParam)))
+    {
+	NOTIFY_PARENT(hWnd, BN_CLICKED);
 	NOTIFY_PARENT(hWnd, BN_UNHILITE);
+    }
     InvalidateRect(hWnd, NULL, FALSE);
     UpdateWindow(hWnd);
 }
diff --git a/controls/combo.c b/controls/combo.c
index 61b5e20..ae18601 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -11,13 +11,16 @@
 
 static char Copyright[] = "Copyright Martin Ayotte, 1993";
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
 #include "windows.h"
 #include "combo.h"
 #include "heap.h"
 #include "win.h"
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/stat.h>
+#include "prototypes.h"
 
 HBITMAP hComboBit = 0;
 
@@ -45,275 +48,290 @@
     switch(message)
     {
     case WM_CREATE:
-	wndPtr = WIN_FindWndPtr(hwnd);
-	if (wndPtr == NULL) return 0;
+		wndPtr = WIN_FindWndPtr(hwnd);
+		if (wndPtr == NULL) return 0;
 #ifdef DEBUG_COMBO
-        printf("Combo WM_CREATE %lX !\n", lphc);
+		printf("Combo WM_CREATE %lX !\n", lphc);
 #endif
-	if (hComboBit == (HBITMAP)NULL) 
-	    hComboBit = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_COMBO));
-	GetObject(hComboBit, sizeof(BITMAP), (LPSTR)&bm);
-	wndPtr->dwStyle &= 0xFFFFFFFFL ^ (WS_VSCROLL | WS_HSCROLL);
-	GetWindowRect(hwnd, &rect);
-	width = rect.right - rect.left;
-	height = rect.bottom - rect.top;
-	SetWindowPos(hwnd, 0, 0, 0, width + bm.bmHeight, bm.bmHeight, 
+		if (hComboBit == (HBITMAP)NULL) 
+		hComboBit = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_COMBO));
+		GetObject(hComboBit, sizeof(BITMAP), (LPSTR)&bm);
+		wndPtr->dwStyle &= 0xFFFFFFFFL ^ (WS_VSCROLL | WS_HSCROLL);
+		GetWindowRect(hwnd, &rect);
+		width = rect.right - rect.left;
+		height = rect.bottom - rect.top;
+		SetWindowPos(hwnd, 0, 0, 0, width + bm.bmHeight, bm.bmHeight, 
 		SWP_NOMOVE | SWP_NOZORDER); 
-	CreateComboStruct(hwnd);
-	lphc = ComboGetStorageHeader(hwnd);
-	if (lphc == NULL) return 0;
-        if (wndPtr->dwStyle & CBS_SIMPLE)
-/*	    lphc->hWndEdit = CreateWindow("EDIT", "", */
-	    lphc->hWndEdit = CreateWindow("STATIC", "", 
-		WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | SS_LEFT,
-		0, 0, width - bm.bmHeight, bm.bmHeight, 
-		hwnd, 1, wndPtr->hInstance, 0L);
-	else
-	    lphc->hWndEdit = CreateWindow("STATIC", "", 
-		WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | SS_LEFT,
-		0, 0, width - bm.bmHeight, bm.bmHeight, 
-		hwnd, 1, wndPtr->hInstance, 0L);
-	lphc->hWndLBox = CreateWindow("LISTBOX", "", 
-        	WS_CHILD | WS_CLIPCHILDREN | WS_BORDER | WS_VSCROLL | LBS_NOTIFY,
-        	wndPtr->rectClient.left, wndPtr->rectClient.top + bm.bmHeight, 
-        	width, height, wndPtr->hwndParent, 1, 
-        	wndPtr->hInstance, (LPSTR)MAKELONG(0, hwnd));
-        ShowWindow(lphc->hWndLBox, SW_HIDE);
+		CreateComboStruct(hwnd);
+		lphc = ComboGetStorageHeader(hwnd);
+		if (lphc == NULL) return 0;
+		if (wndPtr->dwStyle & CBS_SIMPLE)
+/*			lphc->hWndEdit = CreateWindow("EDIT", "", */
+			lphc->hWndEdit = CreateWindow("STATIC", "", 
+				WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | SS_LEFT,
+				0, 0, width - bm.bmHeight, bm.bmHeight, 
+				hwnd, 1, wndPtr->hInstance, 0L);
+		else
+			lphc->hWndEdit = CreateWindow("STATIC", "", 
+				WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | SS_LEFT,
+				0, 0, width - bm.bmHeight, bm.bmHeight, 
+				hwnd, 1, wndPtr->hInstance, 0L);
+		lphc->hWndLBox = CreateWindow("LISTBOX", "", 
+			WS_CHILD | WS_CLIPCHILDREN | WS_BORDER | WS_VSCROLL | LBS_NOTIFY,
+			wndPtr->rectClient.left, wndPtr->rectClient.top + bm.bmHeight, 
+			width, height, wndPtr->hwndParent, 1, 
+			wndPtr->hInstance, (LPSTR)MAKELONG(0, hwnd));
+		ShowWindow(lphc->hWndLBox, SW_HIDE);
 #ifdef DEBUG_COMBO
-        printf("Combo Creation LBox=%X!\n", lphc->hWndLBox);
+		printf("Combo Creation LBox=%X!\n", lphc->hWndLBox);
 #endif
-	return 0;
+		return 0;
     case WM_DESTROY:
-	lphc = ComboGetStorageHeader(hwnd);
-	if (lphc == 0) return 0;
+		lphc = ComboGetStorageHeader(hwnd);
+		if (lphc == 0) return 0;
 /*
-	DestroyWindow(lphc->hWndEdit);
+		DestroyWindow(lphc->hWndEdit);
 */
-	DestroyWindow(lphc->hWndLBox);
-	free(lphc);
+		DestroyWindow(lphc->hWndLBox);
+		free(lphc);
 /*
-	*((LPHEADCOMBO *)&wndPtr->wExtra[1]) = 0; 
-        printf("Combo WM_DESTROY after clearing wExtra !\n");
+		*((LPHEADCOMBO *)&wndPtr->wExtra[1]) = 0; 
+		printf("Combo WM_DESTROY after clearing wExtra !\n");
 */
 #ifdef DEBUG_COMBO
-        printf("Combo WM_DESTROY %lX !\n", lphc);
+		printf("Combo WM_DESTROY %lX !\n", lphc);
 #endif
-	return DefWindowProc( hwnd, message, wParam, lParam );
+		return DefWindowProc( hwnd, message, wParam, lParam );
 	
     case WM_COMMAND:
-	wndPtr = WIN_FindWndPtr(hwnd);
-	lphc = ComboGetStorageHeader(hwnd);
-	if (lphc == NULL) return 0;
-        if (LOWORD(lParam) == lphc->hWndLBox) {
-            switch(HIWORD(lParam))
-        	{
-        	case LBN_SELCHANGE:
-		    lphc->dwState = lphc->dwState & (CB_SHOWDROPDOWN ^ 0xFFFFFFFFL);
-		    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);
-		    	}
-		    SendMessage(GetParent(hwnd), WM_COMMAND, wndPtr->wIDmenu,
-			        	MAKELONG(hwnd, CBN_SELCHANGE));
-        	    break;
-        	case LBN_DBLCLK:
-		    SendMessage(GetParent(hwnd), WM_COMMAND, wndPtr->wIDmenu,
-			        	MAKELONG(hwnd, CBN_DBLCLK));
-        	    break;
-        	}
+		wndPtr = WIN_FindWndPtr(hwnd);
+		lphc = ComboGetStorageHeader(hwnd);
+		if (lphc == NULL) return 0;
+		if (LOWORD(lParam) == lphc->hWndLBox) {
+            switch(HIWORD(lParam)) {
+	        	case LBN_SELCHANGE:
+				    lphc->dwState = lphc->dwState & (CB_SHOWDROPDOWN ^ 0xFFFFFFFFL);
+				    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);
+				    	}
+				    SendMessage(GetParent(hwnd), WM_COMMAND, wndPtr->wIDmenu,
+					        	MAKELONG(hwnd, CBN_SELCHANGE));
+	        	    break;
+	        	case LBN_DBLCLK:
+				    SendMessage(GetParent(hwnd), WM_COMMAND, wndPtr->wIDmenu,
+					        	MAKELONG(hwnd, CBN_DBLCLK));
+	        	    break;
+	        	}
             }
-	break;
+		break;
     case WM_LBUTTONDOWN:
-        printf("Combo WM_LBUTTONDOWN wParam=%x lParam=%lX !\n", wParam, lParam);
-	GetClientRect(hwnd, &rect);
-	rect.left = rect.right - (rect.bottom - rect.top); 
-	hDC = GetDC(hwnd);
-	InflateRect(&rect, -1, -1);
-	DrawReliefRect(hDC, rect, 1, 1);
-	ReleaseDC(hwnd, hDC);
-	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);
-	else {
-/*
-	    SetFocus(lphc->hWndEdit);
-*/
-	    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);
-		}
+		printf("Combo WM_LBUTTONDOWN wParam=%x lParam=%lX !\n", wParam, lParam);
+		GetClientRect(hwnd, &rect);
+		rect.left = rect.right - (rect.bottom - rect.top); 
+		hDC = GetDC(hwnd);
+		InflateRect(&rect, -1, -1);
+		DrawReliefRect(hDC, rect, 1, 1);
+		ReleaseDC(hwnd, hDC);
+		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);
+		    SetFocus(lphc->hWndLBox);
+			}
+		else {
+		    SetFocus(lphc->hWndEdit);
+			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);
+			}
 	    }
-	break;
+		break;
     case WM_LBUTTONUP:
-        printf("Combo WM_LBUTTONUP wParam=%x lParam=%lX !\n", wParam, lParam);
-	GetClientRect(hwnd, &rect);
-	rect.left = rect.right - (rect.bottom - rect.top); 
-	hDC = GetDC(hwnd);
-	InflateRect(&rect, -1, -1);
-	DrawReliefRect(hDC, rect, 1, 0);
-	ReleaseDC(hwnd, hDC);
-	break;
+		printf("Combo WM_LBUTTONUP wParam=%x lParam=%lX !\n", wParam, lParam);
+		GetClientRect(hwnd, &rect);
+		rect.left = rect.right - (rect.bottom - rect.top); 
+		hDC = GetDC(hwnd);
+		InflateRect(&rect, -1, -1);
+		DrawReliefRect(hDC, rect, 1, 0);
+		ReleaseDC(hwnd, hDC);
+		break;
    case WM_KEYDOWN:
-	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);
+		wndPtr = WIN_FindWndPtr(hwnd);
+		lphc = ComboGetStorageHeader(hwnd);
 		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);
+		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);
+			    SetFocus(lphc->hWndLBox);
+				}
+			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;
+		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_MEASUREITEM:
+		printf("ComboBoxWndProc WM_MEASUREITEM !\n");
+    	return(SendMessage(GetParent(hwnd), WM_MEASUREITEM, wParam, lParam));
     case WM_CTLCOLOR:
     	return(SendMessage(GetParent(hwnd), WM_CTLCOLOR, wParam, lParam));
     case WM_PAINT:
-	GetClientRect(hwnd, &rect);
-	hDC = BeginPaint(hwnd, &paintstruct);
-	hMemDC = CreateCompatibleDC(hDC);
-	GetObject(hComboBit, sizeof(BITMAP), (LPSTR)&bm);
-	SelectObject(hMemDC, hComboBit);
-	BitBlt(hDC, rect.right - bm.bmWidth, 0, 
+		GetClientRect(hwnd, &rect);
+		hDC = BeginPaint(hwnd, &paintstruct);
+		hMemDC = CreateCompatibleDC(hDC);
+		GetObject(hComboBit, sizeof(BITMAP), (LPSTR)&bm);
+		SelectObject(hMemDC, hComboBit);
+		BitBlt(hDC, rect.right - bm.bmWidth, 0, 
 		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-	DeleteDC(hMemDC);
-	EndPaint(hwnd, &paintstruct);
-	lphc = ComboGetStorageHeader(hwnd);
-        InvalidateRect(lphc->hWndEdit, NULL, TRUE);
-        UpdateWindow(lphc->hWndEdit);
-        if ((lphc->dwState & CB_SHOWDROPDOWN) == CB_SHOWDROPDOWN) {
-	    InvalidateRect(lphc->hWndLBox, NULL, TRUE);
-	    UpdateWindow(lphc->hWndLBox);
-	    }
-	break;
-    case CB_ADDSTRING:
+		DeleteDC(hMemDC);
+		EndPaint(hwnd, &paintstruct);
+		lphc = ComboGetStorageHeader(hwnd);
+		InvalidateRect(lphc->hWndEdit, NULL, TRUE);
+		UpdateWindow(lphc->hWndEdit);
+		if ((lphc->dwState & CB_SHOWDROPDOWN) == CB_SHOWDROPDOWN) {
+			InvalidateRect(lphc->hWndLBox, NULL, TRUE);
+			UpdateWindow(lphc->hWndLBox);
+			}
+		break;
+	case WM_SETFOCUS:
+		lphc = ComboGetStorageHeader(hwnd);
+		SetFocus(lphc->hWndEdit);
+		break;
+	case WM_KILLFOCUS:
+		lphc = ComboGetStorageHeader(hwnd);
+		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);
+			}
+		break;
+	case CB_ADDSTRING:
 #ifdef DEBUG_COMBO
-        printf("CB_ADDSTRING '%s' !\n", (LPSTR)lParam);
+		printf("CB_ADDSTRING '%s' !\n", (LPSTR)lParam);
 #endif
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_ADDSTRING, wParam, lParam));
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_ADDSTRING, wParam, lParam));
     case CB_GETLBTEXT:
-        printf("CB_GETLBTEXT #%u !\n", wParam);
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_GETTEXT, wParam, lParam));
+		printf("CB_GETLBTEXT #%u !\n", wParam);
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_GETTEXT, wParam, lParam));
     case CB_GETLBTEXTLEN:
-        printf("CB_GETLBTEXTLEN !\n");
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_GETTEXTLEN, wParam, lParam));
+		printf("CB_GETLBTEXTLEN !\n");
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_GETTEXTLEN, wParam, lParam));
     case CB_INSERTSTRING:
-        printf("CB_INSERTSTRING '%s' !\n", (LPSTR)lParam);
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam));
-    case CB_DELETESTRING:
-        printf("CB_DELETESTRING #%u !\n", wParam);
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_DELETESTRING, wParam, 0L));
-    case CB_RESETCONTENT:
-        printf("CB_RESETCONTENT !\n");
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_RESETCONTENT, 0, 0L));
+		printf("CB_INSERTSTRING '%s' !\n", (LPSTR)lParam);
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam));
+	case CB_DELETESTRING:
+		printf("CB_DELETESTRING #%u !\n", wParam);
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_DELETESTRING, wParam, 0L));
+	case CB_RESETCONTENT:
+		printf("CB_RESETCONTENT !\n");
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_RESETCONTENT, 0, 0L));
     case CB_DIR:
-        printf("ComboBox CB_DIR !\n");
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_DIR, wParam, lParam));
-    case CB_FINDSTRING:
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam));
-    case CB_GETCOUNT:
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_GETCOUNT, 0, 0L));
-    case CB_GETCURSEL:
-        printf("ComboBox CB_GETCURSEL !\n");
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_GETCURSEL, 0, 0L));
+		printf("ComboBox CB_DIR !\n");
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_DIR, wParam, lParam));
+	case CB_FINDSTRING:
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam));
+	case CB_GETCOUNT:
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_GETCOUNT, 0, 0L));
+	case CB_GETCURSEL:
+		printf("ComboBox CB_GETCURSEL !\n");
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_GETCURSEL, 0, 0L));
     case CB_SETCURSEL:
-        printf("ComboBox CB_SETCURSEL wParam=%X !\n", wParam);
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_SETCURSEL, wParam, 0L));
-    case CB_GETEDITSEL:
-        printf("ComboBox CB_GETEDITSEL !\n");
-	lphc = ComboGetStorageHeader(hwnd);
+		printf("ComboBox CB_SETCURSEL wParam=%X !\n", wParam);
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_SETCURSEL, wParam, 0L));
+	case CB_GETEDITSEL:
+		printf("ComboBox CB_GETEDITSEL !\n");
+		lphc = ComboGetStorageHeader(hwnd);
 /*        return(SendMessage(lphc->hWndEdit, EM_GETSEL, 0, 0L)); */
-        break;
-     case CB_SETEDITSEL:
-        printf("ComboBox CB_SETEDITSEL lParam=%lX !\n", lParam);
-	lphc = ComboGetStorageHeader(hwnd);
+		break;
+	case CB_SETEDITSEL:
+		printf("ComboBox CB_SETEDITSEL lParam=%lX !\n", lParam);
+		lphc = ComboGetStorageHeader(hwnd);
 /*        return(SendMessage(lphc->hWndEdit, EM_SETSEL, 0, lParam)); */
-	break;
-    case CB_SELECTSTRING:
-        printf("ComboBox CB_SELECTSTRING !\n");
-	lphc = ComboGetStorageHeader(hwnd);
-        break;
-    case CB_SHOWDROPDOWN:
-        printf("ComboBox CB_SHOWDROPDOWN !\n");
-	lphc = ComboGetStorageHeader(hwnd);
-	lphc->dwState = lphc->dwState | CB_SHOWDROPDOWN;
-	if (wParam != 0) {
-	    ShowWindow(lphc->hWndLBox, SW_SHOW);
-	    }
-	else {
-	    lphc->dwState = lphc->dwState ^ CB_SHOWDROPDOWN;
-	    ShowWindow(lphc->hWndLBox, SW_HIDE);
-	    SendMessage(GetParent(hwnd), WM_COMMAND, wndPtr->wIDmenu,
-			        	MAKELONG(hwnd, CBN_DROPDOWN));
-	    }
-        break;
+		break;
+	case CB_SELECTSTRING:
+		printf("ComboBox CB_SELECTSTRING !\n");
+		lphc = ComboGetStorageHeader(hwnd);
+		break;
+	case CB_SHOWDROPDOWN:
+		printf("ComboBox CB_SHOWDROPDOWN !\n");
+		lphc = ComboGetStorageHeader(hwnd);
+		lphc->dwState = lphc->dwState | CB_SHOWDROPDOWN;
+		if (wParam != 0) {
+			ShowWindow(lphc->hWndLBox, SW_SHOW);
+			}
+		else {
+			lphc->dwState = lphc->dwState ^ CB_SHOWDROPDOWN;
+			ShowWindow(lphc->hWndLBox, SW_HIDE);
+			SendMessage(GetParent(hwnd), WM_COMMAND, wndPtr->wIDmenu,
+									MAKELONG(hwnd, CBN_DROPDOWN));
+		}
+		break;
     case CB_GETITEMDATA:
-        printf("ComboBox CB_GETITEMDATA wParam=%X !\n", wParam);
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_GETITEMDATA, wParam, 0L));
+		printf("ComboBox CB_GETITEMDATA wParam=%X !\n", wParam);
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_GETITEMDATA, wParam, 0L));
         break;
     case CB_SETITEMDATA:
-        printf("ComboBox CB_SETITEMDATA wParam=%X lParam=%lX !\n", wParam, lParam);
-	lphc = ComboGetStorageHeader(hwnd);
-        return(SendMessage(lphc->hWndLBox, LB_SETITEMDATA, wParam, lParam));
+		printf("ComboBox CB_SETITEMDATA wParam=%X lParam=%lX !\n", wParam, lParam);
+		lphc = ComboGetStorageHeader(hwnd);
+		return(SendMessage(lphc->hWndLBox, LB_SETITEMDATA, wParam, lParam));
         break;
     case CB_LIMITTEXT:
-        printf("ComboBox CB_LIMITTEXT !\n");
-	lphc = ComboGetStorageHeader(hwnd);
+		printf("ComboBox CB_LIMITTEXT !\n");
+		lphc = ComboGetStorageHeader(hwnd);
 /*        return(SendMessage(lphc->hWndEdit, EM_LIMITTEXT, wParam, 0L)); */
         break;
-	
+
     default:
-	return DefWindowProc( hwnd, message, wParam, lParam );
+		return DefWindowProc( hwnd, message, wParam, lParam );
     }
 return 0;
 }
diff --git a/controls/desktop.c b/controls/desktop.c
index 14bf3c5..183b2a2 100644
--- a/controls/desktop.c
+++ b/controls/desktop.c
@@ -6,16 +6,108 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1994";
 
-#include "windows.h"
+#include <stdio.h>
+#include <string.h>
+#include "win.h"
+#include "desktop.h"
 
+
+/***********************************************************************
+ *           DESKTOP_DoEraseBkgnd
+ *
+ * Handle the WM_ERASEBKGND message.
+ */
+static LONG DESKTOP_DoEraseBkgnd( HWND hwnd, HDC hdc, DESKTOPINFO *infoPtr )
+{
+    RECT rect;
+
+      /* Set colors in case pattern is a monochrome bitmap */
+    SetBkColor( hdc, RGB(0,0,0) );
+    SetTextColor( hdc, GetSysColor(COLOR_BACKGROUND) );
+    GetClientRect( hwnd, &rect );    
+    FillRect( hdc, &rect, infoPtr->hbrushPattern );
+    return 1;
+}
+
+
+/***********************************************************************
+ *           DesktopWndProc
+ *
+ * Window procedure for the desktop window.
+ */
 LONG DesktopWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 {
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    DESKTOPINFO *infoPtr = (DESKTOPINFO *)wndPtr->wExtra;
+
       /* Most messages are ignored (we DON'T call DefWindowProc) */
 
     switch(message)
     {
+	/* Warning: this message is sent directly by                     */
+	/* WIN_CreateDesktopWindow() and does not contain a valid lParam */
+    case WM_NCCREATE:
+	infoPtr->hbrushPattern = 0;
+	infoPtr->hbitmapWallPaper = 0;
+	SetDeskPattern();
+	break;
+	
+    case WM_ERASEBKGND:
+	if (rootWindow == DefaultRootWindow(display)) return 1;
+	return DESKTOP_DoEraseBkgnd( hwnd, (HDC)wParam, infoPtr );
     }
     
     return 0;
 }
 
+
+/***********************************************************************
+ *           SetDeskPattern   (USER.279)
+ */
+BOOL SetDeskPattern()
+{
+    char buffer[100];
+    GetProfileString( "desktop", "Pattern", "(None)", buffer, 100 );
+    return DESKTOP_SetPattern( buffer );
+}
+
+
+/***********************************************************************
+ *           SetDeskWallPaper   (USER.285)
+ */
+BOOL SetDeskWallPaper( LPSTR filename )
+{
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           DESKTOP_SetPattern
+ *
+ * Set the desktop pattern.
+ */
+BOOL DESKTOP_SetPattern(char *pattern )
+{
+    WND *wndPtr = WIN_FindWndPtr( GetDesktopWindow() );
+    DESKTOPINFO *infoPtr = (DESKTOPINFO *)wndPtr->wExtra;
+    int pat[8];
+
+    if (infoPtr->hbrushPattern) DeleteObject( infoPtr->hbrushPattern );
+    memset( pat, 0, sizeof(pat) );
+    if (pattern && sscanf( pattern, " %d %d %d %d %d %d %d %d",
+			   &pat[0], &pat[1], &pat[2], &pat[3],
+			   &pat[4], &pat[5], &pat[6], &pat[7] ))
+    {
+	WORD pattern[8];
+	HBITMAP hbitmap;
+	int i;
+
+	for (i = 0; i < 8; i++) pattern[i] = pat[i] & 0xffff;
+	hbitmap = CreateBitmap( 8, 8, 1, 1, pattern );
+	infoPtr->hbrushPattern = CreatePatternBrush( hbitmap );
+	DeleteObject( hbitmap );
+    }
+    else infoPtr->hbrushPattern = CreateSolidBrush( GetSysColor(COLOR_BACKGROUND) );
+    return TRUE;
+}
+
diff --git a/controls/listbox.c b/controls/listbox.c
index 76a3ecd..a20eea9 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -12,17 +12,17 @@
 static char Copyright[] = "Copyright Martin Ayotte, 1993";
 
 #include <stdio.h>
+#include <stdlib.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 "msdos.h"
 #include "wine.h"
 #include "listbox.h"
 #include "scroll.h"
-#include "int21.h"
 #include "prototypes.h"
 
 #define GMEM_ZEROINIT 0x0040
@@ -34,6 +34,7 @@
 void OwnerDrawListBox(HWND hwnd);
 int ListBoxFindMouse(HWND hwnd, int X, int Y);
 int CreateListBoxStruct(HWND hwnd);
+void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls);
 int ListBoxAddString(HWND hwnd, LPSTR newstr);
 int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr);
 int ListBoxGetText(HWND hwnd, UINT uIndex, LPSTR OutStr);
@@ -56,378 +57,411 @@
  */
 LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 {    
-    WND  *wndPtr;
-    LPHEADLIST  lphl;
-    WORD	wRet;
-    RECT	rect;
-    int		y;
-    CREATESTRUCT *createStruct;
-    static RECT rectsel;
-    switch(message)
-    {
-    case WM_CREATE:
-	CreateListBoxStruct(hwnd);
-	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+	WND  *wndPtr;
+	LPHEADLIST  lphl;
+	HWND	hWndCtl;
+	WORD	wRet;
+	RECT	rect;
+	int		y;
+	CREATESTRUCT *createStruct;
+	static RECT rectsel;
+    switch(message) {
+	case WM_CREATE:
+		CreateListBoxStruct(hwnd);
+		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
 #ifdef DEBUG_LISTBOX
-        printf("ListBox WM_CREATE %lX !\n", lphl);
+		printf("ListBox WM_CREATE %lX !\n", lphl);
 #endif
-	createStruct = (CREATESTRUCT *)lParam;
-     	if (HIWORD(createStruct->lpCreateParams) != 0)
-	    lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
-	else
-	    lphl->hWndLogicParent = GetParent(hwnd);
-	lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
-	if (wndPtr->dwStyle & WS_VSCROLL) {
-	    SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
-	    ShowScrollBar(hwnd, SB_VERT, FALSE);
-	    }
-	if (wndPtr->dwStyle & WS_HSCROLL) {
-	    SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
-	    ShowScrollBar(hwnd, SB_HORZ, FALSE);
-	    }
-	return 0;
-    case WM_DESTROY:
-	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-        if (lphl == 0) return 0;
-	ListBoxResetContent(hwnd);
-	free(lphl);
-	*((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
+		createStruct = (CREATESTRUCT *)lParam;
+		if (HIWORD(createStruct->lpCreateParams) != 0)
+			lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
+		else
+			lphl->hWndLogicParent = GetParent(hwnd);
+		lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
+		if (wndPtr->dwStyle & WS_VSCROLL) {
+			SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, TRUE);
+			ShowScrollBar(hwnd, SB_VERT, FALSE);
+			}
+		if (wndPtr->dwStyle & WS_HSCROLL) {
+			SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
+			ShowScrollBar(hwnd, SB_HORZ, FALSE);
+			}
+		if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
+			}
+		return 0;
+	case WM_DESTROY:
+		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+		if (lphl == 0) return 0;
+		ListBoxResetContent(hwnd);
+		free(lphl);
+		*((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
 #ifdef DEBUG_LISTBOX
-        printf("ListBox WM_DESTROY %lX !\n", lphl);
+		printf("ListBox WM_DESTROY %lX !\n", lphl);
 #endif
-	return 0;
+		return 0;
 
-    case WM_VSCROLL:
-        lphl = ListBoxGetStorageHeader(hwnd);
-        if (lphl == NULL) return 0;
-        y = lphl->FirstVisible;
-        switch(wParam) {
-            case SB_LINEUP:
-		if (lphl->FirstVisible > 1)
-		    lphl->FirstVisible--;
-		break;
-            case SB_LINEDOWN:
-		if (lphl->FirstVisible < lphl->ItemsCount)
-		    lphl->FirstVisible++;
-		break;
-	    case SB_PAGEUP:
-		if (lphl->FirstVisible > 1)  
-		    lphl->FirstVisible -= lphl->ItemsVisible;
-		break;
-	    case SB_PAGEDOWN:
-		if (lphl->FirstVisible < lphl->ItemsCount)  
-		    lphl->FirstVisible += lphl->ItemsVisible;
-		break;
-	    case SB_THUMBTRACK:
-	    	lphl->FirstVisible = LOWORD(lParam);
-		break;
-	    }
-	if (lphl->FirstVisible < 1)    lphl->FirstVisible = 1;
-	if (lphl->FirstVisible > lphl->ItemsCount)
-	    lphl->FirstVisible = lphl->ItemsCount;
-	if (y != lphl->FirstVisible) {
-	    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-	    InvalidateRect(hwnd, NULL, TRUE);
-	    UpdateWindow(hwnd);
-            }
-	return 0;
+	case WM_VSCROLL:
+#ifdef DEBUG_LISTBOX
+		printf("ListBox WM_VSCROLL w=%04X l=%08X !\n", wParam, lParam);
+#endif
+		lphl = ListBoxGetStorageHeader(hwnd);
+		if (lphl == NULL) return 0;
+		y = lphl->FirstVisible;
+		switch(wParam) {
+			case SB_LINEUP:
+				if (lphl->FirstVisible > 1)	
+					lphl->FirstVisible--;
+				break;
+			case SB_LINEDOWN:
+				if (lphl->FirstVisible < lphl->ItemsCount)
+					lphl->FirstVisible++;
+				break;
+			case SB_PAGEUP:
+				if (lphl->FirstVisible > 1)  
+					lphl->FirstVisible -= lphl->ItemsVisible;
+				break;
+			case SB_PAGEDOWN:
+				if (lphl->FirstVisible < lphl->ItemsCount)  
+					lphl->FirstVisible += lphl->ItemsVisible;
+				break;
+			case SB_THUMBTRACK:
+				lphl->FirstVisible = LOWORD(lParam);
+				break;
+			}
+		if (lphl->FirstVisible < 1)    lphl->FirstVisible = 1;
+		if (lphl->FirstVisible > lphl->ItemsCount)
+			lphl->FirstVisible = lphl->ItemsCount;
+		if (y != lphl->FirstVisible) {
+			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);
+	case WM_HSCROLL:
+#ifdef DEBUG_LISTBOX
+		printf("ListBox WM_HSCROLL w=%04X l=%08X !\n", wParam, lParam);
+#endif
+		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 = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+	        if (lphl == NULL) return 0;
+		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;
-	
-    case WM_LBUTTONDOWN:
-/*
-	SetFocus(hwnd);
-*/
-	SetCapture(hwnd);
-	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-        if (lphl == NULL) return 0;
-	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;
-    case WM_LBUTTONUP:
-	ReleaseCapture();
-	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-        if (lphl == NULL) return 0;
-	if (lphl->PrevFocused != lphl->ItemFocused)
-	    SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
-		        	MAKELONG(hwnd, LBN_SELCHANGE));
-	return 0;
-    case WM_RBUTTONUP:
-    case WM_LBUTTONDBLCLK:
-	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-        if (lphl == NULL) return 0;
-        SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
-		        	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->dwStyle & WS_VSCROLL)
-			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->dwStyle & WS_VSCROLL)
-			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:
-	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->dwStyle & WS_VSCROLL)
-	    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-        InvalidateRect(hwnd, NULL, TRUE);
-        UpdateWindow(hwnd);
-	break;
-    case WM_PAINT:
-	wndPtr = WIN_FindWndPtr(hwnd);
-	if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
-	    OwnerDrawListBox(hwnd);
-	    break;
-	    }
-	if ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) {
-	    OwnerDrawListBox(hwnd);
-	    break;
-	    }
-	StdDrawListBox(hwnd);
-	break;
+	case WM_LBUTTONUP:
+		ReleaseCapture();
+		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+		if (lphl == NULL) return 0;
+		if (lphl->PrevFocused != lphl->ItemFocused)
+			SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
+											MAKELONG(hwnd, LBN_SELCHANGE));
+		return 0;
+	case WM_RBUTTONUP:
+	case WM_LBUTTONDBLCLK:
+		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+		if (lphl == NULL) return 0;
+		SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
+										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->dwStyle & WS_VSCROLL)
+					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->dwStyle & WS_VSCROLL)
+					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:
+		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+		if (lphl == NULL) return 0;
+		switch(wParam) {
+			case VK_TAB:
+				hWndCtl = GetNextDlgTabItem(lphl->hWndLogicParent,
+					hwnd, !(GetKeyState(VK_SHIFT) < 0));
+				SetFocus(hWndCtl);
+				if ((GetKeyState(VK_SHIFT) < 0))
+					printf("ListBox PreviousDlgTabItem %04X !\n", hWndCtl);
+				else
+					printf("ListBox NextDlgTabItem %04X !\n", hWndCtl);
+				break;
+			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->dwStyle & WS_VSCROLL)
+			SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+		InvalidateRect(hwnd, NULL, TRUE);
+		UpdateWindow(hwnd);
+		break;
+	case WM_PAINT:
+		wndPtr = WIN_FindWndPtr(hwnd);
+		if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
+			OwnerDrawListBox(hwnd);
+			break;
+			}
+		if ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) {
+			OwnerDrawListBox(hwnd);
+			break;
+			}
+		StdDrawListBox(hwnd);
+		break;
+	case WM_SETFOCUS:
+#ifdef DEBUG_LISTBOX
+		printf("ListBox WM_SETFOCUS !\n");
+#endif
+		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+		break;
+	case WM_KILLFOCUS:
+#ifdef DEBUG_LISTBOX
+		printf("ListBox WM_KILLFOCUS !\n");
+#endif
+		InvalidateRect(hwnd, NULL, TRUE);
+		UpdateWindow(hwnd);
+		break;
 
     case LB_RESETCONTENT:
-        printf("ListBox LB_RESETCONTENT !\n");
-	ListBoxResetContent(hwnd);
-	return 0;
+#ifdef DEBUG_LISTBOX
+		printf("ListBox LB_RESETCONTENT !\n");
+#endif
+		ListBoxResetContent(hwnd);
+		return 0;
     case LB_DIR:
-        printf("ListBox LB_DIR !\n");
-	wRet = ListBoxDirectory(hwnd, wParam, (LPSTR)lParam);
-	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);
+		printf("ListBox LB_DIR !\n");
 #endif
-	return wRet;
-    case LB_INSERTSTRING:
-	wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)lParam);
-	return wRet;
-    case LB_DELETESTRING:
-        printf("ListBox LB_DELETESTRING #%u !\n", wParam);
-	wRet = ListBoxDeleteString(hwnd, wParam);
-	return wRet;
-    case LB_FINDSTRING:
-	wRet = ListBoxFindString(hwnd, wParam, (LPSTR)lParam);
-	return wRet;
-    case LB_GETCARETINDEX:
-	return wRet;
-    case LB_GETCOUNT:
-        lphl = ListBoxGetStorageHeader(hwnd);
-	return lphl->ItemsCount;
-    case LB_GETCURSEL:
-	lphl = ListBoxGetStorageHeader(hwnd);
-        printf("ListBox LB_GETCURSEL %u !\n", lphl->ItemFocused);
-	return lphl->ItemFocused;
-    case LB_GETHORIZONTALEXTENT:
-	return wRet;
-    case LB_GETITEMDATA:
-	return wRet;
-    case LB_GETITEMHEIGHT:
-	return wRet;
-    case LB_GETITEMRECT:
-	return wRet;
-    case LB_GETSEL:
-        wRet = ListBoxGetSel(hwnd, wParam);
-	return wRet;
-    case LB_GETSELCOUNT:
-	return wRet;
-    case LB_GETSELITEMS:
-	return wRet;
-    case LB_GETTEXTLEN:
-	return wRet;
-    case LB_GETTOPINDEX:
-	return wRet;
-    case LB_SELECTSTRING:
-	return wRet;
-    case LB_SELITEMRANGE:
-	return wRet;
-    case LB_SETCARETINDEX:
-	return wRet;
-    case LB_SETCOLUMNWIDTH:
-        lphl = ListBoxGetStorageHeader(hwnd);
-        lphl->ColumnsWidth = wParam;
-        break;
-    case LB_SETHORIZONTALEXTENT:
-	return wRet;
-    case LB_SETITEMDATA:
-	return wRet;
-    case LB_SETTABSTOPS:
-	return wRet;
-    case LB_SETCURSEL:
+		wRet = ListBoxDirectory(hwnd, wParam, (LPSTR)lParam);
+		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_SETCURSEL wParam=%x !\n", wParam);
+		printf("ListBox LB_GETTEXT #%u '%s' !\n", wParam, (LPSTR)lParam);
 #endif
-	wRet = ListBoxSetCurSel(hwnd, wParam);
-	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, 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;
-	if (wndPtr->dwStyle & WS_VSCROLL)
-	    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-	InvalidateRect(hwnd, NULL, TRUE);
-	UpdateWindow(hwnd);
-	break;
-    case LB_SETITEMHEIGHT:
+		return wRet;
+	case LB_INSERTSTRING:
+		wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)lParam);
+		return wRet;
+	case LB_DELETESTRING:
+		printf("ListBox LB_DELETESTRING #%u !\n", wParam);
+		wRet = ListBoxDeleteString(hwnd, wParam);
+		return wRet;
+	case LB_FINDSTRING:
+		wRet = ListBoxFindString(hwnd, wParam, (LPSTR)lParam);
+		return wRet;
+	case LB_GETCARETINDEX:
+		return wRet;
+	case LB_GETCOUNT:
+		lphl = ListBoxGetStorageHeader(hwnd);
+		return lphl->ItemsCount;
+	case LB_GETCURSEL:
+		lphl = ListBoxGetStorageHeader(hwnd);
 #ifdef DEBUG_LISTBOX
-        printf("ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
+		printf("ListBox LB_GETCURSEL %u !\n", lphl->ItemFocused);
 #endif
-	wRet = ListBoxSetItemHeight(hwnd, wParam, lParam);
-	return wRet;
-	
-    default:
-	return DefWindowProc( hwnd, message, wParam, lParam );
+		return lphl->ItemFocused;
+	case LB_GETHORIZONTALEXTENT:
+		return wRet;
+	case LB_GETITEMDATA:
+		return wRet;
+	case LB_GETITEMHEIGHT:
+		return wRet;
+	case LB_GETITEMRECT:
+		return wRet;
+	case LB_GETSEL:
+		wRet = ListBoxGetSel(hwnd, wParam);
+		return wRet;
+	case LB_GETSELCOUNT:
+		return wRet;
+	case LB_GETSELITEMS:
+		return wRet;
+	case LB_GETTEXTLEN:
+		return wRet;
+	case LB_GETTOPINDEX:
+		return wRet;
+	case LB_SELECTSTRING:
+		return wRet;
+	case LB_SELITEMRANGE:
+		return wRet;
+	case LB_SETCARETINDEX:
+		return wRet;
+	case LB_SETCOLUMNWIDTH:
+		lphl = ListBoxGetStorageHeader(hwnd);
+		lphl->ColumnsWidth = wParam;
+		break;
+	case LB_SETHORIZONTALEXTENT:
+		return wRet;
+	case LB_SETITEMDATA:
+		return wRet;
+	case LB_SETTABSTOPS:
+		return wRet;
+	case LB_SETCURSEL:
+#ifdef DEBUG_LISTBOX
+		printf("ListBox LB_SETCURSEL wParam=%x !\n", wParam);
+#endif
+		wRet = ListBoxSetCurSel(hwnd, wParam);
+		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, 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;
+		if (wndPtr->dwStyle & WS_VSCROLL)
+		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);
+		return wRet;
+
+	default:
+		return DefWindowProc( hwnd, message, wParam, lParam );
     }
 return 0;
 }
@@ -459,11 +493,13 @@
 	LPHEADLIST  lphl;
 	LPLISTSTRUCT lpls;
 	PAINTSTRUCT ps;
-	HBRUSH hBrush;
+	HBRUSH 	hBrush;
+	int 	OldBkMode;
+	DWORD 	dwOldTextColor;
 	HWND	hWndParent;
-	HDC hdc;
-	RECT rect;
-	UINT  i, h, h2, maxwidth, ipc;
+	HDC 	hdc;
+	RECT 	rect;
+	UINT	i, h, h2, maxwidth, ipc;
 	char	C[128];
 	h = 0;
 	hdc = BeginPaint( hwnd, &ps );
@@ -509,12 +545,18 @@
 		lpls->dis.rcItem.bottom = h + h2;
 		lpls->dis.rcItem.left = rect.left;
 		lpls->dis.rcItem.right = rect.right;
+		OldBkMode = SetBkMode(hdc, TRANSPARENT);
+		if (lpls->dis.itemState != 0) {
+			dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
+		    FillRect(hdc, &lpls->dis.rcItem, GetStockObject(BLACK_BRUSH));
+		    }
 		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);
+			SetTextColor(hdc, dwOldTextColor);
 		    }
-		if (lphl->ItemFocused == i - 1) {
+		SetBkMode(hdc, OldBkMode);
+		if ((lphl->ItemFocused == i - 1) && GetFocus() == hwnd) {
 		    DrawFocusRect(hdc, &lpls->dis.rcItem);
 		    }
 		h += h2;
@@ -675,6 +717,25 @@
 }
 
 
+void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls)  
+{
+	MEASUREITEMSTRUCT *measure;
+	HANDLE hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(MEASUREITEMSTRUCT));
+	measure = (MEASUREITEMSTRUCT *) USER_HEAP_ADDR(hTemp);
+	if (measure == NULL) return;
+	measure->CtlType = ODT_LISTBOX;
+	measure->CtlID = wndPtr->wIDmenu;
+	measure->itemID = lpls->dis.itemID;
+	measure->itemWidth = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
+	measure->itemHeight = 0;
+	measure->itemData = lpls->dis.itemData;
+	SendMessage(lphl->hWndLogicParent, WM_MEASUREITEM, 0, (DWORD)measure);
+	lpls->dis.rcItem.right = lpls->dis.rcItem.left + measure->itemWidth;
+	lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + measure->itemHeight;
+	USER_HEAP_FREE(hTemp);			
+}
+
+
 int ListBoxAddString(HWND hwnd, LPSTR newstr)
 {
     WND  	*wndPtr;
@@ -708,6 +769,9 @@
 	    if (str == NULL) return LB_ERRSPACE;
 	    strcpy(str, newstr);
 	    newstr = str;
+#ifdef DEBUG_LISTBOX
+	    printf("ListBoxAddString// after strcpy '%s'\n", str);
+#endif
 	    }
 	}
     ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
@@ -716,6 +780,8 @@
     lplsnew->dis.itemID = lphl->ItemsCount;
     lplsnew->dis.itemData = (DWORD)newstr;
     lplsnew->hData = hTemp;
+	if ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) 
+		ListBoxAskMeasure(wndPtr, lphl, lplsnew);
     if (wndPtr->dwStyle & WS_VSCROLL)
 	SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, 
 	    (lphl->FirstVisible != 1));
@@ -738,62 +804,62 @@
 
 int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr)
 {
-    WND  	*wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lplsnew;
-    HANDLE	hTemp;
-    LPSTR	str;
-    UINT	Count;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) 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++) {
-	if (lpls->lpNext == NULL) return LB_ERR;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-    }
-    hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LISTSTRUCT));
-    lplsnew = (LPLISTSTRUCT) USER_HEAP_ADDR(hTemp);
-    ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
-    lplsnew->hMem = hTemp;
-    lpls->lpNext = lplsnew;
-    lphl->ItemsCount++;
-    hTemp = 0;
-    if ((wndPtr->dwStyle & LBS_HASSTRINGS) != LBS_HASSTRINGS) {
-	if (((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) != LBS_OWNERDRAWFIXED) &&
-	    ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) != LBS_OWNERDRAWVARIABLE)) {
-	    hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, strlen(newstr) + 1);
-	    str = (LPSTR)USER_HEAP_ADDR(hTemp);
-	    if (str == NULL) return LB_ERRSPACE;
-	    strcpy(str, newstr);
-	    newstr = str;
-	    }
-	}
-    lplsnew->lpNext = NULL;
-    lplsnew->dis.itemID = lphl->ItemsCount;
-    lplsnew->dis.itemData = (DWORD)newstr;
-    lplsnew->hData = hTemp;
-    if (wndPtr->dwStyle & WS_VSCROLL)
-	SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, 
-	    (lphl->FirstVisible != 1));
-    if ((wndPtr->dwStyle & WS_HSCROLL) && 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)) {
+	WND  	*wndPtr;
+	LPHEADLIST 	lphl;
+	LPLISTSTRUCT lpls, lplsnew;
+	HANDLE	hTemp;
+	LPSTR	str;
+	UINT	Count;
+	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+	if (lphl == NULL) 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++) {
+		if (lpls->lpNext == NULL) return LB_ERR;
+		lpls = (LPLISTSTRUCT)lpls->lpNext;
+		}
+	hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LISTSTRUCT));
+	lplsnew = (LPLISTSTRUCT) USER_HEAP_ADDR(hTemp);
+	ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
+	lplsnew->hMem = hTemp;
+	lpls->lpNext = lplsnew;
+	lphl->ItemsCount++;
+	hTemp = 0;
+	if ((wndPtr->dwStyle & LBS_HASSTRINGS) != LBS_HASSTRINGS) {
+		if (((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) != LBS_OWNERDRAWFIXED) &&
+			((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) != LBS_OWNERDRAWVARIABLE)) {
+			hTemp = USER_HEAP_ALLOC(GMEM_MOVEABLE, strlen(newstr) + 1);
+			str = (LPSTR)USER_HEAP_ADDR(hTemp);
+			if (str == NULL) return LB_ERRSPACE;
+			strcpy(str, newstr);
+			newstr = str;
+			}
+		}
+	lplsnew->lpNext = NULL;
+	lplsnew->dis.itemID = lphl->ItemsCount;
+	lplsnew->dis.itemData = (DWORD)newstr;
+	lplsnew->hData = hTemp;
+	if ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) 
+		ListBoxAskMeasure(wndPtr, lphl, lplsnew);
 	if (wndPtr->dwStyle & WS_VSCROLL)
-	    ShowScrollBar(hwnd, SB_VERT, TRUE);
-	if (wndPtr->dwStyle & WS_HSCROLL)
-	    ShowScrollBar(hwnd, SB_HORZ, TRUE);
-	}
-    if ((lphl->FirstVisible <= uIndex) &&
-        ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
-        InvalidateRect(hwnd, NULL, TRUE);
-        UpdateWindow(hwnd);
-        }
-    return lphl->ItemsCount;
+		SetScrollRange(hwnd, SB_VERT, 1, lphl->ItemsCount, 
+						    (lphl->FirstVisible != 1));
+	if ((wndPtr->dwStyle & WS_HSCROLL) && 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)) {
+		if (wndPtr->dwStyle & WS_VSCROLL) ShowScrollBar(hwnd, SB_VERT, TRUE);
+		if (wndPtr->dwStyle & WS_HSCROLL) ShowScrollBar(hwnd, SB_HORZ, TRUE);
+		}
+	if ((lphl->FirstVisible <= uIndex) &&
+		((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
+		InvalidateRect(hwnd, NULL, TRUE);
+		UpdateWindow(hwnd);
+		}
+	return lphl->ItemsCount;
 }
 
 
@@ -1015,25 +1081,20 @@
 	struct stat	st;
 	int	x, wRet;
 	char 	temp[256];
-
+#ifdef DEBUG_LISTBOX
 	fprintf(stderr,"ListBoxDirectory: %s, %4x\n",filespec,attrib);
-
-
-	if ((dp = (struct dosdirent *)DOS_opendir(filespec)) ==NULL)
-		return 0;
-	
-	while (1)
-	{
+#endif
+	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 (!dp->inuse)	break;
+#ifdef DEBUG_LISTBOX
+		printf("ListBoxDirectory %08X '%s' !\n", dp->filename, dp->filename);
+#endif
+		if (dp->attribute & FA_DIREC) {
 			if (attrib & DDL_DIRECTORY) {
 				sprintf(temp, "[%s]", dp->filename);
-				if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR)
-	    				break;
+				if ( (wRet = ListBoxAddString(hwnd, temp)) == LB_ERR) break;
 			}
 		} else 
 		if (attrib & DDL_EXCLUSIVE) {
@@ -1059,7 +1120,9 @@
 			}		
 		}
 	}
-
+#ifdef DEBUG_LISTBOX
+	printf("End of ListBoxDirectory !\n");
+#endif
 	return wRet;
 }
 
diff --git a/controls/menu.c b/controls/menu.c
index 53d9f0d..9ab0366 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -6,35 +6,44 @@
 
 /*
 #define DEBUG_MENU
-#define DEBUG_SYSMENU
 */
 
+#include <stdlib.h>
+#include <stdio.h>
 #include "windows.h"
 #include "sysmetrics.h"
+#include "prototypes.h"
 #include "menu.h"
 #include "heap.h"
 #include "win.h"
 
-#define SC_ABOUTWINE     SC_SCREENSAVE+1
-#define SC_SYSMENU	 SC_SCREENSAVE+2
-#define SC_ABOUTWINEDLG	 SC_SCREENSAVE+3
+#define SC_ABOUTWINE    	SC_SCREENSAVE+1
+#define SC_SYSMENU			SC_SCREENSAVE+2
+#define SC_ABOUTWINEDLG		SC_SCREENSAVE+3
 
 extern HINSTANCE hSysRes;
 HMENU	hSysMenu = 0;
 HBITMAP hStdCheck = 0;
 HBITMAP hStdMnArrow = 0;
+static BOOL	MenuHasFocus = FALSE;
 
 LPPOPUPMENU PopupMenuGetStorageHeader(HWND hwnd);
 LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr);
 void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop);
-void MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
+BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
 void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
 void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y);
 void StdDrawPopupMenu(HWND hwnd);
+void ResetHiliteFlags(LPPOPUPMENU lppop);
+BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop);
+void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex);
 LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet);
 LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet);
+BOOL ActivateMenuFocus(HWND hWnd);
+BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu);
 void PopupMenuCalcSize(HWND hwnd);
 void MenuBarCalcSize(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop);
+LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags);
 LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos);
 WORD GetSelectionKey(LPSTR str);
 LPSTR GetShortCutString(LPSTR str);
@@ -51,491 +60,538 @@
  */
 LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 {    
-    CREATESTRUCT *createStruct;
-    WORD	wRet;
-    short	x, y;
-    WND  	*wndPtr;
-    LPPOPUPMENU lppop, lppop2;
-    LPMENUITEM	lpitem, lpitem2;
-    HMENU	hSubMenu;
-    RECT	rect;
-    HDC		hDC;
-    PAINTSTRUCT ps;
-    switch(message) 
-    {
-    case WM_CREATE:
+	CREATESTRUCT *createStruct;
+	WORD	wRet;
+	short	x, y;
+	WND  	*wndPtr;
+	LPPOPUPMENU lppop, lppop2;
+	LPMENUITEM	lpitem, lpitem2;
+	HMENU	hSubMenu;
+	RECT	rect;
+	HDC		hDC;
+	PAINTSTRUCT ps;
+	switch(message) {
+	case WM_CREATE:
 #ifdef DEBUG_MENU
-        printf("PopupMenu WM_CREATE lParam=%08X !\n", lParam);
+		printf("PopupMenu WM_CREATE lParam=%08X !\n", lParam);
 #endif
-	createStruct = (CREATESTRUCT *)lParam;
-     	lppop = (LPPOPUPMENU)createStruct->lpCreateParams;
-     	if (lppop == NULL) break;
-	wndPtr = WIN_FindWndPtr(hwnd);
-	*((LPPOPUPMENU *)&wndPtr->wExtra[1]) = lppop;
+		createStruct = (CREATESTRUCT *)lParam;
+		lppop = (LPPOPUPMENU)createStruct->lpCreateParams;
+		if (lppop == NULL) break;
+		wndPtr = WIN_FindWndPtr(hwnd);
+		*((LPPOPUPMENU *)&wndPtr->wExtra[1]) = lppop;
 #ifdef DEBUG_MENU
-        printf("PopupMenu WM_CREATE lppop=%08X !\n", lppop);
+		printf("PopupMenu WM_CREATE lppop=%08X !\n", lppop);
 #endif
-	if (hStdCheck == (HBITMAP)NULL) 
-	    hStdCheck = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_CHECK);
-	if (hStdMnArrow == (HBITMAP)NULL) 
-	    hStdMnArrow = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_MNARROW);
-	return 0;
-    case WM_DESTROY:
-	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+		if (hStdCheck == (HBITMAP)NULL) 
+			hStdCheck = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_CHECK);
+		if (hStdMnArrow == (HBITMAP)NULL) 
+			hStdMnArrow = LoadBitmap((HANDLE)NULL, (LPSTR)OBM_MNARROW);
+		return 0;
+	case WM_DESTROY:
+		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
 #ifdef DEBUG_MENU
-        printf("PopupMenu WM_DESTROY %lX !\n", lppop);
+		printf("PopupMenu WM_DESTROY %lX !\n", lppop);
 #endif
-	return 0;
-    case WM_COMMAND:
-	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-	if (lppop->hWndParent != (HWND)NULL) {
-	    SendMessage(lppop->hWndParent, WM_COMMAND, wParam, lParam);
+		return 0;
+	case WM_COMMAND:
 #ifdef DEBUG_MENU
-	    printf("PopupMenu // push to lower parent WM_COMMAND !\n");
+		printf("PopupMenuWndProc // WM_COMMAND received !\n");
 #endif
-	    }
-	else {
-	    if (lppop->SysFlag == 0) {
-		SendMessage(lppop->ownerWnd, WM_COMMAND, wParam, lParam);
+		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+		if (lppop == NULL) break;
+/*		if (!lppop->BarFlag)  ShowWindow(hwnd, SW_HIDE); */
+		if (lppop->SysFlag) {
+			MenuHasFocus = FALSE;
+			if (wParam == SC_ABOUTWINE) {
+				printf("SysMenu // Show 'About Wine ...' !\n");
+/*				DialogBox(hSysRes, MAKEINTRESOURCE(SC_ABOUTWINEDLG), */
+				DialogBox(hSysRes, MAKEINTRESOURCE(2), 
+					GetParent(hwnd), (FARPROC)AboutWine_Proc);
+				}
+			else
 #ifdef DEBUG_MENU
-		printf("PopupMenu // push to Owner WM_COMMAND !\n");
+				printf("PopupMenuWndProc // push to Owner WM_SYSCOMMAND !\n");
 #endif
-		}
-	    else {
-#ifdef DEBUG_SYSMENU
-		printf("PopupMenu // push to Owner WM_SYSCOMMAND !\n");
-#endif
-		SendMessage(lppop->ownerWnd, WM_SYSCOMMAND, wParam, lParam);
-		}
-	    }
-	if (lppop->BarFlags == 0)  ShowWindow(hwnd, SW_HIDE);
-    	break;
-    case WM_SHOWWINDOW:
-	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-    	if (wParam == 0 && lParam == 0L) {
-	    HideAllSubPopupMenu(lppop);
-#ifdef DEBUG_MENU
-	    printf("PopupMenu WM_SHOWWINDOW -> HIDE!\n");
-#endif
-/*
-	    UpdateWindow(lppop->ownerWnd);
-*/
-	    break;
-	    }
-	lppop->FocusedItem = (WORD)-1;
-	if (lppop->BarFlags == 0) {
-	    PopupMenuCalcSize(hwnd);
-#ifdef DEBUG_MENU
-	    printf("PopupMenu WM_SHOWWINDOW Width=%d Height=%d !\n", 
-			lppop->Width, lppop->Height);
-#endif
-	    SetWindowPos(hwnd, 0, 0, 0, lppop->Width + 2, lppop->Height, 
-		SWP_NOZORDER | SWP_NOMOVE);
-	    }
-    	break;
-    case WM_LBUTTONDOWN:
-	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-	SetCapture(hwnd);
-	MenuButtonDown(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
-	break;
-    case WM_LBUTTONUP:
-	lppop = PopupMenuGetStorageHeader(hwnd);
-	ReleaseCapture();
-	MenuButtonUp(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
-	break;
-    case WM_MOUSEMOVE:
-	lppop = PopupMenuGetStorageHeader(hwnd);
-	MenuMouseMove(hwnd, lppop, wParam, LOWORD(lParam), HIWORD(lParam));
-	break;
-
-    case WM_KEYDOWN:
-    case WM_KEYUP:
-	if (lParam < 0L) break;
-	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-	if (lppop->FocusedItem == (WORD)-1) {
-	    if (wParam == VK_UP || wParam == VK_DOWN || 
-		wParam == VK_LEFT || wParam == VK_RIGHT) {
-		hDC = GetDC(hwnd);
-		lppop->FocusedItem = 0;
-		lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
-		if (((lpitem->item_flags & MF_POPUP) == MF_POPUP) ||
-		    ((lpitem->item_flags & MF_STRING) == MF_STRING)) {
-		    InvertRect(hDC, &lpitem->rect);
-		    }
-		ReleaseDC(hwnd, hDC);
-		}
-	    break;
-	    }
-	switch(wParam) {
-	    case VK_UP:
-		if (lppop->BarFlags != 0) break;
-		if (lppop->FocusedItem < 1) break;
-		lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
-		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP)
-		    HideAllSubPopupMenu(lppop);
-		hDC = GetDC(hwnd);
-		if (((lpitem->item_flags & MF_POPUP) == MF_POPUP) ||
-		    ((lpitem->item_flags & MF_STRING) == MF_STRING)) {
-		    InvertRect(hDC, &lpitem->rect);
-		    }
-		lppop->FocusedItem--;
-		lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
-		if (((lpitem->item_flags & MF_POPUP) == MF_POPUP) ||
-		    ((lpitem->item_flags & MF_STRING) == MF_STRING)) {
-		    InvertRect(hDC, &lpitem->rect);
-		    }
-		ReleaseDC(hwnd, hDC);
-		break;
-	    case VK_DOWN:
-		if (lppop->BarFlags != 0) goto ProceedSPACE;
-		if (lppop->FocusedItem >= lppop->nItems - 1) break;
-		lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
-		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP)
-		    HideAllSubPopupMenu(lppop);
-		hDC = GetDC(hwnd);
-		if (((lpitem->item_flags & MF_POPUP) == MF_POPUP) ||
-		    ((lpitem->item_flags & MF_STRING) == MF_STRING)) {
-		    InvertRect(hDC, &lpitem->rect);
-		    }
-		lppop->FocusedItem++;
-		lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
-		if (((lpitem->item_flags & MF_POPUP) == MF_POPUP) ||
-		    ((lpitem->item_flags & MF_STRING) == MF_STRING)) {
-		    InvertRect(hDC, &lpitem->rect);
-		    }
-		ReleaseDC(hwnd, hDC);
-		break;
-	    case VK_LEFT:
-		if (lppop->BarFlags == 0) {
-		    if (lppop->hWndParent != 0) 
-			SendMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
-		    break;
-		    }
-		if (lppop->FocusedItem < 1) break;
-		lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
-		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP)
-		    HideAllSubPopupMenu(lppop);
-		hDC = GetDC(hwnd);
-		if (((lpitem->item_flags & MF_POPUP) == MF_POPUP) ||
-		    ((lpitem->item_flags & MF_STRING) == MF_STRING)) {
-		    InvertRect(hDC, &lpitem->rect);
-		    }
-		lppop->FocusedItem--;
-		lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
-		if (((lpitem->item_flags & MF_POPUP) == MF_POPUP) ||
-		    ((lpitem->item_flags & MF_STRING) == MF_STRING)) {
-		    InvertRect(hDC, &lpitem->rect);
-		    }
-		ReleaseDC(hwnd, hDC);
-		break;
-	    case VK_RIGHT:
-		if (lppop->BarFlags == 0) {
-		    if (lppop->hWndParent != 0) 
-			SendMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
-		    break;
-		    }
-		if (lppop->FocusedItem >= lppop->nItems - 1) break;
-		lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
-		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP)
-		    HideAllSubPopupMenu(lppop);
-		hDC = GetDC(hwnd);
-		if (((lpitem->item_flags & MF_POPUP) == MF_POPUP) ||
-		    ((lpitem->item_flags & MF_STRING) == MF_STRING)) {
-		    InvertRect(hDC, &lpitem->rect);
-		    }
-		lppop->FocusedItem++;
-		lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
-		if (((lpitem->item_flags & MF_POPUP) == MF_POPUP) ||
-		    ((lpitem->item_flags & MF_STRING) == MF_STRING)) {
-		    InvertRect(hDC, &lpitem->rect);
-		    }
-		ReleaseDC(hwnd, hDC);
-		break;
-	    case VK_RETURN:
-	    case VK_SPACE:
-ProceedSPACE:
-		printf("PopupMenu VK_SPACE !\n");
-		lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
-		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
-		    hSubMenu = (HMENU)lpitem->item_id;
-		    lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
-		    if (lppop2 == NULL) break;
-		    lppop2->hWndParent = hwnd;
-		    GetClientRect(hwnd, &rect);
-		    if (lppop->BarFlags != 0) {
-			y = rect.bottom - rect.top;
-			TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-				lpitem->rect.left, 0, 
-				0, lppop->ownerWnd, (LPRECT)NULL);
+				PostMessage(lppop->ownerWnd, WM_SYSCOMMAND, wParam, lParam);
+/*				PostMessage(lppop->hWndParent, WM_SYSCOMMAND, wParam, lParam); */
+			break;
 			}
-		    else {
-			x = rect.right;
-			GetWindowRect(hwnd, &rect);
-			x += rect.left;
-			TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-				x, lpitem->rect.top,
-				0, lppop->ownerWnd, (LPRECT)NULL);
-			}
-		    GlobalUnlock(hSubMenu);
-		    break;
-		    }
-		if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
-		    ((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
-		    ShowWindow(lppop->hWnd, SW_HIDE);
-		    if (lppop->hWndParent != (HWND)NULL)
-			SendMessage(lppop->hWndParent, WM_COMMAND, 
-					lpitem->item_id, 0L);
-		    else 
-			SendMessage(lppop->ownerWnd, WM_COMMAND, 
-					lpitem->item_id, 0L);
 #ifdef DEBUG_MENU
-		    printf("PopupMenu // SendMessage WM_COMMAND wParam=%d !\n", 
-				lpitem->item_id);
+		printf("PopupMenuWndProc // push to Owner WM_COMMAND !\n");
 #endif
-		   }
+		MenuHasFocus = FALSE;
+		PostMessage(lppop->hWndParent, WM_COMMAND, wParam, lParam);
+/*		PostMessage(lppop->ownerWnd, WM_COMMAND, wParam, lParam); */
 		break;
-	    }
-	break;
-    case WM_CHAR:
-	if (lParam < 0L) break;
-	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-	if (wParam == VK_ESCAPE) {
-	    if (lppop->hWndParent != 0) {
-		lppop2 = PopupMenuGetWindowAndStorage(
-			lppop->hWndParent, &wndPtr);
-		HideAllSubPopupMenu(lppop2);
-		break;
-		}
-	    if (lppop->FocusedItem != (WORD)-1) {
-		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);
-		    }
-		ReleaseDC(hwnd, hDC);
+	case WM_SHOWWINDOW:
+#ifdef DEBUG_MENU
+		printf("PopupMenuWndProc // WM_SHOWWINDOW received !\n");
+#endif
+		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+		if (lppop == NULL) break;
+		if (wParam == 0 && lParam == 0L) {
+			HideAllSubPopupMenu(lppop);
+#ifdef DEBUG_MENU
+			printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW -> HIDE!\n", hwnd);
+#endif
+			if (lppop->SysFlag) MenuHasFocus = FALSE;
+			SetFocus(lppop->hWndPrev);
+			break;
+			}
 		lppop->FocusedItem = (WORD)-1;
-		}
-	    }
-	if (wParam >= 'a' && wParam <= 'z') wParam -= 'a' - 'A';
-	lpitem = MenuFindItemBySelKey(lppop, wParam, &wRet);
-	if (lpitem != NULL) {
-	    printf("Found  wRet=%d !\n", wRet);
-	    if (lppop->FocusedItem != (WORD)-1) {
-		lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
-		if ((lpitem2->item_flags & MF_POPUP) == MF_POPUP)
-		    HideAllSubPopupMenu(lppop);
-		hDC = GetDC(hwnd);
-		if (((lpitem2->item_flags & MF_POPUP) == MF_POPUP) ||
-		    ((lpitem2->item_flags & MF_STRING) == MF_STRING)) {
-		    InvertRect(hDC, &lpitem2->rect);
-		    }
-		ReleaseDC(hwnd, hDC);
-		}
-	    lppop->FocusedItem = wRet;
-	    goto ProceedSPACE;
-	    }
-	break;
-    case WM_PAINT:
-	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-	if (lppop->BarFlags == 0) {
-	    PopupMenuCalcSize(hwnd);
-	    StdDrawPopupMenu(hwnd);
-	    }
-	break;
-    default:
-	return DefWindowProc( hwnd, message, wParam, lParam );
+		if (!lppop->BarFlag) {
+			PopupMenuCalcSize(hwnd);
+			ResetHiliteFlags(lppop);
+#ifdef DEBUG_MENU
+			printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW Width=%d Height=%d !\n", 
+									hwnd, lppop->Width, lppop->Height);
+#endif
+			SetWindowPos(hwnd, 0, 0, 0, lppop->Width + 2, lppop->Height, 
+											SWP_NOZORDER | SWP_NOMOVE);
+#ifdef DEBUG_MENU
+			printf("PopupMenuWndProc // End of WM_SHOWWINDOW !\n");
+#endif
+			}
+    	break;
+	case WM_LBUTTONDOWN:
+		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+		if (lppop == NULL) break;
+		SetCapture(hwnd); 
+		MenuButtonDown(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
+		break;
+	case WM_LBUTTONUP:
+		lppop = PopupMenuGetStorageHeader(hwnd);
+		if (lppop == NULL) break;
+		ReleaseCapture(); 
+		MenuButtonUp(hwnd, lppop, LOWORD(lParam), HIWORD(lParam));
+		break;
+	case WM_MOUSEMOVE:
+		lppop = PopupMenuGetStorageHeader(hwnd);
+		if (lppop == NULL) break;
+		MenuMouseMove(hwnd, lppop, wParam, LOWORD(lParam), HIWORD(lParam));
+		break;
+
+	case WM_KEYUP:
+#ifdef DEBUG_MENU
+		printf("PopupMenuWndProc hWnd=%04X WM_KEYUP w=%04X l=%08X !\n", 
+												hwnd, wParam, lParam);
+#endif
+		break;
+	case WM_KEYDOWN:
+#ifdef DEBUG_MENU
+		printf("PopupMenuWndProc hWnd=%04X WM_KEYDOWN w=%04X l=%08X !\n", 
+												hwnd, wParam, lParam);
+#endif
+		if (lParam < 0L) break;
+		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+		if (lppop == NULL) break;
+		switch(wParam) {
+			case VK_HOME:
+				if (lppop->FocusedItem == 0) break;
+				MenuItemSelect(hwnd, lppop, 0);
+				break;
+			case VK_UP:
+				if (lppop->BarFlag) break;
+				if (lppop->FocusedItem < 1) break;
+				MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
+				break;
+			case VK_DOWN:
+				if (lppop->BarFlag) goto ProceedSPACE;
+				if (lppop->FocusedItem == (WORD)-1) {
+					MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
+					break;
+					}
+				if (lppop->FocusedItem >= lppop->nItems - 1) break;
+				MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
+				break;
+			case VK_LEFT:
+				if (lppop->SysFlag != 0) {
+					ShowWindow(hwnd, SW_HIDE);
+					hwnd = lppop->hWndParent;
+					lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+					if (lppop == NULL) break;
+					MenuItemSelect(hwnd, lppop, lppop->nItems - 1);
+				    break;
+					}
+				if (lppop->BarFlag) {
+					if (lppop->FocusedItem < 1) {
+						MenuItemSelect(hwnd, lppop, -1);
+						NC_TrackSysMenu(hwnd);
+						break;
+						}
+					if (HideAllSubPopupMenu(lppop)) {
+						MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
+						goto ProceedSPACE;
+						}
+					}
+			    if (lppop->hWndParent != 0) {
+					PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
+				    break;
+				    }
+				MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
+				break;
+			case VK_RIGHT:
+				if (lppop->SysFlag != 0) {
+					ShowWindow(hwnd, SW_HIDE);
+					hwnd = lppop->hWndParent;
+					lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+					if (lppop == NULL) break;
+					MenuItemSelect(hwnd, lppop, 0);
+				    break;
+					}
+				if (lppop->BarFlag) {
+					if (lppop->FocusedItem >= lppop->nItems - 1) {
+						MenuItemSelect(hwnd, lppop, -1);
+						NC_TrackSysMenu(hwnd);
+						break;
+						}
+					if (HideAllSubPopupMenu(lppop)) {
+						MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
+						goto ProceedSPACE;
+						}
+					}
+			    if (lppop->hWndParent != 0) {
+					PostMessage(lppop->hWndParent, WM_KEYDOWN, wParam, lParam);
+				    break;
+				    }
+				MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
+				break;
+			case VK_RETURN:
+			case VK_SPACE:
+ProceedSPACE:	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+				ExecFocusedMenuItem(hwnd, lppop);
+				break;
+			default:
+				break;
+			}
+			break;
+	case WM_CHAR:
+#ifdef DEBUG_MENU
+		printf("PopupMenuWndProc hWnd=%04X WM_CHAR wParam=%04X !\n", hwnd, wParam);
+#endif
+		if (lParam < 0L) break;
+		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+		if (lppop == NULL) break;
+		if (wParam == VK_ESCAPE) {
+			if (lppop->BarFlag) {
+#ifdef DEBUG_MENU
+				printf("VK_ESCAPE // Unselect all MenuBar's Items !\n");
+#endif
+				if (lppop->FocusedItem != (WORD)-1)
+					MenuItemSelect(hwnd, lppop, -1);
+				}
+			if (lppop->SysFlag) {
+#ifdef DEBUG_MENU
+				printf("VK_ESCAPE // SysMenu !\n");
+#endif
+				ShowWindow(hwnd, SW_HIDE);
+				break;
+				}
+			if (lppop->hWndParent != 0) {
+#ifdef DEBUG_MENU
+				printf("VK_ESCAPE // Hide only SubPopup !\n");
+#endif
+				lppop2 = PopupMenuGetWindowAndStorage(lppop->hWndParent, &wndPtr);
+				if (lppop2 == NULL) break;
+				HideAllSubPopupMenu(lppop2);
+				break;
+				}
+			else {
+#ifdef DEBUG_MENU
+				printf("VK_ESCAPE // Hide Root Popup !\n");
+#endif
+				ShowWindow(hwnd, SW_HIDE);
+				MenuHasFocus = FALSE;
+				}
+			break;
+			}
+		if (wParam >= 'a' && wParam <= 'z') wParam -= 'a' - 'A';
+		lpitem = MenuFindItemBySelKey(lppop, wParam, &wRet);
+		if (lpitem != NULL) {
+		    printf("Found  wRet=%d !\n", wRet);
+			MenuItemSelect(hwnd, lppop, wRet);
+			lppop->FocusedItem = wRet;
+			goto ProceedSPACE;
+			}
+		if (lppop->hWndParent != (HWND)NULL)
+			SendMessage(lppop->hWndParent, WM_MENUCHAR, wParam, 
+				MAKELONG(0, 0));
+		else 
+			SendMessage(lppop->ownerWnd, WM_MENUCHAR, wParam, 
+				MAKELONG(0, 0));
+		break;
+	case WM_PAINT:
+#ifdef DEBUG_MENU
+		printf("PopupMenuWndProc // WM_PAINT received !\n");
+#endif
+		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+		if (lppop == NULL) break;
+		if (!lppop->BarFlag) {
+			PopupMenuCalcSize(hwnd);
+			StdDrawPopupMenu(hwnd);
+			}
+		break;
+	default:
+		return DefWindowProc(hwnd, message, wParam, lParam);
     }
-return(0);
+return 0;
 }
 
 
-void MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
+BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop)
 {
-    HDC		hDC;
-    LPMENUITEM	lpitem, lpitem2;
-    RECT	rect;
-    HMENU	hSubMenu;
-    WORD	wRet;
-    LPPOPUPMENU lppop2;
-    lpitem = MenuFindItem(lppop, x, y, &wRet);
-#ifdef DEBUG_MENU
-    printf("MenuButtonDown // x=%d y=%d // wRet=%d lpitem=%08X !\n", 
-					x, y, wRet, lpitem);
-#endif
-    if (lpitem != NULL) {
-	if (lppop->FocusedItem != (WORD)-1) {
-	    HideAllSubPopupMenu(lppop);
-	    lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
-	    if (((lpitem2->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
-		((lpitem2->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
-	        hDC = GetWindowDC(hWnd);
-	        InvertRect(hDC, &lpitem2->rect);
-		ReleaseDC(hWnd, hDC);
-		}
-	    }
-	lppop->FocusedItem = wRet;
-	if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
-	    ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
-	    hDC = GetWindowDC(hWnd);
-	    InvertRect(hDC, &lpitem->rect);
-	    ReleaseDC(hWnd, hDC);
-	    }
+	short	x, y;
+	LPPOPUPMENU lppop2;
+	LPMENUITEM	lpitem;
+	HMENU	hSubMenu;
+	RECT	rect;
+	lpitem = GetMenuItemPtr(lppop, lppop->FocusedItem);
 	if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
-	    hSubMenu = (HMENU)lpitem->item_id;
-	    lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
-	    if (lppop2 == NULL) return;
-	    lppop2->hWndParent = hWnd;
-	    if (lppop->BarFlags != 0) {
-		GetWindowRect(hWnd, &rect);
-/*		y = rect.top + lppop->Height; */
-		y = rect.top + lppop->rect.bottom;
-		TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-			rect.left + lpitem->rect.left, 
-			y, 0, lppop->ownerWnd, (LPRECT)NULL);
+		hSubMenu = (HMENU)lpitem->item_id;
+		lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
+		if (lppop2 == NULL) return FALSE;
+		lppop2->hWndParent = hWnd;
+		lppop2->hWndPrev = GetFocus();
+		GetClientRect(hWnd, &rect);
+		if (lppop->BarFlag) {
+			GetWindowRect(hWnd, &rect);
+			y = rect.top + lppop->rect.bottom;
+			TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
+				rect.left + lpitem->rect.left, 
+				y, 0, lppop->ownerWnd, (LPRECT)NULL);
+			}
+		else {
+			x = lppop->rect.right;
+			GetWindowRect(hWnd, &rect);
+			x += rect.left;
+			TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
+				x, rect.top + lpitem->rect.top,
+				0, lppop->ownerWnd, (LPRECT)NULL);
+			}
+		GlobalUnlock(hSubMenu);
+		return TRUE;
 		}
-	    else {
-		x = lppop->rect.right;
-		GetWindowRect(hWnd, &rect);
-		x += rect.left;
-		TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-			x, rect.top + lpitem->rect.top,
-			0, lppop->ownerWnd, (LPRECT)NULL);
+	if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
+		((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
+		MenuHasFocus = FALSE;
+		if (lppop->BarFlag) {
+			PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
+			}
+		else {
+			ShowWindow(lppop->hWnd, SW_HIDE);
+			SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L);
+			}
 		}
-	    GlobalUnlock(hSubMenu);
-	    }
-	}
+	return TRUE;
+}
+
+
+
+BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
+{
+	HDC		hDC;
+	LPMENUITEM	lpitem, lpitem2;
+	RECT	rect;
+	HMENU	hSubMenu;
+	WORD	wRet;
+	LPPOPUPMENU lppop2;
+	if (lppop == NULL) return;
+	lpitem = MenuFindItem(lppop, x, y, &wRet);
+#ifdef DEBUG_MENU
+	printf("MenuButtonDown // x=%d y=%d // wRet=%d lpitem=%08X !\n", 
+												x, y, wRet, lpitem);
+#endif
+	if (lpitem != NULL) {
+		MenuItemSelect(hWnd, lppop, wRet);
+		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
+			hSubMenu = (HMENU)lpitem->item_id;
+			lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
+			if (lppop2 == NULL) return;
+			lppop2->hWndParent = hWnd;
+			lppop2->hWndPrev = GetFocus();
+			if (lppop->BarFlag) {
+				GetWindowRect(hWnd, &rect);
+				y = rect.top + lppop->rect.bottom;
+				ReleaseCapture(); 
+				if (MenuHasFocus) {
+					TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
+						rect.left + lpitem->rect.left, 
+						y, 0, lppop->ownerWnd, (LPRECT)NULL);
+					}
+				else {
+					MenuHasFocus = TRUE;
+					TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
+						rect.left + lpitem->rect.left, 
+						y, 0, lppop->ownerWnd, (LPRECT)NULL);
+					MenuHasFocus = FALSE;
+					MenuFocusLoop(hWnd, lppop);
+					return TRUE;
+					}
+				}
+			else {
+				x = lppop->rect.right;
+				GetWindowRect(hWnd, &rect);
+				x += rect.left;
+				TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON,
+					x, rect.top + lpitem->rect.top,
+					0, lppop->ownerWnd, (LPRECT)NULL);
+				}
+			GlobalUnlock(hSubMenu);
+			}
+		return TRUE;
+		}
+	printf("MenuButtonDown // x=%d y=%d // Not Found !\n", x, y);
+	MenuHasFocus = FALSE;
+	ShowWindow(lppop->hWnd, SW_HIDE);
+	return FALSE;
 }
 
 
 
 void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y)
 {
-    HDC		hDC;
-    LPMENUITEM	lpitem, lpitem2;
-    RECT	rect;
-    HMENU	hSubMenu;
-    WORD	wRet;
-    LPPOPUPMENU lppop2;
-    lpitem = MenuFindItem(lppop, x, y, &wRet);
+	HDC		hDC;
+	LPMENUITEM	lpitem, lpitem2;
+	RECT	rect;
+	HMENU	hSubMenu;
+	WORD	wRet;
+	LPPOPUPMENU lppop2;
+	if (lppop == NULL) return;
+	lpitem = MenuFindItem(lppop, x, y, &wRet);
 #ifdef DEBUG_MENU
-    printf("MenuButtonUp // x=%d y=%d // wRet=%d lpitem=%08X !\n", 
-					x, y, wRet, lpitem);
+	printf("MenuButtonUp // x=%d y=%d // wRet=%d lpitem=%08X !\n", 
+											x, y, wRet, lpitem);
 #endif
-    if (lpitem != NULL) {
-	if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
-	    return;
-	    }
-	if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
-	    ((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
-	    ShowWindow(lppop->hWnd, SW_HIDE);
-	    if (lppop->hWndParent != (HWND)NULL) {
-		SendMessage(lppop->hWndParent, WM_COMMAND, 
-				lpitem->item_id, 0L);
-#ifdef DEBUG_MENU
-		printf("MenuButtonUp // WM_COMMAND to ParentMenu wParam=%d !\n", 
-			lpitem->item_id);
-#endif
-		}
-	    else {
-		if (lppop->SysFlag == 0) {
-#ifdef DEBUG_MENU
-		    printf("PopupMenu // WM_COMMAND wParam=%d !\n", 
-				lpitem->item_id);
-#endif
-		    SendMessage(lppop->ownerWnd, WM_COMMAND, 
-					lpitem->item_id, 0L);
-		    }
-		else {
-		    if (lpitem->item_id == SC_ABOUTWINE) {
-			printf("SysMenu // Show 'About Wine ...' !\n");
-/*			DialogBox(hSysRes, MAKEINTRESOURCE(SC_ABOUTWINEDLG), */
-			DialogBox(hSysRes, MAKEINTRESOURCE(2), 
-				GetParent(hWnd), (FARPROC)AboutWine_Proc);
+	if (lpitem != NULL) {
+		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
+			return;
 			}
-		    else {
-			SendMessage(lppop->ownerWnd, WM_SYSCOMMAND,
-					 lpitem->item_id, 0L);
-#ifdef DEBUG_SYSMENU
-			printf("MenuButtonUp // WM_SYSCOMMAND wParam=%04X !\n", 
-					lpitem->item_id);
-#endif
+		if (((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
+			((lpitem->item_flags & MF_POPUP) != MF_POPUP)) {
+			MenuHasFocus = FALSE;
+			if (lppop->BarFlag) {
+				PostMessage(lppop->ownerWnd, WM_COMMAND, lpitem->item_id, 0L);
+				}
+			else {
+				ShowWindow(lppop->hWnd, SW_HIDE);
+				SendMessage(lppop->hWnd, WM_COMMAND, lpitem->item_id, 0L);
+				}
+			return;
 			}
-		    }
 		}
-#ifdef DEBUG_MENU
-	    printf("MenuButtonUp // SendMessage WM_COMMAND wParam=%d !\n", 
-			lpitem->item_id);
-#endif
-	    return;
-	    }
-	}
-    if (lppop->FocusedItem != (WORD)-1) {
-	HideAllSubPopupMenu(lppop); 
-	lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
-	if (((lpitem2->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
-	    ((lpitem2->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
-	    hDC = GetWindowDC(hWnd);
-	    InvertRect(hDC, &lpitem2->rect);
-	    ReleaseDC(hWnd, hDC);
-	    }
-	}
+	if (lppop->FocusedItem != (WORD)-1) {
+		MenuItemSelect(hWnd, lppop, lppop->FocusedItem);
+		}
 }
 
 
 
 void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y)
 {
-    HDC		hDC;
-    LPMENUITEM	lpitem, lpitem2;
-    RECT	rect;
-    HMENU	hSubMenu;
-    WORD	wRet;
-    LPPOPUPMENU lppop2;
-    if ((wParam & MK_LBUTTON) != 0) {
-	lpitem = MenuFindItem(lppop, x, y, &wRet);
+	HDC		hDC;
+	RECT	rect;
+	HMENU	hSubMenu;
+	LPMENUITEM	lpitem, lpitem2;
+	LPPOPUPMENU lppop2;
+	WORD	wRet;
+	if ((wParam & MK_LBUTTON) != 0) {
+		lpitem = MenuFindItem(lppop, x, y, &wRet);
 #ifdef DEBUG_MENU
-	printf("MenuMouseMove // x=%d y=%d // wRet=%d lpitem=%08X !\n", 
-					x, y, wRet, lpitem);
+		printf("MenuMouseMove // x=%d y=%d // wRet=%d lpitem=%08X !\n", 
+												x, y, wRet, lpitem);
 #endif
-	if ((lpitem != NULL) && (lppop->FocusedItem != wRet)) {
-	    lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
-	    hDC = GetWindowDC(hWnd);
-	    if (((lpitem2->item_flags & MF_POPUP) == MF_POPUP) ||
-		((lpitem2->item_flags & MF_STRING) == MF_STRING)) {
-		InvertRect(hDC, &lpitem2->rect);
+		if ((lpitem != NULL) && (lppop->FocusedItem != wRet)) {
+			lpitem2 = GetMenuItemPtr(lppop, lppop->FocusedItem);
+			hDC = GetWindowDC(hWnd);
+			if ((lpitem2->item_flags & MF_POPUP) == MF_POPUP) {
+				HideAllSubPopupMenu(lppop);
+				}
+			MenuItemSelect(hWnd, lppop, wRet);
+			if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
+				hSubMenu = (HMENU)lpitem->item_id;
+				lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
+				if (lppop2 == NULL) {
+					ReleaseDC(hWnd, hDC);
+					return;
+					}
+				if (lppop->BarFlag) {
+					lppop2->hWndParent = hWnd;
+					lppop2->hWndPrev = GetFocus();
+					GetWindowRect(hWnd, &rect);
+					rect.top += lppop->rect.bottom;
+					TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
+						rect.left + lpitem->rect.left, rect.top, 
+						0, lppop->ownerWnd, (LPRECT)NULL);
+					}
+				GlobalUnlock(hSubMenu);
+				}
+			ReleaseDC(hWnd, hDC);
+			}
 		}
-	    if ((lpitem2->item_flags & MF_POPUP) == MF_POPUP) {
-		HideAllSubPopupMenu(lppop);
-		}
-	    lppop->FocusedItem = wRet;
-	    if (((lpitem->item_flags & MF_POPUP) == MF_POPUP) ||
-		((lpitem->item_flags & MF_STRING) == MF_STRING)) {
-		InvertRect(hDC, &lpitem->rect);
-		}
-	    if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
-		hSubMenu = (HMENU)lpitem->item_id;
-		lppop2 = (LPPOPUPMENU) GlobalLock(hSubMenu);
-		if (lppop2 == NULL) {
-		    ReleaseDC(hWnd, hDC);
-		    return;
-		    }
-		if (lppop->BarFlags != 0) {
-		    lppop2->hWndParent = hWnd;
-		    GetWindowRect(hWnd, &rect);
-		    rect.top += lppop->rect.bottom;
-		    TrackPopupMenu(hSubMenu, TPM_LEFTBUTTON, 
-				rect.left + lpitem->rect.left, rect.top, 
-				0, lppop->ownerWnd, (LPRECT)NULL);
-		    }
-		GlobalUnlock(hSubMenu);
-		}
-	    ReleaseDC(hWnd, hDC);
-	    }
-	}
 }
 
 
+void ResetHiliteFlags(LPPOPUPMENU lppop)
+{
+	HDC		hDC;
+	LPMENUITEM lpitem;
+	int		i;
+	if (lppop == NULL) return;
+	lpitem = lppop->firstItem;
+	for(i = 0; i < lppop->nItems; i++) {
+		if (lpitem == NULL) return;
+		lpitem->item_flags &= MF_HILITE ^ 0xFFFF;
+		lpitem = (LPMENUITEM)lpitem->next;
+		}
+}
+
+
+void MenuItemSelect0(HWND hWnd, LPPOPUPMENU lppop, 
+				LPMENUITEM lpitem, WORD wIndex)
+{
+	LPMENUITEM lpprev;
+	if (lppop == NULL) return;
+	if (lppop->FocusedItem != (WORD)-1) {
+	    lpprev = GetMenuItemPtr(lppop, lppop->FocusedItem);
+		if (lpprev != NULL) {
+			lpprev->item_flags &= MF_HILITE ^ 0xFFFF;
+			if ((lpprev->item_flags & MF_POPUP) == MF_POPUP)
+				HideAllSubPopupMenu(lppop);
+			if (lppop->BarFlag)
+				DrawMenuBar(hWnd);
+			else {
+				InvalidateRect(hWnd, &lpprev->rect, TRUE);
+				UpdateWindow(hWnd);
+				}
+			}
+		}
+    lppop->FocusedItem = wIndex;
+	if (lpitem == NULL || wIndex == (WORD)-1) {
+		ResetHiliteFlags(lppop);
+		if (lppop->BarFlag) DrawMenuBar(hWnd);
+		}
+	else {
+		lpitem->item_flags |= MF_HILITE;
+		if (lppop->BarFlag)
+			DrawMenuBar(hWnd);
+		else {
+			InvalidateRect(hWnd, &lpitem->rect, TRUE);
+			UpdateWindow(hWnd);
+			}
+		}
+	SendMessage(hWnd, WM_MENUSELECT, lpitem->item_id, 
+					MAKELONG(0, lpitem->item_flags));
+}
+
+
+void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex)
+{
+	LPMENUITEM lpitem;
+    lpitem = GetMenuItemPtr(lppop, wIndex);
+	MenuItemSelect0(hWnd, lppop, lpitem, wIndex);
+}
+
 
 LPPOPUPMENU PopupMenuGetWindowAndStorage(HWND hwnd, WND **wndPtr)
 {
@@ -543,10 +599,17 @@
     LPPOPUPMENU lppop;
     *(wndPtr) = Ptr = WIN_FindWndPtr(hwnd);
     if (Ptr == 0) {
-    	printf("Bad Window handle on PopupMenu !\n");
-    	return 0;
+    	printf("PopupMenuGetWindowAndStorage // Bad Window handle !\n");
+    	return NULL;
     	}
     lppop = *((LPPOPUPMENU *)&Ptr->wExtra[1]);
+	if (lppop == NULL) {
+		lppop = (LPPOPUPMENU) GlobalLock(Ptr->wIDmenu);
+		if (lppop == NULL) {
+			printf("PopupMenuGetWindowAndStorage // Bad Menu Handle !\n");
+	    	return NULL;
+			}
+		}
     return lppop;
 }
 
@@ -576,397 +639,446 @@
 
 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;
-    DWORD	OldTextColor;
-    HFONT	hOldFont;
-    HBITMAP	hBitMap;
-    BITMAP	bm;
-    UINT  	i, x;
-    hDC = BeginPaint( hwnd, &ps );
-    if (!IsWindowVisible(hwnd)) {
-	EndPaint( hwnd, &ps );
-	return;
-	}
-    lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-    if (lppop == NULL) goto EndOfPaint;
-    hBrush = GetStockObject(WHITE_BRUSH);
-    GetClientRect(hwnd, &rect);
-    GetClientRect(hwnd, &rect2);
-    FillRect(hDC, &rect, hBrush);
-    FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
-    if (lppop->nItems == 0) goto EndOfPaint;
-    lpitem = lppop->firstItem;
-    if (lpitem == NULL) goto EndOfPaint;
-    for(i = 0; i < lppop->nItems; i++) {
+	WND 	*wndPtr;
+	LPPOPUPMENU lppop;
+	LPMENUITEM 	lpitem;
+	PAINTSTRUCT ps;
+	HBRUSH 	hBrush;
+	HPEN	hOldPen;
+	HWND	hWndParent;
+	HDC 	hDC, hMemDC;
+	RECT 	rect, rect2, rect3;
+	DWORD	OldTextColor;
+	int		OldBkMode;
+	HFONT	hOldFont;
+	HBITMAP	hBitMap;
+	BITMAP	bm;
+	UINT  	i, x;
+	hDC = BeginPaint(hwnd, &ps);
+	if (!IsWindowVisible(hwnd)) {
+		EndPaint(hwnd, &ps);
+		return;
+		}
+	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+	if (lppop == NULL) goto EndOfPaint;
+	hBrush = GetStockObject(WHITE_BRUSH);
+	GetClientRect(hwnd, &rect);
+	GetClientRect(hwnd, &rect2);
+	FillRect(hDC, &rect, hBrush);
+	FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
+	if (lppop->nItems == 0) goto EndOfPaint;
+	lpitem = lppop->firstItem;
+	if (lpitem == NULL) goto EndOfPaint;
+	for(i = 0; i < lppop->nItems; i++) {
 	CopyRect(&rect2, &lpitem->rect);
 	if ((lpitem->item_flags & MF_SEPARATOR) == MF_SEPARATOR) {
-    	    hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
-	    MoveTo(hDC, rect2.left, rect2.top + 1);
-	    LineTo(hDC, rect2.right, rect2.top + 1);
-	    SelectObject(hDC, hOldPen);
-	    }
+		hOldPen = SelectObject(hDC, GetStockObject(BLACK_PEN));
+		MoveTo(hDC, rect2.left, rect2.top + 1);
+		LineTo(hDC, rect2.right, rect2.top + 1);
+		SelectObject(hDC, hOldPen);
+		}
 	if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
-	    hMemDC = CreateCompatibleDC(hDC);
-	    if (lpitem->hCheckBit == 0) {
-		SelectObject(hMemDC, hStdCheck);
-		GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
-		}
-	    else {
-		SelectObject(hMemDC, lpitem->hCheckBit);
-		GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
-		}
-	    BitBlt(hDC, rect2.left, rect2.top + 1,
-		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-	    DeleteDC(hMemDC);
-	    }
-	else {
-	    if (lpitem->hUnCheckBit != 0) {
 		hMemDC = CreateCompatibleDC(hDC);
-		SelectObject(hMemDC, lpitem->hUnCheckBit);
-		GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
+		if (lpitem->hCheckBit == 0) {
+			SelectObject(hMemDC, hStdCheck);
+			GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
+			}
+		else {
+			SelectObject(hMemDC, lpitem->hCheckBit);
+			GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
+			}
 		BitBlt(hDC, rect2.left, rect2.top + 1,
-			bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
 		DeleteDC(hMemDC);
 		}
-	    }
+	else {
+		if (lpitem->hUnCheckBit != 0) {
+			hMemDC = CreateCompatibleDC(hDC);
+			SelectObject(hMemDC, lpitem->hUnCheckBit);
+			GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
+			BitBlt(hDC, rect2.left, rect2.top + 1,
+			bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+			DeleteDC(hMemDC);
+			}
+		}
 	if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
-	    hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
-	    rect2.left += lppop->CheckWidth;
-	    hMemDC = CreateCompatibleDC(hDC);
-	    SelectObject(hMemDC, hBitMap);
-	    GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
-	    BitBlt(hDC, rect2.left, rect2.top,
+		hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
+		rect2.left += lppop->CheckWidth;
+		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);
-	    }
+		DeleteDC(hMemDC);
+		if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
+			InvertRect(hDC, &lpitem->rect);
+		}
 	if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
-	    ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
-	    ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
-	    hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
-	    if ((lpitem->item_flags & MF_DISABLED) == MF_DISABLED)
-		OldTextColor = SetTextColor(hDC, 0x00C0C0C0L);
+		((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
+		((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
+		hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
+		OldBkMode = SetBkMode(hDC, TRANSPARENT);
+		if ((lpitem->item_flags & MF_DISABLED) == MF_DISABLED)
+			OldTextColor = SetTextColor(hDC, 0x00C0C0C0L);
+		else {
+			if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
+				OldTextColor = SetTextColor(hDC, 0x00FFFFFFL);
+			else
+				OldTextColor = SetTextColor(hDC, 0x00000000L);
+			}
+		CopyRect(&rect3, &lpitem->rect);
+		if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
+			FillRect(hDC, &rect3, GetStockObject(BLACK_BRUSH));
+		InflateRect(&rect3, 0, -2);
+		rect3.left += lppop->CheckWidth;
+		if ((x = GetShortCutPos(lpitem->item_text)) != (WORD)-1) {
+			DrawText(hDC, lpitem->item_text, x, &rect3, 
+				DT_LEFT | DT_VCENTER | DT_SINGLELINE);
+			DrawText(hDC, &lpitem->item_text[x], -1, &rect3, 
+				DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
+			} 
 	    else
-		OldTextColor = SetTextColor(hDC, 0x00000000L);
-	    CopyRect(&rect3, &lpitem->rect);
-	    InflateRect(&rect3, 0, -2);
-	    rect3.left += lppop->CheckWidth;
-	    if ((x = GetShortCutPos(lpitem->item_text)) != (WORD)-1) {
-		DrawText(hDC, lpitem->item_text, x, &rect3, 
-		    DT_LEFT | DT_VCENTER | DT_SINGLELINE);
-		DrawText(hDC, &lpitem->item_text[x], -1, &rect3, 
-		    DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
-		} 
-	    else
-		DrawText(hDC, lpitem->item_text, -1, &rect3, 
-		    DT_LEFT | DT_VCENTER | DT_SINGLELINE);
-	    SetTextColor(hDC, OldTextColor);
-	    SelectObject(hDC, hOldFont);
-	    CopyRect(&rect2, &lpitem->rect);
-	    }
+			DrawText(hDC, lpitem->item_text, -1, &rect3, 
+				DT_LEFT | DT_VCENTER | DT_SINGLELINE);
+		SetTextColor(hDC, OldTextColor);
+		SetBkMode(hDC, OldBkMode);
+		SelectObject(hDC, hOldFont);
+		CopyRect(&rect2, &lpitem->rect);
+		}
 	if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
-	    CopyRect(&rect3, &lpitem->rect);
-	    rect3.left = rect3.right - lppop->PopWidth;
-	    hMemDC = CreateCompatibleDC(hDC);
-	    SelectObject(hMemDC, hStdMnArrow);
-	    GetObject(hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm);
-	    BitBlt(hDC, rect3.left, rect3.top + 1,
+		CopyRect(&rect3, &lpitem->rect);
+		rect3.left = rect3.right - lppop->PopWidth;
+		hMemDC = CreateCompatibleDC(hDC);
+		SelectObject(hMemDC, hStdMnArrow);
+		GetObject(hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm);
+		BitBlt(hDC, rect3.left, rect3.top + 1,
 		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-	    DeleteDC(hMemDC);
-	    }
+		DeleteDC(hMemDC);
+		}
 	if (lpitem->next == NULL) goto EndOfPaint;
 	lpitem = (LPMENUITEM)lpitem->next;
-    }
+	}
 EndOfPaint:
-    EndPaint( hwnd, &ps );
+	EndPaint( hwnd, &ps );
 }
 
 
 
 void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop)
 {
-    LPMENUITEM 	lpitem;
-    HBRUSH 	hBrush;
-    HPEN	hOldPen;
-    HDC 	hMemDC;
-    RECT 	rect, rect2, rect3;
-    HFONT	hOldFont;
-    DWORD	OldTextColor;
-    HBITMAP	hBitMap;
-    BITMAP	bm;
-    UINT  	i, textwidth;
-    if (lppop == NULL || lprect == NULL) return;
+	LPMENUITEM 	lpitem;
+	HBRUSH 	hBrush;
+	HPEN	hOldPen;
+	HDC 	hMemDC;
+	RECT 	rect, rect2, rect3;
+	HFONT	hOldFont;
+	DWORD	OldTextColor;
+	int		OldBkMode;
+	HBITMAP	hBitMap;
+	BITMAP	bm;
+	UINT  	i, textwidth;
+	if (lppop == NULL || lprect == NULL) return;
 #ifdef DEBUG_MENU
-    printf("StdDrawMenuBar(%04X, %08X, %08X); !\n", hDC, lprect, lppop);
+	printf("StdDrawMenuBar(%04X, %08X, %08X); !\n", hDC, lprect, lppop);
 #endif
-    MenuBarCalcSize(hDC, lprect, lppop);
-    hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
-    hBrush = GetStockObject(WHITE_BRUSH);
-    CopyRect(&rect, lprect);
-    FillRect(hDC, &rect, hBrush);
-    FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
-    if (lppop->nItems == 0) goto EndOfPaint;
-    lpitem = lppop->firstItem;
-    if (lpitem == NULL) goto EndOfPaint;
-    for(i = 0; i < lppop->nItems; i++) {
-	CopyRect(&rect2, &lpitem->rect);
-	if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
-	    hMemDC = CreateCompatibleDC(hDC);
-	    if (lpitem->hCheckBit == 0) {
-		SelectObject(hMemDC, hStdCheck);
-		GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
-		}
-	    else {
-		SelectObject(hMemDC, lpitem->hCheckBit);
-		GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
-		}
-	    BitBlt(hDC, rect2.left, rect2.top + 1,
-		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-	    DeleteDC(hMemDC);
-	    }
-	else {
-	    if (lpitem->hUnCheckBit != 0) {
-		hMemDC = CreateCompatibleDC(hDC);
-		SelectObject(hMemDC, lpitem->hUnCheckBit);
-		GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
-		BitBlt(hDC, rect2.left, rect2.top + 1,
+	MenuBarCalcSize(hDC, lprect, lppop);
+	hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
+	hBrush = GetStockObject(WHITE_BRUSH);
+	CopyRect(&rect, lprect);
+	FillRect(hDC, &rect, hBrush);
+	FrameRect(hDC, &rect, GetStockObject(BLACK_BRUSH));
+	if (lppop->nItems == 0) goto EndOfPaint;
+	lpitem = lppop->firstItem;
+	if (lpitem == NULL) goto EndOfPaint;
+	for(i = 0; i < lppop->nItems; i++) {
+		CopyRect(&rect2, &lpitem->rect);
+		if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
+			hMemDC = CreateCompatibleDC(hDC);
+			if (lpitem->hCheckBit == 0) {
+				SelectObject(hMemDC, hStdCheck);
+				GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
+				}
+			else {
+				SelectObject(hMemDC, lpitem->hCheckBit);
+				GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
+				}
+			BitBlt(hDC, rect2.left, rect2.top + 1,
 			bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-		DeleteDC(hMemDC);
+			DeleteDC(hMemDC);
+			}
+		else {
+			if (lpitem->hUnCheckBit != 0) {
+				hMemDC = CreateCompatibleDC(hDC);
+				SelectObject(hMemDC, lpitem->hUnCheckBit);
+				GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
+				BitBlt(hDC, rect2.left, rect2.top + 1,
+					bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+				DeleteDC(hMemDC);
+				}
+			}
+		if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
+			hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
+			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);
+			}
+		if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
+			((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
+			((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
+			hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
+			OldBkMode = SetBkMode(hDC, TRANSPARENT);
+			if ((lpitem->item_flags & MF_DISABLED) == MF_DISABLED)
+				OldTextColor = SetTextColor(hDC, 0x00C0C0C0L);
+			else {
+				if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
+					OldTextColor = SetTextColor(hDC, 0x00FFFFFFL);
+				else
+					OldTextColor = SetTextColor(hDC, 0x00000000L);
+				}
+			if ((lpitem->item_flags & MF_HILITE) == MF_HILITE)
+				FillRect(hDC, &rect2, GetStockObject(BLACK_BRUSH));
+			DrawText(hDC, lpitem->item_text, -1, &rect2, 
+				DT_LEFT | DT_VCENTER | DT_SINGLELINE);
+			SetTextColor(hDC, OldTextColor);
+			SetBkMode(hDC, OldBkMode);
+			SelectObject(hDC, hOldFont);
+			}
+		if (lpitem->next == NULL) goto EndOfPaint;
+		lpitem = (LPMENUITEM)lpitem->next;
 		}
-	    }
-	if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
-	    hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
-	    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);
-	    }
-	if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
-	    ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
-	    ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
-	    hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
-	    if ((lpitem->item_flags & MF_DISABLED) == MF_DISABLED)
-		OldTextColor = SetTextColor(hDC, 0x00C0C0C0L);
-	    else
-		OldTextColor = SetTextColor(hDC, 0x00000000L);
-	    DrawText(hDC, lpitem->item_text, -1, &rect2, 
-	    	DT_LEFT | DT_VCENTER | DT_SINGLELINE);
-	    SetTextColor(hDC, OldTextColor);
-	    SelectObject(hDC, hOldFont);
-	    }
-	if (lpitem->next == NULL) goto EndOfPaint;
-	lpitem = (LPMENUITEM)lpitem->next;
-    }
 EndOfPaint:
-    SelectObject(hDC, hOldFont);
+	SelectObject(hDC, hOldFont);
 } 
 
 
 
 LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet)
 {
-    LPMENUITEM 	lpitem;
-    UINT  	i;
-    if (lpRet != NULL) *lpRet = 0;
-    if (lppop == NULL) return NULL;
-    if (lppop->nItems == 0) return NULL;
-    lpitem = lppop->firstItem;
-    for(i = 0; i < lppop->nItems; i++) {
-	if (lpitem == NULL) return NULL;
+	LPMENUITEM 	lpitem;
+	UINT  	i;
+	if (lpRet != NULL) *lpRet = 0;
+	if (lppop == NULL) return NULL;
+	if (lppop->nItems == 0) return NULL;
+	lpitem = lppop->firstItem;
+	for(i = 0; i < lppop->nItems; i++) {
+		if (lpitem == NULL) return NULL;
 #ifdef DEBUG_MENUFINDITEM
-	printf("FindItem // left=%d top=%d right=%d bottom=%d\n",
+		printf("FindItem // left=%d top=%d right=%d bottom=%d\n",
 		lpitem->rect.left, lpitem->rect.top, 
 		lpitem->rect.right, lpitem->rect.bottom);
 #endif
-	if (x > lpitem->rect.left && x < lpitem->rect.right && 
-	    y > lpitem->rect.top && y < lpitem->rect.bottom) {
-	    if (lpRet != NULL) *lpRet = i;
-	    return lpitem;
-	    }
-	lpitem = (LPMENUITEM)lpitem->next;
-    }
-    return NULL;
+		if (x > lpitem->rect.left && x < lpitem->rect.right && 
+			y > lpitem->rect.top && y < lpitem->rect.bottom) {
+			if (lpRet != NULL) *lpRet = i;
+			return lpitem;
+			}
+		lpitem = (LPMENUITEM)lpitem->next;
+		}
+	return NULL;
 }
 
 
 LPMENUITEM MenuFindItemBySelKey(LPPOPUPMENU lppop, WORD key, WORD *lpRet)
 {
-    LPMENUITEM 	lpitem;
-    UINT  	i;
-    if (lppop == NULL) return NULL;
-    if (lppop->nItems == 0) return NULL;
-    lpitem = lppop->firstItem;
-    for(i = 0; i < lppop->nItems; i++) {
-	if (lpitem == NULL) return NULL;
+	LPMENUITEM 	lpitem;
+	UINT  	i;
+	if (lppop == NULL) return NULL;
+	if (lppop->nItems == 0) return NULL;
+	lpitem = lppop->firstItem;
+	for(i = 0; i < lppop->nItems; i++) {
+		if (lpitem == NULL) return NULL;
 #ifdef DEBUG_MENUFINDITEM
-	printf("FindItemBySelKey // key=%d lpitem->sel_key=%d\n",
-		key, lpitem->sel_key);
+		printf("FindItemBySelKey // key=%d lpitem->sel_key=%d\n",
+										key, lpitem->sel_key);
 #endif
-	if (key == lpitem->sel_key) {
-	    if (lpRet != NULL) *lpRet = i;
-	    return lpitem;
-	    }
-	lpitem = (LPMENUITEM)lpitem->next;
-    }
-    return NULL;
+		if (key == lpitem->sel_key) {
+			if (lpRet != NULL) *lpRet = i;
+			return lpitem;
+			}
+		lpitem = (LPMENUITEM)lpitem->next;
+		}
+	return NULL;
 }
 
 
 void PopupMenuCalcSize(HWND hwnd)
 {
-    WND 	*wndPtr;
-    LPPOPUPMENU lppop;
-    LPMENUITEM 	lpitem;
-    HDC		hDC;
-    RECT 	rect;
-    HBITMAP	hBitMap;
-    BITMAP	bm;
-    HFONT	hOldFont;
-    UINT  	i, OldWidth, TempWidth;
-    DWORD	dwRet;
+	WND 	*wndPtr;
+	LPPOPUPMENU lppop;
+	LPMENUITEM 	lpitem;
+	HDC		hDC;
+	RECT 	rect;
+	HBITMAP	hBitMap;
+	BITMAP	bm;
+	HFONT	hOldFont;
+	UINT  	i, OldWidth, TempWidth;
+	DWORD	dwRet;
 #ifdef DEBUG_MENUCALC
 	printf("PopupMenuCalcSize hWnd=%04X !\n", hWnd);
 #endif
-    lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
-    if (lppop == NULL) return;
-    if (lppop->nItems == 0) return;
-    hDC = GetDC(hwnd);
-    lppop->Width = 20;
-    lppop->CheckWidth = lppop->PopWidth = 0;
-    hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
+	lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
+	if (lppop == NULL) return;
+	if (lppop->nItems == 0) return;
+	hDC = GetDC(hwnd);
+	lppop->Width = 20;
+	lppop->CheckWidth = lppop->PopWidth = 0;
+	hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
 CalcAGAIN:
-    OldWidth = lppop->Width;
-    SetRect(&rect, 1, 1, OldWidth, 0);
-    lpitem = lppop->firstItem;
-    for(i = 0; i < lppop->nItems; i++) {
-	if (lpitem == NULL) break;
+	OldWidth = lppop->Width;
+	SetRect(&rect, 1, 1, OldWidth, 0);
+	lpitem = lppop->firstItem;
+	for(i = 0; i < lppop->nItems; i++) {
+		if (lpitem == NULL) break;
 #ifdef DEBUG_MENUCALC
-	printf("PopupMenuCalcSize item #%d !\n", i);
+		printf("PopupMenuCalcSize item #%d !\n", i);
 #endif
-	rect.right = rect.left + lppop->Width;
-	if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
-	    if (lpitem->hCheckBit != 0)
-		GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
-	    else
-		GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
-	    lppop->CheckWidth = max(lppop->CheckWidth, bm.bmWidth);
-	    }
-	else {
-	    if (lpitem->hUnCheckBit != 0) {
-		GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
-		lppop->CheckWidth = max(lppop->CheckWidth, bm.bmWidth);
+		rect.right = rect.left + lppop->Width;
+		if ((lpitem->item_flags & MF_CHECKED) == MF_CHECKED) {
+			if (lpitem->hCheckBit != 0)
+				GetObject(lpitem->hCheckBit, sizeof(BITMAP), (LPSTR)&bm);
+			else
+				GetObject(hStdCheck, sizeof(BITMAP), (LPSTR)&bm);
+			lppop->CheckWidth = max(lppop->CheckWidth, bm.bmWidth);
+			}
+		else {
+			if (lpitem->hUnCheckBit != 0) {
+				GetObject(lpitem->hUnCheckBit, sizeof(BITMAP), (LPSTR)&bm);
+				lppop->CheckWidth = max(lppop->CheckWidth, bm.bmWidth);
+				}
+			}
+		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
+			GetObject(hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm);
+			lppop->PopWidth = max(lppop->PopWidth, bm.bmWidth);
+			}
+		if ((lpitem->item_flags & MF_SEPARATOR) == MF_SEPARATOR) {
+			rect.bottom = rect.top + 3;
+			}
+		if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
+			hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
+			GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
+			rect.bottom = rect.top + bm.bmHeight;
+			lppop->Width = max(lppop->Width, bm.bmWidth);
+			}
+		if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
+			((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
+			((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
+			dwRet = GetTextExtent(hDC, (char *)lpitem->item_text, 
+			strlen((char *)lpitem->item_text));
+			rect.bottom = rect.top + HIWORD(dwRet);
+			InflateRect(&rect, 0, 2);
+			TempWidth = LOWORD(dwRet);
+			if (GetShortCutPos(lpitem->item_text) != (WORD)-1) 
+				TempWidth += 15;
+			TempWidth += lppop->CheckWidth;
+			TempWidth += lppop->PopWidth;
+			lppop->Width = max(lppop->Width, TempWidth);
+			}
+		CopyRect(&lpitem->rect, &rect);
+		rect.top = rect.bottom;
+		lpitem = (LPMENUITEM)lpitem->next;
 		}
-	    }
-	if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
-	    GetObject(hStdMnArrow, sizeof(BITMAP), (LPSTR)&bm);
-	    lppop->PopWidth = max(lppop->PopWidth, bm.bmWidth);
-	    }
-	if ((lpitem->item_flags & MF_SEPARATOR) == MF_SEPARATOR) {
-	    rect.bottom = rect.top + 3;
-	    }
-	if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
-	    hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
-	    GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
-	    rect.bottom = rect.top + bm.bmHeight;
-	    lppop->Width = max(lppop->Width, bm.bmWidth);
-	    }
-	if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
-	    ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
-	    ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
-	    dwRet = GetTextExtent(hDC, (char *)lpitem->item_text, 
-		strlen((char *)lpitem->item_text));
-	    rect.bottom = rect.top + HIWORD(dwRet);
-	    InflateRect(&rect, 0, 2);
-	    TempWidth = LOWORD(dwRet);
-	    if (GetShortCutPos(lpitem->item_text) != (WORD)-1)
-	        TempWidth += 15;
-	    TempWidth += lppop->CheckWidth;
-	    TempWidth += lppop->PopWidth;
-	    lppop->Width = max(lppop->Width, TempWidth);
-	    }
-	CopyRect(&lpitem->rect, &rect);
-	rect.top = rect.bottom;
-	lpitem = (LPMENUITEM)lpitem->next;
-	}
-    if (OldWidth < lppop->Width) goto CalcAGAIN;
-    lppop->Height = rect.bottom;
-    SetRect(&lppop->rect, 1, 1, lppop->Width, lppop->Height);
+	if (OldWidth < lppop->Width) goto CalcAGAIN;
+	lppop->Height = rect.bottom;
+	SetRect(&lppop->rect, 1, 1, lppop->Width, lppop->Height);
 #ifdef DEBUG_MENUCALC
-    printf("PopupMenuCalcSize w=%d h=%d !\n", lppop->Width, lppop->Height);
+	printf("PopupMenuCalcSize w=%d h=%d !\n", lppop->Width, lppop->Height);
 #endif
-    SelectObject(hDC, hOldFont);
-    ReleaseDC(hwnd, hDC);
+	SelectObject(hDC, hOldFont);
+	ReleaseDC(hwnd, hDC);
 }
 
 
 
 void MenuBarCalcSize(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop)
 {
-    LPMENUITEM 	lpitem;
-    RECT 	rect;
-    HBITMAP	hBitMap;
-    BITMAP	bm;
-    HFONT	hOldFont;
-    UINT  	i, OldHeight;
-    DWORD	dwRet;
-    if (lppop == NULL) return;
-    if (lppop->nItems == 0) return;
+	LPMENUITEM 	lpitem;
+	RECT 	rect;
+	HBITMAP	hBitMap;
+	BITMAP	bm;
+	HFONT	hOldFont;
+	UINT  	i, OldHeight;
+	DWORD	dwRet;
+	if (lppop == NULL) return;
+	if (lppop->nItems == 0) return;
 #ifdef DEBUG_MENUCALC
-    printf("MenuBarCalcSize left=%d top=%d right=%d bottom=%d !\n", 
-    	lprect->left, lprect->top, lprect->right, lprect->bottom);
+	printf("MenuBarCalcSize left=%d top=%d right=%d bottom=%d !\n", 
+		lprect->left, lprect->top, lprect->right, lprect->bottom);
 #endif
-    hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
-    lppop->Height = lprect->bottom - lprect->top;
+	hOldFont = SelectObject(hDC, GetStockObject(SYSTEM_FONT));
+	lppop->Height = lprect->bottom - lprect->top;
 CalcAGAIN:
-    OldHeight = lppop->Height;
-    SetRect(&rect, lprect->left, lprect->top, 0, lprect->top + OldHeight);
-    lpitem = lppop->firstItem;
-    for(i = 0; i < lppop->nItems; i++) {
-	if (lpitem == NULL) break;
-	rect.bottom = lprect->top + lppop->Height;
-	if (rect.right > lprect->right) 
-	    SetRect(&rect, lprect->left, rect.bottom, 
-		0, rect.bottom + SYSMETRICS_CYMENU);
-	if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
-	    hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
-	    GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
-	    rect.right = rect.left + bm.bmWidth;
-	    lppop->Height = max(lppop->Height, bm.bmHeight);
-	    }
-	if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
-	    ((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
-	    ((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
-	    dwRet = GetTextExtent(hDC, (char *)lpitem->item_text, 
-		strlen((char *)lpitem->item_text));
-	    rect.right = rect.left + LOWORD(dwRet) + 10;
-	    lppop->Height = max(lppop->Height, HIWORD(dwRet) + 10);
-	    }
-	CopyRect(&lpitem->rect, &rect);
-	rect.left = rect.right;
-	lpitem = (LPMENUITEM)lpitem->next;
-	}
-    if (OldHeight < lppop->Height) goto CalcAGAIN;
-    lppop->Width = rect.right;
-    lprect->bottom =  lprect->top + lppop->Height;
-    CopyRect(&lppop->rect, lprect);
+	OldHeight = lppop->Height;
+	SetRect(&rect, lprect->left, lprect->top, 0, lprect->top + OldHeight);
+	lpitem = lppop->firstItem;
+	for(i = 0; i < lppop->nItems; i++) {
+		if (lpitem == NULL) break;
+		rect.bottom = lprect->top + lppop->Height;
+		if (rect.right > lprect->right) 
+			SetRect(&rect, lprect->left, rect.bottom, 
+				0, rect.bottom + SYSMETRICS_CYMENU);
+		if ((lpitem->item_flags & MF_BITMAP) == MF_BITMAP) {
+			hBitMap = (HBITMAP)LOWORD((LONG)lpitem->item_text);
+			GetObject(hBitMap, sizeof(BITMAP), (LPSTR)&bm);
+			rect.right = rect.left + bm.bmWidth;
+			lppop->Height = max(lppop->Height, bm.bmHeight);
+			}
+		if (((lpitem->item_flags & MF_BITMAP) != MF_BITMAP) &&
+			((lpitem->item_flags & MF_SEPARATOR) != MF_SEPARATOR) &&
+			((lpitem->item_flags & MF_MENUBREAK) != MF_MENUBREAK)) {
+			dwRet = GetTextExtent(hDC, (char *)lpitem->item_text, 
+			strlen((char *)lpitem->item_text));
+			rect.right = rect.left + LOWORD(dwRet) + 10;
+			dwRet = max(SYSMETRICS_CYMENU, (HIWORD(dwRet) + 6));
+			lppop->Height = max(lppop->Height, (WORD)dwRet);
+			}
+		CopyRect(&lpitem->rect, &rect);
+		rect.left = rect.right;
+		lpitem = (LPMENUITEM)lpitem->next;
+		}
+	if (OldHeight < lppop->Height) goto CalcAGAIN;
+	lppop->Width = rect.right;
+	lprect->bottom =  lprect->top + lppop->Height;
+	CopyRect(&lppop->rect, lprect);
 #ifdef DEBUG_MENUCALC
-    printf("MenuBarCalcSize w=%d h=%d !\n", 
-    	lppop->Width, lppop->Height);
+	printf("MenuBarCalcSize w=%d h=%d !\n", lppop->Width, lppop->Height);
 #endif
-    SelectObject(hDC, hOldFont);
+	SelectObject(hDC, hOldFont);
 }
 
 
 
+/***********************************************************************
+ *           FindMenuItem
+ */
+LPMENUITEM FindMenuItem(HMENU hMenu, WORD nPos, WORD wFlags)
+{
+	LPPOPUPMENU	menu;
+	LPMENUITEM 	lpitem;
+	int		i;
+	menu = (LPPOPUPMENU) GlobalLock(hMenu);
+	if (menu == NULL) {
+		GlobalUnlock(hMenu);
+		return FALSE;
+		}
+	lpitem = menu->firstItem;
+	if (wFlags & MF_BYPOSITION) {
+		for (i = 0; i < nPos; i++, lpitem = lpitem->next) 
+			if (lpitem == NULL)	return NULL;
+		}
+	else {
+		for (i = 0; i < menu->nItems && lpitem != NULL; i++) {
+			if (lpitem->item_id == nPos) return lpitem;
+			lpitem = lpitem->next;
+			}
+		return NULL;
+		}
+    return lpitem;
+}
+
+
 LPMENUITEM GetMenuItemPtr(LPPOPUPMENU menu, WORD nPos)
 {
     LPMENUITEM 	lpitem;
@@ -984,92 +1096,89 @@
 
 WORD GetSelectionKey(LPSTR str)
 {
-    int		i;
-    WORD	sel_key;
-    for (i = 0; i < strlen(str); i++) {
-	if (str[i] == '&' && str[i + 1] != '&') 
-	    {
-	    sel_key = str[i + 1];
-	    if (sel_key >= 'a' && sel_key <= 'z') sel_key -= 'a' - 'A';
+	int		i;
+	WORD	sel_key;
+	for (i = 0; i < strlen(str); i++) {
+		if (str[i] == '&' && str[i + 1] != '&') {
+			sel_key = str[i + 1];
+			if (sel_key >= 'a' && sel_key <= 'z') sel_key -= 'a' - 'A';
 #ifdef DEBUG_MENU
-	    printf("GetSelectionKey // %04X\n", sel_key);
+			printf("GetSelectionKey // %04X\n", sel_key);
 #endif
-	    return sel_key;
-	    }
-	}
+			return sel_key;
+			}
+		}
 #ifdef DEBUG_MENU
-    printf("GetSelectionKey NULL \n");
+	printf("GetSelectionKey NULL \n");
 #endif
-    return 0;
+	return 0;
 }
 
 
 
 LPSTR GetShortCutString(LPSTR str)
 {
-    int		i;
-    LPSTR	str2;
-    for (i = 0; i < strlen(str); i++) {
-	if (str[i] == '\t' && str[i + 1] != '\t') 
-	    {
-	    str2 = &str[i + 1];
+	int		i;
+	LPSTR	str2;
+	for (i = 0; i < strlen(str); i++) {
+		if (str[i] == '\t' && str[i + 1] != '\t') {
+			str2 = &str[i + 1];
 #ifdef DEBUG_MENUSHORTCUT
-	    printf("GetShortCutString // '%s' \n", str2);
+			printf("GetShortCutString // '%s' \n", str2);
 #endif
-	    return str2;
-	    }
-	}
+			return str2;
+			}
+		}
 #ifdef DEBUG_MENUSHORTCUT
-    printf("GetShortCutString NULL \n");
+	printf("GetShortCutString NULL \n");
 #endif
-    return NULL;
+	return NULL;
 }
 
 
 
 WORD GetShortCutPos(LPSTR str)
 {
-    int		i;
-    for (i = 0; i < strlen(str); i++) {
-	if (str[i] == '\t' && str[i + 1] != '\t') 
-	    {
+	int		i;
+	for (i = 0; i < strlen(str); i++) {
+		if (str[i] == '\t' && str[i + 1] != '\t') {
 #ifdef DEBUG_MENUSHORTCUT
-	    printf("GetShortCutPos = %d \n", i);
+			printf("GetShortCutPos = %d \n", i);
 #endif
-	    return i;
-	    }
-	}
+			return i;
+			}
+		}
 #ifdef DEBUG_MENUSHORTCUT
-    printf("GetShortCutString NULL \n");
+	printf("GetShortCutString NULL \n");
 #endif
-    return -1;
+	return -1;
 }
 
 
 
 BOOL HideAllSubPopupMenu(LPPOPUPMENU menu)
 {
-    LPPOPUPMENU submenu;
-    LPMENUITEM 	lpitem;
-    BOOL	someClosed = FALSE;
-    int		i;
-    if (menu == NULL) return;
-    lpitem = menu->firstItem;
-    for (i = 0; i < menu->nItems; i++) {
-    	if (lpitem == NULL) return;
-    	if (lpitem->item_flags & MF_POPUP) {
-	    submenu = (LPPOPUPMENU) GlobalLock((HMENU)lpitem->item_id);
-	    if (submenu != NULL) {
-		if (IsWindowVisible(submenu->hWnd)) {
-		    ShowWindow(submenu->hWnd, SW_HIDE);
-		    someClosed = TRUE;
-		    }
-		GlobalUnlock((HMENU)lpitem->item_id);
-	    	}
-    	    }
-    	lpitem = (LPMENUITEM)lpitem->next;
-    	}
-    return someClosed;
+	LPPOPUPMENU submenu;
+	LPMENUITEM 	lpitem;
+	BOOL	someClosed = FALSE;
+	int		i;
+	if (menu == NULL) return;
+	lpitem = menu->firstItem;
+	for (i = 0; i < menu->nItems; i++) {
+		if (lpitem == NULL) return;
+		if (lpitem->item_flags & MF_POPUP) {
+			submenu = (LPPOPUPMENU) GlobalLock((HMENU)lpitem->item_id);
+			if (submenu != NULL) {
+				if (IsWindowVisible(submenu->hWnd)) {
+					ShowWindow(submenu->hWnd, SW_HIDE);
+					someClosed = TRUE;
+					}
+				GlobalUnlock((HMENU)lpitem->item_id);
+		    	}
+	   	    }
+	   	lpitem = (LPMENUITEM)lpitem->next;
+	   	}
+	return someClosed;
 }
 
 
@@ -1081,22 +1190,17 @@
 BOOL ChangeMenu(HMENU hMenu, WORD nPos, LPSTR lpNewItem, 
 			WORD wItemID, WORD wFlags)
 {
-    if (wFlags & MF_APPEND) {
-    	return AppendMenu(hMenu, wFlags, wItemID, lpNewItem);
-	}
-    if (wFlags & MF_DELETE) {
-    	return DeleteMenu(hMenu, wItemID, wFlags);
-	}
-    if (wFlags & MF_INSERT) {
-    	return InsertMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
-	}
-    if (wFlags & MF_CHANGE) {
-    	return ModifyMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
-	}
-    if (wFlags & MF_REMOVE) {
-    	return RemoveMenu(hMenu, wItemID, wFlags);
-	}
-    return FALSE;
+	if (wFlags & MF_APPEND)
+		return AppendMenu(hMenu, wFlags, wItemID, lpNewItem);
+	if (wFlags & MF_DELETE)
+		return DeleteMenu(hMenu, wItemID, wFlags);
+	if (wFlags & MF_INSERT) 
+		return InsertMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
+	if (wFlags & MF_CHANGE) 
+		return ModifyMenu(hMenu, nPos, wFlags, wItemID, lpNewItem);
+	if (wFlags & MF_REMOVE) 
+		return RemoveMenu(hMenu, wItemID, wFlags);
+	return FALSE;
 }
 
 
@@ -1105,30 +1209,30 @@
  */
 BOOL CheckMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags)
 {
-    WND		*wndPtr;
-    LPPOPUPMENU	menu;
-    LPMENUITEM 	lpitem;
-    int		i;
+	WND		*wndPtr;
+	LPPOPUPMENU	menu;
+	LPMENUITEM 	lpitem;
+	int		i;
 #ifdef DEBUG_MENU
-    printf("CheckMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags);
+	printf("CheckMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags);
 #endif
-    menu = (LPPOPUPMENU) GlobalLock(hMenu);
-    if (menu == NULL) return FALSE;
-    lpitem = menu->firstItem;
-    for (i = 0; i < menu->nItems; i++) {
-    	if (lpitem == NULL) break;
-    	if (i == wItemID) {
-	    if (wFlags && MF_CHECKED)
-		lpitem->item_flags |= MF_CHECKED;
-	    else
-		lpitem->item_flags &= ((WORD)-1 ^ MF_CHECKED);
-	    GlobalUnlock(hMenu);
-	    return(TRUE);
-	    }
-    	lpitem = (LPMENUITEM)lpitem->next;
-    	}
-    GlobalUnlock(hMenu);
-    return FALSE;
+	menu = (LPPOPUPMENU) GlobalLock(hMenu);
+	if (menu == NULL) return FALSE;
+	lpitem = menu->firstItem;
+	for (i = 0; i < menu->nItems; i++) {
+		if (lpitem == NULL) break;
+		if (i == wItemID) {
+			if (wFlags && MF_CHECKED)
+				lpitem->item_flags |= MF_CHECKED;
+			else
+				lpitem->item_flags &= ((WORD)-1 ^ MF_CHECKED);
+			GlobalUnlock(hMenu);
+			return(TRUE);
+			}
+		lpitem = (LPMENUITEM)lpitem->next;
+		}
+	GlobalUnlock(hMenu);
+	return FALSE;
 }
 
 
@@ -1137,30 +1241,30 @@
  */
 BOOL EnableMenuItem(HMENU hMenu, WORD wItemID, WORD wFlags)
 {
-    WND		*wndPtr;
-    LPPOPUPMENU	menu;
-    LPMENUITEM 	lpitem;
-    int		i;
+	WND		*wndPtr;
+	LPPOPUPMENU	menu;
+	LPMENUITEM 	lpitem;
+	int		i;
 #ifdef DEBUG_MENU
-    printf("EnableMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags);
+	printf("EnableMenuItem (%04X, %04X, %04X) !\n", hMenu, wItemID, wFlags);
 #endif
-    menu = (LPPOPUPMENU) GlobalLock(hMenu);
-    if (menu == NULL) return FALSE;
-    lpitem = menu->firstItem;
-    for (i = 0; i < menu->nItems; i++) {
-    	if (lpitem == NULL) break;
-    	if (i == wItemID) {
-	    if (wFlags && MF_DISABLED)
-		lpitem->item_flags |= MF_DISABLED;
-	    else
-		lpitem->item_flags &= ((WORD)-1 ^ MF_DISABLED);
-	    GlobalUnlock(hMenu);
-	    return(TRUE);
-	    }
-    	lpitem = (LPMENUITEM)lpitem->next;
-    	}
-    GlobalUnlock(hMenu);
-    return FALSE;
+	menu = (LPPOPUPMENU) GlobalLock(hMenu);
+	if (menu == NULL) return FALSE;
+	lpitem = menu->firstItem;
+	for (i = 0; i < menu->nItems; i++) {
+		if (lpitem == NULL) break;
+		if (i == wItemID) {
+			if (wFlags && MF_DISABLED)
+				lpitem->item_flags |= MF_DISABLED;
+			else
+				lpitem->item_flags &= ((WORD)-1 ^ MF_DISABLED);
+			GlobalUnlock(hMenu);
+			return(TRUE);
+			}
+		lpitem = (LPMENUITEM)lpitem->next;
+		}
+	GlobalUnlock(hMenu);
+	return FALSE;
 }
 
 
@@ -1169,61 +1273,56 @@
  */
 BOOL InsertMenu(HMENU hMenu, WORD nPos, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
 {
-    WND		*wndPtr;
-    LPPOPUPMENU	menu;
-    HANDLE	hNewItem;
-    LPMENUITEM 	lpitem, lpitem2;
-    int		i;
+	WND		*wndPtr;
+	LPPOPUPMENU	menu;
+	HANDLE	hNewItem;
+	LPMENUITEM 	lpitem, lpitem2;
+	int		i;
 #ifdef DEBUG_MENU
-    if (wFlags & MF_STRING) 
-	printf("InsertMenu (%04X, %04X, %04X, '%s') !\n",
-		hMenu, wFlags, wItemID, lpNewItem);
-    else
-	printf("InsertMenu (%04X, %04X, %04X, %04X, %08X) !\n",
-		hMenu, nPos, wFlags, wItemID, lpNewItem);
+	if (wFlags & MF_STRING) 
+		printf("InsertMenu (%04X, %04X, %04X, '%s') !\n",
+					hMenu, wFlags, wItemID, lpNewItem);
+	else
+		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 == NULL) break;
-    	if (i == nPos) 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) {
+	menu = (LPPOPUPMENU) GlobalLock(hMenu);
+	if (menu == NULL) return FALSE;
+	lpitem = FindMenuItem(hMenu, nPos, wFlags);
+	hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
+	if (hNewItem == 0) {
+		GlobalUnlock(hMenu);
+		return FALSE;
+		}
+	lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
+	if (lpitem2 == NULL) {
+		GlobalFree(hNewItem);
+		GlobalUnlock(hMenu);
+		return FALSE;
+		}
+	lpitem2->item_flags = wFlags;
+	lpitem2->item_id = wItemID;
+	if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | 
+			MF_MENUBREAK | MF_SEPARATOR))) {
+	        lpitem2->item_text = GlobalQuickAlloc(strlen(lpNewItem) + 1);
+		strcpy(lpitem2->item_text, lpNewItem);
+		lpitem2->sel_key = GetSelectionKey(lpitem2->item_text);
+		}
+	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;
+	menu->nItems++;
 	GlobalUnlock(hMenu);
-    	return FALSE;
-    	}
-    lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
-    if (lpitem2 == NULL) {
-	GlobalFree(hNewItem);
-	GlobalUnlock(hMenu);
-	return FALSE;
-	}
-    lpitem2->item_flags = wFlags;
-    lpitem2->item_id = wItemID;
-    if (((wFlags & MF_BITMAP) != MF_BITMAP) &&
-	((wFlags & MF_MENUBREAK) != MF_MENUBREAK) &&
-	((wFlags & MF_STRING) != MF_SEPARATOR)) {
-	lpitem2->item_text = lpNewItem;
-	lpitem2->sel_key = GetSelectionKey(lpitem2->item_text);
-	}
-    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;
-    menu->nItems++;
-    GlobalUnlock(hMenu);
-    return TRUE;
+	return TRUE;
 }
 
 
@@ -1232,61 +1331,62 @@
  */
 BOOL AppendMenu(HMENU hMenu, WORD wFlags, WORD wItemID, LPSTR lpNewItem)
 {
-    WND		*wndPtr;
-    LPPOPUPMENU	menu;
-    HANDLE	hNewItem;
-    LPMENUITEM 	lpitem, lpitem2;
+	WND		*wndPtr;
+	LPPOPUPMENU	menu;
+	HANDLE	hNewItem;
+	LPMENUITEM 	lpitem, lpitem2;
 #ifdef DEBUG_MENU
-    if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0)
-	printf("AppendMenu (%04X, %04X, %04X, '%s') !\n",
-		hMenu, wFlags, wItemID, lpNewItem);
-    else
-	printf("AppendMenu (%04X, %04X, %04X, %08X) !\n",
-		hMenu, wFlags, wItemID, lpNewItem);
+	if ((wFlags & (MF_BITMAP | MF_SEPARATOR | MF_MENUBREAK | MF_OWNERDRAW)) == 0)
+		printf("AppendMenu (%04X, %04X, %04X, '%s') !\n",
+			hMenu, wFlags, wItemID, lpNewItem);
+	else
+		printf("AppendMenu (%04X, %04X, %04X, %08X) !\n",
+			hMenu, wFlags, wItemID, lpNewItem);
 #endif
-    menu = (LPPOPUPMENU) GlobalLock(hMenu);
-    if (menu == NULL) return FALSE;
-    lpitem = menu->firstItem;
-    if (lpitem != NULL) {
-	while (lpitem->next != NULL) {
-	    lpitem = (LPMENUITEM)lpitem->next;
-	    }
-	}
-    hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
-    if (hNewItem == 0) {
+	menu = (LPPOPUPMENU) GlobalLock(hMenu);
+	if (menu == NULL) return FALSE;
+	lpitem = menu->firstItem;
+	if (lpitem != NULL) {
+		while (lpitem->next != NULL) {
+			lpitem = (LPMENUITEM)lpitem->next;
+			}
+		}
+	hNewItem = GlobalAlloc(GMEM_MOVEABLE, sizeof(MENUITEM));
+	if (hNewItem == 0) {
+		GlobalUnlock(hMenu);
+		return FALSE;
+		}
+	lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
+	if (lpitem2 == NULL) {
+		GlobalFree(hNewItem);
+		GlobalUnlock(hMenu);
+		return FALSE;
+		}
+	lpitem2->item_flags = wFlags;
+	lpitem2->item_id = wItemID;
+	if (!(wFlags & (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | 
+			MF_MENUBREAK | MF_SEPARATOR))) {
+	        lpitem2->item_text = GlobalQuickAlloc(strlen(lpNewItem) + 1);
+		strcpy(lpitem2->item_text, lpNewItem);
+		lpitem2->sel_key = GetSelectionKey(lpitem2->item_text);
+		}
+	else {
+	        lpitem2->item_text = lpNewItem;
+                }
+	
+	if (lpitem == NULL)
+		menu->firstItem = lpitem2;
+	else
+		lpitem->next = lpitem2;
+	lpitem2->prev = lpitem;
+	lpitem2->next = NULL;
+	lpitem2->child = NULL;
+	lpitem2->parent = NULL;
+	lpitem2->hCheckBit = (HBITMAP)NULL;
+	lpitem2->hUnCheckBit = (HBITMAP)NULL;
+	menu->nItems++;
 	GlobalUnlock(hMenu);
-	return FALSE;
-	}
-    lpitem2 = (LPMENUITEM)GlobalLock(hNewItem);
-    if (lpitem2 == NULL) {
-	GlobalFree(hNewItem);
-	GlobalUnlock(hMenu);
-	return FALSE;
-	}
-    lpitem2->item_flags = wFlags;
-    lpitem2->item_id = wItemID;
-    if (((wFlags & MF_BITMAP) != MF_BITMAP) &&
-	((wFlags & MF_MENUBREAK) != MF_MENUBREAK) &&
-	((wFlags & MF_STRING) != MF_SEPARATOR)) {
-	lpitem2->item_text = lpNewItem;
-	lpitem2->sel_key = GetSelectionKey(lpitem2->item_text);
-	lpitem2->shortcut = GetShortCutString(lpitem2->item_text);
-	}
-    else
-	lpitem2->item_text = lpNewItem;
-    if (lpitem == NULL)
-    	menu->firstItem = lpitem2;
-    else
-    	lpitem->next = lpitem2;
-    lpitem2->prev = lpitem;
-    lpitem2->next = NULL;
-    lpitem2->child = NULL;
-    lpitem2->parent = NULL;
-    lpitem2->hCheckBit = (HBITMAP)NULL;
-    lpitem2->hUnCheckBit = (HBITMAP)NULL;
-    menu->nItems++;
-    GlobalUnlock(hMenu);
-    return TRUE;
+	return TRUE;
 }
 
 
@@ -1295,31 +1395,36 @@
  */
 BOOL RemoveMenu(HMENU hMenu, WORD nPos, WORD wFlags)
 {
-    WND		*wndPtr;
-    LPPOPUPMENU	menu;
-    LPMENUITEM 	lpitem;
-    int		i;
+	WND		*wndPtr;
+	LPPOPUPMENU	menu;
+	LPMENUITEM 	lpitem;
+	int		i;
 #ifdef DEBUG_MENU
-    printf("RemoveMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags);
+	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 == NULL) break;
-    	if (i == nPos) {
-    	    lpitem->prev->next = lpitem->next;
-    	    lpitem->next->prev = lpitem->prev;
-    	    GlobalFree(HIWORD(lpitem));
-	    GlobalUnlock(hMenu);
-    	    return(TRUE);
-	    }
-    	lpitem = (LPMENUITEM)lpitem->next;
-	printf("RemoveMenu // during loop items !\n");
-    	}
-    printf("RemoveMenu // after loop items !\n");
-    GlobalUnlock(hMenu);
-    return FALSE;
+	menu = (LPPOPUPMENU) GlobalLock(hMenu);
+	if (menu == NULL) return FALSE;
+	lpitem = menu->firstItem;
+	for (i = 0; i < menu->nItems; i++) {
+		if (lpitem == NULL) break;
+		if (i == nPos) {
+			lpitem->prev->next = lpitem->next;
+			lpitem->next->prev = lpitem->prev;
+			if (!(lpitem->item_flags & 
+			      (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | 
+			       MF_MENUBREAK | MF_SEPARATOR))) {
+			        GlobalFree(lpitem->item_text);
+			        }
+			GlobalFree(lpitem);
+			GlobalUnlock(hMenu);
+			return TRUE;
+			}
+		lpitem = (LPMENUITEM)lpitem->next;
+		printf("RemoveMenu // during loop items !\n");
+		}
+	printf("RemoveMenu // after loop items !\n");
+	GlobalUnlock(hMenu);
+	return FALSE;
 }
 
 
@@ -1328,10 +1433,42 @@
  */
 BOOL DeleteMenu(HMENU hMenu, WORD nPos, WORD wFlags)
 {
+    LPPOPUPMENU	menu;
+    LPMENUITEM 	lpitem;
+    int		i;
 #ifdef DEBUG_MENU
     printf("DeleteMenu (%04X, %04X, %04X) !\n", hMenu, nPos, wFlags);
 #endif
-    return TRUE;
+    menu = (LPPOPUPMENU) GlobalLock(hMenu);
+    if (menu == NULL) 
+    {
+	GlobalUnlock(hMenu);
+	return FALSE;
+    }
+	
+    lpitem = FindMenuItem(hMenu, nPos, wFlags);
+    if (lpitem != NULL)
+    {
+	if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) 
+	    DestroyMenu((HMENU)lpitem->item_id);
+
+	if (!(lpitem->item_flags & 
+	      (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | 
+	       MF_MENUBREAK | MF_SEPARATOR))) 
+	{
+	    GlobalFree(lpitem->item_text);
+	}
+	if (lpitem->prev)
+	    lpitem->prev->next = lpitem->next;
+	if (lpitem->next)
+	    lpitem->next->prev = lpitem->prev;
+	GlobalFree(lpitem);
+	GlobalUnlock(hMenu);
+	return TRUE;
+    }
+
+    GlobalUnlock(hMenu);
+    return FALSE;
 }
 
 
@@ -1356,7 +1493,16 @@
     	if (i == nPos) {
     	    lpitem->item_flags = wFlags;
     	    lpitem->item_id    = wItemID;
-    	    lpitem->item_text  = lpNewItem;
+	    if (!(lpitem->item_flags & 
+		  (MF_BITMAP | MF_OWNERDRAW | MF_MENUBARBREAK | 
+		   MF_MENUBREAK | MF_SEPARATOR))) {
+		    lpitem->item_text = GlobalReAlloc(lpitem->item_text,
+						      strlen(lpNewItem) + 1,
+						      GLOBAL_FLAGS_MOVEABLE);
+		    strcpy(lpitem->item_text, lpNewItem);
+		    }
+	    else
+		    lpitem->item_text = lpNewItem;
 	    GlobalUnlock(hMenu);
     	    return(TRUE);
 	    }
@@ -1372,30 +1518,32 @@
  */
 HMENU CreatePopupMenu()
 {
-    HANDLE	hItem;
-    HMENU	hMenu;
-    LPPOPUPMENU menu;
+	HANDLE	hItem;
+	HMENU	hMenu;
+	LPPOPUPMENU menu;
 #ifdef DEBUG_MENU
-    printf("CreatePopupMenu !\n");
+	printf("CreatePopupMenu !\n");
 #endif
-    hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
-    menu = (LPPOPUPMENU) GlobalLock(hMenu);
-    if (menu == NULL) {
-	GlobalFree(hMenu);
-	return 0;
- 	}
-    menu->nItems 	  = 0;
-    menu->firstItem       = NULL;
-    menu->ownerWnd	  = 0;
-    menu->hWnd		  = 0;
-    menu->hWndParent	  = 0;
-    menu->MouseFlags	  = 0;
-    menu->BarFlags	  = 0;
-    menu->SysFlag	  = FALSE;
-    menu->Width = 100;
-    menu->Height = 0;
-    GlobalUnlock(hMenu);
-    return hMenu;
+	hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
+	menu = (LPPOPUPMENU) GlobalLock(hMenu);
+	if (menu == NULL) {
+		GlobalFree(hMenu);
+		return 0;
+		}
+	menu->nItems 		= 0;
+	menu->firstItem 	= NULL;
+	menu->ownerWnd		= 0;
+	menu->hWndPrev		= 0;
+	menu->hWnd			= 0;
+	menu->hWndParent	= 0;
+	menu->MouseFlags	= 0;
+	menu->BarFlag		= FALSE;
+	menu->SysFlag		= FALSE;
+	menu->ChildFlag		= TRUE;
+	menu->Width 		= 100;
+	menu->Height 		= 0;
+	GlobalUnlock(hMenu);
+	return hMenu;
 }
 
 
@@ -1405,36 +1553,112 @@
 BOOL TrackPopupMenu(HMENU hMenu, WORD wFlags, short x, short y,
 	short nReserved, HWND hWnd, LPRECT lpRect)
 {
-    WND		*wndPtr;
-    LPPOPUPMENU	lppop;
-    RECT	rect;
+	WND		*wndPtr;
+	LPPOPUPMENU	lppop;
+	RECT	rect;
 #ifdef DEBUG_MENU
-    printf("TrackPopupMenu (%04X, %04X, %d, %d, %04X, %04X, %08X) !\n",
-	hMenu, wFlags, x, y, nReserved, hWnd, lpRect);
+	printf("TrackPopupMenu (%04X, %04X, %d, %d, %04X, %04X, %08X) !\n",
+		hMenu, wFlags, x, y, nReserved, hWnd, lpRect);
 #endif
-    lppop = (LPPOPUPMENU) GlobalLock(hMenu);
-    if (lppop == NULL) return FALSE;
+	lppop = (LPPOPUPMENU) GlobalLock(hMenu);
+	if (lppop == NULL) return FALSE;
+	wndPtr = WIN_FindWndPtr(hWnd);
+	lppop->ownerWnd = hWnd;
+	if (lppop->hWnd == (HWND)NULL) {
+		lppop->hWnd = CreateWindow("POPUPMENU", "", WS_POPUP | WS_VISIBLE,
+			x, y, lppop->Width, lppop->Height, (HWND)NULL, 0, 
+			wndPtr->hInstance, (LPSTR)lppop);
+		}
+	else {
+		ShowWindow(lppop->hWnd, SW_SHOW);
+		}
+	if (!lppop->BarFlag) {
+		PopupMenuCalcSize(lppop->hWnd);
+#ifdef DEBUG_MENU
+		printf("TrackPopupMenu // x=%d y=%d Width=%d Height=%d\n", 
+			x, y, lppop->Width, lppop->Height); 
+#endif
+		SetWindowPos(lppop->hWnd, 0, x, y, lppop->Width + 2, lppop->Height, 
+			SWP_NOZORDER);
+		}
+	if (!MenuHasFocus) {
+#ifdef DEBUG_MENU
+		printf("TrackPopupMenu // before MenuFocusLoop !\n");
+#endif
+		MenuFocusLoop(hWnd, NULL);
+/*		ActivateMenuFocus(hWnd); */
+#ifdef DEBUG_MENU
+		printf("TrackPopupMenu // after MenuFocusLoop !\n");
+#endif
+		}
+	GlobalUnlock(hMenu);
+	return TRUE;
+}
+
+
+BOOL ActivateMenuFocus(HWND hWnd)
+{
+	WND		*wndPtr;
+	LPPOPUPMENU	lpmenu;
+	BOOL	bRet;
+	MSG		msg;
+	if (MenuHasFocus) return FALSE;
     wndPtr = WIN_FindWndPtr(hWnd);
-    lppop->ownerWnd = hWnd;
-    if (lppop->hWnd == (HWND)NULL) {
-        lppop->hWnd = CreateWindow("POPUPMENU", "", WS_POPUP | WS_VISIBLE,
-        	x, y, lppop->Width, lppop->Height, (HWND)NULL, 0, 
-        	wndPtr->hInstance, (LPSTR)lppop);
-        }
-    else {
-    	ShowWindow(lppop->hWnd, SW_SHOW);
-    	}
-    if (lppop->BarFlags == 0) {
-	PopupMenuCalcSize(lppop->hWnd);
+	if (wndPtr == NULL) return FALSE;
 #ifdef DEBUG_MENU
-	printf("TrackPopupMenu // x=%d y=%d Width=%d Height=%d\n", 
-		x, y, lppop->Width, lppop->Height); 
+	printf("ActivateMenuFocus (%04X) !\n", hWnd);
 #endif
-	SetWindowPos(lppop->hWnd, 0, x, y, lppop->Width + 2, lppop->Height, 
-		SWP_NOZORDER);
-	}
-    GlobalUnlock(hMenu);
-    return TRUE;
+	if ((wndPtr->dwStyle & WS_CHILD) == 0 && wndPtr->wIDmenu != 0) {
+		lpmenu = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
+		MenuItemSelect(hWnd, lpmenu, 0);
+		bRet = MenuFocusLoop(hWnd, lpmenu);
+		if (lpmenu != NULL) GlobalUnlock(wndPtr->wIDmenu);
+		return bRet;
+		}
+	return FALSE;
+}
+
+
+BOOL MenuFocusLoop(HWND hWnd, LPPOPUPMENU lpmenu)
+{
+	WND		*wndPtr;
+	MSG		msg;
+#ifdef DEBUG_MENU
+	printf("Enter in Menu Focus Loop !\n");
+#endif
+	MenuHasFocus = TRUE;
+	while(TRUE) {
+		if (!MenuHasFocus) break;
+		if (!GetMessage(&msg, (HWND)NULL, 0, 0)) break;
+		TranslateMessage(&msg);
+		if (hWnd == msg.hwnd && lpmenu != NULL) {
+			if ((msg.message == WM_SYSKEYDOWN && msg.wParam == VK_MENU) ||
+				(msg.message == WM_CHAR && msg.wParam == VK_ESCAPE)) {
+				HideAllSubPopupMenu(lpmenu);
+				break;
+				}
+			switch(msg.message) {
+				case WM_KEYDOWN:
+				case WM_KEYUP:
+				case WM_CHAR:
+				case WM_LBUTTONDOWN:
+				case WM_LBUTTONUP:
+				case WM_MOUSEMOVE:
+					PopupMenuWndProc(hWnd, msg.message, msg.wParam, msg.lParam);
+				default:
+					DispatchMessage(&msg);
+				}
+			}
+		else
+			DispatchMessage(&msg);
+		}
+EndOfFocus:
+	MenuHasFocus = FALSE;
+	if (lpmenu != NULL) MenuItemSelect(hWnd, lpmenu, -1);
+#ifdef DEBUG_MENU
+	printf("End of Menu Focus Loop !\n");
+#endif
+	return TRUE;
 }
 
 
@@ -1443,36 +1667,56 @@
  */
 void NC_TrackSysMenu(HWND hWnd)
 {
-    RECT	rect;
-    LPPOPUPMENU	lpsys;
-    WND *wndPtr = WIN_FindWndPtr(hWnd);    
+	RECT	rect;
+	LPPOPUPMENU	lpsys;
+	WND *wndPtr = WIN_FindWndPtr(hWnd);    
 #ifdef DEBUG_MENU
-    printf("NC_TrackSysMenu hWnd=%04X !\n", hWnd);
+	printf("NC_TrackSysMenu hWnd=%04X !\n", hWnd);
 #endif
-    if (!wndPtr) return;
-    lpsys = (LPPOPUPMENU)GlobalLock(wndPtr->hSysMenu);
+	if (!wndPtr) return;
+	lpsys = (LPPOPUPMENU)GlobalLock(wndPtr->hSysMenu);
 #ifdef DEBUG_MENU
-    printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
+	printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
 #endif
-    if (lpsys == NULL) return;
+	if (lpsys == NULL) return;
 #ifdef DEBUG_MENU
-    printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
+	printf("NC_TrackSysMenu wndPtr->hSysMenu=%04X !\n", wndPtr->hSysMenu);
 #endif
-    lpsys->BarFlags = FALSE;
-    lpsys->SysFlag = TRUE;
-    if (!IsWindowVisible(lpsys->hWnd)) {
-	GetWindowRect(hWnd, &rect);
+	lpsys->BarFlag = FALSE;
+	lpsys->SysFlag = TRUE;
+	lpsys->ChildFlag = FALSE;
+	lpsys->hWndParent = hWnd;
+	if (!IsWindowVisible(lpsys->hWnd)) {
+		GetWindowRect(hWnd, &rect);
+		lpsys->hWndPrev = GetFocus();
 #ifdef DEBUG_MENU
-	printf("NC_TrackSysMenu lpsys->hWnd=%04X !\n", lpsys->hWnd);
+		printf("NC_TrackSysMenu lpsys->hWnd=%04X !\n", lpsys->hWnd);
 #endif
-	TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON, 
-		rect.left, rect.top + SYSMETRICS_CYSIZE, 
-		0, hWnd, (LPRECT)NULL);
-	}
-    else {
-	ShowWindow(lpsys->hWnd, SW_HIDE);
-	}
-    GlobalUnlock(wndPtr->hSysMenu);
+		if (MenuHasFocus) {
+			TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON, 
+				rect.left, rect.top + SYSMETRICS_CYSIZE, 
+				0, hWnd, (LPRECT)NULL);
+			}
+		else {
+			MenuHasFocus = TRUE;
+			TrackPopupMenu(wndPtr->hSysMenu, TPM_LEFTBUTTON, 
+				rect.left, rect.top + SYSMETRICS_CYSIZE, 
+				0, hWnd, (LPRECT)NULL);
+			MenuHasFocus = FALSE;
+#ifdef DEBUG_MENU
+			printf("NC_TrackSysMenu // before MenuFocusLoop !\n");
+#endif
+			MenuFocusLoop(hWnd, NULL);
+/*			ActivateMenuFocus(hWnd); */
+#ifdef DEBUG_MENU
+			printf("NC_TrackSysMenu // after MenuFocusLoop !\n");
+#endif
+			}
+		}
+	else {
+		ShowWindow(lpsys->hWnd, SW_HIDE);
+		}
+	GlobalUnlock(wndPtr->hSysMenu);
 }
 
 
@@ -1495,29 +1739,29 @@
 BOOL SetMenuItemBitmaps(HMENU hMenu, WORD nPos, WORD wFlags,
 		HBITMAP hNewCheck, HBITMAP hNewUnCheck)
 {
-    WND		*wndPtr;
-    LPPOPUPMENU	menu;
-    LPMENUITEM 	lpitem;
-    int		i;
+	WND		*wndPtr;
+	LPPOPUPMENU	menu;
+	LPMENUITEM 	lpitem;
+	int		i;
 #ifdef DEBUG_MENU
-    printf("SetMenuItemBitmaps (%04X, %04X, %04X, %04X, %08X) !\n",
-	hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
+	printf("SetMenuItemBitmaps (%04X, %04X, %04X, %04X, %08X) !\n",
+					hMenu, nPos, wFlags, hNewCheck, hNewUnCheck);
 #endif
-    menu = (LPPOPUPMENU) GlobalLock(hMenu);
-    if (menu == NULL) return FALSE;
-    lpitem = menu->firstItem;
-    for (i = 0; i < menu->nItems; i++) {
-    	if (lpitem == NULL) break;
-    	if (i == nPos) {
-    	    lpitem->hCheckBit   = hNewCheck;
-     	    lpitem->hUnCheckBit = hNewUnCheck;
-	    GlobalUnlock(hMenu);
-    	    return TRUE;
-	    }
-    	lpitem = (LPMENUITEM)lpitem->next;
-    	}
-    GlobalUnlock(hMenu);
-    return FALSE;
+	menu = (LPPOPUPMENU) GlobalLock(hMenu);
+	if (menu == NULL) return FALSE;
+	lpitem = menu->firstItem;
+	for (i = 0; i < menu->nItems; i++) {
+		if (lpitem == NULL) break;
+		if (i == nPos) {
+			lpitem->hCheckBit   = hNewCheck;
+			lpitem->hUnCheckBit = hNewUnCheck;
+			GlobalUnlock(hMenu);
+			return TRUE;
+			}
+		lpitem = (LPMENUITEM)lpitem->next;
+		}
+	GlobalUnlock(hMenu);
+	return FALSE;
 }
 
 
@@ -1526,30 +1770,32 @@
  */
 HMENU CreateMenu()
 {
-    HANDLE	hItem;
-    HMENU	hMenu;
-    LPPOPUPMENU menu;
+	HANDLE	hItem;
+	HMENU	hMenu;
+	LPPOPUPMENU menu;
 #ifdef DEBUG_MENU
-    printf("CreatePopupMenu !\n");
+	printf("CreatePopupMenu !\n");
 #endif
-    hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
-    menu = (LPPOPUPMENU) GlobalLock(hMenu);
-    if (menu == NULL) {
-	GlobalFree(hMenu);
-	return 0;
- 	}
-    menu->nItems 	  = 0;
-    menu->firstItem       = NULL;
-    menu->ownerWnd	  = 0;
-    menu->hWnd		  = 0;
-    menu->hWndParent	  = 0;
-    menu->MouseFlags	  = 0;
-    menu->BarFlags	  = TRUE;
-    menu->SysFlag	  = FALSE;
-    menu->Width = 100;
-    menu->Height = 0;
-    GlobalUnlock(hMenu);
-    return hMenu;
+	hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
+	menu = (LPPOPUPMENU) GlobalLock(hMenu);
+	if (menu == NULL) {
+		GlobalFree(hMenu);
+		return 0;
+		}
+	menu->nItems 		= 0;
+	menu->firstItem 	= NULL;
+	menu->hWndPrev		= 0;
+	menu->ownerWnd		= 0;
+	menu->hWnd			= 0;
+	menu->hWndParent	= 0;
+	menu->MouseFlags	= 0;
+	menu->BarFlag		= TRUE;
+	menu->SysFlag		= FALSE;
+	menu->ChildFlag 	= TRUE;
+	menu->Width 		= 100;
+	menu->Height 		= 0;
+	GlobalUnlock(hMenu);
+	return hMenu;
 }
 
 
@@ -1558,31 +1804,31 @@
  */
 BOOL DestroyMenu(HMENU hMenu)
 {
-    LPPOPUPMENU lppop;
-    LPMENUITEM 	lpitem, lpitem2;
+	LPPOPUPMENU lppop;
+	LPMENUITEM 	lpitem, lpitem2;
 #ifdef DEBUG_MENU
-    printf("DestroyMenu (%04X) !\n", hMenu);
+	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 != NULL) {
+	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 != NULL) {
 #ifdef DEBUG_MENU
-	printf("DestroyMenu (%04X) // during loop items !\n", hMenu);
+		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;
-    	}
-    GlobalUnlock(hMenu);
-    GlobalFree(hMenu);
+		if ((lpitem->item_flags & MF_POPUP) == MF_POPUP) {
+			DestroyMenu((HMENU)lpitem->item_id);
+			}
+		lpitem = (LPMENUITEM)lpitem->next;
+		}
+	GlobalUnlock(hMenu);
+	GlobalFree(hMenu);
 #ifdef DEBUG_MENU
-    printf("DestroyMenu (%04X) // End !\n", hMenu);
+	printf("DestroyMenu (%04X) // End !\n", hMenu);
 #endif
-    return TRUE;
+	return TRUE;
 }
 
 
@@ -1591,29 +1837,23 @@
  */
 HMENU LoadMenu(HINSTANCE instance, char *menu_name)
 {
-    HMENU     		hMenu;
-    HANDLE		hMenu_desc;
-    MENU_HEADER 	*menu_desc;
+	HMENU     		hMenu;
+	HANDLE		hMenu_desc;
+	MENU_HEADER 	*menu_desc;
 #ifdef DEBUG_MENU
-    if ((LONG)menu_name & 0xFFFF0000L)
-	printf("LoadMenu: instance %02x, menu '%s'\n", instance, menu_name);
-    else
-	printf("LoadMenu: instance %02x, menu '%04X'\n", instance, menu_name);
+	if ((LONG)menu_name & 0xFFFF0000L)
+		printf("LoadMenu: instance %02x, menu '%s'\n", instance, menu_name);
+	else
+		printf("LoadMenu: instance %02x, menu '%04X'\n", instance, menu_name);
 #endif
-    if (instance == (HANDLE)NULL)  instance = hSysRes;
-    if (menu_name == NULL || 
-	(hMenu_desc = RSC_LoadMenu(instance, menu_name)) == 0 ||
-	(menu_desc = (MENU_HEADER *) GlobalLock(hMenu_desc)) == NULL) {
-	return 0;
-        }
-    hMenu = LoadMenuIndirect((LPSTR)menu_desc);
-/*
-    hMenu = CreateMenu();
-    ParseMenuResource((WORD *) (menu_desc + 1), 0, hMenu);
-    GlobalUnlock(hMenu_desc);
-    GlobalFree(hMenu_desc);
-*/
-    return hMenu;
+	if (instance == (HANDLE)NULL)  instance = hSysRes;
+	if (menu_name == NULL || 
+		(hMenu_desc = RSC_LoadMenu(instance, menu_name)) == 0 ||
+		(menu_desc = (MENU_HEADER *) GlobalLock(hMenu_desc)) == NULL) {
+		return 0;
+		}
+	hMenu = LoadMenuIndirect((LPSTR)menu_desc);
+	return hMenu;
 }
 
 
@@ -1622,16 +1862,16 @@
  */
 HMENU GetSystemMenu(HWND hWnd, BOOL bRevert)
 {
-    WND		*wndPtr;
-    wndPtr = WIN_FindWndPtr(hWnd);
-    if (!bRevert) {
+	WND		*wndPtr;
+	wndPtr = WIN_FindWndPtr(hWnd);
+	if (!bRevert) {
+		return wndPtr->hSysMenu;
+		}
+	else {
+		DestroyMenu(wndPtr->hSysMenu);
+		wndPtr->hSysMenu = CopySysMenu();
+		}
 	return wndPtr->hSysMenu;
-	}
-    else {
-	DestroyMenu(wndPtr->hSysMenu);
-	wndPtr->hSysMenu = CopySysMenu();
-	}
-    return wndPtr->hSysMenu;
 }
 
 
@@ -1640,9 +1880,9 @@
  */
 HMENU GetMenu(HWND hWnd) 
 { 
-    WND * wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr == NULL) return 0;
-    return wndPtr->wIDmenu;
+	WND * wndPtr = WIN_FindWndPtr(hWnd);
+	if (wndPtr == NULL) return 0;
+	return wndPtr->wIDmenu;
 }
 
 /**********************************************************************
@@ -1650,19 +1890,20 @@
  */
 BOOL SetMenu(HWND hWnd, HMENU hMenu)
 {
-    LPPOPUPMENU lppop;
-    WND * wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr == NULL) return FALSE;
+	LPPOPUPMENU lppop;
+	WND * wndPtr = WIN_FindWndPtr(hWnd);
+	if (wndPtr == NULL) return FALSE;
 #ifdef DEBUG_MENU
-    printf("SetMenu(%04X, %04X);\n", hWnd, hMenu);
+	printf("SetMenu(%04X, %04X);\n", hWnd, hMenu);
 #endif
-    wndPtr->wIDmenu = hMenu;
-    if (hMenu == 0) return TRUE;
-    lppop = (LPPOPUPMENU) GlobalLock(hMenu);
-    if (lppop == NULL) return FALSE;
-    lppop->ownerWnd = hWnd;
-    GlobalUnlock(hMenu);
-    return TRUE;
+	wndPtr->wIDmenu = hMenu;
+	if (hMenu == 0) return TRUE;
+	lppop = (LPPOPUPMENU) GlobalLock(hMenu);
+	if (lppop == NULL) return FALSE;
+	lppop->ownerWnd = hWnd;
+	ResetHiliteFlags(lppop);
+	GlobalUnlock(hMenu);
+	return TRUE;
 }
 
 
@@ -1671,28 +1912,31 @@
  */
 HMENU GetSubMenu(HMENU hMenu, short nPos)
 {
-    HMENU	hSubMenu;
-    LPPOPUPMENU lppop;
-    LPMENUITEM 	lpitem;
-    int		i;
+	HMENU	hSubMenu;
+	LPPOPUPMENU lppop;
+	LPMENUITEM 	lpitem;
+	int		i;
 #ifdef DEBUG_MENU
-    printf("GetSubMenu (%04X, %04X) !\n", hMenu, nPos);
+	printf("GetSubMenu (%04X, %04X) !\n", hMenu, nPos);
 #endif
-    if (hMenu == 0) return 0;
-    lppop = (LPPOPUPMENU) GlobalLock(hMenu);
-    if (lppop == NULL) return 0;
-    lpitem = lppop->firstItem;
-    for (i = 0; i < lppop->nItems; i++) {
-    	if (lpitem == NULL) break;
-    	if (i == nPos) {
-	    if (lpitem->item_flags & MF_POPUP)
-		return hSubMenu;
-	    else
-		return 0;
-	    }
-    	lpitem = (LPMENUITEM)lpitem->next;
-    	}
-    return 0;
+	if (hMenu == 0) return 0;
+	lppop = (LPPOPUPMENU) GlobalLock(hMenu);
+	if (lppop == NULL) return 0;
+	lpitem = lppop->firstItem;
+	for (i = 0; i < lppop->nItems; i++) {
+		if (lpitem == NULL) break;
+		if (i == nPos) {
+#ifdef DEBUG_MENU
+			printf("    found %04x\n", lpitem->item_id);
+#endif	    
+			if (lpitem->item_flags & MF_POPUP)
+				return lpitem->item_id;
+			else
+				return 0;
+			}
+		lpitem = (LPMENUITEM)lpitem->next;
+		}
+	return 0;
 }
 
 
@@ -1701,17 +1945,29 @@
  */
 void DrawMenuBar(HWND hWnd)
 {
-    WND		*wndPtr;
+	WND		*wndPtr;
+	LPPOPUPMENU lppop;
+	HDC		hDC;
 #ifdef DEBUG_MENU
-    printf("DrawMenuBar (%04X)\n", hWnd);
+	printf("DrawMenuBar (%04X)\n", hWnd);
 #endif
-    wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr != NULL && wndPtr->wIDmenu != 0) {
+	wndPtr = WIN_FindWndPtr(hWnd);
+	if (wndPtr != NULL && (wndPtr->dwStyle & WS_CHILD) == 0 && 
+		wndPtr->wIDmenu != 0) {
 #ifdef DEBUG_MENU
-	printf("DrawMenuBar wIDmenu=%04X \n", wndPtr->wIDmenu);
+		printf("DrawMenuBar wIDmenu=%04X \n", wndPtr->wIDmenu);
 #endif
-	SendMessage(hWnd, WM_NCPAINT, 1, 0L);
-	}
+		lppop = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
+		if (lppop == NULL) return;
+		if ((lppop->rect.bottom - lppop->rect.top) != 0) {
+			hDC = GetWindowDC(hWnd);
+			StdDrawMenuBar(hDC, &lppop->rect, lppop);
+			ReleaseDC(hWnd, hDC);
+			}
+		else
+			SendMessage(hWnd, WM_NCPAINT, 1, 0L);
+		GlobalUnlock(wndPtr->wIDmenu);
+		}
 }
 
 
@@ -1720,15 +1976,19 @@
  */
 HMENU LoadMenuIndirect(LPSTR menu_template)
 {
-    HMENU     		hMenu;
-    MENU_HEADER 	*menu_desc;
+	HMENU     		hMenu;
+	MENU_HEADER 	*menu_desc;
+	LPPOPUPMENU lppop;
 #ifdef DEBUG_MENU
-    printf("LoadMenuIndirect: menu_template '%08X'\n", menu_template);
+	printf("LoadMenuIndirect: menu_template '%08X'\n", menu_template);
 #endif
-    hMenu = CreateMenu();
-    menu_desc = (MENU_HEADER *)menu_template;
-    ParseMenuResource((WORD *)(menu_desc + 1), 0, hMenu); 
-    return hMenu;
+	hMenu = CreateMenu();
+	menu_desc = (MENU_HEADER *)menu_template;
+	ParseMenuResource((WORD *)(menu_desc + 1), 0, hMenu); 
+	lppop = (LPPOPUPMENU) GlobalLock(hMenu);
+	ResetHiliteFlags(lppop);
+	GlobalUnlock(hMenu);
+	return hMenu;
 }
 
 
@@ -1737,46 +1997,47 @@
  */
 HMENU CopySysMenu()
 {
-    HMENU     		hMenu;
-    LPPOPUPMENU 	menu;
-    LPPOPUPMENU 	sysmenu;
+	HMENU     		hMenu;
+	LPPOPUPMENU 	menu;
+	LPPOPUPMENU 	sysmenu;
 #ifdef DEBUG_MENU
-    printf("CopySysMenu entry !\n");
+	printf("CopySysMenu entry !\n");
 #endif
-    if (hSysMenu == 0) {
-	hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(1));
-/*	hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(SC_SYSMENU));*/
-/*	hSysMenu = LoadMenu((HINSTANCE)NULL, "SYSMENU"); */
 	if (hSysMenu == 0) {
-	    printf("SysMenu not found in system resources !\n");
-	    return (HMENU)NULL;
-	    }
+		hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(1));
+/*		hSysMenu = LoadMenu((HINSTANCE)NULL, MAKEINTRESOURCE(SC_SYSMENU));*/
+/*		hSysMenu = LoadMenu((HINSTANCE)NULL, "SYSMENU"); */
+		if (hSysMenu == 0) {
+			printf("SysMenu not found in system resources !\n");
+			return (HMENU)NULL;
+			}
 #ifdef DEBUG_MENU
-	else
-	    printf("SysMenu loaded from system resources %04X !\n", hSysMenu);
+		else
+			printf("SysMenu loaded from system resources %04X !\n", hSysMenu);
 #endif
-	}
-    hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
-    menu = (LPPOPUPMENU) GlobalLock(hMenu);
-    sysmenu = (LPPOPUPMENU) GlobalLock(hSysMenu);
-    if (menu != NULL && sysmenu != NULL) {
-	sysmenu->BarFlags = FALSE;
-	memcpy(menu, sysmenu, sizeof(POPUPMENU));
-	}
-    else {
-	printf("CopySysMenu // Bad SysMenu pointers !\n");
-	if (menu != NULL) {
-	    GlobalUnlock(hMenu);
-	    GlobalFree(hMenu);
-	    }
-	return (HMENU)NULL;
-	}
-    GlobalUnlock(hMenu);
-    GlobalUnlock(hSysMenu);
+		}
+	hMenu = GlobalAlloc(GMEM_MOVEABLE, sizeof(POPUPMENU));
+	menu = (LPPOPUPMENU) GlobalLock(hMenu);
+	sysmenu = (LPPOPUPMENU) GlobalLock(hSysMenu);
+	if (menu != NULL && sysmenu != NULL) {
+		sysmenu->BarFlag = FALSE;
+		sysmenu->SysFlag = TRUE;
+		memcpy(menu, sysmenu, sizeof(POPUPMENU));
+		}
+	else {
+		printf("CopySysMenu // Bad SysMenu pointers !\n");
+		if (menu != NULL) {
+			GlobalUnlock(hMenu);
+			GlobalFree(hMenu);
+			}
+		return (HMENU)NULL;
+		}
+	GlobalUnlock(hMenu);
+	GlobalUnlock(hSysMenu);
 #ifdef DEBUG_MENU
-    printf("CopySysMenu hMenu=%04X !\n", hMenu);
+	printf("CopySysMenu hMenu=%04X !\n", hMenu);
 #endif
-    return hMenu;
+	return hMenu;
 }
 
 
@@ -1806,11 +2067,13 @@
 	    	hSubMenu, popup_item->item_text);
 	    }
 	else {
-	    MENUITEMTEMPLATE *normal_item = (MENUITEMTEMPLATE *) item;
-	    next_item = (WORD *) (normal_item->item_text + 
-				  strlen(normal_item->item_text) + 1);
-	    AppendMenu(hMenu, normal_item->item_flags, 
-	    	normal_item->item_id, normal_item->item_text);
+		MENUITEMTEMPLATE *normal_item = (MENUITEMTEMPLATE *) item;
+		next_item = (WORD *) (normal_item->item_text + 
+		strlen(normal_item->item_text) + 1);
+		if (strlen(normal_item->item_text) == 0 && normal_item->item_id == 0) 
+			normal_item->item_flags |= MF_SEPARATOR;
+		AppendMenu(hMenu, normal_item->item_flags, 
+			normal_item->item_id, normal_item->item_text);
 	    }
 	}
     while (!(*item & MF_END));
diff --git a/controls/scroll.c b/controls/scroll.c
index 2894b21..1d05ee3 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -10,14 +10,16 @@
 */
 static char Copyright[] = "Copyright Martin Ayotte, 1993";
 
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include "windows.h"
 #include "sysmetrics.h"
 #include "scroll.h"
 #include "heap.h"
 #include "win.h"
-#include <sys/types.h>
-#include <dirent.h>
-#include <sys/stat.h>
+#include "prototypes.h"
 
 HBITMAP hUpArrow = 0;
 HBITMAP hDnArrow = 0;
@@ -142,174 +144,212 @@
 
 void ScrollBarButtonDown(HWND hWnd, int nBar, int x, int y)
 {
-    LPHEADSCROLL lphs;
-    HWND	hWndParent;
-    RECT	rect, rect2;
-    int		width, height;
-    LONG	dwOwner;
-    lphs = GetScrollObjectStruct(hWnd, nBar);
+	LPHEADSCROLL lphs;
+	HWND	hWndParent;
+	RECT	rect, rect2;
+	int		width, height;
+	LONG	dwOwner;
+	lphs = GetScrollObjectStruct(hWnd, nBar);
+	if (nBar == SB_CTL) {
+		hWndParent = GetParent(hWnd);
+		dwOwner = MAKELONG(0, lphs->hWndOwner);
 #ifdef DEBUG_SCROLL
-    printf("ScrollBarButtonDown // x=%d y=%d\n", x, y);
+		printf("ScrollBarButtonDown SB_CTL // x=%d y=%d\n", x, y);
 #endif
-    if (nBar == SB_CTL) {
-	hWndParent = GetParent(hWnd);
-	dwOwner = MAKELONG(0, lphs->hWndOwner);
-	}
-    else {
-	hWndParent = hWnd;
-	dwOwner = 0L;
-	}
+		}
+	else {
+		hWndParent = hWnd;
+		dwOwner = 0L; 
+#ifdef DEBUG_SCROLL
+		printf("ScrollBarButtonDown SB_?SCROLL // x=%d y=%d\n", x, y);
+#endif
+		}
 /*
-    SetFocus(lphs->hWndOwner);
+	SetFocus(lphs->hWndOwner);
 */
-    CopyRect(&rect, &lphs->rect);
+	CopyRect(&rect, &lphs->rect);
 #ifdef DEBUG_SCROLL
-    printf("ScrollDown / x=%d y=%d left=%d top=%d right=%d bottom=%d \n",
-    	x, y, rect.left, rect.top, rect.right, rect.bottom);
+	printf("ScrollDown / x=%d y=%d left=%d top=%d right=%d bottom=%d \n",
+					x, y, rect.left, rect.top, rect.right, rect.bottom);
 #endif
-    if (lphs->Direction == WM_VSCROLL) {
-	width = rect.right - rect.left;
-	if (y < (lphs->CurPix + width)) {
-	    if (y < width) {
-		lphs->ButtonDown = 1;
-		CopyRect(&rect2, &rect);
-		rect2.bottom = rect2.top + width;
-		InvalidateRect(lphs->hWndOwner, &rect2, TRUE);
-	        SendMessage(hWndParent, lphs->Direction, 
-				SB_LINEUP, dwOwner);
-		}
-	    else {
-		lphs->ButtonDown = 5;
-		SendMessage(hWndParent, lphs->Direction, 
-				SB_PAGEUP, dwOwner);
-		}
-	    }
-	if (y > (lphs->CurPix + (width << 1))) {
-	    if (y > (rect.bottom - rect.top - width)) {
-		lphs->ButtonDown = 2;
-		CopyRect(&rect2, &rect);
-		rect2.top = rect2.bottom - width;
-		InvalidateRect(lphs->hWndOwner, &rect2, TRUE);
-	        SendMessage(hWndParent, lphs->Direction, 
-				SB_LINEDOWN, dwOwner);
-		}
-	    else {
-		lphs->ButtonDown = 6;
-		SendMessage(hWndParent, lphs->Direction, 
-				SB_PAGEDOWN, dwOwner);
-		}
-	    }
-	if ((y > (lphs->CurPix + width)) &&
-	    (y < (lphs->CurPix + (width << 1)))) {
-	    lphs->ThumbActive = TRUE;
+	if (lphs->Direction == WM_VSCROLL) {
+		width = rect.right - rect.left;
+		if (y < (lphs->CurPix + width)) {
+			if (y < width) {
+				lphs->ButtonDown = 1;
+				CopyRect(&rect2, &rect);
+				rect2.bottom = rect2.top + width;
+				InvalidateRect(lphs->hWndOwner, &rect2, TRUE);
 #ifdef DEBUG_SCROLL
-	    printf("THUMB DOWN !\n");
+				printf("ScrollBarButtonDown send SB_LINEUP\n");
 #endif
-	    }
-	}
-    else {
-	height = rect.bottom - rect.top;
-	if (x < (lphs->CurPix + height)) {
-	    if (x < height) {
-		lphs->ButtonDown = 3;
-		CopyRect(&rect2, &rect);
-		rect2.right = rect2.left + height;
-		InvalidateRect(lphs->hWndOwner, &rect2, TRUE);
-	        SendMessage(hWndParent, lphs->Direction, 
-				SB_LINEUP, dwOwner);
-		}
-	    else {
-		lphs->ButtonDown = 5;
-		SendMessage(hWndParent, lphs->Direction, 
-				SB_PAGEUP, dwOwner);
-		}
-	    }
-	if (x > (lphs->CurPix + (height << 1))) {
-	    if (x > (rect.right - rect.left - height)) {
-		lphs->ButtonDown = 4;
-		CopyRect(&rect2, &rect);
-		rect2.left = rect2.right - height;
-		InvalidateRect(lphs->hWndOwner, &rect2, TRUE);
-	        SendMessage(hWndParent, lphs->Direction, 
-				SB_LINEDOWN, dwOwner);
-		}
-	    else {
-		lphs->ButtonDown = 6;
-		SendMessage(hWndParent, lphs->Direction, 
-				SB_PAGEDOWN, dwOwner);
-		}
-	    }
-	if ((x > (lphs->CurPix + height)) &&
-	    (x < (lphs->CurPix + (height << 1)))) {
-	    lphs->ThumbActive = TRUE;
+				SendMessage(hWndParent, lphs->Direction, 
+									SB_LINEUP, dwOwner);
+				}
+			else {
+				lphs->ButtonDown = 5;
 #ifdef DEBUG_SCROLL
-	    printf("THUMB DOWN !\n");
+				printf("ScrollBarButtonDown send SB_PAGEUP\n");
 #endif
-	    }
-	}
-    if (lphs->ButtonDown != 0) {
-	UpdateWindow(lphs->hWndOwner);
-	if (!lphs->TimerPending && nBar == SB_CTL) {
-	    lphs->TimerPending = TRUE;
-	    SetTimer(lphs->hWndOwner, 1, 500, NULL);
-	    }
-	}
+				SendMessage(hWndParent, lphs->Direction, 
+									SB_PAGEUP, dwOwner);
+				}
+			}
+		if (y > (lphs->CurPix + (width << 1))) {
+			if (y > (rect.bottom - rect.top - width)) {
+				lphs->ButtonDown = 2;
+				CopyRect(&rect2, &rect);
+				rect2.top = rect2.bottom - width;
+				InvalidateRect(lphs->hWndOwner, &rect2, TRUE);
+#ifdef DEBUG_SCROLL
+				printf("ScrollBarButtonDown send SB_LINEDOWN\n");
+#endif
+				SendMessage(hWndParent, lphs->Direction, 
+								SB_LINEDOWN, dwOwner);
+				}
+			else {
+				lphs->ButtonDown = 6;
+#ifdef DEBUG_SCROLL
+				printf("ScrollBarButtonDown send SB_PAGEDOWN\n");
+#endif
+				SendMessage(hWndParent, lphs->Direction, 
+								SB_PAGEDOWN, dwOwner);
+				}
+			}
+		if ((y > (lphs->CurPix + width)) &&
+		(y < (lphs->CurPix + (width << 1)))) {
+			lphs->ThumbActive = TRUE;
+#ifdef DEBUG_SCROLL
+			printf("THUMB DOWN !\n");
+#endif
+			}
+		}
+	else {
+		height = rect.bottom - rect.top;
+		if (x < (lphs->CurPix + height)) {
+			if (x < height) {
+				lphs->ButtonDown = 3;
+				CopyRect(&rect2, &rect);
+				rect2.right = rect2.left + height;
+				InvalidateRect(lphs->hWndOwner, &rect2, TRUE);
+#ifdef DEBUG_SCROLL
+				printf("ScrollBarButtonDown send SB_LINEUP\n");
+#endif
+				SendMessage(hWndParent, lphs->Direction, 
+									SB_LINEUP, dwOwner);
+				}
+			else {
+				lphs->ButtonDown = 5;
+#ifdef DEBUG_SCROLL
+				printf("ScrollBarButtonDown send SB_PAGEUP\n");
+#endif
+				SendMessage(hWndParent, lphs->Direction, 
+									SB_PAGEUP, dwOwner);
+				}
+			}
+		if (x > (lphs->CurPix + (height << 1))) {
+			if (x > (rect.right - rect.left - height)) {
+				lphs->ButtonDown = 4;
+				CopyRect(&rect2, &rect);
+				rect2.left = rect2.right - height;
+				InvalidateRect(lphs->hWndOwner, &rect2, TRUE);
+#ifdef DEBUG_SCROLL
+				printf("ScrollBarButtonDown send SB_LINEDOWN\n");
+#endif
+				SendMessage(hWndParent, lphs->Direction, 
+								SB_LINEDOWN, dwOwner);
+				}
+			else {
+				lphs->ButtonDown = 6;
+#ifdef DEBUG_SCROLL
+				printf("ScrollBarButtonDown send SB_PAGEDOWN\n");
+#endif
+				SendMessage(hWndParent, lphs->Direction, 
+								SB_PAGEDOWN, dwOwner);
+				}
+			}
+		if ((x > (lphs->CurPix + height)) &&
+		(x < (lphs->CurPix + (height << 1)))) {
+			lphs->ThumbActive = TRUE;
+#ifdef DEBUG_SCROLL
+			printf("THUMB DOWN !\n");
+#endif
+			}
+		}
+	if (lphs->ButtonDown != 0) {
+		UpdateWindow(lphs->hWndOwner);
+		if (!lphs->TimerPending && nBar == SB_CTL) {
+			lphs->TimerPending = TRUE;
+			SetTimer(lphs->hWndOwner, 1, 500, NULL);
+			}
+		}
 }
 
 
 void ScrollBarButtonUp(HWND hWnd, int nBar, int x, int y)
 {
-    LPHEADSCROLL lphs;
-    RECT	rect, rect2;
+	LPHEADSCROLL lphs;
+	RECT	rect, rect2;
+	HDC		hDC;
 #ifdef DEBUG_SCROLL
-    printf("ScrollBarButtonUp // x=%d y=%d\n", x, y); 
+	printf("ScrollBarButtonUp // x=%d y=%d\n", x, y); 
 #endif
-    lphs = GetScrollObjectStruct(hWnd, nBar);
-    lphs->ThumbActive = FALSE;
-    if (lphs->ButtonDown != 0) {
-	lphs->ButtonDown = 0;
-	GetClientRect(lphs->hWndOwner, &rect);
-	InvalidateRect(lphs->hWndOwner, &rect, TRUE);
-	UpdateWindow(lphs->hWndOwner);
-	}
+	lphs = GetScrollObjectStruct(hWnd, nBar);
+	lphs->ThumbActive = FALSE;
+	if (lphs->ButtonDown != 0) {
+		lphs->ButtonDown = 0;
+		GetClientRect(lphs->hWndOwner, &rect);
+		if (nBar == SB_CTL) {
+			InvalidateRect(lphs->hWndOwner, &rect, TRUE);
+			UpdateWindow(lphs->hWndOwner);
+			}
+		else {
+			hDC = GetWindowDC(lphs->hWndOwner);
+			StdDrawScrollBar(lphs->hWndOwner, hDC, nBar, &lphs->rect, lphs);
+			ReleaseDC(lphs->hWndOwner, hDC);
+			}
+		}
 }
 
 
 void ScrollBarMouseMove(HWND hWnd, int nBar, WORD wParam, int x, int y)
 {
-    LPHEADSCROLL lphs;
-    HWND	hWndParent;
-    HWND	hWndOwner;
-    LONG	dwOwner;
-    if ((wParam & MK_LBUTTON) == 0) return;
+	LPHEADSCROLL lphs;
+	HWND	hWndParent;
+	HWND	hWndOwner;
+	LONG	dwOwner;
+	if ((wParam & MK_LBUTTON) == 0) return;
+	lphs = GetScrollObjectStruct(hWnd, nBar);
+	if (lphs->ThumbActive == 0) return;
+	if (nBar == SB_CTL) {
+		hWndParent = GetParent(hWnd);
+		hWndOwner = lphs->hWndOwner;
 #ifdef DEBUG_SCROLL
-    printf("ScrollBarButtonMove // w=%04X x=%d y=%d \n", wParam, x, y);
+		printf("ScrollBarButtonMove SB_CTL // x=%d y=%d\n", x, y);
 #endif
-    lphs = GetScrollObjectStruct(hWnd, nBar);
-    if (lphs->ThumbActive == 0) return;
-    if (nBar == SB_CTL) {
-	hWndParent = GetParent(hWnd);
-	hWndOwner = lphs->hWndOwner;
-	}
-    else {
-	hWndParent = hWnd;
-	hWndOwner = 0;
-	}
-    if (lphs->Direction == WM_VSCROLL) {
-	int butsiz = lphs->rect.right - lphs->rect.left;
-	y = y - butsiz - (butsiz >> 1);
-	}
-    else {
-	int butsiz = lphs->rect.bottom - lphs->rect.top;
-	y = x - butsiz - (butsiz >> 1);
-	}
-    x = (y * (lphs->MaxVal - lphs->MinVal) / 
-		lphs->MaxPix) + lphs->MinVal;
+		}
+	else {
+		hWndParent = hWnd;
+		hWndOwner = 0;
 #ifdef DEBUG_SCROLL
-    printf("Scroll WM_MOUSEMOVE val=%d pix=%d\n", x, y);
+		printf("ScrollBarButtonMove SB_?SCROLL // x=%d y=%d\n", x, y);
 #endif
-    SendMessage(hWndParent, lphs->Direction, 
-	SB_THUMBTRACK, MAKELONG(x, hWndOwner));
+		}
+	if (lphs->Direction == WM_VSCROLL) {
+		int butsiz = lphs->rect.right - lphs->rect.left;
+		y = y - butsiz - (butsiz >> 1);
+		}
+	else {
+		int butsiz = lphs->rect.bottom - lphs->rect.top;
+		y = x - butsiz - (butsiz >> 1);
+		}
+	x = (y * (lphs->MaxVal - lphs->MinVal) / 
+			lphs->MaxPix) + lphs->MinVal;
+#ifdef DEBUG_SCROLL
+	printf("Scroll WM_MOUSEMOVE val=%d pix=%d\n", x, y);
+#endif
+	SendMessage(hWndParent, lphs->Direction, 
+		SB_THUMBTRACK, MAKELONG(x, hWndOwner));
 }
 
 
@@ -341,6 +381,7 @@
 }
 
 
+
 void StdDrawScrollBar(HWND hWnd, HDC hDC, int nBar, LPRECT lprect, LPHEADSCROLL lphs)
 {
     HWND	hWndParent;
@@ -385,19 +426,15 @@
 	    SelectObject(hMemDC, hUpArrowD);
 	else
 	    SelectObject(hMemDC, hUpArrow);
-	BitBlt(hDC, rect.left, rect.top, 
-		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
-/*
-	StretchBlt(hDC, 0, 0, lpdis->rcItem.right, lpdis->rcItem.right,
-			hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
-*/
+	StretchBlt(hDC, rect.left, rect.top, w, w, hMemDC, 
+			0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
 	GetObject(hDnArrow, sizeof(BITMAP), (LPSTR)&bm);
 	if (lphs->ButtonDown == 2)
 	    SelectObject(hMemDC, hDnArrowD);
 	else
 	    SelectObject(hMemDC, hDnArrow);
-	BitBlt(hDC, rect.left, rect.bottom - bm.bmHeight, 
-		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+	StretchBlt(hDC, rect.left, rect.bottom - w, w, w, hMemDC, 
+			0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
 	rect.top += w;
 	rect.bottom -= w;
 	}
@@ -407,15 +444,15 @@
 	    SelectObject(hMemDC, hLfArrowD);
 	else
 	    SelectObject(hMemDC, hLfArrow);
-	BitBlt(hDC, rect.left, rect.top, 
-		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+	StretchBlt(hDC, rect.left, rect.top, h, h, hMemDC, 
+			0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
 	GetObject(hRgArrow, sizeof(BITMAP), (LPSTR)&bm);
 	if (lphs->ButtonDown == 4)
 	    SelectObject(hMemDC, hRgArrowD);
 	else
 	    SelectObject(hMemDC, hRgArrow);
-	BitBlt(hDC, rect.right - bm.bmWidth, rect.top, 
-		bm.bmWidth, bm.bmHeight, hMemDC, 0, 0, SRCCOPY);
+	StretchBlt(hDC, rect.right - h, rect.top, h, h, hMemDC, 
+			0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
 	rect.left += h;
 	rect.right -= h;
 	}
@@ -549,7 +586,6 @@
 LPHEADSCROLL GetScrollObjectStruct(HWND hWnd, int nBar)
 {
     WND *wndPtr;
-    LPHEADSCROLL lphs;
     if (nBar != SB_CTL) {
 	wndPtr = WIN_FindWndPtr(hWnd);
     	if (nBar == SB_VERT) return (LPHEADSCROLL)wndPtr->VScroll;
@@ -565,13 +601,14 @@
  */
 int SetScrollPos(HWND hWnd, int nBar, int nPos, BOOL bRedraw)
 {
-    int nRet;
-    LPHEADSCROLL lphs;
-    lphs = GetScrollObjectStruct(hWnd, nBar);
-    if (lphs == NULL) return 0;
-    nRet = lphs->CurVal;
-    lphs->CurVal = (short)nPos;
-    if (lphs->MaxVal != lphs->MinVal)
+	LPHEADSCROLL lphs;
+	HDC		hDC;
+	int 	nRet;
+	lphs = GetScrollObjectStruct(hWnd, nBar);
+	if (lphs == NULL) return 0;
+	nRet = lphs->CurVal;
+	lphs->CurVal = (short)nPos;
+	if (lphs->MaxVal != lphs->MinVal)
 	lphs->CurPix = lphs->MaxPix * (abs((short)nPos) - abs(lphs->MinVal)) / 
     		(abs(lphs->MaxVal) - abs(lphs->MinVal));
     if (lphs->CurPix > lphs->MaxPix)  lphs->CurPix = lphs->MaxPix;
@@ -582,8 +619,17 @@
 	    lphs->MinVal, lphs->MaxVal);
 #endif
     if ((bRedraw) && (IsWindowVisible(lphs->hWndOwner))) {
-        InvalidateRect(lphs->hWndOwner, &lphs->rect, TRUE);
-        UpdateWindow(lphs->hWndOwner);
+		if (nBar == SB_CTL) {
+	        InvalidateRect(lphs->hWndOwner, &lphs->rect, TRUE);
+	        UpdateWindow(lphs->hWndOwner);
+			}
+		else {
+			if (lphs->rect.right != 0 && lphs->rect.bottom != 0) {
+				hDC = GetWindowDC(lphs->hWndOwner);
+				StdDrawScrollBar(lphs->hWndOwner, hDC, nBar, &lphs->rect, lphs);
+				ReleaseDC(lphs->hWndOwner, hDC);
+				}
+			}
         }
     return nRet;
 }
@@ -609,6 +655,7 @@
 void SetScrollRange(HWND hWnd, int nBar, int MinPos, int MaxPos, BOOL bRedraw)
 {
     LPHEADSCROLL lphs;
+	HDC		hDC;
     lphs = GetScrollObjectStruct(hWnd, nBar);
     if (lphs == NULL) return;
     lphs->MinVal = (short)MinPos;
@@ -622,8 +669,17 @@
     printf("SetScrollRange min=%d max=%d\n", lphs->MinVal, lphs->MaxVal);
 #endif
     if ((bRedraw) && (IsWindowVisible(lphs->hWndOwner))) {
-        InvalidateRect(lphs->hWndOwner, &lphs->rect, TRUE);
-        UpdateWindow(lphs->hWndOwner);
+		if (nBar == SB_CTL) {
+	        InvalidateRect(lphs->hWndOwner, &lphs->rect, TRUE);
+	        UpdateWindow(lphs->hWndOwner);
+			}
+		else {
+			if (lphs->rect.right != 0 && lphs->rect.bottom != 0) {
+				hDC = GetWindowDC(lphs->hWndOwner);
+				StdDrawScrollBar(lphs->hWndOwner, hDC, nBar, &lphs->rect, lphs);
+				ReleaseDC(lphs->hWndOwner, hDC);
+				}
+			}
         }
 }
 
diff --git a/controls/static.c b/controls/static.c
index 655d2fe..a78fd77 100644
--- a/controls/static.c
+++ b/controls/static.c
@@ -7,6 +7,7 @@
 
 static char Copyright[] = "Copyright  David W. Metcalfe, 1993";
 
+#include <stdio.h>
 #include <windows.h>
 #include "win.h"
 #include "user.h"
diff --git a/controls/widgets.c b/controls/widgets.c
index 1ad506d..c56daba 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -7,7 +7,9 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 #include "win.h"
-
+#include "desktop.h"
+#include "mdi.h"
+#include "gdi.h"
 
 LONG ButtonWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam );
 LONG StaticWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam );
@@ -16,6 +18,7 @@
 LONG ComboBoxWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
 LONG PopupMenuWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
 LONG DesktopWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG MDIClientWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
 
 
 static WNDCLASS WIDGETS_BuiltinClasses[] =
@@ -32,10 +35,12 @@
       0, 0, 0, 0, NULL, "COMBOBOX" },
     { CS_GLOBALCLASS, (LONG(*)())PopupMenuWndProc, 0, 8,
       0, 0, 0, 0, NULL, "POPUPMENU" },
-    { CS_GLOBALCLASS, (LONG(*)())DesktopWndProc, 0, 0,
+    { CS_GLOBALCLASS, (LONG(*)())DesktopWndProc, 0, sizeof(DESKTOPINFO),
       0, 0, 0, 0, NULL, DESKTOP_CLASS_NAME },
     { CS_GLOBALCLASS, (LONG(*)())DefDlgProc, 0, DLGWINDOWEXTRA,
-      0, 0, 0, 0, NULL, DIALOG_CLASS_NAME }
+      0, 0, 0, 0, NULL, DIALOG_CLASS_NAME },
+    { CS_GLOBALCLASS, (LONG(*)())MDIClientWndProc, 0, sizeof(MDICLIENTINFO),
+      0, 0, 0, STOCK_LTGRAY_BRUSH, NULL, "MDICLIENT" }
 };
 
 #define NB_BUILTIN_CLASSES \
@@ -47,7 +52,7 @@
  * 
  * Initialize the built-in window classes.
  */
-BOOL WIDGETS_Init()
+BOOL WIDGETS_Init(void)
 {
     int i;
     for (i = 0; i < NB_BUILTIN_CLASSES; i++)
diff --git a/if1632/Imakefile b/if1632/Imakefile
index 6803aaa..deee54f 100644
--- a/if1632/Imakefile
+++ b/if1632/Imakefile
@@ -8,15 +8,25 @@
 	callback.c \
 	relay.c
 
-/*
- * Hack alert. There appear to be no object files, 'cause a very
- * nasty rule below links *.o together, which is a generally bad idea,
- * but I can't see how else to do it.
- */
-OBJS = \
-	call.o \
-	callback.o \
-	relay.o
+DLLOBJS = \
+	dll_gdi.o \
+	dll_kernel.o \
+	dll_keyboard.o \
+	dll_shell.o \
+	dll_sound.o \
+	dll_stress.o \
+	dll_unixlib.o \
+	dll_user.o \
+	dll_win87em.o \
+	dll_winsock.o
+
+OBJS1= $(SRCS:.S=.o)
+
+#ifndef NewBuild
+OBJS = $(DLLOBJS) $(OBJS1:.c=.o) $(DLLOBJS:.o=_tab.o)
+#else
+OBJS = $(DLLOBJS) $(OBJS1:.c=.o) $(DLLOBJS:.o=_tab.o) $(DLLOBJS:dll_.rly_)
+#endif
 
 /*
  * If you add a new spec file, copy one of these lines
@@ -26,21 +36,19 @@
 MakeDllFromSpec(keyboard,$(TOP)/$(MODULE))
 MakeDllFromSpec(shell,$(TOP)/$(MODULE))
 MakeDllFromSpec(sound,$(TOP)/$(MODULE))
+MakeDllFromSpec(stress,$(TOP)/$(MODULE))
 MakeDllFromSpec(unixlib,$(TOP)/$(MODULE))
 MakeDllFromSpec(user,$(TOP)/$(MODULE))
 MakeDllFromSpec(win87em,$(TOP)/$(MODULE))
 MakeDllFromSpec(winsock,$(TOP)/$(MODULE))
 
-/*
- * Yes I know *.o is not very clever, but can you do it cleaner ?
- */
-WineRelocatableTarget($(TOP)/$(MODULE),*.o,)
+WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
+DependTarget()
+CleanTarget()
 
-$(TOP)/$(MODULE).o: $(OBJS)
+includes::
+
+install::
 
 clean::
 	$(RM) dll* dtb*
-
-depend::
-
-includes::
diff --git a/if1632/call.S b/if1632/call.S
index 5b49777..420d7bb 100644
--- a/if1632/call.S
+++ b/if1632/call.S
@@ -105,7 +105,7 @@
 	movw	$UDATASEL,%ax
 	movw	%ax,%fs
 	movw	%ax,%gs
-	movw	%ds,%ax
+/*	movw	%ds,%ax */
 
 	/*
 	 * Call entry point
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index 144e0df..b1a46fb 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -126,6 +126,8 @@
 148 pascal SetBrushOrg(word s_word s_word) SetBrushOrg(1 2 3)
 149 pascal GetBrushOrg(word) GetBrushOrg(1)
 150 pascal UnrealizeObject(word) UnrealizeObject(1)
+153 pascal CreateIC(ptr ptr ptr ptr) CreateIC(1 2 3 4)
+154 pascal GetNearestColor(word long) GetNearestColor(1 2)
 161 pascal PtInRegion(word s_word s_word) PtInRegion(1 2 3)
 162 pascal GetBitmapDimension(word) GetBitmapDimension(1)
 163 pascal SetBitmapDimension(word s_word s_word) SetBitmapDimension(1 2 3)
@@ -134,6 +136,7 @@
 179 pascal GetDCState(word) GetDCState(1)
 180 pascal SetDCState(word word) SetDCState(1 2)
 181 pascal RectInRegionOld(word ptr) RectInRegion(1 2)
+250 pascal Copy(ptr ptr word) Copy(1 2 3)
 345 pascal GetTextAlign(word) GetTextAlign(1)
 346 pascal SetTextAlign(word word) SetTextAlign(1 2)
 348 pascal Chord(word s_word s_word s_word s_word s_word s_word s_word s_word)
@@ -141,14 +144,21 @@
 349 pascal SetMapperFlags(word word) SetMapperFlags(1 2)
 350 pascal GetCharWidth(word word word ptr) GetCharWidth(1 2 3 4)
 360 pascal CreatePalette(ptr) CreatePalette(1)
+361 pascal GDISelectPalette(word word) GDISelectPalette(1 2)
+362 pascal GDIRealizePalette(word) GDIRealizePalette(1)
 363 pascal GetPaletteEntries(word word word ptr) GetPaletteEntries(1 2 3 4)
 364 pascal SetPaletteEntries(word word word ptr) SetPaletteEntries(1 2 3 4)
+365 pascal RealizeDefaultPalette(word) RealizeDefaultPalette(1)
 370 pascal GetNearestPaletteIndex(word long) GetNearestPaletteIndex(1 2)
+375 pascal GetSystemPaletteEntries(word word word ptr)
+	   GetSystemPaletteEntries(1 2 3 4)
 411 pascal GetCurLogFont(word) GetCurLogFont(1)
 440 pascal SetDIBits(word word word word ptr ptr word) SetDIBits(1 2 3 4 5 6 7)
 441 pascal GetDIBits(word word word word ptr ptr word) GetDIBits(1 2 3 4 5 6 7)
 442 pascal CreateDIBitmap(word ptr long ptr ptr word)
 	   CreateDIBitmap(1 2 3 4 5 6)
+443 pascal SetDIBitsToDevice(word s_word s_word word word word word word word ptr ptr word)
+	   SetDIBitsToDevice(1 2 3 4 5 6 7 8 9 10 11 12)
 444 pascal CreateRoundRectRgn(s_word s_word s_word s_word s_word s_word)
 	   CreateRoundRectRgn(1 2 3 4 5 6)
 445 pascal CreateDIBPatternBrush(word word) CreateDIBPatternBrush(1 2)
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index a3f9dd2..4472289 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -6,16 +6,16 @@
 
 3   pascal GetVersion() GetVersion()
 #return GetVersion 0 0x301
-4   pascal LocalInit(word word word) LocalInit(1 2 3)
-5   pascal LocalAlloc(word word) LocalAlloc(1 2)
-6   pascal LocalReAlloc(word word word) LocalReAlloc(1 2 3)
-7   pascal LocalFree(word) LocalFree(1)
-8   pascal LocalLock(word) LocalLock(1)
-9   pascal LocalUnlock(word) LocalUnlock(1)
-10  pascal LocalSize(word) LocalSize(1)
+4   pascal LocalInit(word word word) WIN16_LocalInit(1 2 3)
+5   pascal LocalAlloc(word word) WIN16_LocalAlloc(1 2)
+6   pascal LocalReAlloc(word word word) WIN16_LocalReAlloc(1 2 3)
+7   pascal LocalFree(word) WIN16_LocalFree(1)
+8   pascal LocalLock(word) WIN16_LocalLock(1)
+9   pascal LocalUnlock(word) WIN16_LocalUnlock(1)
+10  pascal LocalSize(word) WIN16_LocalSize(1)
 11  pascal LocalHandle(word) ReturnArg(1)
-12  pascal LocalFlags(word) LocalFlags(1)
-13  pascal LocalCompact(word) LocalCompact(1)
+12  pascal LocalFlags(word) WIN16_LocalFlags(1)
+13  pascal LocalCompact(word) WIN16_LocalCompact(1)
 14  return LocalNotify 4 0
 15  pascal GlobalAlloc(word long) GlobalAlloc(1 2)
 16  pascal GlobalReAlloc(word long word) GlobalReAlloc(1 2 3)
@@ -89,6 +89,7 @@
 163 pascal GlobalLRUOldest(word) ReturnArg(1)
 164 pascal GlobalLRUNewest(word) ReturnArg(1)
 166 pascal WinExec(ptr word) WinExec(1 2)
+169 pascal GetFreeSpace(word) GetFreeSpace(1)
 170 pascal AllocCStoDSAlias(word) AllocDStoCSAlias(1)
 171 pascal AllocDStoCSAlias(word) AllocDStoCSAlias(1)
 175 pascal AllocSelector(word) AllocSelector(1)
diff --git a/if1632/relay.c b/if1632/relay.c
index 92d5622..2189855 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -3,6 +3,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -14,6 +15,7 @@
 #include <linux/segment.h>
 #endif
 #include <errno.h>
+
 #include "neexe.h"
 #include "segmem.h"
 #include "prototypes.h"
@@ -22,7 +24,7 @@
 
 #define DEBUG_RELAY /* */
 
-#define N_BUILTINS	9
+#define N_BUILTINS	10
 
 struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS] =
 {
@@ -35,6 +37,7 @@
     { "SOUND",   SOUND_table,    20, 7 },
     { "KEYBOARD",KEYBOARD_table,137, 8 },
     { "WINSOCK", WINSOCK_table, 155, 9 },
+    { "STRESS",  STRESS_table,   15,10 },
 };
 
 unsigned short *Stack16Frame;
@@ -65,6 +68,7 @@
 DLLRelay(unsigned int func_num, unsigned int seg_off)
 {
     struct dll_table_entry_s *dll_p;
+    unsigned short *saved_Stack16Frame;
     unsigned int segment;
     unsigned int offset;
     unsigned int dll_id;
@@ -78,6 +82,7 @@
     /*
      * Determine address of arguments.
      */
+    saved_Stack16Frame = Stack16Frame;
     Stack16Frame = (unsigned short *) seg_off;
     arg_ptr = (void *) (seg_off + 0x18);
 
@@ -138,7 +143,11 @@
      * if we choose.
      */
     if (dll_p->n_args == 0)
-	return (*func_ptr)(arg_ptr);
+    {
+	ret_val = (*func_ptr)(arg_ptr);
+	Stack16Frame = saved_Stack16Frame;
+	return ret_val;
+    }
 
     /*
      * Getting this far means we need to convert the 16-bit argument stack.
@@ -197,6 +206,7 @@
     }
 #endif
 
+    Stack16Frame = saved_Stack16Frame;
     return ret_val;
 }
 
diff --git a/if1632/stress.spec b/if1632/stress.spec
new file mode 100644
index 0000000..8c93cb7
--- /dev/null
+++ b/if1632/stress.spec
@@ -0,0 +1,18 @@
+# summary: resource modification dll
+#
+name	stress
+id	10
+length	15
+
+2   pascal allocmem(long)		AllocMem(1)
+3   pascal freeallmem()			FreeAllMem()
+6   pascal allocfilehandles(word)	AllocFileHandles(1)
+7   pascal unallocfilehandles()		UnAllocFileHandles()
+8   pascal getfreefilehandles()		GetFreeFileHandles()
+10  pascal allocdiskspace(long word)	AllocDiskSpace(1 2)
+11  pascal unallocdiskspace(word)	UnAllocDiskSpace(1)
+12  pascal allocusermem(word)		AllocUserMem(1)
+13  pascal freeallusermem()		FreeAllUserMem()
+14  pascal allocgdimem(word)		AllocGDIMem(1)
+15  pascal freeallgdimem()		FreeAllGDIMem()
+
diff --git a/if1632/user.spec b/if1632/user.spec
index d6f213a..d79948c 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -152,7 +152,7 @@
 167 pascal ShowCaret(word) ShowCaret(1)
 168 pascal SetCaretBlinkTime(word) SetCaretBlinkTime(1)
 169 pascal GetCaretBlinkTime() GetCaretBlinkTime()
-171 pascal WinHelp(word word long) WinHelp(1 2 3)
+171 pascal WinHelp(word ptr word long) WinHelp(1 2 3 4)
 173 pascal LoadCursor(word ptr) LoadCursor(1 2)
 174 pascal LoadIcon(word ptr) LoadIcon(1 2)
 175 pascal LoadBitmap(word ptr) LoadBitmap(1 2)
@@ -215,6 +215,7 @@
 277 pascal GetDlgCtrlID(word) GetDlgCtrlID(1)
 282 pascal SelectPalette(word word word) SelectPalette(1 2 3)
 283 pascal RealizePalette(word) RealizePalette(1)
+284 pascal GetFreeSystemResources(word) GetFreeSystemResources(1)
 286 pascal GetDesktopWindow() GetDesktopWindow()
 288 pascal GetMessageExtraInfo() GetMessageExtraInfo()
 290 pascal RedrawWindow(word ptr word word) RedrawWindow(1 2 3 4)
@@ -235,6 +236,8 @@
 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)
+407 pascal CreateIcon(word word word byte byte ptr ptr)
+           CreateIcon(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)
@@ -257,6 +260,9 @@
 436 pascal IsCharLower(byte) IsCharLower(1)
 437 pascal AnsiUpperBuff(ptr word) AnsiUpperBuff(1 2)
 438 pascal AnsiLowerBuff(ptr word) AnsiLowerBuff(1 2)
+445 pascal DefFrameProc(word word word word long) DefFrameProc(1 2 3 4 5)
+447 pascal DefMDIChildProc(word word word long) DefMDIChildProc(1 2 3 4)
+451 pascal TranslateMDISysAccel(word ptr) TranslateMDISysAccel(1 2)
 452 pascal CreateWindowEx(long ptr ptr long s_word s_word s_word s_word 
 	                  word word word ptr) 
 	   CreateWindowEx(1 2 3 4 5 6 7 8 9 10 11 12)
diff --git a/include/arch.h b/include/arch.h
index 50e8255..c929a3e 100644
--- a/include/arch.h
+++ b/include/arch.h
@@ -5,13 +5,20 @@
 */
 
 #if defined (mc68000) || defined (sparc)
-#define CONV_LONG(a) (((a)&0xFF) << 24) | (((a) & 0xFF00) << 8) | (((a) & 0xFF0000) >> 8) | ((a)&0xFF000000 >> 24)
-#define CONV_SHORT(a) (((a) & 0xFF) << 8) | (((a) & 0xFF00) >> 8)
-#define CONV_CHAR_TO_LONG(x) ((x) >> 24)
-#define CONV_SHORT_TO_LONG(x) ((x) >> 16)
+
+#define CONV_LONG(a) (((a)&0xFF) << 24) | (((a) & 0xFF00) << 8) | (((unsigned long)(a) & 0xFF0000) >> 8) | ((unsigned long)((a)&0xFF000000) >> 24) 
+#define CONV_SHORT(a) (((a) & 0xFF) << 8) | (((unsigned long)(a) & 0xFF00) >> 8)
+#define CONV_CHAR_TO_LONG(x) ((unsigned long)(x) >> 24)
+#define CONV_SHORT_TO_LONG(x) ((unsigned long)(x) >> 16)
+
+#define CONV_BITMAPINFO ARCH_ConvBitmapInfo
+#define CONV_BITMAPCOREHEADER ARCH_ConvCoreHeader
 #else
 #define CONV_LONG(a) (a)
 #define CONV_SHORT(a) (a)
 #define CONV_CHAR_TO_LONG(a) (a)
 #define CONV_SHORT_TO_LONG(a) (a)
+
+#define CONV_BITMAPINFO
+#define CONV_BITMAPCOREHEADER
 #endif
diff --git a/include/atom.h b/include/atom.h
index c6234f4..9182769 100644
--- a/include/atom.h
+++ b/include/atom.h
@@ -9,7 +9,6 @@
 
 #include "windows.h"
 
-
 typedef struct
 {
     HANDLE      next;
@@ -27,7 +26,10 @@
 #ifdef WINELIB
 #define LocalAlign(flags,bytes) LocalAlloc (flags|LMEM_WINE_ALIGN,bytes)
 #else
-#define LocalAlign(flags,bytes) LocalAlloc (flags,bytes)
+#define LocalAlign(flags,bytes) WIN16_LocalAlloc((flags),(bytes))
+#define LocalAlloc		WIN16_LocalAlloc
+#define LocalLock		WIN16_LocalLock
+#define LocalFree		WIN16_LocalFree
 #endif
 
 #endif  /* ATOM_H */
diff --git a/include/bitmap.h b/include/bitmap.h
new file mode 100644
index 0000000..9addd88
--- /dev/null
+++ b/include/bitmap.h
@@ -0,0 +1,22 @@
+/*
+ * GDI bitmap definitions
+ *
+ * Copyright 1993 Alexandre Julliard
+ */
+
+#ifndef BITMAP_H
+#define BITMAP_H
+
+#include <X11/Xlib.h>
+#include "windows.h"
+
+  /* Handle of the bitmap selected by default in a memory DC */
+extern HBITMAP BITMAP_hbitmapMemDC;
+
+  /* GCs used for B&W and color bitmap operations */
+extern GC BITMAP_monoGC, BITMAP_colorGC;
+
+#define BITMAP_GC(bmp) \
+  (((bmp)->bitmap.bmBitsPixel == 1) ? BITMAP_monoGC : BITMAP_colorGC)
+
+#endif  /* BITMAP_H */
diff --git a/include/desktop.h b/include/desktop.h
new file mode 100644
index 0000000..38b7868
--- /dev/null
+++ b/include/desktop.h
@@ -0,0 +1,20 @@
+/*
+ * Desktop window definitions.
+ *
+ * Copyright 1994 Alexandre Julliard
+ */
+
+#ifndef DESKTOP_H
+#define DESKTOP_H
+
+#include "windows.h"
+
+typedef struct
+{
+    HBRUSH   hbrushPattern;
+    HBITMAP  hbitmapWallPaper;
+} DESKTOPINFO;
+
+extern BOOL DESKTOP_SetPattern(char *pattern );
+
+#endif  /* DESKTOP_H */
diff --git a/include/dlls.h b/include/dlls.h
index f82ae94..19a2dfb 100644
--- a/include/dlls.h
+++ b/include/dlls.h
@@ -63,5 +63,6 @@
 extern struct dll_table_entry_s SOUND_table[];
 extern struct dll_table_entry_s KEYBOARD_table[];
 extern struct dll_table_entry_s WINSOCK_table[];
+extern struct dll_table_entry_s STRESS_table[];
 
 #endif /* DLLS_H */
diff --git a/include/gdi.h b/include/gdi.h
index c1a5671..3ec95ea 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -69,10 +69,9 @@
 typedef struct tagBITMAPOBJ
 {
     GDIOBJHDR   header;
-    HANDLE      hBitmap;
-    BOOL        bSelected;
-    HDC         hdc;
-    SIZE        size;
+    BITMAP      bitmap;
+    Pixmap      pixmap;
+    SIZE        size;   /* For SetBitmapDimension() */
 } BITMAPOBJ;
 
 typedef struct tagRGNOBJ
@@ -152,7 +151,6 @@
     short         breakExtra;        /* breakTotalExtra / breakCount */
     short         breakRem;          /* breakTotalExtra % breakCount */
 
-    BYTE          planes;
     BYTE          bitsPerPixel;
 
     WORD          MapMode;
@@ -179,6 +177,8 @@
     int          style;
     int          pixel;
     int          width;
+    char *       dashes;
+    int          dash_len;
 } X_PHYSPEN;
 
   /* X physical brush */
@@ -197,6 +197,13 @@
     TEXTMETRIC    metrics;
 } X_PHYSFONT;
 
+  /* X physical palette information */
+typedef struct
+{
+    HANDLE    hMapping;
+    WORD      mappingSize;
+} X_PHYSPALETTE;
+
   /* X-specific DC information */
 typedef struct
 {
@@ -205,6 +212,7 @@
     X_PHYSFONT    font;
     X_PHYSPEN     pen;
     X_PHYSBRUSH   brush;
+    X_PHYSPALETTE pal;
 } X_DC_INFO;
 
 
@@ -282,7 +290,7 @@
 extern MDESC *GDI_Heap;
 
 #define GDI_HEAP_ALLOC(f,size) ((int)HEAP_Alloc(&GDI_Heap,f,size) & 0xffff)
-#define GDI_HEAP_ADDR(handle) ((void *)(handle | ((int)GDI_Heap & 0xffff0000)))
+#define GDI_HEAP_ADDR(handle) ((void *)((handle)|((int)GDI_Heap & 0xffff0000)))
 #define GDI_HEAP_FREE(handle) (HEAP_Free(&GDI_Heap,GDI_HEAP_ADDR(handle)))
 
 #endif
@@ -296,5 +304,7 @@
 
 extern Display * display;
 extern Screen * screen;
+extern Window rootWindow;
+extern int screenWidth, screenHeight, screenDepth;
 
 #endif  /* GDI_H */
diff --git a/include/heap.h b/include/heap.h
index 2b3b157..94ba9c9 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -6,6 +6,10 @@
 #ifndef HEAP_H
 #define HEAP_H
 
+#include "segmem.h"
+#include "regfunc.h"
+#include "atom.h"
+
 /**********************************************************************
  * LOCAL HEAP STRUCTURES AND FUNCTIONS
  */
@@ -17,11 +21,24 @@
     unsigned char  flags;
 } MDESC;
 
+typedef struct heap_local_heap_s
+{
+    struct heap_local_heap_s *next;
+    MDESC *free_list;
+    ATOMTABLE *local_table;
+    unsigned short selector;
+} LHEAP;
+
 extern void HEAP_Init(MDESC **free_list, void *start, int length);
 extern void *HEAP_Alloc(MDESC **free_list, int flags, int bytes);
 extern int  HEAP_Free(MDESC **free_list, void *block);
 extern void *HEAP_ReAlloc(MDESC **free_list, void *old_block, 
 			  int new_size, unsigned int flags);
+extern LHEAP *HEAP_LocalFindHeap(unsigned short owner);
+
+#define HEAP_OWNER	(Segments[Stack16Frame[11] >> 3].owner)
+#define LOCALHEAP()	(&HEAP_LocalFindHeap(HEAP_OWNER)->free_list)
+#define LOCALATOMTABLE() (&HEAP_LocalFindHeap(HEAP_OWNER)->local_table)
 
 /**********************************************************************
  * GLOBAL HEAP STRUCTURES AND FUNCTIONS:
diff --git a/include/mdi.h b/include/mdi.h
new file mode 100644
index 0000000..b6d179e
--- /dev/null
+++ b/include/mdi.h
@@ -0,0 +1,33 @@
+/* MDI.H
+ *
+ * Copyright 1994, Bob Amstadt
+ *
+ * MDI structure definitions.
+ */
+
+#ifndef MDI_H
+#define MDI_H
+
+#include "windows.h"
+
+#define MDI_MAXLISTLENGTH	64
+
+typedef struct mdi_child_info_s
+{
+    struct mdi_child_info_s *next, *prev;
+    HWND hwnd;
+} MDICHILDINFO;
+
+typedef struct 
+{
+    HMENU         hWindowMenu;
+    MDICHILDINFO *infoActiveChildren;
+    WORD          nActiveChildren;
+    WORD          idFirstChild;
+    HWND          hwndActiveChild;
+    HWND	  hwndHitTest;
+    BOOL          flagMenuAltered;
+    BOOL          flagChildMaximized;
+} MDICLIENTINFO;
+
+#endif /* MDI_H */
diff --git a/include/menu.h b/include/menu.h
index 315ef2e..19a6644 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -28,15 +28,17 @@
 
 typedef struct tagPOPUPMENU
 {
-    HWND	hWnd;			/* PopupMenu window handle	  */
-    HWND	hWndParent;		/* Parent opupMenu window handle  */
-    HWND	ownerWnd;		/* Owner window			  */
-    WORD	nItems;    		/* Number of items on menu	  */
+    HWND	hWnd;			/* PopupMenu window handle	  		*/
+    HWND	hWndParent;		/* Parent PopupMenu window handle  	*/
+    HWND	ownerWnd;		/* Owner window			  			*/
+    HWND	hWndPrev;		/* Previous Window Focus Owner 		*/
+    WORD	nItems;    		/* Number of items on menu			*/
     MENUITEM   *firstItem;
     WORD	FocusedItem;
     WORD	MouseFlags;
-    WORD	BarFlags;
-    BOOL	SysFlag;
+    BOOL	BarFlag;		/* TRUE if menu is a MENUBAR		*/
+    BOOL	SysFlag; 		/* TRUE if menu is a SYSMENU		*/
+    BOOL	ChildFlag;		/* TRUE if child of other menu		*/
     WORD	Width;
     WORD	Height;
     WORD	CheckWidth;
@@ -64,7 +66,7 @@
 } MENUITEMTEMPLATE;
 
 void StdDrawMenuBar(HDC hDC, LPRECT lprect, LPPOPUPMENU lppop);
-void MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
+BOOL MenuButtonDown(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
 void MenuButtonUp(HWND hWnd, LPPOPUPMENU lppop, int x, int y);
 void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y);
 extern void NC_TrackSysMenu(HWND hwnd);
diff --git a/include/message.h b/include/message.h
index fc3054d..905d182 100644
--- a/include/message.h
+++ b/include/message.h
@@ -48,9 +48,10 @@
 extern void MSG_DecPaintCount( HANDLE hQueue );
 extern void MSG_IncTimerCount( HANDLE hQueue );
 extern void MSG_DecTimerCount( HANDLE hQueue );
+extern void MSG_Synchronize();
 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);
+extern void hardware_event( WORD message, WORD wParam, LONG lParam,
+			    int xPos, int yPos, DWORD time, DWORD extraInfo );
 extern BOOL MSG_GetHardwareMessage( LPMSG msg );
 
 #endif  /* MESSAGE_H */
diff --git a/include/int21.h b/include/msdos.h
similarity index 65%
rename from include/int21.h
rename to include/msdos.h
index 2d3d221..b06d56c 100644
--- a/include/int21.h
+++ b/include/msdos.h
@@ -1,6 +1,7 @@
-#ifndef INT21_H
-#define INT21_H
+#ifndef __MSDOS_H
+#define __MSDOS_H
 #include <dirent.h>
+#include <windows.h>
 
 struct dosdirent {
 	int  inuse;
@@ -11,20 +12,9 @@
 	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 DOSVERSION 0x0330;
 
 #define EAX context->sc_eax
 #define EBX context->sc_ebx
@@ -45,13 +35,39 @@
 
 #define EFL context->sc_efl
 
-#define pointer(a,b) 	(((unsigned int) a << 16) | b)
-#define segment(a) 	(a >> 16)
-#define offset(a)	(a & 0xffff)
-
 #define SetCflag	(EFL |= 0x00000001L)
 #define ResetCflag	(EFL &= 0xfffffffeL)
 
+#define pointer(a,b) 	(BYTE*)(((WORD) a << 16) | b)
+#define segment(a) 	((DWORD)a >> 16)
+#define offset(a)	((DWORD)a & 0xffff)
+
+#define setword(a,b)	*(BYTE*)a	= b & 0xff; \
+			*((BYTE*)a + 1) = (b>>8) & 0xff;
+			
+#define setdword(a,b)	*(BYTE*)a	= b & 0xff; \
+			*((BYTE*)a + 1) = (b>>8) & 0xff; \
+			*((BYTE*)a + 2) = (b>>16) & 0xff; \
+			*((BYTE*)a + 3) = (b>>24) & 0xff;
+
+#define getword(a)	(WORD) *(BYTE*)a + \
+			(*((BYTE*)a + 1) << 8)
+
+#define getdword(a)	(DWORD) (*(BYTE*)a + \
+			(*((BYTE*)a + 1) << 8) + \
+			(*((BYTE*)a + 2) << 16) + \
+			(*((BYTE*)a + 3) << 24))
+
+/* dos file attributes */
+
+#define FA_NORMAL   0x00        /* Normal file, no attributes */
+#define FA_RDONLY   0x01        /* Read only attribute */
+#define FA_HIDDEN   0x02        /* Hidden file */
+#define FA_SYSTEM   0x04        /* System file */
+#define FA_LABEL    0x08        /* Volume label */
+#define FA_DIREC    0x10        /* Directory */
+#define FA_ARCH     0x20        /* Archive */
+
 /* extended error codes */
 
 #define NoError		0x00
@@ -113,4 +129,4 @@
 #define EL_Network	0x03
 #define EL_Memory	0x05
 
-#endif /* INT21_H */
+#endif /* __MSDOS_H */
diff --git a/include/neexe.h b/include/neexe.h
index cf2700d..d31a0e3 100644
--- a/include/neexe.h
+++ b/include/neexe.h
@@ -220,4 +220,7 @@
 #define NE_RSCTYPE_RCDATA		0x800a
 #define NE_RSCTYPE_STRING		0x8006
 
+int  load_typeinfo  (int, struct resource_typeinfo_s *);
+int  load_nameinfo  (int, struct resource_nameinfo_s *);
+
 #endif /* NEEXE_H */
diff --git a/include/options.h b/include/options.h
index e313305..ae38f73 100644
--- a/include/options.h
+++ b/include/options.h
@@ -10,6 +10,8 @@
 struct options
 {
     char * spyFilename;
+    char * desktopGeometry; /* NULL when no desktop */
+    char * programName;     /* To use when loading resources */
     int    usePrivateMap;
     int    synchronous;
     short  cmdShow;
diff --git a/include/prototypes.h b/include/prototypes.h
index d8a3195..a972176 100644
--- a/include/prototypes.h
+++ b/include/prototypes.h
@@ -3,54 +3,259 @@
 /*
  * Copyright  Robert J. Amstadt, 1993
  */
-#ifndef PROTOTYPES_H
-#define PROTOTYPES_H
+#ifndef _WINE_PROTOTYPES_H
+#define _WINE_PROTOTYPES_H
 
 #include <sys/types.h>
 
 #include "neexe.h"
 #include "segmem.h"
 #include "wine.h"
-#include "int21.h"
+#include "heap.h"
+#include "msdos.h"
+#include "windows.h"
 
 #ifndef WINELIB
-extern struct segment_descriptor_s *
-    CreateSelectors(struct w_files *);
+
+/* loader/dump.c */
 
 extern void PrintFileHeader(struct ne_header_s *ne_header);
 extern void PrintSegmentTable(struct ne_segment_table_entry_s *seg_table, 
-			      int nentries);
+				int nentries);
 extern void PrintRelocationTable(char *exe_ptr, 
-				 struct ne_segment_table_entry_s *seg_entry_p,
-				 int segment);
-extern int FixupSegment(struct w_files * wpnt, int segment_num);
-extern struct  dll_table_entry_s *FindDLLTable(char *dll_name);
-extern unsigned int GetEntryPointFromOrdinal(struct w_files * wpnt, 
-					     int ordinal);
+				struct ne_segment_table_entry_s *seg_entry_p, 
+				int segment);
 
-extern struct segment_descriptor_s *GetNextSegment(unsigned int flags,
-						   unsigned int limit);
-extern struct segment_descriptor_s *CreateNewSegments(int code_flag, 
-						      int read_only, 
-						      int length, 
-						      int n_segments);
+/* loader/ldtlib.c */
+
+struct segment_descriptor *
+make_sd(unsigned base, unsigned limit, int contents, int read_exec_only, int seg32, int inpgs);
+int get_ldt(void *buffer);
+int set_ldt_entry(int entry, unsigned long base, unsigned int limit,
+	      int seg_32bit_flag, int contents, int read_only_flag,
+	      int limit_in_pages_flag);
+
+/* loader/resource.c */
+
+extern int OpenResourceFile(HANDLE instance);
+extern HBITMAP ConvertCoreBitmap( HDC hdc, BITMAPCOREHEADER * image );
+extern HBITMAP ConvertInfoBitmap( HDC hdc, BITMAPINFO * image );
+extern int FindResourceByNumber(struct resource_nameinfo_s *result_p, 
+				int type_id, int resource_id);
+extern int FindResourceByName(struct resource_nameinfo_s *result_p,
+		     int type_id, char *resource_name);
+extern HICON LoadIcon(HANDLE instance, LPSTR icon_name);
+extern HANDLE RSC_LoadResource(int instance, char *rsc_name, int type,
+				int *image_size_ret);
+extern int LoadString(HANDLE instance, WORD resource_id, LPSTR buffer, int buflen);
+extern HANDLE RSC_LoadMenu(HANDLE instance, LPSTR menu_name);
+extern HBITMAP LoadBitmap(HANDLE instance, LPSTR bmp_name);
+
+/* loader/selector.c */
+
+extern int FindUnusedSelectors(int n_selectors);
+extern int IPCCopySelector(int i_old, unsigned long new, int swap_type);
+extern WORD AllocSelector(WORD old_selector);
+extern unsigned int PrestoChangoSelector(unsigned src_selector, unsigned dst_selector);
+extern WORD AllocDStoCSAlias(WORD ds_selector);
+extern WORD FreeSelector(WORD sel);
+extern SEGDESC *CreateNewSegments(int code_flag, int read_only, int length, 
+					int n_segments);
+extern SEGDESC *GetNextSegment(unsigned int flags, unsigned int limit);
+extern unsigned int GetEntryDLLName(char *dll_name, char *function, int *sel,
+					int *addr);
+extern unsigned int GetEntryDLLOrdinal(char *dll_name, int ordinal, int *sel,
+					int *addr);
+extern unsigned int GetEntryPointFromOrdinal(struct w_files * wpnt,
+					int ordinal);
+extern SEGDESC *CreateSelectors(struct  w_files * wpnt);
+
+/* loader/signal.c */
+
+extern int init_wine_signals(void);
+
+/* loader/wine.c */
+
+extern void myerror(const char *s);
+extern void load_mz_header (int, struct mz_header_s *);
+extern void load_ne_header (int, struct ne_header_s *);
+
+extern char *GetFilenameFromInstance(unsigned short instance);
+extern struct w_files *GetFileInfo(unsigned short instance);
+extern HINSTANCE LoadImage(char *modulename, int filetype);
+extern int _WinMain(int argc, char **argv);
+extern void InitializeLoadedDLLs();
+extern int FixupSegment(struct w_files * wpnt, int segment_num);
+/*
 extern struct mz_header_s *CurrentMZHeader;
 extern struct ne_header_s *CurrentNEHeader;
 extern int CurrentNEFile;
-extern do_int1A(struct sigcontext_struct * context);
-extern do_int21(struct sigcontext_struct * context);
+*/
 
-extern void GetUnixDirName(char *rootdir, char *name);
-extern char *GetDirectUnixFileName(char *dosfilename);
+/* if1632/relay.c */
+
+extern int CallBack16(void *func, int n_args, ...);
+extern void *CALLBACK_MakeProcInstance(void *func, int instance);
+extern void CallLineDDAProc(FARPROC func, short xPos, short yPos, long lParam);
+extern void winestat(void);
+
+/* if1632/callback.c */
+
+extern int DLLRelay(unsigned int func_num, unsigned int seg_off);
+extern struct dll_table_entry_s *FindDLLTable(char *dll_name);
+extern int FindOrdinalFromName(struct dll_table_entry_s *dll_table, char *func_name);
+extern int ReturnArg(int arg);
+
+/* miscemu/int1a.c */
+
+extern do_int1A(struct sigcontext_struct *context);
+
+/* miscemu/int21.c */
+
+extern do_int21(struct sigcontext_struct *context);
+
+/* miscemu/kernel.c */
+
+extern int KERNEL_LockSegment(int segment);
+extern int KERNEL_UnlockSegment(int segment);
+extern KERNEL_InitTask();
+extern int KERNEL_WaitEvent(int task);
+
+/* misc/comm.c */
+
+void Comm_Init(void);
+void Comm_DeInit(void);
+
+/* misc/dos_fs.c */
+
+extern void DOS_InitFS(void);
+extern WORD DOS_GetEquipment(void);
+extern int DOS_ValidDrive(int drive);
+extern int DOS_GetDefaultDrive(void); 
+extern void DOS_SetDefaultDrive(int drive);
+extern void ToUnix(char *s); 
+extern void ToDos(char *s); 
+extern void ChopOffSlash(char *string);
+extern int DOS_DisableDrive(int drive);
+extern int DOS_EnableDrive(int drive); 
 extern char *GetUnixFileName(char *dosfilename);
-
+extern char *DOS_GetCurrentDir(int drive);
+extern int DOS_ChangeDir(int drive, char *dirname);
+extern int DOS_MakeDir(int drive, char *dirname);
+extern int DOS_GetSerialNumber(int drive, unsigned long *serialnumber); 
+extern int DOS_SetSerialNumber(int drive, unsigned long serialnumber); 
+extern char *DOS_GetVolumeLabel(int drive);
+extern int DOS_SetVolumeLabel(int drive, char *label);
+extern int DOS_GetFreeSpace(int drive, long *size, long *available);
 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 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 /* WINELIB */
+/* misc/profile.c */
 
-#endif /* PROTOTYPES_H */
+extern void sync_profiles(void);
+
+/* misc/spy.c */
+
+extern void SpyInit(void);
+
+/* controls/button.c */
+
+extern LONG ButtonWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
+
+/* controls/combo.c */
+
+extern LONG ComboBoxWndProc(HWND hwnd, WORD message, WORD wParam, LONG lParam);
+
+/* controls/desktop.c */
+
+extern LONG DesktopWndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam);
+extern BOOL DESKTOP_SetPattern(char *pattern);
+
+/* controls/listbox.c */
+
+extern LONG ListBoxWndProc(HWND hwnd, WORD message, WORD wParam, LONG lParam);
+
+/* controls/menu.c */
+
+extern LONG PopupMenuWndProc(HWND hwnd, WORD message, WORD wParam, LONG lParam);
+
+/* controls/scrollbar.c */
+
+extern LONG ScrollBarWndProc(HWND hWnd, WORD message, WORD wParam, LONG lParam);
+
+/* controls/static.c */
+
+extern LONG StaticWndProc(HWND hwnd, WORD message, WORD wParam, LONG lParam);
+
+/* controls/widget.c */
+
+extern BOOL WIDGETS_Init(void);
+
+/* memory/heap.c */
+
+extern void HEAP_Init(MDESC **free_list, void *start, int length);
+extern void *HEAP_Alloc(MDESC **free_list, int flags, int bytes);
+extern void *HEAP_ReAlloc(MDESC **free_list, void *old_block, int new_size, unsigned int flags);
+extern int HEAP_Free(MDESC **free_list, void *block);
+extern LHEAP *HEAP_LocalFindHeap(unsigned short owner);
+extern void HEAP_LocalInit(unsigned short owner, void *start, int length);
+extern void *WIN16_LocalAlloc(int flags, int bytes);
+extern int WIN16_LocalCompact(int min_free);
+extern unsigned int WIN16_LocalFlags(unsigned int handle);
+extern unsigned int WIN16_LocalFree(unsigned int handle);
+extern unsigned int WIN16_LocalInit(unsigned int segment, unsigned int start, unsigned int end);
+extern void *WIN16_LocalLock(unsigned int handle);
+extern void *WIN16_LocalReAlloc(unsigned int handle, int flags, int bytes);
+extern unsigned int WIN16_LocalSize(unsigned int handle);
+extern unsigned int WIN16_LocalUnlock(unsigned int handle);
+
+/* objects/bitmaps.c */
+
+extern BOOL BITMAP_Init(void);
+
+/* objects/color.c */
+
+extern BOOL COLOR_Init(void);
+
+/* objects/dib.c */
+
+extern int DIB_BitmapInfoSize(BITMAPINFO *info, WORD coloruse);
+
+/* objects/gdiobj.c */
+
+extern BOOL GDI_Init(void);
+
+/* objects/palette.c */
+
+extern BOOL PALETTE_Init(void);
+
+/* objects/region.c */
+
+extern BOOL REGION_Init(void);
+
+/* windows/graphic.c */
+
+extern void DrawReliefRect(HDC hdc, RECT rect, int thickness, BOOL pressed);
+
+/* windows/dce.c */
+
+extern void DCE_Init(void);
+
+/* windows/dialog.c */
+
+extern BOOL DIALOG_Init(void);
+
+/* windows/syscolor.c */
+
+extern void SYSCOLOR_Init(void);
+
+/* windows/sysmetrics.c */
+
+extern void SYSMETRICS_Init(void);
+
+#endif /* WINELIB */
+#endif /* _WINE_PROTOTYPES_H */
diff --git a/include/regfunc.h b/include/regfunc.h
index e31e9aa..96f2fef 100644
--- a/include/regfunc.h
+++ b/include/regfunc.h
@@ -6,6 +6,7 @@
 
 extern unsigned short *Stack16Frame;
 
+#define _CONTEXT &Stack16Frame[12]
 #define _AX	Stack16Frame[34]
 #define _BX	Stack16Frame[28]
 #define _CX	Stack16Frame[32]
diff --git a/include/stress.h b/include/stress.h
new file mode 100644
index 0000000..190e675
--- /dev/null
+++ b/include/stress.h
@@ -0,0 +1,30 @@
+#ifndef __STRESS_H
+#define __STRESS_H
+
+#include <windows.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define	EDS_WIN		1
+#define EDS_CUR		2
+#define EDS_TEMP	3
+
+BOOL	AllocGDIMem(UINT);
+BOOL	AllocMem(DWORD);
+BOOL	AllocUserMem(UINT);
+int	AllocDiskSpace(long, UINT);
+int	AllocFileHandles(int);
+int	GetFreeFileHandles(void);
+void	FreeAllGDIMem(void);
+void	FreeAllMem(void);
+void	FreeAllUserMem(void);
+void	UnAllocDiskSpace(UINT);
+void	UnAllocFileHandles(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STRESS_H */
diff --git a/include/user.h b/include/user.h
index d702023..166a707 100644
--- a/include/user.h
+++ b/include/user.h
@@ -25,7 +25,7 @@
 #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_ADDR(handle) ((void *)((handle)|((int)USER_Heap&0xffff0000)))
 #define USER_HEAP_FREE(handle) (HEAP_Free(&USER_Heap,USER_HEAP_ADDR(handle)))
 
 #endif  /* WINELIB */
diff --git a/include/win.h b/include/win.h
index 706deec..2631911 100644
--- a/include/win.h
+++ b/include/win.h
@@ -67,8 +67,11 @@
 BOOL WIN_UnlinkWindow( HWND hwnd );
 BOOL WIN_LinkWindow( HWND hwnd, HWND hwndInsertAfter );
 HWND WIN_FindWinToRepaint( HWND hwnd );
+BOOL WINPOS_IsAnActiveWindow( HWND hwnd );
+void WINPOS_ActivateChild( HWND hwnd );
 
 extern Display * display;
 extern Screen * screen;
+extern Window rootWindow;
 
 #endif  /* WIN_H */
diff --git a/include/windows.h b/include/windows.h
index 4bd0205..7986183 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -5,6 +5,7 @@
 
 #ifndef _WINARGS
 
+typedef short	INT;
 typedef unsigned short UINT;
 typedef unsigned short WORD;
 typedef unsigned long DWORD;
@@ -218,6 +219,25 @@
     DWORD     dwExStyle WINE_PACKED;
 } CREATESTRUCT, *LPCREATESTRUCT;
 
+typedef struct 
+{
+    HMENU     hWindowMenu;
+    WORD      idFirstChild;
+} CLIENTCREATESTRUCT, *LPCLIENTCREATESTRUCT;
+
+typedef struct
+{
+    LPSTR     szClass;
+    LPSTR     szTitle;
+    HANDLE    hOwner;
+    short     x;
+    short     y;
+    short     cx;
+    short     cy;
+    LONG      style WINE_PACKED;
+    LONG      lParam WINE_PACKED;
+} MDICREATESTRUCT, *LPMDICREATESTRUCT;
+
   /* Offsets for GetWindowLong() and GetWindowWord() */
 #define GWL_EXSTYLE         (-20)
 #define GWL_STYLE           (-16)
@@ -466,7 +486,9 @@
 
 typedef DWORD COLORREF;
 
-#define RGB(r,g,b)  ((COLORREF)((r) | ((g) << 8) | ((b) << 16)))
+#define RGB(r,g,b)          ((COLORREF)((r) | ((g) << 8) | ((b) << 16)))
+#define PALETTERGB(r,g,b)   (0x02000000 | RGB(r,g,b))
+#define PALETTEINDEX(i)     ((COLORREF)(0x01000000 | (WORD)(i)))
 
 #define GetRValue(rgb)	    ((rgb) & 0xff)
 #define GetGValue(rgb)      (((rgb) >> 8) & 0xff)
@@ -987,6 +1009,8 @@
 #define OF_SHARE_EXCLUSIVE 0x0010
 #define OF_VERIFY 0x0400
 
+#define DRIVE_CANNOTDETERMINE	0
+#define DRIVE_DOESNOTEXIST	1
 #define DRIVE_REMOVABLE	2
 #define DRIVE_FIXED	3
 #define DRIVE_REMOTE	4
@@ -1378,6 +1402,18 @@
 
 #define WM_PARENTNOTIFY     0x0210
 
+#define WM_MDICREATE	    0x0220
+#define WM_MDIDESTROY	    0x0221
+#define WM_MDIACTIVATE	    0x0222
+#define WM_MDIRESTORE	    0x0223
+#define WM_MDINEXT	    0x0224
+#define WM_MDIMAXIMIZE	    0x0225
+#define WM_MDITILE	    0x0226
+#define WM_MDICASCADE	    0x0227
+#define WM_MDIICONARRANGE   0x0228
+#define WM_MDIGETACTIVE     0x0229
+#define WM_MDISETMENU	    0x0230
+
 #define WM_ENTERSIZEMOVE    0x0231
 #define WM_EXITSIZEMOVE     0x0232
 
@@ -2117,6 +2153,7 @@
 
 F(HMENU,CreateMenu)
 F(BOOL,GetInputState)
+F(BOOL,SetDeskPattern)
 F(LPSTR,GetDOSEnvironment)
 F(DWORD,GetMessagePos)
 F(LONG,GetMessageTime)
@@ -2199,9 +2236,11 @@
 Fa(BOOL,EnableHardwareInput,BOOL,a)
 Fa(BOOL,FreeModule,HANDLE,a)
 Fa(BOOL,FreeResource,HANDLE,a)
+#ifndef GLOBAL_SOURCE
 Fa(BOOL,GlobalUnWire,HANDLE,a)
 Fa(BOOL,GlobalUnfix,HANDLE,a)
 Fa(BOOL,GlobalUnlock,HANDLE,a)
+#endif
 Fa(BOOL,InitAtomTable,WORD,a)
 Fa(BOOL,IsClipboardFormatAvailable,WORD,a)
 Fa(BOOL,IsIconic,HWND,a)
@@ -2215,6 +2254,7 @@
 Fa(BOOL,OpenClipboard,HWND,a)
 Fa(BOOL,OpenIcon,HWND,a)
 Fa(BOOL,RemoveFontResource,LPSTR,a)
+Fa(BOOL,SetDeskWallPaper,LPSTR,a)
 Fa(BOOL,SetErrorMode,WORD,a)
 Fa(BOOL,SwapMouseButton,BOOL,a)
 Fa(BOOL,UnrealizeObject,HBRUSH,a)
@@ -2232,9 +2272,11 @@
 Fa(DWORD,GetViewportOrg,HDC,a)
 Fa(DWORD,GetWindowExt,HDC,a)
 Fa(DWORD,GetWindowOrg,HDC,a)
+#ifndef GLOBAL_SOURCE
 Fa(DWORD,GlobalCompact,DWORD,a)
 Fa(DWORD,GlobalHandle,WORD,a)
 Fa(DWORD,GlobalSize,HANDLE,a)
+#endif
 Fa(DWORD,OemKeyScan,WORD,a)
 Fa(FARPROC,LocalNotify,FARPROC,a)
 Fa(HANDLE,BeginDeferWindowPos,int,nNumWindows)
@@ -2248,9 +2290,11 @@
 Fa(HANDLE,GetModuleHandle,LPSTR,a)
 Fa(HANDLE,GetStockObject,int,a)
 Fa(HANDLE,GetWindowTask,HWND,a)
+#ifndef GLOBAL_SOURCE
 Fa(HANDLE,GlobalFree,HANDLE,a)
 Fa(HANDLE,GlobalLRUNewest,HANDLE,a)
 Fa(HANDLE,GlobalLRUOldest,HANDLE,a)
+#endif
 Fa(HANDLE,LoadLibrary,LPSTR,a)
 Fa(HANDLE,LocalFree,HANDLE,a)
 Fa(HANDLE,LocalHandle,WORD,a)
@@ -2289,13 +2333,19 @@
 Fa(LPSTR,AnsiLower,LPSTR,a)
 Fa(LPSTR,AnsiNext,LPSTR,a)
 Fa(LPSTR,AnsiUpper,LPSTR,a)
+#ifndef GLOBAL_SOURCE
 Fa(LPSTR,GlobalLock,HANDLE,a)
 Fa(LPSTR,GlobalWire,HANDLE,a)
+#endif
 Fa(LPSTR,LockResource,HANDLE,a)
+#ifndef GLOBAL_SOURCE
 Fa(void,GlobalFix,HANDLE,a)
 Fa(void,GlobalNotify,FARPROC,a)
+#endif
 Fa(void,LimitEmsPages,DWORD,a)
 Fa(void,SetConvertHook,BOOL,a)
+Fa(UINT,GDIRealizePalette,HDC,a)
+Fa(UINT,RealizePalette,HDC,a)
 Fa(WORD,AllocDStoCSAlias,WORD,a)
 Fa(WORD,AllocSelector,WORD,a)
 Fa(WORD,ArrangeIconicWindows,HWND,a)
@@ -2305,13 +2355,15 @@
 Fa(WORD,GetMenuItemCount,HMENU,a)
 Fa(WORD,GetTaskQueue,HANDLE,a)
 Fa(WORD,GetTextAlign,HDC,a)
+#ifndef GLOBAL_SOURCE
 Fa(WORD,GlobalFlags,HANDLE,a)
 Fa(WORD,GlobalPageLock,HANDLE,a)
 Fa(WORD,GlobalPageUnlock,HANDLE,a)
+#endif
 Fa(WORD,LocalCompact,WORD,a)
 Fa(WORD,LocalFlags,HANDLE,a)
 Fa(WORD,LocalSize,HANDLE,a)
-Fa(int,RealizePalette,HDC,a)
+Fa(WORD,RealizeDefaultPalette,HDC,a)
 Fa(WORD,RegisterClipboardFormat,LPCSTR,a)
 Fa(WORD,RegisterWindowMessage,LPCSTR,a)
 Fa(WORD,SetHandleCount,WORD,a)
@@ -2412,7 +2464,9 @@
 Fb(FARPROC,SetWindowsHook,int,a,FARPROC,b)
 Fb(HANDLE,CopyMetaFile,HANDLE,a,LPSTR,b)
 Fb(HANDLE,GetProp,HWND,a,LPSTR,b)
+#ifndef GLOBAL_SOURCE
 Fb(HANDLE,GlobalAlloc,WORD,a,DWORD,b)
+#endif
 Fb(HANDLE,LoadAccelerators,HANDLE,a,LPSTR,b)
 Fb(HANDLE,LoadModule,LPSTR,a,LPVOID,b)
 Fb(HANDLE,LoadResource,HANDLE,a,HANDLE,b)
@@ -2425,6 +2479,7 @@
 Fb(HBRUSH,CreateHatchBrush,short,a,COLORREF,b)
 Fb(HCURSOR,LoadCursor,HANDLE,a,LPSTR,b)
 Fb(HICON,LoadIcon,HANDLE,a,LPSTR,b)
+Fb(HPALETTE,GDISelectPalette,HDC,a,HPALETTE,b)
 Fb(HMENU,GetSubMenu,HMENU,a,short,b)
 Fb(HMENU,GetSystemMenu,HWND,a,BOOL,b)
 Fb(HMENU,LoadMenu,HANDLE,a,LPSTR,b)
@@ -2553,7 +2608,9 @@
 Fc(FARPROC,SetResourceHandler,HANDLE,a,LPSTR,b,FARPROC,c)
 Fc(HANDLE,AllocResource,HANDLE,a,HANDLE,b,DWORD,c)
 Fc(HANDLE,FindResource,HANDLE,a,LPSTR,b,LPSTR,c)
+#ifndef GLOBAL_SOURCE
 Fc(HANDLE,GlobalReAlloc,HANDLE,a,DWORD,b,WORD,c)
+#endif
 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)
@@ -2737,7 +2794,7 @@
 Fk(HWND,CreateWindow,LPSTR,szAppName,LPSTR,Label,DWORD,ol,short,x,short,y,short,w,short,h,HWND,d,HMENU,e,,HANDLE i,LPSTR,g)
 Fk(BOOL,StretchBlt,HDC,a,short,b,short,c,short,d,short,e,HDC,f,short,g,short,h,short,i,short,j,DWORD,k)
 Fl(HWND,CreateWindowEx,DWORD,a,LPSTR,b,LPSTR,c,DWORD,d,short,e,short,f,short,g,short,h,HWND,i,HMENU,j,HANDLE,k,LPSTR,l)
-Fl(int,SetDIBitsToDevice,HDC,a,WORD,b,WORD,c,WORD,d,WORD,e,WORD,f,WORD,g,WORD,h,WORD,i,LPSTR,j,LPBITMAPINFO,k,WORD,l)
+Fl(int,SetDIBitsToDevice,HDC,a,short,b,short,c,WORD,d,WORD,e,WORD,f,WORD,g,WORD,h,WORD,i,LPSTR,j,LPBITMAPINFO,k,WORD,l)
 Fm(int,StretchDIBits,HDC,a,WORD,b,WORD,c,WORD,d,WORD,e,WORD,f,WORD,g,WORD,h,WORD,i,LPSTR,j,LPBITMAPINFO,k,WORD,l,DWORD,m)
 Fn(HFONT,CreateFont,int,a,int,b,int,c,int,d,int,e,BYTE,f,BYTE,g,BYTE,h,BYTE,i,BYTE,j,BYTE,k,BYTE,l,BYTE,m,LPSTR,n)
 
diff --git a/include/wine.h b/include/wine.h
index 13eee61..28cda57 100644
--- a/include/wine.h
+++ b/include/wine.h
@@ -3,28 +3,35 @@
 
 #include "dlls.h"
 
-struct w_files{
-  struct w_files  * next;
-  char * name;   /* Name, as it appears in the windows binaries */
-  char * filename;  /* Actual name of the unix file that satisfies this */
-  int fd;
-  struct mz_header_s *mz_header;
-  struct ne_header_s *ne_header;
-  struct ne_segment_table_entry_s *seg_table;
-  struct segment_descriptor_s *selector_table;
-  char * lookup_table;
-  char * nrname_table;
-  char * rname_table;
-  unsigned short hinstance;
+#define MAX_NAME_LENGTH		64
+
+typedef struct resource_name_table
+{
+    struct resource_name_table *next;
+    unsigned short type_ord;
+    unsigned short id_ord;
+    char id[MAX_NAME_LENGTH];
+} RESNAMTAB;
+
+struct w_files
+{
+    struct w_files  * next;
+    char * name;   /* Name, as it appears in the windows binaries */
+    char * filename;  /* Actual name of the unix file that satisfies this */
+    int fd;
+    struct mz_header_s *mz_header;
+    struct ne_header_s *ne_header;
+    struct ne_segment_table_entry_s *seg_table;
+    struct segment_descriptor_s *selector_table;
+    char * lookup_table;
+    char * nrname_table;
+    char * rname_table;
+    unsigned short hinstance;
+    RESNAMTAB *resnamtab;
 };
 
 extern struct  w_files * wine_files;
 
-extern char *GetFilenameFromInstance(unsigned short instance);
-extern struct w_files *GetFileInfo(unsigned short instance);
-extern char *WineIniFileName(void);
-extern char *WinIniFileName(void);
-
 #define MAX_DOS_DRIVES	26
 
 #define WINE_INI WineIniFileName()
@@ -63,9 +70,4 @@
 #define HZ 100
 #endif
 
-void load_mz_header (int, struct mz_header_s *);
-void load_ne_header (int, struct ne_header_s *);
-int  load_typeinfo  (int, struct resource_typeinfo_s *);
-int  load_nameinfo  (int, struct resource_nameinfo_s *);
-
 #endif /* WINE_H */
diff --git a/include/winsock.h b/include/winsock.h
index 6b83e52..c36be06 100644
--- a/include/winsock.h
+++ b/include/winsock.h
@@ -63,6 +63,7 @@
 #endif
 
 #ifndef _SYS_SOCKET_H_
+#ifndef _sys_socket_h
 /*
  * Structure used by kernel to pass protocol
  * information in raw sockets.
@@ -72,6 +73,7 @@
         u_short sp_protocol;            /* protocol */
 };
 #endif
+#endif
 
 /*
  * Maximum queue length specifiable by listen.
diff --git a/loader/Imakefile b/loader/Imakefile
index 7c9ddeb..df53854 100644
--- a/loader/Imakefile
+++ b/loader/Imakefile
@@ -9,6 +9,7 @@
 	selector.c \
 	signal.c \
 	library.c \
+	resource.c \
 	wine.c
 
 OBJS = $(SRCS:.c=.o)
diff --git a/loader/dump.c b/loader/dump.c
index 42fee12..08e1962 100644
--- a/loader/dump.c
+++ b/loader/dump.c
@@ -1,3 +1,4 @@
+#ifndef WINELIB
 static char RCSId[] = "$Id: dump.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 
@@ -89,3 +90,4 @@
 	printf("TARGET %04.4x %04.4x\n", rep->target1, rep->target2);
     }
 }
+#endif /* ifndef WINELIB */
diff --git a/loader/ldt.c b/loader/ldt.c
index 8ac6b1e..96ca5e4 100644
--- a/loader/ldt.c
+++ b/loader/ldt.c
@@ -1,11 +1,12 @@
+#ifndef WINELIB
 static char RCSId[] = "$Id: ldt.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <errno.h>
-
 #include "prototypes.h"
+
 #if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <machine/segments.h>
 #endif
@@ -84,3 +85,5 @@
 	}
     }
 }
+
+#endif /* ifndef WINELIB */
diff --git a/loader/ldtlib.c b/loader/ldtlib.c
index d361040..c264979 100644
--- a/loader/ldtlib.c
+++ b/loader/ldtlib.c
@@ -1,3 +1,4 @@
+#ifndef WINELIB
 static char RCSId[] = "$Id: ldtlib.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 
@@ -90,3 +91,4 @@
     
 #endif
 }
+#endif /* ifndef WINELIB */
diff --git a/loader/library.c b/loader/library.c
index ebb91fe..39ea0bb 100644
--- a/loader/library.c
+++ b/loader/library.c
@@ -1,5 +1,7 @@
+#ifndef WINELIB
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -9,8 +11,18 @@
 #include "wine.h"
 #include "dlls.h"
 
+typedef struct module_table_entry
+{
+	HINSTANCE	hInst;
+	LPSTR		name;
+	WORD		count;
+} MODULEENTRY;
+
 extern struct  w_files * wine_files;
 
+#define N_BUILTINS	10
+
+extern struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS];
 
 /**********************************************************************
  *				GetCurrentTask	[KERNEL.36]
@@ -28,19 +40,27 @@
  */
 HANDLE GetModuleHandle(LPSTR lpModuleName)
 {
-    register struct w_files *w = wine_files;
-    printf("GetModuleHandle('%s');\n", lpModuleName);
-    while (w) {
-	printf("GetModuleHandle // '%s' \n", w->name); 
-	if (strcmp(w->name, lpModuleName) == 0) {
-	    printf("GetModuleHandle('%s') return %04X \n", 
-		lpModuleName, w->hinstance);
-	    return w->hinstance;
-	    }
-	w = w->next;
-	}
-    printf("GetModuleHandle('%s') not found !\n", lpModuleName);
-    return 0;
+	register struct w_files *w = wine_files;
+	int 	i;
+ 	printf("GetModuleHandle('%s');\n", lpModuleName);
+	while (w) {
+/*		printf("GetModuleHandle // '%s' \n", w->name);  */
+		if (strcmp(w->name, lpModuleName) == 0) {
+			printf("GetModuleHandle('%s') return %04X \n", 
+							lpModuleName, w->hinstance);
+			return w->hinstance;
+			}
+		w = w->next;
+		}
+    for (i = 0; i < N_BUILTINS; i++) {
+		if (strcmp(dll_builtin_table[i].dll_name, lpModuleName) == 0) {
+			printf("GetModuleHandle('%s') return %04X \n", 
+							lpModuleName, 0xFF00 + i);
+			return (0xFF00 + i);
+			}
+		}
+	printf("GetModuleHandle('%s') not found !\n", lpModuleName);
+	return 0;
 }
 
 
@@ -79,11 +99,11 @@
  */
 HANDLE LoadLibrary(LPSTR libname)
 {
-    HANDLE hRet;
+    HANDLE hModule;
     printf("LoadLibrary '%s'\n", libname);
-    hRet = LoadImage(libname, DLL);
-    printf("after LoadLibrary hRet=%04X\n", hRet);
-    return hRet;
+    hModule = LoadImage(libname, DLL);
+    printf("LoadLibrary returned hModule=%04X\n", hModule);
+    return hModule;
 }
 
 
@@ -97,3 +117,64 @@
 }
 
 
+/**********************************************************************
+ *					GetProcAddress	[KERNEL.50]
+ */
+FARPROC GetProcAddress(HANDLE hModule, char *proc_name)
+{
+	WORD 	wOrdin;
+	int		sel, addr, ret;
+    register struct w_files *w = wine_files;
+	int 	ordinal, len;
+	char 	* cpnt;
+	char	C[128];
+	if (hModule == 0) {
+		printf("GetProcAddress: Bad Module handle=%#04X\n", hModule);
+		return NULL;
+		}
+	if (hModule >= 0xF000) {
+		if ((int) proc_name & 0xffff0000) {
+			printf("GetProcAddress: builtin %#04x, '%s'\n", hModule, proc_name);
+/*			wOrdin = FindOrdinalFromName(struct dll_table_entry_s *dll_table, proc_name); */
+			}
+		else {
+			printf("GetProcAddress: builtin %#04x, %d\n", hModule, (int) proc_name);
+			}
+		return NULL;
+		}
+	while (w && w->hinstance != hModule) w = w->next;
+	printf("GetProcAddress // Module Found ! w->filename='%s'\n", w->filename);
+	if (w == NULL) return NULL;
+	if ((int) proc_name & 0xffff0000) {
+		AnsiUpper(proc_name);
+		printf("GetProcAddress: %#04x, '%s'\n", hModule, proc_name);
+		cpnt = w->nrname_table;
+		while(TRUE) {
+			if (((int) cpnt)  - ((int)w->nrname_table) >  
+			   w->ne_header->nrname_tab_length)  return NULL;
+			len = *cpnt++;
+			strncpy(C, cpnt, len);
+			C[len] = '\0';
+			printf("pointing Function '%s' !\n", C);
+			if (strncmp(cpnt, proc_name, len) ==  0) break;
+			cpnt += len + 2;
+			};
+		ordinal =  *((unsigned short *)  (cpnt +  len));
+		}
+	else {
+		printf("GetProcAddress: %#04x, %d\n", hModule, (int) proc_name);
+		ordinal = (int)proc_name;
+		}
+	ret = GetEntryPointFromOrdinal(w, ordinal);
+	if (ret == -1) {
+		printf("GetProcAddress // Function not found !\n");
+		return NULL;
+		}
+	addr  = ret & 0xffff;
+	sel = (ret >> 16);
+	printf("GetProcAddress // ret=%08X sel=%04X addr=%04X\n", ret, sel, addr);
+	return ret;
+}
+
+#endif /* ifndef WINELIB */
+
diff --git a/misc/resource.c b/loader/resource.c
similarity index 80%
rename from misc/resource.c
rename to loader/resource.c
index 680b61f1..4ff3c28 100644
--- a/misc/resource.c
+++ b/loader/resource.c
@@ -1,14 +1,14 @@
-#ifndef WINELIB
 static char RCSId[] = "$Id: resource.c,v 1.4 1993/07/04 04:04:21 root Exp root $";
 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
-#endif
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+
 #include "arch.h"
 #include "prototypes.h"
 #include "windows.h"
@@ -17,6 +17,8 @@
 #include "icon.h"
 #include "accel.h"
 
+/* #define DEBUG_RESOURCE  */
+
 #define MIN(a,b)	((a) < (b) ? (a) : (b))
 
 typedef struct resource_s
@@ -34,18 +36,105 @@
 static RESOURCE *Top = NULL;
 extern HINSTANCE hSysRes;
 
-HANDLE RSC_LoadResource(int instance, char *rsc_name, int type, int *image_size_ret);
+HANDLE RSC_LoadResource(int instance, char *rsc_name, int type, 
+			int *image_size_ret);
+void RSC_LoadNameTable(void);
 
 extern char *ProgramName;
 
-/*****************************************************************************
-  * Super Patch, I promise to arrange things as soon as I can.
-  *
-******************************************************************************/
-#ifdef WINELIB
-#include "../loader/wine.c"
-#endif
+
+/**********************************************************************
+ *					RSC_LoadNameTable
+ */
+#ifndef WINELIB
+void 
+RSC_LoadNameTable()
+{
+    struct resource_typeinfo_s typeinfo;
+    struct resource_nameinfo_s nameinfo;
+    unsigned short             size_shift;
+    RESNAMTAB                 *top, *new;
+    char                       read_buf[1024];
+    char                      *p;
+    int                        i;
+    unsigned short             len;
+    off_t                      rtoff;
+    off_t		       saved_pos;
+    
+    top = NULL;
 
+    /*
+     * Move to beginning of resource table.
+     */
+    rtoff = (ResourceFileInfo->mz_header->ne_offset +
+	     ResourceFileInfo->ne_header->resource_tab_offset);
+    lseek(ResourceFd, rtoff, SEEK_SET);
+    
+    /*
+     * Read block size.
+     */
+    if (read(ResourceFd, &size_shift, sizeof(size_shift)) != 
+	sizeof(size_shift))
+    {
+	return;
+    }
+    size_shift = CONV_SHORT(size_shift);
+
+    /*
+     * Find resource.
+     */
+    typeinfo.type_id = 0xffff;
+    while (typeinfo.type_id != 0) 
+    {
+	if (!load_typeinfo (ResourceFd, &typeinfo))
+	    break;
+
+	if (typeinfo.type_id == 0) 
+	    break;
+	if (typeinfo.type_id == 0x800f) 
+	{
+	    for (i = 0; i < typeinfo.count; i++) 
+	    {
+		if (read(ResourceFd, &nameinfo, sizeof(nameinfo)) != 
+		    sizeof(nameinfo))
+		{
+		    break;
+		}
+		
+		saved_pos = lseek(ResourceFd, 0, SEEK_CUR);
+		lseek(ResourceFd, (long) nameinfo.offset << size_shift, 
+		      SEEK_SET);
+		read(ResourceFd, &len, sizeof(len));
+		while (len)
+		{
+		    new = (RESNAMTAB *) GlobalQuickAlloc(sizeof(*new));
+		    new->next = top;
+		    top = new;
+
+		    read(ResourceFd, &new->type_ord, 2);
+		    read(ResourceFd, &new->id_ord, 2);
+		    read(ResourceFd, read_buf, len - 6);
+		    
+		    p = read_buf + strlen(read_buf) + 1;
+		    strncpy(new->id, p, MAX_NAME_LENGTH);
+		    new->id[MAX_NAME_LENGTH - 1] = '\0';
+
+		    read(ResourceFd, &len, sizeof(len));
+		}
+
+		lseek(ResourceFd, saved_pos, SEEK_SET);
+	    }
+	    break;
+	}
+	else 
+	{
+	    lseek(ResourceFd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
+	}
+    }
+
+    ResourceFileInfo->resnamtab = top;
+}
+#endif /* WINELIB */
 
 /**********************************************************************
  *					OpenResourceFile
@@ -69,8 +158,15 @@
 	close(ResourceFd);
     
     ResourceInst = instance;
-
-    ResourceFd = open (res_file, O_RDONLY);
+    ResourceFd   = open (res_file, O_RDONLY);
+#if 1
+#ifndef WINELIB
+    if (w->resnamtab == (RESNAMTAB *) -1)
+    {
+	RSC_LoadNameTable();
+    }
+#endif
+#endif
 
 #ifdef DEBUG_RESOURCE
     printf("OpenResourceFile(%04X) // file='%s' hFile=%04X !\n", 
@@ -242,6 +338,25 @@
     off_t rtoff;
 
     /*
+     * Check for loaded name table.
+     */
+    if (ResourceFileInfo->resnamtab != NULL)
+    {
+	RESNAMTAB *e;
+
+	for (e = ResourceFileInfo->resnamtab; e != NULL; e = e->next)
+	{
+	    if (e->type_ord == (type_id & 0x000f) &&
+		strcasecmp(e->id, resource_name) == 0)
+	    {
+		return FindResourceByNumber(result_p, type_id, e->id_ord);
+	    }
+	}
+
+	return -1;
+    }
+
+    /*
      * Move to beginning of resource table.
      */
     rtoff = (ResourceFileInfo->mz_header->ne_offset +
@@ -311,9 +426,7 @@
 			typeinfo.type_id, i + 1, typeinfo.count, 
 			name, resource_name);
 #endif
-/*		if (strcasecmp(name, resource_name) == 0) */
-		if (strcasecmp(name, resource_name) == 0 ||
-		(nameinfo.id == 0x8001 && type_id == NE_RSCTYPE_MENU))
+		if (strcasecmp(name, resource_name) == 0)
 		{
 		    memcpy(result_p, &nameinfo, sizeof(nameinfo));
 		    return size_shift;
@@ -794,6 +907,10 @@
 HANDLE
 RSC_LoadMenu(HANDLE instance, LPSTR menu_name)
 {
+#ifdef DEBUG_RESOURCE
+    printf("RSC_LoadMenu: instance = %04x, name = '%s'\n",
+	   instance, menu_name);
+#endif
     return RSC_LoadResource(instance, menu_name, NE_RSCTYPE_MENU, NULL);
 }
 
@@ -808,7 +925,8 @@
     HDC hdc;
     long *lp;
     int image_size;
-
+    int size;
+    
 #ifdef DEBUG_RESOURCE
     printf("LoadBitmap: instance = %04x, name = %08x\n",
 	   instance, bmp_name);
@@ -828,14 +946,73 @@
 	GlobalFree(rsc_mem);
 	return 0;
     }
-    if (*lp == sizeof(BITMAPCOREHEADER))
+    size = CONV_LONG (*lp);
+    if (size == sizeof(BITMAPCOREHEADER)){
+	CONV_BITMAPCOREHEADER (lp);
 	hbitmap = ConvertCoreBitmap( hdc, (BITMAPCOREHEADER *) lp );
-    else if (*lp == sizeof(BITMAPINFOHEADER))
+    } else if (size == sizeof(BITMAPINFOHEADER)){
+	CONV_BITMAPINFO (lp);
 	hbitmap = ConvertInfoBitmap( hdc, (BITMAPINFO *) lp );
-    else hbitmap = 0;
+    } else hbitmap = 0;
     GlobalFree(rsc_mem);
     ReleaseDC( 0, hdc );
     return hbitmap;
 }
+
+/**********************************************************************
+ *			CreateIcon [USER.407]
+ */
+HICON CreateIcon(HANDLE hInstance, int nWidth, int nHeight, 
+                 BYTE nPlanes, BYTE nBitsPixel, LPSTR lpANDbits, 
+                 LPSTR lpXORbits)
+{
+    HICON 	hIcon;
+    ICONALLOC	*lpico;
 
+#ifdef DEBUG_RESOURCE
+    printf("CreateIcon: hInstance = %04x, nWidth = %08x, nHeight = %08x \n",
+	    hInstance, nWidth, nHeight);
+    printf("  nPlanes = %04x, nBitsPixel = %04x,",nPlanes, nBitsPixel);
+    printf(" lpANDbits= %04x, lpXORbits = %04x, \n",lpANDbits, lpXORbits);
+#endif
 
+    if (hInstance == (HANDLE)NULL) { 
+        printf("CreateIcon / hInstance %04x not Found!\n",hInstance);
+        return 0;
+	}
+    hIcon = GlobalAlloc(GMEM_MOVEABLE, sizeof(ICONALLOC) + 1024);
+    if (hIcon == (HICON)NULL) {
+	printf("Can't allocate memory for Icon in CreateIcon\n");
+	return 0;
+	}
+    lpico= (ICONALLOC *)GlobalLock(hIcon);
+
+    lpico->descriptor.Width=nWidth;
+    lpico->descriptor.Height=nHeight;
+    lpico->descriptor.ColorCount=16; /* Dummy Value */ 
+    lpico->descriptor.Reserved1=0;
+    lpico->descriptor.Reserved2=nPlanes;
+    lpico->descriptor.Reserved3=nWidth*nHeight;
+
+    /* either nPlanes and/or nBitCount is set to one */
+    lpico->descriptor.icoDIBSize=nWidth*nHeight*nPlanes*nBitsPixel; 
+    lpico->descriptor.icoDIBOffset=0; 
+
+    if( !(lpico->hBitmap=CreateBitmap(nWidth, nHeight, nPlanes, nBitsPixel, 
+                                 lpXORbits)) ) {
+      printf("CreateIcon: couldn't create the XOR bitmap\n");
+      return(0);
+    }
+    
+    /* the AND BitMask is always monochrome */
+    if( !(lpico->hBitMask=CreateBitmap(nWidth, nHeight, 1, 1, lpANDbits)) ) {
+      printf("CreateIcon: couldn't create the AND bitmap\n");
+      return(0);
+    }
+
+    GlobalUnlock(hIcon);
+#ifdef DEBUG_RESOURCE
+    printf("CreateIcon Alloc hIcon=%X\n", hIcon);
+#endif
+    return hIcon;
+}
diff --git a/loader/selector.c b/loader/selector.c
index bea1886..834e252 100644
--- a/loader/selector.c
+++ b/loader/selector.c
@@ -1,12 +1,16 @@
+#ifndef WINELIB
 static char RCSId[] = "$Id: selector.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <errno.h>
+
 #ifdef __linux__
 #include <linux/unistd.h>
 #include <linux/head.h>
@@ -16,14 +20,16 @@
 #endif
 #if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <sys/mman.h>
+#include <machine/segments.h>
 #endif
-#include <errno.h>
+
 #include "neexe.h"
 #include "segmem.h"
-#include "prototypes.h"
 #include "wine.h"
+#include "windows.h"
+#include "prototypes.h"
 
-/* #define DEBUG_SELECTORS /* */
+/* #define DEBUG_SELECTORS */
 
 #ifdef linux
 #define DEV_ZERO
@@ -31,7 +37,6 @@
 #endif
 
 #if defined(__NetBSD__) || defined(__FreeBSD__)
-#include <machine/segments.h>
 #define PAGE_SIZE getpagesize()
 #define MODIFY_LDT_CONTENTS_DATA	0
 #define MODIFY_LDT_CONTENTS_STACK	1
@@ -214,8 +219,7 @@
  * This is very bad!!!  This function is implemented for Windows
  * compatibility only.  Do not call this from the emulation library.
  */
-unsigned int
-AllocSelector(unsigned int old_selector)
+WORD AllocSelector(WORD old_selector)
 {
     SEGDESC *s_new, *s_old;
     int i_new, i_old;
@@ -382,7 +386,7 @@
 /**********************************************************************
  *					AllocCStoDSAlias
  */
-AllocDStoCSAlias(unsigned int ds_selector)
+WORD AllocDStoCSAlias(WORD ds_selector)
 {
     unsigned int cs_selector;
     
@@ -396,7 +400,7 @@
 /**********************************************************************
  *					FreeSelector
  */
-unsigned int FreeSelector(unsigned int sel)
+WORD FreeSelector(WORD sel)
 {
     SEGDESC *s;
     int sel_idx;
@@ -694,10 +698,9 @@
 /**********************************************************************
  *					GetDOSEnvironment
  */
-void *
-GetDOSEnvironment()
+LPSTR GetDOSEnvironment(void)
 {
-    return EnvironmentSelector->base_addr;
+    return (LPSTR) EnvironmentSelector->base_addr;
 }
 
 /**********************************************************************
@@ -916,3 +919,4 @@
 
     return selectors;
 }
+#endif /* ifndef WINELIB */
diff --git a/loader/signal.c b/loader/signal.c
index be88b96..d788cc0 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -1,6 +1,8 @@
-#include <signal.h>
+#ifndef WINELIB
 #include <stdio.h>
 #include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
 #include <time.h>
 
 #if defined(__NetBSD__) || defined(__FreeBSD__)
@@ -8,14 +10,14 @@
 #else
 #include <syscall.h>
 #endif
-#include <signal.h>
-#include <errno.h>
 #ifdef linux
 #include <linux/sched.h>
 #include <asm/system.h>
 #endif
+
 #include "wine.h"
 #include "segmem.h"
+#include "prototypes.h"
  
 char * cstack[4096];
 struct sigaction segv_act;
@@ -40,92 +42,145 @@
 }
 
 #ifdef linux
-static void win_fault(int signal, struct sigcontext_struct context){
-        struct sigcontext_struct *scp = &context;
+static void win_fault(int signal, struct sigcontext_struct context)
+{
+    struct sigcontext_struct *scp = &context;
 #else
-static void win_fault(int signal, int code, struct sigcontext *scp){
+static void win_fault(int signal, int code, struct sigcontext *scp)
+{
 #endif
-	unsigned char * instr;
-	unsigned char intno;
-	unsigned int * dump;
-	int i;
+    unsigned char * instr;
+    unsigned int * dump;
+    int i;
 
 	/* First take care of a few preliminaries */
 #ifdef linux
-	if(signal != SIGSEGV) exit(1);
-	if((scp->sc_cs & 7) != 7){
+    if(signal != SIGSEGV) 
+	exit(1);
+    if((scp->sc_cs & 7) != 7)
+    {
 #endif
 #if defined(__NetBSD__) || defined(__FreeBSD__)
 /*         set_es(0x27); set_ds(0x27); */
-	if(signal != SIGBUS) exit(1);
-	if(scp->sc_cs == 0x1f){
-#endif
-		fprintf(stderr,
-			"Segmentation fault in Wine program (%x:%x)."
-			"  Please debug\n",
-			scp->sc_cs, scp->sc_eip);
-		goto oops;
-	};
-
-	/*  Now take a look at the actual instruction where the program
-	    bombed */
-	instr = (char *) SAFEMAKEPTR(scp->sc_cs, scp->sc_eip);
-
-	if(*instr != 0xcd) {
-		fprintf(stderr,
-			"Unexpected Windows program segfault"
-			" - opcode = %x\n", *instr);
-#if 0
-		return;
-#else
-		goto oops;
-#endif
-	};
-
-	instr++;
-	intno = *instr;
-	switch(intno){
-	case 0x21:
-		if(!do_int21(scp)) goto oops;
-		break;
-        case 0x11:  
-  		scp->sc_eax = (scp->sc_eax & 0xffff0000L) | DOS_GetEquipment();
-		break;
-        case 0x12:               
-          	scp->sc_eax = (scp->sc_eax & 0xffff0000L) | 640L; 
-          	break;				/* get base mem size */                
-	case 0x1A:
-		if(!do_int1A(scp)) goto oops;
-		break;
-	default:
-		fprintf(stderr,"Unexpected Windows interrupt %x\n", intno);
-		goto oops;
-	};
-
-	/* OK, done handling the interrupt */
-
-	scp->sc_eip += 2;  /* Bypass the int instruction */
-	return;
- oops:
-	fprintf(stderr,"In win_fault %x:%x\n", scp->sc_cs, scp->sc_eip);
-#ifdef linux
-	wine_debug(scp);  /* Enter our debugger */
-#else
-	fprintf(stderr,"Stack: %x:%x\n", scp->sc_ss, scp->sc_esp);
-	dump = (int*) scp;
-	for(i=0; i<22; i++) 
-	{
-	    fprintf(stderr," %8.8x", *dump++);
-	    if ((i % 8) == 7)
-		fprintf(stderr,"\n");
-	}
-	fprintf(stderr,"\n");
+    if(signal != SIGBUS) 
 	exit(1);
+    if(scp->sc_cs == 0x1f)
+    {
+#endif
+	fprintf(stderr,
+		"Segmentation fault in Wine program (%x:%x)."
+		"  Please debug\n",
+		scp->sc_cs, scp->sc_eip);
+	goto oops;
+    };
+
+    /*  Now take a look at the actual instruction where the program
+	bombed */
+    instr = (unsigned char *) SAFEMAKEPTR(scp->sc_cs, scp->sc_eip);
+
+    switch(*instr)
+    {
+      case 0xcd: /* int <XX> */
+            instr++;
+	    switch(*instr)
+	    {
+	      case 0x10:
+		if(!do_int10(scp)) 
+		    goto oops;
+		break;
+
+	      case 0x11:  
+		scp->sc_eax = (scp->sc_eax & 0xffff0000L) | DOS_GetEquipment();
+		break;
+
+	      case 0x12:               
+		scp->sc_eax = (scp->sc_eax & 0xffff0000L) | 640L; 
+		break;				/* get base mem size */                
+
+	      case 0x1A:
+		if(!do_int1A(scp)) 
+		    goto oops;
+		break;
+
+	      case 0x21:
+		if (!do_int21(scp)) 
+		    goto oops;
+		break;
+
+	      case 0x22:
+		scp->sc_eax = 0x1234;
+		scp->sc_ebx = 0x5678;
+		scp->sc_ecx = 0x9abc;
+		scp->sc_edx = 0xdef0;
+		break;
+
+	      case 0x25:
+		if (!do_int25(scp)) 
+		    goto oops;
+		break;
+
+	      case 0x26:
+		if (!do_int26(scp)) 
+		    goto oops;
+		break;
+		
+	      default:
+		fprintf(stderr,"Unexpected Windows interrupt %x\n", *instr);
+		goto oops;
+	    }
+	    scp->sc_eip += 2;  /* Bypass the int instruction */
+            break;
+            
+      case 0xec: /* inb al,dx */
+            inportb(scp);
+	    scp->sc_eip++;
+            break;
+
+      case 0xed: /* in ax,dx */
+            inport(scp);
+	    scp->sc_eip++;  
+            break;
+
+      case 0xee: /* outb dx,al */
+            outportb(scp);
+	    scp->sc_eip++;
+            break;
+      
+      case 0xef: /* out dx,ax */
+            outport(scp);
+	    scp->sc_eip++;
+            break;
+
+      default:
+		fprintf(stderr, "Unexpected Windows program segfault"
+			" - opcode = %x\n", *instr);
+		goto oops;
+    }
+    
+    /* OK, done handling the interrupt */
+
+    return;
+
+  oops:
+    fprintf(stderr,"In win_fault %x:%x\n", scp->sc_cs, scp->sc_eip);
+#ifdef linux
+    wine_debug(scp);  /* Enter our debugger */
+#else
+    fprintf(stderr,"Stack: %x:%x\n", scp->sc_ss, scp->sc_esp);
+    dump = (int*) scp;
+    for(i=0; i<22; i++) 
+    {
+	fprintf(stderr," %8.8x", *dump++);
+	if ((i % 8) == 7)
+	    fprintf(stderr,"\n");
+    }
+    fprintf(stderr,"\n");
+    exit(1);
 #endif
 }
 
-int
-init_wine_signals(){
+int init_wine_signals(void)
+{
 #ifdef linux
 	segv_act.sa_handler = (__sighandler_t) win_fault;
 	/* Point to the top of the stack, minus 4 just in case, and make
@@ -155,3 +210,4 @@
 #endif
 }
 
+#endif /* ifndef WINELIB */
diff --git a/loader/wine.c b/loader/wine.c
index 26936da..4edecaa 100644
--- a/loader/wine.c
+++ b/loader/wine.c
@@ -49,7 +49,6 @@
 
 static char *DLL_Extensions[] = { "dll", "exe", NULL };
 static char *EXE_Extensions[] = { "exe", NULL };
-static char *WinePath = NULL;
 
 FILE *SpyFp = NULL;
 
@@ -137,7 +136,7 @@
     if (FindFile(buffer, sizeof(buffer), modulename, (filetype == EXE ? 
     	EXE_Extensions : DLL_Extensions), WindowsPath) ==NULL)
     {
-    	fprintf(stderr,"LoadImage: I can't find %s !\n",modulename);
+    	fprintf(stderr, "LoadImage: I can't find %s.dll | %s.exe !\n",modulename, modulename);
 	return (HINSTANCE) NULL;
     }
     fprintf(stderr,"LoadImage: loading %s (%s)\n", modulename, buffer);
@@ -155,6 +154,7 @@
       wpnt1->next  = wpnt;
     };
     wpnt->next = NULL;
+    wpnt->resnamtab = (RESNAMTAB *) -1;
 
     /*
      * Open file for reading.
@@ -248,8 +248,6 @@
      */
     for(i=0; i<wpnt->ne_header->n_mod_ref_tab; i++){
       char buff[14];
-      char buff2[256];
-      int  fd, j;
       GetModuleName(wpnt, i + 1, buff);
       
 #ifndef WINELIB
@@ -265,37 +263,26 @@
 }
 
 
+#ifndef WINELIB
 /**********************************************************************
  *					main
  */
-_WinMain(int argc, char **argv)
+int _WinMain(int argc, char **argv)
 {
 	int segment;
 	char *p;
 	char *sysresname;
 	char filename[100];
-	char syspath[256];
-	char exe_path[256];
 #ifdef WINESTAT
 	char * cp;
 #endif
 	struct w_files * wpnt;
 	int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
-	int i;
 	int rv;
 
 	Argc = argc - 1;
 	Argv = argv + 1;
 	
-	WinePath = malloc(1024);
-	
-	getcwd(WinePath, 512);
-	
-	if ((p = getenv("WINEPATH")) != NULL) { 
-		strcat(WinePath, ";");
-		strcat(WinePath, p);
-	}
-	
 	if (LoadImage(Argv[0], EXE) == (HINSTANCE) NULL ) {
 		fprintf(stderr, "wine: can't find %s!.\n", Argv[0]);
 		exit(1);
@@ -393,6 +380,7 @@
 	}
     }
 }
+#endif
 
 
 /**********************************************************************
@@ -402,10 +390,8 @@
 GetImportedName(int fd, struct mz_header_s *mz_header, 
 		struct ne_header_s *ne_header, int name_offset, char *buffer)
 {
-    char *p;
     int length;
     int status;
-    int i;
     
     status = lseek(fd, mz_header->ne_offset + ne_header->iname_tab_offset +
 		   name_offset, SEEK_SET);
@@ -426,7 +412,6 @@
     int fd = wpnt->fd;
     struct mz_header_s *mz_header = wpnt->mz_header; 
     struct ne_header_s *ne_header = wpnt->ne_header;
-    char *p;
     int length;
     WORD name_offset, status;
     int i;
@@ -714,16 +699,4 @@
     return 0;
 }
 
-/**********************************************************************
- *					GetProcAddress
- */
-FARPROC GetProcAddress(HINSTANCE hinstance, char *proc_name)
-{
-    if ((int) proc_name & 0xffff0000)
-	printf("GetProcAddress: %#04x, '%s'\n", hinstance, proc_name);
-    else
-	printf("GetProcAddress: %#04x, %d\n", hinstance, (int) proc_name);
-
-    return NULL;
-}
 #endif
diff --git a/memory/global.c b/memory/global.c
index 76b558f..11ab363 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -1,8 +1,11 @@
 static char RCSId[] = "$Id: global.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 
+#define GLOBAL_SOURCE
+
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include "prototypes.h"
 #include "heap.h"
 #include "segmem.h"
@@ -153,7 +156,7 @@
 /**********************************************************************
  *					GlobalAlloc
  */
-unsigned int
+HANDLE
 GlobalAlloc(unsigned int flags, unsigned long size)
 {
     GDESC *g;
@@ -258,7 +261,7 @@
  * Windows programs will pass a handle in the "block" parameter, but
  * this function will also accept a 32-bit address.
  */
-unsigned int
+HANDLE
 GlobalFree(unsigned int block)
 {
     GDESC *g;
@@ -269,18 +272,7 @@
     /*
      * Find GDESC for this block.
      */
-    if (block & 0xffff0000)
-    {
-	for (g = GlobalList; g != NULL; g = g->next)
-	    if (g->handle > 0 && (unsigned int) g->addr == block)
-		break;
-    }
-    else
-    {
-	for (g = GlobalList; g != NULL; g = g->next)
-	    if (g->handle == block)
-		break;
-    }
+    g = GlobalGetGDesc(block);
     if (g == NULL)
 	return block;
 
@@ -556,12 +548,7 @@
     /*
      * Find GDESC for this block.
      */
-    for (g = GlobalList; g != NULL; g = g->next)
-    {
-	if (g->handle == block)
-	    break;
-    }
-
+    g = GlobalGetGDesc(block);
     if (g == NULL)
 	return 0;
     
@@ -733,6 +720,70 @@
     else
 	return g->handle;
 }
+
+/**********************************************************************
+ *                      GetFreeSpace (kernel.169)
 
+ */
+DWORD GetFreeSpace(UINT wFlags)
+/* windows 3.1 doesn't use the wFlags parameter !! 
+   (so I won't either)                            */
+{
+    GDESC *g;
+    unsigned char free_map[512];
+    unsigned int max_selector_used = 0;
+    unsigned int i;
+    unsigned int selector;
+    int total_free;
 
+    /*
+     * Initialize free list to all items not controlled by GlobalAlloc()
+     */
+    for (i = 0; i < 512; i++)
+	free_map[i] = -1;
 
+    /*
+     * Traverse table looking for used and free selectors.
+     */
+    for (g = GlobalList; g != NULL; g = g->next)
+    {
+	/*
+	 * Check for free segments.
+	 */
+	if (g->sequence == -1)
+	{
+	    free_map[g->handle >> 3] = 1;
+	    if (g->handle > max_selector_used)
+		max_selector_used = g->handle;
+	}
+
+	/*
+	 * Check for heap allocated segments.
+	 */
+	else if (g->handle == 0)
+	{
+	    selector = (unsigned int) g->addr >> 16;
+	    free_map[selector >> 3] = 0;
+	    if (selector > max_selector_used)
+		max_selector_used = selector;
+	}
+    }
+
+    /*
+     * All segments past the biggest selector used are free.
+     */
+    for (i = (max_selector_used >> 3) + 1; i < 512; i++)
+	free_map[i] = 1;
+
+    /*
+     * Add up the total free segments (obviously this amount of memory
+       may not be contiguous, use GlobalCompact to get largest contiguous
+       memory available).
+     */
+    total_free=0;
+    for (i = 0; i < 512; i++)
+	if (free_map[i] == 1)
+	    total_free++;
+    
+    return total_free << 16;
+}
diff --git a/memory/heap.c b/memory/heap.c
index 18f50a4..71cb561 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -3,17 +3,13 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include "prototypes.h"
 #include "segmem.h"
 #include "heap.h"
 #include "regfunc.h"
 
-typedef struct heap_local_heap_s
-{
-    struct heap_local_heap_s *next;
-    MDESC *free_list;
-    unsigned short selector;
-} LHEAP;
+/* #define DEBUG_HEAP */
 
 LHEAP *LocalHeaps = NULL;
 
@@ -23,6 +19,9 @@
 void
 HEAP_Init(MDESC **free_list, void *start, int length)
 {
+    if (length < 2 * sizeof(MDESC))
+	return;
+    
     *free_list = (MDESC *) start;
     (*free_list)->prev = NULL;
     (*free_list)->next = NULL;
@@ -302,8 +301,6 @@
     return NULL;
 }
 
-#define LOCALHEAP() (&HEAP_LocalFindHeap(Segments[Stack16Frame[11] >> 3].owner)->free_list)
-
 /**********************************************************************
  *					HEAP_LocalInit
  */
@@ -316,43 +313,47 @@
     printf("HEAP_LocalInit: owner %04x, start %08x, length %04x\n",
 	   owner, start, length);
 #endif
+
+    if (length < 2 * sizeof(MDESC))
+	return;
     
     lh = (LHEAP *) malloc(sizeof(*lh));
     if (lh == NULL)
 	return;
     
-    lh->selector = owner;
-    lh->next = LocalHeaps;
+    lh->next        = LocalHeaps;
+    lh->selector    = owner;
+    lh->local_table = NULL;
     HEAP_Init(&lh->free_list, start, length);
     LocalHeaps = lh;
 }
 
 /**********************************************************************
- *					LocalAlloc
+ *					WIN16_LocalAlloc
  */
 void *
-LocalAlloc(int flags, int bytes)
+WIN16_LocalAlloc(int flags, int bytes)
 {
     void *m;
     
 #ifdef DEBUG_HEAP
-    printf("LocalAlloc: flags %x, bytes %d\n", flags, bytes);
+    printf("WIN16_LocalAlloc: flags %x, bytes %d\n", flags, bytes);
     printf("    called from segment %04x\n", Stack16Frame[11]);
 #endif
 
     m = HEAP_Alloc(LOCALHEAP(), flags, bytes);
 	
 #ifdef DEBUG_HEAP
-	printf("LocalAlloc: returning %x\n", (int) m);
+	printf("WIN16_LocalAlloc: returning %x\n", (int) m);
 #endif
     return m;
 }
 
 /**********************************************************************
- *					LocalCompact
+ *					WIN16_LocalCompact
  */
 int
-LocalCompact(int min_free)
+WIN16_LocalCompact(int min_free)
 {
     MDESC *m;
     int max_block;
@@ -366,10 +367,10 @@
 }
 
 /**********************************************************************
- *					LocalFlags
+ *					WIN16_LocalFlags
  */
 unsigned int
-LocalFlags(unsigned int handle)
+WIN16_LocalFlags(unsigned int handle)
 {
     MDESC *m;
     
@@ -382,10 +383,10 @@
 }
 
 /**********************************************************************
- *					LocalFree
+ *					WIN16_LocalFree
  */
 unsigned int 
-LocalFree(unsigned int handle)
+WIN16_LocalFree(unsigned int handle)
 {
     unsigned int addr;
     
@@ -397,12 +398,12 @@
 }
 
 /**********************************************************************
- *					LocalInit
+ *					WIN16_LocalInit
  */
 unsigned int
-LocalInit(unsigned int segment, unsigned int start, unsigned int end)
+WIN16_LocalInit(unsigned int segment, unsigned int start, unsigned int end)
 {
-    unsigned short owner = Segments[Stack16Frame[11] >> 3].owner;
+    unsigned short owner = HEAP_OWNER;
     LHEAP *lh = HEAP_LocalFindHeap(owner);
     
     if (segment == 0)
@@ -426,10 +427,10 @@
 }
 
 /**********************************************************************
- *					LocalLock
+ *					WIN16_LocalLock
  */
 void *
-LocalLock(unsigned int handle)
+WIN16_LocalLock(unsigned int handle)
 {
     MDESC *m;
     
@@ -443,10 +444,10 @@
 }
 
 /**********************************************************************
- *					LocalReAlloc
+ *					WIN16_LocalReAlloc
  */
 void *
-LocalReAlloc(unsigned int handle, int flags, int bytes)
+WIN16_LocalReAlloc(unsigned int handle, int flags, int bytes)
 {
     void *m;
     
@@ -458,10 +459,10 @@
 }
 
 /**********************************************************************
- *					LocalSize
+ *					WIN16_LocalSize
  */
 unsigned int
-LocalSize(unsigned int handle)
+WIN16_LocalSize(unsigned int handle)
 {
     MDESC *m;
     
@@ -474,10 +475,10 @@
 }
 
 /**********************************************************************
- *					LocalUnlock
+ *					WIN16_LocalUnlock
  */
 unsigned int
-LocalUnlock(unsigned int handle)
+WIN16_LocalUnlock(unsigned int handle)
 {
     MDESC *m;
     
@@ -491,3 +492,49 @@
 
     return 0;
 }
+
+/**********************************************************************
+ *                      GetFreeSystemResources (user.284)
+
+ */
+#define USERRESOURCES 2
+#define GDIRESOURCES 1
+#define SYSTEMRESOURCES 0
+#include <user.h>
+#include <gdi.h>
+
+WORD GetFreeSystemResources(WORD SystemResourceType)
+{
+  unsigned int GdiFree=0,GdiResult=0;
+  unsigned int UserFree=0,UserResult=0;
+  unsigned int result=0;
+  MDESC *m;
+
+  printf("GetFreeSystemResources(%u)\n",SystemResourceType);
+
+  switch(SystemResourceType) {
+    case(USERRESOURCES):
+      for (m = USER_Heap; m != NULL; m = m->next) /* add up free area in heap */
+         UserFree += m->length;
+      result=(UserFree*100)/65516;  /* 65516 == 64K */
+      break;
+    case(GDIRESOURCES):
+      for (m = GDI_Heap; m != NULL; m = m->next)
+         GdiFree += m->length;
+      result=(GdiFree*100)/65516;
+      break;
+    case(SYSTEMRESOURCES):
+      for (m = USER_Heap; m != NULL; m = m->next)
+         UserFree += m->length;
+      UserResult=(UserFree*100)/65516;
+      for (m = GDI_Heap; m != NULL; m = m->next)
+         GdiFree += m->length;
+      GdiResult=(GdiFree*100)/65516;
+      result=(UserResult < GdiResult) ? UserResult:GdiResult; 
+      break;
+    default:
+      result=0;
+      break;
+  }
+  return(result);
+}
diff --git a/memory/linear.c b/memory/linear.c
index af403e2..1bceeaa 100644
--- a/memory/linear.c
+++ b/memory/linear.c
@@ -3,6 +3,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include "prototypes.h"
 #include "heap.h"
 #include "segmem.h"
diff --git a/misc/Imakefile b/misc/Imakefile
index 43ee484..2979b52 100644
--- a/misc/Imakefile
+++ b/misc/Imakefile
@@ -16,9 +16,9 @@
 	message.c \
 	profile.c \
 	rect.c \
-	resource.c \
 	sound.c \
 	spy.c \
+	stress.c \
 	user.c \
 	winsocket.c
 
diff --git a/misc/atom.c b/misc/atom.c
index 79db3b9..f8f7d07 100644
--- a/misc/atom.c
+++ b/misc/atom.c
@@ -7,13 +7,6 @@
 /*
  * 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.
@@ -30,22 +23,35 @@
  * aligned block. Needed to test the Library.
  */
 
-#include <ctype.h>
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "user.h"
 #include "atom.h"
-
+#include "prototypes.h"
+#ifndef WINELIB
+#include "heap.h"
+#endif
 
 #define DEFAULT_ATOMTABLE_SIZE    37
 #define MIN_STR_ATOM              0xc000
 
+#ifdef WINELIB
+#define ATOMTOHANDLE
+#define HANDLETOATOM
+#else
 #define ATOMTOHANDLE(atom)        ((HANDLE)(atom) << 2)
 #define HANDLETOATOM(handle)      ((ATOM)(0xc000 | ((handle) >> 2)))
+#endif
 
-
+#ifdef WINELIB
 static ATOMTABLE * localTable = NULL;
+#undef LOCALATOMTABLE
+#define LOCALATOMTABLE() &localTable
+#endif
+
 static ATOMTABLE * globalTable = NULL;
 
 
@@ -56,18 +62,31 @@
 {
     int i;
     HANDLE handle;
+
+    if (table == &globalTable)
+    {
+	handle = USER_HEAP_ALLOC(LMEM_MOVEABLE, sizeof(ATOMTABLE) +
+				 (entries-1) * sizeof(HANDLE) );
+	if (!handle) 
+	    return FALSE;
+	*table = (ATOMTABLE *) USER_HEAP_ADDR( handle );
+    }
+    else
+    {
+	handle = LocalAlign ( LMEM_MOVEABLE, sizeof(ATOMTABLE) +
+			     (entries-1) * sizeof(HANDLE) );
+	if (!handle) 
+	    return FALSE;
+	*table = (ATOMTABLE *) LocalLock( handle );
+    }
     
-    handle = LocalAlign ( 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;
+    for (i = 0; i < entries; i++) 
+	(*table)->entries[i] = 0;
     return TRUE;
     
 }
 
-
 /***********************************************************************
  *           ATOM_Init
  *
@@ -87,7 +106,11 @@
  */
 static ATOMENTRY * ATOM_MakePtr( ATOMTABLE * table, HANDLE handle )
 {
+#ifdef WINELIB
+    return (ATOMENTRY *) LocalLock (handle);
+#else
     return (ATOMENTRY *) (((int)table & 0xffff0000) | (int)handle);
+#endif
 }
 
 
@@ -132,8 +155,18 @@
 	}
 	entry = entryPtr->next;
     }
+
+    if (table == globalTable)
+    {
+	entry = (int) USER_HEAP_ALLOC(LMEM_MOVEABLE, 
+				      sizeof(ATOMENTRY)+len-1 ) & 0xffff;
+    }
+    else
+    {
+	entry = (int) LocalAlign(LMEM_MOVEABLE, 
+				 sizeof(ATOMENTRY)+len-1 ) & 0xffff;
+    }
     
-    entry = (int)LocalAlign( LMEM_MOVEABLE, sizeof(ATOMENTRY)+len-1 ) & 0xffff;
     if (!entry) return 0;
     entryPtr = ATOM_MakePtr( table, entry );
     entryPtr->next = table->entries[hash];
@@ -173,7 +206,10 @@
     if (--entryPtr->refCount == 0)
     {
 	*prevEntry = entryPtr->next;	
-	USER_HEAP_FREE( entry );
+	if (table == globalTable)
+	    USER_HEAP_FREE(entry);
+	else
+	    LocalFree( entry );
     }    
     return 0;
 }
@@ -246,7 +282,7 @@
  */
 BOOL InitAtomTable( WORD entries )
 {
-    return ATOM_InitTable( &localTable, entries );
+    return ATOM_InitTable( LOCALATOMTABLE(), entries );
 }
 
 
@@ -265,8 +301,8 @@
  */
 ATOM AddAtom( LPCSTR str )
 {
-    if (!localTable) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
-    return ATOM_AddAtom( localTable, str );
+    if (!*LOCALATOMTABLE()) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
+    return ATOM_AddAtom( *LOCALATOMTABLE(), str );
 }
 
 
@@ -275,8 +311,8 @@
  */
 ATOM DeleteAtom( ATOM atom )
 {
-    if (!localTable) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
-    return ATOM_DeleteAtom( localTable, atom );
+    if (!*LOCALATOMTABLE()) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
+    return ATOM_DeleteAtom( *LOCALATOMTABLE(), atom );
 }
 
 
@@ -285,8 +321,8 @@
  */
 ATOM FindAtom( LPCSTR str )
 {
-    if (!localTable) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
-    return ATOM_FindAtom( localTable, str );
+    if (!*LOCALATOMTABLE()) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
+    return ATOM_FindAtom( *LOCALATOMTABLE(), str );
 }
 
 
@@ -295,8 +331,8 @@
  */
 WORD GetAtomName( ATOM atom, LPSTR buffer, short count )
 {
-    if (!localTable) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
-    return ATOM_GetAtomName( localTable, atom, buffer, count );
+    if (!*LOCALATOMTABLE()) InitAtomTable( DEFAULT_ATOMTABLE_SIZE );
+    return ATOM_GetAtomName( *LOCALATOMTABLE(), atom, buffer, count );
 }
 
 
diff --git a/misc/clipboard.c b/misc/clipboard.c
index f62d083..17cca79 100644
--- a/misc/clipboard.c
+++ b/misc/clipboard.c
@@ -10,6 +10,8 @@
 #define DEBUG_CLIPBOARD
 */
 
+#include <stdlib.h>
+#include <stdio.h>
 #include <windows.h>
 #include <sys/types.h>
 #include <sys/stat.h>
diff --git a/misc/comm.c b/misc/comm.c
index 84cc620..0a51b77 100644
--- a/misc/comm.c
+++ b/misc/comm.c
@@ -8,11 +8,14 @@
 #include <fcntl.h>
 #include <string.h>
 #include <errno.h>
+#include <ctype.h>
 #include <sys/stat.h>
 #if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <errno.h>
 #include <sys/ioctl.h>
 #endif
+#include <unistd.h>
+
 #include "wine.h"
 #include "windows.h"
 
@@ -38,7 +41,7 @@
 void Comm_Init(void)
 {
 	int x, serial = 0, parallel = 0;
-	char option[10], temp[256], *ptr;
+	char option[10], temp[256];
 	struct stat st;
 
 	for (x=0; x!=MAX_PORTS; x++) {
@@ -145,10 +148,10 @@
 	/*  012345		*/
 
 	int port;
-	char *ptr, *ptr2, temp[256],temp2[10];
+	char *ptr, temp[256];
 
 #ifdef DEBUG_COMM
-fprintf(stderr,"BuildCommDCB: (%s), ptr %d\n", device, lpdcb);
+fprintf(stderr,"BuildCommDCB: (%s), ptr %d\n", device, (long) lpdcb);
 #endif
 	commerror = 0;
 
@@ -296,8 +299,6 @@
 
 int CloseComm(int fd)
 {
-	int status;
-
 #ifdef DEBUG_COMM
 fprintf(stderr,"CloseComm: fd %d\n", fd);
 #endif	
@@ -477,7 +478,7 @@
 	struct termios port;
 
 #ifdef DEBUG_COMM
-fprintf(stderr,"SetCommState: fd %d, ptr %d\n", lpdcb->Id, lpdcb);
+fprintf(stderr,"SetCommState: fd %d, ptr %d\n", lpdcb->Id, (long) lpdcb);
 #endif	
 
 	if (tcgetattr(lpdcb->Id, &port) == -1) {
@@ -666,7 +667,7 @@
 	struct termios port;
 
 #ifdef DEBUG_COMM
-fprintf(stderr,"GetCommState: fd %d, ptr %d\n", fd, lpdcb);
+fprintf(stderr,"GetCommState: fd %d, ptr %d\n", fd, (long) lpdcb);
 #endif
 
 	if (tcgetattr(fd, &port) == -1) {
@@ -836,7 +837,7 @@
 	struct DosDeviceStruct *ptr;
 
 #ifdef DEBUG_COMM
-fprintf(stderr,"ReadComm: fd %d, ptr %d, length %d\n", fd, lpvBuf, cbRead);
+fprintf(stderr,"ReadComm: fd %d, ptr %d, length %d\n", fd, (long) lpvBuf, cbRead);
 #endif	
 
 	if ((ptr = GetDeviceStruct(fd)) == NULL) {
@@ -875,7 +876,7 @@
 	struct DosDeviceStruct *ptr;
 
 #ifdef DEBUG_COMM
-fprintf(stderr,"WriteComm: fd %d, ptr %d, length %d\n", fd, lpvBuf, cbWrite);
+fprintf(stderr,"WriteComm: fd %d, ptr %d, length %d\n", fd, (long) lpvBuf, cbWrite);
 #endif
 	
 	if ((ptr = GetDeviceStruct(fd)) == NULL) {
diff --git a/misc/cursor.c b/misc/cursor.c
index 931d538..fa2d0ec 100644
--- a/misc/cursor.c
+++ b/misc/cursor.c
@@ -7,14 +7,15 @@
 #define DEBUG_CURSOR
 */
 
-#include <X11/cursorfont.h>
-#include <X11/Xlib.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <X11/cursorfont.h>
+#include <X11/Xlib.h>
 #include "prototypes.h"
 #include "windows.h"
 #include "win.h"
@@ -28,6 +29,7 @@
 RECT	ClipCursorRect;
 extern HINSTANCE hSysRes;
 extern Window winHasCursor;
+extern int desktopX, desktopY;   /* misc/main.c */
 
 static struct { LPSTR name; HCURSOR cursor; } system_cursor[] =
 {
@@ -116,6 +118,11 @@
 		lpcur->xcursor = XCreateFontCursor(XT_display, XC_sb_h_double_arrow);
 		GlobalUnlock(hCursor);
 	    	return hCursor;
+            case IDC_SIZENWSE:
+            case IDC_SIZENESW:
+                lpcur->xcursor = XCreateFontCursor(XT_display, XC_fleur);
+                GlobalUnlock(hCursor);
+                return hCursor;
 	    default:
 		break;
 	    }
@@ -358,19 +365,10 @@
  */
 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);
+    XWarpPointer( display, None, rootWindow, 0, 0, 0, 0, x, y );
 }
 
 
@@ -383,15 +381,19 @@
     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);
+
+    if (!lpRetPoint) return;
+    if (!XQueryPointer( display, rootWindow, &root, &child,
+		        &rootX, &rootY, &childX, &childY, &mousebut ))
+	lpRetPoint->x = lpRetPoint->y = 0;
+    else
+    {
+	lpRetPoint->x = rootX + desktopX;
+	lpRetPoint->y = rootY + desktopY;
+    }
 #ifdef DEBUG_CURSOR
-	printf("GetCursorPos // x=%d y=%d\n", rootX, rootY);
+	printf("GetCursorPos // x=%d y=%d\n", lpRetPoint->x, lpRetPoint->y);
 #endif
-	lpRetPoint->x = rootX;
-	lpRetPoint->y = rootY;
-    	}
 }
 
 
diff --git a/misc/dos_fs.c b/misc/dos_fs.c
index cc220c4..9c9e9ef 100644
--- a/misc/dos_fs.c
+++ b/misc/dos_fs.c
@@ -10,6 +10,11 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <pwd.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <fcntl.h>
+
 #if defined(__linux__) || defined(sun)
 #include <sys/vfs.h>
 #endif
@@ -17,27 +22,23 @@
 #include <sys/types.h>
 #include <sys/mount.h>
 #endif
-#include <dirent.h>
-#include "windows.h"
-#include "wine.h"
-#include "int21.h"
 
-/*
- #define DEBUG 
-*/
+#include "windows.h"
+#include "msdos.h"
+#include "prototypes.h"
+#include "autoconf.h"
+
+/* #define DEBUG */
+
+#define WINE_INI_USER "~/.winerc"
 #define MAX_OPEN_DIRS 16
+#define MAX_DOS_DRIVES	26
 
 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;
+static int CurrentDrive = 2;
 
 struct DosDriveStruct {			/*  eg: */
 	char 		*rootdir;	/*  /usr/windows 	*/
@@ -47,9 +48,35 @@
 	int 		disabled;	/*  0			*/
 };
 
-struct DosDriveStruct DosDrives[MAX_DOS_DRIVES];
+static struct DosDriveStruct DosDrives[MAX_DOS_DRIVES];
+static struct dosdirent DosDirs[MAX_OPEN_DIRS];
 
-struct dosdirent DosDirs[MAX_OPEN_DIRS];
+static void ExpandTildeString(char *s)
+{
+	struct passwd *entry;
+	char temp[1024], *ptr = temp;
+	
+	strcpy(temp, s);
+	while (*ptr)
+	{
+		if (*ptr != '~') { 
+			*s++ = *ptr++;
+			continue;
+		}
+		ptr++;
+		if ( (entry = getpwuid(getuid())) == NULL) {
+			continue;
+		}
+		strcpy(s, entry->pw_dir);
+		s += strlen(entry->pw_dir);
+	}
+}
+
+void ChopOffSlash(char *path)
+{
+	if (path[strlen(path)-1] == '/' || path[strlen(path)-1] == '\\')
+		path[strlen(path)-1] = '\0';
+}
 
 void DOS_InitFS(void)
 {
@@ -68,10 +95,17 @@
 	GetPrivateProfileString("wine", "path", "c:\\windows;c:\\windows\\system", 
 		WindowsPath, sizeof(WindowsPath), WINE_INI);
 
+	ChopOffSlash(WindowsDirectory);
 	ToDos(WindowsDirectory);
+
+	ChopOffSlash(SystemDirectory);
 	ToDos(SystemDirectory);
+
+	ChopOffSlash(TempDirectory);
 	ToDos(TempDirectory);
+
 	ToDos(WindowsPath);
+	ExpandTildeString(WindowsPath);
 
 	for (x=0; x!=MAX_DOS_DRIVES; x++) {
 		DosDrives[x].serialnumber = (0xEB0500L | x);
@@ -86,16 +120,15 @@
 			DosDrives[x].disabled = 1;
 			continue;
 		}
-
+		ExpandTildeString(temp);
 		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';
+			ChopOffSlash(temp);
 			DosDrives[x].rootdir = ptr;
 			strcpy(DosDrives[x].rootdir, temp);
-			strcpy(DosDrives[x].cwd, "/");
+			strcpy(DosDrives[x].cwd, "/windows/");
 			strcpy(DosDrives[x].label, "DRIVE-");
 			strcat(DosDrives[x].label, drive);
 			DosDrives[x].disabled = 0;
@@ -130,27 +163,6 @@
 #endif
 }
 
-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;
@@ -214,40 +226,51 @@
 	return( CurrentDrive);
 }
 
-int DOS_SetDefaultDrive(int drive)
+void DOS_SetDefaultDrive(int drive)
 {
 #ifdef DEBUG
 	fprintf(stderr,"SetDefaultDrive to %c:\n",'A'+drive);
 #endif
 
-	if (!DOS_ValidDrive(drive))
-		return 1;
-		
-	CurrentDrive = drive;
+	if (DOS_ValidDrive(drive))
+		CurrentDrive = drive;
 }
 
 void ToUnix(char *s)
 {
-	while (*s) {
-	        if (*s == '/')
-		    break;
- 		if (*s == '\\')
-			*s = '/';		
-		if (isupper(*s))
-			*s = tolower(*s);
-	s++;
+	/*  \WINDOWS\\SYSTEM   =>   /windows/system */
+
+	char *p;
+
+	for (p = s; *p; p++) 
+	{
+		if (*p != '\\')
+			*s++ = tolower(*p);
+		else {
+			*s++ = '/';
+			if (*(p+1) == '/' || *(p+1) == '\\')
+				p++;
+		}
 	}
+	*s = '\0';
 }
 
 void ToDos(char *s)
 {
-	while (*s) {
-		if (*s == '/')
-			*s = '\\';		
-		if (islower(*s))
-			*s = toupper(*s);
-	s++;
+	/* /windows//system   =>   \WINDOWS\SYSTEM */
+
+	char *p;
+	for (p = s; *p; p++) 
+	{
+		if (*p != '/')
+			*s++ = toupper(*p);
+		else {
+			*s++ = '\\';
+			if (*s == '/' || *s == '\\') 
+			    p++;
+		}
 	}
+	*s = '\0';
 }
 
 int DOS_DisableDrive(int drive)
@@ -272,9 +295,9 @@
 	return 1;
 }
 
-void GetUnixDirName(char *rootdir, char *name)
+static void GetUnixDirName(char *rootdir, char *name)
 {
-	int filename;
+	int filename = 1;
 	char *nameptr, *cwdptr;
 	
 	cwdptr = rootdir + strlen(rootdir);
@@ -299,7 +322,6 @@
 						*(cwdptr+1) = '\0';
 						goto next;
 					}
-					
 				}
 				goto next;
 			}
@@ -330,13 +352,12 @@
 */
 }
 
-char *GetDirectUnixFileName(char *dosfilename)
+char *GetUnixFileName(char *dosfilename)
 { 
-	/*   a:\windows\system.ini  =>  /dos/windows/system.ini   */
+	/*   a:\windows\system.ini  =>  /dos/windows/system.ini */
 	
-	static char temp[256];
+	char temp[256];
 	int drive;
-	char x;
 
 	if (dosfilename[1] == ':') 
 	{
@@ -349,59 +370,22 @@
 	} else
 		drive = CurrentDrive;
 
-	strcpy(temp,DosDrives[drive].rootdir);
+	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);
+	fprintf(stderr,"GetUnixFileName: %s => %s\n", 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)
+char *DOS_GetCurrentDir(int drive)
 { 
-	/* should return 'windows\system' */
+	/* should return 'WINDOWS\SYSTEM' */
 
 	char temp[256];
 
@@ -410,25 +394,29 @@
 	
 	strcpy(temp, DosDrives[drive].cwd);
 	ToDos(temp);
-
-	if (temp[strlen(temp)-1] == '\\')
-		temp[strlen(temp)] = '\0';	
+	fprintf(stderr, "2 %s\n", temp);
+	ChopOffSlash(temp);
 
 #ifdef DEBUG
-	fprintf(stderr,"DOS_GetCWD: %c:\%s",'A'+drive, temp+1);
+	fprintf(stderr,"DOS_GetCWD: %c: %s\n",'A'+drive, temp + 1);
 #endif
-	return (temp+1);
+	return (temp + 1);
 }
 
 int DOS_ChangeDir(int drive, char *dirname)
 {
+	char temp[256];
+
 	if (!DOS_ValidDrive(drive)) 
 		return 0;
 
-	GetUnixDirName(DosDrives[drive].cwd, dirname);
+	strcpy(temp, dirname);
+	ToUnix(temp);
+	
+	GetUnixDirName(DosDrives[drive].cwd, temp);
 	strcat(DosDrives[drive].cwd,"/");
 #ifdef DEBUG
-	fprintf(stderr,"DOS_SetCWD: %c:\%s",'A'+drive, DosDrives[drive].cwd);
+	fprintf(stderr,"DOS_SetCWD: %c: %s\n",'A'+drive, DosDrives[drive].cwd);
 #endif
 	return 1;
 }
@@ -450,35 +438,9 @@
 #ifdef DEBUG
 	fprintf(stderr,"DOS_MakeDir: %c:\%s => %s",'A'+drive, dirname, temp);
 #endif
+	return 1;
 }
 
-/*
-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)) 
@@ -497,6 +459,23 @@
 	return 1;
 }
 
+char *DOS_GetVolumeLabel(int drive)
+{
+	if (!DOS_ValidDrive(drive)) 
+		return NULL;
+
+	return (DosDrives[drive].label);
+}
+
+int DOS_SetVolumeLabel(int drive, char *label)
+{
+	if (!DOS_ValidDrive(drive)) 
+		return 0;
+
+	strncpy(DosDrives[drive].label, label, 8);
+	return 1;
+}
+
 int DOS_GetFreeSpace(int drive, long *size, long *available)
 {
 	struct statfs info;
@@ -515,50 +494,39 @@
 	return 1;
 }
 
-char *FindFile(char *buffer, int buflen, char *rootname, char **extensions, 
+char *FindFile(char *buffer, int buflen, char *filename, char **extensions, 
 		char *path)
 {
-    char *workingpath;
-    char *dirname;
+    char *workingpath, *dirname, *rootname, **e;
     DIR *d;
     struct dirent *f;
-    char **e;
-    int rootnamelen;
-    int found = 0;
+    int rootnamelen, found = 0;
+    struct stat filestat;
 
-
-    if (strchr(rootname, '\\') != NULL)
+    if (strchr(filename, '\\') != NULL)
     {
-	strncpy(buffer, GetDirectUnixFileName(rootname), buflen);
+	strncpy(buffer, GetUnixFileName(filename), buflen);
 	ToUnix(buffer);
-	
-#ifdef DEBUG
-fprintf(stderr,"FindFile: %s -> %s\n",rootname,buffer);
-#endif
-
 	return buffer;
     }
 
-    if (strchr(rootname, '/') != NULL)
+    if (strchr(filename, '/') != NULL)
     {
-	strncpy(buffer, rootname, buflen);
-
-#ifdef DEBUG
-fprintf(stderr,"FindFile: %s -> %s\n",rootname,buffer);
-#endif
-
+	strncpy(buffer, filename, buflen);
 	return buffer;
     }
 
 #ifdef DEBUG
-fprintf(stderr,"FindFile: looking for %s\n",rootname);
+fprintf(stderr,"FindFile: looking for %s\n", filename);
 #endif
 
+    rootnamelen = strlen(filename);
+    if ((rootname = malloc(rootnamelen + 1)) == NULL)
+    	return NULL;
+    strcpy(rootname, filename);
     ToUnix(rootname);
 
-    rootnamelen = strlen(rootname);
-    workingpath = malloc(strlen(path) + 1);
-    if (workingpath == NULL)
+    if ((workingpath = malloc(strlen(path) + 1)) == NULL)
 	return NULL;
     strcpy(workingpath, path);
 
@@ -566,8 +534,8 @@
 	dirname != NULL;
 	dirname = strtok(NULL, ";"))
     {
-	if (strchr(dirname, '\\')!=NULL)
-		d = opendir( GetDirectUnixFileName(dirname) );
+	if (strchr(dirname, '\\') != NULL)
+		d = opendir( GetUnixFileName(dirname) );
 	else
 		d = opendir( dirname );
 
@@ -583,38 +551,37 @@
 		{
 		    if (extensions == NULL || 
 			strcasecmp(rootname, f->d_name) == 0)
-		    {
-			found = 1;
-		    }
-		    else if (f->d_name[rootnamelen] == '.')
-		    {
+				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
+			if (strchr(dirname, '\\') != NULL)
+				strncpy(buffer, GetUnixFileName(dirname), buflen);
+			else
 				strncpy(buffer, dirname, buflen);
 
-			if (buffer[strlen(buffer)-1]!='/')			
-				strncat(buffer, "/", buflen - strlen(buffer));
-			
+			strncat(buffer, "/", buflen - strlen(buffer));
 			strncat(buffer, f->d_name, buflen - strlen(buffer));
-			closedir(d);
 
-			ToUnix(buffer);
+			fprintf(stderr,"$$%s$$\n", buffer);
 
-			return buffer;
+			stat(buffer, &filestat);
+			if (S_ISREG(filestat.st_mode)) {
+				closedir(d);
+				free(rootname);
+				ToUnix(buffer);
+				return buffer;
+		    	} else 
+		    		found = 0; 
 		    }
 		}
 	    }
@@ -629,52 +596,52 @@
  */
 char *WineIniFileName(void)
 {
-    static char *IniName = NULL, *env;
+	int fd;
+	static char *filename = NULL;
+	char name[256];
 
-    char inipath[256];
-    
-    if (IniName)
-	return IniName;
+	if (filename)
+		return filename;
 
-    getcwd(inipath, 256);
-    
-    if ((env = getenv("HOME")) !=NULL) {
-	    strcat(inipath, ";");
-	    strcat(inipath, env);
-    }
-    if ((env = getenv("WINEPATH")) !=NULL) {
-	    strcat(inipath, ";");
-	    strcat(inipath, env);
-    }
-
-    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;
+	strcpy(name, WINE_INI_USER);
+	ExpandTildeString(name);
+	if ((fd = open(name, O_RDONLY)) != -1) {
+		close(fd);
+		filename = malloc(strlen(name) + 1);
+		strcpy(filename, name);
+		return(filename);
+	}
+	if ((fd = open(WINE_INI_GLOBAL, O_RDONLY)) != -1) {
+		close(fd);
+		filename = malloc(strlen(WINE_INI_GLOBAL) + 1);
+		strcpy(filename, WINE_INI_GLOBAL);
+		return(filename);
+	}
+	fprintf(stderr,"wine: can't open configuration file %s or %s !\n", 
+				WINE_INI_GLOBAL, WINE_INI_USER);
+	exit(1);
 }
 
-char *WinIniFileName()
+char *WinIniFileName(void)
 {
-	static char name[256];
+	static char *name = NULL;
 	
-	strcpy(name,GetDirectUnixFileName(WindowsDirectory));	
-	strcat(name,"win.ini");
+	if (name)
+		return name;
+		
+	name = malloc(1024);
 
+	strcpy(name, GetUnixFileName(WindowsDirectory));
+	strcat(name, "/");
+	strcat(name, "win.ini");
 	ToUnix(name);
+
+	name = realloc(name, strlen(name) + 1);
 	
 	return name;
 }
 
-int match(char *filename, char *filemask)
+static int match(char *filename, char *filemask)
 {
 	int x, masklength = strlen(filemask);
 
@@ -683,10 +650,8 @@
 #endif
 
 	for (x = 0; x != masklength ; x++) {
-#ifdef DEBUG
-		printf("(%c%c) ", *filename, filemask[x]); 
-#endif
-
+/*		printf("(%c%c) ", *filename, filemask[x]); 
+*/
 		if (!*filename)
 			/* stop if EOFname */
 			return 1;
@@ -723,12 +688,10 @@
 	if (x == MAX_OPEN_DIRS)
 		return NULL;
 
-	if ((unixdirname = GetDirectUnixFileName(dosdirname)) == NULL)
+	if ((unixdirname = GetUnixFileName(dosdirname)) == NULL)
 		return NULL;
 
 	strcpy(temp, unixdirname);
-
-
 	y = strlen(temp);
 	while (y--)
 	{
@@ -779,15 +742,18 @@
 		ToDos(de->filename);
 	} while ( !match(de->filename, de->filemask) );
 
-	de->attribute = 0x0;
-
 	strcpy(temp,de->unixpath);
 	strcat(temp,"/");
 	strcat(temp,de->filename);
 	ToUnix(temp);
+
 	stat (temp, &st);
+	de->attribute = 0x0;
 	if S_ISDIR(st.st_mode)
-		de->attribute |= 0x08;
+		de->attribute |= FA_DIREC;
+	
+	de->filesize = st.st_size;
+	de->filetime = st.st_mtime;
 
 	return de;
 }
diff --git a/misc/exec.c b/misc/exec.c
index a41a95c..f6730c6 100644
--- a/misc/exec.c
+++ b/misc/exec.c
@@ -3,6 +3,10 @@
 *
 */
 
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
 #include "windows.h"
 
 #define HELP_CONTEXT      0x0001
@@ -23,79 +27,65 @@
 
 WORD WinExec(LPSTR lpCmdLine, WORD nCmdShow)
 {
-   int X, X2, C;
-   char *ArgV[20];
-   printf("WinExec('%s', %04X)\n", lpCmdLine, nCmdShow);
-   for (X = X2 = C = 0; X < strlen(lpCmdLine) + 1; X++) {
-      if ((lpCmdLine[X] == ' ') || (lpCmdLine[X] == '\0')) {
-          ArgV[C] = (char *)malloc(X - X2 + 1);
-          strncpy(ArgV[C], &lpCmdLine[X2], X - X2);
-          ArgV[C][X - X2] = '\0';
-          C++;   X2 = X + 1;
-      }
-   }  
-   ArgV[C] = NULL;
-   for (C = 0; ; C++) {
-      if (ArgV[C] == NULL)  break;
-      printf("--> '%s' \n", ArgV[C]);
-   }  
-   switch(fork()) {
-      case -1:
-         printf("Can't 'fork' process !\n");
-         break;
-      case 0:
-         printf("New process started !\n");
-         execvp(ArgV[0], ArgV);
-         printf("Child process died !\n");
-         exit(1);
-         break;
-      default:
-         printf("Main process stay alive !\n");
-         break;         
-      }
-   for (C = 0; ; C++) {
-      if (ArgV[C] == NULL)  break;
-      free(ArgV[C]);
-   }  
-   return(TRUE);
+	int X, X2, C;
+	char *ArgV[20];
+	printf("WinExec('%s', %04X)\n", lpCmdLine, nCmdShow);
+	ArgV[0] = "wine";
+	C = 1;
+	for (X = X2 = 0; X < strlen(lpCmdLine) + 1; X++) {
+		if ((lpCmdLine[X] == ' ') || (lpCmdLine[X] == '\0')) {
+			ArgV[C] = (char *)malloc(X - X2 + 1);
+			strncpy(ArgV[C], &lpCmdLine[X2], X - X2);
+			ArgV[C][X - X2] = '\0';
+			C++;   X2 = X + 1;
+		}							  
+	}  
+	ArgV[C] = NULL;
+	for (C = 0; ; C++) {
+		if (ArgV[C] == NULL)  break;
+		printf("--> '%s' \n", ArgV[C]);
+	}  
+	switch(fork()) {
+	case -1:
+		printf("Can't 'fork' process !\n");
+		break;
+	case 0:
+		printf("New process started !\n");
+		execvp(ArgV[0], ArgV);
+		printf("Child process died !\n");
+		exit(1);
+		break;
+	default:
+		printf("Main process stay alive !\n");
+		break;         
+	}
+	for (C = 0; ; C++) {
+		if (ArgV[C] == NULL)  break;
+		free(ArgV[C]);
+	}  
+	return(TRUE);
 }
 
 
 BOOL WinHelp(HWND hWnd, LPSTR lpHelpFile, WORD wCommand, DWORD dwData)
 {
-   char *ArgV[6];
-   char	str[32];
-   printf("WinHelp(%s, %u, %lu)\n", lpHelpFile, wCommand, dwData);
-   switch(fork()) {
-      case -1:
-         printf("Can't 'fork' process !\n");
-         break;
-      case 0:
-         printf("New process started !\n");
-         ArgV[0] = "wine";
-         ArgV[1] = "winhelp.exe";
-         ArgV[2] = lpHelpFile;
-         switch (wCommand) {
-	     case HELP_CONTEXT:
-	     case HELP_KEY:
-	     case HELP_SETINDEX:
-		 sprintf(str, "%lu", dwData);
-		 ArgV[3] = str;
-	     default:
-		 ArgV[3] = NULL;
-	     }
-         ArgV[4] = NULL;
-         if (wCommand == HELP_HELPONHELP)  ArgV[2] = NULL;
-/*
-         _WinMain(ArgV, 2);
-*/
-         execvp(ArgV[0], ArgV);
-         printf("Child process died !\n");
-         exit(1);
-         break;
-      default:
-         printf("Main process stay alive !\n");
-         break;         
-      }
-return(TRUE);
+	char	str[256];
+	printf("WinHelp(%s, %u, %lu)\n", lpHelpFile, wCommand, dwData);
+	switch(wCommand) {
+	case 0:
+	case HELP_HELPONHELP:
+		GetWindowsDirectory(str, sizeof(str));
+		strcat(str, "\\winhelp.exe");
+		printf("'%s'\n", str);
+		break;
+	case HELP_INDEX:
+		GetWindowsDirectory(str, sizeof(str));
+		strcat(str, "\\winhelp.exe");
+		printf("'%s'\n", str);
+		break;
+	default:
+		return FALSE;
+	}
+	WinExec(str, SW_SHOWNORMAL);
+	return(TRUE);
 }
diff --git a/misc/file.c b/misc/file.c
index de8a7e2..5d41f1c 100644
--- a/misc/file.c
+++ b/misc/file.c
@@ -19,16 +19,16 @@
 
 #define DEBUG_FILE
 
-#include <windows.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <limits.h>
 #include <unistd.h>
+#include <time.h>
+#include <windows.h>
 #include "prototypes.h"
 
 char WindowsDirectory[256], SystemDirectory[256], TempDirectory[256];
 
-
 /***************************************************************************
  _lopen 
 
@@ -40,12 +40,12 @@
   char *UnixFileName;
 
 #ifdef DEBUG_FILE
-  fprintf (stderr, "_lopen: open %s\n", lpPathName);
+  fprintf (stderr, "_lopen: open('%s', %X);\n", lpPathName, iReadWrite);
 #endif
 
   if ((UnixFileName = GetUnixFileName(lpPathName)) == NULL)
   	return HFILE_ERROR;
-
+  iReadWrite &= 0x000F;
   handle =  open (UnixFileName, iReadWrite);
 
 #ifdef DEBUG_FILE
@@ -67,7 +67,7 @@
 
 #ifdef DEBUG_FILE
   fprintf(stderr, "_lread: handle %d, buffer = %ld, length = %d\n",
-	  		hFile, lpBuffer, wBytes);
+	  		hFile, (int) lpBuffer, wBytes);
 #endif
   
   result = read (hFile, lpBuffer, wBytes);
@@ -87,7 +87,7 @@
 
 #ifdef DEBUG_FILE
   fprintf(stderr, "_lwrite: handle %d, buffer = %ld, length = %d\n",
-	  		hFile, lpBuffer, wBytes);
+	  		hFile, (int) lpBuffer, wBytes);
 #endif
 	result = write (hFile, lpBuffer, wBytes);
 
@@ -103,10 +103,12 @@
 int _lclose (int hFile)
 {
 #ifdef DEBUG_FILE
-  fprintf(stderr, "_lclose: handle %d\n", hFile);
+	fprintf(stderr, "_lclose: handle %d\n", hFile);
 #endif
-  
-  close (hFile);
+	if (close (hFile))
+  		return HFILE_ERROR;
+  	else
+  		return 0;
 }
 
 /**************************************************************************
@@ -221,12 +223,12 @@
 #endif
 
 	if (!DOS_ValidDrive(drive))
-		return 0;
+		return DRIVE_DOESNOTEXIST;
 
 	if (drive == 0 || drive == 1)
 		return DRIVE_REMOVABLE;
 		 
-	return DRIVE_REMOTE;
+	return DRIVE_REMOVABLE;
 }
 
 /***************************************************************************
@@ -254,6 +256,7 @@
 	fprintf(stderr,"GetWindowsDirectory (%s)\n",lpszSysPath);
 #endif
 
+	ChopOffSlash(lpszSysPath);
 	return(strlen(lpszSysPath));
 }
 /***************************************************************************
@@ -270,6 +273,7 @@
 	fprintf(stderr,"GetSystemDirectory (%s)\n",lpszSysPath);
 #endif
 
+	ChopOffSlash(lpszSysPath);
 	return(strlen(lpszSysPath));
 }
 /***************************************************************************
@@ -288,7 +292,7 @@
 	strcpy(tempname,lpszPrefixString);
 	tempname[3]='\0';
 
-	sprintf(lpszTempFileName,"%s\%s%d.tmp",WindowsDirectory, tempname, 
+	sprintf(lpszTempFileName,"%s\\%s%d.tmp",WindowsDirectory, tempname, 
 		unique);
 
 	ToDos(lpszTempFileName);
@@ -308,3 +312,52 @@
 {
 	fprintf(stderr,"wine: SetErrorMode %4x (ignored)\n",x);
 }
+
+/***************************************************************************
+ _hread
+ ***************************************************************************/
+long _hread(int hf, void FAR *hpvBuffer, long cbBuffer)
+{
+	long dataread = 0;
+	size_t status, size;
+	
+	while (cbBuffer) 
+	{
+		size = cbBuffer < 30000 ? cbBuffer : 30000;
+		
+		status = read(hf, hpvBuffer, size);
+		if (status == -1)
+			return HFILE_ERROR;
+		if (status == 0)
+			return dataread;
+
+		dataread += status;
+		hpvBuffer += status;
+		cbBuffer -= status;
+	}		
+	return dataread;
+}
+/***************************************************************************
+ _hwrite
+ ***************************************************************************/
+long _hwrite(int hf, const void FAR *hpvBuffer, long cbBuffer)
+{
+	long datawritten = 0;
+	size_t status, size;
+	
+	while (cbBuffer) 
+	{
+		size = cbBuffer < 30000 ? cbBuffer : 30000;
+		
+		status = write(hf, hpvBuffer, size);
+		if (status == -1)
+			return HFILE_ERROR;
+		if (status == 0)
+			return datawritten;
+
+		datawritten += status;
+		hpvBuffer += status;
+		cbBuffer -= status;
+	}		
+	return datawritten;
+}
diff --git a/misc/keyboard.c b/misc/keyboard.c
index cc4b017..178a74f 100644
--- a/misc/keyboard.c
+++ b/misc/keyboard.c
@@ -1,6 +1,8 @@
 static char RCSId[] = "$Id: keyboard.c,v 1.2 1993/09/13 18:52:02 scott Exp $";
 static char Copyright[] = "Copyright  Scott A. Laird, 1993";
 
+#include <stdlib.h>
+#include <stdio.h>
 #include "prototypes.h"
 #include "windows.h"
 
diff --git a/misc/lstr.c b/misc/lstr.c
index bd30f88..cec2748 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -6,6 +6,7 @@
 #include <ctype.h>
 #include <sys/types.h>
 #include <fcntl.h>
+#include <unistd.h>
 
 #include "prototypes.h"
 #include "regfunc.h"
diff --git a/misc/main.c b/misc/main.c
index 59bd197..c98b723 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -7,24 +7,36 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1994";
 
 #include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include <X11/Xlib.h>
 #include <X11/Xresource.h>
-
+#include <X11/Xutil.h>
+#include <X11/cursorfont.h>
+#include "msdos.h"
 #include "windows.h"
 #include "options.h"
+#include "prototypes.h"
 
+#define WINE_CLASS    "Wine"    /* Class name for resources */
 
 Display * XT_display;  /* To be removed */
 Screen * XT_screen;    /* To be removed */
 
-Display * display;
-Screen * screen;
+Display *display;
+Screen *screen;
+Window rootWindow;
+int screenWidth = 0, screenHeight = 0;  /* Desktop window dimensions */
+int screenDepth = 0;  /* Screen depth to use */
+int desktopX = 0, desktopY = 0;  /* Desktop window position (if any) */
 
 char *ProgramName;		/* Used by resource.c with WINELIB */
 
 struct options Options =
 {  /* default options */
     NULL,           /* spyFilename */
+    NULL,           /* desktopGeometry */
+    NULL,           /* programName */
     FALSE,          /* usePrivateMap */
     FALSE,          /* synchronous */
     SW_SHOWNORMAL,  /* cmdShow */
@@ -34,8 +46,11 @@
 
 static XrmOptionDescRec optionsTable[] =
 {
+    { "-desktop",     ".desktop",     XrmoptionSepArg, (caddr_t)NULL },
+    { "-depth",       ".depth",       XrmoptionSepArg, (caddr_t)NULL },
     { "-display",     ".display",     XrmoptionSepArg, (caddr_t)NULL },
     { "-iconic",      ".iconic",      XrmoptionNoArg,  (caddr_t)"on" },
+    { "-name",        ".name",        XrmoptionSepArg, (caddr_t)NULL },
     { "-privatemap",  ".privatemap",  XrmoptionNoArg,  (caddr_t)"on" },
     { "-synchronous", ".synchronous", XrmoptionNoArg,  (caddr_t)"on" },
     { "-spy",         ".spy",         XrmoptionSepArg, (caddr_t)NULL },
@@ -44,38 +59,104 @@
 
 #define NB_OPTIONS  (sizeof(optionsTable) / sizeof(optionsTable[0]))
 
+#define USAGE \
+  "Usage:  %s [options] program_name [arguments]\n" \
+  "\n" \
+  "Options:\n" \
+  "    -depth n        Change the depth to use for multiple-depth screens\n" \
+  "    -desktop geom   Use a desktop window of the given geometry\n" \
+  "    -display name   Use the specified display\n" \
+  "    -iconic         Start as an icon\n" \
+  "    -name name      Set the application name\n" \
+  "    -privatemap     Use a private color map\n" \
+  "    -synchronous    Turn on synchronous display mode\n" \
+  "    -spy file       Turn on message spying to the specified file\n" \
+  "    -relaydbg       Display call relay information\n"
+
 
 /***********************************************************************
  *           MAIN_Usage
  */
 static void MAIN_Usage( char *name )
 {
-    fprintf( stderr,"Usage: %s [-display name] [-iconic] [-privatemap]\n"
-	            "        [-synchronous] [-spy file] program [arguments]\n",
-	     name );
+    fprintf( stderr, USAGE, name );
     exit(1);
 }
 
 
 /***********************************************************************
+ *           MAIN_GetProgramName
+ *
+ * Get the program name. The name is specified by (in order of precedence):
+ * - the option '-name'.
+ * - the environment variable 'WINE_NAME'.
+ * - the last component of argv[0].
+ */
+static char *MAIN_GetProgramName( int argc, char *argv[] )
+{
+    int i;
+    char *p;
+
+    for (i = 1; i < argc-1; i++)
+	if (!strcmp( argv[i], "-name" )) return argv[i+1];
+    if ((p = getenv( "WINE_NAME" )) != NULL) return p;
+    if ((p = strrchr( argv[0], '/' )) != NULL) return p+1;
+    return argv[0];
+}
+
+
+/***********************************************************************
+ *           MAIN_GetResource
+ *
+ * Fetch the value of resource 'name' using the correct instance name.
+ * 'name' must begin with '.' or '*'
+ */
+static int MAIN_GetResource( XrmDatabase db, char *name, XrmValue *value )
+{
+    char *buff_instance, *buff_class;
+    char *dummy;
+    int retval;
+
+    buff_instance = (char *)malloc(strlen(Options.programName)+strlen(name)+1);
+    buff_class    = (char *)malloc( strlen(WINE_CLASS) + strlen(name) + 1 );
+
+    strcpy( buff_instance, Options.programName );
+    strcat( buff_instance, name );
+    strcpy( buff_class, WINE_CLASS );
+    strcat( buff_class, name );
+    retval = XrmGetResource( db, buff_instance, buff_class, &dummy, value );
+    free( buff_instance );
+    free( buff_class );
+    return retval;
+}
+
+
+/***********************************************************************
  *           MAIN_ParseOptions
  *
  * Parse command line options and open display.
  */
 static void MAIN_ParseOptions( int *argc, char *argv[] )
 {
-    char *dummy, *display_name;
+    char *display_name;
     XrmValue value;
     XrmDatabase db = NULL;
 
-    XrmParseCommand( &db, optionsTable, NB_OPTIONS, "wine", argc, argv );
+      /* Parse command line */
+
+    Options.programName = MAIN_GetProgramName( *argc, argv );
+    XrmParseCommand( &db, optionsTable, NB_OPTIONS,
+		     Options.programName, argc, argv );
 #ifdef WINELIB
     /* Need to assemble command line and pass it to WinMain */
 #else
-    if (*argc < 2) MAIN_Usage( argv[0] );
+    if (*argc < 2 || strcasecmp(argv[1], "-h") == 0) 
+    	MAIN_Usage( argv[0] );
 #endif
-    if (XrmGetResource( db, "wine.display", "Wine.display", &dummy, &value ))
-	display_name = value.addr;
+
+      /* Open display */
+
+    if (MAIN_GetResource( db, ".display", &value )) display_name = value.addr;
     else display_name = NULL;
 
     if (!(display = XOpenDisplay( display_name )))
@@ -85,50 +166,98 @@
 	exit(1);
     }
 
-    if (XrmGetResource(db,"wine.iconic","Wine.iconic",&dummy,&value))
+      /* Get all options */
+
+    if (MAIN_GetResource( db, ".iconic", &value ))
 	Options.cmdShow = SW_SHOWMINIMIZED;
-    if (XrmGetResource(db,"wine.privatemap","Wine.privatemap",&dummy,&value))
+    if (MAIN_GetResource( db, ".privatemap", &value ))
 	Options.usePrivateMap = TRUE;
-    if (XrmGetResource(db,"wine.synchronous","Wine.synchronous",&dummy,&value))
+    if (MAIN_GetResource( db, ".synchronous", &value ))
 	Options.synchronous = TRUE;
-    if (XrmGetResource(db,"wine.relaydbg","Wine.relaydbg",&dummy,&value))
+    if (MAIN_GetResource( db, ".relaydbg", &value ))
 	Options.relay_debug = TRUE;
-    if (XrmGetResource(db,"wine.spy","Wine.spy",&dummy,&value))
+    if (MAIN_GetResource( db, ".spy", &value))
 	Options.spyFilename = value.addr;
+    if (MAIN_GetResource( db, ".depth", &value))
+	screenDepth = atoi( value.addr );
+    if (MAIN_GetResource( db, ".desktop", &value))
+	Options.desktopGeometry = value.addr;
 }
 
 
 /***********************************************************************
- *           main
+ *           MAIN_CreateDesktop
  */
-int main( int argc, char *argv[] )
-{    
-    int ret_val;
-    XKeyboardState keyboard_state;
-    XKeyboardControl keyboard_value;
-    
-    XrmInitialize();
-    
-    MAIN_ParseOptions( &argc, argv );
+static void MAIN_CreateDesktop( int argc, char *argv[] )
+{
+    int flags;
+    unsigned int width = 640, height = 480;  /* Default size = 640x480 */
+    char *name = "Wine desktop";
+    XSizeHints size_hints;
+    XWMHints wm_hints;
+    XClassHint class_hints;
+    XSetWindowAttributes win_attr;
+    XTextProperty window_name;
 
-    screen = DefaultScreenOfDisplay( display );
-    XT_display = display;
-    XT_screen = screen;
-    if (Options.synchronous) XSynchronize( display, True );
+    flags = XParseGeometry( Options.desktopGeometry,
+			    &desktopX, &desktopY, &width, &height );
+    screenWidth  = width;
+    screenHeight = height;
 
+      /* Create window */
+
+    win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
+	                 PointerMotionMask | ButtonPressMask |
+			 ButtonReleaseMask | EnterWindowMask | 
+			 StructureNotifyMask;
+    win_attr.cursor = XCreateFontCursor( display, XC_top_left_arrow );
+
+    rootWindow = XCreateWindow( display, DefaultRootWindow(display),
+			        desktopX, desktopY, width, height, 0,
+			        CopyFromParent, InputOutput, CopyFromParent,
+			        CWEventMask | CWCursor, &win_attr );
+
+      /* Set window manager properties */
+
+    size_hints.min_width = size_hints.max_width = width;
+    size_hints.min_height = size_hints.max_height = height;
+    size_hints.flags = PMinSize | PMaxSize;
+    if (flags & (XValue | YValue)) size_hints.flags |= USPosition;
+    if (flags & (WidthValue | HeightValue)) size_hints.flags |= USSize;
+    else size_hints.flags |= PSize;
+
+    wm_hints.flags = InputHint | StateHint;
+    wm_hints.input = True;
+    wm_hints.initial_state = NormalState;
+    class_hints.res_name = argv[0];
+    class_hints.res_class = "Wine";
+
+    XStringListToTextProperty( &name, 1, &window_name );
+    XSetWMProperties( display, rootWindow, &window_name, &window_name,
+		      argv, argc, &size_hints, &wm_hints, &class_hints );
+
+      /* Map window */
+
+    XMapWindow( display, rootWindow );
+}
+
+
+XKeyboardState keyboard_state;
+
+/***********************************************************************
+ *           MAIN_SaveSetup
+ */
+static void MAIN_SaveSetup(void)
+{
     XGetKeyboardControl(display, &keyboard_state);
+}
 
-    ProgramName = argv [0];
-    DOS_InitFS();
-    Comm_Init();
-
-    ret_val = _WinMain( argc, argv );
-    
-    Comm_DeInit ();
-    DOS_DeInitFS ();
-    sync_profiles ();
-
-    /* restore sounds/keyboard settings */
+/***********************************************************************
+ *           MAIN_RestoreSetup
+ */
+static void MAIN_RestoreSetup(void)
+{
+    XKeyboardControl keyboard_value;
 
     keyboard_value.key_click_percent	= keyboard_state.key_click_percent;
     keyboard_value.bell_percent 	= keyboard_state.bell_percent;
@@ -138,6 +267,65 @@
 
     XChangeKeyboardControl(display, KBKeyClickPercent | KBBellPercent | 
     	KBBellPitch | KBBellDuration | KBAutoRepeatMode, &keyboard_value);
+}
+
+static void called_at_exit(void)
+{
+    Comm_DeInit();
+    sync_profiles();
+    MAIN_RestoreSetup();
+}
+
+/***********************************************************************
+ *           main
+ */
+int main( int argc, char *argv[] )
+{    
+    int ret_val;
+    int depth_count, i;
+    int *depth_list;
+    
+    XrmInitialize();
+    
+    MAIN_ParseOptions( &argc, argv );
+
+    screen       = DefaultScreenOfDisplay( display );
+    screenWidth  = WidthOfScreen( screen );
+    screenHeight = HeightOfScreen( screen );
+    XT_display   = display;
+    XT_screen    = screen;
+    if (screenDepth)  /* -depth option specified */
+    {
+	depth_list = XListDepths(display,DefaultScreen(display),&depth_count);
+	for (i = 0; i < depth_count; i++)
+	    if (depth_list[i] == screenDepth) break;
+	XFree( depth_list );
+	if (i >= depth_count)
+	{
+	    fprintf( stderr, "%s: Depth %d not supported on this screen.\n",
+		              Options.programName, screenDepth );
+	    exit(1);
+	}
+    }
+    else screenDepth  = DefaultDepthOfScreen( screen );
+    if (Options.synchronous) XSynchronize( display, True );
+    if (Options.desktopGeometry) MAIN_CreateDesktop( argc, argv );
+    else rootWindow = DefaultRootWindow( display );
+
+    ProgramName = argv [0];
+    MAIN_SaveSetup();
+    DOS_InitFS();
+    Comm_Init();
+    
+#ifndef sun
+    atexit(called_at_exit);
+#endif
+
+    ret_val = _WinMain( argc, argv );
+
+#ifdef sunos
+    called_at_exit();
+#endif
 
     return ret_val;
 }
@@ -145,7 +333,7 @@
 /***********************************************************************
  *           MessageBeep    (USER.104)
  */
-void MessageBeep( WORD i )
+void MessageBeep(WORD i)
 {
 	XBell(display, 100);
 }
@@ -155,7 +343,7 @@
  */
 LONG GetVersion(void)
 {
-	return (0x04001003); /* dos version 4.00, win ver 3.1 */
+	return( 0x03300a03 ); /*  dos 3.30 & win 3.10 */
 }
 
 /***********************************************************************
@@ -179,9 +367,12 @@
  */
 BOOL SystemParametersInfo (UINT uAction, UINT uParam, void FAR *lpvParam, UINT fuWinIni)
 {
+	int timeout, temp;
+	char buffer[256];
 	XKeyboardState		keyboard_state;
 	XKeyboardControl	keyboard_value;
 
+
 	fprintf(stderr, "SystemParametersInfo: action %d, param %x, flag %x\n", 
 			uAction, uParam, fuWinIni);
 
@@ -195,7 +386,7 @@
 			break;
 		
 		case SPI_GETBORDER:
-			*(int *) lpvParam = 1;
+			*(INT *) lpvParam = 1;
 			break;
 
 		case SPI_GETFASTTASKSWITCH:
@@ -203,7 +394,7 @@
 			break;
 
 		case SPI_GETGRIDGRANULARITY:
-			*(int *) lpvParam = 1;
+			*(INT *) lpvParam = 1;
 			break;
 
 		case SPI_GETICONTITLEWRAP:
@@ -211,7 +402,7 @@
 			break;
 
 		case SPI_GETKEYBOARDDELAY:
-			*(int *) lpvParam = 1;
+			*(INT *) lpvParam = 1;
 			break;
 
 		case SPI_GETKEYBOARDSPEED:
@@ -223,25 +414,26 @@
 			break;
 
 		case SPI_GETSCREENSAVEACTIVE:
-			*(WORD *) lpvParam = FALSE;
+			*(BOOL *) lpvParam = FALSE;
 			break;
 
 		case SPI_GETSCREENSAVETIMEOUT:
-			*(int *) lpvParam = 0;
+			XGetScreenSaver(display, &timeout, &temp,&temp,&temp);
+			*(INT *) lpvParam = timeout * 1000;
 			break;
 
 		case SPI_ICONHORIZONTALSPACING:
 			if (lpvParam == NULL)
 				fprintf(stderr, "SystemParametersInfo: Horizontal icon spacing set to %d\n.", uParam);
 			else
-				*(int *) lpvParam = 50;
+				*(INT *) lpvParam = 50;
 			break;
 
 		case SPI_ICONVERTICALSPACING:
 			if (lpvParam == NULL)
 				fprintf(stderr, "SystemParametersInfo: Vertical icon spacing set to %d\n.", uParam);
 			else
-				*(int *) lpvParam = 50;
+				*(INT *) lpvParam = 50;
 			break;
 
 		case SPI_SETBEEP:
@@ -265,10 +457,22 @@
 						DefaultExposures);
 			break;
 
+		case SPI_SETDESKWALLPAPER:
+			return (SetDeskWallPaper((LPSTR) lpvParam));
+			break;
+
+		case SPI_SETDESKPATTERN:
+			if ((INT) uParam == -1) {
+				GetProfileString("Desktop", "Pattern", 
+						"170 85 170 85 170 85 170 85", 
+						buffer, sizeof(buffer) );
+				return (DESKTOP_SetPattern((LPSTR) buffer));
+			} else
+				return (DESKTOP_SetPattern((LPSTR) lpvParam));
+			break;
+
 		case SPI_LANGDRIVER:
 		case SPI_SETBORDER:
-		case SPI_SETDESKPATTERN:
-		case SPI_SETDESKWALLPAPER:
 		case SPI_SETDOUBLECLKHEIGHT:
 		case SPI_SETDOUBLECLICKTIME:
 		case SPI_SETDOUBLECLKWIDTH:
@@ -280,7 +484,33 @@
 
 		default:
 			fprintf(stderr, "SystemParametersInfo: unknown option %d.\n", uParam);
-			break;		
+			break;
 	}
 	return 1;
 }
+
+/***********************************************************************
+*	HMEMCPY (KERNEL.348)
+*/
+void hmemcpy(void FAR *hpvDest, const void FAR *hpvSource, long cbCopy)
+{
+	size_t copysize;
+	
+	while (cbCopy) 
+	{
+		copysize = cbCopy < 30000 ? cbCopy : 30000;
+		
+		memcpy(hpvDest,	hpvSource, copysize);
+		hpvDest += copysize;
+		hpvSource += copysize;
+		cbCopy -= copysize;
+	}		
+}
+
+/***********************************************************************
+*	COPY (GDI.250)
+*/
+void Copy(LPVOID lpSource, LPVOID lpDest, WORD nBytes)
+{
+	memcpy(lpDest, lpSource, nBytes);
+}
diff --git a/misc/message.c b/misc/message.c
index 79a49f7..57428e7 100644
--- a/misc/message.c
+++ b/misc/message.c
@@ -8,6 +8,9 @@
 
 #define DEBUG_MSGBOX
 
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
 #include <windows.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -43,53 +46,55 @@
 
 int MessageBox(HWND hWnd, LPSTR str, LPSTR title, WORD type)
 {
-    HWND    	hDlg;
-    WND	    	*wndPtr;
-    WNDCLASS  	wndClass;
-    MSG	    	msg;
-    MSGBOX	mb;
-    DWORD	dwStyle;
-    HINSTANCE	hInst;
-    wndPtr = WIN_FindWndPtr(hWnd);
+	HWND    	hDlg, hWndOld;
+	WND	    	*wndPtr;
+	WNDCLASS  	wndClass;
+	MSG	    	msg;
+	MSGBOX	mb;
+	DWORD	dwStyle;
+	HINSTANCE	hInst;
+	wndPtr = WIN_FindWndPtr(hWnd);
 #ifdef DEBUG_MSGBOX
-    printf( "MessageBox: '%s'\n", str );
+	printf( "MessageBox: '%s'\n", str );
 #endif
-    if (wndPtr == NULL)
+	if (wndPtr == NULL)
 	hInst = hSysRes;
-    else
+	else
 	hInst = wndPtr->hInstance;
-    wndClass.style           = CS_HREDRAW | CS_VREDRAW ;
-    wndClass.lpfnWndProc     = (WNDPROC)SystemMessageBoxProc;
-    wndClass.cbClsExtra      = 0;
-    wndClass.cbWndExtra      = 0;
-    wndClass.hInstance       = hInst;
-    wndClass.hIcon           = (HICON)NULL;
-    wndClass.hCursor         = LoadCursor((HANDLE)NULL, IDC_ARROW); 
-    wndClass.hbrBackground   = GetStockObject(WHITE_BRUSH);
-    wndClass.lpszMenuName    = NULL;
-    wndClass.lpszClassName   = "MESSAGEBOX";
-    if (!RegisterClass(&wndClass)) return 0;
-    memset(&mb, 0, sizeof(MSGBOX));
-    mb.Title = title;
-    mb.Str = str;
-    mb.wType = type;
-    mb.ActiveFlg = TRUE;
-    dwStyle = WS_POPUP | WS_DLGFRAME | WS_VISIBLE;
-    if ((type & (MB_SYSTEMMODAL | MB_TASKMODAL)) == 0) dwStyle |= WS_CAPTION;
-    hDlg = CreateWindow("MESSAGEBOX", title, dwStyle, 100, 150, 400, 120,
-    	(HWND)NULL, (HMENU)NULL, hInst, (LPSTR)&mb);
-    if (hDlg == 0) return 0;
-    while(TRUE) {
-	if (!mb.ActiveFlg) break;
-	if (!GetMessage(&msg, (HWND)NULL, 0, 0)) break;
-	TranslateMessage(&msg);
-	DispatchMessage(&msg);
-	}
-    if (!UnregisterClass("MESSAGEBOX", hInst)) return 0;
+	wndClass.style           = CS_HREDRAW | CS_VREDRAW ;
+	wndClass.lpfnWndProc     = (WNDPROC)SystemMessageBoxProc;
+	wndClass.cbClsExtra      = 0;
+	wndClass.cbWndExtra      = 0;
+	wndClass.hInstance       = hInst;
+	wndClass.hIcon           = (HICON)NULL;
+	wndClass.hCursor         = LoadCursor((HANDLE)NULL, IDC_ARROW); 
+	wndClass.hbrBackground   = GetStockObject(WHITE_BRUSH);
+	wndClass.lpszMenuName    = NULL;
+	wndClass.lpszClassName   = "MESSAGEBOX";
+	if (!RegisterClass(&wndClass)) return 0;
+	memset(&mb, 0, sizeof(MSGBOX));
+	mb.Title = title;
+	mb.Str = str;
+	mb.wType = type;
+	mb.ActiveFlg = TRUE;
+	dwStyle = WS_POPUP | WS_DLGFRAME | WS_VISIBLE;
+	if ((type & (MB_SYSTEMMODAL | MB_TASKMODAL)) == 0) dwStyle |= WS_CAPTION;
+	hWndOld = GetFocus();
+	hDlg = CreateWindow("MESSAGEBOX", title, dwStyle, 100, 150, 400, 120,
+				(HWND)NULL, (HMENU)NULL, hInst, (LPSTR)&mb);
+	if (hDlg == 0) return 0;
+	while(TRUE) {
+		if (!mb.ActiveFlg) break;
+		if (!GetMessage(&msg, (HWND)NULL, 0, 0)) break;
+		TranslateMessage(&msg);
+		DispatchMessage(&msg);
+		}
+	SetFocus(hWndOld);
+	if (!UnregisterClass("MESSAGEBOX", hInst)) return 0;
 #ifdef DEBUG_MSGBOX
-    printf( "MessageBox return %04X !\n", mb.wRetVal);
+	printf( "MessageBox return %04X !\n", mb.wRetVal);
 #endif
-    return(mb.wRetVal);
+	return(mb.wRetVal);
 }
 
 LPMSGBOX MsgBoxGetStorageHeader(HWND hwnd)
@@ -110,113 +115,113 @@
 
 LONG SystemMessageBoxProc(HWND hWnd, WORD message, WORD wParam, LONG lParam)
 {
-    WND	    *wndPtr;
-    CREATESTRUCT *createStruct;
-    PAINTSTRUCT	ps;
-    HDC		hDC;
-    RECT	rect;
-    LPMSGBOX	lpmb;
-    LPMSGBOX	lpmbInit;
-    BITMAP	bm;
-    HBITMAP	hBitMap;
-    HDC		hMemDC;
-    HICON	hIcon;
-    HINSTANCE	hInst2;
-    int		x;
-    switch(message) {
+	WND	    	*wndPtr;
+	CREATESTRUCT *createStruct;
+	PAINTSTRUCT	ps;
+	HDC			hDC;
+	RECT		rect;
+	LPMSGBOX	lpmb;
+	LPMSGBOX	lpmbInit;
+	BITMAP		bm;
+	HBITMAP		hBitMap;
+	HDC			hMemDC;
+	HICON		hIcon;
+	HINSTANCE	hInst2;
+	int			x;
+	switch(message) {
 	case WM_CREATE:
 #ifdef DEBUG_MSGBOX
-	    printf("MessageBox WM_CREATE !\n");
+		printf("MessageBox WM_CREATE !\n");
 #endif
-	    wndPtr = WIN_FindWndPtr(hWnd);
-	    createStruct = (CREATESTRUCT *)lParam;
-     	    lpmbInit = (LPMSGBOX)createStruct->lpCreateParams;
-     	    if (lpmbInit == 0) break;
-	    *((LPMSGBOX *)&wndPtr->wExtra[1]) = lpmbInit;
-	    lpmb = MsgBoxGetStorageHeader(hWnd);
-	    GetClientRect(hWnd, &rect);
-	    CopyRect(&lpmb->rectStr, &rect);
-	    lpmb->rectStr.bottom -= 32;
-	    switch(lpmb->wType & MB_TYPEMASK) {
+		wndPtr = WIN_FindWndPtr(hWnd);
+		createStruct = (CREATESTRUCT *)lParam;
+		lpmbInit = (LPMSGBOX)createStruct->lpCreateParams;
+		if (lpmbInit == 0) break;
+		*((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 - 30, rect.bottom - 25, 
-			60, 18, hWnd, IDOK, wndPtr->hInstance, 0L);
-		    break;
+			lpmb->hWndYes = CreateWindow("BUTTON", "&Ok", 
+				WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
+				rect.right / 2 - 30, rect.bottom - 25, 
+				60, 18, hWnd, IDOK, wndPtr->hInstance, 0L);
+			break;
 		case MB_OKCANCEL :
-		    lpmb->hWndYes = CreateWindow("BUTTON", "&Ok", 
-			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 - 65, rect.bottom - 25, 
-			60, 18, hWnd, IDOK, wndPtr->hInstance, 0L);
-		    lpmb->hWndCancel = CreateWindow("BUTTON", "&Cancel", 
-			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 + 5, rect.bottom - 25, 
-			60, 18, hWnd, IDCANCEL, wndPtr->hInstance, 0L);
-		    break;
+			lpmb->hWndYes = CreateWindow("BUTTON", "&Ok", 
+				WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
+				rect.right / 2 - 65, rect.bottom - 25, 
+				60, 18, hWnd, IDOK, wndPtr->hInstance, 0L);
+			lpmb->hWndCancel = CreateWindow("BUTTON", "&Cancel", 
+				WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
+				rect.right / 2 + 5, rect.bottom - 25, 
+				60, 18, hWnd, IDCANCEL, wndPtr->hInstance, 0L);
+			break;
 		case MB_ABORTRETRYIGNORE :
-		    lpmb->hWndYes = CreateWindow("BUTTON", "&Retry", 
-			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 - 100, rect.bottom - 25, 
-			60, 18, hWnd, IDRETRY, wndPtr->hInstance, 0L);
-		    lpmb->hWndNo = CreateWindow("BUTTON", "&Ignore", 
-			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 - 30, rect.bottom - 25, 
-			60, 18, hWnd, IDIGNORE, wndPtr->hInstance, 0L);
-		    lpmb->hWndCancel = CreateWindow("BUTTON", "&Abort", 
-			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 + 40, rect.bottom - 25, 
-			60, 18, hWnd, IDABORT, wndPtr->hInstance, 0L);
-		    break;
+			lpmb->hWndYes = CreateWindow("BUTTON", "&Retry", 
+				WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
+				rect.right / 2 - 100, rect.bottom - 25, 
+				60, 18, hWnd, IDRETRY, wndPtr->hInstance, 0L);
+			lpmb->hWndNo = CreateWindow("BUTTON", "&Ignore", 
+				WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
+				rect.right / 2 - 30, rect.bottom - 25, 
+				60, 18, hWnd, IDIGNORE, wndPtr->hInstance, 0L);
+			lpmb->hWndCancel = CreateWindow("BUTTON", "&Abort", 
+				WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
+				rect.right / 2 + 40, rect.bottom - 25, 
+				60, 18, hWnd, IDABORT, wndPtr->hInstance, 0L);
+			break;
 		case MB_YESNO :
-		    lpmb->hWndYes = CreateWindow("BUTTON", "&Yes", 
-			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 - 65, rect.bottom - 25, 
-			60, 18, hWnd, IDYES, wndPtr->hInstance, 0L);
-		    lpmb->hWndNo = CreateWindow("BUTTON", "&No", 
-			WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
-			rect.right / 2 + 5, rect.bottom - 25, 
-			60, 18, hWnd, IDNO, wndPtr->hInstance, 0L);
-		    break;
+			lpmb->hWndYes = CreateWindow("BUTTON", "&Yes", 
+				WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
+				rect.right / 2 - 65, rect.bottom - 25, 
+				60, 18, hWnd, IDYES, wndPtr->hInstance, 0L);
+			lpmb->hWndNo = CreateWindow("BUTTON", "&No", 
+				WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
+				rect.right / 2 + 5, rect.bottom - 25, 
+				60, 18, hWnd, IDNO, 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, IDYES, 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, IDNO, 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, IDCANCEL, wndPtr->hInstance, 0L);
-		    break;
+			lpmb->hWndYes = CreateWindow("BUTTON", "&Yes", 
+				WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE | BS_PUSHBUTTON,
+				rect.right / 2 - 100, rect.bottom - 25, 
+				60, 18, hWnd, IDYES, 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, IDNO, 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, IDCANCEL, wndPtr->hInstance, 0L);
+			break;
 		}
 	    switch(lpmb->wType & MB_ICONMASK) {
 		case MB_ICONEXCLAMATION:
-		    printf("MsgBox LoadIcon Exclamation !\n");
-		    lpmb->hIcon = LoadIcon((HINSTANCE)NULL, IDI_EXCLAMATION);
-		    break;
+			printf("MsgBox LoadIcon Exclamation !\n");
+			lpmb->hIcon = LoadIcon((HINSTANCE)NULL, IDI_EXCLAMATION);
+			break;
 		case MB_ICONQUESTION:
-		    printf("MsgBox LoadIcon Question !\n");
-		    lpmb->hIcon = LoadIcon((HINSTANCE)NULL, IDI_QUESTION);
-		    break;
+			printf("MsgBox LoadIcon Question !\n");
+			lpmb->hIcon = LoadIcon((HINSTANCE)NULL, IDI_QUESTION);
+			break;
 		case MB_ICONASTERISK:
-		    printf("MsgBox LoadIcon Asterisk !\n");
-		    lpmb->hIcon = LoadIcon((HINSTANCE)NULL, IDI_ASTERISK);
-		    break;
+			printf("MsgBox LoadIcon Asterisk !\n");
+			lpmb->hIcon = LoadIcon((HINSTANCE)NULL, IDI_ASTERISK);
+			break;
 		case MB_ICONHAND:
-		    printf("MsgBox LoadIcon Hand !\n");
-		    lpmb->hIcon = LoadIcon((HINSTANCE)NULL, IDI_HAND);
-		    break;
-	    	}
+			printf("MsgBox LoadIcon Hand !\n");
+			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;
-		}
+			SetRect(&lpmb->rectIcon, 16,
+			lpmb->rectStr.bottom / 2 - 16, 48,
+			lpmb->rectStr.bottom / 2 + 16);
+			lpmb->rectStr.left += 64;
+			}
 	    break;
 	case WM_PAINT:
 #ifdef DEBUG_MSGBOX
@@ -259,6 +264,37 @@
 #endif
 	    PostMessage(hWnd, WM_CLOSE, 0, 0L);
 	    break;
+	case WM_CHAR:
+	    lpmb = MsgBoxGetStorageHeader(hWnd);
+		if (wParam >= 'a' || wParam <= 'z') wParam -= 'a' - 'A';
+		switch(wParam) {
+			case 'Y':
+			    lpmb->wRetVal = IDYES;
+				break;
+			case 'O':
+			    lpmb->wRetVal = IDOK;
+				break;
+			case 'R':
+			    lpmb->wRetVal = IDRETRY;
+				break;
+			case 'A':
+			    lpmb->wRetVal = IDABORT;
+				break;
+			case 'N':
+			    lpmb->wRetVal = IDNO;
+				break;
+			case 'I':
+			    lpmb->wRetVal = IDIGNORE;
+				break;
+			case 'C':
+			case VK_ESCAPE:
+			    lpmb->wRetVal = IDCANCEL;
+				break;
+			default:
+			    return 0;
+			}
+	    PostMessage(hWnd, WM_CLOSE, 0, 0L);
+	    break;
 	default:
 	    return DefWindowProc(hWnd, message, wParam, lParam );
     }
diff --git a/misc/profile.c b/misc/profile.c
index f150c9c..377924a 100644
--- a/misc/profile.c
+++ b/misc/profile.c
@@ -14,9 +14,12 @@
 static char Copyright [] = "Copyright (C) 1993 Miguel de Icaza";
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include "windows.h"
+
 #include "wine.h"
+#include "windows.h"
+#include "prototypes.h"
 
 /* #define DEBUG */
 
@@ -121,12 +124,18 @@
 	    }
 	    if (state == FirstBrace) /* On first pass, don't allow dangling keys */
 		break;
-	    
+
 	    if (c == ' ' || c == '\t')
 		break;
 	    
 	    if (c == '\n' || c == ';' || overflow) /* Abort Definition */
 		next = CharBuffer;
+
+	    if (c == ';')
+	    {
+		state = IgnoreToEOL;
+		break;
+	    }
 	    
 	    if (c == '=' || overflow){
 		TKeys *temp;
@@ -165,7 +174,7 @@
     return SecHeader;
 }
 
-static new_key (TSecHeader *section, char *KeyName, char *Value)
+static void new_key (TSecHeader *section, char *KeyName, char *Value)
 {
     TKeys *key;
     
diff --git a/misc/rect.c b/misc/rect.c
index cbb2281..b5c0fc5 100644
--- a/misc/rect.c
+++ b/misc/rect.c
@@ -150,6 +150,12 @@
 BOOL SubtractRect( LPRECT dest, LPRECT src1, LPRECT src2 )
 {
     RECT tmp;
+
+    if (IsRectEmpty( src1 ))
+    {
+	SetRectEmpty( dest );
+	return FALSE;
+    }
     *dest = *src1;
     if (IntersectRect( &tmp, src1, src2 ))
     {
@@ -160,13 +166,13 @@
 	}
 	if ((tmp.top == dest->top) && (tmp.bottom == dest->bottom))
 	{
-	    if (tmp.left == dest->left) dest->right = tmp.right;
-	    else if (tmp.right == dest->right) dest->left = tmp.left;
+	    if (tmp.left == dest->left) dest->left = tmp.right;
+	    else if (tmp.right == dest->right) dest->right = tmp.left;
 	}
 	else if ((tmp.left == dest->left) && (tmp.right == dest->right))
 	{
-	    if (tmp.top == dest->top) dest->bottom = tmp.bottom;
-	    else if (tmp.bottom == dest->bottom) dest->top = tmp.top;
+	    if (tmp.top == dest->top) dest->top = tmp.bottom;
+	    else if (tmp.bottom == dest->bottom) dest->bottom = tmp.top;
 	}
     }
     return TRUE;
diff --git a/misc/sound.c b/misc/sound.c
index 90e9c7d..c976a97 100644
--- a/misc/sound.c
+++ b/misc/sound.c
@@ -1,6 +1,8 @@
 static char RCSId[] = "$Id: heap.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 
+#include <stdlib.h>
+#include <stdio.h>
 #include "prototypes.h"
 
 int OpenSound(void)
diff --git a/misc/spy.c b/misc/spy.c
index 86e5791..bfc0042 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -7,6 +7,7 @@
 #include <stdio.h>
 #include <X11/Xlib.h>
 #include <X11/Xresource.h>
+#include <string.h>
 #include "wineopts.h"
 #include "windows.h"
 #include "wine.h"
@@ -14,7 +15,7 @@
 
 #ifndef NOSPY
 
-#define SPY_MAX_MSGNUM		0x0210
+#define SPY_MAX_MSGNUM		0x0232
 
 const char *MessageTypeNames[SPY_MAX_MSGNUM + 1] =
 {
@@ -92,7 +93,9 @@
     "WM_NCCREATE",		/* 0x0081 */
     "WM_NCDESTROY",		/* 0x0082 */
     "WM_NCCALCSIZE",		/* 0x0083 */
-    NULL, NULL, NULL,
+    "WM_NCHITTEST",        	/* 0x0084 */
+    "WM_NCPAINT",          	/* 0x0085 */
+    "WM_NCACTIVATE",       	/* 0x0086 */
     "WM_GETDLGCODE",		/* 0x0087 */
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
@@ -135,9 +138,9 @@
     "WM_KEYLAST",		/* 0x0108 */
     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
-    "WM_INITDIALOG",		/* 0x0110  */
+    "WM_INITDIALOG",		/* 0x0110 */
     "WM_COMMAND",		/* 0x0111 */
-    NULL,
+    "WM_SYSCOMMAND",       	/* 0x0112 */
     "WM_TIMER",			/* 0x0113 */
     "WM_HSCROLL",		/* 0x0114 */
     "WM_VSCROLL",		/* 0x0115 */
@@ -211,9 +214,26 @@
     "WM_MBUTTONDOWN",		/* 0x0207 */
     "WM_MBUTTONUP",		/* 0x0208 */
     "WM_MBUTTONDBLCLK",		/* 0x0209 */
+    NULL, NULL, NULL, NULL, NULL, NULL,
+
     "WM_PARENTNOTIFY",		/* 0x0210 */
+
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x0220 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    
+    NULL,			/* 0x0230 */
+    "WM_ENTERSIZEMOVE",		/* 0x0231 */
+    "WM_EXITSIZEMOVE"		/* 0x0232 */
 };
 
+char SpyFilters[256];
+char SpyIncludes[256];
+
 #endif /* NOSPY */
 
 /**********************************************************************
@@ -222,18 +242,24 @@
 void SpyMessage(HWND hwnd, WORD msg, WORD wParam, LONG lParam)
 {
 #ifndef NOSPY
+    char msg_name[80];
+    
     if (SpyFp == NULL)
 	return;
     
     if (msg > SPY_MAX_MSGNUM || MessageTypeNames[msg] == NULL)
-    {
-	fprintf(SpyFp, "%04.4x                  %04.4x  %04.4x  %08.8x\n",
-		hwnd, msg, wParam, lParam);
-    }
+	msg_name[0] = '\0';
     else
+	strcpy(msg_name, MessageTypeNames[msg]);
+    
+    strcat(msg_name, ";");
+    
+    if ((strlen(SpyIncludes) == 0 || strstr(SpyIncludes, msg_name) != NULL) &&
+	strstr(SpyFilters, msg_name) == NULL)
     {
-	fprintf(SpyFp, "%04.4x  %20.20s  %04.4x  %08.8x\n",
-		hwnd, MessageTypeNames[msg], wParam, lParam);
+	msg_name[strlen(msg_name) - 1] = '\0';
+	fprintf(SpyFp, "%04.4x  %20.20s  %04.4x  %04.4x  %08.8x\n",
+		hwnd, msg_name, msg, wParam, lParam);
     }
 #endif
 }
@@ -245,7 +271,7 @@
 {
     char filename[100];
 
-    if (SpyFp == NULL)
+    if (SpyFp != NULL)
 	return;
 
     if (Options.spyFilename == NULL)
@@ -261,5 +287,13 @@
     else if (strlen(filename))
 	SpyFp = fopen(filename, "a");
     else
+    {
 	SpyFp = NULL;
+	return;
+    }
+    
+    GetPrivateProfileString("spy", "exclude", "", SpyFilters, 
+			    sizeof(SpyFilters), WINE_INI);
+    GetPrivateProfileString("spy", "include", "", SpyIncludes, 
+			    sizeof(SpyIncludes), WINE_INI);
 }
diff --git a/misc/stress.c b/misc/stress.c
new file mode 100644
index 0000000..2b748b7
--- /dev/null
+++ b/misc/stress.c
@@ -0,0 +1,109 @@
+#include <stdio.h>
+#include <limits.h>
+#include "windows.h"
+#include "stress.h"
+
+#define STRESS_DEBUG
+
+int AllocDiskSpace(long lLeft, UINT uDrive)
+{
+#ifdef STRESS_DEBUG
+	fprintf(stderr, "stress.dll: AllocDiskSpace %d, %ld\n", uDrive, lLeft);
+#endif
+
+	return 1;
+}
+
+int AllocFileHandles(int Left)
+{
+#ifdef STRESS_DEBUG
+	fprintf(stderr, "stress.dll: AllocFileHandles %d\n", Left);
+#endif
+
+	if (Left < 0)
+		return -1;
+	else
+		return 1;
+}
+
+BOOL AllocGDIMem(UINT uLeft)
+{
+#ifdef STRESS_DEBUG
+	fprintf(stderr, "stress.dll: AllocGDIMem %d\n", uLeft);
+#endif
+
+	return 1;
+}
+
+BOOL AllocMem(DWORD dwLeft)
+{
+#ifdef STRESS_DEBUG
+	fprintf(stderr, "stress.dll: AllocMem %ld\n", dwLeft);
+#endif
+
+	return 1;
+}
+
+BOOL AllocUserMem(UINT uContig)
+{
+#ifdef STRESS_DEBUG
+	fprintf(stderr, "stress.dll: AllocUserMem %d\n", uContig);
+#endif
+
+	return 1;
+}
+
+void FreeAllMem(void)
+{
+#ifdef STRESS_DEBUG
+	fprintf(stderr, "stress.dll: FreeAllMem\n");
+#endif
+}
+
+void FreeAllGDIMem(void)
+{
+#ifdef STRESS_DEBUG
+	fprintf(stderr, "stress.dll: FreeAllGDIMem\n");
+#endif
+}
+
+void FreeAllUserMem(void)
+{
+#ifdef STRESS_DEBUG
+	fprintf(stderr, "stress.dll: FreeAllUserMem\n");
+#endif
+}
+
+void GetFreeAllUserMem(void)
+{
+#ifdef STRESS_DEBUG
+	fprintf(stderr, "stress.dll: GetFreeAllUserMem\n");
+#endif
+}
+
+int GetFreeFileHandles(void)
+{
+#ifdef STRESS_DEBUG
+	fprintf(stderr, "stress.dll: GetFreeFileHandles\n");
+#endif
+
+#ifndef OPEN_MAX
+	return _POSIX_OPEN_MAX
+#else
+	return OPEN_MAX;
+#endif
+}
+
+void UnAllocDiskSpace(UINT drive)
+{
+#ifdef STRESS_DEBUG
+	fprintf(stderr, "stress.dll: UnAllocDiskSpace %d\n", drive);
+#endif
+}
+
+void UnAllocFileHandles(void)
+{
+#ifdef STRESS_DEBUG
+	fprintf(stderr, "stress.dll: GetFreeAllUserMem\n");
+#endif
+}
diff --git a/misc/user.c b/misc/user.c
index 51b94af..ed0045b 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -17,6 +17,7 @@
 extern BOOL ATOM_Init();
 extern BOOL GDI_Init();
 extern void SYSMETRICS_Init();
+extern BOOL WIN_CreateDesktopWindow();
 
 #ifndef WINELIB
 /***********************************************************************
@@ -44,6 +45,11 @@
 
     SpyInit();
 
+#ifndef WINELIB    
+      /* Create USER heap */
+    if (!USER_HeapInit()) return 0;
+#endif
+    
       /* Global atom table initialisation */
     if (!ATOM_Init()) return 0;
     
@@ -54,11 +60,6 @@
     SYSMETRICS_Init();
     SYSCOLOR_Init();
 
-#ifndef WINELIB    
-      /* Create USER heap */
-    if (!USER_HeapInit()) return 0;
-#endif
-    
       /* Create the DCEs */
     DCE_Init();
     
@@ -76,10 +77,15 @@
     queueSize = GetProfileInt( "windows", "DefaultQueueSize", 8 );
     if (!SetMessageQueue( queueSize )) return 0;
 
+      /* Create desktop window */
+    if (!WIN_CreateDesktopWindow()) return 0;
+
+#if 1
 #ifndef WINELIB
     /* Initialize DLLs */
     InitializeLoadedDLLs();
 #endif
+#endif
         
     return 1;
 }
diff --git a/misc/winsocket.c b/misc/winsocket.c
index d5483f9..0d520db 100644
--- a/misc/winsocket.c
+++ b/misc/winsocket.c
@@ -1,18 +1,19 @@
 /*
  * based on Windows Sockets 1.1 specs
  * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
+ * 
+ * (C) 1993,1994 John Brezak, Erik Bos.
  */
  
-#include <netdb.h>
 #include <stdio.h>
+#include <string.h>
 #include <sys/types.h>
 #include <sys/socket.h>
-#if defined(__FreeBSD__)
 #include <netinet/in.h>
-#endif
 #include <arpa/inet.h>
 #include <errno.h>
 #include <netdb.h>
+#include <unistd.h>
 #include "winsock.h"
 
 #define DEBUG_WINSOCK
@@ -47,12 +48,12 @@
                         sys_errlist[errno], errno);
 #else
                 fprintf(stderr, "winsock: errno_to_wsaerrno translation failure.\n\t: %s (%d)\n",
-                        strerror [errno], errno);
+                        strerror[errno], errno);
 #endif
 #else
 		fprintf (stderr, "winsock: errno_to_wsaerrno translation failure.\n");
 #endif
-                break;
+		return WSAENETDOWN;
         }
 }
  
diff --git a/miscemu/Imakefile b/miscemu/Imakefile
index dca1f1d..c9c9db8 100644
--- a/miscemu/Imakefile
+++ b/miscemu/Imakefile
@@ -4,8 +4,12 @@
 
 SRCS = \
 	emulate.c \
+	int10.c \
 	int1a.c \
 	int21.c \
+	int25.c \
+	int26.c \
+	ioports.c \
 	kernel.c
 
 OBJS = $(SRCS:.c=.o)
diff --git a/miscemu/emulate.c b/miscemu/emulate.c
index c53aaa9..b43f9f3 100644
--- a/miscemu/emulate.c
+++ b/miscemu/emulate.c
@@ -1,6 +1,8 @@
 static char RCSId[] = "$Id: heap.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
 static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
 
+#include <stdlib.h>
+#include <stdio.h>
 #include "prototypes.h"
 #include "regfunc.h"
 
@@ -13,9 +15,6 @@
   unsigned short Unused;
 };
 
-
-
-
 int
 WIN87_fpmath()
 {
@@ -49,5 +48,3 @@
 {
   printf( "__WinEm87Save(%p,%d)\n",pWin87EmSaveArea,cbWin87EmSaveArea);
 }
-
-
diff --git a/miscemu/int10.c b/miscemu/int10.c
new file mode 100644
index 0000000..0f932bd
--- /dev/null
+++ b/miscemu/int10.c
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include "msdos.h"
+#include "wine.h"
+
+static void Barf(struct sigcontext_struct *context)
+{
+	fprintf(stderr, "int10: unknown/not implemented parameters:\n");
+	fprintf(stderr, "int10: AX %04x, BX %04x, CX %04x, DX %04x, "
+	       "SI %04x, DI %04x, DS %04x, ES %04x\n",
+	       AX, BX, CX, DX, SI, DI, DS, ES);
+}
+
+int do_int10(struct sigcontext_struct *context)
+{
+	switch((context->sc_eax >> 8) & 0xff)
+	{
+	case 0x0f:
+		EAX = (EAX & 0xffffff00) | 0x5b;
+		break;
+
+	case 0x12:
+		if ((EBX & 0xff) == 0x10) {
+			EBX = (EBX & 0xffff0000) | 0x0003;
+			ECX = (ECX & 0xffff0000) | 0x0009;
+		}
+		break;
+			
+	case 0x1a:
+		EBX = (EBX & 0xffff0000) | 0x0008;
+		break;
+		
+	default:
+		Barf(context);
+	};
+	return 1;
+}
diff --git a/miscemu/int1a.c b/miscemu/int1a.c
index addfdbc..0d25a77 100644
--- a/miscemu/int1a.c
+++ b/miscemu/int1a.c
@@ -1,5 +1,6 @@
 #include <time.h>
 #include <stdio.h>
+#include "msdos.h"
 #include "wine.h"
 
 #ifdef linux
diff --git a/miscemu/int21.c b/miscemu/int21.c
index 47368e1..350f9e0 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -1,13 +1,10 @@
 #include <time.h>
 #include <fcntl.h>
 #include <errno.h>
-#ifndef __STDC__
-#include <malloc.h>
-#endif
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <sys/stat.h>
-#include <time.h>
 #include <unistd.h>
 #include <utime.h>
 
@@ -15,24 +12,80 @@
 #include "regfunc.h"
 #include "windows.h"
 #include "wine.h"
-#include "int21.h"
+#include "msdos.h"
+#include "options.h"
 
 static char Copyright[] = "copyright Erik Bos, 1993";
 
 WORD ExtendedError, CodePage = 437;
 BYTE ErrorClass, Action, ErrorLocus;
+BYTE *dta;
 
 extern char TempDirectory[];
 
-void Error(int e, int class, int el)
+static int Error(int e, int class, int el)
 {
-	ExtendedError = e;
 	ErrorClass = class;
 	Action = SA_Ask4Retry;
 	ErrorLocus = el;
+	ExtendedError = e;
+
+	return e;
 }
 
-void GetFreeDiskSpace(struct sigcontext_struct *context)
+static void Barf(struct sigcontext_struct *context)
+{
+	fprintf(stderr, "int21: unknown/not implemented parameters:\n");
+	fprintf(stderr, "int21: AX %04x, BX %04x, CX %04x, DX %04x, "
+	       "SI %04x, DI %04x, DS %04x, ES %04x\n",
+	       AX, BX, CX, DX, SI, DI, DS, ES);
+}
+
+void ChopOffWhiteSpace(char *string)
+{
+	int length;
+
+	for (length = strlen(string) ; length ; length--)
+		if (string[length] == ' ')
+			string[length] = '\0';
+}
+
+static void CreateBPB(int drive, BYTE *data)
+{
+	if (drive > 1) {
+		setword(data, 512);
+		data[2] = 2;
+		setword(&data[3], 0);
+		data[5] = 2;
+		setword(&data[6], 240);
+		setword(&data[8], 64000);
+		data[0x0a] = 0xf8;
+		setword(&data[0x0b], 40);
+		setword(&data[0x0d], 56);
+		setword(&data[0x0f], 2);
+		setword(&data[0x11], 0);
+		setword(&data[0x1f], 800);
+		data[0x21] = 5;
+		setword(&data[0x22], 1);
+	} else { /* 1.44mb */
+		setword(data, 512);
+		data[2] = 2;
+		setword(&data[3], 0);
+		data[5] = 2;
+		setword(&data[6], 240);
+		setword(&data[8], 2880);
+		data[0x0a] = 0xf8;
+		setword(&data[0x0b], 6);
+		setword(&data[0x0d], 18);
+		setword(&data[0x0f], 2);
+		setword(&data[0x11], 0);
+		setword(&data[0x1f], 80);
+		data[0x21] = 7;
+		setword(&data[0x22], 2);
+	}	
+}
+
+static void GetFreeDiskSpace(struct sigcontext_struct *context)
 {
 	int drive;
 	long size,available;
@@ -54,15 +107,15 @@
 		return;
 	}
 
-	EAX = (EAX & 0xffff0000L) | SectorsPerCluster;	
-	ECX = (ECX & 0xffff0000L) | SectorSize;
+	EAX = (EAX & 0xffff0000L) | 4;	
+	ECX = (ECX & 0xffff0000L) | 512;
 
 	EBX = (EBX & 0xffff0000L) | (available / (CX * AX));
 	EDX = (EDX & 0xffff0000L) | (size / (CX * AX));
 	Error (0,0,0);
 }
 
-void SetDefaultDrive(struct sigcontext_struct *context)
+static void SetDefaultDrive(struct sigcontext_struct *context)
 {
 	int drive;
 
@@ -78,13 +131,13 @@
 	}
 }
 
-void GetDefaultDrive(struct sigcontext_struct *context)
+static void GetDefaultDrive(struct sigcontext_struct *context)
 {
 	EAX = (EAX & 0xffffff00L) | DOS_GetDefaultDrive();
 	Error (0,0,0);
 }
 
-void GetDriveAllocInfo(struct sigcontext_struct *context)
+static void GetDriveAllocInfo(struct sigcontext_struct *context)
 {
 	int drive;
 	long size, available;
@@ -93,8 +146,8 @@
 	drive = EDX & 0xffL;
 	
 	if (!DOS_ValidDrive(drive)) {
-		EAX = (EAX & 0xffff0000L) | SectorsPerCluster;	
-		ECX = (ECX & 0xffff0000L) | SectorSize;
+		EAX = (EAX & 0xffff0000L) | 4;
+		ECX = (ECX & 0xffff0000L) | 512;
 		EDX = (EDX & 0xffff0000L);
 		Error (InvalidDrive, EC_MediaError, EL_Disk);
 		return;
@@ -106,8 +159,8 @@
 		return;
 	}
 	
-	EAX = (EAX & 0xffff0000L) | SectorsPerCluster;	
-	ECX = (ECX & 0xffff0000L) | SectorSize;
+	EAX = (EAX & 0xffff0000L) | 4;	
+	ECX = (ECX & 0xffff0000L) | 512;
 	EDX = (EDX & 0xffff0000L) | (size / (CX * AX));
 
 	mediaID = 0xf0;
@@ -117,20 +170,20 @@
 	Error (0,0,0);
 }
 
-void GetDefDriveAllocInfo(struct sigcontext_struct *context)
+static void GetDefDriveAllocInfo(struct sigcontext_struct *context)
 {
 	EDX = DOS_GetDefaultDrive();
 	GetDriveAllocInfo(context);
 }
 
-void GetDrivePB(struct sigcontext_struct *context)
+static 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)
+static void ReadFile(struct sigcontext_struct *context)
 {
 	char *ptr;
 	int size;
@@ -144,7 +197,7 @@
 		return;
 	}
 
-	ptr = (char *) pointer (DS,DX);
+	ptr = pointer (DS,DX);
 
 	if (BX == 0) {
 		*ptr = EOF;
@@ -182,12 +235,12 @@
 	}
 }
 
-void WriteFile(struct sigcontext_struct *context)
+static void WriteFile(struct sigcontext_struct *context)
 {
 	char *ptr;
 	int x,size;
 	
-	ptr = (char *) pointer (DS,DX);
+	ptr = pointer (DS,DX);
 	
 	if (BX == 0) {
 		Error (InvalidHandle, EC_Unknown, EL_Unknown);
@@ -238,9 +291,9 @@
 	}
 }
 
-void UnlinkFile(struct sigcontext_struct *context)
+static void UnlinkFile(struct sigcontext_struct *context)
 {
-	if (unlink( GetUnixFileName((char *) pointer(DS,DX)) ) == -1) {
+	if (unlink( GetUnixFileName( pointer(DS,DX)) ) == -1) {
 		switch (errno) {
 			case EACCES:
 			case EPERM:
@@ -267,9 +320,9 @@
 	ResetCflag;
 }
 
-void SeekFile(struct sigcontext_struct *context)
+static void SeekFile(struct sigcontext_struct *context)
 {
-	int handle, status, fileoffset;
+	int status, fileoffset;
 	
 	switch (EAX & 0xffL) {
 		case 1: fileoffset = SEEK_CUR;
@@ -300,31 +353,82 @@
 	ResetCflag;
 }
 
-void GetFileAttributes(struct sigcontext_struct *context)
+static void GetFileAttributes(struct sigcontext_struct *context)
 {
 	EAX &= 0xfffff00L;
 	ResetCflag;
 }
 
-void SetFileAttributes(struct sigcontext_struct *context)
+static void SetFileAttributes(struct sigcontext_struct *context)
 {
 	ResetCflag;
 }
 
-void DosIOCTL(struct sigcontext_struct *context)
+static void ioctlGetDeviceInfo(struct sigcontext_struct *context)
 {
-	fprintf(stderr,"int21: IOCTL\n");
-	EAX = (EAX & 0xfffff00L) | UnknownUnit;
-	SetCflag;
+	WORD handle = EBX & 0xffff;
+
+	switch (handle) {
+		case 0:
+		case 1:
+		case 2:
+			EDX = (EDX & 0xffff0000) | 0x80d3;
+			break;
+
+		default:
+			Barf(context);
+			EDX = (EDX & 0xffff0000) | 0x50;
+	}
+	ResetCflag;
 }
 
-void DupeFileHandle(struct sigcontext_struct *context)
+static void ioctlGenericBlkDevReq(struct sigcontext_struct *context)
+{
+	BYTE *dataptr = pointer(DS, DX);
+	int drive;
+
+	if (!(EBX & 0xffL))
+		drive = DOS_GetDefaultDrive();
+	else
+		drive = (EBX & 0xffL) - 1;
+
+	if ((ECX & 0xff00L) != 0x0800) {
+		Barf(context);
+		return;
+	}
+	switch (ECX & 0xffL) {
+		case 0x60: /* get device parameters */
+			   /* used by w4wgrp's winfile */
+			dataptr[0] = 0x04;
+			dataptr[6] = 0; /* media type */
+			if (drive > 1) 
+			{
+				dataptr[1] = 0x05; /* fixed disk */
+				setword(&dataptr[2], 0x01); /* non removable */
+				setword(&dataptr[4], 0x300); /* # of cylinders */
+			}
+			else
+			{
+				dataptr[1] = 0x07; /* block dev, floppy */
+				setword(&dataptr[2], 0x02); /* removable */
+				setword(&dataptr[4], 80); /* # of cylinders */
+			}
+			CreateBPB(drive, &dataptr[7]);			
+			EAX = (EAX & 0xfffff00L);
+			ResetCflag;
+			return;
+		default:
+			Barf(context);
+	}
+}
+
+static void DupeFileHandle(struct sigcontext_struct *context)
 {
 	EAX = (EAX & 0xffff0000L) | dup(BX);
 	ResetCflag;
 }
 
-void GetSystemDate(struct sigcontext_struct *context)
+static void GetSystemDate(struct sigcontext_struct *context)
 {
 	struct tm *now;
 	time_t ltime;
@@ -332,12 +436,12 @@
 	ltime = time(NULL);
 	now = localtime(&ltime);
 
-	ECX = (ECX & 0xffff0000L) | now->tm_year + 1900;
+	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)
+static void GetSystemTime(struct sigcontext_struct *context)
 {
 	struct tm *now;
 	time_t ltime;
@@ -349,14 +453,14 @@
 	EDX = (EDX & 0xffffff00L) | now->tm_sec << 8;
 }
 
-void GetExtendedErrorInfo(struct sigcontext_struct *context)
+static 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)
+static void GetInDosFlag(struct sigcontext_struct *context)
 {
 	const BYTE InDosFlag = 0;
 	
@@ -364,11 +468,11 @@
 	EBX = (EBX & 0xffff0000L) | offset(InDosFlag);
 }
 
-void CreateFile(struct sigcontext_struct *context)
+static void CreateFile(struct sigcontext_struct *context)
 {
 	int handle;
 
-	if ((handle = open(GetUnixFileName((char *) pointer(DS,DX)), O_CREAT | O_TRUNC)) == -1) {
+	if ((handle = open(GetUnixFileName( pointer(DS,DX)), O_CREAT | O_TRUNC)) == -1) {
 		switch (errno) {
 			case EACCES:
 			case EPERM:
@@ -401,13 +505,13 @@
 	ResetCflag;
 }
 
-void OpenExistingFile(struct sigcontext_struct *context)
+static void OpenExistingFile(struct sigcontext_struct *context)
 {
 	int handle;
 
-	fprintf(stderr,"OpenExistingFile (%s)\n",(char *) pointer(DS,DX));
+	fprintf(stderr,"OpenExistingFile (%s)\n", pointer(DS,DX));
 	
-	if ((handle = open(GetUnixFileName((char*) pointer(DS,DX)), O_RDWR)) == -1) {
+	if ((handle = open(GetUnixFileName(pointer(DS,DX)), O_RDWR)) == -1) {
 		switch (errno) {
 			case EACCES:
 			case EPERM:
@@ -443,7 +547,7 @@
 	ResetCflag;
 }
 
-void CloseFile(struct sigcontext_struct *context)
+static void CloseFile(struct sigcontext_struct *context)
 {
 	if (close(BX) == -1) {
 		switch (errno) {
@@ -463,34 +567,35 @@
 	ResetCflag;
 }
 
-void RenameFile(struct sigcontext_struct *context)
+static void RenameFile(struct sigcontext_struct *context)
 {
 	char *newname, *oldname;
 
-	fprintf(stderr,"int21: renaming %s to %s\n",(char *) pointer(DS,DX), pointer(ES,DI) );
+	fprintf(stderr,"int21: renaming %s to %s\n", 
+			pointer(DS,DX), pointer(ES,DI) );
 	
-	oldname = GetUnixFileName( (char *) pointer(DS,DX) );
-	newname = GetUnixFileName( (char *) pointer(ES,DI) );
+	oldname = GetUnixFileName( pointer(DS,DX) );
+	newname = GetUnixFileName( pointer(ES,DI) );
 
 	rename( oldname, newname);
 	ResetCflag;
 }
 
-void GetTrueFileName(struct sigcontext_struct *context)
+static void GetTrueFileName(struct sigcontext_struct *context)
 {
-	fprintf(stderr,"int21: GetTrueFileName of %s\n",(char *) pointer(DS,SI));
+	fprintf(stderr,"int21: GetTrueFileName of %s\n", pointer(DS,SI) );
 	
-	strncpy((char *) pointer(ES,DI), (char *) pointer(DS,SI), strlen((char *) pointer(DS,SI)) & 0x7f);
+	strncpy(pointer(ES,DI), pointer(DS,SI), strlen(pointer(DS,SI)) & 0x7f);
 	ResetCflag;
 }
 
-void MakeDir(struct sigcontext_struct *context)
+static void MakeDir(struct sigcontext_struct *context)
 {
 	char *dirname;
 
-	fprintf(stderr,"int21: makedir %s\n",(char *) pointer(DS,DX) );
+	fprintf(stderr,"int21: makedir %s\n", pointer(DS,DX) );
 	
-	if ((dirname = GetUnixFileName( (char *) pointer(DS,DX) ))== NULL) {
+	if ((dirname = GetUnixFileName( pointer(DS,DX) ))== NULL) {
 		EAX = (EAX & 0xffffff00L) | CanNotMakeDir;
 		SetCflag;
 		return;
@@ -504,20 +609,26 @@
 	ResetCflag;
 }
 
-void ChangeDir(struct sigcontext_struct *context)
+static void ChangeDir(struct sigcontext_struct *context)
 {
-	fprintf(stderr,"int21: changedir %s\n",(char *) pointer(DS,DX) );
-
-	DOS_ChangeDir(DOS_GetDefaultDrive(), (char *) pointer (DS,DX));
+	int drive;
+	char *dirname = pointer(DS,DX);
+	drive = DOS_GetDefaultDrive();
+	fprintf(stderr,"int21: changedir %s\n", dirname);
+	if (dirname != NULL && dirname[1] == ':') {
+		drive = toupper(dirname[0]) - 'A';
+		dirname += 2;
+		}
+	DOS_ChangeDir(drive, dirname);
 }
 
-void RemoveDir(struct sigcontext_struct *context)
+static void RemoveDir(struct sigcontext_struct *context)
 {
 	char *dirname;
 
-	fprintf(stderr,"int21: removedir %s\n",(char *) pointer(DS,DX) );
+	fprintf(stderr,"int21: removedir %s\n", pointer(DS,DX) );
 
-	if ((dirname = GetUnixFileName( (char *) pointer(DS,DX) ))== NULL) {
+	if ((dirname = GetUnixFileName( pointer(DS,DX) ))== NULL) {
 		EAX = (EAX & 0xffffff00L) | CanNotMakeDir;
 		SetCflag;
 		return;
@@ -536,82 +647,151 @@
 	ResetCflag;
 }
 
-void AllocateMemory(struct sigcontext_struct *context)
+static 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) {
+/*	if ((ptr = (void *) memalign((size_t) (BX * 0x10), 0x10)) == NULL) {
 		EAX = (EAX & 0xffffff00L) | OutOfMemory;
-		EBX = (EBX & 0xffffff00L); /* out of memory */
+		EBX = (EBX & 0xffffff00L);
 		SetCflag;
 	}
 	fprintf(stderr,"int21: malloc (ptr = %d)\n", ptr );
 
-	EAX = (EAX & 0xffff0000L) | segment((unsigned long) ptr);
-	ResetCflag;
+	EAX = (EAX & 0xffff0000L) | segment(ptr);
+*/
+	Barf(context);
+	SetCflag;
 }
 
-void FreeMemory(struct sigcontext_struct *context)
+static void FreeMemory(struct sigcontext_struct *context)
 {
 	fprintf(stderr,"int21: freemem (ptr = %d)\n", ES * 0x10 );
-
+/*
 	free((void *)(ES * 0x10));
+*/	Barf(context);
 	ResetCflag;
 }
 
-void ResizeMemoryBlock(struct sigcontext_struct *context)
+static 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) {
+/*	if ((ptr = (void *) realloc((void *)(ES * 0x10), (size_t) BX * 0x10)) == NULL) {
 		EAX = (EAX & 0xffffff00L) | OutOfMemory;
-		EBX = (EBX & 0xffffff00L); /* out of memory */
+		EBX = (EBX & 0xffffff00L);
 		SetCflag;
 	}
-	EBX = (EBX & 0xffff0000L) | segment((unsigned long) ptr);
-	ResetCflag;
+	EBX = (EBX & 0xffff0000L) | segment(ptr);
+*/	Barf(context);
+	SetCflag;
 }
 
-void ExecProgram(struct sigcontext_struct *context)
+static void ExecProgram(struct sigcontext_struct *context)
 {
-	execl("wine", GetUnixFileName((char *) pointer(DS,DX)) );
+	execl("wine", GetUnixFileName( pointer(DS,DX)) );
 }
 
-void GetReturnCode(struct sigcontext_struct *context)
+static void GetReturnCode(struct sigcontext_struct *context)
 {
 	EAX = (EAX & 0xffffff00L) | NoError; /* normal exit */
 }
 
-void FindFirst(struct sigcontext_struct *context)
+static void FindNext(struct sigcontext_struct *context)
 {
+	struct dosdirent *dp;
+	
+	dp = (struct dosdirent *)(dta + 0x0d);
 
+	do {
+		if ((dp = DOS_readdir(dp)) == NULL) {
+			DOS_closedir(dp);
+			Error(NoMoreFiles, EC_MediaError , EL_Disk);
+			EAX = (EAX & 0xffffff00L) | NoMoreFiles;
+			SetCflag;
+			return;
+		}
+	} while (*(dta + 0x0c) != dp->attribute);
+				
+	setword(&dta[0x16], 0x1234); /* time */
+	setword(&dta[0x18], 0x1234); /* date */
+	setdword(&dta[0x1a], dp->filesize);
+	strncpy(dta + 0x1e, dp->filename, 13);
+
+	EAX = (EAX & 0xffffff00L);
+	ResetCflag;
+	return;
 }
 
-void FindNext(struct sigcontext_struct *context)
+static void FindFirst(struct sigcontext_struct *context)
 {
+	BYTE drive, *path = pointer(DS, DX);
+	struct dosdirent *dp;
 
+	if (path[1] == ':') {
+		drive = (islower(*path) ? toupper(*path) : *path) - 'A';
+
+		if (!DOS_ValidDrive(drive)) {
+			Error(InvalidDrive, EC_MediaError , EL_Disk);
+			EAX = (EAX & 0xffffff00L) | InvalidDrive;
+			SetCflag;
+			return;
+		}
+	} else
+		drive = DOS_GetDefaultDrive();
+
+	*dta = drive;
+	memset(dta + 1 , '?', 11);
+	*(dta + 0x0c) = ECX & (FA_LABEL | FA_DIREC);
+
+	if (ECX & FA_LABEL) {
+		/* return volume label */
+
+		if (DOS_GetVolumeLabel(drive) != NULL) 
+			strncpy(dta + 0x1e, DOS_GetVolumeLabel(drive), 8);
+
+		EAX = (EAX & 0xffffff00L);
+		ResetCflag;
+		return;
+	}
+
+	if ((dp = DOS_opendir(path)) == NULL) {
+		Error(PathNotFound, EC_MediaError, EL_Disk);
+		EAX = (EAX & 0xffffff00L) | FileNotFound;
+		SetCflag;
+		return;
+	}
+/*	strncpy(dta + 1, AsciizToFCB(dp->filemask), 11); */
+
+/*	*((BYTE *) ((void*)dta + 0x0d)) = (BYTE *) dp; */
+
+	*((struct dosdirent *)(dta + 0x0d))
+	 =
+	  *dp;
+	FindNext(context);
 }
 
-void GetSysVars(struct sigcontext_struct *context)
+static void GetSysVars(struct sigcontext_struct *context)
 {
 	/* return a null pointer, to encourage anyone who tries to
 	   use the pointer */
 
 	ES = 0x0;
 	EBX = (EBX & 0xffff0000L);
+	Barf(context);
 }
 
-void GetFileDateTime(struct sigcontext_struct *context)
+static void GetFileDateTime(struct sigcontext_struct *context)
 {
 	char *filename;
 	struct stat filestat;
 	struct tm *now;
 
-	if ((filename = GetUnixFileName( (char *) pointer(DS,DX) ))== NULL) {
+	if ((filename = GetUnixFileName( pointer(DS,DX) ))== NULL) {
 		EAX = (EAX & 0xffffff00L) | FileNotFound;
 		SetCflag;
 		return;
@@ -620,18 +800,18 @@
 	 	
 	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;
+	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)
+static void SetFileDateTime(struct sigcontext_struct *context)
 {
 	char *filename;
 	struct utimbuf filetime;
 	
-	filename = GetUnixFileName((char *) pointer(DS,DX));
+	filename = GetUnixFileName( pointer(DS,DX) );
 
 	filetime.actime = 0L;
 	filetime.modtime = filetime.actime;
@@ -640,10 +820,10 @@
 	ResetCflag;
 }
 
-void CreateTempFile(struct sigcontext_struct *context)
+static void CreateTempFile(struct sigcontext_struct *context)
 {
-	char *filename, temp[256];
-	int drive, handle;
+	char temp[256];
+	int handle;
 	
 	sprintf(temp,"%s\\win%d.tmp",TempDirectory,(int) getpid());
 
@@ -657,17 +837,17 @@
 		return;
 	}
 
-	strcpy((char *) pointer(DS,DX), temp);
+	strcpy(pointer(DS,DX), temp);
 	
 	EAX = (EAX & 0xffff0000L) | handle;
 	ResetCflag;
 }
 
-void CreateNewFile(struct sigcontext_struct *context)
+static void CreateNewFile(struct sigcontext_struct *context)
 {
 	int handle;
 	
-	if ((handle = open(GetUnixFileName((char *) pointer(DS,DX)), O_CREAT | O_TRUNC | O_RDWR)) == -1) {
+	if ((handle = open(GetUnixFileName( pointer(DS,DX) ), O_CREAT | O_TRUNC | O_RDWR)) == -1) {
 		EAX = (EAX & 0xffffff00L) | WriteProtected;
 		SetCflag;
 		return;
@@ -677,17 +857,17 @@
 	ResetCflag;
 }
 
-void FileLock(struct sigcontext_struct *context)
+static void FileLock(struct sigcontext_struct *context)
 {
-
+	fprintf(stderr, "int21: flock()\n");
 }
 
-void GetExtendedCountryInfo(struct sigcontext_struct *context)
+static void GetExtendedCountryInfo(struct sigcontext_struct *context)
 {
 	ResetCflag;
 }
 
-void GetCurrentDirectory(struct sigcontext_struct *context)
+static void GetCurrentDirectory(struct sigcontext_struct *context)
 {
 	int drive;
 
@@ -702,20 +882,20 @@
 		return;
 	}
 
-	DOS_GetCurrentDir(drive, (char *) pointer(DS,SI) );
+	strcpy(pointer(DS,SI), DOS_GetCurrentDir(drive) );
 	ResetCflag;
 }
 
-void GetCurrentPSP(struct sigcontext_struct *context)
+static void GetCurrentPSP(struct sigcontext_struct *context)
 {
-
+	Barf(context);
 }
 
-void GetDiskSerialNumber(struct sigcontext_struct *context)
+static void GetDiskSerialNumber(struct sigcontext_struct *context)
 {
 	int drive;
-	unsigned long serialnumber;
-	struct diskinfo *ptr;
+	BYTE *dataptr = pointer(DS, DX);
+	DWORD serialnumber;
 	
 	if ((EBX & 0xffL) == 0)
 		drive = DOS_GetDefaultDrive();
@@ -728,474 +908,640 @@
 		return;
 	}
 
-	DOS_GetSerialNumber(drive,&serialnumber);
+	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   ");
+	setword(dataptr, 0);
+	setdword(&dataptr[2], serialnumber);
+	strncpy(dataptr + 6, DOS_GetVolumeLabel(drive), 8);
+	strncpy(dataptr + 0x11, "FAT16   ", 8);
 	
-	EAX = (EAX & 0xffffff00L) | NoError;
+	EAX = (EAX & 0xffffff00L);
 	ResetCflag;
 }
 
-void SetDiskSerialNumber(struct sigcontext_struct *context)
+static void SetDiskSerialNumber(struct sigcontext_struct *context)
 {
+	int drive;
+	BYTE *dataptr = pointer(DS, DX);
+	DWORD serialnumber;
+
+	if ((EBX & 0xffL) == 0)
+		drive = DOS_GetDefaultDrive();
+	else
+		drive = (EBX & 0xffL) - 1;
+
+	if (!DOS_ValidDrive(drive)) {
+		EAX = (EAX & 0xffffff00L) | InvalidDrive;
+		SetCflag;
+		return;
+	}
+
+	serialnumber = dataptr[1] + (dataptr[2] << 8) + (dataptr[3] << 16) + 
+			(dataptr[4] << 24);
+
+	DOS_SetSerialNumber(drive, serialnumber);
 	EAX = (EAX & 0xffffff00L) | 1L;
 	ResetCflag;
 }
 
+static void DumpFCB(BYTE *fcb)
+{
+	int x, y;
+
+	fcb -= 7;
+
+	for (y = 0; y !=2 ; y++) {
+		for (x = 0; x!=15;x++)
+			fprintf(stderr, "%02x ", *fcb++);
+		fprintf(stderr,"\n");
+	}
+}
+
+/* microsoft's programmers should be shot for using CP/M style int21
+   calls in Windows for Workgroup's winfile.exe */
+
+static void FindFirstFCB(struct sigcontext_struct *context)
+{
+	BYTE *fcb = pointer(DS, DX);
+	int drive;
+
+	DumpFCB( fcb );
+
+	if (*fcb)
+		drive = *fcb - 1;
+	else
+		drive = DOS_GetDefaultDrive();
+
+	if (*(fcb - 7) == 0xff) {
+		if (*(fcb - 1) == FA_DIREC) {
+			/* return volume label */
+
+			memset(dta, ' ', 11);
+			if (DOS_GetVolumeLabel(drive) != NULL) 
+				strncpy(dta, DOS_GetVolumeLabel(drive), 8);
+			*(dta + 0x0b) = FA_DIREC;
+
+			EAX = (EAX & 0xffffff00L);
+			return;
+		}
+	}
+	Barf(context);
+}
+
+static void DeleteFileFCB(struct sigcontext_struct *context)
+{
+	BYTE *fcb = pointer(DS, DX);
+	int drive;
+	struct dosdirent *dp;
+	char temp[256], *ptr;
+
+	DumpFCB( fcb );
+
+	if (*fcb)
+		drive = *fcb - 1;
+	else
+		drive = DOS_GetDefaultDrive();
+
+	strcpy(temp, DOS_GetCurrentDir(drive));
+	strcat(temp, "\\");
+	strncat(temp, fcb + 1, 8);
+	ChopOffWhiteSpace(temp);
+	strncat(temp, fcb + 9, 3);
+	ChopOffWhiteSpace(temp);
+
+	if ((dp = DOS_opendir(temp)) == NULL) {
+		Error(InvalidDrive, EC_MediaError , EL_Disk);
+		EAX = (EAX & 0xffffff00L) | 0xffL;
+		return;
+	}
+
+	strcpy(temp, DOS_GetCurrentDir(drive) );
+	strcat(temp, "\\");
+	
+	ptr = temp + strlen(temp);
+	
+	while (DOS_readdir(dp) != NULL)
+	{
+		strcpy(ptr, dp->filename);
+		fprintf(stderr, "int21: delete file %s\n", temp);
+		/* unlink(GetUnixFileName(temp)); */
+	}
+
+	DOS_closedir(dp);
+	EAX = (EAX & 0xffffff00L);
+}
+
+static void RenameFileFCB(struct sigcontext_struct *context)
+{
+	BYTE *fcb = pointer(DS, DX);
+	int drive;
+	struct dosdirent *dp;
+	char temp[256], oldname[256], newname[256], *oldnameptr, *newnameptr;
+
+	DumpFCB( fcb );
+
+	if (*fcb)
+		drive = *fcb - 1;
+	else
+		drive = DOS_GetDefaultDrive();
+
+	strcpy(temp, DOS_GetCurrentDir(drive));
+	strcat(temp, "\\");
+	strncat(temp, fcb + 1, 8);
+	ChopOffWhiteSpace(temp);
+	strncat(temp, fcb + 9, 3);
+	ChopOffWhiteSpace(temp);
+
+	if ((dp = DOS_opendir(temp)) == NULL) {
+		Error(InvalidDrive, EC_MediaError , EL_Disk);
+		EAX = (EAX & 0xffffff00L) | 0xffL;
+		return;
+	}
+
+	strcpy(oldname, DOS_GetCurrentDir(drive) );
+	strcat(oldname, "\\");
+	oldnameptr = oldname + strlen(oldname);
+
+	strcpy(newname, DOS_GetCurrentDir(drive) );
+	strcat(newname, "\\");
+	newnameptr = newname + strlen(newname);
+	
+	while (DOS_readdir(dp) != NULL)
+	{
+		strcpy(oldnameptr, dp->filename);
+		strcpy(newnameptr, fcb + 1);
+		fprintf(stderr, "int21: renamefile %s -> %s\n", oldname, newname);
+	}
+
+	DOS_closedir(dp);
+	EAX = (EAX & 0xffffff00L);
+}
+
 /************************************************************************/
 
 int do_int21(struct sigcontext_struct * context)
 {
-	int ah;
+    int ah;
 
-	fprintf(stderr, "int21: AX %04x, BX %04x, CX %04x, DX %04x, SI %04x, DI %04x, DS %04x, ES %04x\n",
-				AX, BX, CX, DX, SI, DI, DS, ES);
+    if (Options.relay_debug)
+    {
+	printf("int21: AX %04x, BX %04x, CX %04x, DX %04x, "
+	       "SI %04x, DI %04x, DS %04x, ES %04x\n",
+	       AX, BX, CX, DX, SI, DI, DS, ES);
+    }
 
-	ah = (EAX >> 8) & 0xffL;
+    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;
-	};
-	}
+    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 0x0f: /* OPEN FILE USING FCB */
+	  case 0x10: /* CLOSE FILE USING FCB */
+	  case 0x12: /* FIND NEXT MATCHING 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 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 0x26: /* CREATE NEW PROGRAM SEGMENT PREFIX */
+	  case 0x27: /* RANDOM BLOCK READ FROM FCB FILE */
+	  case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */
+	  case 0x29: /* PARSE FILENAME INTO FCB */
+	  case 0x2e: /* SET VERIFY FLAG */
+	    Barf(context);
+	    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 */
+            Barf(context);
+	    EAX &= 0xff00;
+	    break;
+	
+	  case 0x0d: /* DISK BUFFER FLUSH */
+            ResetCflag; /* dos 6+ only */
+            break;
+
+	  case 0x0e: /* SELECT DEFAULT DRIVE */
+	    SetDefaultDrive(context);
+	    break;
+
+	  case 0x11: /* FIND FIRST MATCHING FILE USING FCB */
+            FindFirstFCB(context);
+            break;
+
+	  case 0x13: /* DELETE FILE USING FCB */
+            DeleteFileFCB(context);
+            break;
+            
+	  case 0x17: /* RENAME FILE USING FCB */
+            RenameFileFCB(context);
+            break;
+
+	  case 0x19: /* GET CURRENT DEFAULT DRIVE */
+	    GetDefaultDrive(context);
+	    break;
+	    
+	  case 0x1a: /* SET DISK TRANSFER AREA ADDRESS */
+            dta = pointer(DS, DX);
+            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 */
+	    GetDrivePB(context);
+	    break;
+		
+	  case 0x25: /* SET INTERRUPT VECTOR */
+	    /* Ignore any attempt to set a segment vector */
+ 		fprintf(stderr, "int21: set interrupt vector %2x (%04x:%04x)\n", AX & 0xff, DS, DX);
+            break;
+
+	  case 0x2a: /* GET SYSTEM DATE */
+	    GetSystemDate(context);
+            break;
+
+	  case 0x2c: /* GET SYSTEM TIME */
+	    GetSystemTime(context);
+	    break;
+
+	  case 0x2f: /* GET DISK TRANSFER AREA ADDRESS */
+            ES = segment(dta);
+            EBX = (EBX & 0xffff0000L) | offset(dta);
+            break;
+            
+	  case 0x30: /* GET DOS VERSION */
+	    EAX = (EAX & 0xffff0000L) | DOSVERSION;
+	    EBX = (EBX & 0xffff0000L) | 0x0012;     /* 0x123456 is Wine's serial # */
+	    ECX = (ECX & 0xffff0000L) | 0x3456;
+	    break;
+
+	  case 0x31: /* TERMINATE AND STAY RESIDENT */
+            Barf(context);
+	    break;
+
+	  case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
+	    GetDrivePB(context);
+	    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 */
+	    fprintf(stderr, "int21: get interrupt vector %2x\n", AX & 0xff);
+	    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 & 0xffL) 
+	    {
+	      case 0x00:
+		GetFileAttributes(context);
+		break;
+	      case 0x01:
+		SetFileAttributes(context);
+		break;
+	    }
+	    break;
+		
+	  case 0x44: /* IOCTL */
+	    switch (EAX & 0xff) 
+	    {
+              case 0x00:
+                ioctlGetDeviceInfo(context);
+		break;
+		                
+              case 0x0d:
+                ioctlGenericBlkDevReq(context);
+                break;
+                
+	      default:
+                Barf(context);
+		break;
+	    }
+	    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; 
+	    /* intlist: 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(EAX & 0xffL);
+	    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 & 0xffL) 
+	    {
+	      case 0x00:
+		GetFileDateTime(context);
+		break;
+	      case 0x01:
+		SetFileDateTime(context);
+		break;
+	    }
+	    break;
+
+	  case 0x58: /* GET OR SET MEMORY/UMB ALLOCATION STRATEGY */
+	    switch (EAX & 0xffL) 
+	    {
+	      case 0x00:
+		EAX = (EAX & 0xffffff00L) | 0x01L;
+		break;
+	      case 0x02:
+		EAX &= 0xff00L;
+		break;
+	      case 0x01:
+	      case 0x03:
+		break;
+	    }
+	    ResetCflag;
+	    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:
+	    /* network software not installed */
+	    EAX = (EAX & 0xfffff00L) | NoNetwork;
+	    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:
+		/* network software not installed */
+		EAX = (EAX & 0xfffff00L) | NoNetwork; 
+		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 = BX;
+		ResetCflag;
+		break;			
+	      case 0x02: 
+		CodePage = BX;
+		ResetCflag;
+		break;
+	    }
+	    break;
+
+	  case 0x68: /* "FFLUSH" - COMMIT FILE */
+	    ResetCflag;
+	    break;		
+	
+	  case 0x69: /* DISK SERIAL NUMBER */
+	    switch (EAX & 0xffL) 
+	    {
+	      case 0x00:
+		GetDiskSerialNumber(context);
+		break;			
+	      case 0x01: 
+		SetDiskSerialNumber(context);
+		break;
+	    }
+	    break;
+
+	  case 0x6a: /* COMMIT FILE */
+	    ResetCflag;
+	    break;		
+
+	  case 0x67: /* SET HANDLE COUNT */			
+	    ResetCflag;
+	    break;
+
+	  default:
+            Barf(context);
+	    return 1;
+	}
+    }
+    return 1;
 }
 
 /**********************************************************************
  *			DOS3Call
  */
-int DOS3Call()
+void DOS3Call()
 {
-	static struct sigcontext_struct *context = NULL;
-	
-	if (!context) 
-		context = malloc(sizeof(struct sigcontext_struct));
-
-/*	fprintf(stderr, "DOS3: AX %04x, BX %04x, CX %04x, DX %04x, SI %04x, DI %04x, DS %04x, ES %04x\n",
-				_AX, _BX, _CX, _DX, _SI, _DI, _DS, _ES);
-*/
-	EAX = _AX;
-	EBX = _BX;
-	ECX = _CX;
-	EDX = _DX;
-	DS = _DS;
-	ES = _ES;
-	DI = _DI;
-	SI = _SI;
-/*	EFL = _FL;
-*/
-	do_int21(context);
-
-	_AX = AX;
-	_BX = BX;
-	_CX = CX;
-	_DX = DX;
-	
-	_DS = DS;
-	_ES = ES;
-
-	_DI = DI;
-	_SI = SI;
-/*	_FL = EFL;
- */
-	return 0;
+    do_int21((struct sigcontext_struct *) _CONTEXT);
+    ReturnFromRegisterFunc();
 }
diff --git a/miscemu/int25.c b/miscemu/int25.c
new file mode 100644
index 0000000..f08c7a9
--- /dev/null
+++ b/miscemu/int25.c
@@ -0,0 +1,30 @@
+#include <stdio.h>
+#include "msdos.h"
+#include "wine.h"
+
+int do_int25(struct sigcontext_struct *context)
+{
+	BYTE *dataptr = pointer(DS, BX);
+	DWORD begin, length;
+
+	if( (ECX & 0xffff) == 0xffff)
+	{
+		begin = getdword(dataptr);
+
+		length = getword(&dataptr[4]);
+
+		dataptr = (BYTE *) getdword(&dataptr[6]);
+			
+		fprintf(stderr, "int25: abs diskread, drive %d, sector %d, "
+	"count %d, buffer %d\n", EAX & 0xff, begin, length, (int) dataptr);
+	}
+
+	begin = EDX & 0xffff;
+	length = ECX & 0xffff;
+	
+	fprintf(stderr,"int25: abs diskread-2, drive %d, sector %d, count %d,"
+		" buffer %d\n", EAX & 0xff, begin, length, (int) dataptr);
+
+	ResetCflag;
+	return 1;
+}
diff --git a/miscemu/int26.c b/miscemu/int26.c
new file mode 100644
index 0000000..c4f8464
--- /dev/null
+++ b/miscemu/int26.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include "msdos.h"
+#include "wine.h"
+
+int do_int26(struct sigcontext_struct *context)
+{
+	BYTE *dataptr = pointer(DS, BX);
+	DWORD begin, length;
+
+	if( (ECX & 0xffff) == 0xffff)
+	{
+		begin = getdword(dataptr);
+		length = getword(&dataptr[4]);
+		dataptr = (BYTE *) getdword(&dataptr[6]);
+			
+		fprintf(stderr, "int26: abs diskread, drive %d, sector %d, "
+	"count %d, buffer %d\n", EAX & 0xff, begin, length, (int) dataptr);
+	}
+
+	begin = EDX & 0xffff;
+	length = ECX & 0xffff;
+	
+	fprintf(stderr,"int26: abs diskread-2, drive %d, sector %d, count %d,"
+		" buffer %d\n", EAX & 0xff, begin, length, (int) dataptr);
+
+	ResetCflag;
+	return 1;
+}
diff --git a/miscemu/ioports.c b/miscemu/ioports.c
new file mode 100644
index 0000000..44fa971
--- /dev/null
+++ b/miscemu/ioports.c
@@ -0,0 +1,60 @@
+#include <stdio.h>
+#include <time.h>
+#include "msdos.h"
+#include "wine.h"
+
+static BYTE cmosaddress;
+
+static BYTE cmosimage[64] = {
+	0x27, 0x34, 0x31, 0x47, 0x16, 0x15, 0x00, 0x01,
+	0x04, 0x94, 0x26, 0x02, 0x50, 0x80, 0x00, 0x00,
+	0x40, 0xb1, 0x00, 0x9c, 0x01, 0x80, 0x02, 0x00,
+	0x1c, 0x00, 0x00, 0xad, 0x02, 0x10, 0x00, 0x00,
+	0x08, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x03, 0x58,
+	0x00, 0x1c, 0x19, 0x81, 0x00, 0x0e, 0x00, 0x80,
+	0x1b, 0x7b, 0x21, 0x00, 0x00, 0x00, 0x05, 0x5f };
+
+void inportb(struct sigcontext_struct *context)
+{
+	fprintf(stderr, "IO: inb (%x)\n", EDX & 0xffff);
+
+	switch(EDX & 0xffff)
+	{
+		case 0x70:
+			EAX = (EAX & 0xffffff00L) | cmosaddress;
+			break;
+		case 0x71:
+			EAX = (EAX & 0xffffff00L) | cmosimage[cmosaddress & 0x3f];
+			break;
+		default:
+	}
+}
+
+void inport(struct sigcontext_struct *context)
+{
+	fprintf(stderr, "IO: in (%x)\n", EDX & 0xffff);
+
+	EAX = (EAX & 0xffff0000L) | 0xffff;
+}
+
+void outportb(struct sigcontext_struct *context)
+{
+	fprintf(stderr, "IO: outb (%x), %x\n", EDX & 0xffff, EAX & 0xff);
+
+	switch (EDX & 0xffff)
+	{
+		case 0x70:
+			cmosaddress = EAX & 0xff;
+			break;
+		case 0x71:
+			cmosimage[cmosaddress & 0x3f] = EAX & 0xff;
+			break;
+		default:
+	}
+}
+
+void outport(struct sigcontext_struct *context)
+{
+	fprintf(stderr, "IO: out (%x), %x\n", EDX & 0xffff, EAX & 0xffff);
+}
diff --git a/objects/Imakefile b/objects/Imakefile
index 458761d..bce8061 100644
--- a/objects/Imakefile
+++ b/objects/Imakefile
@@ -16,7 +16,8 @@
 	clipping.c \
 	bitblt.c \
 	linedda.c \
-	color.c
+	color.c \
+	dither.c
 
 OBJS = \
 	bitmap.o \
@@ -32,7 +33,8 @@
 	clipping.o \
 	bitblt.o \
 	linedda.o \
-	color.o
+	color.o \
+	dither.o
 
 WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
 DependTarget()
diff --git a/objects/bitblt.c b/objects/bitblt.c
index bbfa3bd..992f7ca 100644
--- a/objects/bitblt.c
+++ b/objects/bitblt.c
@@ -314,7 +314,7 @@
     sxi = XGetImage(display, dcSrc->u.x.drawable, xs1, ys1, 
 	     widthSrc, heightSrc, AllPlanes, ZPixmap);
     dxi = XCreateImage(display, DefaultVisualOfScreen(screen),
-	  		    DefaultDepthOfScreen(screen), ZPixmap, 
+	  		    screenDepth, ZPixmap,
 			    0, NULL, widthDest, heightDest,
 			    32, 0);
     dxi->data = malloc(dxi->bytes_per_line * heightDest);
diff --git a/objects/bitmap.c b/objects/bitmap.c
index ffec3e9..6c21e0c 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -6,22 +6,18 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
 #include "gdi.h"
+#include "bitmap.h"
 
-/* A GDI bitmap object contains a handle to a packed BITMAP,
- * which is stored on the global heap.
- * A packed BITMAP is a BITMAP structure followed by the bitmap bits.
- */
 
   /* Handle of the bitmap selected by default in a memory DC */
-HBITMAP BITMAP_hbitmapMemDC;
+HBITMAP BITMAP_hbitmapMemDC = 0;
 
-  /* List of supported depths */
-static int depthCount;
-static int * depthList;
-
-  /* List of GC used for bitmap to pixmap operations (one for each depth) */
-static GC * bitmapGC;
+  /* GCs used for B&W and color bitmap operations */
+GC BITMAP_monoGC = 0, BITMAP_colorGC = 0;
 
 
 /***********************************************************************
@@ -29,27 +25,25 @@
  */
 BOOL BITMAP_Init()
 {
-    int i;
     Pixmap tmpPixmap;
     
-    depthList = XListDepths( XT_display, DefaultScreen(XT_display), 
-			     &depthCount );
-    if (!depthList || !depthCount) return FALSE;
-    if (!(bitmapGC = (GC *) malloc( depthCount * sizeof(GC) ))) return FALSE;
-    
       /* Create the necessary GCs */
     
-    for (i = 0; i < depthCount; i++)
+    if ((tmpPixmap = XCreatePixmap( display, rootWindow, 1, 1, 1 )))
     {
-	tmpPixmap = XCreatePixmap( XT_display, DefaultRootWindow(XT_display),
-				  1, 1, depthList[i] );
-	if (tmpPixmap)
+	BITMAP_monoGC = XCreateGC( display, tmpPixmap, 0, NULL );
+	XSetGraphicsExposures( display, BITMAP_monoGC, False );
+	XFreePixmap( display, tmpPixmap );
+    }
+
+    if (screenDepth != 1)
+    {
+	if ((tmpPixmap = XCreatePixmap(display, rootWindow, 1,1,screenDepth)))
 	{
-	    bitmapGC[i] = XCreateGC( XT_display, tmpPixmap, 0, NULL );
-	    XSetGraphicsExposures( XT_display, bitmapGC[i], False );
-	    XFreePixmap( XT_display, tmpPixmap );
+	    BITMAP_colorGC = XCreateGC( display, tmpPixmap, 0, NULL );
+	    XSetGraphicsExposures( display, BITMAP_colorGC, False );
+	    XFreePixmap( display, tmpPixmap );
 	}
-	else bitmapGC[i] = 0;
     }
 
     BITMAP_hbitmapMemDC = CreateBitmap( 1, 1, 1, 1, NULL );
@@ -58,26 +52,13 @@
 
 
 /***********************************************************************
- *           BITMAP_FindGCForDepth
- *
- * Return a GC appropriate for operations with the given depth.
- */
-GC BITMAP_FindGCForDepth( int depth )
-{
-    int i;
-    for (i = 0; i < depthCount; i++)
-	if (depthList[i] == depth) return bitmapGC[i];
-    return 0;
-}
-
-
-/***********************************************************************
  *           BITMAP_BmpToImage
  *
  * Create an XImage pointing to the bitmap data.
  */
-XImage * BITMAP_BmpToImage( BITMAP * bmp, void * bmpData )
+static XImage *BITMAP_BmpToImage( BITMAP * bmp, void * bmpData )
 {
+    extern void _XInitImageFuncPtrs( XImage* );
     XImage * image;
 
     image = XCreateImage( XT_display, DefaultVisualOfScreen(XT_screen),
@@ -93,57 +74,6 @@
 
 
 /***********************************************************************
- *           BITMAP_CopyToPixmap
- *
- * Copy the content of the bitmap to the pixmap. Both must have the same depth.
- */
-BOOL BITMAP_CopyToPixmap( BITMAP * bmp, Pixmap pixmap,
-			  int x, int y, int width, int height )
-{
-    GC gc;
-    XImage * image;
-    
-    gc = BITMAP_FindGCForDepth( bmp->bmBitsPixel );
-    if (!gc) return FALSE;
-    
-    image = BITMAP_BmpToImage( bmp, ((char *)bmp) + sizeof(BITMAP) );
-    if (!image) return FALSE;
-
-#ifdef DEBUG_GDI
-    printf( "BITMAP_CopyToPixmap: %dx%d %d colors -> %d,%d %dx%d\n",
-	    bmp->bmWidth, bmp->bmHeight, 1 << bmp->bmBitsPixel, x, y, width, height );
-#endif
-    XPutImage(XT_display, pixmap, gc, image, 0, 0, x, y, width, height); 
-    image->data = NULL;
-    XDestroyImage( image );
-    return TRUE;
-}
-
-
-/***********************************************************************
- *           BITMAP_CopyFromPixmap
- *
- * Copy the content of the pixmap to the bitmap. Both must have
- * the same dimensions and depth.
- */
-BOOL BITMAP_CopyFromPixmap( BITMAP * bmp, Pixmap pixmap )
-{
-    XImage *image = BITMAP_BmpToImage( bmp, ((char *)bmp) + sizeof(BITMAP) );
-    if (!image) return FALSE;
-
-#ifdef DEBUG_GDI
-    printf( "BITMAP_CopyFromPixmap: %dx%d %d colors\n",
-	    bmp->bmWidth, bmp->bmHeight, 1 << bmp->bmBitsPixel );
-#endif    
-    XGetSubImage( XT_display, pixmap, 0, 0, bmp->bmWidth, bmp->bmHeight,
-		  AllPlanes, ZPixmap, image, 0, 0 );
-    image->data = NULL;
-    XDestroyImage( image );
-    return TRUE;
-}
-
-
-/***********************************************************************
  *           CreateBitmap    (GDI.48)
  */
 HBITMAP CreateBitmap( short width, short height, 
@@ -154,9 +84,6 @@
     printf( "CreateBitmap: %dx%d, %d colors\n", 
 	     width, height, 1 << (planes*bpp) );
 #endif
-    if (!width || !height) return 0;
-    if ((planes != 1) && (bpp != 1)) return 0;
-    bitmap.bmWidthBytes = (width * bpp + 15) / 16 * 2;
     return CreateBitmapIndirect( &bitmap );
 }
 
@@ -166,15 +93,12 @@
  */
 HBITMAP CreateCompatibleBitmap( HDC hdc, short width, short height )
 {
-    HBITMAP hbitmap;
     DC * dc;
 #ifdef DEBUG_GDI
     printf( "CreateCompatibleBitmap: %d %dx%d\n", hdc, width, height );
 #endif
-    dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return 0;
-    hbitmap = CreateBitmap( width, height, dc->w.planes, dc->w.bitsPerPixel, NULL);
-    return hbitmap;
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+    return CreateBitmap( width, height, 1, dc->w.bitsPerPixel, NULL );
 }
 
 
@@ -184,72 +108,34 @@
 HBITMAP CreateBitmapIndirect( BITMAP * bmp )
 {
     BITMAPOBJ * bmpObjPtr;
-    char * bmpPtr;
     HBITMAP hbitmap;
-    int size = bmp->bmPlanes * bmp->bmHeight * bmp->bmWidthBytes;
-    
-      /* Create the BITMAPOBJ */
 
+      /* Check parameters */
+    if (!bmp->bmHeight || !bmp->bmWidth) return 0;
+    if (bmp->bmPlanes != 1) return 0;
+    if ((bmp->bmBitsPixel != 1) && (bmp->bmBitsPixel != screenDepth)) return 0;
+
+      /* Create the BITMAPOBJ */
     hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC );
     if (!hbitmap) return 0;
     bmpObjPtr = (BITMAPOBJ *) GDI_HEAP_ADDR( hbitmap );
-    
-      /* Create the bitmap in global heap */
 
-    bmpObjPtr->hBitmap = GlobalAlloc( GMEM_MOVEABLE, sizeof(BITMAP) + size );
-    if (!bmpObjPtr->hBitmap)
+    bmpObjPtr->size.cx = 0;
+    bmpObjPtr->size.cy = 0;
+    bmpObjPtr->bitmap  = *bmp;
+    bmpObjPtr->bitmap.bmBits = NULL;
+    bmpObjPtr->bitmap.bmWidthBytes = (bmp->bmWidth*bmp->bmBitsPixel+15)/16 * 2;
+
+      /* Create the pixmap */
+    bmpObjPtr->pixmap = XCreatePixmap( display, rootWindow, bmp->bmWidth,
+				       bmp->bmHeight, bmp->bmBitsPixel );
+    if (!bmpObjPtr->pixmap)
     {
-	GDI_FreeObject( hbitmap );
-	return 0;
+	GDI_HEAP_FREE( hbitmap );
+	hbitmap = 0;
     }
-    bmpPtr = (char *) GlobalLock( bmpObjPtr->hBitmap );
-    memcpy( bmpPtr, bmp, sizeof(BITMAP) );
-    ((BITMAP *)bmpPtr)->bmBits = NULL;
-    if (bmp->bmBits) memcpy( bmpPtr + sizeof(BITMAP), bmp->bmBits, size );
-    GlobalUnlock( bmpObjPtr->hBitmap );
-
-    bmpObjPtr->bSelected = FALSE;
-    bmpObjPtr->hdc       = 0;
-    bmpObjPtr->size.cx   = 0;
-    bmpObjPtr->size.cy   = 0;
-    return hbitmap;
-}
-
-
-/***********************************************************************
- *           BITMAP_GetSetBitmapBits
- */
-LONG BITMAP_GetSetBitmapBits( HBITMAP hbitmap, LONG count,
-			      LPSTR buffer, int set )
-{
-    BITMAPOBJ * bmpObjPtr;
-    BITMAP * bmp;
-    DC * dc = NULL;
-    int maxSize;
-    
-    if (!count) return 0;
-    bmpObjPtr = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
-    if (!bmpObjPtr) return 0;
-    if (!(bmp = (BITMAP *) GlobalLock( bmpObjPtr->hBitmap ))) return 0;
-    
-    if (bmpObjPtr->bSelected) 
-	dc = (DC *) GDI_GetObjPtr( bmpObjPtr->hdc, DC_MAGIC );
-
-    maxSize = bmp->bmPlanes * bmp->bmHeight * bmp->bmWidthBytes;
-    if (count > maxSize) count = maxSize;
-    	
-    if (set)
-    {
-	memcpy( bmp+1, buffer, count );
-	if (dc) BITMAP_CopyToPixmap( bmp, dc->u.x.drawable,
-				     0, 0, bmp->bmWidth, bmp->bmHeight );
-    }
-    else
-    {
-	if (dc) BITMAP_CopyFromPixmap( bmp, dc->u.x.drawable );
-	memcpy( buffer, bmp+1, count );
-    }
-    GlobalUnlock( bmpObjPtr->hBitmap );
+    else if (bmp->bmBits)  /* Set bitmap bits */
+	SetBitmapBits( hbitmap, bmp->bmHeight*bmp->bmWidthBytes, bmp->bmBits );
     return hbitmap;
 }
 
@@ -259,7 +145,29 @@
  */
 LONG GetBitmapBits( HBITMAP hbitmap, LONG count, LPSTR buffer )
 {
-    return BITMAP_GetSetBitmapBits( hbitmap, count, buffer, 0 );
+    BITMAPOBJ * bmp;
+    LONG height;
+    XImage * image;
+    
+    bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
+    if (!bmp) return 0;
+
+#ifdef DEBUG_BITMAP
+    printf( "GetBitmapBits: %dx%d %d colors %p\n",
+	    bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
+	    1 << bmp->bitmap.bmBitsPixel, buffer );
+#endif
+      /* Only get entire lines */
+    height = count / bmp->bitmap.bmWidthBytes;
+    if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
+    if (!height) return 0;
+    
+    if (!(image = BITMAP_BmpToImage( &bmp->bitmap, buffer ))) return 0;
+    XGetSubImage( display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth, height,
+		  AllPlanes, ZPixmap, image, 0, 0 );
+    image->data = NULL;
+    XDestroyImage( image );
+    return height * bmp->bitmap.bmWidthBytes;
 }
 
 
@@ -268,7 +176,29 @@
  */
 LONG SetBitmapBits( HBITMAP hbitmap, LONG count, LPSTR buffer )
 {
-    return BITMAP_GetSetBitmapBits( hbitmap, count, buffer, 1 );
+    BITMAPOBJ * bmp;
+    LONG height;
+    XImage * image;
+    
+    bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
+    if (!bmp) return 0;
+
+#ifdef DEBUG_BITMAP
+    printf( "SetBitmapBits: %dx%d %d colors %p\n",
+	    bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
+	    1 << bmp->bitmap.bmBitsPixel, buffer );
+#endif
+      /* Only set entire lines */
+    height = count / bmp->bitmap.bmWidthBytes;
+    if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
+    if (!height) return 0;
+    	
+    if (!(image = BITMAP_BmpToImage( &bmp->bitmap, buffer ))) return 0;
+    XPutImage( display, bmp->pixmap, BITMAP_GC(bmp), image, 0, 0,
+	       0, 0, bmp->bitmap.bmWidth, height );
+    image->data = NULL;
+    XDestroyImage( image );
+    return height * bmp->bitmap.bmWidthBytes;
 }
 
 
@@ -277,8 +207,7 @@
  */
 BOOL BMP_DeleteObject( HBITMAP hbitmap, BITMAPOBJ * bitmap )
 {
-      /* Free bitmap on global heap */
-    GlobalFree( bitmap->hBitmap );
+    XFreePixmap( display, bitmap->pixmap );
     return GDI_FreeObject( hbitmap );
 }
 
@@ -286,95 +215,39 @@
 /***********************************************************************
  *           BMP_GetObject
  */
-int BMP_GetObject( BITMAPOBJ * bitmap, int count, LPSTR buffer )
+int BMP_GetObject( BITMAPOBJ * bmp, int count, LPSTR buffer )
 {
-    char * bmpPtr = (char *) GlobalLock( bitmap->hBitmap );    
     if (count > sizeof(BITMAP)) count = sizeof(BITMAP);
-    memcpy( buffer, bmpPtr, count );
-    GlobalUnlock( bitmap->hBitmap );
+    memcpy( buffer, &bmp->bitmap, count );
     return count;
 }
-
     
-/***********************************************************************
- *           BITMAP_UnselectBitmap
- *
- * Unselect the bitmap from the DC. Used by SelectObject and DeleteDC.
- */
-BOOL BITMAP_UnselectBitmap( DC * dc )
-{
-    BITMAPOBJ * bmp;
-    BITMAP * bmpPtr;
-
-    if (!dc->w.hBitmap) return TRUE;
-    bmp = (BITMAPOBJ *) GDI_GetObjPtr( dc->w.hBitmap, BITMAP_MAGIC );
-    if (!bmp) return FALSE;
-    
-    if (!(bmpPtr = (BITMAP *) GlobalLock( bmp->hBitmap ))) return FALSE;
-    
-    BITMAP_CopyFromPixmap( bmpPtr, dc->u.x.drawable );
-    XFreePixmap( XT_display, dc->u.x.drawable );
-    bmp->bSelected = FALSE;
-    bmp->hdc       = 0;
-    GlobalUnlock( bmp->hBitmap );
-    return TRUE;
-}
-
 
 /***********************************************************************
  *           BITMAP_SelectObject
  */
 HBITMAP BITMAP_SelectObject( HDC hdc, DC * dc, HBITMAP hbitmap,
-			     BITMAPOBJ * bitmap )
+			     BITMAPOBJ * bmp )
 {
-    BITMAP * bmp;
     HBITMAP prevHandle = dc->w.hBitmap;
     
     if (!(dc->w.flags & DC_MEMORY)) return 0;
-    if (bitmap->bSelected && hbitmap != BITMAP_hbitmapMemDC) return 0;
-    if (!(bmp = (BITMAP *) GlobalLock( bitmap->hBitmap ))) return 0;
-
-      /* Make sure the bitmap has the right format */
-
-    if ((bmp->bmPlanes != 1) || !BITMAP_FindGCForDepth( bmp->bmBitsPixel ))
-    {
-	GlobalUnlock( bitmap->hBitmap );
-	return 0;
-    }
-    
-      /* Unselect the previous bitmap */
-
-    if (!BITMAP_UnselectBitmap( dc ))
-    {
-	GlobalUnlock( bitmap->hBitmap );
-	return 0;
-    }
-    
-      /* Create the pixmap */
-    
-    dc->u.x.drawable   = XCreatePixmap( XT_display,
-				        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 );
+    dc->u.x.drawable = bmp->pixmap;
+    dc->w.DCSizeX    = bmp->bitmap.bmWidth;
+    dc->w.DCSizeY    = bmp->bitmap.bmHeight;
+    dc->w.hBitmap    = hbitmap;
 
       /* Change GC depth if needed */
 
-    if (dc->w.bitsPerPixel != bmp->bmBitsPixel)
+    if (dc->w.bitsPerPixel != bmp->bitmap.bmBitsPixel)
     {
-	XFreeGC( XT_display, dc->u.x.gc );
-	dc->u.x.gc = XCreateGC( XT_display, dc->u.x.drawable, 0, NULL );
-	dc->w.bitsPerPixel = bmp->bmBitsPixel;
-	DC_SetDeviceInfo( hdc, dc );
+	XFreeGC( display, dc->u.x.gc );
+	dc->u.x.gc = XCreateGC( display, dc->u.x.drawable, 0, NULL );
+	dc->w.bitsPerPixel = bmp->bitmap.bmBitsPixel;
+	  /* Re-select objects with changed depth */
+	SelectObject( hdc, dc->w.hPen );
+	SelectObject( hdc, dc->w.hBrush );
     }
-    
-    GlobalUnlock( bitmap->hBitmap );
-    dc->w.hBitmap     = hbitmap;
-    bitmap->bSelected = TRUE;
-    bitmap->hdc       = hdc;
     return prevHandle;
 }
 
diff --git a/objects/brush.c b/objects/brush.c
index 582349e..9464184 100644
--- a/objects/brush.c
+++ b/objects/brush.c
@@ -7,6 +7,8 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 #include "gdi.h"
+#include "bitmap.h"
+#include "prototypes.h"
 
 
 #define NB_HATCH_STYLES  6
@@ -21,7 +23,8 @@
     { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 }  /* HS_DIAGCROSS  */
 };
 
-extern XImage * BITMAP_BmpToImage( BITMAP *, void * );
+extern WORD COLOR_ToPhysical( DC *dc, COLORREF color );
+
 
 /***********************************************************************
  *           CreateBrushIndirect    (GDI.50)
@@ -57,23 +60,21 @@
 HBRUSH CreatePatternBrush( HBITMAP hbitmap )
 {
     LOGBRUSH logbrush = { BS_PATTERN, 0, 0 };
-    BITMAPOBJ * bmpObj;
-    BITMAP * bmp;
-    
+    BITMAPOBJ *bmp, *newbmp;
+
 #ifdef DEBUG_GDI
     printf( "CreatePatternBrush: %d\n", hbitmap );
 #endif
 
       /* Make a copy of the bitmap */
 
-    if (!(bmpObj = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
+    if (!(bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
 	return 0;
-    if (!(bmp = (BITMAP *) GlobalLock( bmpObj->hBitmap ))) return 0;    
-    logbrush.lbHatch = CreateBitmap( bmp->bmWidth, bmp->bmHeight,
-				     bmp->bmPlanes, bmp->bmBitsPixel,
-				     ((char *)bmp) + sizeof(BITMAP) );
-    GlobalUnlock( bmpObj->hBitmap );
-    if (!logbrush.lbHatch) return 0;
+    logbrush.lbHatch = CreateBitmapIndirect( &bmp->bitmap );
+    newbmp = (BITMAPOBJ *) GDI_GetObjPtr( logbrush.lbHatch, BITMAP_MAGIC );
+    if (!newbmp) return 0;
+    XCopyArea( display, bmp->pixmap, newbmp->pixmap, BITMAP_GC(bmp),
+	       0, 0, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight, 0, 0 );
     return CreateBrushIndirect( &logbrush );
 }
 
@@ -172,32 +173,46 @@
 
 
 /***********************************************************************
+ *           BRUSH_MakeSolidBrush
+ */
+static void BRUSH_SelectSolidBrush( DC *dc, COLORREF color )
+{
+    if ((dc->w.bitsPerPixel > 1) && !COLOR_IsSolid( color ))
+    {
+	  /* Dithered brush */
+	dc->u.x.brush.pixmap = DITHER_DitherColor( dc, color );
+	dc->u.x.brush.fillStyle = FillTiled;
+	dc->u.x.brush.pixel = 0;
+    }
+    else
+    {
+	  /* Solid brush */
+	dc->u.x.brush.pixel = COLOR_ToPhysical( dc, color );
+	dc->u.x.brush.fillStyle = FillSolid;
+    }
+}
+
+
+/***********************************************************************
  *           BRUSH_SelectPatternBrush
  */
-BOOL BRUSH_SelectPatternBrush( DC * dc, HBITMAP hbitmap )
+static BOOL BRUSH_SelectPatternBrush( DC * dc, HBITMAP hbitmap )
 {
-    BITMAPOBJ * bmpObjPtr;
-    BITMAP * bmp;
+    BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
+    if (!bmp) return FALSE;
+    dc->u.x.brush.pixmap = XCreatePixmap( display, rootWindow,
+					  8, 8, bmp->bitmap.bmBitsPixel );
+    XCopyArea( display, bmp->pixmap, dc->u.x.brush.pixmap,
+	       BITMAP_GC(bmp), 0, 0, 8, 8, 0, 0 );
     
-    bmpObjPtr = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
-    if (!bmpObjPtr) return FALSE;
-    if (!(bmp = (BITMAP *) GlobalLock( bmpObjPtr->hBitmap ))) return FALSE;
-
-    dc->u.x.brush.pixmap = XCreatePixmap( XT_display,
-					  DefaultRootWindow(XT_display),
-					  8, 8, bmp->bmBitsPixel );
-    BITMAP_CopyToPixmap( bmp, dc->u.x.brush.pixmap, 0, 0, 8, 8 );
-    
-    if (bmp->bmBitsPixel > 1)
+    if (bmp->bitmap.bmBitsPixel > 1)
     {
 	dc->u.x.brush.fillStyle = FillTiled;
-	XSetTile( XT_display, dc->u.x.gc, dc->u.x.brush.pixmap );
 	dc->u.x.brush.pixel = 0;  /* Ignored */
     }
     else
     {
 	dc->u.x.brush.fillStyle = FillOpaqueStippled;
-	XSetStipple( XT_display, dc->u.x.gc, dc->u.x.brush.pixmap );
 	dc->u.x.brush.pixel = -1;  /* Special case (see DC_SetupGCForBrush) */
     }
     return TRUE;
@@ -218,28 +233,24 @@
 
     if (dc->u.x.brush.pixmap)
     {
-	XFreePixmap( XT_display, dc->u.x.brush.pixmap );
+	XFreePixmap( display, dc->u.x.brush.pixmap );
 	dc->u.x.brush.pixmap = 0;
     }
     dc->u.x.brush.style = brush->logbrush.lbStyle;
     
     switch(brush->logbrush.lbStyle)
     {
-      case BS_SOLID:
       case BS_NULL:
-	dc->u.x.brush.pixel = GetNearestPaletteIndex( dc->w.hPalette, 
-						 brush->logbrush.lbColor );
-	dc->u.x.brush.fillStyle = FillSolid;
+	break;
+
+      case BS_SOLID:
+	BRUSH_SelectSolidBrush( dc, brush->logbrush.lbColor );
 	break;
 	
       case BS_HATCHED:
-	dc->u.x.brush.pixel = GetNearestPaletteIndex( dc->w.hPalette, 
-						 brush->logbrush.lbColor );
-	dc->u.x.brush.pixmap = XCreateBitmapFromData(XT_display, 
-					DefaultRootWindow(XT_display),
-					HatchBrushes[brush->logbrush.lbHatch],
-					8, 8 );
-	XSetStipple( XT_display, dc->u.x.gc, dc->u.x.brush.pixmap );
+	dc->u.x.brush.pixel = COLOR_ToPhysical( dc, brush->logbrush.lbColor );
+	dc->u.x.brush.pixmap = XCreateBitmapFromData( display, rootWindow,
+				 HatchBrushes[brush->logbrush.lbHatch], 8, 8 );
 	dc->u.x.brush.fillStyle = FillStippled;
 	break;
 	
@@ -264,5 +275,3 @@
     
     return prevHandle;
 }
-
-
diff --git a/objects/color.c b/objects/color.c
index 8eb9c2e..41f3ae6 100644
--- a/objects/color.c
+++ b/objects/color.c
@@ -11,55 +11,46 @@
 
 #include "windows.h"
 #include "options.h"
-
-extern Display * display;
-extern Screen * screen;
+#include "gdi.h"
 
 
 Colormap COLOR_WinColormap = 0;
 
+  /* System palette static colors */
 
-  /* System colors */
+#define NB_RESERVED_COLORS  20
 
-static const char * SysColors[] = 
+  /* The first and last eight colors are EGA colors */
+static PALETTEENTRY COLOR_sysPaletteEntries[NB_RESERVED_COLORS] =
 {
-      /* Low pixel values (0..7) */
+    /* red  green blue  flags */
+    { 0x00, 0x00, 0x00, 0 },
+    { 0x80, 0x00, 0x00, 0 },
+    { 0x00, 0x80, 0x00, 0 },
+    { 0x80, 0x80, 0x00, 0 },
+    { 0x00, 0x00, 0x80, 0 },
+    { 0x80, 0x00, 0x80, 0 },
+    { 0x00, 0x80, 0x80, 0 },
+    { 0xc0, 0xc0, 0xc0, 0 },
+    { 0xc0, 0xdc, 0xc0, 0 },
+    { 0xa6, 0xca, 0xf0, 0 },
 
-    "black", "red4", "green4", "yellow4",
-    "blue4", "magenta4", "cyan4", "gray50",
-
-      /* High pixel values (max-7..max) */
-
-    "gray75", "red", "green", "yellow",
-    "blue", "magenta", "cyan", "white"
+    { 0xff, 0xfb, 0xf0, 0 },
+    { 0xa0, 0xa0, 0xa4, 0 },
+    { 0x80, 0x80, 0x80, 0 },
+    { 0xff, 0x00, 0x00, 0 },
+    { 0x00, 0xff, 0x00, 0 },
+    { 0xff, 0xff, 0x00, 0 },
+    { 0x00, 0x00, 0xff, 0 },
+    { 0xff, 0x00, 0xff, 0 },
+    { 0x00, 0xff, 0xff, 0 },
+    { 0xff, 0xff, 0xff, 0 }
 };
 
-#define NB_SYS_COLORS   (sizeof(SysColors) / sizeof(SysColors[0]))
+static HANDLE hSysColorTranslation = 0;
 
-
-/***********************************************************************
- *           COLOR_FillDefaultMap
- *
- * Try to allocate colors from default screen map (used when we
- * don't want to or can't use a private map).
- */
-static int COLOR_FillDefaultMap()
-{
-    XColor color;
-    int i, total = 0;
-
-    for (i = 0; i < NB_SYS_COLORS; i++)
-    {
-	if (XParseColor( display, DefaultColormapOfScreen( screen ),
-			 SysColors[i], &color ))
-	{
-	    if (XAllocColor( display, DefaultColormapOfScreen( screen ), 
-			     &color ))
-		total++;
-	}
-    }
-    return total;
-}
+   /* Map an EGA index (0..15) to a pixel value. Used for dithering. */
+int COLOR_mapEGAPixel[16];
 
 
 /***********************************************************************
@@ -70,50 +61,108 @@
 static BOOL COLOR_BuildMap( Colormap map, int depth, int size )
 {
     XColor color;
-    int i;
+    int r, g, b, red_incr, green_incr, blue_incr;
+    int index = 0;
 
       /* Fill the whole map with a range of colors */
 
-    if ((1 << depth) > NB_SYS_COLORS)
-    {
-	int red_incr, green_incr, blue_incr;
-	int r, g, b;
-	
-	blue_incr  = 0x10000 >> (depth / 3);
-	red_incr   = 0x10000 >> ((depth + 1) / 3);
-	green_incr = 0x10000 >> ((depth + 2) / 3);
+    blue_incr  = 0x10000 >> (depth / 3);
+    red_incr   = 0x10000 >> ((depth + 1) / 3);
+    green_incr = 0x10000 >> ((depth + 2) / 3);
 
-	for (i = 0, r = red_incr - 1; r < 0x10000; r += red_incr)
-	    for (g = green_incr - 1; g < 0x10000; g += green_incr)
-		for (b = blue_incr - 1; b < 0x10000; b += blue_incr)
-		{
-		    if (i >= size) break;
-		    color.pixel = i++;
-		    color.red   = r;
-		    color.green = g;
-		    color.blue  = b;
-		    XStoreColor( display, map, &color );
-		}
-    }
-    
-      /* Store the system palette colors */
+    for (r = red_incr - 1; r < 0x10000; r += red_incr)
+	for (g = green_incr - 1; g < 0x10000; g += green_incr)
+	    for (b = blue_incr - 1; b < 0x10000; b += blue_incr)
+	    {
+		if (index >= size) break;
+		color.pixel = index++;
+		color.red   = r;
+		color.green = g;
+		color.blue  = b;
+		XStoreColor( display, map, &color );
+	    }
 
-    for (i = 0; i < NB_SYS_COLORS; i++)
-    {
-	if (!XParseColor( display, map, SysColors[i], &color ))
-	    color.red = color.green = color.blue = color.flags = 0;
-	if (i < NB_SYS_COLORS/2) color.pixel = i;
-	else color.pixel = (1 << depth) - NB_SYS_COLORS + i;
-	if (color.pixel < size) XStoreColor( display, map, &color );
-    }
     return TRUE;
 }
 
 
 /***********************************************************************
- *           COLOR_Init
+ *           COLOR_InitPalette
+ *
+ * Create the system palette.
  */
-BOOL COLOR_Init()
+static HPALETTE COLOR_InitPalette()
+{
+    int i, size;
+    XColor color;
+    HPALETTE hpalette;
+    LOGPALETTE * palPtr;
+    WORD *colorTranslation;
+
+    if (!(hSysColorTranslation = GDI_HEAP_ALLOC( GMEM_MOVEABLE,
+				   sizeof(WORD)*NB_RESERVED_COLORS ))) return FALSE;
+    colorTranslation = (WORD *) GDI_HEAP_ADDR( hSysColorTranslation );
+    size = DefaultVisual( display, DefaultScreen(display) )->map_entries;
+    for (i = 0; i < NB_RESERVED_COLORS; i++)
+    {
+	color.red   = COLOR_sysPaletteEntries[i].peRed * 65535 / 255;
+	color.green = COLOR_sysPaletteEntries[i].peGreen * 65535 / 255;
+	color.blue  = COLOR_sysPaletteEntries[i].peBlue * 65535 / 255;
+	color.flags = DoRed | DoGreen | DoBlue;
+
+	if (COLOR_WinColormap != DefaultColormapOfScreen(screen))
+	{
+	    if (i < NB_RESERVED_COLORS/2)
+	    {
+		  /* Bottom half of the colormap */
+		color.pixel = i;
+		if (color.pixel >= size/2) continue;
+	    }
+	    else
+	    {
+		  /* Top half of the colormap */
+		color.pixel = size - NB_RESERVED_COLORS + i;
+		if (color.pixel < size/2) continue;
+	    }
+	    XStoreColor( display, COLOR_WinColormap, &color );
+	}
+	else if (!XAllocColor( display, COLOR_WinColormap, &color ))
+	{
+	    printf( "Warning: Not enough free colors. Try using the -privatemap option.\n" );
+	    color.pixel = color.red = color.green = color.blue = 0;
+	}
+	colorTranslation[i] = color.pixel;
+#if 0
+	  /* Put the allocated colors back in the list */
+	COLOR_sysPaletteEntries[i].peRed   = color.red >> 8;
+	COLOR_sysPaletteEntries[i].peGreen = color.green >> 8;
+	COLOR_sysPaletteEntries[i].peBlue  = color.blue >> 8;
+#endif
+	  /* Set EGA mapping if color in the first or last eight */
+	if (i < 8)
+	    COLOR_mapEGAPixel[i] = color.pixel;
+	else if (i >= NB_RESERVED_COLORS-8)
+	    COLOR_mapEGAPixel[i - (NB_RESERVED_COLORS-16)] = color.pixel;
+    }
+
+    palPtr = malloc( sizeof(LOGPALETTE) + (NB_RESERVED_COLORS-1)*sizeof(PALETTEENTRY) );
+    if (!palPtr) return FALSE;
+    palPtr->palVersion = 0x300;
+    palPtr->palNumEntries = NB_RESERVED_COLORS;
+    memcpy( palPtr->palPalEntry, COLOR_sysPaletteEntries,
+	    sizeof(COLOR_sysPaletteEntries) );
+    hpalette = CreatePalette( palPtr );
+    free( palPtr );
+    return hpalette;
+}
+
+
+/***********************************************************************
+ *           COLOR_Init
+ *
+ * Initialize color map and system palette.
+ */
+HPALETTE COLOR_Init()
 {
     Visual * visual = DefaultVisual( display, DefaultScreen(display) );
     
@@ -124,14 +173,19 @@
     case DirectColor:
 	if (Options.usePrivateMap)
 	{
-	    COLOR_WinColormap = XCreateColormap( display,
-						 DefaultRootWindow(display),
+	    COLOR_WinColormap = XCreateColormap( display, rootWindow,
 						 visual, AllocAll );
 	    if (COLOR_WinColormap)
 	    {
-		COLOR_BuildMap(COLOR_WinColormap,
-			       DefaultDepth(display, DefaultScreen(display)),
-			       visual->map_entries );
+		COLOR_BuildMap( COLOR_WinColormap, screenDepth,
+			        visual->map_entries );
+		if (rootWindow != DefaultRootWindow(display))
+		{
+		    XSetWindowAttributes win_attr;
+		    win_attr.colormap = COLOR_WinColormap;
+		    XChangeWindowAttributes( display, rootWindow,
+					     CWColormap, &win_attr );
+		}
 		break;
 	    }
 	}
@@ -139,9 +193,109 @@
     case StaticGray:
     case StaticColor:
     case TrueColor:
-	COLOR_FillDefaultMap();
 	COLOR_WinColormap = DefaultColormapOfScreen( screen );
 	break;	
     }
-    return TRUE;
+    return COLOR_InitPalette();
+}
+
+
+/***********************************************************************
+ *           COLOR_IsSolid
+ *
+ * Check whether 'color' can be represented with a solid color.
+ */
+BOOL COLOR_IsSolid( COLORREF color )
+{
+    int i;
+    PALETTEENTRY *pEntry = COLOR_sysPaletteEntries;
+
+    if (color & 0xff000000) return TRUE;
+    if (!color || (color == 0xffffff)) return TRUE;
+    for (i = NB_RESERVED_COLORS; i > 0; i--, pEntry++)
+    {
+	if ((GetRValue(color) == pEntry->peRed) &&
+	    (GetGValue(color) == pEntry->peGreen) &&
+	    (GetBValue(color) == pEntry->peBlue)) return TRUE;
+    }
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           COLOR_ToPhysical
+ *
+ * Return the physical color closest to 'color'.
+ */
+WORD COLOR_ToPhysical( DC *dc, COLORREF color )
+{
+    WORD index = 0;
+    WORD *mapping;
+
+    if (!dc->u.x.pal.hMapping) return 0;
+    switch(color & 0xff000000)
+    {
+    case 0:  /* RGB */
+	index = GetNearestPaletteIndex( STOCK_DEFAULT_PALETTE, color );
+	break;
+    case 1:  /* PALETTEINDEX */
+	index = color & 0xffff;
+	break;
+    case 2:  /* PALETTERGB */
+	index = GetNearestPaletteIndex( dc->w.hPalette, color );
+	break;
+    }
+    if (index >= dc->u.x.pal.mappingSize) return 0;
+    mapping = (WORD *) GDI_HEAP_ADDR( dc->u.x.pal.hMapping );
+    return mapping[index];
+}
+
+
+/***********************************************************************
+ *           COLOR_SetMapping
+ *
+ * Set the color-mapping table in a DC.
+ */
+void COLOR_SetMapping( DC *dc, HANDLE map, WORD size )
+{
+    WORD *pmap, *pnewmap;
+
+    if (dc->u.x.pal.hMapping && (dc->u.x.pal.hMapping != hSysColorTranslation))
+	GDI_HEAP_FREE( dc->u.x.pal.hMapping );
+    if (map && (map != hSysColorTranslation))
+    {
+	  /* Copy mapping table */
+	dc->u.x.pal.hMapping = GDI_HEAP_ALLOC(GMEM_MOVEABLE,sizeof(WORD)*size);
+	pmap = (WORD *) GDI_HEAP_ADDR( map );
+	pnewmap = (WORD *) GDI_HEAP_ADDR( dc->u.x.pal.hMapping );
+	memcpy( pnewmap, pmap, sizeof(WORD)*size );
+    }
+    else dc->u.x.pal.hMapping = map;
+    dc->u.x.pal.mappingSize = size;
+}
+
+
+/***********************************************************************
+ *           GetNearestColor    (GDI.154)
+ */
+COLORREF GetNearestColor( HDC hdc, COLORREF color )
+{
+    WORD index;
+    DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if (!dc) return 0;
+    index = COLOR_ToPhysical( dc, color & 0xffffff );
+    return PALETTEINDEX( index );
+}
+
+
+/***********************************************************************
+ *           RealizeDefaultPalette    (GDI.365)
+ */
+WORD RealizeDefaultPalette( HDC hdc )
+{
+    DC *dc;
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+    dc->w.hPalette = STOCK_DEFAULT_PALETTE;
+    COLOR_SetMapping( dc, hSysColorTranslation, NB_RESERVED_COLORS );
+    return NB_RESERVED_COLORS;
 }
diff --git a/objects/dcvalues.c b/objects/dcvalues.c
index 73c98aa..12b775f 100644
--- a/objects/dcvalues.c
+++ b/objects/dcvalues.c
@@ -40,7 +40,6 @@
     0,                      /* breakCount */
     0,                      /* breakExtra */
     0,                      /* breakRem */
-    1,                      /* planes */
     1,                      /* bitsPerPixel */
     MM_TEXT,                /* MapMode */
     0,                      /* DCOrgX */
diff --git a/objects/dib.c b/objects/dib.c
index 15e3d09..c6d9d44 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -8,13 +8,13 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
 #include "gdi.h"
+#include "bitmap.h"
 #include "icon.h"
 
-
-extern XImage * BITMAP_BmpToImage( BITMAP *, void * );
-
+extern WORD COLOR_ToPhysical( DC *dc, COLORREF color );  /* color.c */
 
 /***********************************************************************
  *           DIB_BitmapInfoSize
@@ -39,8 +39,9 @@
  *
  * Create an XImage pointing to the bitmap data.
  */
-XImage * DIB_DIBmpToImage( BITMAPINFOHEADER * bmp, void * bmpData )
+static XImage *DIB_DIBmpToImage( BITMAPINFOHEADER * bmp, void * bmpData )
 {
+    extern void _XInitImageFuncPtrs( XImage* );
     XImage * image;
     int bytesPerLine = (bmp->biWidth * bmp->biBitCount + 31) / 32 * 4;
     
@@ -57,70 +58,251 @@
 
 
 /***********************************************************************
+ *           DIB_SetImageBits_1
+ *
+ * SetDIBits for a 1-bit deep DIB.
+ */
+static void DIB_SetImageBits_1( WORD lines, BYTE *bits, WORD width,
+			        WORD *colors, XImage *bmpImage )
+{
+    WORD i, x;
+    BYTE pad, pix;
+
+    if (!(width & 31)) pad = 0;
+    else pad = ((32 - (width & 31)) + 7) / 8;
+
+    while (lines--)
+    {
+	for (i = width/8, x = 0; (i > 0); i--)
+	{
+	    pix = *bits++;
+	    XPutPixel( bmpImage, x++, lines, colors[pix >> 7] );
+	    XPutPixel( bmpImage, x++, lines, colors[(pix >> 6) & 1] );
+	    XPutPixel( bmpImage, x++, lines, colors[(pix >> 5) & 1] );
+	    XPutPixel( bmpImage, x++, lines, colors[(pix >> 4) & 1] );
+	    XPutPixel( bmpImage, x++, lines, colors[(pix >> 3) & 1] );
+	    XPutPixel( bmpImage, x++, lines, colors[(pix >> 2) & 1] );
+	    XPutPixel( bmpImage, x++, lines, colors[(pix >> 1) & 1] );
+	    XPutPixel( bmpImage, x++, lines, colors[pix & 1] );
+	}
+	pix = *bits;
+	switch(width & 7)
+	{
+	case 7: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
+	case 6: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
+	case 5: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
+	case 4: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
+	case 3: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
+	case 2: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] ); pix <<= 1;
+	case 1: XPutPixel( bmpImage, x++, lines, colors[pix >> 7] );
+	}
+	bits += pad;
+    }
+}
+
+
+/***********************************************************************
+ *           DIB_SetImageBits_4
+ *
+ * SetDIBits for a 4-bit deep DIB.
+ */
+static void DIB_SetImageBits_4( WORD lines, BYTE *bits, WORD width,
+			        WORD *colors, XImage *bmpImage )
+{
+    WORD i, x;
+    BYTE pad;
+
+    if (!(width & 7)) pad = 0;
+    else pad = ((8 - (width & 7)) + 1) / 2;
+
+    while (lines--)
+    {
+	for (i = width/2, x = 0; i > 0; i--)
+	{
+	    BYTE pix = *bits++;
+	    XPutPixel( bmpImage, x++, lines, colors[pix >> 4] );
+	    XPutPixel( bmpImage, x++, lines, colors[pix & 0x0f] );
+	}
+	if (width & 1) XPutPixel( bmpImage, x, lines, colors[*bits >> 4] );
+	bits += pad;
+    }
+}
+
+
+/***********************************************************************
+ *           DIB_SetImageBits_8
+ *
+ * SetDIBits for an 8-bit deep DIB.
+ */
+static void DIB_SetImageBits_8( WORD lines, BYTE *bits, WORD width,
+			        WORD *colors, XImage *bmpImage )
+{
+    WORD x;
+    BYTE pad = (4 - (width & 3)) & 3;
+
+    while (lines--)
+    {
+	for (x = 0; x < width; x++)
+	    XPutPixel( bmpImage, x, lines, colors[*bits++] );
+	bits += pad;
+    }
+}
+
+
+/***********************************************************************
+ *           DIB_SetImageBits_24
+ *
+ * SetDIBits for a 24-bit deep DIB.
+ */
+static void DIB_SetImageBits_24( WORD lines, BYTE *bits, WORD width,
+				 DC *dc, XImage *bmpImage )
+{
+    WORD x;
+    BYTE pad = (4 - ((width*3) & 3)) & 3;
+
+    while (lines--)
+    {
+	for (x = 0; x < width; x++, bits += 3)
+	{
+	    XPutPixel( bmpImage, x, lines,
+		       COLOR_ToPhysical( dc, RGB(bits[0],bits[1],bits[2]) ));
+	}
+	bits += pad;
+    }
+}
+
+
+/***********************************************************************
+ *           DIB_SetImageBits
+ *
+ * Transfer the bits to an X image.
+ * Helper function for SetDIBits() and SetDIBitsToDevice().
+ */
+static int DIB_SetImageBits( DC *dc, WORD lines, WORD depth, LPSTR bits,
+			     BITMAPINFO *info, WORD coloruse,
+			     Drawable drawable, GC gc, int xSrc, int ySrc,
+			     int xDest, int yDest, int width, int height )
+{
+    WORD *colorMapping;
+    XImage *bmpImage;
+    void *bmpData;
+    int i, colors, widthBytes;
+
+      /* Build the color mapping table */
+
+    if (info->bmiHeader.biBitCount == 24) colorMapping = NULL;
+    else
+    {
+	colors = info->bmiHeader.biClrUsed;
+	if (!colors) colors = 1 << info->bmiHeader.biBitCount;
+	if (!(colorMapping = (WORD *)malloc( colors * sizeof(WORD) )))
+	    return 0;
+	if (coloruse == DIB_RGB_COLORS)
+	{
+	    RGBQUAD * rgbPtr = info->bmiColors;
+	    for (i = 0; i < colors; i++, rgbPtr++)
+		colorMapping[i] = COLOR_ToPhysical( dc, RGB(rgbPtr->rgbRed,
+							    rgbPtr->rgbGreen,
+							    rgbPtr->rgbBlue) );
+	}
+	else
+	{
+	    WORD * index = (WORD *)info->bmiColors;
+	    for (i = 0; i < colors; i++, index++)
+		colorMapping[i] = COLOR_ToPhysical( dc, PALETTEINDEX(*index) );
+	}
+    }
+
+      /* Transfer the pixels */
+
+    widthBytes = (info->bmiHeader.biWidth * depth + 31) / 32 * 4;
+    bmpData  = malloc( lines * widthBytes );
+    bmpImage = XCreateImage( display, DefaultVisualOfScreen(screen),
+			     depth, ZPixmap, 0, bmpData,
+			     info->bmiHeader.biWidth, lines, 32, widthBytes );
+
+    switch(info->bmiHeader.biBitCount)
+    {
+    case 1:
+	DIB_SetImageBits_1( lines, bits, info->bmiHeader.biWidth,
+			    colorMapping, bmpImage );
+	break;
+    case 4:
+	DIB_SetImageBits_4( lines, bits, info->bmiHeader.biWidth,
+			    colorMapping, bmpImage );
+	break;
+    case 8:
+	DIB_SetImageBits_8( lines, bits, info->bmiHeader.biWidth,
+			    colorMapping, bmpImage );
+	break;
+    case 24:
+	DIB_SetImageBits_24( lines, bits, info->bmiHeader.biWidth,
+			     dc, bmpImage );
+	break;
+    }
+    if (colorMapping) free(colorMapping);
+
+    XPutImage( display, drawable, gc, bmpImage, xSrc, ySrc,
+	       xDest, yDest, width, height );
+    XDestroyImage( bmpImage );
+    return lines;
+}
+
+
+/***********************************************************************
  *           SetDIBits    (GDI.440)
  */
 int SetDIBits( HDC hdc, HBITMAP hbitmap, WORD startscan, WORD lines,
 	       LPSTR bits, BITMAPINFO * info, WORD coloruse )
 {
     DC * dc;
-    BITMAPOBJ * bmpObj;
-    BITMAP * bmp;
-    WORD * colorMapping;
-    RGBQUAD * rgbPtr;
-    XImage * bmpImage, * dibImage;
-    int i, x, y, pixel, colors;
-        
-    if (!lines) return 0;
+    BITMAPOBJ * bmp;
+
+      /* Check parameters */
+
     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
-    if (!(bmpObj = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
+    if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
 	return 0;
-    if (!(bmp = (BITMAP *) GlobalLock( bmpObj->hBitmap ))) return 0;
+    if (!lines || (startscan >= (WORD)info->bmiHeader.biHeight)) return 0;
+    if (startscan+lines > info->bmiHeader.biHeight)
+	lines = info->bmiHeader.biHeight - startscan;
 
-      /* Build the color mapping table */
+    return DIB_SetImageBits( dc, lines, bmp->bitmap.bmBitsPixel,
+			     bits, info, coloruse, bmp->pixmap, BITMAP_GC(bmp),
+			     0, 0, 0, startscan, bmp->bitmap.bmWidth, lines );
+}
 
-    if (info->bmiHeader.biBitCount == 24) colorMapping = NULL;
-    else if (coloruse == DIB_RGB_COLORS)
-    {
-	colors = info->bmiHeader.biClrUsed;
-	if (!colors) colors = 1 << info->bmiHeader.biBitCount;
-	if (!(colorMapping = (WORD *)malloc( colors * sizeof(WORD) )))
-	{
-	    GlobalUnlock( bmpObj->hBitmap );
-	    return 0;
-	}
-	for (i = 0, rgbPtr = info->bmiColors; i < colors; i++, rgbPtr++)
-	    colorMapping[i] = GetNearestPaletteIndex( dc->w.hPalette, 
-						     RGB(rgbPtr->rgbRed,
-							 rgbPtr->rgbGreen,
-							 rgbPtr->rgbBlue) );
-    }
-    else colorMapping = (WORD *)info->bmiColors;
 
-      /* Transfer the pixels (very slow...) */
+/***********************************************************************
+ *           SetDIBitsToDevice    (GDI.443)
+ */
+int SetDIBitsToDevice( HDC hdc, short xDest, short yDest, WORD cx, WORD cy,
+		       WORD xSrc, WORD ySrc, WORD startscan, WORD lines,
+		       LPSTR bits, BITMAPINFO * info, WORD coloruse )
+{
+    DC * dc;
 
-    bmpImage = BITMAP_BmpToImage( bmp, ((char *)bmp) + sizeof(BITMAP) );
-    dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
+      /* Check parameters */
 
-    for (y = 0; y < lines; y++)
-    {
-	for (x = 0; x < info->bmiHeader.biWidth; x++)
-	{
-	    pixel = XGetPixel( dibImage, x, y );
-	    if (colorMapping) pixel = colorMapping[pixel];
-	    else pixel = GetNearestPaletteIndex(dc->w.hPalette,(COLORREF)pixel);
-	    XPutPixel( bmpImage, x, bmp->bmHeight - startscan - y - 1, pixel );
-	}
-    }
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+    if (!lines || (startscan >= info->bmiHeader.biHeight)) return 0;
+    if (startscan+lines > info->bmiHeader.biHeight)
+	lines = info->bmiHeader.biHeight - startscan;
+    if (ySrc < startscan) ySrc = startscan;
+    else if (ySrc >= startscan+lines) return 0;
+    if (xSrc >= info->bmiHeader.biWidth) return 0;
+    if (ySrc+cy >= startscan+lines) cy = startscan + lines - ySrc;
+    if (xSrc+cx >= info->bmiHeader.biWidth) cx = info->bmiHeader.biWidth-xSrc;
+    if (!cx || !cy) return 0;
 
-    bmpImage->data = NULL;
-    dibImage->data = NULL;
-    XDestroyImage( bmpImage );
-    XDestroyImage( dibImage );
-
-    if (colorMapping && (coloruse == DIB_RGB_COLORS)) free(colorMapping);
-    
-    GlobalUnlock( bmpObj->hBitmap );
-    return lines;
+    DC_SetupGCForText( dc );  /* To have the correct ROP */
+    return DIB_SetImageBits( dc, lines, dc->w.bitsPerPixel,
+			     bits, info, coloruse,
+			     dc->u.x.drawable, dc->u.x.gc,
+			     xSrc, ySrc - startscan,
+			     dc->w.DCOrgX + XLPTODP( dc, xDest ),
+			     dc->w.DCOrgY + YLPTODP( dc, yDest ),
+			     cx, cy );
 }
 
 
@@ -131,8 +313,7 @@
 	       LPSTR bits, BITMAPINFO * info, WORD coloruse )
 {
     DC * dc;
-    BITMAPOBJ * bmpObj;
-    BITMAP * bmp;
+    BITMAPOBJ * bmp;
     PALETTEENTRY * palEntry;
     PALETTEOBJ * palette;
     XImage * bmpImage, * dibImage;
@@ -140,11 +321,10 @@
         
     if (!lines) return 0;
     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
-    if (!(bmpObj = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
+    if (!(bmp = (BITMAPOBJ *)GDI_GetObjPtr( hbitmap, BITMAP_MAGIC )))
 	return 0;
     if (!(palette = (PALETTEOBJ*)GDI_GetObjPtr( dc->w.hPalette, PALETTE_MAGIC )))
 	return 0;
-    if (!(bmp = (BITMAP *) GlobalLock( bmpObj->hBitmap ))) return 0;
 
       /* Transfer color info */
     
@@ -165,7 +345,8 @@
 
     if (bits)
     {	
-	bmpImage = BITMAP_BmpToImage( bmp, ((char *)bmp) + sizeof(BITMAP) );
+	bmpImage = XGetImage( display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
+			      bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
 	dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
 
 	for (y = 0; y < lines; y++)
@@ -173,18 +354,15 @@
 	    for (x = 0; x < info->bmiHeader.biWidth; x++)
 	    {
 		XPutPixel( dibImage, x, y,
-		         XGetPixel(bmpImage, x, bmp->bmHeight-startscan-y-1) );
+		  XGetPixel(bmpImage, x, bmp->bitmap.bmHeight-startscan-y-1) );
 		
 	    }
 	}
 	
-	bmpImage->data = NULL;
 	dibImage->data = NULL;
-	XDestroyImage( bmpImage );
 	XDestroyImage( dibImage );
+	XDestroyImage( bmpImage );
     }
-
-    GlobalUnlock( bmpObj->hBitmap );
     return lines;
 }
 
diff --git a/objects/dither.c b/objects/dither.c
new file mode 100644
index 0000000..5210106
--- /dev/null
+++ b/objects/dither.c
@@ -0,0 +1,140 @@
+/*
+ * Dithering functions
+ *
+ * Copyright 1994 Alexandre Julliard
+ */
+
+static char Copyright[] = "Copyright  Alexandre Julliard, 1994";
+
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "gdi.h"
+#include "bitmap.h"
+
+
+  /* Levels of each primary */
+#define PRIMARY_LEVELS  3  
+#define TOTAL_LEVELS    (PRIMARY_LEVELS*PRIMARY_LEVELS*PRIMARY_LEVELS)
+
+ /* Dithering matrix size  */
+#define MATRIX_SIZE     8
+#define MATRIX_SIZE_2   (MATRIX_SIZE*MATRIX_SIZE)
+
+  /* Total number of possible levels for a dithered primary color */
+#define DITHER_LEVELS   (MATRIX_SIZE_2 * (PRIMARY_LEVELS-1) + 1)
+
+  /* Dithering matrix */
+static const int dither_matrix[MATRIX_SIZE_2] =
+{
+     0, 32,  8, 40,  2, 34, 10, 42,
+    48, 16, 56, 24, 50, 18, 58, 26,
+    12, 44,  4, 36, 14, 46,  6, 38,
+    60, 28, 52, 20, 62, 30, 54, 22,
+     3, 35, 11, 43,  1, 33,  9, 41,
+    51, 19, 59, 27, 49, 17, 57, 25,
+    15, 47,  7, 39, 13, 45,  5, 37,
+    63, 31, 55, 23, 61, 29, 53, 21
+};
+
+  /* Mapping between (R,G,B) triples and EGA colors */
+static const int EGAmapping[TOTAL_LEVELS] =
+{
+    0,  /* 000000 -> 000000 */
+    4,  /* 00007f -> 000080 */
+    12, /* 0000ff -> 0000ff */
+    2,  /* 007f00 -> 008000 */
+    6,  /* 007f7f -> 008080 */
+    6,  /* 007fff -> 008080 */
+    10, /* 00ff00 -> 00ff00 */
+    6,  /* 00ff7f -> 008080 */
+    14, /* 00ffff -> 00ffff */
+    1,  /* 7f0000 -> 800000 */
+    5,  /* 7f007f -> 800080 */
+    5,  /* 7f00ff -> 800080 */
+    3,  /* 7f7f00 -> 808000 */
+    8,  /* 7f7f7f -> 808080 */
+    7,  /* 7f7fff -> c0c0c0 */
+    3,  /* 7fff00 -> 808000 */
+    7,  /* 7fff7f -> c0c0c0 */
+    7,  /* 7fffff -> c0c0c0 */
+    9,  /* ff0000 -> ff0000 */
+    5,  /* ff007f -> 800080 */
+    13, /* ff00ff -> ff00ff */
+    3,  /* ff7f00 -> 808000 */
+    7,  /* ff7f7f -> c0c0c0 */
+    7,  /* ff7fff -> c0c0c0 */
+    11, /* ffff00 -> ffff00 */
+    7,  /* ffff7f -> c0c0c0 */
+    15  /* ffffff -> ffffff */
+};
+
+   /* Map an EGA index (0..15) to a pixel value */
+extern int COLOR_mapEGAPixel[16];  /* in color.c */
+
+#define PIXEL_VALUE(r,g,b) \
+    COLOR_mapEGAPixel[EGAmapping[((r)*PRIMARY_LEVELS+(g))*PRIMARY_LEVELS+(b)]]
+
+  /* X image for building dithered pixmap */
+static XImage *ditherImage = NULL;
+static char *imageData = NULL;
+
+
+/***********************************************************************
+ *           DITHER_Init
+ *
+ * Create the X image used for dithering.
+ */
+BOOL DITHER_Init()
+{
+    int bytes_per_line = (screenDepth * MATRIX_SIZE + 7) / 8;
+    if (!(imageData = (char *) malloc( bytes_per_line * MATRIX_SIZE )))
+	return FALSE;
+    ditherImage = XCreateImage( display, DefaultVisualOfScreen(screen),
+			        screenDepth, ZPixmap, 0, imageData,
+			        MATRIX_SIZE, MATRIX_SIZE, 8, bytes_per_line );
+    return (ditherImage != NULL);
+}
+
+
+/***********************************************************************
+ *           DITHER_DitherColor
+ */
+Pixmap DITHER_DitherColor( DC *dc, COLORREF color )
+{
+    static COLORREF prevColor = 0xffffffff;
+    unsigned int x, y;
+    Pixmap pixmap;
+
+/*    printf( "Dither: %x\n", color ); */
+
+    if (color != prevColor)
+    {
+	int r = GetRValue( color ) * DITHER_LEVELS;
+	int g = GetGValue( color ) * DITHER_LEVELS;
+	int b = GetBValue( color ) * DITHER_LEVELS;
+	const int *pmatrix = dither_matrix;
+
+	WORD *mapping = (WORD *) GDI_HEAP_ADDR( dc->u.x.pal.hMapping );
+
+	for (y = 0; y < MATRIX_SIZE; y++)
+	{
+	    for (x = 0; x < MATRIX_SIZE; x++)
+	    {
+		int d  = *pmatrix++ * 256;
+		int dr = ((r + d) / MATRIX_SIZE_2) / 256;
+		int dg = ((g + d) / MATRIX_SIZE_2) / 256;
+		int db = ((b + d) / MATRIX_SIZE_2) / 256;
+		XPutPixel( ditherImage, x, y, PIXEL_VALUE(dr,dg,db) );
+	    }
+	}
+	prevColor = color;
+    }
+    
+    pixmap = XCreatePixmap( display, rootWindow,
+			    MATRIX_SIZE, MATRIX_SIZE, screenDepth );
+    XPutImage( display, pixmap, BITMAP_colorGC, ditherImage, 0, 0,
+	       0, 0, MATRIX_SIZE, MATRIX_SIZE );
+    return pixmap;
+}
diff --git a/objects/font.c b/objects/font.c
index 883e699..382976b 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -8,6 +8,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <X11/Xatom.h>
 #include "gdi.h"
 
@@ -17,7 +18,7 @@
  *
  * Find a X font matching the logical font.
  */
-XFontStruct * FONT_MatchFont( DC * dc, LOGFONT * font )
+static XFontStruct * FONT_MatchFont( LOGFONT * font )
 {
     char pattern[100];
     char *family, *weight, *charset;
@@ -44,8 +45,16 @@
       default:            family = "*"; break;
     }
     
-    sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-%d-%s",
-	    family, weight, slant, height, spacing, width, charset );
+    /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
+    if ( width == 0 )
+      sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-*-%s",
+	      family, weight, slant, height, spacing, charset
+	      );
+    else
+      sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-%d-%s",
+	      family, weight, slant, height, spacing, width, charset
+	      );
+
 #ifdef DEBUG_FONT
     printf( "FONT_MatchFont: '%s'\n", pattern );
 #endif
@@ -166,13 +175,24 @@
 
       /* Load font if necessary */
 
+    if (!font)
+    {
+	HFONT hnewfont;
+
+	hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
+			      FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
+			      DEFAULT_QUALITY, FF_DONTCARE, "*" );
+	font = (FONTOBJ *) GDI_HEAP_ADDR( hnewfont );
+    }
+
     if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
 	stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
-    else stockPtr = NULL;
+    else 
+	stockPtr = NULL;
     
     if (!stockPtr || !stockPtr->fstruct)
     {
-	fontStruct = FONT_MatchFont( dc, &font->logfont );
+	fontStruct = FONT_MatchFont( &font->logfont );
     }
     else
     {
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index bc59d86..cd78887 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -6,11 +6,14 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
+#include <stdlib.h>
+#include <stdio.h>
 #include "gdi.h"
-
+#include "prototypes.h"
 
 MDESC *GDI_Heap = NULL;
 
+extern HPALETTE COLOR_Init();  /* color.c */
 
 /***********************************************************************
  *          GDI stock objects 
@@ -130,12 +133,10 @@
     (GDIOBJHDR *) &AnsiVarFont,
     (GDIOBJHDR *) &SystemFont,
     (GDIOBJHDR *) &DeviceDefaultFont,
-    NULL,            /* DEFAULT_PALETTE created by PALETTE_Init */
+    NULL,            /* DEFAULT_PALETTE created by COLOR_Init */
     (GDIOBJHDR *) &SystemFixedFont
 };
 
-extern GDIOBJHDR * PALETTE_systemPalette;
-
 
 /***********************************************************************
  *           GDI_Init
@@ -144,6 +145,7 @@
  */
 BOOL GDI_Init()
 {
+    HPALETTE hpalette;
     struct segment_descriptor_s * s;
 
 #ifndef WINELIB
@@ -156,9 +158,8 @@
     
       /* Create default palette */
 
-    COLOR_Init();
-    PALETTE_Init();
-    StockObjects[DEFAULT_PALETTE] = PALETTE_systemPalette;
+    if (!(hpalette = COLOR_Init())) return FALSE;
+    StockObjects[DEFAULT_PALETTE] = (GDIOBJHDR *) GDI_HEAP_ADDR( hpalette );
 
       /* Create default bitmap */
 
@@ -168,6 +169,10 @@
 
     if (!REGION_Init()) return FALSE;
     
+      /* Initialise dithering */
+
+    if (!DITHER_Init()) return FALSE;
+
     return TRUE;
 }
 
@@ -217,7 +222,6 @@
 BOOL GDI_FreeObject( HANDLE handle )
 {
     GDIOBJHDR * object;
-    HANDLE prev;
 
       /* Can't free stock objects */
     if (handle >= FIRST_STOCK_HANDLE) return FALSE;
diff --git a/objects/palette.c b/objects/palette.c
index 03300c4..dc52635 100644
--- a/objects/palette.c
+++ b/objects/palette.c
@@ -1,62 +1,32 @@
 /*
  * GDI palette objects
  *
- * Copyright 1993 Alexandre Julliard
+ * Copyright 1993,1994 Alexandre Julliard
  */
 
-static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
+static char Copyright[] = "Copyright  Alexandre Julliard, 1993,1994";
 
 #include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+/*
 #ifdef linux
 #include <values.h>
 #endif
+*/
+
 #if !defined  (MAXINT)
 #include <limits.h>
 #define MAXINT INT_MAX
 #endif
 
 #include <X11/Xlib.h>
-
 #include "gdi.h"
 
+extern void COLOR_SetMapping( DC *dc, HANDLE map, WORD size );  /* color.c */
+
 extern Colormap COLOR_WinColormap;
 
-GDIOBJHDR * PALETTE_systemPalette;
-
-
-/***********************************************************************
- *           PALETTE_Init
- */
-BOOL PALETTE_Init()
-{
-    int i, size;
-    XColor color;
-    HPALETTE hpalette;
-    LOGPALETTE * palPtr;
-
-    size = DefaultVisual( display, DefaultScreen(display) )->map_entries;
-    palPtr = malloc( sizeof(LOGPALETTE) + (size-1)*sizeof(PALETTEENTRY) );
-    if (!palPtr) return FALSE;
-    palPtr->palVersion = 0x300;
-    palPtr->palNumEntries = size;
-    memset( palPtr->palPalEntry, 0xff, size*sizeof(PALETTEENTRY) );
-
-    for (i = 0; i < size; i++)
-    {
-	color.pixel = i;
-	XQueryColor( display, COLOR_WinColormap, &color );
-	palPtr->palPalEntry[i].peRed   = color.red >> 8;
-	palPtr->palPalEntry[i].peGreen = color.green >> 8;
-	palPtr->palPalEntry[i].peBlue  = color.blue >> 8;
-	palPtr->palPalEntry[i].peFlags = 0;	
-    }
-
-    hpalette = CreatePalette( palPtr );
-    PALETTE_systemPalette = (GDIOBJHDR *) GDI_HEAP_ADDR( hpalette );
-    free( palPtr );
-    return TRUE;
-}
-
 
 /***********************************************************************
  *           CreatePalette    (GDI.360)
@@ -117,6 +87,33 @@
 
 
 /***********************************************************************
+ *           GetSystemPaletteEntries    (GDI.375)
+ */
+WORD GetSystemPaletteEntries( HDC hdc, WORD start, WORD count,
+			      LPPALETTEENTRY entries )
+{
+    WORD i;
+    DC *dc;
+    XColor color;
+
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+    if (start >= dc->w.devCaps->sizePalette) return 0;
+    if (start+count >= dc->w.devCaps->sizePalette)
+	count = dc->w.devCaps->sizePalette - start;
+    for (i = 0; i < count; i++)
+    {
+	color.pixel = start + i;
+	XQueryColor( display, COLOR_WinColormap, &color );
+	entries[i].peRed   = color.red >> 8;
+	entries[i].peGreen = color.green >> 8;
+	entries[i].peBlue  = color.blue >> 8;
+	entries[i].peFlags = 0;	
+    }
+    return count;
+}
+
+
+/***********************************************************************
  *           GetNearestPaletteIndex    (GDI.370)
  */
 WORD GetNearestPaletteIndex( HPALETTE hpalette, COLORREF color )
@@ -143,7 +140,8 @@
     b = GetBValue(color);
 
     entry = palPtr->logpalette.palPalEntry;
-    for (i = 0, minDist = MAXINT; i < palPtr->logpalette.palNumEntries; i++)
+    for (i = 0, minDist = MAXINT; minDist !=0 &&
+         i < palPtr->logpalette.palNumEntries ; i++)
     {
 	if (entry->peFlags != 0xff)
 	{
@@ -178,18 +176,51 @@
 
 
 /***********************************************************************
+ *           GDISelectPalette    (GDI.361)
+ */
+HPALETTE GDISelectPalette( HDC hdc, HPALETTE hpal )
+{
+    HPALETTE prev;
+    DC *dc;
+
+#ifdef DEBUG_PALETTE
+    printf( "GDISelectPalette: %d %d\n", hdc, hpal );
+#endif
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
+    prev = dc->w.hPalette;
+    dc->w.hPalette = hpal;
+    if (hpal != STOCK_DEFAULT_PALETTE) COLOR_SetMapping( dc, 0, 0 );
+    else RealizeDefaultPalette( hdc );  /* Always realize default palette */
+    return prev;
+}
+
+
+/***********************************************************************
+ *           GDIRealizePalette    (GDI.362)
+ */
+UINT GDIRealizePalette( HDC hdc )
+{
+#ifdef DEBUG_PALETTE
+    printf( "GDIRealizePalette: %d\n", hdc );
+#endif
+    return 0;
+}
+
+
+/***********************************************************************
  *           SelectPalette    (USER.282)
  */
 HPALETTE SelectPalette(HDC hDC, HPALETTE hPal, BOOL bForceBackground)
 {
-    return (HPALETTE)NULL;
+    return GDISelectPalette( hDC, hPal );
 }
 
+
 /***********************************************************************
  *           RealizePalette    (USER.283)
  */
-int RealizePalette(HDC hDC)
+UINT RealizePalette(HDC hDC)
 {
-    return 0;
+    return GDIRealizePalette( hDC );
 }
 
diff --git a/objects/pen.c b/objects/pen.c
index a0a7ad7..48da252 100644
--- a/objects/pen.c
+++ b/objects/pen.c
@@ -8,6 +8,7 @@
 
 #include "gdi.h"
 
+extern WORD COLOR_ToPhysical( DC *dc, COLORREF color );
 
 /***********************************************************************
  *           CreatePen    (GDI.61)
@@ -68,21 +69,24 @@
 	                  / dc->w.WndExtX;
     if (dc->u.x.pen.width < 0) dc->u.x.pen.width = -dc->u.x.pen.width;
     if (dc->u.x.pen.width == 1) dc->u.x.pen.width = 0;  /* Faster */
-    dc->u.x.pen.pixel = GetNearestPaletteIndex( dc->w.hPalette,
-					        pen->logpen.lopnColor );    
+    dc->u.x.pen.pixel = COLOR_ToPhysical( dc, pen->logpen.lopnColor );    
     switch(pen->logpen.lopnStyle)
     {
       case PS_DASH:
-	XSetDashes( XT_display, dc->u.x.gc, 0, dash_dash, 2 );
+	dc->u.x.pen.dashes = dash_dash;
+	dc->u.x.pen.dash_len = 2;
 	break;
       case PS_DOT:
-	XSetDashes( XT_display, dc->u.x.gc, 0, dash_dot, 2 );
+	dc->u.x.pen.dashes = dash_dot;
+	dc->u.x.pen.dash_len = 2;
 	break;
       case PS_DASHDOT:
-	XSetDashes( XT_display, dc->u.x.gc, 0, dash_dashdot, 4 );
+	dc->u.x.pen.dashes = dash_dashdot;
+	dc->u.x.pen.dash_len = 4;
 	break;
       case PS_DASHDOTDOT:
-	XSetDashes( XT_display, dc->u.x.gc, 0, dash_dashdotdot, 6 );
+	dc->u.x.pen.dashes = dash_dashdotdot;
+	dc->u.x.pen.dash_len = 6;
 	break;
     }
     
diff --git a/objects/region.c b/objects/region.c
index 3a7b9ef..afe4dd4 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -8,13 +8,13 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
 #include "gdi.h"
 
-
   /* GC used for region operations */
 static GC regionGC = 0;
 
-
 /***********************************************************************
  *           REGION_Init
  */
@@ -23,8 +23,7 @@
     Pixmap tmpPixmap;
 
       /* CreateGC needs a drawable */
-    tmpPixmap = XCreatePixmap( XT_display, DefaultRootWindow(XT_display),
-			       1, 1, 1 );
+    tmpPixmap = XCreatePixmap( display, rootWindow, 1, 1, 1 );
     if (tmpPixmap)
     {
 	regionGC = XCreateGC( XT_display, tmpPixmap, 0, NULL );
@@ -68,8 +67,7 @@
     
       /* Create pixmap */
 
-    region->pixmap = XCreatePixmap( XT_display, DefaultRootWindow(XT_display),
-				    width, height, 1 );
+    region->pixmap = XCreatePixmap( display, rootWindow, width, height, 1 );
     if (!region->pixmap) return FALSE;
 
       /* Fill pixmap */
@@ -576,8 +574,19 @@
     
     width  = region->box.right - region->box.left;
     height = region->box.bottom - region->box.top;
-    region->pixmap = XCreatePixmap( XT_display, DefaultRootWindow(XT_display),
-				    width, height, 1 );
+    if (!width || !height)
+    {
+	printf( "CombineRgn: width or height is 0. Please report this.\n" );
+	printf( "src1=%d,%d-%d,%d  src2=%d,%d-%d,%d  dst=%d,%d-%d,%d  op=%d\n",
+	        src1Obj->region.box.left, src1Obj->region.box.top,
+	        src1Obj->region.box.right, src1Obj->region.box.bottom,
+	        src2Obj->region.box.left, src2Obj->region.box.top,
+	        src2Obj->region.box.right, src2Obj->region.box.bottom,
+	        region->box.left, region->box.top,
+	        region->box.right, region->box.bottom, mode );
+	exit(1);
+    }
+    region->pixmap = XCreatePixmap( display, rootWindow, width, height, 1 );
 
     switch(mode)
     {
diff --git a/objects/text.c b/objects/text.c
index 787b0f7..a900baa 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -221,7 +221,6 @@
 	    	(rect->bottom - rect->top) / 2 - size.cy / 2;
 	    else if (flags & DT_BOTTOM) y = rect->bottom - size.cy;
 	}
-
 	if (!(flags & DT_CALCRECT))
 	    if (!TextOut(hdc, x, y, line, len)) return 0;
 	if (prefix_offset != -1)
diff --git a/test/blandmdi.exe b/test/blandmdi.exe
new file mode 100644
index 0000000..6dc03d5
--- /dev/null
+++ b/test/blandmdi.exe
Binary files differ
diff --git a/test/btnlook.exe b/test/btnlook.exe
deleted file mode 100755
index d952b61..0000000
--- a/test/btnlook.exe
+++ /dev/null
Binary files differ
diff --git a/test/hw.exe b/test/hw.exe
deleted file mode 100755
index 0567dc3..0000000
--- a/test/hw.exe
+++ /dev/null
Binary files differ
diff --git a/test/hyperoid.exe b/test/hyperoid.exe
deleted file mode 100644
index 4e689f0..0000000
--- a/test/hyperoid.exe
+++ /dev/null
Binary files differ
diff --git a/test/menutest.exe b/test/menutest.exe
deleted file mode 100755
index ad4f791..0000000
--- a/test/menutest.exe
+++ /dev/null
Binary files differ
diff --git a/test/winetest2.exe b/test/winetest2.exe
deleted file mode 100755
index 57d7edc..0000000
--- a/test/winetest2.exe
+++ /dev/null
Binary files differ
diff --git a/toolkit/Imakefile b/toolkit/Imakefile
index 53a7da3..5ddccc8 100644
--- a/toolkit/Imakefile
+++ b/toolkit/Imakefile
@@ -3,6 +3,7 @@
 MODULE = toolkit
 
 SRCS = \
+	arch.c \
 	heap.c \
 	sup.c \
 	winmain.c
diff --git a/toolkit/arch.c b/toolkit/arch.c
new file mode 100644
index 0000000..9f9c6c7
--- /dev/null
+++ b/toolkit/arch.c
@@ -0,0 +1,32 @@
+/*
+ * Big endian structure conversion routines
+ *
+ * Copyright Miguel de Icaza, 1994
+ */
+
+#include "arch.h"
+#include "windows.h"
+
+void ARCH_ConvBitmapInfo (BITMAPINFOHEADER *image)
+{
+    image->biSize = CONV_LONG (image->biSize);
+    image->biWidth = CONV_LONG (image->biWidth);
+    image->biHeight = CONV_LONG (image->biHeight);
+    image->biPlanes = CONV_SHORT (image->biPlanes);
+    image->biBitCount = CONV_SHORT (image->biBitCount);
+    image->biCompression = CONV_LONG (image->biCompression);
+    image->biSizeImage = CONV_LONG (image->biSizeImage);
+    image->biXPelsPerMeter = CONV_LONG (image->biXPelsPerMeter);
+    image->biYPelsPerMeter = CONV_LONG (image->biYPelsPerMeter);
+    image->biClrUsed = CONV_LONG (image->biClrUsed);
+    image->biClrImportant = CONV_LONG (image->biClrImportant);
+}
+
+void ARCH_ConvCoreHeader (BITMAPCOREHEADER *image)
+{
+    image->bcSize = CONV_LONG (image->bcSize);
+    image->bcWidth = CONV_SHORT (image->bcWidth);
+    image->bcHeight = CONV_SHORT (image->bcHeight);
+    image->bcPlanes = CONV_SHORT (image->bcPlanes);
+    image->bcBitCount = CONV_SHORT (image->bcBitCount);
+}
diff --git a/tools/Imakefile b/tools/Imakefile
index 7b739a1..c993ef4 100644
--- a/tools/Imakefile
+++ b/tools/Imakefile
@@ -2,4 +2,8 @@
 
 MODULE = tools
 
+#ifndef NewBuild
 SimpleProgramTarget(build)
+#else
+SimpleProgramTarget(newbuild)
+#endif
\ No newline at end of file
diff --git a/tools/newbuild.c b/tools/newbuild.c
new file mode 100644
index 0000000..647594f
--- /dev/null
+++ b/tools/newbuild.c
@@ -0,0 +1,954 @@
+static char RCSId[] = "$Id: build.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
+static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef linux
+#define UTEXTSEL 	0x23
+#define UDATASEL	0x2b
+#endif
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#define UTEXTSEL 	0x1f
+#define UDATASEL	0x27
+#endif
+
+#define VARTYPE_BYTE	0
+#define VARTYPE_SIGNEDWORD	0
+#define VARTYPE_WORD	1
+#define VARTYPE_LONG	2
+#define VARTYPE_FARPTR	3
+
+#define FUNCTYPE_PASCAL	16
+#define FUNCTYPE_C	17
+#define FUNCTYPE_REG	19
+
+#define EQUATETYPE_ABS	18
+#define TYPE_RETURN	20
+
+#define MAX_ORDINALS	1024
+
+typedef struct ordinal_definition_s
+{
+    int valid;
+    int type;
+    char export_name[80];
+    void *additional_data;
+} ORDDEF;
+
+typedef struct ordinal_variable_definition_s
+{
+    int n_values;
+    int *values;
+} ORDVARDEF;
+
+typedef struct ordinal_function_definition_s
+{
+    int n_args_16;
+    int arg_types_16[16];
+    int arg_16_offsets[16];
+    int arg_16_size;
+    char internal_name[80];
+    int n_args_32;
+    int arg_indices_32[16];
+} ORDFUNCDEF;
+
+typedef struct ordinal_return_definition_s
+{
+    int arg_size;
+    int ret_value;
+} ORDRETDEF;
+
+ORDDEF OrdinalDefinitions[MAX_ORDINALS];
+
+char LowerDLLName[80];
+char UpperDLLName[80];
+int Limit;
+int DLLId;
+FILE *SpecFp;
+
+char *ParseBuffer = NULL;
+char *ParseNext;
+char ParseSaveChar;
+int Line;
+
+int IsNumberString(char *s)
+{
+    while (*s != '\0')
+	if (!isdigit(*s++))
+	    return 0;
+
+    return 1;
+}
+
+char *strlower(char *s)
+{
+    char *p;
+    
+    for(p = s; *p != '\0'; p++)
+	*p = tolower(*p);
+
+    return s;
+}
+
+char *strupper(char *s)
+{
+    char *p;
+    
+    for(p = s; *p != '\0'; p++)
+	*p = toupper(*p);
+
+    return s;
+}
+
+int stricmp(char *s1, char *s2)
+{
+    if (strlen(s1) != strlen(s2))
+	return -1;
+    
+    while (*s1 != '\0')
+	if (*s1++ != *s2++)
+	    return -1;
+    
+    return 0;
+}
+
+char *
+GetTokenInLine(void)
+{
+    char *p;
+    char *token;
+
+    if (ParseNext != ParseBuffer)
+    {
+	if (ParseSaveChar == '\0')
+	    return NULL;
+	*ParseNext = ParseSaveChar;
+    }
+    
+    /*
+     * Remove initial white space.
+     */
+    for (p = ParseNext; isspace(*p); p++)
+	;
+    
+    if (*p == '\0')
+	return NULL;
+    
+    /*
+     * Find end of token.
+     */
+    token = p++;
+    if (*token != '(' && *token != ')')
+	while (*p != '\0' && *p != '(' && *p != ')' && !isspace(*p))
+	    p++;
+    
+    ParseSaveChar = *p;
+    ParseNext = p;
+    *p = '\0';
+
+    return token;
+}
+
+char *
+GetToken(void)
+{
+    char *token;
+
+    if (ParseBuffer == NULL)
+    {
+	ParseBuffer = malloc(512);
+	ParseNext = ParseBuffer;
+	Line++;
+	while (1)
+	{
+	    if (fgets(ParseBuffer, 511, SpecFp) == NULL)
+		return NULL;
+	    if (ParseBuffer[0] != '#')
+		break;
+	}
+    }
+
+    while ((token = GetTokenInLine()) == NULL)
+    {
+	ParseNext = ParseBuffer;
+	Line++;
+	while (1)
+	{
+	    if (fgets(ParseBuffer, 511, SpecFp) == NULL)
+		return NULL;
+	    if (ParseBuffer[0] != '#')
+		break;
+	}
+    }
+
+    return token;
+}
+
+int
+ParseVariable(int ordinal, int type)
+{
+    ORDDEF *odp;
+    ORDVARDEF *vdp;
+    char export_name[80];
+    char *token;
+    char *endptr;
+    int *value_array;
+    int n_values;
+    int value_array_size;
+    
+    strcpy(export_name, GetToken());
+
+    token = GetToken();
+    if (*token != '(')
+    {
+	fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
+	exit(1);
+    }
+
+    n_values = 0;
+    value_array_size = 25;
+    value_array = malloc(sizeof(*value_array) * value_array_size);
+    
+    while ((token = GetToken()) != NULL)
+    {
+	if (*token == ')')
+	    break;
+
+	value_array[n_values++] = strtol(token, &endptr, 0);
+	if (n_values == value_array_size)
+	{
+	    value_array_size += 25;
+	    value_array = realloc(value_array, 
+				  sizeof(*value_array) * value_array_size);
+	}
+	
+	if (endptr == NULL || *endptr != '\0')
+	{
+	    fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
+		    token);
+	    exit(1);
+	}
+    }
+    
+    if (token == NULL)
+    {
+	fprintf(stderr, "%d: End of file in variable declaration\n", Line);
+	exit(1);
+    }
+
+    if (ordinal >= MAX_ORDINALS)
+    {
+	fprintf(stderr, "%d: Ordinal number too large\n", Line);
+	exit(1);
+    }
+    
+    odp = &OrdinalDefinitions[ordinal];
+    odp->valid = 1;
+    odp->type = type;
+    strcpy(odp->export_name, export_name);
+    
+    vdp = malloc(sizeof(*vdp));
+    odp->additional_data = vdp;
+    
+    vdp->n_values = n_values;
+    vdp->values = realloc(value_array, sizeof(*value_array) * n_values);
+
+    return 0;
+}
+
+int
+ParseExportFunction(int ordinal, int type)
+{
+    char *token;
+    ORDDEF *odp;
+    ORDFUNCDEF *fdp;
+    int arg_types[16];
+    int i;
+    int arg_num;
+    int current_offset;
+    int arg_size;
+	
+    
+    if (ordinal >= MAX_ORDINALS)
+    {
+	fprintf(stderr, "%d: Ordinal number too large\n", Line);
+	exit(1);
+    }
+    
+    odp = &OrdinalDefinitions[ordinal];
+    strcpy(odp->export_name, GetToken());
+    odp->valid = 1;
+    odp->type = type;
+    fdp = malloc(sizeof(*fdp));
+    odp->additional_data = fdp;
+
+    token = GetToken();
+    if (*token != '(')
+    {
+	fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
+	exit(1);
+    }
+
+    fdp->arg_16_size = 0;
+    for (i = 0; i < 16; i++)
+    {
+	token = GetToken();
+	if (*token == ')')
+	    break;
+
+	if (stricmp(token, "byte") == 0 || stricmp(token, "word") == 0)
+	{
+	    fdp->arg_types_16[i] = VARTYPE_WORD;
+	    fdp->arg_16_size += 2;
+	    fdp->arg_16_offsets[i] = 2;
+	}
+	else if (stricmp(token, "s_byte") == 0 || 
+		 stricmp(token, "s_word") == 0)
+	{
+	    fdp->arg_types_16[i] = VARTYPE_SIGNEDWORD;
+	    fdp->arg_16_size += 2;
+	    fdp->arg_16_offsets[i] = 2;
+	}
+	else if (stricmp(token, "long") == 0 || stricmp(token, "s_long") == 0)
+	{
+	    fdp->arg_types_16[i] = VARTYPE_LONG;
+	    fdp->arg_16_size += 4;
+	    fdp->arg_16_offsets[i] = 4;
+	}
+	else if (stricmp(token, "ptr") == 0)
+	{
+	    fdp->arg_types_16[i] = VARTYPE_FARPTR;
+	    fdp->arg_16_size += 4;
+	    fdp->arg_16_offsets[i] = 4;
+	}
+	else
+	{
+	    fprintf(stderr, "%d: Unknown variable type '%s'\n", Line, token);
+	    exit(1);
+	}
+    }
+    fdp->n_args_16 = i;
+
+    if (type == FUNCTYPE_PASCAL || type == FUNCTYPE_REG)
+    {
+	current_offset = 0;
+	for (i--; i >= 0; i--)
+	{
+	    arg_size = fdp->arg_16_offsets[i];
+	    fdp->arg_16_offsets[i] = current_offset;
+	    current_offset += arg_size;
+	}
+    }
+    else
+    {
+	current_offset = 0;
+	for (i = 0; i < fdp->n_args_16; i++)
+	{
+	    arg_size = fdp->arg_16_offsets[i];
+	    fdp->arg_16_offsets[i] = current_offset;
+	    current_offset += arg_size;
+	}
+    }
+
+    strcpy(fdp->internal_name, GetToken());
+    token = GetToken();
+    if (*token != '(')
+    {
+	fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
+	exit(1);
+    }
+    for (i = 0; i < 16; i++)
+    {
+	token = GetToken();
+	if (*token == ')')
+	    break;
+
+	fdp->arg_indices_32[i] = atoi(token);
+	if (fdp->arg_indices_32[i] < 1 || 
+	    fdp->arg_indices_32[i] > fdp->n_args_16)
+	{
+	    fprintf(stderr, "%d: Bad argument index %d\n", Line,
+		    fdp->arg_indices_32[i]);
+	    exit(1);
+	}
+    }
+    fdp->n_args_32 = i;
+
+    return 0;
+}
+
+int
+ParseEquate(int ordinal)
+{
+    ORDDEF *odp;
+    char *token;
+    char *endptr;
+    int value;
+    
+    if (ordinal >= MAX_ORDINALS)
+    {
+	fprintf(stderr, "%d: Ordinal number too large\n", Line);
+	exit(1);
+    }
+    
+    odp = &OrdinalDefinitions[ordinal];
+    strcpy(odp->export_name, GetToken());
+
+    token = GetToken();
+    value = strtol(token, &endptr, 0);
+    if (endptr == NULL || *endptr != '\0')
+    {
+	fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
+		token);
+	exit(1);
+    }
+
+    odp->valid = 1;
+    odp->type = EQUATETYPE_ABS;
+    odp->additional_data = (void *) value;
+
+    return 0;
+}
+
+int
+ParseReturn(int ordinal)
+{
+    ORDDEF *odp;
+    ORDRETDEF *rdp;
+    char *token;
+    char *endptr;
+    int value;
+    
+    if (ordinal >= MAX_ORDINALS)
+    {
+	fprintf(stderr, "%d: Ordinal number too large\n", Line);
+	exit(1);
+    }
+
+    rdp = malloc(sizeof(*rdp));
+    
+    odp = &OrdinalDefinitions[ordinal];
+    strcpy(odp->export_name, GetToken());
+    odp->valid = 1;
+    odp->type = TYPE_RETURN;
+    odp->additional_data = rdp;
+
+    token = GetToken();
+    rdp->arg_size = strtol(token, &endptr, 0);
+    if (endptr == NULL || *endptr != '\0')
+    {
+	fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
+		token);
+	exit(1);
+    }
+
+    token = GetToken();
+    rdp->ret_value = strtol(token, &endptr, 0);
+    if (endptr == NULL || *endptr != '\0')
+    {
+	fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
+		token);
+	exit(1);
+    }
+
+    return 0;
+}
+
+int
+ParseOrdinal(int ordinal)
+{
+    char *token;
+    
+    token = GetToken();
+    if (token == NULL)
+    {
+	fprintf(stderr, "%d: Expected type after ordinal\n", Line);
+	exit(1);
+    }
+
+    if (stricmp(token, "byte") == 0)
+	return ParseVariable(ordinal, VARTYPE_BYTE);
+    else if (stricmp(token, "word") == 0)
+	return ParseVariable(ordinal, VARTYPE_WORD);
+    else if (stricmp(token, "long") == 0)
+	return ParseVariable(ordinal, VARTYPE_LONG);
+    else if (stricmp(token, "c") == 0)
+	return ParseExportFunction(ordinal, FUNCTYPE_C);
+    else if (stricmp(token, "p") == 0)
+	return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
+    else if (stricmp(token, "pascal") == 0)
+	return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
+    else if (stricmp(token, "register") == 0)
+	return ParseExportFunction(ordinal, FUNCTYPE_REG);
+    else if (stricmp(token, "equate") == 0)
+	return ParseEquate(ordinal);
+    else if (stricmp(token, "return") == 0)
+	return ParseReturn(ordinal);
+    else
+    {
+	fprintf(stderr, 
+		"%d: Expected type after ordinal, found '%s' instead\n",
+		Line, token);
+	exit(1);
+    }
+}
+
+int
+ParseTopLevel(void)
+{
+    char *token;
+    
+    while ((token = GetToken()) != NULL)
+    {
+	if (stricmp(token, "name") == 0)
+	{
+	    strcpy(LowerDLLName, GetToken());
+	    strlower(LowerDLLName);
+
+	    strcpy(UpperDLLName, LowerDLLName);
+	    strupper(UpperDLLName);
+	}
+	else if (stricmp(token, "id") == 0)
+	{
+	    token = GetToken();
+	    if (!IsNumberString(token))
+	    {
+		fprintf(stderr, "%d: Expected number after id\n", Line);
+		exit(1);
+	    }
+	    
+	    DLLId = atoi(token);
+	}
+	else if (stricmp(token, "length") == 0)
+	{
+	    token = GetToken();
+	    if (!IsNumberString(token))
+	    {
+		fprintf(stderr, "%d: Expected number after length\n", Line);
+		exit(1);
+	    }
+
+	    Limit = atoi(token);
+	}
+	else if (IsNumberString(token))
+	{
+	    int ordinal;
+	    int rv;
+	    
+	    ordinal = atoi(token);
+	    if ((rv = ParseOrdinal(ordinal)) < 0)
+		return rv;
+	}
+	else
+	{
+	    fprintf(stderr, 
+		    "%d: Expected name, id, length or ordinal\n", Line);
+	    exit(1);
+	}
+    }
+
+    return 0;
+}
+
+void
+OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
+{
+    ORDVARDEF *vdp;
+    int i;
+
+    fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
+
+    vdp = odp->additional_data;
+    for (i = 0; i < vdp->n_values; i++)
+    {
+	if ((i & 7) == 0)
+	    fprintf(fp, "\t%s\t", storage);
+	    
+	fprintf(fp, "%d", vdp->values[i]);
+	
+	if ((i & 7) == 7 || i == vdp->n_values - 1)
+	    fprintf(fp, "\n");
+	else
+	    fprintf(fp, ", ");
+    }
+    fprintf(fp, "\n");
+}
+
+main(int argc, char **argv)
+{
+    ORDDEF *odp;
+    ORDFUNCDEF *fdp;
+    ORDRETDEF *rdp;
+    FILE *fp;
+    char filename[80];
+    char buffer[80];
+    char *p;
+    int i;
+    
+    if (argc < 2)
+    {
+	fprintf(stderr, "usage: build SPECNAME\n");
+	exit(1);
+    }
+
+    SpecFp = fopen(argv[1], "r");
+    if (SpecFp == NULL)
+    {
+	fprintf(stderr, "Could not open specification file, '%s'\n", argv[1]);
+	exit(1);
+    }
+
+    ParseTopLevel();
+
+    /**********************************************************************
+     *					DLL ENTRY POINTS
+     */
+    sprintf(filename, "dll_%s.S", LowerDLLName);
+    fp = fopen(filename, "w");
+
+    fprintf(fp, "\t.globl _%s_Dispatch\n", UpperDLLName);
+    fprintf(fp, "_%s_Dispatch:\n", UpperDLLName);
+    fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
+    fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
+    fprintf(fp, "\torl\t$0x%08x,%%eax\n", DLLId << 16);
+    fprintf(fp, "\tjmp\t_CallTo32\n\n");
+
+    odp = OrdinalDefinitions;
+    for (i = 0; i <= Limit; i++, odp++)
+    {
+	fprintf(fp, "\t.globl _%s_Ordinal_%d\n", UpperDLLName, i);
+
+	if (!odp->valid)
+	{
+	    fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
+#ifdef BOB_SAYS_NO
+	    fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
+	    fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
+#endif
+	    fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
+	    fprintf(fp, "\tpushw\t$0\n");
+	    fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
+	}
+	else
+	{
+	    fdp = odp->additional_data;
+	    rdp = odp->additional_data;
+	    
+	    switch (odp->type)
+	    {
+	      case EQUATETYPE_ABS:
+		fprintf(fp, "_%s_Ordinal_%d = %d\n\n", 
+			UpperDLLName, i, (int) odp->additional_data);
+		break;
+
+	      case VARTYPE_BYTE:
+		OutputVariableCode(fp, ".byte", odp);
+		break;
+
+	      case VARTYPE_WORD:
+		OutputVariableCode(fp, ".word", odp);
+		break;
+
+	      case VARTYPE_LONG:
+		OutputVariableCode(fp, ".long", odp);
+		break;
+
+	      case TYPE_RETURN:
+		fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
+		fprintf(fp, "\tmovw\t$%d,%%ax\n", rdp->ret_value & 0xffff);
+		fprintf(fp, "\tmovw\t$%d,%%dx\n", 
+			(rdp->ret_value >> 16) & 0xffff);
+		fprintf(fp, "\t.byte\t0x66\n");
+		if (rdp->arg_size != 0)
+		    fprintf(fp, "\tlret\t$%d\n", rdp->arg_size);
+		else
+		    fprintf(fp, "\tlret\n");
+		break;
+
+	      case FUNCTYPE_REG:
+		fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
+		fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
+		fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
+		fprintf(fp, "\tpushl\t$0\n");			/* cr2     */
+		fprintf(fp, "\tpushl\t$0\n");			/* oldmask */
+		fprintf(fp, "\tpushl\t$0\n");			/* i387    */
+		fprintf(fp, "\tpushw\t$0\n");			/* __ssh   */
+		fprintf(fp, "\tpushw\t%%ss\n");			/* ss      */
+		fprintf(fp, "\tpushl\t%%esp\n");		/* esp     */
+		fprintf(fp, "\tpushfl\n");			/* eflags  */
+		fprintf(fp, "\tpushw\t$0\n");			/* __csh   */
+		fprintf(fp, "\tpushw\t%%cs\n");			/* cs      */
+		fprintf(fp, "\tpushl\t$0\n");			/* eip     */
+		fprintf(fp, "\tpushl\t$0\n");			/* err     */
+		fprintf(fp, "\tpushl\t$0\n");			/* trapno  */
+		fprintf(fp, "\tpushal\n");			/* AX, ... */
+		fprintf(fp, "\tpushw\t$0\n");			/* __dsh   */
+		fprintf(fp, "\tpushw\t%%ds\n");			/* ds      */
+		fprintf(fp, "\tpushw\t$0\n");			/* __esh   */
+		fprintf(fp, "\tpushw\t%%es\n");			/* es      */
+		fprintf(fp, "\tpushw\t$0\n");			/* __fsh   */
+		fprintf(fp, "\tpushw\t%%fs\n");			/* fs      */
+		fprintf(fp, "\tpushw\t$0\n");			/* __gsh   */
+		fprintf(fp, "\tpushw\t%%gs\n");			/* gs      */
+		fprintf(fp, "\tmovl\t%%ebp,%%eax\n");
+		fprintf(fp, "\tmovw\t%%esp,%%ebp\n");
+		fprintf(fp, "\tpushl\t88(%%ebp)\n");
+		fprintf(fp, "\tmovl\t%%eax,%%ebp\n");
+		fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
+		fprintf(fp, "\tpushw\t$92\n");
+		fprintf(fp, "\tjmp\t_%s_Relay_%d:\n", UpperDLLName, i);
+		break;
+
+	      case FUNCTYPE_PASCAL:
+		fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
+#ifdef BOB_SAYS_NO
+		fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
+		fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
+#endif
+		fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
+		fprintf(fp, "\tpushw\t$%d\n", fdp->arg_16_size);
+		fprintf(fp, "\tjmp\t_%s_Relay_%d:\n", UpperDLLName, i);
+		break;
+		
+	      case FUNCTYPE_C:
+	      default:
+		fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
+#ifdef BOB_SAYS_NO
+		fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
+		fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
+#endif
+		fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
+		fprintf(fp, "\tpushw\t$0\n");
+		fprintf(fp, "\tjmp\t_%s_Relay_%d:\n", UpperDLLName, i);
+		break;
+	    }
+	}
+    }
+
+    fclose(fp);
+
+    /**********************************************************************
+     *					RELAY CODE
+     */
+    sprintf(filename, "rly_%s.S", LowerDLLName);
+    fp = fopen(filename, "w");
+
+    odp = OrdinalDefinitions;
+    for (i = 0; i <= Limit; i++, odp++)
+    {
+	if (!odp->valid)
+	    continue;
+
+	fdp = odp->additional_data;
+	
+	fprintf(fp, "\t.globl _%s_Relay_%d\n", UpperDLLName, i);
+	fprintf(fp, "_%s_Relay_%d:\n", UpperDLLName, i);
+	fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
+	fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
+
+	fprintf(fp, "\tpushl\t%%ebp\n");
+	fprintf(fp, "\tmovl\t%%esp,%%ebp\n");
+
+	/*
+ 	 * Save registers.  286 mode does not have fs or gs.
+	 */
+	fprintf(fp, "\tpushw\t%%ds\n");
+	fprintf(fp, "\tpushw\t%%es\n");
+
+	/*
+	 * Restore segment registers.
+	 */
+	fprintf(fp, "\tmovw\t%d,%%ax\n", UDATASEL);
+	fprintf(fp, "\tmovw\t%%ax,%%ds\n");
+	fprintf(fp, "\tmovw\t%%ax,%%es\n");
+
+	/*
+	 * Save old stack save variables, save stack registers, reload
+	 * stack registers.
+	 */
+	fprintf(fp, "\tpushl\t_IF1632_Saved16_esp\n");
+	fprintf(fp, "\tpushl\t_IF1632_Saved16_ebp\n");
+	fprintf(fp, "\tpushw\t_IF1632_Saved16_ss\n");
+
+	fprintf(fp, "\tmovw\t%%ss,_IF1632_Saved16_ss\n");
+	fprintf(fp, "\tmovl\t%%esp,_IF1632_Saved16_esp\n");
+	fprintf(fp, "\tmovl\t%%ebp,_IF1632_Saved16_ebp\n");
+
+	fprintf(fp, "\tmovw\t%%ss,%%ax\n");
+	fprintf(fp, "\tshll\t16,%%eax\n");
+	fprintf(fp, "\torl\t%%esp,%%eax\n");
+
+	fprintf(fp, "\tmovw\t_IF1632_Saved32_ss,%%ss\n");
+	fprintf(fp, "\tmovl\t_IF1632_Saved32_esp,%%esp\n");
+	fprintf(fp, "\tmovl\t_IF1632_Saved32_ebp,%%ebp\n");
+
+	fprintf(fp, "\tpushl\t_Stack16Frame\n");
+	fprintf(fp, "\tmovl\t%%eax,_Stack16Frame\n");
+
+	/*
+	 * Move arguments.
+	 */
+	
+
+	/*
+	 * Call entry point
+	 */
+	fprintf(fp, "\tcall\t%s\n", fdp->internal_name);
+
+	/*
+ 	 * Restore registers, but do not destroy return value.
+	 */
+	fprintf(fp, "\tmovw\t_IF1632_Saved16_ss,%%ss\n");
+	fprintf(fp, "\tmovl\t_IF1632_Saved16_esp,%%esp\n");
+	fprintf(fp, "\tmovl\t_IF1632_Saved16_ebp,%%ebp\n");
+
+	fprintf(fp, "\tpopw\t_IF1632_Saved16_ss\n");
+	fprintf(fp, "\tpopl\t_IF1632_Saved16_ebp\n");
+	fprintf(fp, "\tpopl\t_IF1632_Saved16_esp\n");
+
+	fprintf(fp, "\tpopw\t%%es\n");
+	fprintf(fp, "\tpopw\t%%ds\n");
+
+	fprintf(fp, "\t.align\t2,0x90\n");
+	fprintf(fp, "\tleave\n");
+	
+	/*
+	 * Now we need to ditch the parameter bytes that were left on the
+	 * stack. We do this by effectively popping the number of bytes,
+	 * and the return address, removing the parameters and then putting
+	 * the return address back on the stack.
+	 * Normally this field is filled in by the relevant function in
+	 * the emulation library, since it should know how many bytes to
+	 * expect.
+	 */
+	fprintf(fp, "\tpopw\t%%gs:nbytes\n");
+	fprintf(fp, "\tcmpw\t$0,%%gs:nbytes\n");
+	fprintf(fp, "\tje\tnoargs\n");
+	fprintf(fp, "\tpopw\t%%gs:offset\n");
+	fprintf(fp, "\tpopw\t%%gs:selector\n");
+	fprintf(fp, "\taddw\t%%gs:nbytes,%%esp\n");
+	fprintf(fp, "\tpushw\t%%gs:selector\n");
+	fprintf(fp, "\tpushw\t%%gs:offset\n");
+	fprintf(fp, "noargs:\n");
+
+	/*
+	 * Last, but not least we need to move the high word from eax to dx
+	 */
+	fprintf(fp, "\t	pushl\t%%eax\n");
+	fprintf(fp, "\tpopw\t%%dx\n");
+	fprintf(fp, "\tpopw\t%%dx\n");
+
+	fprintf(fp, "\t.byte\t0x66\n");
+	fprintf(fp, "\tlret\n");
+
+    }
+
+    fclose(fp);
+
+    /**********************************************************************
+     *					DLL ENTRY TABLE
+     */
+#ifndef SHORTNAMES
+    sprintf(filename, "dll_%s_tab.c", LowerDLLName);
+#else
+    sprintf(filename, "dtb_%s.c", LowerDLLName);
+#endif
+    fp = fopen(filename, "w");
+
+    fprintf(fp, "#include <stdio.h>\n");
+    fprintf(fp, "#include <stdlib.h>\n");
+    fprintf(fp, "#include \042dlls.h\042\n\n");
+
+    for (i = 0; i <= Limit; i++)
+    {
+	fprintf(fp, "extern void %s_Ordinal_%d();\n", UpperDLLName, i);
+    }
+    
+    odp = OrdinalDefinitions;
+    for (i = 0; i <= Limit; i++, odp++)
+    {
+	if (odp->valid && 
+	    (odp->type == FUNCTYPE_PASCAL || odp->type == FUNCTYPE_C ||
+	     odp->type == FUNCTYPE_REG))
+	{
+	    fdp = odp->additional_data;
+	    fprintf(fp, "extern int %s();\n", fdp->internal_name);
+	}
+    }
+    
+    fprintf(fp, "\nstruct dll_table_entry_s %s_table[%d] =\n", 
+	    UpperDLLName, Limit + 1);
+    fprintf(fp, "{\n");
+    odp = OrdinalDefinitions;
+    for (i = 0; i <= Limit; i++, odp++)
+    {
+	fdp = odp->additional_data;
+
+	if (!odp->valid)
+	    odp->type = -1;
+	
+	switch (odp->type)
+	{
+	  case FUNCTYPE_PASCAL:
+	  case FUNCTYPE_REG:
+	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
+	    fprintf(fp, "\042%s\042, ", odp->export_name);
+	    fprintf(fp, "%s, DLL_HANDLERTYPE_PASCAL, ", fdp->internal_name);
+#ifdef WINESTAT
+	    fprintf(fp, "0, ");
+#endif	    
+	    fprintf(fp, "%d, ", fdp->n_args_32);
+	    if (fdp->n_args_32 > 0)
+	    {
+		int argnum;
+		
+		fprintf(fp, "\n      {\n");
+		for (argnum = 0; argnum < fdp->n_args_32; argnum++)
+		{
+		    fprintf(fp, "        { %d, %d },\n",
+			    fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
+			    fdp->arg_types_16[argnum]);
+		}
+		fprintf(fp, "      }\n    ");
+	    }
+	    fprintf(fp, "}, \n");
+	    break;
+		
+	  case FUNCTYPE_C:
+	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
+	    fprintf(fp, "\042%s\042, ", odp->export_name);
+	    fprintf(fp, "%s, DLL_HANDLERTYPE_C, ", fdp->internal_name);
+#ifdef WINESTAT
+	    fprintf(fp, "0, ");
+#endif	    
+	    fprintf(fp, "%d, ", fdp->n_args_32);
+	    if (fdp->n_args_32 > 0)
+	    {
+		int argnum;
+		
+		fprintf(fp, "\n      {\n");
+		for (argnum = 0; argnum < fdp->n_args_32; argnum++)
+		{
+		    fprintf(fp, "        { %d, %d },\n",
+			    fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
+			    fdp->arg_types_16[argnum]);
+		}
+		fprintf(fp, "      }\n    ");
+	    }
+	    fprintf(fp, "}, \n");
+	    break;
+	    
+	  default:
+	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, \042\042, NULL },\n", 
+		    UTEXTSEL, UpperDLLName, i);
+	    break;
+	}
+    }
+    fprintf(fp, "};\n");
+
+    fclose(fp);
+}
+
diff --git a/windows/Imakefile b/windows/Imakefile
index 947968a..9689eff 100644
--- a/windows/Imakefile
+++ b/windows/Imakefile
@@ -15,6 +15,7 @@
 	graphics.c \
 	keyboard.c \
 	mapping.c \
+	mdi.c \
 	message.c \
 	nonclient.c \
 	painting.c \
diff --git a/windows/class.c b/windows/class.c
index fbec0a1..68277c6 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -6,11 +6,16 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
 #include "class.h"
 #include "user.h"
 #include "win.h"
 #include "dce.h"
 
+/* #define DEBUG_CLASS /* */
+
 
 static HCLASS firstClass = 0;
 
@@ -88,8 +93,9 @@
     HCLASS handle, prevClass;
     
 #ifdef DEBUG_CLASS
-    printf( "RegisterClass: wndproc=%08x hinst=%d name='%s'\n", 
-	    class->lpfnWndProc, class->hInstance, class->lpszClassName );
+    printf( "RegisterClass: wndproc=%08x hinst=%d name='%s' background %x\n", 
+	    class->lpfnWndProc, class->hInstance, class->lpszClassName,
+	    class->hbrBackground );
 #endif
 
       /* Check if a class with this name already exists */
@@ -117,14 +123,25 @@
     if (newClass->wc.style & CS_GLOBALCLASS)
 	newClass->atomName = GlobalAddAtom( class->lpszClassName );
     else newClass->atomName = AddAtom( class->lpszClassName );
+    newClass->wc.lpszClassName = NULL; 
 
     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; 
-    
+      /* Make a copy of the menu name (only if it is a string) */
+
+    if ((int)class->lpszMenuName & 0xffff0000)
+    {
+	HANDLE hname;
+	hname = USER_HEAP_ALLOC( GMEM_MOVEABLE, strlen(class->lpszMenuName)+1);
+	if (hname)
+	{
+	    newClass->wc.lpszMenuName = (char *)USER_HEAP_ADDR( hname );
+	    strcpy( newClass->wc.lpszMenuName, class->lpszMenuName );
+	}
+    }
+
     if (class->cbClsExtra) memset( newClass->wExtra, 0, class->cbClsExtra );
     firstClass = handle;
     return newClass->atomName;
@@ -136,7 +153,7 @@
  */
 BOOL UnregisterClass( LPSTR className, HANDLE instance )
 {
-    HANDLE class, next, prevClass;
+    HANDLE class, prevClass;
     CLASS * classPtr, * prevClassPtr;
     
       /* Check if we can remove this class */
@@ -167,6 +184,8 @@
     if (classPtr->wc.hbrBackground) DeleteObject( classPtr->wc.hbrBackground );
     if (classPtr->wc.style & CS_GLOBALCLASS) GlobalDeleteAtom( classPtr->atomName );
     else DeleteAtom( classPtr->atomName );
+    if ((int)classPtr->wc.lpszMenuName & 0xffff0000)
+	USER_HEAP_FREE( (int)classPtr->wc.lpszMenuName & 0xffff );
     USER_HEAP_FREE( class );
     return TRUE;
 }
diff --git a/windows/dc.c b/windows/dc.c
index 4224b3a..58dd531 100644
--- a/windows/dc.c
+++ b/windows/dc.c
@@ -7,16 +7,17 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
 #include <stdlib.h>
-
+#include <string.h>
 #include "gdi.h"
-
-extern HBITMAP BITMAP_hbitmapMemDC;
+#include "bitmap.h"
 
 static DeviceCaps * displayDevCaps = NULL;
 
 extern const WIN_DC_INFO DCVAL_defaultValues;
 
-extern void CLIPPING_SetDeviceClipping( DC * dc );  /* in objects/clipping.c */
+extern void CLIPPING_SetDeviceClipping( DC * dc );     /* objects/clipping.c */
+extern WORD COLOR_ToPhysical( DC *dc, COLORREF color );/* objects/color.c */
+extern void COLOR_SetMapping( DC *dc, HANDLE, WORD );  /* objects/color.c */
 
 
   /* ROP code to GC function conversion */
@@ -50,11 +51,11 @@
 {
     caps->version       = 0x300; 
     caps->technology    = DT_RASDISPLAY;
-    caps->horzSize      = WidthMMOfScreen( XT_screen );
-    caps->vertSize      = HeightMMOfScreen( XT_screen );
-    caps->horzRes       = WidthOfScreen( XT_screen );
-    caps->vertRes       = HeightOfScreen( XT_screen );
-    caps->bitsPixel     = DefaultDepthOfScreen( XT_screen );
+    caps->horzSize      = WidthMMOfScreen(screen) * screenWidth / WidthOfScreen(screen);
+    caps->vertSize      = HeightMMOfScreen(screen) * screenHeight / HeightOfScreen(screen);
+    caps->horzRes       = screenWidth;
+    caps->vertRes       = screenHeight;
+    caps->bitsPixel     = screenDepth;
     caps->planes        = 1;
     caps->numBrushes    = 0;
     caps->numPens       = 0;
@@ -81,26 +82,26 @@
     caps->aspectXY      = 51;
     caps->logPixelsX    = (int)(caps->horzRes * 25.4 / caps->horzSize);
     caps->logPixelsY    = (int)(caps->vertRes * 25.4 / caps->vertSize);
-    caps->sizePalette   = DefaultVisual( XT_display, DefaultScreen(XT_display) )->map_entries;
+    caps->sizePalette   = DefaultVisual(display,DefaultScreen(display))->map_entries;
     caps->numReserved   = 0;
     caps->colorRes      = 0;
 }
 
 
 /***********************************************************************
- *           DC_SetDeviceInfo
+ *           DC_InitDC
  *
- * Set device-specific info from device-independent info.
+ * Setup device-specific DC values for a newly created DC.
  */
-void DC_SetDeviceInfo( HDC hdc, DC * dc )
+static void DC_InitDC( HDC hdc )
 {
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    RealizeDefaultPalette( hdc );
     SetTextColor( hdc, dc->w.textColor );
     SetBkColor( hdc, dc->w.backgroundColor );
-    SetROP2( hdc, dc->w.ROPmode );
     SelectObject( hdc, dc->w.hPen );
     SelectObject( hdc, dc->w.hBrush );
     SelectObject( hdc, dc->w.hFont );
-    
     XSetGraphicsExposures( XT_display, dc->u.x.gc, False );
     CLIPPING_SetDeviceClipping( dc );
 }
@@ -114,6 +115,9 @@
  */
 int DC_SetupGCForBrush( DC * dc )
 {
+    XGCValues val;
+    unsigned long mask = 0;
+
     if (dc->u.x.brush.style == BS_NULL) return 0;
     if (dc->u.x.brush.pixel == -1)
     {
@@ -121,26 +125,34 @@
 	 * We need to swap foreground and background because
 	 * Windows does it the wrong way...
 	 */
-	XSetForeground( XT_display, dc->u.x.gc, dc->w.backgroundPixel );
-	XSetBackground( XT_display, dc->u.x.gc, dc->w.textPixel );
+	val.foreground = dc->w.backgroundPixel;
+	val.background = dc->w.textPixel;
     }
     else
     {
-	XSetForeground( XT_display, dc->u.x.gc, dc->u.x.brush.pixel );
-	XSetBackground( XT_display, dc->u.x.gc, dc->w.backgroundPixel );
+	val.foreground = dc->u.x.brush.pixel;
+	val.background = dc->w.backgroundPixel;
     }
-
-    if (dc->u.x.brush.fillStyle != FillStippled)
-	XSetFillStyle( XT_display, dc->u.x.gc, dc->u.x.brush.fillStyle );
-    else
-	XSetFillStyle( XT_display, dc->u.x.gc,
-		       (dc->w.backgroundMode == OPAQUE) ? 
-		          FillOpaqueStippled : FillStippled );
-    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 );
+    val.function = DC_XROPfunction[dc->w.ROPmode-1];
+    val.fill_style = dc->u.x.brush.fillStyle;
+    if (val.fill_style == FillStippled)
+    {
+	if (dc->w.backgroundMode==OPAQUE) val.fill_style = FillOpaqueStippled;
+	val.stipple = dc->u.x.brush.pixmap;
+	mask = GCStipple;
+    }
+    else if (val.fill_style == FillTiled)
+    {
+	val.tile = dc->u.x.brush.pixmap;
+	mask = GCTile;
+    }
+    val.ts_x_origin = dc->w.DCOrgX + dc->w.brushOrgX;
+    val.ts_y_origin = dc->w.DCOrgY + dc->w.brushOrgY;
+    val.fill_rule = (dc->w.polyFillMode==WINDING) ? WindingRule : EvenOddRule;
+    XChangeGC( display, dc->u.x.gc, 
+	       GCFunction | GCForeground | GCBackground | GCFillStyle |
+	       GCFillRule | GCTileStipXOrigin | GCTileStipYOrigin | mask,
+	       &val );
     return 1;
 }
 
@@ -153,23 +165,27 @@
  */
 int DC_SetupGCForPen( DC * dc )
 {
+    XGCValues val;
+
     if (dc->u.x.pen.style == PS_NULL) return 0;
-    XSetForeground( XT_display, dc->u.x.gc, dc->u.x.pen.pixel );
-    XSetBackground( XT_display, dc->u.x.gc, dc->w.backgroundPixel );
-    XSetFillStyle( XT_display, dc->u.x.gc, FillSolid );
-    if ((dc->u.x.pen.style == PS_SOLID) ||
-	(dc->u.x.pen.style == PS_INSIDEFRAME))
+    val.function   = DC_XROPfunction[dc->w.ROPmode-1];
+    val.foreground = dc->u.x.pen.pixel;
+    val.background = dc->w.backgroundPixel;
+    val.fill_style = FillSolid;
+    if ((dc->u.x.pen.style!=PS_SOLID) && (dc->u.x.pen.style!=PS_INSIDEFRAME))
     {
-	XSetLineAttributes( XT_display, dc->u.x.gc, dc->u.x.pen.width, 
-			    LineSolid, CapRound, JoinBevel );    
+	XSetDashes( display, dc->u.x.gc, 0,
+		    dc->u.x.pen.dashes, dc->u.x.pen.dash_len );
+	val.line_style = (dc->w.backgroundMode == OPAQUE) ?
+	                      LineDoubleDash : LineOnOffDash;
     }
-    else
-    {
-    	XSetLineAttributes( XT_display, dc->u.x.gc, dc->u.x.pen.width, 
-	     (dc->w.backgroundMode == OPAQUE) ? LineDoubleDash : LineOnOffDash,
-	     CapRound, JoinBevel );
-    }
-    XSetFunction( XT_display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
+    else val.line_style = LineSolid;
+    val.line_width = dc->u.x.pen.width;
+    val.cap_style  = CapRound;
+    val.join_style = JoinBevel;
+    XChangeGC( display, dc->u.x.gc, 
+	       GCFunction | GCForeground | GCBackground | GCLineWidth |
+	       GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle, &val );
     return 1;    
 }
 
@@ -182,12 +198,20 @@
  */
 int DC_SetupGCForText( DC * dc )
 {
-    XSetForeground( XT_display, dc->u.x.gc, dc->w.textPixel );
-    XSetBackground( XT_display, dc->u.x.gc, dc->w.backgroundPixel );
-    XSetFillStyle( XT_display, dc->u.x.gc, FillSolid );
-    XSetFunction( XT_display, dc->u.x.gc, DC_XROPfunction[dc->w.ROPmode-1] );
-    if (!dc->u.x.font.fstruct) return 0;
-    XSetFont( XT_display, dc->u.x.gc, dc->u.x.font.fstruct->fid );
+    XGCValues val;
+
+    if (!dc->u.x.font.fstruct)
+    {
+	FONT_SelectObject(dc, STOCK_SYSTEM_FIXED_FONT, NULL);
+    }
+    val.function   = DC_XROPfunction[dc->w.ROPmode-1];
+    val.foreground = dc->w.textPixel;
+    val.background = dc->w.backgroundPixel;
+    val.fill_style = FillSolid;
+    val.font       = dc->u.x.font.fstruct->fid;
+    XChangeGC( display, dc->u.x.gc, 
+	       GCFunction | GCForeground | GCBackground | GCFillStyle |
+	       GCFont, &val );
     return 1;
 }
 
@@ -223,6 +247,7 @@
 	CombineRgn( newdc->w.hVisRgn, dc->w.hVisRgn, 0, RGN_COPY );	
     }
     newdc->w.hGCClipRgn = 0;
+    COLOR_SetMapping( newdc, dc->u.x.pal.hMapping, dc->u.x.pal.mappingSize );
     return handle;
 }
 
@@ -243,10 +268,16 @@
     if (dc->w.hClipRgn)	DeleteObject( dc->w.hClipRgn );
     if (dc->w.hVisRgn) DeleteObject( dc->w.hVisRgn );
     if (dc->w.hGCClipRgn) DeleteObject( dc->w.hGCClipRgn );
+
     memcpy( &dc->w, &dcs->w, sizeof(dc->w) );
+    memcpy( &dc->u.x.pen, &dcs->u.x.pen, sizeof(dc->u.x.pen) );
     dc->w.hClipRgn = dc->w.hVisRgn = dc->w.hGCClipRgn = 0;
     dc->w.flags &= ~DC_SAVED;
-    DC_SetDeviceInfo( hdc, dc );
+
+    SelectObject( hdc, dcs->w.hBrush );
+    SelectObject( hdc, dcs->w.hFont );
+    COLOR_SetMapping( dc, dcs->u.x.pal.hMapping, dcs->u.x.pal.mappingSize );
+
     SelectClipRgn( hdc, dcs->w.hClipRgn );
     SelectVisRgn( hdc, dcs->w.hVisRgn );
 }
@@ -284,14 +315,14 @@
 #endif    
     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return FALSE;
     if (level == -1) level = dc->saveLevel;
-    if ((level < 1) || (level > dc->saveLevel))	return FALSE;
+    if ((level < 1) || (level > (short)dc->saveLevel)) return FALSE;
     
-    while (dc->saveLevel >= level)
+    while ((short)dc->saveLevel >= level)
     {
 	HDC hdcs = dc->header.hNext;
 	if (!(dcs = (DC *) GDI_GetObjPtr( hdcs, DC_MAGIC ))) return FALSE;
 	dc->header.hNext = dcs->header.hNext;
-	if (--dc->saveLevel < level) SetDCState( hdc, hdcs );
+	if ((short)--dc->saveLevel < level) SetDCState( hdc, hdcs );
 	DeleteDC( hdcs );
     }
     return TRUE;
@@ -324,22 +355,31 @@
     memcpy( &dc->w, &DCVAL_defaultValues, sizeof(DCVAL_defaultValues) );
     memset( &dc->u.x, 0, sizeof(dc->u.x) );
 
-    dc->u.x.drawable   = DefaultRootWindow( XT_display );
-    dc->u.x.gc         = XCreateGC( XT_display, dc->u.x.drawable, 0, NULL );
+    dc->u.x.drawable   = rootWindow;
+    dc->u.x.gc         = XCreateGC( display, dc->u.x.drawable, 0, NULL );
     dc->w.flags        = 0;
     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 );
+    DC_InitDC( handle );
 
     return handle;
 }
 
 
 /***********************************************************************
+ *           CreateIC    (GDI.153)
+ */
+HDC CreateIC( LPSTR driver, LPSTR device, LPSTR output, LPSTR initData )
+{
+      /* Nothing special yet for ICs */
+    return CreateDC( driver, device, output, initData );
+}
+
+
+/***********************************************************************
  *           CreateCompatibleDC    (GDI.52)
  */
 HDC CreateCompatibleDC( HDC hdc )
@@ -359,20 +399,17 @@
     memcpy( &dc->w, &DCVAL_defaultValues, sizeof(DCVAL_defaultValues) );
     memset( &dc->u.x, 0, sizeof(dc->u.x) );
 
-    dc->u.x.drawable   = XCreatePixmap( XT_display,
-				        DefaultRootWindow( XT_display ),
-				        1, 1, 1 );
-    dc->u.x.gc         = XCreateGC( XT_display, dc->u.x.drawable, 0, NULL );
+    dc->u.x.drawable   = XCreatePixmap( display, rootWindow, 1, 1, 1 );
+    dc->u.x.gc         = XCreateGC( display, dc->u.x.drawable, 0, NULL );
     dc->w.flags        = DC_MEMORY;
-    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 );
-    
+    DC_InitDC( handle );
+
     return handle;
 }
 
@@ -404,9 +441,7 @@
 	SelectObject( hdc, STOCK_BLACK_PEN );
 	SelectObject( hdc, STOCK_WHITE_BRUSH );
 	SelectObject( hdc, STOCK_SYSTEM_FONT );
-	
-	XFreeGC( XT_display, dc->u.x.gc );
-	if (dc->w.flags & DC_MEMORY) BITMAP_UnselectBitmap( dc );
+	XFreeGC( display, dc->u.x.gc );
     }
     
     if (dc->w.hClipRgn) DeleteObject( dc->w.hClipRgn );
@@ -446,8 +481,7 @@
 
     oldColor = dc->w.backgroundColor;
     dc->w.backgroundColor = color;
-    dc->w.backgroundPixel = GetNearestPaletteIndex( dc->w.hPalette, color );
-    XSetBackground( XT_display, dc->u.x.gc, dc->w.backgroundPixel );
+    dc->w.backgroundPixel = COLOR_ToPhysical( dc, color );
     return oldColor;
 }
 
@@ -463,8 +497,7 @@
 
     oldColor = dc->w.textColor;
     dc->w.textColor = color;
-    dc->w.textPixel = GetNearestPaletteIndex( dc->w.hPalette, color );
-    XSetForeground( XT_display, dc->u.x.gc, dc->w.textPixel );
+    dc->w.textPixel = COLOR_ToPhysical( dc, color );
     return oldColor;
 }
 
diff --git a/windows/dce.c b/windows/dce.c
index 6df7ccd..3dfe56e 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -193,7 +193,7 @@
 	IntersectVisRect( hdc, clipRect.left, clipRect.top,
 			  clipRect.right, clipRect.bottom );
     }
-    else dc->u.x.drawable = DefaultRootWindow( display );
+    else dc->u.x.drawable = rootWindow;
 
     if (flags & DCX_CLIPCHILDREN)
 	XSetSubwindowMode( display, dc->u.x.gc, ClipByChildren );
diff --git a/windows/defwnd.c b/windows/defwnd.c
index a495d08..5163a20 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -6,7 +6,8 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
-
+#include <stdlib.h>
+#include <stdio.h>
 #include "windows.h"
 #include "win.h"
 #include "class.h"
@@ -21,6 +22,7 @@
 extern LONG NC_HandleSysCommand( HWND hwnd, WORD wParam, POINT pt );
 extern LONG NC_HandleSetCursor( HWND hwnd, WORD wParam, LONG lParam );
 extern void NC_TrackSysMenu( HWND hwnd ); /* menu.c */
+extern BOOL ActivateMenuFocus(HWND hWnd); /* menu.c */
 
 
 
@@ -48,10 +50,11 @@
  */
 LONG DefWindowProc( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
 {
-    CLASS * classPtr;
-    LPSTR textPtr;
-    int len;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
+	MEASUREITEMSTRUCT *measure;
+	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 );
@@ -208,15 +211,31 @@
 	return NC_HandleSysCommand( hwnd, wParam, MAKEPOINT(lParam) );
 
     case WM_SYSKEYDOWN:
-    	if (wParam == VK_MENU) {
-    	    printf("VK_MENU Pressed // hMenu=%04X !\n", GetMenu(hwnd));
-	    NC_TrackSysMenu(hwnd);
-    	    }
-    	break;    	
+		if (wParam == VK_MENU) ActivateMenuFocus(hwnd);
+		break;    	
     case WM_SYSKEYUP:
-    	if (wParam == VK_MENU) {
-    	    printf("VK_MENU Released // hMenu=%04X !\n", GetMenu(hwnd));
-    	    }
+		break;    	
+    case WM_MENUCHAR:
+		MessageBeep(0);
+		break;    	
+    case WM_MEASUREITEM:
+		measure = (MEASUREITEMSTRUCT *)lParam;
+		switch(measure->CtlType) {
+			case ODT_BUTTON:
+				break;
+			case ODT_COMBOBOX:
+				measure->itemHeight = 10;
+/*				printf("defwndproc WM_MEASUREITEM // ODT_COMBOBOX !\n");*/
+				break;
+			case ODT_LISTBOX:
+				measure->itemHeight = 10;
+/*				printf("defwndproc WM_MEASUREITEM // ODT_LISTBOX !\n");*/
+				break;
+			case ODT_MENU:
+				break;
+			default:
+				break;
+			}
     	break;    	
     }
     return 0;
diff --git a/windows/dialog.c b/windows/dialog.c
index 9f0b64a..35dc9f0 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -6,6 +6,9 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
 #include "windows.h"
 #include "dialog.h"
 #include "win.h"
diff --git a/windows/event.c b/windows/event.c
index 87c0229..887d025 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -6,6 +6,8 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
+#include <stdlib.h>
+#include <stdio.h>
 #include <X11/Xlib.h>
 #include <X11/Xresource.h>
 #include <X11/Xutil.h>
@@ -21,7 +23,7 @@
 
 #define NB_BUTTONS      3     /* Windows can handle 3 buttons */
 
-extern Display * display;
+extern int desktopX, desktopY;   /* misc/main.c */
 
 extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
 
@@ -29,10 +31,10 @@
 static XContext winContext = 0;
 
   /* State variables */
+BOOL MouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
 static WORD ALTKeyState;
 static HWND captureWnd = 0;
 Window winHasCursor = 0;
-extern HWND hWndFocus;
 
 /* Keyboard translation tables */
 static int special_key[] =
@@ -117,13 +119,13 @@
 
   /* Event handlers */
 static void EVENT_key( HWND hwnd, XKeyEvent *event );
-static void EVENT_ButtonPress( HWND hwnd, XButtonEvent *event );
-static void EVENT_ButtonRelease( HWND hwnd, XButtonEvent *event );
-static void EVENT_MotionNotify( HWND hwnd, XMotionEvent *event );
-static void EVENT_EnterNotify( HWND hwnd, XCrossingEvent *event );
-static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event );
+static void EVENT_ButtonPress( XButtonEvent *event );
+static void EVENT_ButtonRelease( XButtonEvent *event );
+static void EVENT_MotionNotify( XMotionEvent *event );
+static void EVENT_EnterNotify( XCrossingEvent *event );
 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event );
 static void EVENT_Expose( HWND hwnd, XExposeEvent *event );
+static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event );
 
 
 /***********************************************************************
@@ -151,23 +153,19 @@
 	break;
 	
     case ButtonPress:
-	EVENT_ButtonPress( hwnd, (XButtonEvent*)event );
+	EVENT_ButtonPress( (XButtonEvent*)event );
 	break;
 
     case ButtonRelease:
-	EVENT_ButtonRelease( hwnd, (XButtonEvent*)event );
+	EVENT_ButtonRelease( (XButtonEvent*)event );
 	break;
 
     case MotionNotify:
-	EVENT_MotionNotify( hwnd, (XMotionEvent*)event );
+	EVENT_MotionNotify( (XMotionEvent*)event );
 	break;
 
     case EnterNotify:
-	EVENT_EnterNotify( hwnd, (XCrossingEvent*)event );
-	break;
-
-    case FocusIn:
-	EVENT_FocusIn( hwnd, (XFocusChangeEvent*)event );
+	EVENT_EnterNotify( (XCrossingEvent*)event );
 	break;
 
     case FocusOut:
@@ -178,6 +176,10 @@
 	EVENT_Expose( hwnd, (XExposeEvent*)event );
 	break;
 
+    case ConfigureNotify:
+	EVENT_ConfigureNotify( hwnd, (XConfigureEvent*)event );
+	break;
+
 #ifdef DEBUG_EVENT
     default:    
 	printf( "Unprocessed event %s for hwnd %d\n",
@@ -225,8 +227,10 @@
 static void EVENT_Expose( HWND hwnd, XExposeEvent *event )
 {
     RECT rect;
+    UINT flags;
     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);
@@ -234,8 +238,10 @@
     rect.bottom = rect.top + event->height;
     winHasCursor = event->window;
 
-    RedrawWindow( hwnd, &rect, 0,
-		  RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_NOCHILDREN );
+    flags = RDW_INVALIDATE | RDW_ERASE | RDW_FRAME;
+      /* Erase desktop background synchronously */
+    if (event->window == rootWindow) flags |= RDW_ERASENOW | RDW_NOCHILDREN;
+    RedrawWindow( hwnd, &rect, 0, flags );
 }
 
 
@@ -252,7 +258,7 @@
     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
@@ -260,12 +266,6 @@
 	   keysym, count, Str[0], Str);
 #endif
 
-    if (wndPtr->dwStyle & WS_DISABLED) {
-	if (event->type == KeyPress) XBell(display, 0);
-	return;
-    }
-
-
     xkey = LOWORD(keysym);
     key_type = HIBYTE(xkey);
     key = LOBYTE(xkey);
@@ -273,10 +273,6 @@
     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 */
@@ -320,9 +316,9 @@
 #ifdef DEBUG_KEY
 	printf("            wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
 #endif
-	hardware_event( hwnd, ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN, 
+	hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN, 
 		        vkey, keylp.lp2,
-		        event->x_root & 0xffff, event->y_root & 0xffff,
+		        event->x_root - desktopX, event->y_root - desktopY,
 		        event->time, 0 );
 	KeyDown = TRUE;
 
@@ -351,11 +347,10 @@
 #ifdef DEBUG_KEY
 	printf("            wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
 #endif
-	hardware_event( hwnd, 
-		        ((ALTKeyState || vkey == VK_MENU) ? 
+	hardware_event( ((ALTKeyState || vkey == VK_MENU) ? 
 			 WM_SYSKEYUP : WM_KEYUP), 
 		        vkey, keylp.lp2,
-		        event->x_root & 0xffff, event->y_root & 0xffff,
+		        event->x_root - desktopX, event->y_root - desktopY,
 		        event->time, 0 );
 	KeyDown = FALSE;
     }
@@ -365,138 +360,84 @@
 /***********************************************************************
  *           EVENT_MotionNotify
  */
-static void EVENT_MotionNotify( HWND hwnd, XMotionEvent *event )
+static void EVENT_MotionNotify( XMotionEvent *event )
 {
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-
-    if (!wndPtr) return;
-    if (wndPtr->dwStyle & WS_DISABLED) {
-        return;
-    }
-
-
-    hardware_event( hwnd, WM_MOUSEMOVE,
-		    EVENT_XStateToKeyState( event->state ), 0L,
-		    event->x_root & 0xffff, event->y_root & 0xffff,
-		    event->time, 0 );		    
+    hardware_event( WM_MOUSEMOVE, EVENT_XStateToKeyState( event->state ), 0L,
+		    event->x_root - desktopX, event->y_root - desktopY,
+		    event->time, 0 );
 }
 
 
 /***********************************************************************
  *           EVENT_ButtonPress
  */
-static void EVENT_ButtonPress( HWND hwnd, XButtonEvent *event )
+static void EVENT_ButtonPress( XButtonEvent *event )
 {
     static WORD messages[NB_BUTTONS] = 
         { WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN };
     int buttonNum = event->button - 1;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
 
-    if (!wndPtr)  { 
-	printf("couldn't find window\n");
-	return;
-    }
-    if (wndPtr->dwStyle & WS_DISABLED) {
-	XBell(display, 0);
-        return;
-    }
-
-	
-
-    if (buttonNum >= NB_BUTTONS) return;    
+    if (buttonNum >= NB_BUTTONS) return;
+    MouseButtonsStates[buttonNum] = TRUE;
     winHasCursor = event->window;
-    hardware_event( hwnd, messages[buttonNum],
+    hardware_event( messages[buttonNum],
 		    EVENT_XStateToKeyState( event->state ), 0L,
-		    event->x_root & 0xffff, event->y_root & 0xffff,
-		    event->time, 0 );		    
+		    event->x_root - desktopX, event->y_root - desktopY,
+		    event->time, 0 );
 }
 
 
 /***********************************************************************
  *           EVENT_ButtonRelease
  */
-static void EVENT_ButtonRelease( HWND hwnd, XButtonEvent *event )
+static void EVENT_ButtonRelease( XButtonEvent *event )
 {
     static const WORD messages[NB_BUTTONS] = 
         { WM_LBUTTONUP, WM_MBUTTONUP, WM_RBUTTONUP };
     int buttonNum = event->button - 1;
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-
-    if (!wndPtr) return;
-    if (wndPtr->dwStyle & WS_DISABLED) {
-        return;
-    } 
-
 
     if (buttonNum >= NB_BUTTONS) return;    
+    MouseButtonsStates[buttonNum] = FALSE;
     winHasCursor = event->window;
-    hardware_event( hwnd, messages[buttonNum],
+    hardware_event( messages[buttonNum],
 		    EVENT_XStateToKeyState( event->state ), 0L,
-		    event->x_root & 0xffff, event->y_root & 0xffff,
-		    event->time, 0 );		    
-}
-
-
-/**********************************************************************
- *              EVENT_FocusIn
- */
-static void EVENT_FocusIn( HWND hwnd, XFocusChangeEvent *event )
-{
-
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-
-    if (!wndPtr) return;
-    if (wndPtr->dwStyle & WS_DISABLED) {
-	return;
-    }
-
-
-    PostMessage( hwnd, WM_SETFOCUS, hwnd, 0 );
-    hWndFocus = hwnd;
+		    event->x_root - desktopX, event->y_root - desktopY,
+		    event->time, 0 );
 }
 
 
 /**********************************************************************
  *              EVENT_FocusOut
+ *
+ * Note: only top-level override-redirect windows get FocusOut events.
  */
 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
 {
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-    if (!wndPtr) return;
-
+    if (event->detail == NotifyPointer) return;
     if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
-
-    if (wndPtr->dwStyle & WS_DISABLED) {
-	return;
-    }
-
-    if (hWndFocus)
-    {
-	PostMessage( hwnd, WM_KILLFOCUS, hwnd, 0 );
-	hWndFocus = 0;
-    }
+    if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus())) SetFocus( 0 );
 }
 
 
 /**********************************************************************
  *              EVENT_EnterNotify
  */
-static void EVENT_EnterNotify( HWND hwnd, XCrossingEvent *event )
+static void EVENT_EnterNotify( XCrossingEvent *event )
 {
-    WND * wndPtr = WIN_FindWndPtr( hwnd );
-
-    if (!wndPtr) return;
-    if (wndPtr->dwStyle & WS_DISABLED) {
-	return;
-    }
-
     if (captureWnd != 0) return;
     winHasCursor = event->window;
-      /* Simulate a mouse motion to set the correct cursor */
-    hardware_event( hwnd, WM_MOUSEMOVE,
-		    EVENT_XStateToKeyState( event->state ), 0L,
-		    event->x_root & 0xffff, event->y_root & 0xffff,
-		    event->time, 0 );		    
+}
+
+
+/**********************************************************************
+ *              EVENT_ConfigureNotify
+ *
+ * The ConfigureNotify event is only selected on the desktop window.
+ */
+static void EVENT_ConfigureNotify( HWND hwnd, XConfigureEvent *event )
+{
+    desktopX = event->x;
+    desktopY = event->y;
 }
 
 
@@ -529,15 +470,7 @@
  */
 void ReleaseCapture()
 {
-    WND *wnd_p;
-    
-    if (captureWnd == 0)
-	return;
-    
-    wnd_p = WIN_FindWndPtr(captureWnd);
-    if (wnd_p == NULL)
-	return;
-    
+    if (captureWnd == 0) return;
     XUngrabPointer( display, CurrentTime );
     captureWnd = 0;
 }
diff --git a/windows/focus.c b/windows/focus.c
index a3ac280..8850af0 100644
--- a/windows/focus.c
+++ b/windows/focus.c
@@ -2,13 +2,56 @@
  * Focus functions
  *
  * Copyright 1993 David Metcalfe
+ * Copyright 1994 Alexandre Julliard
  */
 
 static char Copyright[] = "Copyright  David Metcalfe, 1993";
+static char Copyright2[] = "Copyright  Alexandre Julliard, 1994";
 
 #include "win.h"
 
-HWND hWndFocus = 0;
+extern Colormap COLOR_WinColormap;
+
+static HWND hWndFocus = 0;
+
+
+/*****************************************************************
+ *               FOCUS_SetXFocus
+ *
+ * Set the X focus.
+ */
+static void FOCUS_SetXFocus( HWND hwnd )
+{
+    WND *wndPtr;
+    XWindowAttributes win_attr;
+
+      /* Only mess with the X focus if there's no desktop window */
+    if (rootWindow != DefaultRootWindow(display)) return;
+
+    if (!hwnd)	/* If setting the focus to 0, uninstall the colormap */
+    {
+	if (COLOR_WinColormap != DefaultColormapOfScreen(screen))
+	    XUninstallColormap( display, COLOR_WinColormap );
+	return;
+    }
+
+      /* Set X focus on the top-level ancestor. */
+	
+      /* Find ancestor */
+    wndPtr = WIN_FindWndPtr( hWndFocus );
+    while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
+	wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
+    if (!wndPtr) return;
+
+      /* Make sure window is viewable */
+    if (!XGetWindowAttributes( display, wndPtr->window, &win_attr ) ||
+	(win_attr.map_state != IsViewable)) return;
+
+      /* Set X focus and install colormap */
+    XSetInputFocus( display, wndPtr->window, RevertToParent, CurrentTime );
+    if (COLOR_WinColormap != DefaultColormapOfScreen(screen))
+	XInstallColormap( display, COLOR_WinColormap );
+}
 
 
 /*****************************************************************
@@ -17,29 +60,44 @@
 
 HWND SetFocus(HWND hwnd)
 {
-    HWND hWndPrevFocus;
+    HWND hWndPrevFocus, hwndParent;
     WND *wndPtr;
 
-    hWndPrevFocus = hWndFocus;
-    hWndFocus = hwnd;
+    if (hwnd == hWndFocus) return hWndFocus;  /* Nothing to do! */    
 
-    if (hwnd == 0)
+    if (hwnd)
     {
-	XSetInputFocus(display, None, RevertToPointerRoot, CurrentTime);
-    }
-    else
-    {
-	XWindowAttributes win_attr;
-	wndPtr = WIN_FindWndPtr(hwnd);
-	
-	if (XGetWindowAttributes( display, wndPtr->window, &win_attr ))
+	  /* Check if we can set the focus to this window */
+
+	hwndParent = hwnd;
+	while ((wndPtr = WIN_FindWndPtr( hwndParent )) != NULL)
 	{
-	    if (win_attr.map_state == IsViewable)
-		XSetInputFocus(display, wndPtr->window,
-			       RevertToParent, CurrentTime);
+	    if ((wndPtr->dwStyle & WS_MINIMIZE) ||
+		(wndPtr->dwStyle & WS_DISABLED)) return 0;
+	    if (!(wndPtr->dwStyle & WS_CHILD)) break;
+	    hwndParent = wndPtr->hwndParent;
+	}
+
+	  /* Now hwndParent is the top-level ancestor. Activate it. */
+
+	if (hwndParent != GetActiveWindow())
+	{
+	    SetWindowPos( hwndParent, HWND_TOP, 0, 0, 0, 0,
+			  SWP_NOSIZE | SWP_NOMOVE );
+	    if (!IsWindow( hwnd )) return 0;  /* Abort if window destroyed */
 	}
     }
 
+      /* Change focus and send messages */
+
+    hWndPrevFocus = hWndFocus;
+    hWndFocus = hwnd;    
+    if (hWndPrevFocus) SendMessage( hWndPrevFocus, WM_KILLFOCUS, hwnd, 0 );
+    if (hwnd == hWndFocus)  /* Maybe already changed during WM_KILLFOCUS */
+    {
+	if (hwnd) SendMessage( hWndFocus, WM_SETFOCUS, hWndPrevFocus, 0 );
+	FOCUS_SetXFocus( hwnd );
+    }
     return hWndPrevFocus;
 }
 
diff --git a/windows/graphics.c b/windows/graphics.c
index b37da40..fb3e580 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -17,6 +17,8 @@
 
 #include "gdi.h"
 
+extern int COLOR_ToPhysical( DC *dc, COLORREF color );
+
 /***********************************************************************
  *           LineTo    (GDI.19)
  */
@@ -351,7 +353,7 @@
 
     x = dc->w.DCOrgX + XLPTODP( dc, x );
     y = dc->w.DCOrgY + YLPTODP( dc, y );
-    pixel = GetNearestPaletteIndex( dc->w.hPalette, color );
+    pixel = COLOR_ToPhysical( dc, color );
     GetPaletteEntries( dc->w.hPalette, pixel, 1, &entry );
     
     XSetForeground( XT_display, dc->u.x.gc, pixel );
diff --git a/windows/keyboard.c b/windows/keyboard.c
index e3afb20..3738a41 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -8,10 +8,21 @@
 
 #include "win.h"
 
+extern BOOL MouseButtonsStates[3];
+
 /**********************************************************************
  *		GetKeyState	(USER.106)
  */
 int GetKeyState(int keycode)
 {
-    return 0;
+	switch(keycode) {
+		case VK_LBUTTON:
+		    return MouseButtonsStates[0];
+		case VK_MBUTTON:
+		    return MouseButtonsStates[1];
+		case VK_RBUTTON:
+		    return MouseButtonsStates[2];
+		default:
+		    return 0;
+		}
 }
diff --git a/windows/mdi.c b/windows/mdi.c
new file mode 100644
index 0000000..1912295
--- /dev/null
+++ b/windows/mdi.c
@@ -0,0 +1,448 @@
+/* MDI.C
+ *
+ * Copyright 1994, Bob Amstadt
+ *
+ * This file contains routines to support MDI features.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include "windows.h"
+#include "win.h"
+#include "mdi.h"
+#include "user.h"
+
+/* #define DEBUG_MDI /* */
+
+/**********************************************************************
+ *					MDIRecreateMenuList
+ */
+void
+MDIRecreateMenuList(MDICLIENTINFO *ci)
+{
+    MDICHILDINFO *chi;
+    char buffer[128];
+    int id, n, index;
+
+#ifdef DEBUG_MDI
+    fprintf(stderr, "MDIRecreateMenuList: hWindowMenu %04.4x\n", 
+	    ci->hWindowMenu);
+#endif
+    
+    id = ci->idFirstChild; 
+    while (DeleteMenu(ci->hWindowMenu, id, MF_BYCOMMAND))
+	id++;
+
+#ifdef DEBUG_MDI
+    fprintf(stderr, "MDIRecreateMenuList: id %04.4x, idFirstChild %04.4x\n", 
+	    id, ci->idFirstChild);
+#endif
+
+    if (!ci->flagMenuAltered)
+    {
+	ci->flagMenuAltered = TRUE;
+	AppendMenu(ci->hWindowMenu, MF_SEPARATOR, 0, NULL);
+    }
+    
+    id = ci->idFirstChild;
+    index = 1;
+    for (chi = ci->infoActiveChildren; chi != NULL; chi = chi->next)
+    {
+	n = sprintf(buffer, "%d ", index++);
+	GetWindowText(chi->hwnd, buffer + n, sizeof(buffer) - n - 1);
+
+#ifdef DEBUG_MDI
+	fprintf(stderr, "MDIRecreateMenuList: id %04.4x, '%s'\n", 
+		id, buffer);
+#endif
+
+	AppendMenu(ci->hWindowMenu, MF_STRING, id++, buffer);
+    }
+}
+
+/**********************************************************************
+ *					MDICreateClient
+ */
+HWND 
+MDICreateClient(WND *w, MDICLIENTINFO *ci, HWND parent, LPMDICREATESTRUCT cs)
+{
+    HWND hwnd;
+
+    /*
+     * Create child window
+     */
+    cs->style &= (WS_MINIMIZE | WS_MAXIMIZE | WS_HSCROLL | WS_VSCROLL);
+    
+    hwnd = CreateWindowEx(0, cs->szClass, cs->szTitle, 
+			  WS_CHILD | WS_BORDER | WS_CAPTION | WS_CLIPSIBLINGS |
+			  WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU |
+			  WS_THICKFRAME | WS_VISIBLE | cs->style,
+			  cs->x, cs->y, cs->cx, cs->cy, parent, (HMENU) 0,
+			  w->hInstance, cs->lParam);
+
+    if (hwnd)
+    {
+	HANDLE h = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(MDICHILDINFO));
+	MDICHILDINFO *child_info = USER_HEAP_ADDR(h);
+	if (!h)
+	{
+	    DestroyWindow(hwnd);
+	    return 0;
+	}
+
+	ci->nActiveChildren++;
+	
+	child_info->next = ci->infoActiveChildren;
+	child_info->prev = NULL;
+	child_info->hwnd = hwnd;
+
+	if (ci->infoActiveChildren)
+	    ci->infoActiveChildren->prev = child_info;
+
+	ci->infoActiveChildren = child_info;
+
+	SendMessage(parent, WM_CHILDACTIVATE, 0, 0);
+    }
+	
+    return hwnd;
+}
+
+/**********************************************************************
+ *					MDIDestroyClient
+ */
+HWND 
+MDIDestroyClient(WND *w_parent, MDICLIENTINFO *ci, HWND parent, HWND child,
+		 BOOL flagDestroy)
+{
+    MDICHILDINFO  *chi;
+    
+    chi = ci->infoActiveChildren;
+    while (chi && chi->hwnd != child)
+	chi = chi->next;
+
+    if (chi)
+    {
+	if (chi->prev)
+	    chi->prev->next = chi->next;
+	if (chi->next)
+	    chi->next->prev = chi->prev;
+	if (ci->infoActiveChildren == chi)
+	    ci->infoActiveChildren = chi->next;
+
+	ci->nActiveChildren--;
+	
+	if (chi->hwnd == ci->hwndActiveChild)
+	    SendMessage(parent, WM_CHILDACTIVATE, 0, 0);
+
+	USER_HEAP_FREE((HANDLE) chi);
+	
+	if (flagDestroy)
+	    DestroyWindow(child);
+    }
+    
+    return 0;
+}
+
+/**********************************************************************
+ *					MDIBringChildToTop
+ */
+void MDIBringChildToTop(HWND parent, WORD id, WORD by_id)
+{
+    MDICHILDINFO  *chi;
+    MDICLIENTINFO *ci;
+    WND           *w;
+    int            i;
+
+    w  = WIN_FindWndPtr(parent);
+    ci = (MDICLIENTINFO *) w->wExtra;
+    
+#ifdef DEBUG_MDI
+    fprintf(stderr, "MDIBringToTop: id %04.4x, by_id %d\n", id, by_id);
+#endif
+
+    if (by_id)
+	id -= ci->idFirstChild;
+    if (!by_id || id < ci->nActiveChildren)
+    {
+	chi = ci->infoActiveChildren;
+
+	if (by_id)
+	{
+	    for (i = 0; i < id; i++)
+		chi = chi->next;
+	}
+	else
+	{
+	    while (chi && chi->hwnd != id)
+		chi = chi->next;
+	}
+
+	if (!chi)
+	    return;
+
+#ifdef DEBUG_MDI
+	fprintf(stderr, "MDIBringToTop: child %04.4x\n", chi->hwnd);
+#endif
+	if (chi != ci->infoActiveChildren)
+	{
+	    SetWindowPos(chi->hwnd, HWND_TOP, 0, 0, 0, 0, 
+			 SWP_NOMOVE | SWP_NOSIZE );
+
+	    if (chi->next)
+		chi->next->prev    = chi->prev;
+
+	    if (chi->prev)
+		chi->prev->next    = chi->next;
+	    
+	    chi->prev              = NULL;
+	    chi->next              = ci->infoActiveChildren;
+	    chi->next->prev        = chi;
+	    ci->infoActiveChildren = chi;
+
+	    SendMessage(parent, WM_CHILDACTIVATE, 0, 0);
+	}
+	
+#ifdef DEBUG_MDI
+	fprintf(stderr, "MDIBringToTop: pos %04.4x, hwnd %04.4x\n", 
+		id, chi->hwnd);
+#endif
+    }
+}
+
+/**********************************************************************
+ *					MDIChildActivated
+ */
+LONG MDIChildActivated(WND *w, MDICLIENTINFO *ci, HWND parent)
+{
+    MDICHILDINFO *chi;
+    HWND          deact_hwnd;
+    HWND          act_hwnd;
+    LONG          lParam;
+
+#ifdef DEBUG_MDI
+    fprintf(stderr, "MDIChildActivate: top %04.4x\n", w->hwndChild);
+#endif
+
+    chi = ci->infoActiveChildren;
+    if (chi)
+    {
+	deact_hwnd = ci->hwndActiveChild;
+	act_hwnd   = chi->hwnd;
+	lParam     = ((LONG) deact_hwnd << 16) | act_hwnd;
+
+#ifdef DEBUG_MDI
+	fprintf(stderr, "MDIChildActivate: deact %04.4x, act %04.4x\n",
+	       deact_hwnd, act_hwnd);
+#endif
+
+	ci->hwndActiveChild = act_hwnd;
+
+	if (deact_hwnd != act_hwnd)
+	{
+	    MDIRecreateMenuList(ci);
+	    SendMessage(deact_hwnd,  WM_NCACTIVATE, FALSE, 0);
+	    SendMessage(deact_hwnd, WM_MDIACTIVATE, FALSE, lParam);
+	}
+	
+	SendMessage(act_hwnd,  WM_NCACTIVATE, TRUE, 0);
+	SendMessage(act_hwnd, WM_MDIACTIVATE, TRUE, lParam);
+    }
+
+    if (chi || ci->nActiveChildren == 0)
+    {
+	MDIRecreateMenuList(ci);
+	DrawMenuBar(GetParent(parent));
+    }
+    
+    return 0;
+}
+
+/**********************************************************************
+ *					MDICascade
+ */
+LONG MDICascade(HWND parent, MDICLIENTINFO *ci)
+{
+    MDICHILDINFO *chi;
+    RECT          rect;
+    int           spacing, xsize, ysize;
+    int		  x, y;
+
+    GetClientRect(parent, &rect);
+    spacing = GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CYFRAME);
+    ysize   = abs(rect.bottom - rect.top) - 8 * spacing;
+    xsize   = abs(rect.right  - rect.left) - 8 * spacing;
+    
+#ifdef DEBUG_MDI
+    fprintf(stderr, 
+	    "MDICascade: Client wnd at (%d,%d) - (%d,%d), spacing %d\n", 
+	    rect.left, rect.top, rect.right, rect.bottom, spacing);
+    fprintf(stderr, "MDICascade: searching for last child\n");
+#endif
+    for (chi = ci->infoActiveChildren; chi->next != NULL; chi = chi->next)
+	;
+    
+#ifdef DEBUG_MDI
+    fprintf(stderr, "MDICascade: last child is %04.4x\n", chi->hwnd);
+#endif
+    x = 0;
+    y = 0;
+    for ( ; chi != NULL; chi = chi->prev)
+    {
+#ifdef DEBUG_MDI
+	fprintf(stderr, "MDICascade: move %04.4x to (%d,%d) size [%d,%d]\n", 
+		chi->hwnd, x, y, xsize, ysize);
+#endif
+	SetWindowPos(chi->hwnd, 0, x, y, xsize, ysize, 
+		     SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
+
+	x += spacing;
+	y += spacing;
+    }
+
+    return 0;
+}
+
+/**********************************************************************
+ *					MDIClientWndProc
+ *
+ * This function is the handler for all MDI requests.
+ */
+LONG 
+MDIClientWndProc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
+{
+    LPCREATESTRUCT       cs;
+    LPCLIENTCREATESTRUCT ccs;
+    MDICLIENTINFO       *ci;
+    WND                 *w;
+    RECT                 rect;
+
+    w  = WIN_FindWndPtr(hwnd);
+    ci = (MDICLIENTINFO *) w->wExtra;
+    
+    switch (message)
+    {
+      case WM_CHILDACTIVATE:
+	return MDIChildActivated(w, ci, hwnd);
+
+      case WM_CREATE:
+	cs                      = (LPCREATESTRUCT) lParam;
+	ccs                     = (LPCLIENTCREATESTRUCT) cs->lpCreateParams;
+	ci->hWindowMenu         = ccs->hWindowMenu;
+	ci->idFirstChild        = ccs->idFirstChild;
+	ci->infoActiveChildren  = NULL;
+	ci->flagMenuAltered     = FALSE;
+	ci->flagChildMaximized  = FALSE;
+	w->dwStyle             |= WS_CLIPCHILDREN;
+
+	GetClientRect(w->hwndParent, &rect);
+	MoveWindow(hwnd, 0, 0, rect.right, rect.bottom, 1);
+
+	return 0;
+
+      case WM_MDIACTIVATE:
+	MDIBringChildToTop(hwnd, wParam, FALSE);
+	return 0;
+
+      case WM_MDICASCADE:
+	return MDICascade(hwnd, ci);
+
+      case WM_MDICREATE:
+	return MDICreateClient(w, ci, hwnd, (LPMDICREATESTRUCT) lParam);
+
+      case WM_MDIDESTROY:
+	return MDIDestroyClient(w, ci, hwnd, wParam, TRUE);
+
+      case WM_MDIGETACTIVE:
+	return ((LONG) ci->hwndActiveChild | 
+		((LONG) ci->flagChildMaximized << 16));
+
+      case WM_MDIICONARRANGE:
+	/* return MDIIconArrange(...) */
+	break;
+	
+      case WM_MDIMAXIMIZE:
+	ci->flagChildMaximized = TRUE;
+	MDIBringChildToTop(hwnd, wParam, FALSE);
+	return 0;
+
+      case WM_NCACTIVATE:
+	SendMessage(ci->hwndActiveChild, message, wParam, lParam);
+	break;
+	
+      case WM_PARENTNOTIFY:
+	if (wParam == WM_DESTROY)
+	    return MDIDestroyClient(w, ci, hwnd, LOWORD(lParam), FALSE);
+	else if (wParam == WM_LBUTTONDOWN)
+	    MDIBringChildToTop(hwnd, ci->hwndHitTest, FALSE);
+	break;
+
+    }
+    
+    return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+/**********************************************************************
+ *					DefFrameProc (USER.445)
+ *
+ */
+LONG 
+DefFrameProc(HWND hwnd, HWND hwndMDIClient, WORD message, 
+	     WORD wParam, LONG lParam)
+{
+    switch (message)
+    {
+      case WM_COMMAND:
+	MDIBringChildToTop(hwndMDIClient, wParam, TRUE);
+	break;
+
+      case WM_NCACTIVATE:
+	SendMessage(hwndMDIClient, message, wParam, lParam);
+	break;
+	
+      case WM_SETFOCUS:
+	SendMessage(hwndMDIClient, WM_SETFOCUS, wParam, lParam);
+	break;
+
+      case WM_SIZE:
+	MoveWindow(hwndMDIClient, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
+	break;
+
+    }
+    
+    return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+/**********************************************************************
+ *					DefMDIChildProc (USER.447)
+ *
+ */
+LONG 
+DefMDIChildProc(HWND hwnd, WORD message, WORD wParam, LONG lParam)
+{
+    MDICLIENTINFO       *ci;
+    WND                 *w;
+
+    w  = WIN_FindWndPtr(GetParent(hwnd));
+    ci = (MDICLIENTINFO *) w->wExtra;
+    
+    switch (message)
+    {
+      case WM_NCHITTEST:
+	ci->hwndHitTest = hwnd;
+	break;
+	
+      case WM_NCPAINT:
+	return NC_DoNCPaint(hwnd, (HRGN)1, 
+			    hwnd == ci->hwndActiveChild);
+    }
+	
+    return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+/**********************************************************************
+ *					TranslateMDISysAccel (USER.451)
+ *
+ */
+BOOL TranslateMDISysAccel(HWND hwndClient, LPMSG msg)
+{
+    return 0;
+}
diff --git a/windows/message.c b/windows/message.c
index 910f7a4..62fd981 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -22,10 +22,13 @@
 
 #define MAX_QUEUE_SIZE   120  /* Max. size of a message queue */
 
-extern BOOL TIMER_CheckTimer( DWORD *next );      /* timer.c */
+extern BOOL TIMER_CheckTimer( LONG *next, MSG *msg,
+			      HWND hwnd, BOOL remove );  /* timer.c */
 extern void EVENT_ProcessEvent( XEvent *event );  /* event.c */
 extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
-  
+extern void WIN_SendParentNotify( HWND hwnd, WORD event,
+				  LONG lParam );  /* win.c */
+
 extern Display * display;
 
   /* System message queue (for hardware events) */
@@ -214,6 +217,11 @@
     LONG hittest_result = SendMessage( msg->hwnd, WM_NCHITTEST, 0,
 				       MAKELONG( msg->pt.x, msg->pt.y ) );
 
+      /* Send the WM_PARENTNOTIFY message */
+
+    if (mouseClick) WIN_SendParentNotify( msg->hwnd, msg->message,
+					  MAKELONG( msg->pt.x, msg->pt.y ) );
+
       /* Activate the window if needed */
 
     if (mouseClick)
@@ -360,20 +368,51 @@
  *           hardware_event
  *
  * Add an event to the system message queue.
- * Note: the position is in screen coordinates.
+ * Note: the position is relative to the desktop window.
  */
-void hardware_event( HWND hwnd, WORD message, WORD wParam, LONG lParam,
-		     WORD xPos, WORD yPos, DWORD time, DWORD extraInfo )
+void hardware_event( WORD message, WORD wParam, LONG lParam,
+		     int xPos, int yPos, DWORD time, DWORD extraInfo )
 {
     MSG msg;
 
-    msg.hwnd    = hwnd;
+    msg.hwnd    = 0;
     msg.message = message;
     msg.wParam  = wParam;
     msg.lParam  = lParam;
     msg.time    = time;
-    msg.pt.x    = xPos;
-    msg.pt.y    = yPos;    
+    msg.pt.x    = xPos & 0xffff;
+    msg.pt.y    = yPos & 0xffff;
+
+      /* Determine the hwnd for this message */
+      /* Maybe this should be done in GetMessage() */
+
+    if ((message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST))
+    {
+	  /* Mouse event */
+	if (GetCapture()) msg.hwnd = GetCapture();
+	else msg.hwnd = WindowFromPoint( msg.pt );
+    }
+    else if ((message >= WM_KEYFIRST) && (message <= WM_KEYLAST))
+    {
+	  /* Keyboard event */
+	msg.hwnd = GetFocus();
+	if (!msg.hwnd && ((message==WM_KEYDOWN) || (message==WM_SYSKEYDOWN)))
+	    MessageBeep(0);  /* Beep on key press if no focus */
+    }
+    if (!msg.hwnd) return;  /* No window for this message */
+
+      /* Merge with previous event if possible */
+
+    if (sysMsgQueue->msgCount && (message == WM_MOUSEMOVE))
+    {
+	MSG *prevMsg = &sysMsgQueue->messages[sysMsgQueue->nextMessage].msg;
+	if ((prevMsg->message == message) && (prevMsg->wParam == wParam))
+	{
+	    *prevMsg = msg;  /* Overwrite previous message */
+	    return;
+	}
+    }
+
     if (!MSG_AddMsg( sysMsgQueue, &msg, extraInfo ))
 	printf( "hardware_event: Queue is full\n" );
 }
@@ -481,13 +520,31 @@
 
 
 /***********************************************************************
+ *           MSG_Synchronize
+ *
+ * Synchronize with the X server. Should not be used too often.
+ */
+void MSG_Synchronize()
+{
+    XEvent event;
+
+    XSync( display, False );
+    while (XPending( display ))
+    {
+	XNextEvent( display, &event );
+	EVENT_ProcessEvent( &event );
+    }    
+}
+
+
+/***********************************************************************
  *           MSG_PeekMessage
  */
 static BOOL MSG_PeekMessage( MESSAGEQUEUE * msgQueue, LPMSG msg, HWND hwnd,
 			     WORD first, WORD last, WORD flags, BOOL peek )
 {
     int pos, mask;
-    DWORD nextExp;  /* Next timer expiration time */
+    LONG nextExp;  /* Next timer expiration time */
     XEvent event;
 
     if (first || last)
@@ -584,8 +641,11 @@
 
 	  /* Finally handle WM_TIMER messages */
 	if ((msgQueue->status & QS_TIMER) && (mask & QS_TIMER))
-	    if (TIMER_CheckTimer( &nextExp ))
-		continue;  /* Restart the whole search */
+	{
+	    if (TIMER_CheckTimer( &nextExp, msg, hwnd, flags & PM_REMOVE ))
+		break;  /* Got a timer msg */
+	}
+	else nextExp = -1;  /* No timeout needed */
 
 	  /* Wait until something happens */
 	if (peek) return FALSE;
@@ -635,7 +695,10 @@
 BOOL PostMessage( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 {
     MSG msg;
-    
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+
+    if (!wndPtr || !wndPtr->hmemTaskQ) return FALSE;
+
     msg.hwnd    = hwnd;
     msg.message = message;
     msg.wParam  = wParam;
@@ -643,7 +706,7 @@
     msg.time    = GetTickCount();
     msg.pt.x    = 0;
     msg.pt.y    = 0;
-    
+
     return MSG_AddMsg( appMsgQueue, &msg, 0 );
 }
 
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 5456b08..9a7f85f 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -522,7 +522,7 @@
  * Paint the non-client area.
  * 'hrgn' is the update rgn to use (in client coords) or 1 if no update rgn.
  */
-static void NC_DoNCPaint( HWND hwnd, HRGN hrgn, BOOL active )
+void NC_DoNCPaint( HWND hwnd, HRGN hrgn, BOOL active )
 {
     HDC hdc;
     RECT rect, rect2;
@@ -648,7 +648,7 @@
  */
 LONG NC_HandleNCPaint( HWND hwnd, HRGN hrgn )
 {
-    NC_DoNCPaint( hwnd, hrgn, (hwnd == GetActiveWindow()) );
+    NC_DoNCPaint( hwnd, hrgn, hwnd == GetActiveWindow() );
     return 0;
 }
 
@@ -884,9 +884,9 @@
 
     if (wndPtr->dwStyle & WS_CHILD) hdc = GetDC( wndPtr->hwndParent );
     else
-    {  /* Grab the server only when moving top-level windows */
+    {  /* Grab the server only when moving top-level windows without desktop */
 	hdc = GetDC( 0 );
-	XGrabServer( display );
+	if (rootWindow == DefaultRootWindow(display)) XGrabServer( display );
     }
     NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
 
@@ -951,7 +951,7 @@
     else
     {
 	ReleaseDC( 0, hdc );
-	XUngrabServer( display );
+	if (rootWindow == DefaultRootWindow(display)) XUngrabServer( display );
     }
     SendMessage( hwnd, WM_EXITSIZEMOVE, 0, 0 );
 
@@ -1018,9 +1018,8 @@
  */
 static void NC_TrackScrollBar( HWND hwnd, WORD wParam, POINT pt )
 {
-    MSG msg;
-    WORD scrollbar;
-
+    MSG 	msg;
+    WORD 	scrollbar;
     if ((wParam & 0xfff0) == SC_HSCROLL)
     {
 	if ((wParam & 0x0f) != HTHSCROLL) return;
@@ -1071,26 +1070,27 @@
 #endif
     ScreenToClient(hwnd, &pt);
     pt.y += lppop->rect.bottom;
-    MenuButtonDown(hwnd, lppop, pt.x, pt.y);
     SetCapture(hwnd);
-    do {
-	if (!GetMessage(&msg, (HWND)NULL, 0, 0)) break;
-	ScreenToClient(hwnd, &msg.pt);
-	msg.pt.y += lppop->rect.bottom;
-	switch(msg.message) {
-	case WM_LBUTTONUP:
-	    MenuButtonUp(hwnd, lppop, msg.pt.x, msg.pt.y);
-	    break;
-	case WM_MOUSEMOVE:
-	    MenuMouseMove(hwnd, lppop, msg.wParam, msg.pt.x, msg.pt.y);
-	    break;
-	default:
-	    TranslateMessage(&msg);
-	    DispatchMessage(&msg);
-	    break;
+    if (!MenuButtonDown(hwnd, lppop, pt.x, pt.y)) {
+	    do {
+		if (!GetMessage(&msg, (HWND)NULL, 0, 0)) break;
+		ScreenToClient(hwnd, &msg.pt);
+		msg.pt.y += lppop->rect.bottom;
+		switch(msg.message) {
+		case WM_LBUTTONUP:
+		    MenuButtonUp(hwnd, lppop, msg.pt.x, msg.pt.y);
+		    break;
+		case WM_MOUSEMOVE:
+		    MenuMouseMove(hwnd, lppop, msg.wParam, msg.pt.x, msg.pt.y);
+		    break;
+		default:
+		    TranslateMessage(&msg);
+		    DispatchMessage(&msg);
+		    break;
+		}
+	    } while (msg.message != WM_LBUTTONUP);
+	    ReleaseCapture();
 	}
-    } while (msg.message != WM_LBUTTONUP);
-    ReleaseCapture();
     GlobalUnlock(wndPtr->wIDmenu);
 }
 
@@ -1216,6 +1216,7 @@
 
     case SC_VSCROLL:
     case SC_HSCROLL:
+    if (wndPtr->dwStyle & WS_CHILD) ClientToScreen(wndPtr->hwndParent, &pt);
 	NC_TrackScrollBar( hwnd, wParam, pt );
 	break;
 
diff --git a/windows/painting.c b/windows/painting.c
index 0090d91..36c72e7 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -25,8 +25,10 @@
     if (!wndPtr) return 0;
 
     hrgnUpdate = wndPtr->hrgnUpdate;  /* Save update region */
-
-    if (!(lps->hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
+    if (!hrgnUpdate)    /* Create an empty region */
+	if (!(hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 ))) return 0;
+    
+    if (!(lps->hdc = GetDCEx( hwnd, hrgnUpdate,
 			      DCX_INTERSECTRGN | DCX_USESTYLE ))) return 0;
     GetRgnBox( InquireVisRgn(lps->hdc), &lps->rcPaint );
 
@@ -37,7 +39,7 @@
     wndPtr->flags &= ~(WIN_NEEDS_BEGINPAINT | WIN_INTERNAL_PAINT);
 
     SendMessage( hwnd, WM_NCPAINT, hrgnUpdate, 0 );
-    if (hrgnUpdate) DeleteObject( hrgnUpdate );
+    DeleteObject( hrgnUpdate );
 
     if (!(wndPtr->flags & WIN_ERASE_UPDATERGN)) lps->fErase = TRUE;
     else lps->fErase = !SendMessage( hwnd, WM_ERASEBKGND, lps->hdc, 0 );
diff --git a/windows/syscolor.c b/windows/syscolor.c
index a3ca9ac..80b69d5 100644
--- a/windows/syscolor.c
+++ b/windows/syscolor.c
@@ -2,62 +2,62 @@
  * Support for system colors
  *
  * Copyright  David W. Metcalfe, 1993
+ * Copyright  Alexandre Julliard, 1994
  *
  */
 
 static char Copyright[] = "Copyright  David W. Metcalfe, 1993";
+static char Copyright2[] = "Copyright  Alexandre Julliard, 1994";
 
 #include <stdlib.h>
-#include <X11/Xlib.h>
 
 #include "windows.h"
-#include "gdi.h"
 
-/* Default system colors - loosely based on Windows default color set */
-static const char *DefSysColors[] =
+
+static char * DefSysColors[] =
 {
-    "gray80",              /* COLOR_SCROLLBAR           */
-    "gray60",              /* COLOR_BACKGROUND          */
-    "blue4",               /* COLOR_ACTIVECAPTION       */
-    "white",               /* COLOR_INACTIVECAPTION     */
-    "white",               /* COLOR_MENU                */
-    "white",               /* COLOR_WINDOW              */
-    "black",               /* COLOR_WINDOWFRAME         */
-    "black",               /* COLOR_MENUTEXT            */
-    "black",               /* COLOR_WINDOWTEXT          */
-    "white",               /* COLOR_CAPTIONTEXT         */
-    "gray40",              /* COLOR_ACTIVEBORDER        */
-    "white",               /* COLOR_INACTIVEBORDER      */
-    "gray60",              /* COLOR_APPWORKSPACE        */
-    "black",               /* COLOR_HIGHLIGHT           */
-    "white",               /* COLOR_HIGHLIGHTTEXT       */
-    "gray70",              /* COLOR_BTNFACE             */
-    "gray30",              /* COLOR_BTNSHADOW           */
-    "gray70",              /* COLOR_GRAYTEXT            */
-    "black",               /* COLOR_BTNTEXT             */
-    "black",               /* COLOR_INACTIVECAPTIONTEXT */
-    "white",               /* COLOR_BTNHIGHLIGHT        */
+    "Scrollbar", "224 224 224",      /* COLOR_SCROLLBAR           */
+    "Background", "192 192 192",     /* COLOR_BACKGROUND          */
+    "ActiveTitle", "0 64 128",       /* COLOR_ACTIVECAPTION       */
+    "InactiveTitle", "255 255 255",  /* COLOR_INACTIVECAPTION     */
+    "Menu", "0 255 255",             /* COLOR_MENU                */
+    "Window", "255 255 255",         /* COLOR_WINDOW              */
+    "WindowFrame", "0 0 0",          /* COLOR_WINDOWFRAME         */
+    "MenuText", "0 0 0",             /* COLOR_MENUTEXT            */
+    "WindowText", "0 0 0",           /* COLOR_WINDOWTEXT          */
+    "TitleText", "255 255 255",      /* COLOR_CAPTIONTEXT         */
+    "ActiveBorder", "128 128 128",   /* COLOR_ACTIVEBORDER        */
+    "InactiveBorder", "255 255 255", /* COLOR_INACTIVEBORDER      */
+    "AppWorkspace", "255 255 232",   /* COLOR_APPWORKSPACE        */
+    "Hilight", "166 202 240",        /* COLOR_HIGHLIGHT           */
+    "HilightText", "0 0 0",          /* COLOR_HIGHLIGHTTEXT       */
+    "ButtonFace", "192 192 192",     /* COLOR_BTNFACE             */
+    "ButtonShadow", "128 128 128",   /* COLOR_BTNSHADOW           */
+    "GrayText", "192 192 192",       /* COLOR_GRAYTEXT            */
+    "ButtonText", "0 0 0",           /* COLOR_BTNTEXT             */
+    "InactiveTitleText", "0 0 0",    /* COLOR_INACTIVECAPTIONTEXT */
+    "ButtonHilight", "255 255 255"   /* COLOR_BTNHIGHLIGHT        */
 };
 
-#define NUM_SYS_COLORS     (sizeof(DefSysColors) / sizeof(DefSysColors[0]))
+#define NUM_SYS_COLORS     (COLOR_BTNHIGHLIGHT+1)
 
 static COLORREF SysColors[NUM_SYS_COLORS];
 
-extern Colormap COLOR_WinColormap;
 
-
+/*************************************************************************
+ *             SYSCOLOR_Init
+ */
 void SYSCOLOR_Init()
 {
-    XColor color;
-    int i;
+    int i, r, g, b;
+    char **p;
+    char buffer[100];
 
-    for (i = 0; i < NUM_SYS_COLORS; i++)
+    for (i = 0, p = DefSysColors; i < NUM_SYS_COLORS; i++, p += 2)
     {
-	if (XParseColor(XT_display, COLOR_WinColormap, DefSysColors[i], &color))
-	{
-	    SysColors[i] = RGB(color.red >> 8, color.green >> 8,
-			       color.blue >> 8);
-	}
+	GetProfileString( "colors", p[0], p[1], buffer, 100 );
+	if (!sscanf( buffer, " %d %d %d", &r, &g, &b )) r = g = b = 0;
+	SysColors[i] = RGB( r, g, b );
     }
 }
 
diff --git a/windows/sysmetrics.c b/windows/sysmetrics.c
index bea4561..71413c7 100644
--- a/windows/sysmetrics.c
+++ b/windows/sysmetrics.c
@@ -14,6 +14,7 @@
 short sysMetrics[SM_CMETRICS];
 
 extern Display * display;
+extern int screenWidth, screenHeight;
 
 /***********************************************************************
  *           SYSMETRICS_Init
@@ -22,8 +23,8 @@
  */
 void SYSMETRICS_Init()
 {
-    sysMetrics[SM_CXSCREEN] = DisplayWidth( display, DefaultScreen(display) );
-    sysMetrics[SM_CYSCREEN] = DisplayHeight( display, DefaultScreen(display) );
+    sysMetrics[SM_CXSCREEN] = screenWidth;
+    sysMetrics[SM_CYSCREEN] = screenHeight;
     sysMetrics[SM_CXVSCROLL] = SYSMETRICS_CXVSCROLL;
     sysMetrics[SM_CYHSCROLL] = SYSMETRICS_CYHSCROLL;
     sysMetrics[SM_CYCAPTION] = SYSMETRICS_CYCAPTION;
diff --git a/windows/timer.c b/windows/timer.c
index 2a40bec..641bbe0 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -28,6 +28,10 @@
 
 static TIMER * pNextTimer = NULL;  /* Next timer to expire */
 
+  /* Duration from 'time' until expiration of the timer */
+#define EXPIRE_TIME(pTimer,time) \
+          (((pTimer)->expires <= (time)) ? 0 : (pTimer)->expires - (time))
+
 
 /***********************************************************************
  *           TIMER_InsertTimer
@@ -46,7 +50,7 @@
         TIMER * ptr = pNextTimer;	
 	while (ptr->next && (pTimer->expires >= ptr->next->expires))
 	    ptr = ptr->next;
-	pTimer->next = ptr;
+	pTimer->next = ptr->next;
 	ptr->next = pTimer;
     }
 }
@@ -71,42 +75,50 @@
 
 
 /***********************************************************************
- *           TIMER_NextExpire
+ *           TIMER_RestartTimers
  *
- * Return time until next timer expiration (-1 if none).
+ * Restart an expired timer.
  */
-static DWORD TIMER_NextExpire( DWORD curTime )
+static void TIMER_RestartTimer( TIMER * pTimer, DWORD curTime )
 {
-    if (!pNextTimer) return -1;
-    if (pNextTimer->expires <= curTime) return 0;
-    return pNextTimer->expires - curTime;
+    TIMER_RemoveTimer( pTimer );
+    pTimer->expires = curTime + pTimer->timeout;
+    TIMER_InsertTimer( pTimer );
 }
 
-
+			       
 /***********************************************************************
  *           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'.
+ * Check whether a timer has expired, and create a message if necessary.
+ * Otherwise, return time until next timer expiration in 'next'.
+ * If 'hwnd' is not NULL, only consider timers for this window.
+ * If 'remove' is TRUE, remove all expired timers up to the returned one.
  */
-BOOL TIMER_CheckTimer( DWORD *next )
+BOOL TIMER_CheckTimer( LONG *next, MSG *msg, HWND hwnd, BOOL remove )
 {
     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 (hwnd)  /* Find first timer for this window */
+	while (pTimer && (pTimer->hwnd != hwnd)) pTimer = pTimer->next;
 
-      /* If timeout == 0, the timer has been removed by KillTimer */
-    if (pTimer->timeout)
+    if (!pTimer) *next = -1;
+    else *next = EXPIRE_TIME( pTimer, curTime );
+    if (*next != 0) return FALSE;  /* No timer expired */
+
+    if (remove)	/* Restart all timers before pTimer, and then pTimer itself */
     {
-	  /* Restart the timer */
-	pTimer->expires = curTime + pTimer->timeout;
-	TIMER_InsertTimer( pTimer );
+	while (pNextTimer != pTimer) TIMER_RestartTimer( pNextTimer, curTime );
+	TIMER_RestartTimer( pTimer, curTime );
     }
-    *next = TIMER_NextExpire( curTime );
+
+      /* Build the message */
+    msg->hwnd    = pTimer->hwnd;
+    msg->message = pTimer->msg;
+    msg->wParam  = pTimer->id;
+    msg->lParam  = (LONG)pTimer->proc;
+    msg->time    = curTime;
     return TRUE;
 }
 
diff --git a/windows/win.c b/windows/win.c
index 45157f9..cfc8e85 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -6,6 +6,8 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
+#include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 
 #include "class.h"
@@ -19,7 +21,11 @@
 
 extern void EVENT_RegisterWindow( Window w, HWND hwnd );  /* event.c */
 extern void CURSOR_SetWinCursor( HWND hwnd, HCURSOR hcursor );  /* cursor.c */
+extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
 extern HMENU CopySysMenu(); /* menu.c */
+extern LONG MDIClientWndProc(HWND hwnd, WORD message, 
+			     WORD wParam, LONG lParam); /* mdi.c */
+
 
 static HWND hwndDesktop = 0;
 
@@ -109,7 +115,8 @@
 HWND WIN_FindWinToRepaint( HWND hwnd )
 {
     WND * wndPtr;
-    
+
+      /* Note: the desktop window never gets WM_PAINT messages */
     if (!hwnd) hwnd = GetTopWindow( hwndDesktop );
     for ( ; hwnd != 0; hwnd = wndPtr->hwndNext )
     {
@@ -133,15 +140,15 @@
  * Send a WM_PARENTNOTIFY to all ancestors of the given window, unless
  * the window has the WS_EX_NOPARENTNOTIFY style.
  */
-static void WIN_SendParentNotify( HWND hwnd, WND * wndPtr, WORD event )
+void WIN_SendParentNotify( HWND hwnd, WORD event, LONG lParam )
 {
     HWND current = GetParent( hwnd );
-
-    if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) return;
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    
+    if (!wndPtr || (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY)) return;
     while (current)
     {
-	SendMessage( current, WM_PARENTNOTIFY, 
-		     event, MAKELONG( hwnd, wndPtr->wIDmenu ) );
+	SendMessage( current, WM_PARENTNOTIFY, event, lParam );
 	current = GetParent( current );
     }
 }
@@ -152,19 +159,19 @@
  *
  * Create the desktop window.
  */
-static HWND WIN_CreateDesktopWindow()
+BOOL WIN_CreateDesktopWindow()
 {
-    HWND hwnd;
     WND *wndPtr;
     HCLASS hclass;
     CLASS *classPtr;
 
     if (!(hclass = CLASS_FindClassByName( DESKTOP_CLASS_NAME, &classPtr )))
-	return 0;
+	return FALSE;
 
-    hwnd = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(WND)+classPtr->wc.cbWndExtra);
-    if (!hwnd) return 0;
-    wndPtr = (WND *) USER_HEAP_ADDR( hwnd );
+    hwndDesktop = USER_HEAP_ALLOC( GMEM_MOVEABLE,
+				   sizeof(WND)+classPtr->wc.cbWndExtra );
+    if (!hwndDesktop) return FALSE;
+    wndPtr = (WND *) USER_HEAP_ADDR( hwndDesktop );
 
     wndPtr->hwndNext          = 0;
     wndPtr->hwndChild         = 0;
@@ -187,7 +194,7 @@
     wndPtr->hrgnUpdate        = 0;
     wndPtr->hwndLastActive    = 0;
     wndPtr->lpfnWndProc       = classPtr->wc.lpfnWndProc;
-    wndPtr->dwStyle           = WS_VISIBLE | WS_CLIPCHILDREN;
+    wndPtr->dwStyle           = WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
     wndPtr->dwExStyle         = 0;
     wndPtr->hdce              = 0;
     wndPtr->hmenuSystem       = 0;
@@ -196,9 +203,15 @@
     wndPtr->wIDmenu           = 0;
     wndPtr->hText             = 0;
     wndPtr->flags             = 0;
-    wndPtr->window            = DefaultRootWindow( display );
+    wndPtr->window            = rootWindow;
     wndPtr->hSysMenu          = 0;
-    return hwnd;
+
+      /* Send dummy WM_NCCREATE message */
+    SendMessage( hwndDesktop, WM_NCCREATE, 0, 0 );
+    EVENT_RegisterWindow( wndPtr->window, hwndDesktop );
+    RedrawWindow( hwndDesktop, NULL, 0,
+		  RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW );
+    return TRUE;
 }
 
 
@@ -228,18 +241,12 @@
     HANDLE hcreateStruct;
     int wmcreate;
     XSetWindowAttributes win_attr;
-    Window parentWindow;
-    int x_rel, y_rel;
 
 #ifdef DEBUG_WIN
     printf( "CreateWindowEx: %d '%s' '%s' %d,%d %dx%d %08x %x\n",
 	   exStyle, className, windowName, x, y, width, height, style, parent);
 #endif
 
-      /* Before anything, create the desktop window */
-    if (!hwndDesktop)
-	if (!(hwndDesktop = WIN_CreateDesktopWindow())) return 0;
-
     if (x == CW_USEDEFAULT) x = y = 0;
     if (width == CW_USEDEFAULT)
     {
@@ -257,7 +264,7 @@
 	if (!(parentPtr = WIN_FindWndPtr( parent ))) return 0;
     }
     else if (style & WS_CHILD) return 0;  /* WS_CHILD needs a parent */
-    
+
     if (!(class = CLASS_FindClassByName( className, &classPtr ))) {
 	printf("CreateWindow BAD CLASSNAME '%s' !\n", className);
 	return 0;
@@ -345,30 +352,25 @@
 
     win_attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
 	                 PointerMotionMask | ButtonPressMask |
-			 ButtonReleaseMask | FocusChangeMask | EnterWindowMask;
-    win_attr.override_redirect = True;
-    win_attr.colormap = COLOR_WinColormap;
-    if (style & WS_CHILD)
+			 ButtonReleaseMask | EnterWindowMask;
+    win_attr.override_redirect = (rootWindow == DefaultRootWindow(display));
+    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;
+	parentPtr = WIN_FindWndPtr( hwndDesktop );
+	  /* Only select focus events on top-level override-redirect windows */
+	if (win_attr.override_redirect) win_attr.event_mask |= FocusChangeMask;
     }
-    else
-    {
-	parentWindow = DefaultRootWindow( display );
-	x_rel = x;
-	y_rel = y;
-    }
-    wndPtr->window = XCreateWindow(display, parentWindow,
-				   x_rel, y_rel, width, height, 0,
-				   CopyFromParent, InputOutput, CopyFromParent,
-				   CWEventMask | CWOverrideRedirect |
-				   CWColormap, &win_attr );
+    wndPtr->window = XCreateWindow( display, parentPtr->window,
+		   x + parentPtr->rectClient.left - parentPtr->rectWindow.left,
+		   y + parentPtr->rectClient.top - parentPtr->rectWindow.top,
+		   width, height, 0,
+		   CopyFromParent, InputOutput, CopyFromParent,
+		   CWEventMask | CWOverrideRedirect | CWColormap, &win_attr );
     XStoreName( display, wndPtr->window, windowName );
 
       /* Send the WM_CREATE message */
-	
+
     hcreateStruct = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(CREATESTRUCT) );
     createStruct = (CREATESTRUCT *) USER_HEAP_ADDR( hcreateStruct );
     createStruct->lpCreateParams = data;
@@ -427,12 +429,13 @@
 
     EVENT_RegisterWindow( wndPtr->window, hwnd );
 
-    WIN_SendParentNotify( hwnd, wndPtr, WM_CREATE );
+    WIN_SendParentNotify( hwnd, WM_CREATE, MAKELONG( hwnd, wndPtr->wIDmenu ) );
     
     if (style & WS_VISIBLE) ShowWindow( hwnd, SW_SHOW );
     return hwnd;
 }
 
+
 /***********************************************************************
  *           DestroyWindow   (USER.53)
  */
@@ -443,9 +446,12 @@
     
       /* Initialisation */
 
+    if (hwnd == hwndDesktop) return FALSE;  /* Can't destroy desktop */
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
     if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) return FALSE;
-    WIN_SendParentNotify( hwnd, wndPtr, WM_DESTROY );
+    if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
+    if (hwnd == GetFocus()) SetFocus( 0 );
+    WIN_SendParentNotify( hwnd, WM_DESTROY, MAKELONG(hwnd, wndPtr->wIDmenu) );
 
       /* Send destroy messages and destroy children */
 
@@ -501,7 +507,34 @@
  */
 HWND FindWindow(LPSTR ClassMatch, LPSTR TitleMatch)
 {
-    return((HWND)NULL);
+    HCLASS hclass;
+    CLASS *classPtr;
+    HWND hwnd;
+
+    if (ClassMatch)
+    {
+	hclass = CLASS_FindClassByName( ClassMatch, &classPtr );
+	if (!hclass) return 0;
+    }
+    else hclass = 0;
+
+    hwnd = GetTopWindow( hwndDesktop );
+    while(hwnd)
+    {
+	WND *wndPtr = WIN_FindWndPtr( hwnd );
+	if (!hclass || (wndPtr->hClass == hclass))
+	{
+	      /* Found matching class */
+	    if (!TitleMatch) return hwnd;
+	    if (wndPtr->hText)
+	    {
+		char *textPtr = (char *) USER_HEAP_ADDR( wndPtr->hText );
+		if (!strcmp( textPtr, TitleMatch )) return hwnd;
+	    }
+	}
+	hwnd = wndPtr->hwndNext;
+    }
+    return 0;
 }
  
  
@@ -514,6 +547,47 @@
 }
 
 
+/*******************************************************************
+ *           EnableWindow   (USER.34)
+ */
+BOOL EnableWindow( HWND hwnd, BOOL enable )
+{
+    WND *wndPtr;
+
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
+    if (enable && (wndPtr->dwStyle & WS_DISABLED))
+    {
+	  /* Enable window */
+	wndPtr->dwStyle &= ~WS_DISABLED;
+	SendMessage( hwnd, WM_ENABLE, TRUE, 0 );
+	return TRUE;
+    }
+    else if (!enable && !(wndPtr->dwStyle & WS_DISABLED))
+    {
+	  /* Disable window */
+	wndPtr->dwStyle |= WS_DISABLED;
+	if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus() ))
+	    SetFocus( 0 );  /* A disabled window can't have the focus */
+	if ((hwnd == GetCapture()) || IsChild( hwnd, GetCapture() ))
+	    ReleaseCapture();  /* A disabled window can't capture the mouse */
+	SendMessage( hwnd, WM_ENABLE, FALSE, 0 );
+	return FALSE;
+    }
+    return ((wndPtr->dwStyle & WS_DISABLED) != 0);
+}
+
+
+/***********************************************************************
+ *           IsWindowEnabled   (USER.35)
+ */ 
+BOOL IsWindowEnabled(HWND hWnd)
+{
+    WND * wndPtr; 
+
+    if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
+    return !(wndPtr->dwStyle & WS_DISABLED);
+}
+
 
 /**********************************************************************
  *	     GetWindowWord    (USER.133)
@@ -554,86 +628,6 @@
 }
 
 
-
-/*******************************************************************
- *    WIN_SetSensitive
- * 
- *      sets hWnd and all children to the same sensitivity
- * 
- *      sets hWnd sensitive and then calls SetSensitive on hWnd's child
- *      and all of hWnd's child's Next windows 
- */
-static BOOL WIN_SetSensitive(HWND hWnd, BOOL fEnable)
-{
-    WND *wndPtr;
-    HWND hwnd;
-
-    printf("in SetSenitive\n");
-
-    if (!hWnd) return 0;
-    if (!(wndPtr = WIN_FindWndPtr(hWnd))) return 0;
-
-	
-    if (fEnable) {
-        wndPtr->dwStyle &= ~WS_DISABLED;
-     } else {
-        wndPtr->dwStyle |= WS_DISABLED;
-     }
-  
-    hwnd=wndPtr->hwndChild;
-    while (hwnd) {					/* mk next child sens */
-        WIN_SetSensitive(hwnd, fEnable); 
-        if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) return 0;
-	hwnd=wndPtr->hwndNext;
-    }
-    return 1;
-
-}
-
-/*******************************************************************
- *           EnableWindow   (USER.34)
- * 
- *
- */
-
-BOOL EnableWindow(HWND hWnd, BOOL fEnable)
-{
-    WND *wndPtr;
-    int eprev;
-   
-    if (hWnd == 0) return 0;
-    
-    wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr == 0) return 0;
-
-    eprev = ! (wndPtr->dwStyle & WS_DISABLED);
-
-    if (fEnable != eprev) {                        /* change req */
-        printf("changing window\n");
-        WIN_SetSensitive(hWnd, fEnable); 
-        SendMessage(hWnd, WM_ENABLE, (WORD)fEnable, 0);  
-    }
-    return !eprev;
-}
-
-/***********************************************************************
- *           IsWindowEnabled   (USER.35)
- */
- 
-BOOL IsWindowEnabled(HWND hWnd)
-{
-    WND * wndPtr; 
-
-    if (hWnd == 0) return 0;
-    wndPtr = WIN_FindWndPtr(hWnd);
-    if (wndPtr == 0) return 0;
-
-    return !(wndPtr->dwStyle & WS_DISABLED);
-}
-
-
-
-
 /**********************************************************************
  *	     GetWindowLong    (USER.135)
  */
diff --git a/windows/winpos.c b/windows/winpos.c
index ee37ecb..0534bc8 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -9,8 +9,7 @@
 #include "sysmetrics.h"
 #include "user.h"
 #include "win.h"
-
-extern Display * display;
+#include "message.h"
 
 static HWND hwndActive = 0;  /* Currently active window */
 
@@ -68,15 +67,32 @@
  */
 HWND WindowFromPoint( POINT pt )
 {
-    RECT rect;
-    HWND hwnd = GetTopWindow( GetDesktopWindow() );
-    while (hwnd)
+    HWND hwndRet = 0;
+    HWND hwnd = GetDesktopWindow();
+
+    while(hwnd)
     {
-	GetWindowRect( hwnd, &rect );
-	if (PtInRect( &rect, pt )) return hwnd;
-	hwnd = GetWindow( hwnd, GW_HWNDNEXT );
+	  /* If point is in window, and window is visible,   */
+	  /* not disabled and not transparent, then explore  */
+	  /* its children. Otherwise, go to the next window. */
+
+	WND *wndPtr = WIN_FindWndPtr( hwnd );
+	if ((pt.x >= wndPtr->rectWindow.left) &&
+	    (pt.x < wndPtr->rectWindow.right) &&
+	    (pt.y >= wndPtr->rectWindow.top) &&
+	    (pt.y < wndPtr->rectWindow.bottom) &&
+	    !(wndPtr->dwStyle & WS_DISABLED) &&
+	    (wndPtr->dwStyle & WS_VISIBLE) &&
+	    !(wndPtr->dwExStyle & WS_EX_TRANSPARENT))
+	{
+	    pt.x -= wndPtr->rectClient.left;
+	    pt.y -= wndPtr->rectClient.top;
+	    hwndRet = hwnd;
+	    hwnd = wndPtr->hwndChild;
+	}
+	else hwnd = wndPtr->hwndNext;
     }
-    return 0;
+    return hwndRet;
 }
 
 
@@ -97,7 +113,7 @@
 	if (PtInRect( &rect, pt )) return hwnd;
 	hwnd = GetWindow( hwnd, GW_HWNDNEXT );
     }
-    return 0;
+    return hwndParent;
 }
 
 
@@ -168,7 +184,6 @@
     return hwndActive;
 }
 
-
 /*******************************************************************
  *         SetActiveWindow    (USER.59)
  */
@@ -461,6 +476,20 @@
     winPos->cy = cy;
     winPos->flags = flags;
     SendMessage( hwnd, WM_WINDOWPOSCHANGING, 0, (LONG)winPos );
+    hwndInsertAfter = winPos->hwndInsertAfter;
+
+      /* Some sanity checks */
+
+    if (!IsWindow( hwnd ) || (hwnd == GetDesktopWindow())) goto Abort;
+    if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW))
+	flags |= SWP_NOMOVE | SWP_NOSIZE;
+    if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
+    {
+	if (hwnd != hwndActive) hwndInsertAfter = HWND_TOP;
+	else if ((hwndInsertAfter == HWND_TOPMOST) ||
+		 (hwndInsertAfter == HWND_NOTOPMOST))
+	    hwndInsertAfter = HWND_TOP;	
+    }
 
       /* Calculate new position and size */
 
@@ -485,8 +514,6 @@
 
     if (!(winPos->flags & SWP_NOZORDER))
     {
-	hwndInsertAfter = winPos->hwndInsertAfter;
-
 	  /* TOPMOST not supported yet */
 	if ((hwndInsertAfter == HWND_TOPMOST) ||
 	    (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
@@ -571,6 +598,12 @@
     {
 	wndPtr->dwStyle |= WS_VISIBLE;
 	XMapWindow( display, wndPtr->window );
+	MSG_Synchronize();
+	if (!(winPos->flags & SWP_NOREDRAW))
+	    RedrawWindow( hwnd, NULL, 0, RDW_INVALIDATE | RDW_ERASE |
+			  RDW_ERASENOW | RDW_FRAME );
+	else RedrawWindow( hwnd, NULL, 0, RDW_VALIDATE );
+	
     }
     else if (winPos->flags & SWP_HIDEWINDOW)
     {
diff --git a/wine.ini b/wine.ini
index d8755c4..b2c79af 100644
--- a/wine.ini
+++ b/wine.ini
@@ -2,7 +2,7 @@
 A=/mnt/fd0
 C=/dos
 D=/usr/windows
-E=/home/bob/Wine/work
+E=/home/bob/wine/work
 F=/home/bob/test
 
 [wine]
@@ -11,7 +11,6 @@
 Temp=c:\temp
 Path=c:\windows;c:\windows\system;e:\;e:\test;f:\
 SystemResources=sysres.dll
-; SystemResources=
 
 [serialports]
 Com1=/dev/cua0
@@ -21,12 +20,14 @@
 Lpt1=/dev/lp0
 
 [spy]
-;;;;; Uncomment the following line to activate spying to the console ;;;;;
-File=CON
+;;;;; Uncomment the following line to activate spying to the console     ;;;;;
+;File=CON
 
-;;;;; Uncomment the following line to activate spying to the spy.log ;;;;;
+;;;;; Uncomment the following line to activate spying to the spy.log     ;;;;;
 ;File=spy.log
 
-;;;;; The following options are not supported yet                    ;;;;;
-;Include=
-;Exclude=
+;;;;; List of ; separated (and terminated) msg names to exclude from log ;;;;;
+Exclude=WM_TIMER;WM_SETCURSOR;WM_MOUSEMOVE;
+
+;;;;; List of ; separated (and terminated) msg names to include in log   ;;;;;
+;Include=WM_COMMAND;