Release 970112

Sat Jan 11 18:17:59 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/menu.c]
	Updated to new Win32 types.

	* [controls/listbox.c]
	Fixed Winfile extended selection bug.

	* [files/directory.c]
	Changed DIR_SearchPath to return both long and short file names.

	* [files/dos_fs.c]
	Implemented VFAT ioctl to retrieve the original short filenames
	from a VFAT filesystem (Linux only for now).
	Replaced DOSFS_GetUnixFileName()/DOSFS_GetDosTrueName() by
	DOS_GetFullName().
	Properly implemented GetShortPathName() and GetFullPathName().
	Made all functions re-entrant.

	* [files/file.c] [misc/main.c]
	Replaced -allowreadonly option by -failreadonly. The default is
	now to report success when opening a read-only file for writing.

	* [objects/metafile.c]
	Fixed bug in DIB bitmaps pointer calculation.

	* [scheduler/process.c]
	Implemented environment strings and Get/SetStdHandle with process
 	environment block.

	* [tools/build.c]
	Rewrote BuildContext32() to avoid instructions that may not be
	supported by all assemblers.
	
Fri Jan 10 17:11:09 1997  David Faure  <david.faure@ifhamy.insa-lyon.fr>

	* [windows/event.c]
	Created table keyc2vkey, which associate a vkey(+extended bit) to
	any keycode. Changed EVENT_event_to_vkey to use this table to
	return the correct vkey. Changed EVENT_ToAscii to get the keycode
	from this table too.  Assigned OEM specific vkeys arbitrarily.

Fri Jan 10 09:26:17 1997  John Harvey <john@division.co.uk>

	* [misc/winsock.c] [misc/winsoc_async.c]
        Fixed svr4 header files.
        Changed bzero() to memset().

	* [tools/fnt2bdf.c]
        Removed bcopy() and used memcpy() instead.

	* [debugger/msc.c]
        Include string.h instead of strings.h

	* [debugger/stabs.c]
        Include string.h instead of strings.h.
        Define __ELF__ for svr4 systems.

	* [loader/signal.c]
        Use wait() instead of wait4() which doesnt exist on Unixware.

	* [memory/global.c]
        Use sysconf() instead of getpagesize() for svr4 systems.

Thu Jan  9 21:07:20 1997  Robert Pouliot <krynos@clic.net>

	* [Make.rules.in] [Makefile.in] [make_os2.sh] [rc/Makefile.in]
	  [tools/Makefile.in] [documentation/wine_os2.txt]
	Patches for OS/2 support. Note that it doesn't compile yet.

Tue Jan  7 20:03:53 1997  Eric Youngdale <eric@sub2304.jic.com>

	* [debugger/*]
	Many more debugger improvements (see debugger/README for details).

Tue Jan  7 15:12:21 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [windows/graphics.c] [objects/text.c] [graphics/x11drv/*]
	  [graphics/metafiledrv/*]
	Moved some device dependent code into the resp. subdirs.

	* [include/gdi.h] [include/metafiledrv.h] [include/x11drv.h]
	Prototypes added,
	DC_FUNCTIONS: GetPixel added, some unnecessary functions removed.

	* [objects/region.c]
	CreatePolyPolygonRgn32 added.

	* [files/dos_fs.c]
	QueryDosDevice added.

	* [misc/lstr.c]
	FormatMessage: broken heap management fixed.

	* [scheduler/process.c] [scheduler/thread.c]
	Get/SetThreadPriority/PriorityClass added.

Mon Jan  6 21:55:30 1997  Philippe De Muyter  <phdm@info.ucl.ac.be>

	* [misc/keyboard.c]
	ToAscii : Use EVENT_ToAscii instead.

	* [windows/event.c]
	keypad_key : Do not convert XK_Mode_switch to VK_MENU; recognize
	keypad cursor keys.
	EVENT_event_to_vkey : New function, to transform a X keycode
	into a MSwin vkey + extended bit.
	EVENT_ToAscii : New function, to transform a vkey + extended bit
	(+ key state table) into ascii char(s), using XLookupString, and
	recognizing dead chars.
	EVENT_key : Transform AltGr into Ctrl+Alt sequence; call
	EVENT_event_to_vkey for keycode to vkey conversion; fixed
	previous, context and extended bits.

	* [windows/keyboard.c]
	Include stddebug.h, to get -debugmsg messages.
	GetKeyState : Handle VK_MBUTTON case.
	GetKeyboardState, SetKeyboardState : Debugging messages added.

	* [windows/message.c]
	TranslateMessage : Handle dead chars.

Mon Jan  6 20:10:11 1997  Dominik Strasser  <bm424953@muenchen.org>

	* [if1632/crtdll.spec] [misc/crtdll.c]
	C++ functions new/delete/set_new_handler implemented.

Mon Jan  6 15:48:15 1997 Frans van Dorsselaer <dorssel@rulhmpc49.LeidenUniv.nl>

	* [controls/edit.c] [include/windows.h]
	Moved the edit control to 32 bits.
	Included new (win95) message definitions in windows.h
	Implemented EM_SCROLLCARET, EM_SETMARGINS, EM_GETMARGINS,
	EM_GETLIMITTEXT, EM_POSFROMCHAR, EM_CHARFROMPOS.
	Broke EM_SETWORDBREAKPROC (internal wordwrap still works).
	Fixed some bugs, introduced a couple of others.
	Text buffer is now initially in 32-bit heap.

	* [controls/EDIT.TODO] [controls/combo.c] [controls/widgets.c]
	  [if1632/wprocs.spec] [library/miscstubs.c] [windows/defdlg.c]
	  [misc/commdlg.c]
	Updated to work with 32-bit edit control.

Sat Jan  4 22:07:27 1997  O.Flebbe  <O.Flebbe@science-computing.uni-tuebingen.de>

	* [loader/pe_image.c]
	Use mmap rather then malloc. Better workaround for clean
	segments.
diff --git a/ANNOUNCE b/ANNOUNCE
index 13b5bb4..669aa02 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,13 +1,15 @@
-This is release 970101 of Wine, the MS Windows emulator.  This is still a
+This is release 970112 of Wine, the MS Windows emulator.  This is still a
 developer's only release.  There are many bugs and many unimplemented API
 features.  Most applications still do not work correctly.
 
 Patches should be submitted to "julliard@lrc.epfl.ch".  Please don't
 forget to include a ChangeLog entry.
 
-WHAT'S NEW with Wine-970101: (see ChangeLog for details)
-	- Win32 handle management and related stuff.
-	- Several files moved around, new directories created.
+WHAT'S NEW with Wine-970112: (see ChangeLog for details)
+	- Better support for non-US keyboards.
+	- Support for VFAT filesystem short names.
+	- Many improvements to the built-in debugger.
+	- More Win32 stuff.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -16,10 +18,10 @@
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-970101.tar.gz
-  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-970101.tar.gz
-  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-970101.tar.gz
-  ftp://aris.com/pub/linux/ALPHA/Wine/development/Wine-970101.tar.gz
+  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-970112.tar.gz
+  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-970112.tar.gz
+  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-970112.tar.gz
+  ftp://aris.com/pub/linux/ALPHA/Wine/development/Wine-970112.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index f98f01d..bf0c55d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,154 @@
 ----------------------------------------------------------------------
+Sat Jan 11 18:17:59 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [controls/menu.c]
+	Updated to new Win32 types.
+
+	* [controls/listbox.c]
+	Fixed Winfile extended selection bug.
+
+	* [files/directory.c]
+	Changed DIR_SearchPath to return both long and short file names.
+
+	* [files/dos_fs.c]
+	Implemented VFAT ioctl to retrieve the original short filenames
+	from a VFAT filesystem (Linux only for now).
+	Replaced DOSFS_GetUnixFileName()/DOSFS_GetDosTrueName() by
+	DOS_GetFullName().
+	Properly implemented GetShortPathName() and GetFullPathName().
+	Made all functions re-entrant.
+
+	* [files/file.c] [misc/main.c]
+	Replaced -allowreadonly option by -failreadonly. The default is
+	now to report success when opening a read-only file for writing.
+
+	* [objects/metafile.c]
+	Fixed bug in DIB bitmaps pointer calculation.
+
+	* [scheduler/process.c]
+	Implemented environment strings and Get/SetStdHandle with process
+ 	environment block.
+
+	* [tools/build.c]
+	Rewrote BuildContext32() to avoid instructions that may not be
+	supported by all assemblers.
+	
+Fri Jan 10 17:11:09 1997  David Faure  <david.faure@ifhamy.insa-lyon.fr>
+
+	* [windows/event.c]
+	Created table keyc2vkey, which associate a vkey(+extended bit) to
+	any keycode. Changed EVENT_event_to_vkey to use this table to
+	return the correct vkey. Changed EVENT_ToAscii to get the keycode
+	from this table too.  Assigned OEM specific vkeys arbitrarily.
+
+Fri Jan 10 09:26:17 1997  John Harvey <john@division.co.uk>
+
+	* [misc/winsock.c] [misc/winsoc_async.c]
+        Fixed svr4 header files.
+        Changed bzero() to memset().
+
+	* [tools/fnt2bdf.c]
+        Removed bcopy() and used memcpy() instead.
+
+	* [debugger/msc.c]
+        Include string.h instead of strings.h
+
+	* [debugger/stabs.c]
+        Include string.h instead of strings.h.
+        Define __ELF__ for svr4 systems.
+
+	* [loader/signal.c]
+        Use wait() instead of wait4() which doesnt exist on Unixware.
+
+	* [memory/global.c]
+        Use sysconf() instead of getpagesize() for svr4 systems.
+
+Thu Jan  9 21:07:20 1997  Robert Pouliot <krynos@clic.net>
+
+	* [Make.rules.in] [Makefile.in] [make_os2.sh] [rc/Makefile.in]
+	  [tools/Makefile.in] [documentation/wine_os2.txt]
+	Patches for OS/2 support. Note that it doesn't compile yet.
+
+Tue Jan  7 20:03:53 1997  Eric Youngdale <eric@sub2304.jic.com>
+
+	* [debugger/*]
+	Many more debugger improvements (see debugger/README for details).
+
+Tue Jan  7 15:12:21 1997  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
+
+	* [windows/graphics.c] [objects/text.c] [graphics/x11drv/*]
+	  [graphics/metafiledrv/*]
+	Moved some device dependent code into the resp. subdirs.
+
+	* [include/gdi.h] [include/metafiledrv.h] [include/x11drv.h]
+	Prototypes added,
+	DC_FUNCTIONS: GetPixel added, some unnecessary functions removed.
+
+	* [objects/region.c]
+	CreatePolyPolygonRgn32 added.
+
+	* [files/dos_fs.c]
+	QueryDosDevice added.
+
+	* [misc/lstr.c]
+	FormatMessage: broken heap management fixed.
+
+	* [scheduler/process.c] [scheduler/thread.c]
+	Get/SetThreadPriority/PriorityClass added.
+
+Mon Jan  6 21:55:30 1997  Philippe De Muyter  <phdm@info.ucl.ac.be>
+
+	* [misc/keyboard.c]
+	ToAscii : Use EVENT_ToAscii instead.
+
+	* [windows/event.c]
+	keypad_key : Do not convert XK_Mode_switch to VK_MENU; recognize
+	keypad cursor keys.
+	EVENT_event_to_vkey : New function, to transform a X keycode
+	into a MSwin vkey + extended bit.
+	EVENT_ToAscii : New function, to transform a vkey + extended bit
+	(+ key state table) into ascii char(s), using XLookupString, and
+	recognizing dead chars.
+	EVENT_key : Transform AltGr into Ctrl+Alt sequence; call
+	EVENT_event_to_vkey for keycode to vkey conversion; fixed
+	previous, context and extended bits.
+
+	* [windows/keyboard.c]
+	Include stddebug.h, to get -debugmsg messages.
+	GetKeyState : Handle VK_MBUTTON case.
+	GetKeyboardState, SetKeyboardState : Debugging messages added.
+
+	* [windows/message.c]
+	TranslateMessage : Handle dead chars.
+
+Mon Jan  6 20:10:11 1997  Dominik Strasser  <bm424953@muenchen.org>
+
+	* [if1632/crtdll.spec] [misc/crtdll.c]
+	C++ functions new/delete/set_new_handler implemented.
+
+Mon Jan  6 15:48:15 1997 Frans van Dorsselaer <dorssel@rulhmpc49.LeidenUniv.nl>
+
+	* [controls/edit.c] [include/windows.h]
+	Moved the edit control to 32 bits.
+	Included new (win95) message definitions in windows.h
+	Implemented EM_SCROLLCARET, EM_SETMARGINS, EM_GETMARGINS,
+	EM_GETLIMITTEXT, EM_POSFROMCHAR, EM_CHARFROMPOS.
+	Broke EM_SETWORDBREAKPROC (internal wordwrap still works).
+	Fixed some bugs, introduced a couple of others.
+	Text buffer is now initially in 32-bit heap.
+
+	* [controls/EDIT.TODO] [controls/combo.c] [controls/widgets.c]
+	  [if1632/wprocs.spec] [library/miscstubs.c] [windows/defdlg.c]
+	  [misc/commdlg.c]
+	Updated to work with 32-bit edit control.
+
+Sat Jan  4 22:07:27 1997  O.Flebbe  <O.Flebbe@science-computing.uni-tuebingen.de>
+
+	* [loader/pe_image.c]
+	Use mmap rather then malloc. Better workaround for clean
+	segments.
+
+----------------------------------------------------------------------
 Wed Jan  1 15:36:17 1997  Alexandre Julliard  <julliard@lrc.epfl.ch>
 
 	* [controls/listbox.c]
diff --git a/Make.rules.in b/Make.rules.in
index 88b5f79..dc95c85 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -31,9 +31,9 @@
 ALLCFLAGS = $(CFLAGS) $(DEFS) $(OPTIONS) $(DIVINCL) $(X_CFLAGS)
 LDCOMBINE = ld -r
 RM        = rm -f
-BUILD     = $(TOPOBJDIR)/tools/build
-MAKEDEP   = $(TOPOBJDIR)/tools/makedep
-WINERC    = $(TOPOBJDIR)/rc/winerc
+BUILD     = $(TOPOBJDIR)/tools/build@PROGEXT@
+MAKEDEP   = $(TOPOBJDIR)/tools/makedep@PROGEXT@
+WINERC    = $(TOPOBJDIR)/rc/winerc@PROGEXT@
 WINESTUB  = $(TOPOBJDIR)/library/winestub.o
 SUBMAKE   = $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'OPTIONS=$(OPTIONS)'
 @SET_MAKE@
@@ -72,12 +72,17 @@
 # Rule to rebuild resource compiler
 
 $(WINERC) check_winerc:
-	cd $(TOPOBJDIR)/rc; $(SUBMAKE) winerc
+	cd $(TOPOBJDIR)/rc; $(SUBMAKE) winerc@PROGEXT@
 
-# Rule to rebuild the makedep program
+# Rule to rebuild the 'makedep' program
 
 $(MAKEDEP) check_makedep:
-	cd $(TOPOBJDIR)/tools; $(SUBMAKE) makedep
+	cd $(TOPOBJDIR)/tools; $(SUBMAKE) makedep@PROGEXT@
+
+# Rule to rebuild the 'build' program
+
+$(BUILD) checkbuild:
+	cd $(TOPOBJDIR)/tools; $(SUBMAKE) build@PROGEXT@
 
 # Rule for main module
 
diff --git a/configure b/configure
index 8189b70..13740b5 100755
--- a/configure
+++ b/configure
@@ -550,6 +550,7 @@
 
 # We want these before the checks, so the checks can modify their values.
 test -z "$LDLIBS" && LDLIBS=-lm 
+test -z "$PROGEXT" && PROGEXT="" 
 
 
 # Check whether --with-library or --without-library was given.
@@ -580,7 +581,7 @@
 
 
 echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:584: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:585: checking whether ${MAKE-make} sets \${MAKE}" >&5
 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -609,7 +610,7 @@
 # Extract the first word of "gcc", so it can be a program name with args.
 set dummy gcc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:613: checking for $ac_word" >&5
+echo "configure:614: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -638,7 +639,7 @@
   # Extract the first word of "cc", so it can be a program name with args.
 set dummy cc; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:642: checking for $ac_word" >&5
+echo "configure:643: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -686,7 +687,7 @@
 fi
 
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:690: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:691: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
 
 ac_ext=c
 # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
@@ -696,11 +697,11 @@
 cross_compiling=$ac_cv_prog_cc_cross
 
 cat > conftest.$ac_ext <<EOF
-#line 700 "configure"
+#line 701 "configure"
 #include "confdefs.h"
 main(){return(0);}
 EOF
-if { (eval echo configure:704: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:705: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   ac_cv_prog_cc_works=yes
   # If we can't run a trivial program, we are probably using a cross compiler.
   if (./conftest; exit) 2>/dev/null; then
@@ -720,12 +721,12 @@
   { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
 fi
 echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:724: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:725: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
 cross_compiling=$ac_cv_prog_cc_cross
 
 echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:729: checking whether we are using GNU C" >&5
+echo "configure:730: checking whether we are using GNU C" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -734,7 +735,7 @@
   yes;
 #endif
 EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:738: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:739: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
   ac_cv_prog_gcc=yes
 else
   ac_cv_prog_gcc=no
@@ -749,7 +750,7 @@
   ac_save_CFLAGS="$CFLAGS"
   CFLAGS=
   echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:753: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:754: checking whether ${CC-cc} accepts -g" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -777,7 +778,7 @@
 fi
 
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:781: checking how to run the C preprocessor" >&5
+echo "configure:782: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -792,13 +793,13 @@
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 796 "configure"
+#line 797 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:802: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:803: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   :
@@ -809,13 +810,13 @@
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 813 "configure"
+#line 814 "configure"
 #include "confdefs.h"
 #include <assert.h>
 Syntax Error
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:819: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:820: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   :
@@ -842,7 +843,7 @@
 # Uses ac_ vars as temps to allow command line to override cache and checks.
 # --without-x overrides everything else, but does not touch the cache.
 echo $ac_n "checking for X""... $ac_c" 1>&6
-echo "configure:846: checking for X" >&5
+echo "configure:847: checking for X" >&5
 
 # Check whether --with-x or --without-x was given.
 if test "${with_x+set}" = set; then
@@ -904,12 +905,12 @@
 
   # First, try using that file with no special directory specified.
 cat > conftest.$ac_ext <<EOF
-#line 908 "configure"
+#line 909 "configure"
 #include "confdefs.h"
 #include <$x_direct_test_include>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:913: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:914: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -978,14 +979,14 @@
   ac_save_LIBS="$LIBS"
   LIBS="-l$x_direct_test_library $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 982 "configure"
+#line 983 "configure"
 #include "confdefs.h"
 
 int main() {
 ${x_direct_test_function}()
 ; return 0; }
 EOF
-if { (eval echo configure:989: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:990: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   LIBS="$ac_save_LIBS"
 # We can link X programs with no special library path.
@@ -1091,17 +1092,17 @@
     case "`(uname -sr) 2>/dev/null`" in
     "SunOS 5"*)
       echo $ac_n "checking whether -R must be followed by a space""... $ac_c" 1>&6
-echo "configure:1095: checking whether -R must be followed by a space" >&5
+echo "configure:1096: checking whether -R must be followed by a space" >&5
       ac_xsave_LIBS="$LIBS"; LIBS="$LIBS -R$x_libraries"
       cat > conftest.$ac_ext <<EOF
-#line 1098 "configure"
+#line 1099 "configure"
 #include "confdefs.h"
 
 int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:1105: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1106: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   ac_R_nospace=yes
 else
@@ -1117,14 +1118,14 @@
       else
 	LIBS="$ac_xsave_LIBS -R $x_libraries"
 	cat > conftest.$ac_ext <<EOF
-#line 1121 "configure"
+#line 1122 "configure"
 #include "confdefs.h"
 
 int main() {
 
 ; return 0; }
 EOF
-if { (eval echo configure:1128: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1129: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   ac_R_space=yes
 else
@@ -1156,7 +1157,7 @@
     # libraries were built with DECnet support.  And karl@cs.umb.edu says
     # the Alpha needs dnet_stub (dnet does not exist).
     echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6
-echo "configure:1160: checking for dnet_ntoa in -ldnet" >&5
+echo "configure:1161: checking for dnet_ntoa in -ldnet" >&5
 ac_lib_var=`echo dnet'_'dnet_ntoa | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1164,7 +1165,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-ldnet  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1168 "configure"
+#line 1169 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1175,7 +1176,7 @@
 dnet_ntoa()
 ; return 0; }
 EOF
-if { (eval echo configure:1179: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1180: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1197,7 +1198,7 @@
 
     if test $ac_cv_lib_dnet_dnet_ntoa = no; then
       echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6
-echo "configure:1201: checking for dnet_ntoa in -ldnet_stub" >&5
+echo "configure:1202: checking for dnet_ntoa in -ldnet_stub" >&5
 ac_lib_var=`echo dnet_stub'_'dnet_ntoa | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1205,7 +1206,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-ldnet_stub  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1209 "configure"
+#line 1210 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1216,7 +1217,7 @@
 dnet_ntoa()
 ; return 0; }
 EOF
-if { (eval echo configure:1220: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1221: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1245,12 +1246,12 @@
     # The nsl library prevents programs from opening the X display
     # on Irix 5.2, according to dickey@clark.net.
     echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6
-echo "configure:1249: checking for gethostbyname" >&5
+echo "configure:1250: checking for gethostbyname" >&5
 if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1254 "configure"
+#line 1255 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char gethostbyname(); below.  */
@@ -1273,7 +1274,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1277: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1278: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_gethostbyname=yes"
 else
@@ -1294,7 +1295,7 @@
 
     if test $ac_cv_func_gethostbyname = no; then
       echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
-echo "configure:1298: checking for gethostbyname in -lnsl" >&5
+echo "configure:1299: checking for gethostbyname in -lnsl" >&5
 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1302,7 +1303,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lnsl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1306 "configure"
+#line 1307 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1313,7 +1314,7 @@
 gethostbyname()
 ; return 0; }
 EOF
-if { (eval echo configure:1317: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1318: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1343,12 +1344,12 @@
     # -lsocket must be given before -lnsl if both are needed.
     # We assume that if connect needs -lnsl, so does gethostbyname.
     echo $ac_n "checking for connect""... $ac_c" 1>&6
-echo "configure:1347: checking for connect" >&5
+echo "configure:1348: checking for connect" >&5
 if eval "test \"`echo '$''{'ac_cv_func_connect'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1352 "configure"
+#line 1353 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char connect(); below.  */
@@ -1371,7 +1372,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1375: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1376: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_connect=yes"
 else
@@ -1392,7 +1393,7 @@
 
     if test $ac_cv_func_connect = no; then
       echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6
-echo "configure:1396: checking for connect in -lsocket" >&5
+echo "configure:1397: checking for connect in -lsocket" >&5
 ac_lib_var=`echo socket'_'connect | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1400,7 +1401,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lsocket $X_EXTRA_LIBS $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1404 "configure"
+#line 1405 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1411,7 +1412,7 @@
 connect()
 ; return 0; }
 EOF
-if { (eval echo configure:1415: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1416: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1435,12 +1436,12 @@
 
     # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX.
     echo $ac_n "checking for remove""... $ac_c" 1>&6
-echo "configure:1439: checking for remove" >&5
+echo "configure:1440: checking for remove" >&5
 if eval "test \"`echo '$''{'ac_cv_func_remove'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1444 "configure"
+#line 1445 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char remove(); below.  */
@@ -1463,7 +1464,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1467: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1468: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_remove=yes"
 else
@@ -1484,7 +1485,7 @@
 
     if test $ac_cv_func_remove = no; then
       echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6
-echo "configure:1488: checking for remove in -lposix" >&5
+echo "configure:1489: checking for remove in -lposix" >&5
 ac_lib_var=`echo posix'_'remove | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1492,7 +1493,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lposix  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1496 "configure"
+#line 1497 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1503,7 +1504,7 @@
 remove()
 ; return 0; }
 EOF
-if { (eval echo configure:1507: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1508: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1527,12 +1528,12 @@
 
     # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
     echo $ac_n "checking for shmat""... $ac_c" 1>&6
-echo "configure:1531: checking for shmat" >&5
+echo "configure:1532: checking for shmat" >&5
 if eval "test \"`echo '$''{'ac_cv_func_shmat'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 1536 "configure"
+#line 1537 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char shmat(); below.  */
@@ -1555,7 +1556,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1559: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1560: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_shmat=yes"
 else
@@ -1576,7 +1577,7 @@
 
     if test $ac_cv_func_shmat = no; then
       echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6
-echo "configure:1580: checking for shmat in -lipc" >&5
+echo "configure:1581: checking for shmat in -lipc" >&5
 ac_lib_var=`echo ipc'_'shmat | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1584,7 +1585,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lipc  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1588 "configure"
+#line 1589 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1595,7 +1596,7 @@
 shmat()
 ; return 0; }
 EOF
-if { (eval echo configure:1599: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1600: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1628,7 +1629,7 @@
   # libraries we check for below, so use a different variable.
   #  --interran@uluru.Stanford.EDU, kb@cs.umb.edu.
   echo $ac_n "checking for IceConnectionNumber in -lICE""... $ac_c" 1>&6
-echo "configure:1632: checking for IceConnectionNumber in -lICE" >&5
+echo "configure:1633: checking for IceConnectionNumber in -lICE" >&5
 ac_lib_var=`echo ICE'_'IceConnectionNumber | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1636,7 +1637,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-lICE  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1640 "configure"
+#line 1641 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1647,7 +1648,7 @@
 IceConnectionNumber()
 ; return 0; }
 EOF
-if { (eval echo configure:1651: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1652: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1676,7 +1677,7 @@
 # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1680: checking for $ac_word" >&5
+echo "configure:1681: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1708,7 +1709,7 @@
 # Extract the first word of "flex", so it can be a program name with args.
 set dummy flex; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1712: checking for $ac_word" >&5
+echo "configure:1713: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1741,7 +1742,7 @@
   *) ac_lib=l ;;
   esac
   echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6
-echo "configure:1745: checking for yywrap in -l$ac_lib" >&5
+echo "configure:1746: checking for yywrap in -l$ac_lib" >&5
 ac_lib_var=`echo $ac_lib'_'yywrap | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1749,7 +1750,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-l$ac_lib  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1753 "configure"
+#line 1754 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1760,7 +1761,7 @@
 yywrap()
 ; return 0; }
 EOF
-if { (eval echo configure:1764: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1765: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1785,7 +1786,7 @@
 # Extract the first word of "ranlib", so it can be a program name with args.
 set dummy ranlib; ac_word=$2
 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1789: checking for $ac_word" >&5
+echo "configure:1790: checking for $ac_word" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1822,7 +1823,7 @@
 # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
 # ./install, which can be erroneously created by make from ./install.sh.
 echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:1826: checking for a BSD compatible install" >&5
+echo "configure:1827: checking for a BSD compatible install" >&5
 if test -z "$INSTALL"; then
 if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1872,7 +1873,7 @@
 test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 
 echo $ac_n "checking for i386_set_ldt in -li386""... $ac_c" 1>&6
-echo "configure:1876: checking for i386_set_ldt in -li386" >&5
+echo "configure:1877: checking for i386_set_ldt in -li386" >&5
 ac_lib_var=`echo i386'_'i386_set_ldt | sed 'y%./+-%__p_%'`
 if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
@@ -1880,7 +1881,7 @@
   ac_save_LIBS="$LIBS"
 LIBS="-li386  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1884 "configure"
+#line 1885 "configure"
 #include "confdefs.h"
 /* Override any gcc2 internal prototype to avoid an error.  */
 /* We use char because int might match the return type of a gcc2
@@ -1891,7 +1892,7 @@
 i386_set_ldt()
 ; return 0; }
 EOF
-if { (eval echo configure:1895: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1896: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=yes"
 else
@@ -1917,7 +1918,7 @@
 then
   CFLAGS="$CFLAGS -Wall"
   echo $ac_n "checking "for gcc strength-reduce bug"""... $ac_c" 1>&6
-echo "configure:1921: checking "for gcc strength-reduce bug"" >&5
+echo "configure:1922: checking "for gcc strength-reduce bug"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_gcc_strength_bug'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1925,7 +1926,7 @@
   ac_cv_c_gcc_strength_bug="yes"
 else
   cat > conftest.$ac_ext <<EOF
-#line 1929 "configure"
+#line 1930 "configure"
 #include "confdefs.h"
 
 int main(void) {
@@ -1936,7 +1937,7 @@
   exit( Array[1] != -2 );
 }
 EOF
-if { (eval echo configure:1940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1941: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
 then
   ac_cv_c_gcc_strength_bug="no"
 else
@@ -1959,7 +1960,7 @@
 
 
 echo $ac_n "checking "whether external symbols need an underscore prefix"""... $ac_c" 1>&6
-echo "configure:1963: checking "whether external symbols need an underscore prefix"" >&5
+echo "configure:1964: checking "whether external symbols need an underscore prefix"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_extern_prefix'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -1971,14 +1972,14 @@
 	.long 0
 EOF
 cat > conftest.$ac_ext <<EOF
-#line 1975 "configure"
+#line 1976 "configure"
 #include "confdefs.h"
 extern int ac_test;
 int main() {
 if (ac_test) return 1
 ; return 0; }
 EOF
-if { (eval echo configure:1982: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:1983: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   ac_cv_c_extern_prefix="yes"
 else
@@ -2004,21 +2005,21 @@
 if test "$MAIN_TARGET" = "libwine.so.1.0"
 then
   echo $ac_n "checking "whether we can build a dll"""... $ac_c" 1>&6
-echo "configure:2008: checking "whether we can build a dll"" >&5
+echo "configure:2009: checking "whether we can build a dll"" >&5
 if eval "test \"`echo '$''{'ac_cv_c_dll'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   saved_cflags=$CFLAGS
   CFLAGS="$CFLAGS -fPIC -shared -Wl,-soname,conftest.so.1.0"
   cat > conftest.$ac_ext <<EOF
-#line 2015 "configure"
+#line 2016 "configure"
 #include "confdefs.h"
 
 int main() {
 return 1
 ; return 0; }
 EOF
-if { (eval echo configure:2022: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2023: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   ac_cv_c_dll="yes"
 else
@@ -2045,12 +2046,12 @@
 for ac_func in memmove tcgetattr usleep
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2049: checking for $ac_func" >&5
+echo "configure:2050: checking for $ac_func" >&5
 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2054 "configure"
+#line 2055 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -2073,7 +2074,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2077: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:2078: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
@@ -2098,12 +2099,12 @@
 done
 
 echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
-echo "configure:2102: checking whether stat file-mode macros are broken" >&5
+echo "configure:2103: checking whether stat file-mode macros are broken" >&5
 if eval "test \"`echo '$''{'ac_cv_header_stat_broken'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2107 "configure"
+#line 2108 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -2154,12 +2155,12 @@
 fi
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
-echo "configure:2158: checking for working const" >&5
+echo "configure:2159: checking for working const" >&5
 if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2163 "configure"
+#line 2164 "configure"
 #include "confdefs.h"
 
 int main() {
@@ -2208,7 +2209,7 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:2212: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2213: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
@@ -2229,12 +2230,12 @@
 fi
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:2233: checking for ANSI C header files" >&5
+echo "configure:2234: checking for ANSI C header files" >&5
 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2238 "configure"
+#line 2239 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -2242,7 +2243,7 @@
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2246: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2247: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -2259,7 +2260,7 @@
 if test $ac_cv_header_stdc = yes; then
   # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 2263 "configure"
+#line 2264 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -2277,7 +2278,7 @@
 if test $ac_cv_header_stdc = yes; then
   # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
 cat > conftest.$ac_ext <<EOF
-#line 2281 "configure"
+#line 2282 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -2298,7 +2299,7 @@
   :
 else
   cat > conftest.$ac_ext <<EOF
-#line 2302 "configure"
+#line 2303 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -2309,7 +2310,7 @@
 exit (0); }
 
 EOF
-if { (eval echo configure:2313: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2314: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
 then
   :
 else
@@ -2333,12 +2334,12 @@
 fi
 
 echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:2337: checking for size_t" >&5
+echo "configure:2338: checking for size_t" >&5
 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   cat > conftest.$ac_ext <<EOF
-#line 2342 "configure"
+#line 2343 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
@@ -2531,6 +2532,7 @@
 s%@infodir@%$infodir%g
 s%@mandir@%$mandir%g
 s%@LDLIBS@%$LDLIBS%g
+s%@PROGEXT@%$PROGEXT%g
 s%@MAIN_TARGET@%$MAIN_TARGET%g
 s%@OPTIONS@%$OPTIONS%g
 s%@SET_MAKE@%$SET_MAKE%g
diff --git a/configure.in b/configure.in
index ede5e0c..18f803c 100644
--- a/configure.in
+++ b/configure.in
@@ -8,6 +8,7 @@
 
 # We want these before the checks, so the checks can modify their values.
 test -z "$LDLIBS" && LDLIBS=-lm AC_SUBST(LDLIBS)
+test -z "$PROGEXT" && PROGEXT="" AC_SUBST(PROGEXT)
 
 dnl **** Command-line arguments ****
 
diff --git a/controls/EDIT.TODO b/controls/EDIT.TODO
index 7bacadf..4ff35e7 100644
--- a/controls/EDIT.TODO
+++ b/controls/EDIT.TODO
@@ -4,25 +4,48 @@
 
 A) basic policy
 B) special functions
-C) not implemented
-D) known bugs
+C) not implemented / implementation ideas / implementation problems
+D) known bugs / features
 
 A) Basic Policy
 
+All messages are handled by EditWndProc(), which is the only external
+function call.  All other functions are static (local to edit.c).
+
+All Windows Messages (WM_XXX) are 32-bit, since the edit control is now a
+32-bit registered class.  The message are dealt with through the helper
+functions EDIT_WM_XXX().
+
+The edit control messages can be either 16 or 32 bit, depending on the type
+of application that sends the message.  Wherever possible EditWndProc()
+converts the 16-bit message parameters to parameters corresponding to their
+32-bit counterparts.  The message is then handled by the appropriate
+EDIT_EM_XXX() helper function. Sometimes it is not possible to handle the
+16-bit and 32-bit versions in the same way, in which case both helper
+functions EDIT_EM_XXX16() and EDIT_EM_XXX() are defined.
+
+All other functions are called EDIT_XXX().
+
+Note: Sometimes a function is internally used a bit different than the specs
+of a similar function.  For instance EDIT_SetSel() is used internally and
+should not be mixed up with EDIT_EM_SetSel(), a message handler that _does_
+conform to the specs of EM_SETSEL.
+
 The code has been made in such a way, that functions try to call other
 (documented) functions if that is sufficient.  This might sometimes not be
-the most efficient way, but it keeps the code clear.  This way I tried to keep
-the number of functions that rely on the internal EDITSTATE structure as
-low as possible.  For instance EDIT_WM_Cut() simply calls EDIT_WM_Copy() and
-EDIT_WM_Clear().  The latter two are well documented message handlers, so
-as long as they are right EDIT_WM_Cut() will never have to change again.
+the most efficient way, but it keeps the code clear.  This way I tried to
+keep the number of functions that rely on the internal EDITSTATE structure
+as low as possible.  For instance EDIT_WM_Cut() simply calls EDIT_WM_Copy()
+and EDIT_WM_Clear().  The latter two are well documented message handlers,
+so as long as they are right EDIT_WM_Cut() will never have to change again.
 
 Example:
 The best thing to do, when you want to know the offset of line 3, is calling
-EDIT_EM_LineIndex().  Again this is a well documented message handler.  Don't
-look at es->LineDefs[2].offset.  It would just be another reference to the
-internal structure, and that would make it more difficult to change things.
-Refer to EDIT_WM_???? and EDIT_EM_????? functions as much as possible.
+EDIT_EM_LineIndex().  Again this is a well documented message handler. 
+Don't look at es->LineDefs[2].offset.  It would just be another reference to
+the internal structure, and that would make it more difficult to change
+things. Refer to EDIT_WM_???? and EDIT_EM_????? functions as much as
+possible.
 
 The WND * pointer is used internally whenever possible.  Although it is not
 the real HWND, it improves performance enough to use it.
@@ -33,20 +56,35 @@
 would be much slower even, when everything would be painted instantly.  This
 is especially true for scrollbar tracking and selection changes..
 
+The text buffer is a kind of tricky.  Initially the edit control allocates a
+HLOCAL32 buffer (32 bit linear memory handler).  However, 16 bit application
+might send a EM_GETHANDLE message and expect a HLOCAL16 (16 bit SEG:OFF
+handler).  From that moment on we have to keep using this 16 bit memory
+handler, because it is supposed to be valid at all times after EM_GETHANDLE. 
+What we do is create a HLOCAL16 buffer, copy the text, and do pointer
+conversion.
+
 
 
 B) Special functions
 
-The edit control needs to use local heap memory because applications may
-rely on EM_GETHANDLE.  This is bad, but it can't be helped, we have to live
-with that.  For this reason there is a nice EDIT_GetPointer() function,
-which locks the heap buffer *only once*, no matter how often it is called.
-Only at the end of the message handler EDIT_ReleasePointer() is called.  You
-don't have to worry about unlocking the heap.  Calling EDIT_GetPointer() is
-very fast if the buffer is already locked.
-This way, the buffer gets locked / unlock only once every message, although
-EDIT_GetPointer() may actually have been called a hundred times.
-Only when the actual HLOCAL is needed (for example to ReAlloc), a call to
+Several helper functions try to make your life easier when dealing with the
+allocated buffer.  In principle Windows can move memory blocks around unless
+they are locked.  Currently, WINE doesn't do this, but it might in the
+future.
+
+For this reason there is a nice EDIT_GetPointer() function, which locks the
+heap buffer *only once*, no matter how often it is called. It then returns a
+nice 32-bit pointer to linear memory. Calling EDIT_GetPointer() is very fast
+if the buffer is already locked, so you can call it whenever you feel it
+*might* be useful.
+
+At the end of EditWndProc(), EDIT_ReleasePointer() is automatically called
+which cleans up the initialized pointer.  So you don't have to worry about
+unlocking the memory block. This way, the buffer gets locked / unlock only
+once every message, although EDIT_GetPointer() may actually have been called
+a hundred times.  Only when the actual HLOCAL is needed (for example to
+ReAlloc), an extra call (besides the cleanup at the end of EditWndProc()) to
 EDIT_ReleasePointer() is needed.  Look for instance in EDIT_MakeFit().
 
 This brings us to EDIT_MakeFit().  It automatically re-allocates the buffer
@@ -55,6 +93,9 @@
 to call EDIT_MakeFit().  Currently this is only in EDIT_ReplaceSel() and
 EDIT_WM_SetText().
 
+EDIT_GetPointer(), EDIT_ReleasePointer and EDIT_MakeFit() are aware of the
+HLOCAL32 / HLOCAL16 business.
+
 EDIT_BuildLineDefs() is the most important function in edit.c.  It builds
 the internal EDITSTATE structure.  As soon as text *might* have changed, or
 when the appearance of the text on the screen *might* have changed, call
@@ -64,47 +105,93 @@
 
 
 
-C) Not Implemented
+C) Not Implemented / Implementation Ideas / Implementation Problems
 
-- ES_PASSWORD
+Styles:
+
 - ES_CENTER
 - ES_RIGHT
-- EM_SETRECT
-- EM_SETRECTNP
-- EM_FMTLINES
-- ES_AUTOVSCROLL (every multi line *is* auto vscroll)
-- ES_AUTOHSCROLL (multi line can be yes or no, but single line only yes)
-- WM_UNDO (=EM_UNDO)
-- EM_CANUNDO
-- EM_SCROLL (scrolling works, but this appears to be an undocumented message)
-- ES_LOWERCASE
-- ES_UPPERCASE
+- ES_NUMBER (new since win95)
 - ES_OEMCONVERT
 - ES_WANTRETURN
-- probably much, MUCH more
 
-I encountered several undocumented messages, or message parameters.
-EditWndProc() reports any unknown message with an id > WM_USER.
+None of these should be difficult to include.  I just didn't have the time
+yet.  Feel free ...
+
+- ES_AUTOVSCROLL (every multi line control *is* auto vscroll)
+- ES_AUTOHSCROLL (every single line control *is* auto hscroll)
+		 (for multi line controls it works : wordwrap)
+
+Much, much more difficult.  It comes down to this: When there is no
+autoscrolling, the edit control should first check whether the new text
+(after a typed key for instance) would fit.  If not, an EN_MAXTEXT should be
+sent.  However, currently this would require the actual change to be made,
+then call EDIT_BuildLineDefs() and then find out that the new text doesn't
+fit.  After all this, things should be put back in the state before the
+changes.  Given the fact that even normal UNDO doesn't work ...
+
+Messages:
+
+- EM_SETRECT
+- EM_SETRECTNP
+- EM_SETMARGINS (new since win95)
+- EM_FMTLINES
+
+These shouldn't be really difficult either.  They just confine the visual
+output to something different than the client rectangle.  Currently the
+client area is used everywhere in the code.  At some points this should
+really be so (GetClientRect32()), whereas at other points it should be the
+format rectangle (EDIT_EM_GetRect()). Both functions are now used, but
+inconsistently and mixed up ! If you implement the formatting rectangle /
+margins, be sure to check all references to RECT's, and how they are /
+should be obtained.
+
+- EM_FMTLINES
+
+This means: insert or remove the soft linebreak character (\r\r\n). Probably
+invented by MS to suit their implementation of the edit control.  However,
+with WINE's implementation I've never come up with occasions where it is
+actually useful (we never insert \r\r\n, and applications always request
+removal).  If you are a purist ... implementation shouldn't be difficult. 
+Take care to check if the text still fits the buffer after insertion. If
+not, notify with EN_ERRSPACE.
+
+- WM_UNDO (=EM_UNDO)
+
+I'm working on it.  It is, however, not trivial.  Luckily the only function
+where actual text changes is EM_REPLACESEL, so this is the only spot where
+we have to worry about UNDO capabilities. Before you try: contact me.  I
+already have ideas and might start implementing it myself really soon.
+
+- EM_SETWORDBREAKPROC
+
+Not really difficult.  It used to work, but since we moved to 32 bits there
+are now two kinds of callback functions.  And I don't know the 32-bit specs
+for the WordBreakProc() ...  Look it up and uncomment the code that is still
+there for 16 bit callback.
+
+- EM_SCROLL
+
+Supposed to be the same as WM_VSCROLL, but not quite.  In other words:
+poorly documented.  Somebody that knows ?
 
 
 
-D) Known bugs.
+D) Known bugs / Features
 
--	Scrolling is weird, sometimes.  The current code makes the scrollbar
-	of Notepad work, but the scrollbar code itself is broken.  Currently
-	the scroll code of edit.c is *not* according to specs.  Instead, it
-	is according to the broken scrollbar code.  If that gets fixed, this
-	should be fixed, too.
--	The clipboard is broken.  Whenever things go wrong with
-	cut/copy/paste, it is probably the clipboard that messes up things,
-	not edit.c.
--	Turning on WordWrap with Notepad leaves part of the horizontal
+-	The control still calls GetTabbedTextExtent() and TabbedTextOut() in
+	their 16 bit version (since the 32 bit versions don't yet exist).
+	Therefore the tab list is 16 bits (should be 32).
+-	Scrollbar tracking is broken.
+-	Lots of API calls are to 16 bit functions, because their 32 bit
+	versions haven't been implemented yet (e.g. clipboard).
+-	Turning on WordWrap with 16-bit Notepad leaves part of the horizontal
 	scrollbar visible (problem with WM_ERASEBKGND ???).
+-	FIXME's (grep for them).
 
 
-I am still very actively changing things.  Especially I am working
-on Undo capabilities.  If you want to do things, other than bug fixes,
-please mail me so we can synchronize.
+I am working on Undo capabilities.  If you want to do things, other than bug
+fixes, please mail me so we can synchronize.
 
 Frans van Dorsselaer
 dorssel@rulhm1.LeidenUniv.nl
diff --git a/controls/combo.c b/controls/combo.c
index 4c231f4..dacc760 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -756,7 +756,7 @@
 
     if ((lphc->dwStyle & 3) == CBS_DROPDOWNLIST)
       return CB_ERR;	/* err, documented for CBSetEditSel */
-    return SendMessage16(lphc->hWndEdit, EM_GETSEL, 0, 0);
+    return SendMessage16(lphc->hWndEdit, EM_GETSEL16, 0, 0);
 }
 
 
@@ -770,7 +770,7 @@
 
     if ((lphc->dwStyle & 3) == CBS_DROPDOWNLIST)
       return CB_ERR;
-    return SendMessage16(lphc->hWndEdit, EM_SETSEL, 0, lParam);
+    return SendMessage16(lphc->hWndEdit, EM_SETSEL16, 0, lParam);
 }
 
 /***********************************************************************
diff --git a/controls/edit.c b/controls/edit.c
index 3cb1372..e53103e 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -3,14 +3,18 @@
  *
  *	Copyright  David W. Metcalfe, 1994
  *	Copyright  William Magro, 1995, 1996
- *	Copyright  Frans van Dorsselaer, 1996
+ *	Copyright  Frans van Dorsselaer, 1996, 1997
  *
  */
 
 /*
- *	UNDER CONSTRUCTION, please read EDIT.TODO
+ *	please read EDIT.TODO (and update it when you change things)
+ *	It also contains a discussion about the 16 to 32 bit transition.
+ *
  */
 
+
+#define NO_TRANSITION_TYPES	/* This file is Win32-clean */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -20,9 +24,12 @@
 #include "stddebug.h"
 #include "debug.h"
 #include "xmalloc.h"
+/*
 #include "callback.h"
+*/
 
 #define BUFLIMIT_MULTI		65534	/* maximum text buffer length (not including '\0') */
+					/* FIXME: BTW, new specs say 65535 (do you dare ???) */
 #define BUFLIMIT_SINGLE		32766
 #define BUFSTART_MULTI		1024	/* starting length for multi-line control */
 #define BUFSTART_SINGLE		256	/* starting length for single line control */
@@ -39,38 +46,73 @@
 } LINE_END;
 
 typedef struct {
-	UINT offset;
-	UINT length;
+	INT32 offset;
+	INT32 length;
 	LINE_END ending;
 } LINEDEF;
 
 typedef struct
 {
-	UINT TextWidth;		/* width of the widest line in pixels */
-	HLOCAL16 hBuf;
-	char *text;
-	HFONT16 hFont;
-	LINEDEF *LineDefs;
-	UINT XOffset;		/* offset of the viewport in pixels */
-	UINT FirstVisibleLine;
-	UINT LineCount;
-	UINT LineHeight;	/* height of a screen line in pixels */
-	UINT AveCharWidth;	/* average character width in pixels */
-	UINT BufLimit;
-	UINT BufSize;
-	BOOL TextChanged;
-	BOOL Redraw;
-	UINT SelStart;		/* offset of selection start, == SelEnd if no selection */
-	UINT SelEnd;		/* offset of selection end == current caret position */
-	UINT NumTabStops;
+	HLOCAL16 hBuf16;	/* For when a 16-bit multiline edit
+				 * control gets a EM_GETHANDLE (which
+				 * should return 16-bit local heap).
+				 * From that point on we _have_ to keep
+				 * using 16-bit local heap (apps rely
+				 * on that ... bummer).
+				 */
+	HLOCAL32 hBuf32;	/* Don't worry about 'LOCAL'.  LOCAL32 is
+				 * identical to GLOBAL32, which is
+				 * essentially a HANDLE32 created with
+				 * HeapAlloc(GetProcessHeap(), ...) plus
+				 * a global32 (and thus local32)
+				 * descriptor, which we can return upon
+				 * EM_GETHANDLE32.
+				 * It is 32-bit linear addressing, so
+				 * everything is fine.
+				 */
+	LPSTR text;		/* Depending on the fact that we are a
+				 * 16 or 32 bit control, this is the
+				 * pointer that we get after
+				 * LocalLock32(hBuf23) (which is a typecast :-)
+				 * or LOCAL_Lock(hBuf16).
+				 * This is always a 32-bit linear pointer.
+				 */
+	HFONT32 hFont;
+	LINEDEF *LineDefs;	/* Internal table for (soft) linebreaks */
+	INT32 TextWidth;	/* width of the widest line in pixels */
+	INT32 XOffset;		/* offset of the viewport in pixels */
+	INT32 FirstVisibleLine;
+	INT32 LineCount;
+	INT32 LineHeight;	/* height of a screen line in pixels */
+	INT32 AveCharWidth;	/* average character width in pixels */
+	INT32 BufLimit;
+	INT32 BufSize;
+	BOOL32 TextChanged;
+	BOOL32 CanUndo;
+	BOOL32 Redraw;
+	INT32 SelStart;		/* offset of selection start, == SelEnd if no selection */
+	INT32 SelEnd;		/* offset of selection end == current caret position */
+	INT32 NumTabStops;
 	LPINT16 TabStops;
-	EDITWORDBREAKPROC WordBreakProc;
-	char PasswordChar;
+	/*
+	 *	FIXME: The following should probably be a (VOID *) that is
+	 *	typecast to either 16- or 32-bit callback when used,
+	 *	depending on the type of edit control (16 or 32 bit).
+	 *
+	 *	EDITWORDBREAKPROC WordBreakProc;
+	 *
+	 *	For now: no more application specific wordbreaking.
+	 *	(Internal wordbreak function still works)
+	 */
+	CHAR PasswordChar;
+	INT32 LeftMargin;
+	INT32 RightMargin;
+	RECT32 FormatRect;
 } EDITSTATE;
 
 
-#define SWAP_UINT(x,y) do { UINT temp = (UINT)(x); (x) = (UINT)(y); (y) = temp; } while(0)
-#define ORDER_UINT(x,y) do { if ((UINT)(y) < (UINT)(x)) SWAP_UINT((x),(y)); } while(0)
+#define SWAP_INT32(x,y) do { INT32 temp = (INT32)(x); (x) = (INT32)(y); (y) = temp; } while(0)
+#define ORDER_INT32(x,y) do { if ((INT32)(y) < (INT32)(x)) SWAP_INT32((x),(y)); } while(0)
 
 /* macros to access window styles */
 #define IsMultiLine(wndPtr) ((wndPtr)->dwStyle & ES_MULTILINE)
@@ -86,15 +128,19 @@
 
 #define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
     (SendMessage32A((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \
-                    (WPARAM32)(hdc), (LPARAM)(wndPtr)->hwndSelf ))
+		    (WPARAM32)(hdc), (LPARAM)(wndPtr)->hwndSelf ))
 #define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
     (SendMessage32A((wndPtr)->parent->hwndSelf, WM_COMMAND, \
-                    MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \
-                    (LPARAM)(wndPtr)->hwndSelf ))
-#define DPRINTF_EDIT_MSG(str) \
+		    MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \
+		    (LPARAM)(wndPtr)->hwndSelf ))
+#define DPRINTF_EDIT_MSG16(str) \
     dprintf_edit(stddeb, \
-                 "edit: " str ": hwnd=%04x, wParam=%04x, lParam=%08x\n", \
-                 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
+		 "edit: 16 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n  ", \
+		 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
+#define DPRINTF_EDIT_MSG32(str) \
+    dprintf_edit(stddeb, \
+		 "edit: 32 bit : " str ": hwnd=%08x, wParam=%08x, lParam=%08x\n", \
+		 (UINT32)hwnd, (UINT32)wParam, (UINT32)lParam)
 
 
 /*********************************************************************
@@ -104,76 +150,84 @@
  *	Files like these should really be kept in alphabetical order.
  *
  */
-LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM16 wParam, LPARAM lParam);
+LRESULT EditWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam);
 
 static void    EDIT_BuildLineDefs(WND *wndPtr);
-static INT     EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action);
-static UINT    EDIT_ColFromWndX(WND *wndPtr, UINT line, INT x);
+static INT32   EDIT_CallWordBreakProc(WND *wndPtr, LPSTR s, INT32 index, INT32 count, INT32 action);
+static INT32   EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x);
 static void    EDIT_DelEnd(WND *wndPtr);
 static void    EDIT_DelLeft(WND *wndPtr);
 static void    EDIT_DelRight(WND *wndPtr);
-static UINT    EDIT_GetAveCharWidth(WND *wndPtr);
-static UINT    EDIT_GetLineHeight(WND *wndPtr);
-static void    EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT16 rc);
-static char *  EDIT_GetPointer(WND *wndPtr);
-static char *  EDIT_GetPasswordPointer(WND *wndPtr);
-static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static BOOL    EDIT_GetRedraw(WND *wndPtr);
-static LRESULT EDIT_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static UINT    EDIT_GetTextWidth(WND *wndPtr);
-static UINT    EDIT_GetVisibleLineCount(WND *wndPtr);
-static UINT    EDIT_GetWndWidth(WND *wndPtr);
-static UINT    EDIT_GetXOffset(WND *wndPtr);
-static void    EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end);
-static UINT    EDIT_LineFromWndY(WND *wndPtr, INT y);
-static BOOL    EDIT_MakeFit(WND *wndPtr, UINT size);
-static void    EDIT_MoveBackward(WND *wndPtr, BOOL extend);
-static void    EDIT_MoveDownward(WND *wndPtr, BOOL extend);
-static void    EDIT_MoveEnd(WND *wndPtr, BOOL extend);
-static void    EDIT_MoveForward(WND *wndPtr, BOOL extend);
-static void    EDIT_MoveHome(WND *wndPtr, BOOL extend);
-static void    EDIT_MovePageDown(WND *wndPtr, BOOL extend);
-static void    EDIT_MovePageUp(WND *wndPtr, BOOL extend);
-static void    EDIT_MoveUpward(WND *wndPtr, BOOL extend);
-static void    EDIT_MoveWordBackward(WND *wndPtr, BOOL extend);
-static void    EDIT_MoveWordForward(WND *wndPtr, BOOL extend);
-static void    EDIT_PaintLine(WND *wndPtr, HDC32 hdc, UINT line, BOOL rev);
-static UINT    EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev);
+static INT32   EDIT_GetAveCharWidth(WND *wndPtr);
+static INT32   EDIT_GetLineHeight(WND *wndPtr);
+static void    EDIT_GetLineRect(WND *wndPtr, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc);
+static LPSTR   EDIT_GetPointer(WND *wndPtr);
+static LPSTR   EDIT_GetPasswordPointer(WND *wndPtr);
+static BOOL32  EDIT_GetRedraw(WND *wndPtr);
+static void    EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e);
+static INT32   EDIT_GetTextWidth(WND *wndPtr);
+static INT32   EDIT_GetVisibleLineCount(WND *wndPtr);
+static INT32   EDIT_GetWndWidth(WND *wndPtr);
+static INT32   EDIT_GetXOffset(WND *wndPtr);
+static void    EDIT_InvalidateText(WND *wndPtr, INT32 start, INT32 end);
+static INT32   EDIT_LineFromWndY(WND *wndPtr, INT32 y);
+static BOOL32  EDIT_MakeFit(WND *wndPtr, INT32 size);
+static void    EDIT_MoveBackward(WND *wndPtr, BOOL32 extend);
+static void    EDIT_MoveDownward(WND *wndPtr, BOOL32 extend);
+static void    EDIT_MoveEnd(WND *wndPtr, BOOL32 extend);
+static void    EDIT_MoveForward(WND *wndPtr, BOOL32 extend);
+static void    EDIT_MoveHome(WND *wndPtr, BOOL32 extend);
+static void    EDIT_MovePageDown(WND *wndPtr, BOOL32 extend);
+static void    EDIT_MovePageUp(WND *wndPtr, BOOL32 extend);
+static void    EDIT_MoveUpward(WND *wndPtr, BOOL32 extend);
+static void    EDIT_MoveWordBackward(WND *wndPtr, BOOL32 extend);
+static void    EDIT_MoveWordForward(WND *wndPtr, BOOL32 extend);
+static void    EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev);
+static INT32   EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT32 x, INT32 y, INT32 line, INT32 col, INT32 count, BOOL32 rev);
 static void    EDIT_ReleasePointer(WND *wndPtr);
-static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static void    EDIT_ScrollIntoView(WND *wndPtr);
-static INT     EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col);
-static INT     EDIT_WndYFromLine(WND *wndPtr, UINT line);
-static INT     EDIT_WordBreakProc(char *s, INT index, INT count, INT action);
+static INT32   EDIT_WndXFromCol(WND *wndPtr, INT32 line, INT32 col);
+static INT32   EDIT_WndYFromLine(WND *wndPtr, INT32 line);
+static INT32   EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action);
 
 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
-static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetSel16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
 
@@ -211,22 +265,22 @@
  *
  *	General shortcuts for variable names:
  *
- *	UINT l;		line
- *	UINT c;		column
- *	UINT s;		offset of selection start
- *	UINT e;		offset of selection end
- *	UINT sl;	line on which the selection starts
- *	UINT el;	line on which the selection ends
- *	UINT sc;	column on which the selection starts
- *	UINT ec;	column on which the selection ends
- *	UINT li;	line index (offset)
- *	UINT fv;	first visible line
- *	UINT vlc;	vissible line count
- *	UINT lc;	line count
- *	UINT lh;	line height (in pixels)
- *	UINT tw;	text width (in pixels)
- *	UINT ww;	window width (in pixels)
- *	UINT cw;	character width (average, in pixels)
+ *	INT32 l;	line
+ *	INT32 c;	column
+ *	INT32 s;	offset of selection start
+ *	INT32 e;	offset of selection end
+ *	INT32 sl;	line on which the selection starts
+ *	INT32 el;	line on which the selection ends
+ *	INT32 sc;	column on which the selection starts
+ *	INT32 ec;	column on which the selection ends
+ *	INT32 li;	line index (offset)
+ *	INT32 fv;	first visible line
+ *	INT32 vlc;	vissible line count
+ *	INT32 lc;	line count
+ *	INT32 lh;	line height (in pixels)
+ *	INT32 tw;	text width (in pixels)
+ *	INT32 ww;	window width (in pixels)
+ *	INT32 cw;	character width (average, in pixels)
  *
  */
 
@@ -235,255 +289,496 @@
  *
  *	EditWndProc()
  *
+ *	The messages are in the order of the actual integer values
+ *	(which can be found in include/windows.h)
+ *	Whereever possible the 16 bit versions are converted to
+ *	the 32 bit ones, so that we can 'fall through' to the
+ *	helper functions.  These are mostly 32 bit (with a few
+ *	exceptions, clearly indicated by a '16' extension to their
+ *	names).
+ *
  */
-LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM16 wParam, LPARAM lParam)
+LRESULT EditWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
 {
-	LRESULT lResult = 0L;
+	LRESULT lResult = 0;
 	WND *wndPtr = WIN_FindWndPtr(hwnd);
 
 	if ((!EDITSTATEPTR(wndPtr)) && (msg != WM_CREATE))
-		return DefWindowProc16(hwnd, msg, wParam, lParam);
+		return DefWindowProc32A(hwnd, msg, wParam, lParam);
 
 	switch (msg) {
-	case EM_CANUNDO:
-		DPRINTF_EDIT_MSG("EM_CANUNDO");
-		lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam);
-		break;
-	case EM_EMPTYUNDOBUFFER:
-		DPRINTF_EDIT_MSG("EM_EMPTYUNDOBUFFER");
-		lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam);
-		break;
-	case EM_FMTLINES:
-		DPRINTF_EDIT_MSG("EM_FMTLINES");
-		lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam);
-		break;
-	case EM_GETFIRSTVISIBLELINE:
-		DPRINTF_EDIT_MSG("EM_GETFIRSTVISIBLELINE");
-		lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam);
-		break;
-	case EM_GETHANDLE:
-		DPRINTF_EDIT_MSG("EM_GETHANDLE");
-		lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam);
-		break;
-	case EM_GETLINE:
-		DPRINTF_EDIT_MSG("EM_GETLINE");
-		lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam);
-		break;
-	case EM_GETLINECOUNT:
-		DPRINTF_EDIT_MSG("EM_GETLINECOUNT");
-		lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam);
-		break;
-	case EM_GETMODIFY:
-		DPRINTF_EDIT_MSG("EM_GETMODIFY");
-		lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam);
-		break;
-	case EM_GETPASSWORDCHAR:
-		DPRINTF_EDIT_MSG("EM_GETPASSWORDCHAR");
-		lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam);
-		break;
-	case EM_GETRECT:
-		DPRINTF_EDIT_MSG("EM_GETRECT");
-		lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam);
-		break;
-	case EM_GETSEL:
-		DPRINTF_EDIT_MSG("EM_GETSEL");
+	case EM_GETSEL16:
+		DPRINTF_EDIT_MSG16("EM_GETSEL");
+		wParam = 0;
+		lParam = 0;
+		/* fall through */
+	case EM_GETSEL32:
+		DPRINTF_EDIT_MSG32("EM_GETSEL");
 		lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam);
 		break;
-	case EM_GETTHUMB:
-		DPRINTF_EDIT_MSG("EM_GETTHUMB");
-		lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam);
+
+	case EM_SETSEL16:
+		DPRINTF_EDIT_MSG16("EM_SETSEL");
+		lResult = EDIT_EM_SetSel16(wndPtr, wParam, lParam);
 		break;
-	case EM_GETWORDBREAKPROC:
-		DPRINTF_EDIT_MSG("EM_GETWORDBREAKPROC");
-		lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam);
-		break;
-	case EM_LIMITTEXT:
-		DPRINTF_EDIT_MSG("EM_LIMITTEXT");
-		lResult = EDIT_EM_LimitText(wndPtr, wParam, lParam);
-		break;
-	case EM_LINEFROMCHAR:
-		DPRINTF_EDIT_MSG("EM_LINEFROMCHAR");
-		lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam);
-		break;
-	case EM_LINEINDEX:
-		DPRINTF_EDIT_MSG("EM_LINEINDEX");
-		lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam);
-		break;
-	case EM_LINELENGTH:
-		DPRINTF_EDIT_MSG("EM_LINELENGTH");
-		lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam);
-		break;
-	case EM_LINESCROLL:
-		DPRINTF_EDIT_MSG("EM_LINESCROLL");
-		lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam);
-		break;
-	case EM_REPLACESEL:
-		DPRINTF_EDIT_MSG("EM_REPLACESEL");
-		lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam);
-		break;
-	case EM_SCROLL:
-		DPRINTF_EDIT_MSG("EM_SCROLL");
-		lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam);
- 		break;
-	case EM_SETHANDLE:
-		DPRINTF_EDIT_MSG("EM_SETHANDLE");
-		lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam);
-		break;
-	case EM_SETMODIFY:
-		DPRINTF_EDIT_MSG("EM_SETMODIFY");
-		lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam);
-		break;
-	case EM_SETPASSWORDCHAR:
-		DPRINTF_EDIT_MSG("EM_SETPASSWORDCHAR");
-		lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam);
-		break;
-	case EM_SETREADONLY:
-		DPRINTF_EDIT_MSG("EM_SETREADONLY");
-		lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam);
- 		break;
-	case EM_SETRECT:
-		DPRINTF_EDIT_MSG("EM_SETRECT");
-		lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam);
-		break;
-	case EM_SETRECTNP:
-		DPRINTF_EDIT_MSG("EM_SETRECTNP");
-		lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam);
-		break;
-	case EM_SETSEL:
-		DPRINTF_EDIT_MSG("EM_SETSEL");
+	case EM_SETSEL32:
+		DPRINTF_EDIT_MSG32("EM_SETSEL");
 		lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam);
 		break;
-	case EM_SETTABSTOPS:
-		DPRINTF_EDIT_MSG("EM_SETTABSTOPS");
-		lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam);
+
+	case EM_GETRECT16:
+		DPRINTF_EDIT_MSG16("EM_GETRECT");
+		lResult = EDIT_EM_GetRect16(wndPtr, wParam, lParam);
 		break;
-	case EM_SETWORDBREAKPROC:
-		DPRINTF_EDIT_MSG("EM_SETWORDBREAKPROC");
-		lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam);
+	case EM_GETRECT32:
+		DPRINTF_EDIT_MSG32("EM_GETRECT");
+		lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam);
 		break;
-	case EM_UNDO:
+
+	case EM_SETRECT16:
+		DPRINTF_EDIT_MSG16("EM_SETRECT");
+		/* fall through */
+	case EM_SETRECT32:
+		DPRINTF_EDIT_MSG32("EM_SETRECT");
+		lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam);
+		break;
+
+	case EM_SETRECTNP16:
+		DPRINTF_EDIT_MSG16("EM_SETRECTNP");
+		/* fall through */
+	case EM_SETRECTNP32:
+		DPRINTF_EDIT_MSG32("EM_SETRECTNP");
+		lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam);
+		break;
+
+	case EM_SCROLL16:
+		DPRINTF_EDIT_MSG16("EM_SCROLL");
+		/* fall through */
+	case EM_SCROLL32:
+		DPRINTF_EDIT_MSG32("EM_SCROLL");
+		lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam);
+ 		break;
+
+	case EM_LINESCROLL16:
+		DPRINTF_EDIT_MSG16("EM_LINESCROLL");
+		wParam = (WPARAM32)(INT32)(INT16)HIWORD(lParam);
+		lParam = (LPARAM)(INT32)(INT16)LOWORD(lParam);
+		/* fall through */
+	case EM_LINESCROLL32:
+		DPRINTF_EDIT_MSG32("EM_LINESCROLL");
+		lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam);
+		break;
+
+	case EM_SCROLLCARET16:
+		DPRINTF_EDIT_MSG16("EM_SCROLLCARET");
+		/* fall through */
+	case EM_SCROLLCARET32:
+		DPRINTF_EDIT_MSG32("EM_SCROLLCARET");
+		lResult = EDIT_EM_ScrollCaret(wndPtr, wParam, lParam);
+		break;
+
+	case EM_GETMODIFY16:
+		DPRINTF_EDIT_MSG16("EM_GETMODIFY");
+		/* fall through */
+	case EM_GETMODIFY32:
+		DPRINTF_EDIT_MSG32("EM_GETMODIFY");
+		lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam);
+		break;
+
+	case EM_SETMODIFY16:
+		DPRINTF_EDIT_MSG16("EM_SETMODIFY");
+		/* fall through */
+	case EM_SETMODIFY32:
+		DPRINTF_EDIT_MSG32("EM_SETMODIFY");
+		lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam);
+		break;
+
+	case EM_GETLINECOUNT16:
+		DPRINTF_EDIT_MSG16("EM_GETLINECOUNT");
+		/* fall through */
+	case EM_GETLINECOUNT32:
+		DPRINTF_EDIT_MSG32("EM_GETLINECOUNT");
+		lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam);
+		break;
+
+	case EM_LINEINDEX16:
+		DPRINTF_EDIT_MSG16("EM_LINEINDEX");
+		/* fall through */
+	case EM_LINEINDEX32:
+		DPRINTF_EDIT_MSG32("EM_LINEINDEX");
+		lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam);
+		break;
+
+	case EM_SETHANDLE16:
+		DPRINTF_EDIT_MSG16("EM_SETHANDLE");
+		lResult = EDIT_EM_SetHandle16(wndPtr, wParam, lParam);
+		break;
+	case EM_SETHANDLE32:
+		DPRINTF_EDIT_MSG32("EM_SETHANDLE");
+		lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam);
+		break;
+
+	case EM_GETHANDLE16:
+		DPRINTF_EDIT_MSG16("EM_GETHANDLE");
+		lResult = EDIT_EM_GetHandle16(wndPtr, wParam, lParam);
+		break;
+	case EM_GETHANDLE32:
+		DPRINTF_EDIT_MSG32("EM_GETHANDLE");
+		lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam);
+		break;
+
+	case EM_GETTHUMB16:
+		DPRINTF_EDIT_MSG16("EM_GETTHUMB");
+		/* fall through */
+	case EM_GETTHUMB32:
+		DPRINTF_EDIT_MSG32("EM_GETTHUMB");
+		lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam);
+		break;
+
+	/* messages 0x00bf and 0x00c0 missing from specs */
+
+	case WM_USER+15:
+		DPRINTF_EDIT_MSG16("undocumented WM_USER+15, please report");
+		/* fall through */
+	case 0x00bf:
+		DPRINTF_EDIT_MSG32("undocumented 0x00bf, please report");
+		lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
+		break;
+
+	case WM_USER+16:
+		DPRINTF_EDIT_MSG16("undocumented WM_USER+16, please report");
+		/* fall through */
+	case 0x00c0:
+		DPRINTF_EDIT_MSG32("undocumented 0x00c0, please report");
+		lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
+		break;
+
+	case EM_LINELENGTH16:
+		DPRINTF_EDIT_MSG16("EM_LINELENGTH");
+		/* fall through */
+	case EM_LINELENGTH32:
+		DPRINTF_EDIT_MSG32("EM_LINELENGTH");
+		lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam);
+		break;
+
+	case EM_REPLACESEL16:
+		DPRINTF_EDIT_MSG16("EM_REPLACESEL");
+		lParam = (LPARAM)PTR_SEG_TO_LIN((SEGPTR)lParam);
+		/* fall through */
+	case EM_REPLACESEL32:
+		DPRINTF_EDIT_MSG32("EM_REPLACESEL");
+		lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam);
+		break;
+
+	/* message 0x00c3 missing from specs */
+
+	case WM_USER+19:
+		DPRINTF_EDIT_MSG16("undocumented WM_USER+19, please report");
+		/* fall through */
+	case 0x00c3:
+		DPRINTF_EDIT_MSG32("undocumented 0x00c3, please report");
+		lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
+		break;
+
+	case EM_GETLINE16:
+		DPRINTF_EDIT_MSG16("EM_GETLINE");
+		lParam = (LPARAM)PTR_SEG_TO_LIN((SEGPTR)lParam);
+		/* fall through */
+	case EM_GETLINE32:
+		DPRINTF_EDIT_MSG32("EM_GETLINE");
+		lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam);
+		break;
+
+	case EM_LIMITTEXT16:
+		DPRINTF_EDIT_MSG16("EM_LIMITTEXT");
+		/* fall through */
+	case EM_SETLIMITTEXT32:
+		DPRINTF_EDIT_MSG32("EM_SETLIMITTEXT");
+		lResult = EDIT_EM_SetLimitText(wndPtr, wParam, lParam);
+		break;
+
+	case EM_CANUNDO16:
+		DPRINTF_EDIT_MSG16("EM_CANUNDO");
+		/* fall through */
+	case EM_CANUNDO32:
+		DPRINTF_EDIT_MSG32("EM_CANUNDO");
+		lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam);
+		break;
+
+	case EM_UNDO16:
+		DPRINTF_EDIT_MSG16("EM_UNDO");
+		/* fall through */
+	case EM_UNDO32:
+		/* fall through */
 	case WM_UNDO:
-		DPRINTF_EDIT_MSG("EM_UNDO / WM_UNDO");
+		DPRINTF_EDIT_MSG32("EM_UNDO / WM_UNDO");
 		lResult = EDIT_EM_Undo(wndPtr, wParam, lParam);
 		break;
+
+	case EM_FMTLINES16:
+		DPRINTF_EDIT_MSG16("EM_FMTLINES");
+		/* fall through */
+	case EM_FMTLINES32:
+		DPRINTF_EDIT_MSG32("EM_FMTLINES");
+		lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam);
+		break;
+
+	case EM_LINEFROMCHAR16:
+		DPRINTF_EDIT_MSG16("EM_LINEFROMCHAR");
+		/* fall through */
+	case EM_LINEFROMCHAR32:
+		DPRINTF_EDIT_MSG32("EM_LINEFROMCHAR");
+		lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam);
+		break;
+
+	/* message 0x00ca missing from specs */
+
+	case WM_USER+26:
+		DPRINTF_EDIT_MSG16("undocumented WM_USER+26, please report");
+		/* fall through */
+	case 0x00ca:
+		DPRINTF_EDIT_MSG32("undocumented 0x00ca, please report");
+		lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
+		break;
+
+	case EM_SETTABSTOPS16:
+		DPRINTF_EDIT_MSG16("EM_SETTABSTOPS");
+		lResult = EDIT_EM_SetTabStops16(wndPtr, wParam, lParam);
+		break;
+	case EM_SETTABSTOPS32:
+		DPRINTF_EDIT_MSG32("EM_SETTABSTOPS");
+		lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam);
+		break;
+
+	case EM_SETPASSWORDCHAR16:
+		DPRINTF_EDIT_MSG16("EM_SETPASSWORDCHAR");
+		/* fall through */
+	case EM_SETPASSWORDCHAR32:
+		DPRINTF_EDIT_MSG32("EM_SETPASSWORDCHAR");
+		lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam);
+		break;
+
+	case EM_EMPTYUNDOBUFFER16:
+		DPRINTF_EDIT_MSG16("EM_EMPTYUNDOBUFFER");
+		/* fall through */
+	case EM_EMPTYUNDOBUFFER32:
+		DPRINTF_EDIT_MSG32("EM_EMPTYUNDOBUFFER");
+		lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam);
+		break;
+
+	case EM_GETFIRSTVISIBLELINE16:
+		DPRINTF_EDIT_MSG16("EM_GETFIRSTVISIBLELINE");
+		/* fall through */
+	case EM_GETFIRSTVISIBLELINE32:
+		DPRINTF_EDIT_MSG32("EM_GETFIRSTVISIBLELINE");
+		lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam);
+		break;
+
+	case EM_SETREADONLY16:
+		DPRINTF_EDIT_MSG16("EM_SETREADONLY");
+		/* fall through */
+	case EM_SETREADONLY32:
+		DPRINTF_EDIT_MSG32("EM_SETREADONLY");
+		lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam);
+ 		break;
+
+	case EM_SETWORDBREAKPROC16:
+		DPRINTF_EDIT_MSG16("EM_SETWORDBREAKPROC");
+		/* fall through */
+	case EM_SETWORDBREAKPROC32:
+		DPRINTF_EDIT_MSG32("EM_SETWORDBREAKPROC");
+		lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam);
+		break;
+
+	case EM_GETWORDBREAKPROC16:
+		DPRINTF_EDIT_MSG16("EM_GETWORDBREAKPROC");
+		/* fall through */
+	case EM_GETWORDBREAKPROC32:
+		DPRINTF_EDIT_MSG32("EM_GETWORDBREAKPROC");
+		lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam);
+		break;
+
+	case EM_GETPASSWORDCHAR16:
+		DPRINTF_EDIT_MSG16("EM_GETPASSWORDCHAR");
+		/* fall through */
+	case EM_GETPASSWORDCHAR32:
+		DPRINTF_EDIT_MSG32("EM_GETPASSWORDCHAR");
+		lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam);
+		break;
+
+	/* The following EM_xxx are new to win95 and don't exist for 16 bit */
+
+	case EM_SETMARGINS32:
+		DPRINTF_EDIT_MSG16("EM_SETMARGINS");
+		lResult = EDIT_EM_SetMargins(wndPtr, wParam, lParam);
+		break;
+
+	case EM_GETMARGINS32:
+		DPRINTF_EDIT_MSG16("EM_GETMARGINS");
+		lResult = EDIT_EM_GetMargins(wndPtr, wParam, lParam);
+		break;
+
+	case EM_GETLIMITTEXT32:
+		DPRINTF_EDIT_MSG16("EM_GETLIMITTEXT");
+		lResult = EDIT_EM_GetLimitText(wndPtr, wParam, lParam);
+		break;
+
+	case EM_POSFROMCHAR32:
+		DPRINTF_EDIT_MSG16("EM_POSFROMCHAR");
+		lResult = EDIT_EM_PosFromChar(wndPtr, wParam, lParam);
+		break;
+
+	case EM_CHARFROMPOS32:
+		DPRINTF_EDIT_MSG16("EM_CHARFROMPOS");
+		lResult = EDIT_EM_CharFromPos(wndPtr, wParam, lParam);
+		break;
+
 	case WM_GETDLGCODE:
-		DPRINTF_EDIT_MSG("WM_GETDLGCODE");
+		DPRINTF_EDIT_MSG32("WM_GETDLGCODE");
 		lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam);
 		break;
+
 	case WM_CHAR:
-		DPRINTF_EDIT_MSG("WM_CHAR");
+		DPRINTF_EDIT_MSG32("WM_CHAR");
 		lResult = EDIT_WM_Char(wndPtr, wParam, lParam);
 		break;
+
 	case WM_CLEAR:
-		DPRINTF_EDIT_MSG("WM_CLEAR");
+		DPRINTF_EDIT_MSG32("WM_CLEAR");
 		lResult = EDIT_WM_Clear(wndPtr, wParam, lParam);
 		break;
+
 	case WM_COPY:
-		DPRINTF_EDIT_MSG("WM_COPY");
+		DPRINTF_EDIT_MSG32("WM_COPY");
 		lResult = EDIT_WM_Copy(wndPtr, wParam, lParam);
 		break;
+
 	case WM_CREATE:
-		DPRINTF_EDIT_MSG("WM_CREATE");
+		DPRINTF_EDIT_MSG32("WM_CREATE");
 		lResult = EDIT_WM_Create(wndPtr, wParam, lParam);
 		break;
+
 	case WM_CUT:
-		DPRINTF_EDIT_MSG("WM_CUT");
+		DPRINTF_EDIT_MSG32("WM_CUT");
 		lResult = EDIT_WM_Cut(wndPtr, wParam, lParam);
 		break;
+
 	case WM_DESTROY:
-		DPRINTF_EDIT_MSG("WM_DESTROY");
+		DPRINTF_EDIT_MSG32("WM_DESTROY");
 		lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam);
 		break;
+
 	case WM_ENABLE:
-		DPRINTF_EDIT_MSG("WM_ENABLE");
+		DPRINTF_EDIT_MSG32("WM_ENABLE");
 		lResult = EDIT_WM_Enable(wndPtr, wParam, lParam);
 		break;
+
 	case WM_ERASEBKGND:
-		DPRINTF_EDIT_MSG("WM_ERASEBKGND");
+		DPRINTF_EDIT_MSG32("WM_ERASEBKGND");
 		lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam);
 		break;
+
 	case WM_GETFONT:
-		DPRINTF_EDIT_MSG("WM_GETFONT");
+		DPRINTF_EDIT_MSG32("WM_GETFONT");
 		lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam);
 		break;
+
 	case WM_GETTEXT:
-		DPRINTF_EDIT_MSG("WM_GETTEXT");
+		DPRINTF_EDIT_MSG32("WM_GETTEXT");
 		lResult = EDIT_WM_GetText(wndPtr, wParam, lParam);
 		break;
+
 	case WM_GETTEXTLENGTH:
-		DPRINTF_EDIT_MSG("WM_GETTEXTLENGTH");
+		DPRINTF_EDIT_MSG32("WM_GETTEXTLENGTH");
 		lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam);
 		break;
+
 	case WM_HSCROLL:
-		DPRINTF_EDIT_MSG("WM_HSCROLL");
+		DPRINTF_EDIT_MSG32("WM_HSCROLL");
 		lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam);
 		break;
+
 	case WM_KEYDOWN:
-		DPRINTF_EDIT_MSG("WM_KEYDOWN");
+		DPRINTF_EDIT_MSG32("WM_KEYDOWN");
 		lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam);
 		break;
+
 	case WM_KILLFOCUS:
-		DPRINTF_EDIT_MSG("WM_KILLFOCUS");
+		DPRINTF_EDIT_MSG32("WM_KILLFOCUS");
 		lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam);
 		break;
+
 	case WM_LBUTTONDBLCLK:
-		DPRINTF_EDIT_MSG("WM_LBUTTONDBLCLK");
+		DPRINTF_EDIT_MSG32("WM_LBUTTONDBLCLK");
 		lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam);
 		break;
+
 	case WM_LBUTTONDOWN:
-		DPRINTF_EDIT_MSG("WM_LBUTTONDOWN");
+		DPRINTF_EDIT_MSG32("WM_LBUTTONDOWN");
 		lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam);
 		break;
+
 	case WM_LBUTTONUP:
-		DPRINTF_EDIT_MSG("WM_LBUTTONUP");
+		DPRINTF_EDIT_MSG32("WM_LBUTTONUP");
 		lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam);
 		break;
+
 	case WM_MOUSEMOVE:
 		/*
-		 *	DPRINTF_EDIT_MSG("WM_MOUSEMOVE");
+		 *	DPRINTF_EDIT_MSG32("WM_MOUSEMOVE");
 		 */
 		lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam);
 		break;
+
 	case WM_PAINT:
-		DPRINTF_EDIT_MSG("WM_PAINT");
+		DPRINTF_EDIT_MSG32("WM_PAINT");
 		lResult = EDIT_WM_Paint(wndPtr, wParam, lParam);
 		break;
+
 	case WM_PASTE:
-		DPRINTF_EDIT_MSG("WM_PASTE");
+		DPRINTF_EDIT_MSG32("WM_PASTE");
 		lResult = EDIT_WM_Paste(wndPtr, wParam, lParam);
 		break;
+
 	case WM_SETCURSOR:
 		/*
-		 *	DPRINTF_EDIT_MSG("WM_SETCURSOR");
+		 *	DPRINTF_EDIT_MSG32("WM_SETCURSOR");
 		 */
 		lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam);
 		break;
+
 	case WM_SETFOCUS:
-		DPRINTF_EDIT_MSG("WM_SETFOCUS");
+		DPRINTF_EDIT_MSG32("WM_SETFOCUS");
 		lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam);
 		break;
+
 	case WM_SETFONT:
-		DPRINTF_EDIT_MSG("WM_SETFONT");
+		DPRINTF_EDIT_MSG32("WM_SETFONT");
 		lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam);
 		break;
+
 	case WM_SETREDRAW:
-		DPRINTF_EDIT_MSG("WM_SETREDRAW");
+		DPRINTF_EDIT_MSG32("WM_SETREDRAW");
 		lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam);
 		break;
+
 	case WM_SETTEXT:
-		DPRINTF_EDIT_MSG("WM_SETTEXT");
+		DPRINTF_EDIT_MSG32("WM_SETTEXT");
 		lResult = EDIT_WM_SetText(wndPtr, wParam, lParam);
 		break;
+
 	case WM_SIZE:
-		DPRINTF_EDIT_MSG("WM_SIZE");
+		DPRINTF_EDIT_MSG32("WM_SIZE");
 		lResult = EDIT_WM_Size(wndPtr, wParam, lParam);
 		break;
+
 	case WM_VSCROLL:
-		DPRINTF_EDIT_MSG("WM_VSCROLL");
+		DPRINTF_EDIT_MSG32("WM_VSCROLL");
 		lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam);
 		break;
+
 	default:
-		lResult = DefWindowProc16(hwnd, msg, wParam, lParam);
+		lResult = DefWindowProc32A(hwnd, msg, wParam, lParam);
 		break;
 	}
 	EDIT_ReleasePointer(wndPtr);
@@ -503,28 +798,28 @@
 static void EDIT_BuildLineDefs(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	char *text = EDIT_GetPasswordPointer(wndPtr);
-	int ww = EDIT_GetWndWidth(wndPtr);
+	LPSTR text = EDIT_GetPasswordPointer(wndPtr);
+	INT32 ww = EDIT_GetWndWidth(wndPtr);
 	HDC32 hdc;
-	HFONT16 hFont;
+	HFONT32 hFont;
 	HFONT32 oldFont = 0;
-	char *start, *cp;
-	int prev, next;
-	int width;
-	int length;
+	LPSTR start, cp;
+	INT32 prev, next;
+	INT32 width;
+	INT32 length;
 	LINE_END ending;
 
 	hdc = GetDC32(wndPtr->hwndSelf);
-	hFont = (HFONT16)EDIT_WM_GetFont(wndPtr, 0, 0L);
+	hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
 	if (hFont) oldFont = SelectObject32(hdc, hFont);
 
 	if (!IsMultiLine(wndPtr)) {
 		es->LineCount = 1;
 		es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF));
 		es->LineDefs[0].offset = 0;
-		es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
+		es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0);
 		es->LineDefs[0].ending = END_0;
-		es->TextWidth = LOWORD(GetTabbedTextExtent(hdc, text,
+		es->TextWidth = (INT32)LOWORD(GetTabbedTextExtent(hdc, text,
 					es->LineDefs[0].length,
 					es->NumTabStops, es->TabStops));
 	} else {
@@ -533,7 +828,7 @@
 		do {
 			if (!(cp = strstr(start, "\r\n"))) {
 				ending = END_0;
-				length = strlen(start);
+				length = lstrlen32A(start);
 			} else if ((cp > start) && (*(cp - 1) == '\r')) {
 				ending = END_SOFT;
 				length = cp - start - 1;
@@ -541,7 +836,7 @@
 				ending = END_HARD;
 				length = cp - start;
 			}
-			width = LOWORD(GetTabbedTextExtent(hdc, start, length,
+			width = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, length,
 						es->NumTabStops, es->TabStops));
 
 			if (IsWordWrap(wndPtr) && (width > ww)) {
@@ -550,7 +845,7 @@
 					prev = next;
 					next = EDIT_CallWordBreakProc(wndPtr, start,
 							prev + 1, length, WB_RIGHT);
-					width = LOWORD(GetTabbedTextExtent(hdc, start, next,
+					width = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, next,
 							es->NumTabStops, es->TabStops));
 				} while (width <= ww);
 				if (!prev) {
@@ -558,7 +853,7 @@
 					do {
 						prev = next;
 						next++;
-						width = LOWORD(GetTabbedTextExtent(hdc, start, next,
+						width = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, next,
 								es->NumTabStops, es->TabStops));
 					} while (width <= ww);
 					if(!prev) prev = 1;
@@ -570,7 +865,7 @@
 					ending = END_DELIMIT;
 				} else
 					ending = END_NONE;
-				width = LOWORD(GetTabbedTextExtent(hdc, start, length,
+				width = (INT32)LOWORD(GetTabbedTextExtent(hdc, start, length,
 							es->NumTabStops, es->TabStops));
 			}
 
@@ -610,24 +905,28 @@
  *
  *	Call appropriate WordBreakProc (internal or external).
  *
+ *	FIXME: Heavily broken now that we have a LOCAL32 buffer.
+ *	External wordbreak functions have been disabled in
+ *	EM_SETWORDBREAKPROC.
+ *
  */
-static INT EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action)
+static INT32 EDIT_CallWordBreakProc(WND *wndPtr, LPSTR s, INT32 index, INT32 count, INT32 action)
 {
-    EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0L);
-
-    if (!wbp) return EDIT_WordBreakProc(s, index, count, action);
-    else
-    {
-        /* We need a SEGPTR here */
-
-        EDITSTATE *es = EDITSTATEPTR(wndPtr);
-        SEGPTR ptr = LOCAL_LockSegptr( wndPtr->hInstance, es->hBuf ) +
-                     (UINT16)(s - EDIT_GetPointer(wndPtr));
-        INT ret = CallWordBreakProc( (FARPROC16)wbp, ptr,
-                                     index, count, action);
-        LOCAL_Unlock( wndPtr->hInstance, es->hBuf );
-        return ret;
-    }
+	return EDIT_WordBreakProc(s, index, count, action);
+/*
+ *	EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0);
+ *
+ *	if (!wbp) return EDIT_WordBreakProc(s, index, count, action);
+ *	else {
+ *		EDITSTATE *es = EDITSTATEPTR(wndPtr);
+ *		SEGPTR ptr = LOCAL_LockSegptr( wndPtr->hInstance, es->hBuf16 ) +
+ *			(INT16)(s - EDIT_GetPointer(wndPtr));
+ *		INT ret = CallWordBreakProc( (FARPROC16)wbp, ptr,
+ *						index, count, action);
+ *		LOCAL_Unlock( wndPtr->hInstance, es->hBuf16 );
+ *		return ret;
+ *	}
+ */
 }
 
 
@@ -638,12 +937,12 @@
  *	Calculates, for a given line and X-coordinate on the screen, the column.
  *
  */
-static UINT EDIT_ColFromWndX(WND *wndPtr, UINT line, INT x)
-{	
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
-	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
-	UINT i;
+static INT32 EDIT_ColFromWndX(WND *wndPtr, INT32 line, INT32 x)
+{
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
+	INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
+	INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
+	INT32 i;
 
 	line = MAX(0, MIN(line, lc - 1));
 	for (i = 0 ; i < ll ; i++)
@@ -662,9 +961,9 @@
  */
 static void EDIT_DelEnd(WND *wndPtr)
 {
-	EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
+	EDIT_EM_SetSel(wndPtr, -1, 0);
 	EDIT_MoveEnd(wndPtr, TRUE);
-	EDIT_WM_Clear(wndPtr, 0, 0L);
+	EDIT_WM_Clear(wndPtr, 0, 0);
 }
 
 
@@ -677,9 +976,9 @@
  */
 static void EDIT_DelLeft(WND *wndPtr)
 {
-	EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
+	EDIT_EM_SetSel(wndPtr, -1, 0);
 	EDIT_MoveBackward(wndPtr, TRUE);
-	EDIT_WM_Clear(wndPtr, 0, 0L);
+	EDIT_WM_Clear(wndPtr, 0, 0);
 }
 
 
@@ -692,9 +991,9 @@
  */
 static void EDIT_DelRight(WND *wndPtr)
 {
-	EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
+	EDIT_EM_SetSel(wndPtr, -1, 0);
 	EDIT_MoveForward(wndPtr, TRUE);
-	EDIT_WM_Clear(wndPtr, 0, 0L);
+	EDIT_WM_Clear(wndPtr, 0, 0);
 }
 
 
@@ -703,10 +1002,10 @@
  *	EDIT_GetAveCharWidth
  *
  */
-static UINT EDIT_GetAveCharWidth(WND *wndPtr)
+static INT32 EDIT_GetAveCharWidth(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	
+
 	return es->AveCharWidth;
 }
 
@@ -716,10 +1015,10 @@
  *	EDIT_GetLineHeight
  *
  */
-static UINT EDIT_GetLineHeight(WND *wndPtr)
+static INT32 EDIT_GetLineHeight(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	
+
 	return es->LineHeight;
 }
 
@@ -732,12 +1031,12 @@
  *	column to an ending column.
  *
  */
-static void EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT ecol, LPRECT16 rc)
+static void EDIT_GetLineRect(WND *wndPtr, INT32 line, INT32 scol, INT32 ecol, LPRECT32 rc)
 {
 	rc->top = EDIT_WndYFromLine(wndPtr, line);
 	rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr);
 	rc->left = EDIT_WndXFromCol(wndPtr, line, scol);
-	rc->right = ((INT)ecol == -1) ? EDIT_GetWndWidth(wndPtr) :
+	rc->right = (ecol == -1) ? EDIT_GetWndWidth(wndPtr) :
 				EDIT_WndXFromCol(wndPtr, line, ecol);
 }
 
@@ -750,12 +1049,16 @@
  *	you can call it whenever you like, without unlocking.
  *
  */
-static char *EDIT_GetPointer(WND *wndPtr)
+static LPSTR EDIT_GetPointer(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	
-	if (!es->text && es->hBuf)
-		es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf);
+
+	if (!es->text && (es->hBuf32 || es->hBuf16)) {
+		if (es->hBuf32)
+			es->text = (LPSTR)LocalLock32(es->hBuf32);
+		else
+			es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf16);
+	}
 	return es->text;
 }
 
@@ -766,11 +1069,11 @@
  *
  *
  */
-static char *EDIT_GetPasswordPointer(WND *wndPtr)
+static LPSTR EDIT_GetPasswordPointer(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	char *text = xstrdup(EDIT_GetPointer(wndPtr));
-	char *p;
+	LPSTR text = xstrdup(EDIT_GetPointer(wndPtr));
+	LPSTR p;
 
 	if(es->PasswordChar) {
 		p = text;
@@ -786,26 +1089,10 @@
 
 /*********************************************************************
  *
- *	EDIT_GetRect
- *
- *	Beware: This is not the function called on EM_GETRECT.
- *	It expects a (LPRECT) in lParam, not a (SEGPTR).
- *	It is used internally, as if there were no pointer difficulties.
- *
- */
-static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
-{
-	GetClientRect16( wndPtr->hwndSelf, (LPRECT16)lParam );
-	return 0L;
-}
-
-
-/*********************************************************************
- *
  *	EDIT_GetRedraw
  *
  */
-static BOOL EDIT_GetRedraw(WND *wndPtr)
+static BOOL32 EDIT_GetRedraw(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -818,26 +1105,29 @@
  *	EDIT_GetSel
  *
  *	Beware: This is not the function called on EM_GETSEL.
- *	It returns the start in the low word and the end in the high word.
- *	NB s can be greater than e.
+ *	(because s can be greater than e).
  *
  */
-static LRESULT EDIT_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+static void EDIT_GetSel(WND *wndPtr, LPINT32 s, LPINT32 e)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-	return MAKELONG(es->SelStart, es->SelEnd);
+	if (s)
+		*s = es->SelStart;
+	if (e)
+		*e = es->SelEnd;
 }
 
+
 /*********************************************************************
  *
  *	EDIT_GetTextWidth
  *
  */
-static UINT EDIT_GetTextWidth(WND *wndPtr)
+static INT32 EDIT_GetTextWidth(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	
+
 	return es->TextWidth;
 }
 
@@ -847,11 +1137,11 @@
  *	EDIT_GetVisibleLineCount
  *
  */
-static UINT EDIT_GetVisibleLineCount(WND *wndPtr)
+static INT32 EDIT_GetVisibleLineCount(WND *wndPtr)
 {
-	RECT16 rc;
-	
-	EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
+	RECT32 rc;
+
+	EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rc);
 	return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr));
 }
 
@@ -861,11 +1151,11 @@
  *	EDIT_GetWndWidth
  *
  */
-static UINT EDIT_GetWndWidth(WND *wndPtr)
+static INT32 EDIT_GetWndWidth(WND *wndPtr)
 {
-	RECT16 rc;
-	
-	EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
+	RECT32 rc;
+
+	EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rc);
 	return rc.right - rc.left;
 }
 
@@ -875,10 +1165,10 @@
  *	EDIT_GetXOffset
  *
  */
-static UINT EDIT_GetXOffset(WND *wndPtr)
+static INT32 EDIT_GetXOffset(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	
+
 	return es->XOffset;
 }
 
@@ -894,64 +1184,64 @@
  *	start and end need not be ordered.
  *
  */
-static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end)
+static void EDIT_InvalidateText(WND *wndPtr, INT32 start, INT32 end)
 {
-	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
-	UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
-	UINT sl;
-	UINT el;
-	UINT sc;
-	UINT ec;
-	RECT16 rcWnd;
-	RECT16 rcLine;
-	RECT16 rcUpdate;
-	UINT l;
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
+	INT32 sl;
+	INT32 el;
+	INT32 sc;
+	INT32 ec;
+	RECT32 rcWnd;
+	RECT32 rcLine;
+	RECT32 rcUpdate;
+	INT32 l;
 
 	if (end == start )
 		return;
 
-	if ((INT)end == -1)
-		end = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
-	ORDER_UINT(start, end);
-	sl = (UINT)EDIT_EM_LineFromChar(wndPtr, start, 0L);
-	el = (UINT)EDIT_EM_LineFromChar(wndPtr, end, 0L);
+	if (end == -1)
+		end = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
+	ORDER_INT32(start, end);
+	sl = (INT32)EDIT_EM_LineFromChar(wndPtr, start, 0);
+	el = (INT32)EDIT_EM_LineFromChar(wndPtr, end, 0);
 	if ((el < fv) || (sl > fv + vlc))
 		return;
 
-	sc = start - (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L);
-	ec = end - (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
+	sc = start - (INT32)EDIT_EM_LineIndex(wndPtr, sl, 0);
+	ec = end - (INT32)EDIT_EM_LineIndex(wndPtr, el, 0);
 	if (sl < fv) {
 		sl = fv;
 		sc = 0;
 	}
 	if (el > fv + vlc) {
 		el = fv + vlc;
-		ec = (UINT)EDIT_EM_LineLength(wndPtr,
-				(UINT)EDIT_EM_LineIndex(wndPtr, el, 0L), 0L);
+		ec = (INT32)EDIT_EM_LineLength(wndPtr,
+				(INT32)EDIT_EM_LineIndex(wndPtr, el, 0), 0);
 	}
-	EDIT_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
+	EDIT_EM_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
 	if (sl == el) {
 		EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine);
-		if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
-			InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
+		if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
+			InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
 	} else {
 		EDIT_GetLineRect(wndPtr, sl, sc,
-				(UINT)EDIT_EM_LineLength(wndPtr,
-					(UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L), 0L),
+				(INT32)EDIT_EM_LineLength(wndPtr,
+					(INT32)EDIT_EM_LineIndex(wndPtr, sl, 0), 0),
 				&rcLine);
-		if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
-			InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
+		if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
+			InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
 		for (l = sl + 1 ; l < el ; l++) {
 			EDIT_GetLineRect(wndPtr, l, 0,
-				(UINT)EDIT_EM_LineLength(wndPtr,
-					(UINT)EDIT_EM_LineIndex(wndPtr, l, 0L), 0L),
+				(INT32)EDIT_EM_LineLength(wndPtr,
+					(INT32)EDIT_EM_LineIndex(wndPtr, l, 0), 0),
 				&rcLine);
-			if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
-				InvalidateRect16(wndPtr->hwndSelf, &rcUpdate, FALSE);
+			if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
+				InvalidateRect32(wndPtr->hwndSelf, &rcUpdate, FALSE);
 		}
 		EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine);
-		if (IntersectRect16(&rcUpdate, &rcWnd, &rcLine))
-			InvalidateRect16( wndPtr->hwndSelf, &rcUpdate, FALSE );
+		if (IntersectRect32(&rcUpdate, &rcWnd, &rcLine))
+			InvalidateRect32( wndPtr->hwndSelf, &rcUpdate, FALSE );
 	}
 }
 
@@ -963,11 +1253,11 @@
  *	Calculates, for a given Y-coordinate on the screen, the line.
  *
  */
-static UINT EDIT_LineFromWndY(WND *wndPtr, INT y)
+static INT32 EDIT_LineFromWndY(WND *wndPtr, INT32 y)
 {
-	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
-	UINT lh = EDIT_GetLineHeight(wndPtr);
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 lh = EDIT_GetLineHeight(wndPtr);
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
 
 	return MAX(0, MIN(lc - 1, y / lh + fv));
 }
@@ -980,9 +1270,11 @@
  *	Try to fit size + 1 bytes in the buffer.  Constrain to limits.
  *
  */
-static BOOL EDIT_MakeFit(WND *wndPtr, UINT size)
+static BOOL32 EDIT_MakeFit(WND *wndPtr, INT32 size)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	HLOCAL32 hNew32;
+	HLOCAL16 hNew16;
 
 	if (size <= es->BufSize)
 		return TRUE;
@@ -994,11 +1286,33 @@
 
 	dprintf_edit(stddeb, "edit: EDIT_MakeFit: trying to ReAlloc to %d+1\n", size);
 
-	if (LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, size + 1, LMEM_MOVEABLE)) {
-		es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1, es->BufLimit);
-		return TRUE;
-	} else
-		return FALSE;
+	EDIT_ReleasePointer(wndPtr);
+	if (es->hBuf32) {
+		if ((hNew32 = LocalReAlloc32(es->hBuf32, size + 1, 0))) {
+			dprintf_edit(stddeb, "edit: EDIT_MakeFit: Old 32 bit handle %08x, new handle %08x\n", es->hBuf32, hNew32);
+			es->hBuf32 = hNew32;
+			es->BufSize = MIN(LocalSize32(es->hBuf32) - 1, es->BufLimit);
+			if (es->BufSize < size) {
+				dprintf_edit(stddeb, "edit: EDIT_MakeFit: FAILED !  We now have %d+1\n", es->BufSize);
+				return FALSE;
+			}
+			dprintf_edit(stddeb, "edit: EDIT_MakeFit: We now have %d+1\n", es->BufSize);
+			return TRUE;
+		}
+	} else {
+		if ((hNew16 = LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf16, size + 1, LMEM_MOVEABLE))) {
+			dprintf_edit(stddeb, "edit: EDIT_MakeFit: Old 16 bit handle %08x, new handle %08x\n", es->hBuf16, hNew16);
+			es->hBuf16 = hNew16;
+			es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf16) - 1, es->BufLimit);
+			if (es->BufSize < size) {
+				dprintf_edit(stddeb, "edit: EDIT_MakeFit: FAILED !  We now have %d+1\n", es->BufSize);
+				return FALSE;
+			}
+			dprintf_edit(stddeb, "edit: EDIT_MakeFit: We now have %d+1\n", es->BufSize);
+			return TRUE;
+		}
+	}
+	return FALSE;
 }
 
 
@@ -1007,23 +1321,27 @@
  *	EDIT_MoveBackward
  *
  */
-static void EDIT_MoveBackward(WND *wndPtr, BOOL extend)
+static void EDIT_MoveBackward(WND *wndPtr, BOOL32 extend)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
+	INT32 s;
+	INT32 e;
+	INT32 l;
+	INT32 li;
 
+	EDIT_GetSel(wndPtr, &s, &e);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
 	if (e - li == 0) {
 		if (l) {
-			li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
-			e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
+			li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1, 0);
+			e = li + (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
 		}
 	} else
 		e--;
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, s, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
 }
 
 
@@ -1032,24 +1350,29 @@
  *	EDIT_MoveDownward
  *
  */
-static void EDIT_MoveDownward(WND *wndPtr, BOOL extend)
+static void EDIT_MoveDownward(WND *wndPtr, BOOL32 extend)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
-	INT x;
+	INT32 s;
+	INT32 e;
+	INT32 l;
+	INT32 lc;
+	INT32 li;
+	INT32 x;
 
+	EDIT_GetSel(wndPtr, &s, &e);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+	lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
 	if (l < lc - 1) {
 		x = EDIT_WndXFromCol(wndPtr, l, e - li);
 		l++;
-		e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
+		e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
 				EDIT_ColFromWndX(wndPtr, l, x);
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, s, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
 }
 
 
@@ -1058,18 +1381,23 @@
  *	EDIT_MoveEnd
  *
  */
-static void EDIT_MoveEnd(WND *wndPtr, BOOL extend)
+static void EDIT_MoveEnd(WND *wndPtr, BOOL32 extend)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
-	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
+	INT32 s;
+	INT32 e;
+	INT32 l;
+	INT32 ll;
+	INT32 li;
 
+	EDIT_GetSel(wndPtr, &s, &e);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+	ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
 	e = li + ll;
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, s, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
 }
 
 
@@ -1078,23 +1406,29 @@
  *	EDIT_MoveForward
  *
  */
-static void EDIT_MoveForward(WND *wndPtr, BOOL extend)
+static void EDIT_MoveForward(WND *wndPtr, BOOL32 extend)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
-	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
+	INT32 s;
+	INT32 e;
+	INT32 l;
+	INT32 lc;
+	INT32 ll;
+	INT32 li;
 
+	EDIT_GetSel(wndPtr, &s, &e);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+	lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
+	ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
 	if (e - li == ll) {
 		if (l != lc - 1)
-			e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
+			e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1, 0);
 	} else
 		e++;
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, s, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
 }
 
 
@@ -1105,17 +1439,21 @@
  *	Home key: move to beginning of line.
  *
  */
-static void EDIT_MoveHome(WND *wndPtr, BOOL extend)
+static void EDIT_MoveHome(WND *wndPtr, BOOL32 extend)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
+	INT32 s;
+	INT32 e;
+	INT32 l;
+	INT32 li;
 
+	EDIT_GetSel(wndPtr, &s, &e);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
 	e = li;
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, s, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
 }
 
 
@@ -1124,24 +1462,29 @@
  *	EDIT_MovePageDown
  *
  */
-static void EDIT_MovePageDown(WND *wndPtr, BOOL extend)
+static void EDIT_MovePageDown(WND *wndPtr, BOOL32 extend)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
-	INT x;
+	INT32 s;
+	INT32 e;
+	INT32 l;
+	INT32 lc;
+	INT32 li;
+	INT32 x;
 
+	EDIT_GetSel(wndPtr, &s, &e);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+	lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
 	if (l < lc - 1) {
 		x = EDIT_WndXFromCol(wndPtr, l, e - li);
 		l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr));
-		e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
+		e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
 				EDIT_ColFromWndX(wndPtr, l, x);
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, s, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
 }
 
 
@@ -1150,23 +1493,27 @@
  *	EDIT_MovePageUp
  *
  */
-static void EDIT_MovePageUp(WND *wndPtr, BOOL extend)
+static void EDIT_MovePageUp(WND *wndPtr, BOOL32 extend)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
-	INT x;
+	INT32 s;
+	INT32 e;
+	INT32 l;
+	INT32 li;
+	INT32 x;
 
+	EDIT_GetSel(wndPtr, &s, &e);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
 	if (l) {
 		x = EDIT_WndXFromCol(wndPtr, l, e - li);
 		l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
-		e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
+		e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
 				EDIT_ColFromWndX(wndPtr, l, x);
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, s, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
 }
 
 
@@ -1175,23 +1522,27 @@
  *	EDIT_MoveUpward
  *
  */
-static void EDIT_MoveUpward(WND *wndPtr, BOOL extend)
+static void EDIT_MoveUpward(WND *wndPtr, BOOL32 extend)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
-	INT x;
+	INT32 s;
+	INT32 e;
+	INT32 l;
+	INT32 li;
+	INT32 x;
 
+	EDIT_GetSel(wndPtr, &s, &e);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
 	if (l) {
 		x = EDIT_WndXFromCol(wndPtr, l, e - li);
 		l--;
-		e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
+		e = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0) +
 				EDIT_ColFromWndX(wndPtr, l, x);
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, s, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
 }
 
 
@@ -1200,28 +1551,33 @@
  *	EDIT_MoveWordBackward
  *
  */
-static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend)
+static void EDIT_MoveWordBackward(WND *wndPtr, BOOL32 extend)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
-	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
-	char *text;
+	INT32 s;
+	INT32 e;
+	INT32 l;
+	INT32 ll;
+	INT32 li;
+	LPSTR text;
 
+	EDIT_GetSel(wndPtr, &s, &e);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+	ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
 	if (e - li == 0) {
 		if (l) {
-			li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
-			e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
+			li = (INT32)EDIT_EM_LineIndex(wndPtr, l - 1, 0);
+			e = li + (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
 		}
 	} else {
 		text = EDIT_GetPointer(wndPtr);
-		e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
+		e = li + (INT32)EDIT_CallWordBreakProc(wndPtr,
 				text + li, e - li, ll, WB_LEFT);
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, s, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
 }
 
 
@@ -1230,27 +1586,33 @@
  *	EDIT_MoveWordForward
  *
  */
-static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend)
+static void EDIT_MoveWordForward(WND *wndPtr, BOOL32 extend)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
-	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
-	char *text;
+	INT32 s;
+	INT32 e;
+	INT32 l;
+	INT32 lc;
+	INT32 ll;
+	INT32 li;
+	LPSTR text;
 
+	EDIT_GetSel(wndPtr, &s, &e);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+	lc = (INT32)EDIT_EM_GetLineCount(wndPtr, e, 0);
+	ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
 	if (e - li == ll) {
 		if (l != lc - 1)
-			e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
+			e = (INT32)EDIT_EM_LineIndex(wndPtr, l + 1, 0);
 	} else {
 		text = EDIT_GetPointer(wndPtr);
-		e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
+		e = li + EDIT_CallWordBreakProc(wndPtr,
 				text + li, e - li + 1, ll, WB_RIGHT);
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, s, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
 }
 
 
@@ -1259,17 +1621,17 @@
  *	EDIT_PaintLine
  *
  */
-static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, UINT line, BOOL rev)
+static void EDIT_PaintLine(WND *wndPtr, HDC32 hdc, INT32 line, BOOL32 rev)
 {
-	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
-	UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
-	UINT li;
-	UINT ll;
-	UINT s;
-	UINT e;
-	INT x;
-	INT y;
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
+	INT32 li;
+	INT32 ll;
+	INT32 s;
+	INT32 e;
+	INT32 x;
+	INT32 y;
 
 	if ((line < fv) || (line > fv + vlc) || (line >= lc))
 		return;
@@ -1278,11 +1640,10 @@
 
 	x = EDIT_WndXFromCol(wndPtr, line, 0);
 	y = EDIT_WndYFromLine(wndPtr, line);
-	li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
-	ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
-	s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	ORDER_UINT(s, e);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
+	ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
+	EDIT_GetSel(wndPtr, &s, &e);
+	ORDER_INT32(s, e);
 	s = MIN(li + ll, MAX(li, s));
 	e = MIN(li + ll, MAX(li, e));
 	if (rev && (s != e) &&
@@ -1301,15 +1662,15 @@
  *	EDIT_PaintText
  *
  */
-static UINT EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev)
+static INT32 EDIT_PaintText(WND *wndPtr, HDC32 hdc, INT32 x, INT32 y, INT32 line, INT32 col, INT32 count, BOOL32 rev)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	COLORREF BkColor;
 	COLORREF TextColor;
-	UINT ret;
-	char *text;
-	UINT li;
-	UINT xoff;
+	INT32 ret;
+	LPSTR text;
+	INT32 li;
+	INT32 xoff;
 
 	if (!count)
 		return 0;
@@ -1320,9 +1681,9 @@
 		SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
 	}
 	text = EDIT_GetPasswordPointer(wndPtr);
-	li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
 	xoff = EDIT_GetXOffset(wndPtr);
-	ret = LOWORD(TabbedTextOut(hdc, x, y, text + li + col, count,
+	ret = (INT32)LOWORD(TabbedTextOut(hdc, x, y, text + li + col, count,
 					es->NumTabStops, es->TabStops, -xoff));
 	free(text);
 	if (rev) {
@@ -1330,7 +1691,7 @@
 		SetTextColor(hdc, TextColor);
 	}
 	return ret;
-}	
+}
 
 
 /*********************************************************************
@@ -1339,138 +1700,51 @@
  *
  *	This is the only helper function that can be called with es = NULL.
  *	It is called at the end of EditWndProc() to unlock the buffer.
- *	
+ *
  */
 static void EDIT_ReleasePointer(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	
+
 	if (!es)
 		return;
-	if (es->text && es->hBuf)
-		LOCAL_Unlock(wndPtr->hInstance, es->hBuf);
+	if (es->text && (es->hBuf32 || es->hBuf16))
+        {
+		if (es->hBuf32)
+			LocalUnlock32(es->hBuf32);
+		else
+			LOCAL_Unlock(wndPtr->hInstance, es->hBuf16);
+        }
 	es->text = NULL;
 }
 
 
 /*********************************************************************
  *
- *	EDIT_ReplaceSel
- *
- *	Beware: This is not the function called on EM_REPLACESEL.
- *	It expects a (char *) in lParam, not a (SEGPTR).
- *	It is used internally, as if there were no pointer difficulties.
- *
- */
-static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
-{
-	const char *str = (char *)lParam;
-	int strl = strlen(str);
-	UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	int i;
-	char *p;
-	char *text;
-	BOOL redraw;
-
-	ORDER_UINT(s,e);
-	if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) {
-		EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
-		return 0L;
-	}
-	redraw = EDIT_GetRedraw(wndPtr);
-	EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
-	EDIT_WM_Clear(wndPtr, 0, 0L);
-	tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
-	e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	text = EDIT_GetPointer(wndPtr);
-	for (p = text + tl ; p >= text + e ; p--)
-		p[strl] = p[0];
-	for (i = 0 , p = text + e ; i < strl ; i++)
-		p[i] = str[i];
-	if(IsUpper(wndPtr))
-		AnsiUpperBuff(p, strl);
-	else if(IsLower(wndPtr))
-		AnsiLowerBuff(p, strl);
-	EDIT_BuildLineDefs(wndPtr);
-	e += strl;
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(e, e));
-	EDIT_EM_SetModify(wndPtr, TRUE, 0L);
-	EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
-	EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
-	if (redraw) {
-		InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
-		EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
-	}
-	return 0L;
-}
- 
-
-/*********************************************************************
- *
- *	EDIT_ScrollIntoView
- *
- *	Makes sure the caret is visible.
- *
- */
-static void EDIT_ScrollIntoView(WND *wndPtr)
-{
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
-	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
-	UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
-	UINT ww = EDIT_GetWndWidth(wndPtr);
-	UINT cw = EDIT_GetAveCharWidth(wndPtr);
-	INT x = EDIT_WndXFromCol(wndPtr, l, e - li);
-	int dy = 0;
-	int dx = 0;
-
-	if (l >= fv + vlc)
-		dy = l - vlc + 1 - fv;
-	if (l < fv)
-		dy = l - fv;
-	if (x < 0)
-		dx = x - ww / HSCROLL_FRACTION / cw * cw;
-	if (x > ww)
-		dx = x - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
-	if (dy || dx) {
-		EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, dx));
-		if (dy) 
-			EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
-		if (dx)
-			EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
-	}
-}
-
-
-/*********************************************************************
- *
  *	EDIT_WndXFromCol
  *
  *	Calculates, for a given line and column, the X-coordinate on the screen.
  *
  */
-static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col)
-{	
+static INT32 EDIT_WndXFromCol(WND *wndPtr, INT32 line, INT32 col)
+{
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	char *text = EDIT_GetPasswordPointer(wndPtr);
-	INT ret;
+	LPSTR text = EDIT_GetPasswordPointer(wndPtr);
+	INT32 ret;
 	HDC32 hdc;
-	HFONT16 hFont;
+	HFONT32 hFont;
 	HFONT32 oldFont = 0;
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
-	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
-	UINT xoff = EDIT_GetXOffset(wndPtr);
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
+	INT32 li = (INT32)EDIT_EM_LineIndex(wndPtr, line, 0);
+	INT32 ll = (INT32)EDIT_EM_LineLength(wndPtr, li, 0);
+	INT32 xoff = EDIT_GetXOffset(wndPtr);
 
 	hdc = GetDC32(wndPtr->hwndSelf);
-	hFont = (HFONT16)EDIT_WM_GetFont(wndPtr, 0, 0L);
+	hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
 	if (hFont) oldFont = SelectObject32(hdc, hFont);
 	line = MAX(0, MIN(line, lc - 1));
 	col = MIN(col, ll);
-	ret = LOWORD(GetTabbedTextExtent(hdc,
+	ret = (INT32)LOWORD(GetTabbedTextExtent(hdc,
 			text + li, col,
 			es->NumTabStops, es->TabStops)) - xoff;
 	if (hFont) SelectObject32(hdc, oldFont);
@@ -1487,10 +1761,10 @@
  *	Calculates, for a given line, the Y-coordinate on the screen.
  *
  */
-static INT EDIT_WndYFromLine(WND *wndPtr, UINT line)
+static INT32 EDIT_WndYFromLine(WND *wndPtr, INT32 line)
 {
-	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
-	UINT lh = EDIT_GetLineHeight(wndPtr);
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 lh = EDIT_GetLineHeight(wndPtr);
 
 	return (line - fv) * lh;
 }
@@ -1507,16 +1781,16 @@
  *		internally, so we can decide this for ourselves.
  *
  */
-static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action)
+static INT32 EDIT_WordBreakProc(LPSTR s, INT32 index, INT32 count, INT32 action)
 {
-	INT ret = 0;
+	INT32 ret = 0;
 
-	dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%d"
-			", count=%d, action=%d\n", s, index, count, action);
+	dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%u"
+			", count=%u, action=%d\n", s, index, count, action);
 
 	switch (action) {
 	case WB_LEFT:
-		if (!count) 
+		if (!count)
 			break;
 		if (index)
 			index--;
@@ -1569,7 +1843,38 @@
  */
 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	return 0L;
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	return (LRESULT)es->CanUndo;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_CHARFROMPOS
+ *
+ *	FIXME: do the specs mean LineIndex or LineNumber (li v.s. l) ???
+ */
+static LRESULT EDIT_EM_CharFromPos(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+	POINT32 pt;
+	RECT32 rc;
+	INT32 l;
+	INT32 li;
+	INT32 c;
+
+	pt.x = LOWORD(lParam);
+	pt.y = HIWORD(lParam);
+	GetClientRect32(wndPtr->hwndSelf, &rc);
+
+	if (!PtInRect32(&rc, pt))
+		return -1;
+
+	l = EDIT_LineFromWndY(wndPtr, pt.y);
+	li = EDIT_EM_LineIndex(wndPtr, l, 0);
+	c = EDIT_ColFromWndX(wndPtr, l, pt.x);
+
+	return (LRESULT)MAKELONG(li + c, li);
 }
 
 
@@ -1580,7 +1885,10 @@
  */
 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	return 0L;
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	es->CanUndo = FALSE;
+	return 0;
 }
 
 
@@ -1591,8 +1899,8 @@
  */
 static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented.\n");
-	return wParam ? -1L : 0L;
+	fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented\n");
+	return wParam ? TRUE : FALSE;
 }
 
 
@@ -1604,8 +1912,11 @@
 static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	
-	return (LRESULT)es->FirstVisibleLine;
+
+	if (IsMultiLine(wndPtr))
+		return (LRESULT)es->FirstVisibleLine;
+	else
+		return (LRESULT)EDIT_ColFromWndX(wndPtr, 0, 0);
 }
 
 
@@ -1618,9 +1929,91 @@
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-	return (LRESULT)es->hBuf;
+	if (!IsMultiLine(wndPtr))
+		return 0;
+
+	if (es->hBuf32)
+		return (LRESULT)es->hBuf32;
+	else
+		return (LRESULT)es->hBuf16;
 }
- 
+
+
+/*********************************************************************
+ *
+ *	EM_GETHANDLE16
+ *
+ *	Hopefully this won't fire back at us.
+ *	We always start with a buffer in 32 bit linear memory.
+ *	However, with this message a 16 bit application requests
+ *	a handle of 16 bit local heap memory, where it expects to find
+ *	the text.
+ *	It's a pitty that from this moment on we have to use this
+ *	local heap, because applications may rely on the handle
+ *	in the future.
+ *
+ *	In this function we'll try to switch to local heap.
+ */
+static LRESULT EDIT_EM_GetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	LPSTR text;
+	HLOCAL16 newBuf;
+	LPSTR newText;
+	INT16 newSize;
+
+	if (!IsMultiLine(wndPtr))
+		return 0;
+
+	if (es->hBuf16)
+		return (LRESULT)es->hBuf16;
+
+	if (!LOCAL_HeapSize(wndPtr->hInstance)) {
+		if (!LocalInit(wndPtr->hInstance, 0,
+			       GlobalSize16(wndPtr->hInstance))) {
+			fprintf(stderr, "edit: EM_GETHANDLE: could not initialize local heap\n");
+			return 0;
+		}
+		dprintf_edit(stddeb, "edit: EM_GETHANDLE: local heap initialized\n");
+	}
+	if (!(newBuf = LOCAL_Alloc(wndPtr->hInstance,
+				EDIT_WM_GetTextLength(wndPtr, 0, 0) + 1,
+				LMEM_MOVEABLE))) {
+		fprintf(stderr, "edit: EM_GETHANDLE: could not allocate new 16 bit buffer\n");
+		return 0;
+	}
+	newSize = MIN(LOCAL_Size(wndPtr->hInstance, newBuf) - 1, es->BufLimit);
+	if (!(newText = LOCAL_Lock(wndPtr->hInstance, newBuf))) {
+		fprintf(stderr, "edit: EM_GETHANDLE: could not lock new 16 bit buffer\n");
+		LOCAL_Free(wndPtr->hInstance, newBuf);
+		return 0;
+	}
+	text = EDIT_GetPointer(wndPtr);
+	lstrcpy32A(newText, text);
+	EDIT_ReleasePointer(wndPtr);
+	GlobalFree32(es->hBuf32);
+	es->hBuf32 = (HLOCAL32)NULL;
+	es->hBuf16 = newBuf;
+	es->BufSize = newSize;
+	es->text = newText;
+	dprintf_edit(stddeb, "edit: EM_GETHANDLE: switched to 16 bit buffer\n");
+
+	return (LRESULT)es->hBuf16;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_GETLIMITTEXT
+ *
+ */
+static LRESULT EDIT_EM_GetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	return es->BufLimit;
+}
+
 
 /*********************************************************************
  *
@@ -1629,21 +2022,21 @@
  */
 static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	char *text;
-	char *src;
-	char *dst;
-	UINT len;
-	UINT i;
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	LPSTR text;
+	LPSTR src;
+	LPSTR dst;
+	INT32 len;
+	INT32 i;
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
 
 	if (!IsMultiLine(wndPtr))
 		wParam = 0;
-	if ((UINT)wParam >= lc)
-		return 0L;
+	if ((INT32)wParam >= lc)
+		return 0;
 	text = EDIT_GetPointer(wndPtr);
-	src = text + (UINT)EDIT_EM_LineIndex(wndPtr, wParam, 0L);
-	dst = (char *)PTR_SEG_TO_LIN(lParam);
-	len = MIN(*(WORD *)dst, (UINT)EDIT_EM_LineLength(wndPtr, wParam, 0L));
+	src = text + (INT32)EDIT_EM_LineIndex(wndPtr, wParam, 0);
+	dst = (LPSTR)lParam;
+	len = MIN(*(WORD *)dst, (INT32)EDIT_EM_LineLength(wndPtr, wParam, 0));
 	for (i = 0 ; i < len ; i++) {
 		*dst = *src;
 		src++;
@@ -1661,13 +2054,26 @@
 static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	
+
 	return (LRESULT)es->LineCount;
 }
 
 
 /*********************************************************************
  *
+ *	EM_GETMARGINS
+ *
+ */
+static LRESULT EDIT_EM_GetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	return (LRESULT)MAKELONG(es->LeftMargin, es->RightMargin);
+}
+
+
+/*********************************************************************
+ *
  *	EM_GETMODIFY
  *
  */
@@ -1699,7 +2105,24 @@
  */
 static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	return EDIT_GetRect(wndPtr, wParam, (LPARAM)PTR_SEG_TO_LIN(lParam));
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	CopyRect32((LPRECT32)lParam, &es->FormatRect);
+	return 0;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_GETRECT16
+ *
+ */
+static LRESULT EDIT_EM_GetRect16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	CONV_RECT32TO16(&es->FormatRect, (LPRECT16)PTR_SEG_TO_LIN((SEGPTR)lParam));
+	return 0;
 }
 
 
@@ -1713,11 +2136,16 @@
  */
 static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
+	INT32 s;
+	INT32 e;
 
-	ORDER_UINT(s, e);
-	return MAKELONG(s, e);
+	EDIT_GetSel(wndPtr, &s, &e);
+	ORDER_INT32(s, e);
+	if (wParam)
+		*(LPINT32)wParam = s;
+	if (lParam)
+		*(LPINT32)lParam = e;
+	return MAKELONG((INT16)s, (INT16)e);
 }
 
 
@@ -1725,13 +2153,16 @@
  *
  *	EM_GETTHUMB
  *
- *	FIXME: undocumented: is this right ?
+ *	FIXME: is this right ?  (or should it be only HSCROLL)
+ *	(and maybe only for edit controls that really have their
+ *	own scrollbars) (and maybe only for multiline controls ?)
+ *	All in all: very poorly documented
  *
  */
 static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L),
-		EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L));
+	return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0),
+		EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0));
 }
 
 
@@ -1739,36 +2170,17 @@
  *
  *	EM_GETWORDBREAKPROC
  *
+ *	FIXME: Application defined WordBreakProc should be returned
+ *
  */
 static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
+/*
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
 	return (LRESULT)es->WordBreakProc;
-}
-
-
-/*********************************************************************
- *
- *	EM_LIMITTEXT
- *
- */
-static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
-{
-	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-
-	if (IsMultiLine(wndPtr)) {
-		if (wParam)
-			es->BufLimit = MIN((UINT)wParam, BUFLIMIT_MULTI);
-		else
-			es->BufLimit = BUFLIMIT_MULTI;
-	} else {
-		if (wParam)
-			es->BufLimit = MIN((UINT)wParam, BUFLIMIT_SINGLE);
-		else
-			es->BufLimit = BUFLIMIT_SINGLE;
-	}
-	return 0L;
+*/
+	return 0;
 }
 
 
@@ -1779,14 +2191,14 @@
  */
 static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	UINT l;
+	INT32 l;
 
 	if (!IsMultiLine(wndPtr))
-		return 0L;
-	if ((INT)wParam == -1)
-		wParam = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	l = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1;
-	while ((UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) > (UINT)wParam)
+		return 0;
+	if ((INT32)wParam == -1)
+		EDIT_EM_GetSel(wndPtr, (WPARAM32)&wParam, 0);	/* intentional (looks weird, doesn't it ?) */
+	l = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0) - 1;
+	while ((INT32)EDIT_EM_LineIndex(wndPtr, l, 0) > (INT32)wParam)
 		l--;
 	return (LRESULT)l;
 }
@@ -1800,20 +2212,20 @@
 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	UINT e;
-	UINT l;
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	INT32 e;
+	INT32 l;
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
 
-	if ((INT)wParam == -1) {
-		e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
+	if ((INT32)wParam == -1) {
+		EDIT_GetSel(wndPtr, NULL, &e);
 		l = lc - 1;
 		while (es->LineDefs[l].offset > e)
 			l--;
 		return (LRESULT)es->LineDefs[l].offset;
 	}
-	if ((UINT)wParam >= lc)
-		return -1L;
-	return (LRESULT)es->LineDefs[(UINT)wParam].offset;
+	if ((INT32)wParam >= lc)
+		return -1;
+	return (LRESULT)es->LineDefs[(INT32)wParam].offset;
 }
 
 
@@ -1825,43 +2237,47 @@
 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	UINT s;
-	UINT e;
-	UINT sl;
-	UINT el;
+	INT32 s;
+	INT32 e;
+	INT32 sl;
+	INT32 el;
 
 	if (!IsMultiLine(wndPtr))
 		return (LRESULT)es->LineDefs[0].length;
-	if ((INT)wParam == -1) {
-		s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-		e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-		sl = (UINT)EDIT_EM_LineFromChar(wndPtr, s, 0L);
-		el = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	if ((INT32)wParam == -1) {
+		EDIT_GetSel(wndPtr, &s, &e);
+		sl = (INT32)EDIT_EM_LineFromChar(wndPtr, s, 0);
+		el = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
 		return (LRESULT)(s - es->LineDefs[sl].offset +
 				es->LineDefs[el].offset +
 				es->LineDefs[el].length - e);
 	}
-	return (LRESULT)es->LineDefs[(UINT)EDIT_EM_LineFromChar(wndPtr, wParam, 0L)].length;
+	return (LRESULT)es->LineDefs[(INT32)EDIT_EM_LineFromChar(wndPtr, wParam, 0)].length;
 }
- 
+
 
 /*********************************************************************
  *
  *	EM_LINESCROLL
  *
+ *	FIXME: is wParam in pixels or in average character widths ???
+ *	FIXME: we use this internally to scroll single line controls as well
+ *	(specs are vague about whether this message is valid or not for
+ *	single line controls)
+ *
  */
 static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
-	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
-	UINT nfv = MAX(0, fv + (INT)LOWORD(lParam));
-	UINT xoff = EDIT_GetXOffset(wndPtr);
-	UINT nxoff = MAX(0, xoff + (INT)HIWORD(lParam));
-	UINT tw = EDIT_GetTextWidth(wndPtr);
-	INT dx;
-	INT dy;
-	POINT16 pos;
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 nfv = MAX(0, fv + (INT32)lParam);
+	INT32 xoff = EDIT_GetXOffset(wndPtr);
+	INT32 nxoff = MAX(0, xoff + (INT32)wParam);
+	INT32 tw = EDIT_GetTextWidth(wndPtr);
+	INT32 dx;
+	INT32 dy;
+	POINT32 pos;
 
 	if (nfv >= lc)
 		nfv = lc - 1;
@@ -1873,23 +2289,45 @@
 	if (dx || dy) {
 		if (wndPtr->hwndSelf == GetFocus32())
 			HideCaret(wndPtr->hwndSelf);
-		if (EDIT_GetRedraw(wndPtr)) 
+		if (EDIT_GetRedraw(wndPtr))
 			ScrollWindow32(wndPtr->hwndSelf, dx, dy, NULL, NULL);
 		es->FirstVisibleLine = nfv;
 		es->XOffset = nxoff;
 		if (IsVScrollBar(wndPtr))
 			SetScrollPos32(wndPtr->hwndSelf, SB_VERT,
-				EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
+				EDIT_WM_VScroll(wndPtr, EM_GETTHUMB16, 0), TRUE);
 		if (IsHScrollBar(wndPtr))
 			SetScrollPos32(wndPtr->hwndSelf, SB_HORZ,
-				EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
+				EDIT_WM_HScroll(wndPtr, EM_GETTHUMB16, 0), TRUE);
 		if (wndPtr->hwndSelf == GetFocus32()) {
-			GetCaretPos16(&pos);
+			GetCaretPos32(&pos);
 			SetCaretPos(pos.x + dx, pos.y + dy);
 			ShowCaret(wndPtr->hwndSelf);
 		}
 	}
-	return -1L;
+	if (IsMultiLine(wndPtr))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_POSFROMCHAR
+ *
+ */
+static LRESULT EDIT_EM_PosFromChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+	INT32 len = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
+	INT32 l;
+	INT32 li;
+
+	wParam = MIN(wParam, len);
+	l = EDIT_EM_LineFromChar(wndPtr, wParam, 0);
+	li = EDIT_EM_LineIndex(wndPtr, l, 0);
+	return (LRESULT)MAKELONG(EDIT_WndXFromCol(wndPtr, l, wParam - li),
+				EDIT_WndYFromLine(wndPtr, l));
 }
 
 
@@ -1897,25 +2335,120 @@
  *
  *	EM_REPLACESEL
  *
+ *	FIXME: wParam indicates whether we should maintain an undo buffer
+ *	for this operation.
+ *
  */
 static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	return (LRESULT)EDIT_ReplaceSel(wndPtr, wParam,
-				(LPARAM)(char *)PTR_SEG_TO_LIN(lParam));
+	LPCSTR str = (LPCSTR)lParam;
+	INT32 strl = lstrlen32A(str);
+	INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
+	INT32 s;
+	INT32 e;
+	INT32 i;
+	LPSTR p;
+	LPSTR text;
+	BOOL32 redraw;
+
+	EDIT_GetSel(wndPtr, &s, &e);
+	ORDER_INT32(s,e);
+	if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) {
+		dprintf_edit(stddeb, "edit: notification EN_MAXTEXT sent\n");
+		EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
+		return 0;
+	}
+	redraw = EDIT_GetRedraw(wndPtr);
+	EDIT_WM_SetRedraw(wndPtr, FALSE, 0);
+	EDIT_WM_Clear(wndPtr, 0, 0);
+	tl = EDIT_WM_GetTextLength(wndPtr, 0, 0);
+	EDIT_GetSel(wndPtr, NULL, &e);
+	text = EDIT_GetPointer(wndPtr);
+	for (p = text + tl ; p >= text + e ; p--)
+		p[strl] = p[0];
+	for (i = 0 , p = text + e ; i < strl ; i++)
+		p[i] = str[i];
+	if(IsUpper(wndPtr))
+		CharUpperBuff32A(p, strl);
+	else if(IsLower(wndPtr))
+		CharLowerBuff32A(p, strl);
+	EDIT_BuildLineDefs(wndPtr);
+	e += strl;
+	EDIT_EM_SetSel(wndPtr, e, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	EDIT_EM_SetModify(wndPtr, TRUE, 0);
+	dprintf_edit(stddeb, "edit: notification EN_UPDATE sent\n");
+	EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
+	EDIT_WM_SetRedraw(wndPtr, redraw, 0);
+	if (redraw) {
+		InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
+		dprintf_edit(stddeb, "edit: notification EN_CHANGE sent\n");
+		EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
+	}
+	return 0;
 }
- 
+
 
 /*********************************************************************
  *
  *	EM_SCROLL
  *
- *	FIXME: undocumented message.
+ *	FIXME: Scroll what ???  And where ???
  *
  */
 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	fprintf(stdnimp, "edit: EM_SCROLL: message not implemented (undocumented), please report.\n");
-	return 0L;
+	fprintf(stdnimp, "edit: EM_SCROLL: message not implemented\n");
+	return 0;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SCROLLCARET
+ *
+ *	Makes sure the caret is visible.
+ *	FIXME: We use EM_LINESCROLL, but may we do that for single line
+ *		controls ???
+ *
+ */
+static LRESULT EDIT_EM_ScrollCaret(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+	INT32 e;
+	INT32 l;
+	INT32 li;
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
+	INT32 ww = EDIT_GetWndWidth(wndPtr);
+	INT32 cw = EDIT_GetAveCharWidth(wndPtr);
+	INT32 x;
+	INT32 dy = 0;
+	INT32 dx = 0;
+
+	EDIT_GetSel(wndPtr, NULL, &e);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	x = EDIT_WndXFromCol(wndPtr, l, e - li);
+	if (l >= fv + vlc)
+		dy = l - vlc + 1 - fv;
+	if (l < fv)
+		dy = l - fv;
+	if (x < 0)
+		dx = x - ww / HSCROLL_FRACTION / cw * cw;
+	if (x > ww)
+		dx = x - (HSCROLL_FRACTION - 1) * ww / HSCROLL_FRACTION / cw * cw;
+	if (dy || dx) {
+		EDIT_EM_LineScroll(wndPtr, dx, dy);
+		if (dy) {
+			dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n");
+			EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
+		}
+		if (dx) {
+			dprintf_edit(stddeb, "edit: notification EN_HSCROLL sent\n");
+			EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
+		}
+	}
+	return TRUE;
 }
 
 
@@ -1933,19 +2466,105 @@
 		/*
 		 *	old buffer is freed by caller
 		 */
-		es->hBuf = (HLOCAL16)wParam;
-		es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
+		es->hBuf16 = (HLOCAL16)NULL;
+		es->hBuf32 = (HLOCAL32)wParam;
+		es->BufSize = LocalSize32(es->hBuf32) - 1;
 		es->LineCount = 0;
 		es->FirstVisibleLine = 0;
 		es->SelStart = es->SelEnd = 0;
-		EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
-		EDIT_EM_SetModify(wndPtr, FALSE, 0L);
+		EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
+		EDIT_EM_SetModify(wndPtr, FALSE, 0);
 		EDIT_BuildLineDefs(wndPtr);
 		if (EDIT_GetRedraw(wndPtr))
 			InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
-		EDIT_ScrollIntoView(wndPtr);
+		EDIT_EM_ScrollCaret(wndPtr, 0, 0);
 	}
-	return 0L;
+	return 0;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETHANDLE16
+ *
+ */
+static LRESULT EDIT_EM_SetHandle16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	if (IsMultiLine(wndPtr)) {
+		EDIT_ReleasePointer(wndPtr);
+		/*
+		 *	old buffer is freed by caller
+		 */
+		es->hBuf16 = (HLOCAL16)wParam;
+		es->hBuf32 = (HLOCAL32)NULL;
+		es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf16) - 1;
+		es->LineCount = 0;
+		es->FirstVisibleLine = 0;
+		es->SelStart = es->SelEnd = 0;
+		EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
+		EDIT_EM_SetModify(wndPtr, FALSE, 0);
+		EDIT_BuildLineDefs(wndPtr);
+		if (EDIT_GetRedraw(wndPtr))
+			InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
+		EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	}
+	return 0;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETLIMITTEXT
+ *
+ */
+static LRESULT EDIT_EM_SetLimitText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	if (IsMultiLine(wndPtr)) {
+		if (wParam)
+			es->BufLimit = MIN((INT32)wParam, BUFLIMIT_MULTI);
+		else
+			es->BufLimit = BUFLIMIT_MULTI;
+	} else {
+		if (wParam)
+			es->BufLimit = MIN((INT32)wParam, BUFLIMIT_SINGLE);
+		else
+			es->BufLimit = BUFLIMIT_SINGLE;
+	}
+	return 0;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETMARGINS
+ *
+ *	FIXME: We let the margins be set, but we don't use them yet !?!
+ *
+ */
+static LRESULT EDIT_EM_SetMargins(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	if (wParam & EC_USEFONTINFO) {
+		if (IsMultiLine(wndPtr)) {
+			/*
+			 *	FIXME: do some GetABCCharWidth, or so
+			 *		This is just preliminary
+			 */
+			es->LeftMargin = es->RightMargin = EDIT_GetAveCharWidth(wndPtr);
+		} else
+			es->LeftMargin = es->RightMargin = EDIT_GetAveCharWidth(wndPtr);
+		return 0;
+	}
+	if (wParam & EC_LEFTMARGIN)
+		es->LeftMargin = LOWORD(lParam);
+	if (wParam & EC_RIGHTMARGIN)
+		es->RightMargin = HIWORD(lParam);
+	return 0;
 }
 
 
@@ -1958,8 +2577,8 @@
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-	es->TextChanged = (BOOL)wParam;
-	return 0L;
+	es->TextChanged = (BOOL32)wParam;
+	return 0;
 }
 
 
@@ -1967,13 +2586,15 @@
  *
  *	EM_SETPASSWORDCHAR
  *
+ *	FIXME: This imlementation is way too simple
+ *
  */
 static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-	es->PasswordChar = (char)wParam;
-	return 0L;
+	es->PasswordChar = (CHAR)wParam;
+	return 0;
 }
 
 
@@ -1984,11 +2605,11 @@
  */
 static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	if ((BOOL)wParam)
+	if ((BOOL32)wParam)
 		wndPtr->dwStyle |= ES_READONLY;
 	else
 		wndPtr->dwStyle &= ~(DWORD)ES_READONLY;
-	return 0L;
+	return TRUE;
 }
 
 
@@ -1999,8 +2620,8 @@
  */
 static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	fprintf(stdnimp,"edit: EM_SETRECT: message not implemented, please report.\n");
-	return 0L;
+	fprintf(stdnimp,"edit: EM_SETRECT: message not implemented\n");
+	return 0;
 }
 
 
@@ -2011,8 +2632,8 @@
  */
 static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented, please report.\n");
-	return 0L;
+	fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented\n");
+	return 0;
 }
 
 
@@ -2020,50 +2641,76 @@
  *
  *	EM_SETSEL
  *
+ *	FIXME: specs state that we should order start and end.
+ *		However, we use internally that this is not the case.
+ *
  */
 static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	UINT ns = LOWORD(lParam);
-	UINT ne = HIWORD(lParam);
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT el;
-	UINT eli;
-	UINT tl = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
+	INT32 ns = (INT32)wParam;
+	INT32 ne = (INT32)lParam;
+	INT32 s;
+	INT32 e;
+	INT32 el;
+	INT32 eli;
+	INT32 tl = (INT32)EDIT_WM_GetTextLength(wndPtr, 0, 0);
 
-	if ((INT)ns == -1) {
+	EDIT_GetSel(wndPtr, &s, &e);
+	if (ns == -1) {
 		ns = e;
 		ne = e;
 	}
-	else {
-		ns = MIN(ns, tl);
-		ne = MIN(ne, tl);
-	}
+	if (ne == -1)
+		ne = e;
+/*
+	ORDER_INT32(ns, ne);
+*/
+	ns = MIN(ns, tl);
+	ne = MIN(ne, tl);
 	es->SelStart = ns;
 	es->SelEnd = ne;
 	if (wndPtr->hwndSelf == GetFocus32()) {
-		el = (UINT)EDIT_EM_LineFromChar(wndPtr, ne, 0L);
-		eli = (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
+		el = (INT32)EDIT_EM_LineFromChar(wndPtr, ne, 0);
+		eli = (INT32)EDIT_EM_LineIndex(wndPtr, el, 0);
 		SetCaretPos(EDIT_WndXFromCol(wndPtr, el, ne - eli),
 				EDIT_WndYFromLine(wndPtr, el));
 	}
-	if (!wParam)
-		EDIT_ScrollIntoView(wndPtr);
 	if (EDIT_GetRedraw(wndPtr)) {
-		ORDER_UINT(s, e);
-		ORDER_UINT(s, ns);
-		ORDER_UINT(s, ne);
-		ORDER_UINT(e, ns);
-		ORDER_UINT(e, ne);
-		ORDER_UINT(ns, ne);
+		ORDER_INT32(s, e);
+		ORDER_INT32(s, ns);
+		ORDER_INT32(s, ne);
+		ORDER_INT32(e, ns);
+		ORDER_INT32(e, ne);
+		ORDER_INT32(ns, ne);
 		if (e != ns) {
 			EDIT_InvalidateText(wndPtr, s, e);
 			EDIT_InvalidateText(wndPtr, ns, ne);
 		} else
 			EDIT_InvalidateText(wndPtr, s, ne);
 	}
-	return -1L;
+	return -1;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETSEL16
+ *
+ */
+static LRESULT EDIT_EM_SetSel16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+	INT32 ns = (INT32)LOWORD(lParam);
+	INT32 ne = (INT32)HIWORD(lParam);
+
+	if ((INT16)LOWORD(lParam) == -1)
+		ns = -1;
+	if ((INT16)HIWORD(lParam) == -1)
+		ne = -1;
+	EDIT_EM_SetSel(wndPtr, ns, ne);
+	if (!wParam)
+		EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	return -1;
 }
 
 
@@ -2075,20 +2722,46 @@
 static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	INT32 i;
 
 	if (!IsMultiLine(wndPtr))
-		return 0L;
+		return FALSE;
 	if (es->TabStops)
 		free(es->TabStops);
-	es->NumTabStops = (UINT)wParam;
+	es->NumTabStops = (INT32)wParam;
+	if (!wParam)
+		es->TabStops = NULL;
+	else {
+		es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16));
+		for ( i = 0 ; i < (INT32)wParam ; i++ )
+			es->TabStops[i] = (INT16)((LPINT32)lParam)[i];
+	}
+	return TRUE;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETTABSTOPS16
+ *
+ */
+static LRESULT EDIT_EM_SetTabStops16(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	if (!IsMultiLine(wndPtr))
+		return FALSE;
+	if (es->TabStops)
+		free(es->TabStops);
+	es->NumTabStops = (INT32)wParam;
 	if (!wParam)
 		es->TabStops = NULL;
 	else {
 		es->TabStops = (LPINT16)xmalloc(wParam * sizeof(INT16));
 		memcpy(es->TabStops, (LPINT16)PTR_SEG_TO_LIN(lParam),
-				(UINT)wParam * sizeof(INT16));
+				(INT32)wParam * sizeof(INT16));
 	}
-	return 1L;
+	return TRUE;
 }
 
 
@@ -2099,10 +2772,12 @@
  */
 static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
+/*
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
 	es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
-	return 0L;
+*/
+	return 0;
 }
 
 
@@ -2113,7 +2788,11 @@
  */
 static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	return 0L;
+	fprintf(stdnimp,"edit: EM_UNDO: message not implemented\n");
+	if (IsMultiLine(wndPtr))
+		return FALSE;
+	else
+		return TRUE;
 }
 
 
@@ -2135,22 +2814,22 @@
 				EDIT_MoveHome(wndPtr, FALSE);
 				EDIT_MoveDownward(wndPtr, FALSE);
 			} else
-				EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\r\n");
+				EDIT_EM_ReplaceSel(wndPtr, 0, (LPARAM)"\r\n");
 		}
 		break;
 	case '\t':
 		if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr))
-			EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\t");
+			EDIT_EM_ReplaceSel(wndPtr, 0, (LPARAM)"\t");
 		break;
 	default:
 		if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) {
  			str[0] = c;
  			str[1] = '\0';
- 			EDIT_ReplaceSel(wndPtr, 0, (LPARAM)str);
+ 			EDIT_EM_ReplaceSel(wndPtr, 0, (LPARAM)str);
  		}
 		break;
 	}
-	return 0L;
+	return 0;
 }
 
 
@@ -2161,28 +2840,32 @@
  */
 static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	char *text;
-	BOOL redraw;
-	
+	INT32 s;
+	INT32 e;
+	LPSTR text;
+	BOOL32 redraw;
+
+	EDIT_GetSel(wndPtr, &s, &e);
 	if (s != e) {
 		redraw = EDIT_GetRedraw(wndPtr);
-		EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
-		ORDER_UINT(s, e);
+		EDIT_WM_SetRedraw(wndPtr, FALSE, 0);
+		ORDER_INT32(s, e);
 		text = EDIT_GetPointer(wndPtr);
-		strcpy(text + s, text + e);
+		lstrcpy32A(text + s, text + e);
 		EDIT_BuildLineDefs(wndPtr);
-		EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, s));
-		EDIT_EM_SetModify(wndPtr, TRUE, 0L);
+		EDIT_EM_SetSel(wndPtr, s, s);
+		EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+		EDIT_EM_SetModify(wndPtr, TRUE, 0);
+		dprintf_edit(stddeb, "edit: notification EN_UPDATE sent\n");
 		EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
-		EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
+		EDIT_WM_SetRedraw(wndPtr, redraw, 0);
 		if (redraw) {
 			InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
+			dprintf_edit(stddeb, "edit: notification EN_CHANGE sent\n");
 			EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
 		}
 	}
-	return -1L;
+	return -1;
 }
 
 
@@ -2193,17 +2876,18 @@
  */
 static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
+	INT32 s;
+	INT32 e;
 	HGLOBAL16 hdst;
-	char *text;
-	char *dst;
-	char *src;
-	int i;
+	LPSTR text;
+	LPSTR dst;
+	LPSTR src;
+	INT32 i;
 
+	EDIT_GetSel(wndPtr, &s, &e);
 	if (e == s)
-		return -1L;
-	ORDER_UINT(s, e);
+		return -1;
+	ORDER_INT32(s, e);
 	hdst = GlobalAlloc16(GMEM_MOVEABLE, (DWORD)(e - s + 1));
 	dst = GlobalLock16(hdst);
 	text = EDIT_GetPointer(wndPtr);
@@ -2216,7 +2900,7 @@
 	EmptyClipboard();
 	SetClipboardData(CF_TEXT, hdst);
 	CloseClipboard();
-	return -1L;
+	return -1;
 }
 
 
@@ -2227,9 +2911,9 @@
  */
 static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	CREATESTRUCT16 *cs = (CREATESTRUCT16 *)PTR_SEG_TO_LIN(lParam);
+	CREATESTRUCT32A *cs = (CREATESTRUCT32A *)lParam;
 	EDITSTATE *es;
-	char *text;
+	LPSTR text;
 
 	es = xmalloc(sizeof(EDITSTATE));
 	memset(es, 0, sizeof(EDITSTATE));
@@ -2254,27 +2938,19 @@
 		es->BufLimit = BUFLIMIT_SINGLE;
 		es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0';
 	}
-	if (!LOCAL_HeapSize(wndPtr->hInstance)) {
-		if (!LocalInit(wndPtr->hInstance, 0,
-                               GlobalSize16(wndPtr->hInstance))) {
-			fprintf(stderr, "edit: WM_CREATE: could not initialize local heap\n");
-			return -1L;
-		}
-		dprintf_edit(stddeb, "edit: WM_CREATE: local heap initialized\n");
-	}
-	if (!(es->hBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE, es->BufSize + 1))) {
+	if (!(es->hBuf32 = LocalAlloc32(LMEM_MOVEABLE, es->BufSize + 1))) {
 		fprintf(stderr, "edit: WM_CREATE: unable to allocate buffer\n");
-		return -1L;
+		return -1;
 	}
-	es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
+	es->BufSize = LocalSize32(es->hBuf32) - 1;
 	text = EDIT_GetPointer(wndPtr);
 	*text = '\0';
 	EDIT_BuildLineDefs(wndPtr);
-	EDIT_WM_SetFont(wndPtr, 0, 0L);
-	if (cs->lpszName && *(char *)PTR_SEG_TO_LIN(cs->lpszName) != '\0')
+	EDIT_WM_SetFont(wndPtr, 0, 0);
+	if (cs->lpszName && *(cs->lpszName) != '\0')
 		EDIT_EM_ReplaceSel(wndPtr, FALSE, (LPARAM)cs->lpszName);
-	EDIT_WM_SetRedraw(wndPtr, TRUE, 0L);
-	return 0L;
+	EDIT_WM_SetRedraw(wndPtr, TRUE, 0);
+	return 0;
 }
 
 
@@ -2285,9 +2961,9 @@
  */
 static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	EDIT_WM_Copy(wndPtr, 0, 0L);
-	EDIT_WM_Clear(wndPtr, 0, 0L);
-	return -1L;
+	EDIT_WM_Copy(wndPtr, 0, 0);
+	EDIT_WM_Clear(wndPtr, 0, 0);
+	return -1;
 }
 
 
@@ -2304,10 +2980,13 @@
 	if (es->TabStops)
 		free(es->TabStops);
 	EDIT_ReleasePointer(wndPtr);
-	LOCAL_Free(wndPtr->hInstance, es->hBuf);
+	if (es->hBuf32)
+		LocalFree32(es->hBuf32);
+	else
+		LOCAL_Free(wndPtr->hInstance, es->hBuf16);
 	free(es);
 	*(EDITSTATE **)&wndPtr->wExtra = NULL;
-	return 0L;
+	return 0;
 }
 
 
@@ -2319,7 +2998,7 @@
 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	EDIT_InvalidateText(wndPtr, 0, -1);
-	return 0L;
+	return 0;
 }
 
 
@@ -2331,23 +3010,23 @@
 static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	HBRUSH32 hBrush;
-	RECT16 rc;
+	RECT32 rc;
 
-	hBrush = (HBRUSH16)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
+	hBrush = (HBRUSH32)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
 	if (!hBrush) hBrush = (HBRUSH32)GetStockObject32(WHITE_BRUSH);
 
-	GetClientRect16(wndPtr->hwndSelf, &rc);
-	IntersectClipRect16( (HDC16)wParam, rc.left, rc.top,
-                             rc.right, rc.bottom);
-	GetClipBox16((HDC16)wParam, &rc);
+	GetClientRect32(wndPtr->hwndSelf, &rc);
+	IntersectClipRect32((HDC32)wParam, rc.left, rc.top,
+			     rc.right, rc.bottom);
+	GetClipBox32((HDC32)wParam, &rc);
 	/*
 	 *	FIXME:	specs say that we should UnrealizeObject() the brush,
 	 *		but the specs of UnrealizeObject() say that we shouldn't
 	 *		unrealize a stock object.  The default brush that
 	 *		DefWndProc() returns is ... a stock object.
 	 */
-	FillRect16((HDC16)wParam, &rc, hBrush);
-	return -1L;
+	FillRect32((HDC32)wParam, &rc, hBrush);
+	return -1;
 }
 
 
@@ -2382,14 +3061,14 @@
  */
 static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	char *text = EDIT_GetPointer(wndPtr);
-	int len;
-	LRESULT lResult = 0L;
+	LPSTR text = EDIT_GetPointer(wndPtr);
+	INT32 len;
+	LRESULT lResult = 0;
 
-	len = strlen(text);
-	if ((UINT)wParam > len) {
-		strcpy((char *)PTR_SEG_TO_LIN(lParam), text);
-		lResult = (LRESULT)len ;
+	len = lstrlen32A(text);
+	if ((INT32)wParam > len) {
+		lstrcpy32A((LPSTR)lParam, text);
+		lResult = (LRESULT)len + 1;
 	}
 	return lResult;
 }
@@ -2402,11 +3081,11 @@
  */
 static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	char *text = EDIT_GetPointer(wndPtr);
+	LPSTR text = EDIT_GetPointer(wndPtr);
 
-	return (LRESULT)strlen(text);
+	return (LRESULT)lstrlen32A(text);
 }
- 
+
 
 /*********************************************************************
  *
@@ -2417,13 +3096,13 @@
  */
 static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	UINT ww = EDIT_GetWndWidth(wndPtr);
-	UINT tw = EDIT_GetTextWidth(wndPtr);
-	UINT cw = EDIT_GetAveCharWidth(wndPtr);
-	UINT xoff = EDIT_GetXOffset(wndPtr);
-	INT dx = 0;
-	BOOL not = TRUE;
-	LRESULT ret = 0L;
+	INT32 ww = EDIT_GetWndWidth(wndPtr);
+	INT32 tw = EDIT_GetTextWidth(wndPtr);
+	INT32 cw = EDIT_GetAveCharWidth(wndPtr);
+	INT32 xoff = EDIT_GetXOffset(wndPtr);
+	INT32 dx = 0;
+	BOOL32 not = TRUE;
+	LRESULT ret = 0;
 
 	switch (wParam) {
 	case SB_LINELEFT:
@@ -2449,23 +3128,25 @@
  *		not = FALSE;
  */
 	case SB_THUMBPOSITION:
-		dx = LOWORD(lParam) * tw / 100 - xoff;
+		dx = HIWORD(wParam) * tw / 100 - xoff;
 		break;
 	/* The next two are undocumented ! */
-	case EM_GETTHUMB:
-		ret = tw ? MAKELONG(xoff * 100 / tw, 0) : 0;
+	case EM_GETTHUMB16:
+		ret = tw ? xoff * 100 / tw : 0;
 		break;
-	case EM_LINESCROLL:
-		dx = LOWORD(lParam);
+	case EM_LINESCROLL16:
+		dx = (INT16)HIWORD(wParam);
 		break;
 	case SB_ENDSCROLL:
 	default:
 		break;
 	}
 	if (dx) {
-		EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(0, dx));
-		if (not)
+		EDIT_EM_LineScroll(wndPtr, dx, 0);
+		if (not) {
+			dprintf_edit(stddeb, "edit: notification EN_HSCROLL sent\n");
 			EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
+		}
 	}
 	return ret;
 }
@@ -2481,17 +3162,18 @@
  */
 static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	BOOL shift;
-	BOOL control;
+	INT32 s;
+	INT32 e;
+	BOOL32 shift;
+	BOOL32 control;
 
 	if (GetKeyState(VK_MENU) & 0x8000)
-		return 0L;
+		return 0;
 
 	shift = GetKeyState(VK_SHIFT) & 0x8000;
 	control = GetKeyState(VK_CONTROL) & 0x8000;
 
+	EDIT_GetSel(wndPtr, &s, &e);
 	switch (wParam) {
 	case VK_LEFT:
 	case VK_UP:
@@ -2529,7 +3211,7 @@
 	case VK_BACK:
 		if (!IsReadOnly(wndPtr) && !control)
 			if (e != s)
-				EDIT_WM_Clear(wndPtr, 0, 0L);
+				EDIT_WM_Clear(wndPtr, 0, 0);
 			else
 				EDIT_DelLeft(wndPtr);
 		break;
@@ -2537,9 +3219,9 @@
 		if (!IsReadOnly(wndPtr) && !(shift && control))
 			if (e != s) {
 				if (shift)
-					EDIT_WM_Cut(wndPtr, 0, 0L);
+					EDIT_WM_Cut(wndPtr, 0, 0);
 				else
-					EDIT_WM_Clear(wndPtr, 0, 0L);
+					EDIT_WM_Clear(wndPtr, 0, 0);
 			} else {
 				if (shift)
 					EDIT_DelLeft(wndPtr);
@@ -2552,12 +3234,12 @@
 	case VK_INSERT:
 		if (shift) {
 			if (!IsReadOnly(wndPtr))
-				EDIT_WM_Paste(wndPtr, 0, 0L);
+				EDIT_WM_Paste(wndPtr, 0, 0);
 		} else if (control)
-			EDIT_WM_Copy(wndPtr, 0, 0L);
+			EDIT_WM_Copy(wndPtr, 0, 0);
 		break;
 	}
-	return 0L;
+	return 0;
 }
 
 
@@ -2568,17 +3250,17 @@
  */
 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	UINT s;
-	UINT e;
+	INT32 s;
+	INT32 e;
 
 	DestroyCaret();
 	if(!(wndPtr->dwStyle & ES_NOHIDESEL)) {
-		s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-		e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
+		EDIT_GetSel(wndPtr, &s, &e);
 		EDIT_InvalidateText(wndPtr, s, e);
 	}
+	dprintf_edit(stddeb, "edit: notification EN_KILLFOCUS sent\n");
 	EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS);
-	return 0L;
+	return 0;
 }
 
 
@@ -2591,17 +3273,22 @@
  */
 static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	UINT s;
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
-	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
-	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
-	char *text = EDIT_GetPointer(wndPtr);
+	INT32 s;
+	INT32 e;
+	INT32 l;
+	INT32 li;
+	INT32 ll;
+	LPSTR text = EDIT_GetPointer(wndPtr);
 
+	EDIT_GetSel(wndPtr, NULL, &e);
+	l = (INT32)EDIT_EM_LineFromChar(wndPtr, e, 0);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+	ll = (INT32)EDIT_EM_LineLength(wndPtr, e, 0);
 	s = li + EDIT_CallWordBreakProc (wndPtr, text + li, e - li, ll, WB_LEFT);
 	e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT);
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
-	return 0L;
+	EDIT_EM_SetSel(wndPtr, s, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	return 0;
 }
 
 
@@ -2612,29 +3299,30 @@
  */
 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	INT x = (INT)LOWORD(lParam);
-	INT y = (INT)HIWORD(lParam);
-	UINT l = EDIT_LineFromWndY(wndPtr, y);
-	UINT c;
-	UINT s;
-	UINT e;
-	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
-	UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
-	UINT li;
+	INT32 x = (INT32)(INT16)LOWORD(lParam);
+	INT32 y = (INT32)(INT16)HIWORD(lParam);
+	INT32 l = EDIT_LineFromWndY(wndPtr, y);
+	INT32 c;
+	INT32 s;
+	INT32 e;
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
+	INT32 li;
 
 	SetFocus32(wndPtr->hwndSelf);
 	SetCapture32(wndPtr->hwndSelf);
 	l = MIN(fv + vlc - 1, MAX(fv, l));
 	x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
 	c = EDIT_ColFromWndX(wndPtr, l, x);
-	li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
+	li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
 	e = li + c;
 	if (GetKeyState(VK_SHIFT) & 0x8000)
-		s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	else 
+		EDIT_GetSel(wndPtr, &s, NULL);
+	else
 		s = e;
-	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
-	return 0L;
+	EDIT_EM_SetSel(wndPtr, s, e);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	return 0;
 }
 
 
@@ -2647,7 +3335,7 @@
 {
 	if (GetCapture32() == wndPtr->hwndSelf)
 		ReleaseCapture();
-	return 0L;
+	return 0;
 }
 
 
@@ -2658,29 +3346,29 @@
  */
 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	INT x;
-	INT y;
-	UINT l;
-	UINT c;
-	UINT s;
-	UINT fv;
-	UINT vlc;
-	UINT li;
+	INT32 x;
+	INT32 y;
+	INT32 l;
+	INT32 c;
+	INT32 s;
+	INT32 fv;
+	INT32 vlc;
+	INT32 li;
 
 	if (GetCapture32() == wndPtr->hwndSelf) {
-		x = (INT)LOWORD(lParam);
-		y = (INT)HIWORD(lParam);
-		fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+		x = (INT32)(INT16)LOWORD(lParam);
+		y = (INT32)(INT16)HIWORD(lParam);
+		fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
 		vlc = EDIT_GetVisibleLineCount(wndPtr);
 		l = EDIT_LineFromWndY(wndPtr, y);
 		l = MIN(fv + vlc - 1, MAX(fv, l));
 		x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
 		c = EDIT_ColFromWndX(wndPtr, l, x);
-		s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-		li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
-		EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, li + c));
+		EDIT_GetSel(wndPtr, &s, NULL);
+		li = (INT32)EDIT_EM_LineIndex(wndPtr, l, 0);
+		EDIT_EM_SetSel(wndPtr, s, li + c);
 	}
-	return 0L;
+	return 0;
 }
 
 
@@ -2691,38 +3379,39 @@
  */
 static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	PAINTSTRUCT16 ps;
-	UINT i;
-	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
-	UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
-	HDC16 hdc;
-	HFONT16 hFont;
+	PAINTSTRUCT32 ps;
+	INT32 i;
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
+	HDC32 hdc;
+	HFONT32 hFont;
 	HFONT32 oldFont = 0;
-	RECT16 rc;
-	RECT16 rcLine;
-	RECT16 rcRgn;
-	BOOL rev = IsWindowEnabled(wndPtr->hwndSelf) &&
+	RECT32 rc;
+	RECT32 rcLine;
+	RECT32 rcRgn;
+	BOOL32 rev = IsWindowEnabled(wndPtr->hwndSelf) &&
 				((GetFocus32() == wndPtr->hwndSelf) ||
 					(wndPtr->dwStyle & ES_NOHIDESEL));
 
-	hdc = BeginPaint16(wndPtr->hwndSelf, &ps);
-	GetClientRect16(wndPtr->hwndSelf, &rc);
-	IntersectClipRect16( hdc, rc.left, rc.top, rc.right, rc.bottom );
-	hFont = EDIT_WM_GetFont(wndPtr, 0, 0L);
-	if (hFont) oldFont = SelectObject32(hdc, hFont);
+	hdc = BeginPaint32(wndPtr->hwndSelf, &ps);
+	GetClientRect32(wndPtr->hwndSelf, &rc);
+	IntersectClipRect32( hdc, rc.left, rc.top, rc.right, rc.bottom );
+	hFont = (HFONT32)EDIT_WM_GetFont(wndPtr, 0, 0);
+	if (hFont)
+		oldFont = (HFONT32)SelectObject32(hdc, hFont);
 	EDIT_SEND_CTLCOLOR(wndPtr, hdc);
 	if (!IsWindowEnabled(wndPtr->hwndSelf))
 		SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
-	GetClipBox16(hdc, &rcRgn);
+	GetClipBox32(hdc, &rcRgn);
 	for (i = fv ; i <= MIN(fv + vlc, fv + lc - 1) ; i++ ) {
 		EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine);
-		if (IntersectRect16(&rc, &rcRgn, &rcLine))
+		if (IntersectRect32(&rc, &rcRgn, &rcLine))
 			EDIT_PaintLine(wndPtr, hdc, i, rev);
 	}
 	if (hFont) SelectObject32(hdc, oldFont);
-	EndPaint16(wndPtr->hwndSelf, &ps);
-	return 0L;
+	EndPaint32(wndPtr->hwndSelf, &ps);
+	return 0;
 }
 
 
@@ -2734,16 +3423,16 @@
 static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
 	HGLOBAL16 hsrc;
-	char *src;
+	LPSTR src;
 
 	OpenClipboard(wndPtr->hwndSelf);
 	if ((hsrc = GetClipboardData(CF_TEXT))) {
-		src = (char *)GlobalLock16(hsrc);
-		EDIT_ReplaceSel(wndPtr, 0, (LPARAM)src);
+		src = (LPSTR)GlobalLock16(hsrc);
+		EDIT_EM_ReplaceSel(wndPtr, 0, (LPARAM)src);
 		GlobalUnlock16(hsrc);
 	}
 	CloseClipboard();
-	return -1L;
+	return -1;
 }
 
 
@@ -2756,9 +3445,9 @@
 {
 	if (LOWORD(lParam) == HTCLIENT) {
 		SetCursor(LoadCursor16(0, IDC_IBEAM));
-		return -1L;
+		return -1;
 	} else
-		return 0L;
+		return 0;
 }
 
 
@@ -2769,16 +3458,18 @@
  */
 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	UINT s = LOWORD(EDIT_GetSel(wndPtr, 0, 0L));
-	UINT e = HIWORD(EDIT_GetSel(wndPtr, 0, 0L));
+	INT32 s;
+	INT32 e;
 
+	EDIT_GetSel(wndPtr, &s, &e);
 	CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
-	EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, s, e);
 	if(!(wndPtr->dwStyle & ES_NOHIDESEL))
 		EDIT_InvalidateText(wndPtr, s, e);
 	ShowCaret(wndPtr->hwndSelf);
+	dprintf_edit(stddeb, "edit: notification EN_SETFOCUS sent\n");
 	EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS);
-	return 0L;
+	return 0;
 }
 
 
@@ -2789,30 +3480,32 @@
  */
 static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	TEXTMETRIC16 tm;
+	TEXTMETRIC32A tm;
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	LPARAM sel = EDIT_GetSel(wndPtr, 0, 0L);
+	INT32 s;
+	INT32 e;
 	HDC32 hdc;
 	HFONT32 oldFont = 0;
 
-	es->hFont = (HFONT16)wParam;
+	EDIT_GetSel(wndPtr, &s, &e);
+	es->hFont = (HFONT32)wParam;
 	hdc = GetDC32(wndPtr->hwndSelf);
 	if (es->hFont) oldFont = SelectObject32(hdc, es->hFont);
-	GetTextMetrics16(hdc, &tm);
-	es->LineHeight = HIWORD(GetTextExtent(hdc, "X", 1));
+	GetTextMetrics32A(hdc, &tm);
+	es->LineHeight = tm.tmHeight;
 	es->AveCharWidth = tm.tmAveCharWidth;
 	if (es->hFont) SelectObject32(hdc, oldFont);
 	ReleaseDC32(wndPtr->hwndSelf, hdc);
 	EDIT_BuildLineDefs(wndPtr);
-	if ((BOOL)lParam && EDIT_GetRedraw(wndPtr))
+	if ((BOOL32)lParam && EDIT_GetRedraw(wndPtr))
 		InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
 	if (wndPtr->hwndSelf == GetFocus32()) {
 		DestroyCaret();
 		CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
-		EDIT_EM_SetSel(wndPtr, 1, sel);
+		EDIT_EM_SetSel16(wndPtr, s, e);
 		ShowCaret(wndPtr->hwndSelf);
 	}
-	return 0L;
+	return 0;
 }
 
 
@@ -2825,8 +3518,8 @@
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-	es->Redraw = (BOOL)wParam;
-	return 0L;
+	es->Redraw = (BOOL32)wParam;
+	return 0;
 }
 
 
@@ -2837,14 +3530,15 @@
  */
 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(0, -1));
-	EDIT_WM_Clear(wndPtr, 0, 0L);
+	EDIT_EM_SetSel(wndPtr, 0, -1);
 	if (lParam)
 		EDIT_EM_ReplaceSel(wndPtr, 0, lParam);
-	EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
-	EDIT_EM_SetModify(wndPtr, TRUE, 0L);
-	EDIT_ScrollIntoView(wndPtr);
-	return 0L;
+	else
+            EDIT_WM_Clear(wndPtr, 0, 0);
+	EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0);
+	EDIT_EM_SetModify(wndPtr, TRUE, 0);
+	EDIT_EM_ScrollCaret(wndPtr, 0, 0);
+	return 1;
 }
 
 
@@ -2852,9 +3546,14 @@
  *
  *	WM_SIZE
  *
+ *	FIXME: What about that FormatRect ???
+ *
  */
 static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	GetClientRect32(wndPtr->hwndSelf, &es->FormatRect);
 	if (EDIT_GetRedraw(wndPtr) &&
 			((wParam == SIZE_MAXIMIZED) ||
 				(wParam == SIZE_RESTORED))) {
@@ -2862,7 +3561,7 @@
 			EDIT_BuildLineDefs(wndPtr);
 		InvalidateRect32( wndPtr->hwndSelf, NULL, TRUE );
 	}
-	return 0L;
+	return 0;
 }
 
 
@@ -2875,12 +3574,12 @@
  */
 static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
-	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
-	UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
-	INT dy = 0;
-	BOOL not = TRUE;
-	LRESULT ret = 0L;
+	INT32 lc = (INT32)EDIT_EM_GetLineCount(wndPtr, 0, 0);
+	INT32 fv = (INT32)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0);
+	INT32 vlc = EDIT_GetVisibleLineCount(wndPtr);
+	INT32 dy = 0;
+	BOOL32 not = TRUE;
+	LRESULT ret = 0;
 
 	switch (wParam) {
 	case SB_LINEUP:
@@ -2902,27 +3601,28 @@
 		dy = lc - 1 - fv;
 		break;
 	case SB_THUMBTRACK:
-/*
- *		not = FALSE;
- */
+		not = FALSE;
+		/* fall through */
 	case SB_THUMBPOSITION:
-		dy = LOWORD(lParam) * (lc - 1) / 100 - fv;
+		dy = HIWORD(wParam) * (lc - 1) / 100 - fv;
 		break;
 	/* The next two are undocumented ! */
-	case EM_GETTHUMB:
-		ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0L;
+	case EM_GETTHUMB16:
+		ret = (lc > 1) ? MAKELONG(fv * 100 / (lc - 1), 0) : 0;
 		break;
-	case EM_LINESCROLL:
-		dy = LOWORD(lParam);
+	case EM_LINESCROLL16:
+		dy = (INT16)LOWORD(lParam);
 		break;
 	case SB_ENDSCROLL:
 	default:
 		break;
 	}
 	if (dy) {
-		EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, 0));
-		if (not)
+		EDIT_EM_LineScroll(wndPtr, 0, dy);
+		if (not) {
+			dprintf_edit(stddeb, "edit: notification EN_VSCROLL sent\n");
 			EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
+		}
 	}
 	return ret;
 }
diff --git a/controls/listbox.c b/controls/listbox.c
index 70f13b3..0f3b431 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -1487,7 +1487,7 @@
                 if (long_names) strcpy( buffer, entry.cFileName );
                 else strcpy( buffer, entry.cAlternateFileName );
             }
-            if (!long_names) AnsiLower( buffer );
+            if (!long_names) CharLower32A( buffer );
             pos = LISTBOX_FindFileStrPos( wnd, descr, buffer );
             if ((ret = LISTBOX_InsertString( wnd, descr, pos, buffer )) < 0)
                 break;
@@ -2206,8 +2206,12 @@
 
     case LB_SELITEMRANGE16:
     case LB_SELITEMRANGE32:
-        return LISTBOX_SelectItemRange( wnd, descr, LOWORD(lParam),
-                                        HIWORD(lParam), wParam );
+        if (LOWORD(lParam) <= HIWORD(lParam))
+            return LISTBOX_SelectItemRange( wnd, descr, LOWORD(lParam),
+                                            HIWORD(lParam), wParam );
+        else
+            return LISTBOX_SelectItemRange( wnd, descr, HIWORD(lParam),
+                                            LOWORD(lParam), wParam );
 
     case LB_SELITEMRANGEEX16:
     case LB_SELITEMRANGEEX32:
diff --git a/controls/menu.c b/controls/menu.c
index 8c6123f..197262f 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -11,6 +11,7 @@
  * This is probably not the meaning this style has in MS-Windows.
  */
 
+#define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -24,6 +25,7 @@
 #include "menu.h"
 #include "module.h"
 #include "neexe.h"
+#include "nonclient.h"
 #include "user.h"
 #include "message.h"
 #include "graphics.h"
@@ -34,12 +36,12 @@
 /* Menu item structure */
 typedef struct
 {
-    WORD	item_flags;    /* Item flags */
-    UINT	item_id;       /* Item or popup id */
-    RECT16      rect;          /* Item area (relative to menu window) */
-    WORD        xTab;          /* X position of text after Tab */
-    HBITMAP16	hCheckBit;     /* Bitmap for checked item */
-    HBITMAP16	hUnCheckBit;   /* Bitmap for unchecked item */
+    UINT32      item_flags;    /* Item flags */
+    UINT32      item_id;       /* Item or popup id */
+    RECT32      rect;          /* Item area (relative to menu window) */
+    UINT32      xTab;          /* X position of text after Tab */
+    HBITMAP32   hCheckBit;     /* Bitmap for checked item */
+    HBITMAP32   hUnCheckBit;   /* Bitmap for unchecked item */
     LPSTR       text;          /* Item text or bitmap handle */
 } MENUITEM;
 
@@ -52,9 +54,9 @@
     WORD	Width;        /* Width of the whole menu */
     WORD	Height;       /* Height of the whole menu */
     WORD	nItems;       /* Number of items in the menu */
-    HWND	hWnd;	      /* Window containing the menu */
+    HWND32      hWnd;         /* Window containing the menu */
     MENUITEM   *items;        /* Array of menu items */
-    UINT	FocusedItem;  /* Currently focused item */
+    UINT32      FocusedItem;  /* Currently focused item */
 } POPUPMENU, *LPPOPUPMENU;
 
 #define MENU_MAGIC   0x554d  /* 'MU' */
@@ -67,7 +69,7 @@
 static WORD arrow_bitmap_width = 0, arrow_bitmap_height = 0;
 
   /* Flag set by EndMenu() to force an exit from menu tracking */
-static BOOL fEndMenuCalled = FALSE;
+static BOOL32 fEndMenuCalled = FALSE;
 
   /* Space between 2 menu bar items */
 #define MENU_BAR_ITEMS_SPACE  16
@@ -86,12 +88,9 @@
 #define IS_STRING_ITEM(flags) \
     (!((flags) & (MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR)))
 
-extern void  NC_DrawSysButton(HWND hwnd, HDC32 hdc, BOOL down); /*nonclient.c*/
-extern BOOL  NC_GetSysPopupPos(WND* wndPtr, RECT16* rect);
-
-static HBITMAP16 hStdCheck = 0;
-static HBITMAP16 hStdMnArrow = 0;
-static HMENU16 MENU_DefSysMenu = 0;  /* Default system menu */
+static HBITMAP32 hStdCheck = 0;
+static HBITMAP32 hStdMnArrow = 0;
+static HMENU32 MENU_DefSysMenu = 0;  /* Default system menu */
 
 
 /* we _can_ use global popup window because there's no way 2 menues can
@@ -99,7 +98,7 @@
  */ 
 
 static WND* pTopPWnd   = 0;
-static UINT uSubPWndLevel = 0;
+static UINT32 uSubPWndLevel = 0;
 
 
 /**********************************************************************
@@ -107,9 +106,9 @@
  *
  * Load a copy of the system menu.
  */
-static HMENU16 MENU_CopySysMenu(void)
+static HMENU32 MENU_CopySysMenu(void)
 {
-    HMENU16 hMenu;
+    HMENU32 hMenu;
     POPUPMENU *menu;
 
     if (!(hMenu = LoadMenuIndirect32A( SYSRES_GetResPtr(SYSRES_MENU_SYSMENU))))
@@ -129,20 +128,20 @@
  *
  * Menus initialisation.
  */
-BOOL MENU_Init()
+BOOL32 MENU_Init()
 {
-    BITMAP16 bm;
+    BITMAP32 bm;
 
       /* Load bitmaps */
 
-    if (!(hStdCheck = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_CHECK) )))
+    if (!(hStdCheck = LoadBitmap32A( 0, (LPSTR)MAKEINTRESOURCE(OBM_CHECK) )))
 	return FALSE;
-    GetObject16( hStdCheck, sizeof(bm), &bm );
+    GetObject32A( hStdCheck, sizeof(bm), &bm );
     check_bitmap_width = bm.bmWidth;
     check_bitmap_height = bm.bmHeight;
-    if (!(hStdMnArrow = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_MNARROW) )))
+    if (!(hStdMnArrow = LoadBitmap32A(0,(LPSTR)MAKEINTRESOURCE(OBM_MNARROW))))
 	return FALSE;
-    GetObject16( hStdMnArrow, sizeof(bm), &bm );
+    GetObject32A( hStdMnArrow, sizeof(bm), &bm );
     arrow_bitmap_width = bm.bmWidth;
     arrow_bitmap_height = bm.bmHeight;
 
@@ -160,7 +159,7 @@
  *
  * Return the default system menu.
  */
-HMENU16 MENU_GetDefSysMenu(void)
+HMENU32 MENU_GetDefSysMenu(void)
 {
     return MENU_DefSysMenu;
 }
@@ -171,7 +170,7 @@
  *
  * Check whether the window owning the menu bar has a system menu.
  */
-static BOOL MENU_HasSysMenu( POPUPMENU *menu )
+static BOOL32 MENU_HasSysMenu( POPUPMENU *menu )
 {
     WND *wndPtr;
 
@@ -187,7 +186,7 @@
  * Check whether the point (in screen coords) is in the system menu
  * of the window owning the given menu.
  */
-static BOOL MENU_IsInSysMenu( POPUPMENU *menu, POINT16 pt )
+static BOOL32 MENU_IsInSysMenu( POPUPMENU *menu, POINT32 pt )
 {
     WND *wndPtr;
 
@@ -209,22 +208,22 @@
  *
  * Grey the appropriate items in System menu.
  */
-void MENU_InitSysMenuPopup(HMENU16 hmenu, DWORD style, DWORD clsStyle)
+void MENU_InitSysMenuPopup( HMENU32 hmenu, DWORD style, DWORD clsStyle )
 {
-    BOOL gray;
+    BOOL32 gray;
 
     gray = !(style & WS_THICKFRAME) || (style & (WS_MAXIMIZE | WS_MINIMIZE));
-    EnableMenuItem( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+    EnableMenuItem32( hmenu, SC_SIZE, (gray ? MF_GRAYED : MF_ENABLED) );
     gray = ((style & WS_MAXIMIZE) != 0);
-    EnableMenuItem( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
+    EnableMenuItem32( hmenu, SC_MOVE, (gray ? MF_GRAYED : MF_ENABLED) );
     gray = !(style & WS_MINIMIZEBOX) || (style & WS_MINIMIZE);
-    EnableMenuItem( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+    EnableMenuItem32( hmenu, SC_MINIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
     gray = !(style & WS_MAXIMIZEBOX) || (style & WS_MAXIMIZE);
-    EnableMenuItem( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
+    EnableMenuItem32( hmenu, SC_MAXIMIZE, (gray ? MF_GRAYED : MF_ENABLED) );
     gray = !(style & (WS_MAXIMIZE | WS_MINIMIZE));
-    EnableMenuItem( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
+    EnableMenuItem32( hmenu, SC_RESTORE, (gray ? MF_GRAYED : MF_ENABLED) );
     gray = (clsStyle & CS_NOCLOSE) != 0;
-    EnableMenuItem( hmenu, SC_CLOSE, (gray ? MF_GRAYED : MF_ENABLED) );
+    EnableMenuItem32( hmenu, SC_CLOSE, (gray ? MF_GRAYED : MF_ENABLED) );
 }
 
 
@@ -234,10 +233,10 @@
  * Find a menu item. Return a pointer on the item, and modifies *hmenu
  * in case the item was in a sub-menu.
  */
-static MENUITEM *MENU_FindItem( HMENU16 *hmenu, UINT *nPos, UINT wFlags )
+static MENUITEM *MENU_FindItem( HMENU32 *hmenu, UINT32 *nPos, UINT32 wFlags )
 {
     POPUPMENU *menu;
-    int i;
+    UINT32 i;
 
     if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR(*hmenu))) return NULL;
     if (wFlags & MF_BYPOSITION)
@@ -257,7 +256,7 @@
 	    }
 	    else if (item->item_flags & MF_POPUP)
 	    {
-		HMENU16 hsubmenu = (HMENU16)item->item_id;
+		HMENU32 hsubmenu = (HMENU32)item->item_id;
 		MENUITEM *subitem = MENU_FindItem( &hsubmenu, nPos, wFlags );
 		if (subitem)
 		{
@@ -276,11 +275,12 @@
  *
  * Find the item at the specified coordinates (screen coords).
  */
-static MENUITEM *MENU_FindItemByCoords( POPUPMENU *menu, int x, int y, UINT *pos )
+static MENUITEM *MENU_FindItemByCoords( POPUPMENU *menu, INT32 x, INT32 y,
+                                        UINT32 *pos )
 {
     MENUITEM *item;
     WND *wndPtr;
-    int i;
+    UINT32 i;
 
     if (!(wndPtr = WIN_FindWndPtr( menu->hWnd ))) return NULL;
     x -= wndPtr->rectWindow.left;
@@ -305,14 +305,14 @@
  * Find the menu item selected by a key press.
  * Return item id, -1 if none, -2 if we should close the menu.
  */
-static UINT MENU_FindItemByKey( HWND hwndOwner, HMENU16 hmenu, UINT key )
+static UINT32 MENU_FindItemByKey( HWND32 hwndOwner, HMENU32 hmenu, UINT32 key )
 {
     POPUPMENU *menu;
     MENUITEM *item;
-    int i;
+    UINT32 i;
     LONG menuchar;
 
-    if (!IsMenu( hmenu )) hmenu = WIN_FindWndPtr(hwndOwner)->hSysMenu;
+    if (!IsMenu32( hmenu )) hmenu = WIN_FindWndPtr(hwndOwner)->hSysMenu;
     if (!hmenu) return -1;
 
     menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
@@ -339,29 +339,27 @@
  *
  * Calculate the size of the menu item and store it in lpitem->rect.
  */
-static void MENU_CalcItemSize( HDC32 hdc, MENUITEM *lpitem, HWND hwndOwner,
-			       int orgX, int orgY, BOOL menuBar )
+static void MENU_CalcItemSize( HDC32 hdc, MENUITEM *lpitem, HWND32 hwndOwner,
+			       INT32 orgX, INT32 orgY, BOOL32 menuBar )
 {
     DWORD dwSize;
     char *p;
 
-    SetRect16( &lpitem->rect, orgX, orgY, orgX, orgY );
+    SetRect32( &lpitem->rect, orgX, orgY, orgX, orgY );
 
     if (lpitem->item_flags & MF_OWNERDRAW)
     {
-        MEASUREITEMSTRUCT16 *mis;
-        if (!(mis = SEGPTR_NEW(MEASUREITEMSTRUCT16))) return;
-        mis->CtlType    = ODT_MENU;
-        mis->itemID     = lpitem->item_id;
-        mis->itemData   = (DWORD)lpitem->text;
-        mis->itemHeight = 16;
-        mis->itemWidth  = 30;
-        SendMessage16( hwndOwner, WM_MEASUREITEM, 0, (LPARAM)SEGPTR_GET(mis) );
-        lpitem->rect.bottom += mis->itemHeight;
-        lpitem->rect.right  += mis->itemWidth;
+        MEASUREITEMSTRUCT32 mis;
+        mis.CtlType    = ODT_MENU;
+        mis.itemID     = lpitem->item_id;
+        mis.itemData   = (DWORD)lpitem->text;
+        mis.itemHeight = 16;
+        mis.itemWidth  = 30;
+        SendMessage32A( hwndOwner, WM_MEASUREITEM, 0, (LPARAM)&mis );
+        lpitem->rect.bottom += mis.itemHeight;
+        lpitem->rect.right  += mis.itemWidth;
         dprintf_menu( stddeb, "DrawMenuItem: MeasureItem %04x %dx%d!\n",
-                      lpitem->item_id, mis->itemWidth, mis->itemHeight );
-        SEGPTR_FREE(mis);
+                      lpitem->item_id, mis.itemWidth, mis.itemHeight );
         return;
     } 
 
@@ -380,8 +378,8 @@
 
     if (lpitem->item_flags & MF_BITMAP)
     {
-	BITMAP16 bm;
-        if (GetObject16( (HBITMAP16)(UINT32)lpitem->text, sizeof(bm), &bm ))
+	BITMAP32 bm;
+        if (GetObject32A( (HBITMAP32)lpitem->text, sizeof(bm), &bm ))
         {
             lpitem->rect.right  += bm.bmWidth;
             lpitem->rect.bottom += bm.bmHeight;
@@ -423,7 +421,7 @@
  *
  * Calculate the size of a popup menu.
  */
-static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND hwndOwner )
+static void MENU_PopupMenuCalcSize( LPPOPUPMENU lppop, HWND32 hwndOwner )
 {
     MENUITEM *lpitem;
     HDC32 hdc;
@@ -478,8 +476,8 @@
  *
  * Calculate the size of the menu bar.
  */
-static void MENU_MenuBarCalcSize( HDC32 hdc, LPRECT16 lprect,
-                                  LPPOPUPMENU lppop, HWND hwndOwner )
+static void MENU_MenuBarCalcSize( HDC32 hdc, LPRECT32 lprect,
+                                  LPPOPUPMENU lppop, HWND32 hwndOwner )
 {
     MENUITEM *lpitem;
     int start, i, orgX, orgY, maxY, helpPos;
@@ -546,10 +544,10 @@
  *
  * Draw a single menu item.
  */
-static void MENU_DrawMenuItem( HWND hwnd, HDC32 hdc, MENUITEM *lpitem,
-			       UINT height, BOOL menuBar )
+static void MENU_DrawMenuItem( HWND32 hwnd, HDC32 hdc, MENUITEM *lpitem,
+			       UINT32 height, BOOL32 menuBar )
 {
-    RECT16 rect;
+    RECT32 rect;
 
     if (lpitem->item_flags & MF_OWNERDRAW)
     {
@@ -566,7 +564,7 @@
         dis.itemAction = ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS;
         dis.hwndItem   = hwnd;
         dis.hDC        = hdc;
-        CONV_RECT16TO32( &lpitem->rect, &dis.rcItem );
+        dis.rcItem     = lpitem->rect;
         SendMessage32A( hwnd, WM_DRAWITEM, 0, (LPARAM)&dis );
         return;
     }
@@ -577,8 +575,8 @@
       /* Draw the background */
 
     if (lpitem->item_flags & MF_HILITE)
-	FillRect16( hdc, &rect, sysColorObjects.hbrushHighlight );
-    else FillRect16( hdc, &rect, sysColorObjects.hbrushMenu );
+	FillRect32( hdc, &rect, sysColorObjects.hbrushHighlight );
+    else FillRect32( hdc, &rect, sysColorObjects.hbrushMenu );
     SetBkMode32( hdc, TRANSPARENT );
 
       /* Draw the separator bar (if any) */
@@ -675,19 +673,19 @@
                     break;
 	}
 	
-	DrawText16( hdc, lpitem->text, i, &rect,
-                    DT_LEFT | DT_VCENTER | DT_SINGLELINE );
+	DrawText32A( hdc, lpitem->text, i, &rect,
+                     DT_LEFT | DT_VCENTER | DT_SINGLELINE );
 
 	if (lpitem->text[i])  /* There's a tab or flush-right char */
 	{
 	    if (lpitem->text[i] == '\t')
 	    {
 		rect.left = lpitem->xTab;
-		DrawText16( hdc, lpitem->text + i + 1, -1, &rect,
-                            DT_LEFT | DT_VCENTER | DT_SINGLELINE );
+		DrawText32A( hdc, lpitem->text + i + 1, -1, &rect,
+                             DT_LEFT | DT_VCENTER | DT_SINGLELINE );
 	    }
-	    else DrawText16( hdc, lpitem->text + i + 1, -1, &rect,
-                             DT_RIGHT | DT_VCENTER | DT_SINGLELINE );
+	    else DrawText32A( hdc, lpitem->text + i + 1, -1, &rect,
+                              DT_RIGHT | DT_VCENTER | DT_SINGLELINE );
 	}
     }
 }
@@ -698,15 +696,15 @@
  *
  * Paint a popup menu.
  */
-static void MENU_DrawPopupMenu( HWND hwnd, HDC32 hdc, HMENU16 hmenu )
+static void MENU_DrawPopupMenu( HWND32 hwnd, HDC32 hdc, HMENU32 hmenu )
 {
     POPUPMENU *menu;
     MENUITEM *item;
-    RECT16 rect;
-    int i;
+    RECT32 rect;
+    UINT32 i;
 
-    GetClientRect16( hwnd, &rect );
-    FillRect16( hdc, &rect, sysColorObjects.hbrushMenu );
+    GetClientRect32( hwnd, &rect );
+    FillRect32( hdc, &rect, sysColorObjects.hbrushMenu );
     menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
     if (!menu || !menu->nItems) return;
     for (i = menu->nItems, item = menu->items; i > 0; i--, item++)
@@ -719,11 +717,11 @@
  *
  * Paint a menu bar. Returns the height of the menu bar.
  */
-UINT MENU_DrawMenuBar( HDC32 hDC, LPRECT16 lprect, HWND hwnd,
-                       BOOL suppress_draw)
+UINT32 MENU_DrawMenuBar( HDC32 hDC, LPRECT32 lprect, HWND32 hwnd,
+                         BOOL32 suppress_draw)
 {
     LPPOPUPMENU lppop;
-    int i;
+    UINT32 i;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
     
     lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR( (HMENU16)wndPtr->wIDmenu );
@@ -734,7 +732,7 @@
     lprect->bottom = lprect->top + lppop->Height;
     if (suppress_draw) return lppop->Height;
     
-    FillRect16(hDC, lprect, sysColorObjects.hbrushMenu );
+    FillRect32(hDC, lprect, sysColorObjects.hbrushMenu );
     SelectObject32( hDC, sysColorObjects.hpenWindowFrame );
     MoveTo( hDC, lprect->left, lprect->bottom );
     LineTo32( hDC, lprect->right, lprect->bottom );
@@ -784,13 +782,13 @@
  *
  * Display a popup menu.
  */
-static BOOL MENU_ShowPopup(HWND hwndOwner, HMENU16 hmenu, UINT id, int x, int y, 
-						        int xanchor, int yanchor)
+static BOOL32 MENU_ShowPopup( HWND32 hwndOwner, HMENU32 hmenu, UINT32 id,
+                              INT32 x, INT32 y, INT32 xanchor, INT32 yanchor )
 {
     POPUPMENU 	*menu;
     WND 	*wndPtr = NULL;
-    BOOL	 skip_init = 0;
-    UINT	 width, height;
+    BOOL32	 skip_init = 0;
+    UINT32	 width, height;
 
     if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu ))) return FALSE;
     if (menu->FocusedItem != NO_SELECTED_ITEM)
@@ -799,7 +797,7 @@
 	menu->FocusedItem = NO_SELECTED_ITEM;
     }
     SendMessage16( hwndOwner, WM_INITMENUPOPUP, (WPARAM16)hmenu,
-		 MAKELONG( id, (menu->wFlags & MF_SYSMENU) ? 1 : 0 ));
+                   MAKELONG( id, (menu->wFlags & MF_SYSMENU) ? 1 : 0 ));
     MENU_PopupMenuCalcSize( menu, hwndOwner );
 
     /* adjust popup menu pos so that it fits within the desktop */
@@ -832,11 +830,11 @@
 
     if (!pTopPWnd)
     {
-	pTopPWnd = WIN_FindWndPtr(CreateWindow16( POPUPMENU_CLASS_ATOM, NULL,
+	pTopPWnd = WIN_FindWndPtr(CreateWindow32A( POPUPMENU_CLASS_ATOM, NULL,
                                           WS_POPUP | WS_BORDER, x, y,
                                           width, height,
                                           hwndOwner, 0, wndPtr->hInstance,
-                                          (LPVOID)(HMENU32)hmenu ));
+                                          (LPVOID)hmenu ));
 	if (!pTopPWnd) return FALSE;
 	skip_init = TRUE;
     }
@@ -844,11 +842,11 @@
     if( uSubPWndLevel )
     {
 	/* create new window for the submenu */
-	HWND  hWnd = CreateWindow16( POPUPMENU_CLASS_ATOM, NULL,
-                                   WS_POPUP | WS_BORDER, x, y,
-				   width, height,
-                                   menu->hWnd, 0, wndPtr->hInstance,
-                                   (LPVOID)(HMENU32)hmenu );
+	HWND32 hWnd = CreateWindow32A( POPUPMENU_CLASS_ATOM, NULL,
+                                      WS_POPUP | WS_BORDER, x, y,
+                                      width, height,
+                                      menu->hWnd, 0, wndPtr->hInstance,
+                                      (LPVOID)hmenu );
 	if( !hWnd ) return FALSE;
 	menu->hWnd = hWnd;
     }
@@ -880,8 +878,8 @@
 /***********************************************************************
  *           MENU_SelectItem
  */
-static void MENU_SelectItem( HWND hwndOwner, HMENU16 hmenu, UINT wIndex,
-                             BOOL sendMenuSelect )
+static void MENU_SelectItem( HWND32 hwndOwner, HMENU32 hmenu, UINT32 wIndex,
+                             BOOL32 sendMenuSelect )
 {
     LPPOPUPMENU lppop;
     HDC32 hdc;
@@ -944,9 +942,9 @@
  *           MENU_SelectItemRel
  *
  */
-static void MENU_SelectItemRel( HWND hwndOwner, HMENU16 hmenu, int offset )
+static void MENU_SelectItemRel( HWND32 hwndOwner, HMENU32 hmenu, INT32 offset )
 {
-    int i, min = 0;
+    INT32 i, min = 0;
     POPUPMENU *menu;
 
     menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
@@ -992,7 +990,8 @@
  *
  * Set an item flags, id and text ptr.
  */
-static BOOL MENU_SetItemData( MENUITEM *item, UINT flags, UINT id, LPCSTR str )
+static BOOL32 MENU_SetItemData( MENUITEM *item, UINT32 flags, UINT32 id,
+                                LPCSTR str )
 {
     LPSTR prevText = IS_STRING_ITEM(item->item_flags) ? item->text : NULL;
 
@@ -1022,7 +1021,7 @@
 
     item->item_flags = flags & ~(MF_HILITE | MF_MOUSESELECT);
     item->item_id    = id;
-    SetRectEmpty16( &item->rect );
+    SetRectEmpty32( &item->rect );
     if (prevText) HeapFree( SystemHeap, 0, prevText );
     return TRUE;
 }
@@ -1033,7 +1032,7 @@
  *
  * Insert a new item into a menu.
  */
-static MENUITEM *MENU_InsertItem( HMENU16 hMenu, UINT pos, UINT flags )
+static MENUITEM *MENU_InsertItem( HMENU32 hMenu, UINT32 pos, UINT32 flags )
 {
     MENUITEM *newItems;
     POPUPMENU *menu;
@@ -1048,7 +1047,7 @@
     /* Find where to insert new item */
 
     if ((flags & MF_BYPOSITION) &&
-        ((pos == (UINT)-1) || (pos == menu->nItems)))
+        ((pos == (UINT32)-1) || (pos == menu->nItems)))
     {
         /* Special case: append to menu */
         /* Some programs specify the menu length to do that */
@@ -1099,7 +1098,7 @@
  * Parse a standard menu resource and add items to the menu.
  * Return a pointer to the end of the resource.
  */
-static LPCSTR MENU_ParseResource( LPCSTR res, HMENU16 hMenu, BOOL unicode )
+static LPCSTR MENU_ParseResource( LPCSTR res, HMENU32 hMenu, BOOL32 unicode )
 {
     WORD flags, id = 0;
     LPCSTR str;
@@ -1121,12 +1120,12 @@
         else res += (lstrlen32W((LPCWSTR)str) + 1) * sizeof(WCHAR);
         if (flags & MF_POPUP)
         {
-            HMENU16 hSubMenu = CreatePopupMenu();
+            HMENU32 hSubMenu = CreatePopupMenu32();
             if (!hSubMenu) return NULL;
             if (!(res = MENU_ParseResource( res, hSubMenu, unicode )))
                 return NULL;
-            if (!unicode) AppendMenu32A( hMenu, flags, (UINT)hSubMenu, str );
-            else AppendMenu32W( hMenu, flags, (UINT)hSubMenu, (LPCWSTR)str );
+            if (!unicode) AppendMenu32A( hMenu, flags, (UINT32)hSubMenu, str );
+            else AppendMenu32W( hMenu, flags, (UINT32)hSubMenu, (LPCWSTR)str );
         }
         else  /* Not a popup */
         {
@@ -1144,7 +1143,7 @@
  *
  * Return the handle of the selected sub-popup menu (if any).
  */
-static HMENU16 MENU_GetSubPopup( HMENU16 hmenu )
+static HMENU32 MENU_GetSubPopup( HMENU32 hmenu )
 {
     POPUPMENU *menu;
     MENUITEM *item;
@@ -1157,7 +1156,7 @@
     item = &menu->items[menu->FocusedItem];
     if (!(item->item_flags & MF_POPUP) || !(item->item_flags & MF_MOUSESELECT))
 	return 0;
-    return (HMENU16)item->item_id;
+    return (HMENU32)item->item_id;
 }
 
 
@@ -1166,12 +1165,12 @@
  *
  * Hide the sub-popup menus of this menu.
  */
-static void MENU_HideSubPopups( HWND hwndOwner, HMENU16 hmenu,
-                                BOOL sendMenuSelect )
+static void MENU_HideSubPopups( HWND32 hwndOwner, HMENU32 hmenu,
+                                BOOL32 sendMenuSelect )
 {
     MENUITEM *item;
     POPUPMENU *menu, *submenu;
-    HMENU16 hsubmenu;
+    HMENU32 hsubmenu;
 
     if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu ))) return;
     if (menu->FocusedItem == NO_SELECTED_ITEM) return;
@@ -1185,7 +1184,7 @@
 	if (!(item->item_flags & MF_POPUP) ||
 	    !(item->item_flags & MF_MOUSESELECT)) return;
 	item->item_flags &= ~MF_MOUSESELECT;
-	hsubmenu = (HMENU16)item->item_id;
+	hsubmenu = (HMENU32)item->item_id;
     }
     submenu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hsubmenu );
     MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE );
@@ -1209,8 +1208,8 @@
  * Display the sub-menu of the selected item of this menu.
  * Return the handle of the submenu, or hmenu if no submenu to display.
  */
-static HMENU16 MENU_ShowSubPopup( HWND hwndOwner, HMENU16 hmenu,
-                                  BOOL selectFirst )
+static HMENU32 MENU_ShowSubPopup( HWND32 hwndOwner, HMENU32 hmenu,
+                                  BOOL32 selectFirst )
 {
     POPUPMENU *menu;
     MENUITEM *item;
@@ -1226,7 +1225,8 @@
 	MENU_ShowPopup(hwndOwner, wndPtr->hSysMenu, 0, wndPtr->rectClient.left,
 		wndPtr->rectClient.top - menu->Height - 2*SYSMETRICS_CYBORDER,
 		SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE );
-	if (selectFirst) MENU_SelectItemRel( hwndOwner, wndPtr->hSysMenu, ITEM_NEXT );
+	if (selectFirst)
+            MENU_SelectItemRel( hwndOwner, wndPtr->hSysMenu, ITEM_NEXT );
 	return wndPtr->hSysMenu;
     }
     item = &menu->items[menu->FocusedItem];
@@ -1246,10 +1246,12 @@
 	MENU_ShowPopup( hwndOwner, (HMENU16)item->item_id, menu->FocusedItem,
 		        wndPtr->rectWindow.left + item->rect.left,
 		        wndPtr->rectWindow.top + item->rect.bottom,
-			item->rect.right - item->rect.left, item->rect.bottom - item->rect.top );
+			item->rect.right - item->rect.left,
+                        item->rect.bottom - item->rect.top );
     }
-    if (selectFirst) MENU_SelectItemRel( hwndOwner, (HMENU16)item->item_id, ITEM_NEXT );
-    return (HMENU16)item->item_id;
+    if (selectFirst)
+        MENU_SelectItemRel( hwndOwner, (HMENU32)item->item_id, ITEM_NEXT );
+    return (HMENU32)item->item_id;
 }
 
 
@@ -1258,12 +1260,12 @@
  *
  * Find the menu containing a given point (in screen coords).
  */
-static HMENU16 MENU_FindMenuByCoords( HMENU16 hmenu, POINT16 pt )
+static HMENU32 MENU_FindMenuByCoords( HMENU32 hmenu, POINT32 pt )
 {
     POPUPMENU *menu;
-    HWND hwnd;
+    HWND32 hwnd;
 
-    if (!(hwnd = WindowFromPoint16( pt ))) return 0;
+    if (!(hwnd = WindowFromPoint32( pt ))) return 0;
     while (hmenu)
     {
 	menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
@@ -1296,8 +1298,8 @@
  * Execute a menu item (for instance when user pressed Enter).
  * Return TRUE if we can go on with menu tracking.
  */
-static BOOL MENU_ExecFocusedItem( HWND hwndOwner, HMENU16 hmenu,
-				  HMENU16 *hmenuCurrent )
+static BOOL32 MENU_ExecFocusedItem( HWND32 hwndOwner, HMENU32 hmenu,
+                                    HMENU32 *hmenuCurrent )
 {
     MENUITEM *item;
     POPUPMENU *menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
@@ -1329,12 +1331,12 @@
  * hmenuCurrent is the top-most visible popup.
  * Return TRUE if we can go on with menu tracking.
  */
-static BOOL MENU_ButtonDown( HWND hwndOwner, HMENU16 hmenu,
-                             HMENU16 *hmenuCurrent, POINT16 pt )
+static BOOL32 MENU_ButtonDown( HWND32 hwndOwner, HMENU32 hmenu,
+                               HMENU32 *hmenuCurrent, POINT32 pt )
 {
     POPUPMENU *menu;
     MENUITEM *item;
-    UINT id;
+    UINT32 id;
 
     if (!hmenu) return FALSE;  /* Outside all menus */
     menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
@@ -1379,13 +1381,13 @@
  * hmenuCurrent is the top-most visible popup.
  * Return TRUE if we can go on with menu tracking.
  */
-static BOOL MENU_ButtonUp( HWND hwndOwner, HMENU16 hmenu,
-                           HMENU16 *hmenuCurrent, POINT16 pt )
+static BOOL32 MENU_ButtonUp( HWND32 hwndOwner, HMENU32 hmenu,
+                             HMENU32 *hmenuCurrent, POINT32 pt )
 {
     POPUPMENU *menu;
     MENUITEM *item;
-    HMENU16 hsubmenu = 0;
-    UINT id;
+    HMENU32 hsubmenu = 0;
+    UINT32 id;
 
     if (!hmenu) return FALSE;  /* Outside all menus */
     menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
@@ -1405,7 +1407,7 @@
 	{
 	    return MENU_ExecFocusedItem( hwndOwner, hmenu, hmenuCurrent );
 	}
-	hsubmenu = (HMENU16)item->item_id;
+	hsubmenu = (HMENU32)item->item_id;
     }
       /* Select first item of sub-popup */
     MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, FALSE );
@@ -1421,12 +1423,12 @@
  * hmenuCurrent is the top-most visible popup.
  * Return TRUE if we can go on with menu tracking.
  */
-static BOOL MENU_MouseMove( HWND hwndOwner, HMENU16 hmenu,
-                            HMENU16 *hmenuCurrent, POINT16 pt )
+static BOOL32 MENU_MouseMove( HWND32 hwndOwner, HMENU32 hmenu,
+                              HMENU32 *hmenuCurrent, POINT32 pt )
 {
     MENUITEM *item;
     POPUPMENU *menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
-    UINT id = NO_SELECTED_ITEM;
+    UINT32 id = NO_SELECTED_ITEM;
 
     if (hmenu)
     {
@@ -1451,26 +1453,27 @@
     return TRUE;
 }
 
+
 /***********************************************************************
  *           MENU_DoNextMenu
  */
-static LRESULT MENU_DoNextMenu( HWND* hwndOwner, HMENU16* hmenu,
-                                HMENU16 *hmenuCurrent, UINT vk)
+static LRESULT MENU_DoNextMenu( HWND32* hwndOwner, HMENU32* hmenu,
+                                HMENU32 *hmenuCurrent, UINT32 vk )
 {
   POPUPMENU *menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( *hmenu );
-  UINT	     id = 0;
+  UINT32     id = 0;
 
   if(    (vk == VK_LEFT && !menu->FocusedItem)
       || (vk == VK_RIGHT && menu->FocusedItem == menu->nItems - 1) 
       || menu->FocusedItem == SYSMENU_SELECTED 
-      || ((menu->wFlags & (MF_POPUP | MF_SYSMENU)) == (MF_POPUP | MF_SYSMENU)) )
+      || ((menu->wFlags & (MF_POPUP | MF_SYSMENU)) == (MF_POPUP | MF_SYSMENU)))
   {
     LRESULT l = SendMessage16( *hwndOwner, WM_NEXTMENU, (WPARAM16)vk, 
-				(LPARAM)((menu->FocusedItem == SYSMENU_SELECTED)
-					? GetSystemMenu( *hwndOwner, 0) 
-					: *hmenu));
+                               (LPARAM)((menu->FocusedItem == SYSMENU_SELECTED)
+                                        ? GetSystemMenu32( *hwndOwner, 0) 
+                                        : *hmenu));
 
-    if( l == 0 || !IsMenu(LOWORD(l)) || !IsWindow(HIWORD(l)) ) return 0;
+    if( l == 0 || !IsMenu32(LOWORD(l)) || !IsWindow(HIWORD(l)) ) return 0;
 
     /* shutdown current menu -
      * all these checks for system popup window are needed
@@ -1503,28 +1506,31 @@
     /* init next menu */
 
     if( (menu->wFlags & (MF_POPUP | MF_SYSMENU)) == (MF_POPUP | MF_SYSMENU) )
-	{
-	  RECT16 rect;
-	  WND*   wndPtr = WIN_FindWndPtr( *hwndOwner );
+    {
+        RECT32 rect;
+        WND*   wndPtr = WIN_FindWndPtr( *hwndOwner );
 
-	  /* stupid kludge, see above */
+        /* stupid kludge, see above */
 
-	  if( wndPtr->wIDmenu && !(wndPtr->dwStyle & WS_CHILD) )
-	     { *hmenu = wndPtr->wIDmenu; id = SYSMENU_SELECTED; }
-	  else
-	  { 
-	     if( NC_GetSysPopupPos( wndPtr, &rect ) )
-	         MENU_ShowPopup( *hwndOwner, *hmenu, 0, rect.left, rect.bottom,
-		 SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE );
-
-             if( !IsIconic( *hwndOwner ) )
-             {
-               HDC32 hdc =  GetDCEx32( *hwndOwner, 0, DCX_CACHE | DCX_WINDOW);
-               NC_DrawSysButton( *hwndOwner, hdc, TRUE );
-               ReleaseDC32( *hwndOwner, hdc );
-             }
-	  }
-	}
+        if( wndPtr->wIDmenu && !(wndPtr->dwStyle & WS_CHILD) )
+        {
+            *hmenu = wndPtr->wIDmenu;
+            id = SYSMENU_SELECTED;
+        }
+        else
+        { 
+            if( NC_GetSysPopupPos( wndPtr, &rect ) )
+                MENU_ShowPopup( *hwndOwner, *hmenu, 0, rect.left, rect.bottom,
+                                SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE );
+            
+            if( !IsIconic( *hwndOwner ) )
+            {
+                HDC32 hdc =  GetDCEx32( *hwndOwner, 0, DCX_CACHE | DCX_WINDOW);
+                NC_DrawSysButton( *hwndOwner, hdc, TRUE );
+                ReleaseDC32( *hwndOwner, hdc );
+            }
+        }
+    }
 
     MENU_SelectItem( *hwndOwner, *hmenu, id, TRUE ); 
     return l;
@@ -1538,11 +1544,11 @@
  * Handle a VK_LEFT key event in a menu.
  * hmenuCurrent is the top-most visible popup.
  */
-static void MENU_KeyLeft( HWND* hwndOwner, HMENU16* hmenu,
-                          HMENU16 *hmenuCurrent )
+static void MENU_KeyLeft( HWND32* hwndOwner, HMENU32* hmenu,
+                          HMENU32 *hmenuCurrent )
 {
     POPUPMENU *menu;
-    HMENU16 hmenutmp, hmenuprev;
+    HMENU32 hmenutmp, hmenuprev;
 
     menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( *hmenu );
     hmenuprev = hmenutmp = *hmenu;
@@ -1579,11 +1585,11 @@
  * Handle a VK_RIGHT key event in a menu.
  * hmenuCurrent is the top-most visible popup.
  */
-static void MENU_KeyRight( HWND* hwndOwner, HMENU16* hmenu,
-                           HMENU16 *hmenuCurrent )
+static void MENU_KeyRight( HWND32* hwndOwner, HMENU32* hmenu,
+                           HMENU32 *hmenuCurrent )
 {
     POPUPMENU *menu;
-    HMENU16 hmenutmp;
+    HMENU32 hmenutmp;
 
     menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( *hmenu );
 
@@ -1639,20 +1645,22 @@
  * If 'x' and 'y' are not 0, we simulate a button-down event at (x,y)
  * before beginning tracking. This is to help menu-bar tracking.
  */
-static BOOL32 MENU_TrackMenu( HMENU16 hmenu, UINT32 wFlags, int x, int y,
-                              HWND16 hwnd, const RECT16 *lprect )
+static BOOL32 MENU_TrackMenu( HMENU32 hmenu, UINT32 wFlags, INT32 x, INT32 y,
+                              HWND32 hwnd, const RECT32 *lprect )
 {
     MSG16 msg;
     POPUPMENU *menu;
-    HMENU16 hmenuCurrent = hmenu;
-    BOOL fClosed = FALSE, fRemove;
-    UINT pos;
+    HMENU32 hmenuCurrent = hmenu;
+    BOOL32 fClosed = FALSE, fRemove;
+    UINT32 pos;
+    POINT32 pt;
 
     fEndMenuCalled = FALSE;
     if (!(menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu ))) return FALSE;
     if (x && y)
     {
-	POINT16 pt = { x, y };
+	pt.x = x;
+        pt.y = y;
 	MENU_ButtonDown( hwnd, hmenu, &hmenuCurrent, pt );
     }
 
@@ -1669,13 +1677,14 @@
 	    break;
 
         TranslateMessage( &msg );
+        CONV_POINT16TO32( &msg.pt, &pt );
 
         fRemove = FALSE;
 	if ((msg.message >= WM_MOUSEFIRST) && (msg.message <= WM_MOUSELAST))
 	{
 	      /* Find the sub-popup for this mouse event (if any) */
 
-	    HMENU16 hsubmenu = MENU_FindMenuByCoords( hmenu, msg.pt );
+	    HMENU32 hsubmenu = MENU_FindMenuByCoords( hmenu, pt );
 
 	    switch(msg.message)
 	    {
@@ -1689,7 +1698,7 @@
 	    case WM_LBUTTONDBLCLK:
 	    case WM_LBUTTONDOWN:
 		fClosed = !MENU_ButtonDown( hwnd, hsubmenu,
-					    &hmenuCurrent, msg.pt );
+					    &hmenuCurrent, pt );
 		break;
 		
 	    case WM_RBUTTONUP:
@@ -1698,9 +1707,9 @@
 
 	    case WM_LBUTTONUP:
 		  /* If outside all menus but inside lprect, ignore it */
-		if (!hsubmenu && lprect && PtInRect16(lprect, msg.pt)) break;
+		if (!hsubmenu && lprect && PtInRect32(lprect, pt)) break;
 		fClosed = !MENU_ButtonUp( hwnd, hsubmenu,
-					  &hmenuCurrent, msg.pt );
+					  &hmenuCurrent, pt );
                 fRemove = TRUE;  /* Remove event even if outside menu */
 		break;
 		
@@ -1709,7 +1718,7 @@
 		    ((wFlags & TPM_RIGHTBUTTON) && (msg.wParam & MK_RBUTTON)))
 		{
 		    fClosed = !MENU_MouseMove( hwnd, hsubmenu,
-					       &hmenuCurrent, msg.pt );
+					       &hmenuCurrent, pt );
 		}
 		break;
 	    }
@@ -1780,8 +1789,8 @@
 		      /* We will find a better way real soon... */
 		    if ((msg.wParam <= 32) || (msg.wParam >= 127)) break;
 		    pos = MENU_FindItemByKey( hwnd, hmenuCurrent, msg.wParam );
-		    if (pos == (UINT)-2) fClosed = TRUE;
-		    else if (pos == (UINT)-1) MessageBeep(0);
+		    if (pos == (UINT32)-2) fClosed = TRUE;
+		    else if (pos == (UINT32)-1) MessageBeep(0);
 		    else
 		    {
 			MENU_SelectItem( hwnd, hmenuCurrent, pos, TRUE );
@@ -1823,15 +1832,15 @@
  */
 static void MENU_TrackSysPopup( WND* pWnd )
 {
-    RECT16      rect;
-    HMENU16     hMenu = pWnd->hSysMenu;
-    HDC16       hDC = 0;
+    RECT32  rect;
+    HMENU32 hMenu = pWnd->hSysMenu;
+    HDC32   hDC = 0;
 
     /* track the system menu like a normal popup menu */
 
-    if( IsMenu(hMenu) )
+    if(IsMenu32(hMenu))
     {
-	HWND16 hWnd = pWnd->hwndSelf;
+	HWND32 hWnd = pWnd->hwndSelf;
 	if (!(pWnd->dwStyle & WS_MINIMIZE))
 	{
 	    hDC = GetWindowDC32( hWnd );
@@ -1840,8 +1849,8 @@
 	NC_GetSysPopupPos( pWnd, &rect );
 	MENU_InitSysMenuPopup( hMenu, pWnd->dwStyle,
 				      pWnd->class->style);
-	TrackPopupMenu16( hMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
-				 rect.left, rect.bottom, 0, hWnd, &rect );
+	TrackPopupMenu32( hMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
+                          rect.left, rect.bottom, 0, hWnd, &rect );
 	if (!(pWnd->dwStyle & WS_MINIMIZE))
 	{
              NC_DrawSysButton( hWnd, hDC, FALSE );
@@ -1855,14 +1864,14 @@
  *
  * Menu-bar tracking upon a mouse event. Called from NC_HandleSysCommand().
  */
-void MENU_TrackMouseMenuBar( WND* wndPtr, INT16 ht, POINT16 pt )
+void MENU_TrackMouseMenuBar( WND* wndPtr, INT32 ht, POINT32 pt )
 {
-    BOOL32	bTrackSys = ((ht == HTSYSMENU && !wndPtr->wIDmenu) ||
-		             (wndPtr->dwStyle & (WS_MINIMIZE | WS_CHILD)));
-    HWND16	hWnd = wndPtr->hwndSelf;
-    HMENU16	hMenu = (bTrackSys) ? wndPtr->hSysMenu : wndPtr->wIDmenu;
+    BOOL32  bTrackSys = ((ht == HTSYSMENU && !wndPtr->wIDmenu) ||
+                         (wndPtr->dwStyle & (WS_MINIMIZE | WS_CHILD)));
+    HWND32  hWnd = wndPtr->hwndSelf;
+    HMENU32 hMenu = (bTrackSys) ? wndPtr->hSysMenu : wndPtr->wIDmenu;
 
-    if( IsMenu(hMenu) )
+    if (IsMenu32(hMenu))
     {
 	HideCaret(0);
 	SendMessage16( hWnd, WM_ENTERMENULOOP, 0, 0 );
@@ -1883,11 +1892,11 @@
  *
  * Menu-bar tracking upon a keyboard event. Called from NC_HandleSysCommand().
  */
-void MENU_TrackKbdMenuBar( WND* wndPtr, UINT16 wParam, INT16 vkey)
+void MENU_TrackKbdMenuBar( WND* wndPtr, UINT32 wParam, INT32 vkey)
 {
-   INT16 htMenu;
-   UINT16 uItem = NO_SELECTED_ITEM;
-   HMENU16 hTrackMenu; 
+   INT32 htMenu;
+   UINT32 uItem = NO_SELECTED_ITEM;
+   HMENU32 hTrackMenu; 
 
     /* find window that has a menu */
  
@@ -1900,7 +1909,7 @@
 	      !wndPtr->wIDmenu) ? HTSYSMENU : HTMENU;
     hTrackMenu = ( htMenu == HTSYSMENU ) ? wndPtr->hSysMenu : wndPtr->wIDmenu;
 
-    if( IsMenu( hTrackMenu ) )
+    if (IsMenu32( hTrackMenu ))
     {
         HideCaret(0);
         SendMessage16( wndPtr->hwndSelf, WM_ENTERMENULOOP, 0, 0 );
@@ -1953,13 +1962,11 @@
 BOOL16 TrackPopupMenu16( HMENU16 hMenu, UINT16 wFlags, INT16 x, INT16 y,
                          INT16 nReserved, HWND16 hWnd, const RECT16 *lpRect )
 {
-    BOOL ret = FALSE;
-
-    HideCaret(0);
-    if (MENU_ShowPopup( hWnd, hMenu, 0, x, y, 0, 0 )) 
-	ret = MENU_TrackMenu( hMenu, wFlags, 0, 0, hWnd, lpRect );
-    ShowCaret(0);
-    return ret;
+    RECT32 r;
+    if (lpRect)
+   	 CONV_RECT16TO32( lpRect, &r );
+    return TrackPopupMenu32( hMenu, wFlags, x, y, nReserved, hWnd,
+                             lpRect ? &r : NULL );
 }
 
 
@@ -1969,10 +1976,13 @@
 BOOL32 TrackPopupMenu32( HMENU32 hMenu, UINT32 wFlags, INT32 x, INT32 y,
                          INT32 nReserved, HWND32 hWnd, const RECT32 *lpRect )
 {
-    RECT16 r;
-    if (lpRect)
-   	 CONV_RECT32TO16( lpRect, &r );
-    return TrackPopupMenu16(hMenu,wFlags,x,y,nReserved,hWnd,lpRect?&r:NULL);
+    BOOL32 ret = FALSE;
+
+    HideCaret(0);
+    if (MENU_ShowPopup( hWnd, hMenu, 0, x, y, 0, 0 )) 
+	ret = MENU_TrackMenu( hMenu, wFlags, 0, 0, hWnd, lpRect );
+    ShowCaret(0);
+    return ret;
 }
 
 /**********************************************************************
@@ -1981,25 +1991,22 @@
 BOOL32 TrackPopupMenuEx( HMENU32 hMenu, UINT32 wFlags, INT32 x, INT32 y,
 			 HWND32 hWnd, LPTPMPARAMS lpTpm )
 {
-    RECT16 r;
-
     fprintf( stderr, "TrackPopupMenuEx: not fully implemented\n" );
-
-    if (lpTpm)
-        CONV_RECT32TO16( &lpTpm->rcExclude, &r );
-    return TrackPopupMenu16(hMenu,wFlags,x,y,0,hWnd,lpTpm?&r:NULL);
+    return TrackPopupMenu32( hMenu, wFlags, x, y, 0, hWnd,
+                             lpTpm ? &lpTpm->rcExclude : NULL );
 }
 
 /***********************************************************************
  *           PopupMenuWndProc
  */
-LRESULT PopupMenuWndProc(HWND hwnd,UINT message,WPARAM16 wParam,LPARAM lParam)
+LRESULT PopupMenuWndProc( HWND32 hwnd, UINT32 message, WPARAM32 wParam,
+                          LPARAM lParam )
 {    
     switch(message)
     {
     case WM_CREATE:
 	{
-	    CREATESTRUCT16 *cs = (CREATESTRUCT16*)PTR_SEG_TO_LIN(lParam);
+	    CREATESTRUCT32A *cs = (CREATESTRUCT32A*)lParam;
 	    SetWindowLong32A( hwnd, 0, (LONG)cs->lpCreateParams );
 	    return 0;
 	}
@@ -2009,11 +2016,11 @@
 
     case WM_PAINT:
 	{
-	    PAINTSTRUCT16 ps;
-	    BeginPaint16( hwnd, &ps );
+	    PAINTSTRUCT32 ps;
+	    BeginPaint32( hwnd, &ps );
 	    MENU_DrawPopupMenu( hwnd, ps.hdc,
-                                (HMENU16)GetWindowLong32A( hwnd, 0 ) );
-	    EndPaint16( hwnd, &ps );
+                                (HMENU32)GetWindowLong32A( hwnd, 0 ) );
+	    EndPaint32( hwnd, &ps );
 	    return 0;
 	}
 
@@ -2032,7 +2039,7 @@
 	if (wParam) SetWindowLong32A( hwnd, 0, (HMENU16)wParam );
         break;
     default:
-	return DefWindowProc16(hwnd, message, wParam, lParam);
+	return DefWindowProc32A( hwnd, message, wParam, lParam );
     }
     return 0;
 }
@@ -2043,10 +2050,11 @@
  *
  * Compute the size of the menu bar height. Used by NC_HandleNCCalcSize().
  */
-UINT MENU_GetMenuBarHeight( HWND hwnd, UINT menubarWidth, int orgX, int orgY )
+UINT32 MENU_GetMenuBarHeight( HWND32 hwnd, UINT32 menubarWidth,
+                              INT32 orgX, INT32 orgY )
 {
     HDC32 hdc;
-    RECT16 rectBar;
+    RECT32 rectBar;
     WND *wndPtr;
     LPPOPUPMENU lppop;
 
@@ -2054,7 +2062,7 @@
     if (!(lppop = (LPPOPUPMENU)USER_HEAP_LIN_ADDR((HMENU16)wndPtr->wIDmenu)))
       return 0;
     hdc = GetDCEx32( hwnd, 0, DCX_CACHE | DCX_WINDOW );
-    SetRect16(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+SYSMETRICS_CYMENU);
+    SetRect32(&rectBar, orgX, orgY, orgX+menubarWidth, orgY+SYSMETRICS_CYMENU);
     MENU_MenuBarCalcSize( hdc, &rectBar, lppop, hwnd );
     ReleaseDC32( hwnd, hdc );
     return lppop->Height;
@@ -2074,10 +2082,10 @@
     /* FIXME: Word passes the item id in 'pos' and 0 or 0xffff as id */
     /* for MF_DELETE. We should check the parameters for all others */
     /* MF_* actions also (anybody got a doc on ChangeMenu?). */
-    if (flags & MF_DELETE) return DeleteMenu( hMenu, pos, flags & ~MF_DELETE );
-    if (flags & MF_CHANGE) return ModifyMenu16( hMenu, pos, flags & ~MF_CHANGE,
-                                                id, data );
-    if (flags & MF_REMOVE) return RemoveMenu( hMenu,
+    if (flags & MF_DELETE) return DeleteMenu16(hMenu, pos, flags & ~MF_DELETE);
+    if (flags & MF_CHANGE) return ModifyMenu16(hMenu, pos, flags & ~MF_CHANGE,
+                                               id, data );
+    if (flags & MF_REMOVE) return RemoveMenu16(hMenu,
                                               flags & MF_BYPOSITION ? pos : id,
                                               flags & ~MF_REMOVE );
     /* Default: MF_INSERT */
@@ -2095,10 +2103,10 @@
                   hMenu, pos, (DWORD)data, id, flags );
     if (flags & MF_APPEND) return AppendMenu32A( hMenu, flags & ~MF_APPEND,
                                                  id, data );
-    if (flags & MF_DELETE) return DeleteMenu( hMenu, pos, flags & ~MF_DELETE );
+    if (flags & MF_DELETE) return DeleteMenu32(hMenu, pos, flags & ~MF_DELETE);
     if (flags & MF_CHANGE) return ModifyMenu32A(hMenu, pos, flags & ~MF_CHANGE,
                                                 id, data );
-    if (flags & MF_REMOVE) return RemoveMenu( hMenu,
+    if (flags & MF_REMOVE) return RemoveMenu32( hMenu,
                                               flags & MF_BYPOSITION ? pos : id,
                                               flags & ~MF_REMOVE );
     /* Default: MF_INSERT */
@@ -2116,10 +2124,10 @@
                   hMenu, pos, (DWORD)data, id, flags );
     if (flags & MF_APPEND) return AppendMenu32W( hMenu, flags & ~MF_APPEND,
                                                  id, data );
-    if (flags & MF_DELETE) return DeleteMenu( hMenu, pos, flags & ~MF_DELETE );
+    if (flags & MF_DELETE) return DeleteMenu32(hMenu, pos, flags & ~MF_DELETE);
     if (flags & MF_CHANGE) return ModifyMenu32W(hMenu, pos, flags & ~MF_CHANGE,
                                                 id, data );
-    if (flags & MF_REMOVE) return RemoveMenu( hMenu,
+    if (flags & MF_REMOVE) return RemoveMenu32( hMenu,
                                               flags & MF_BYPOSITION ? pos : id,
                                               flags & ~MF_REMOVE );
     /* Default: MF_INSERT */
@@ -2128,12 +2136,21 @@
 
 
 /*******************************************************************
- *         CheckMenuItem    (USER.154)
+ *         CheckMenuItem16    (USER.154)
  */
-INT CheckMenuItem( HMENU16 hMenu, UINT id, UINT flags )
+BOOL16 CheckMenuItem16( HMENU16 hMenu, UINT16 id, UINT16 flags )
+{
+    return (BOOL16)CheckMenuItem32( hMenu, id, flags );
+}
+
+
+/*******************************************************************
+ *         CheckMenuItem32    (USER32.45)
+ */
+DWORD CheckMenuItem32( HMENU32 hMenu, UINT32 id, UINT32 flags )
 {
     MENUITEM *item;
-    INT ret;
+    DWORD ret;
 
     dprintf_menu( stddeb,"CheckMenuItem: %04x %04x %04x\n", hMenu, id, flags );
     if (!(item = MENU_FindItem( &hMenu, &id, flags ))) return -1;
@@ -2145,9 +2162,18 @@
 
 
 /**********************************************************************
- *			EnableMenuItem		[USER.155]
+ *         EnableMenuItem16    (USER.155)
  */
-BOOL EnableMenuItem(HMENU16 hMenu, UINT wItemID, UINT wFlags)
+BOOL16 EnableMenuItem16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
+{
+    return EnableMenuItem32( hMenu, wItemID, wFlags );
+}
+
+
+/**********************************************************************
+ *         EnableMenuItem32    (USER32.169)
+ */
+BOOL32 EnableMenuItem32( HMENU32 hMenu, UINT32 wItemID, UINT32 wFlags )
 {
     MENUITEM *item;
     dprintf_menu(stddeb,"EnableMenuItem (%04x, %04X, %04X) !\n", 
@@ -2172,29 +2198,69 @@
 
 
 /*******************************************************************
- *         GetMenuString    (USER.161)
+ *         GetMenuString16    (USER.161)
  */
-int GetMenuString( HMENU16 hMenu, UINT wItemID,
-                   LPSTR str, short nMaxSiz, UINT wFlags )
+INT16 GetMenuString16( HMENU16 hMenu, UINT16 wItemID,
+                       LPSTR str, INT16 nMaxSiz, UINT16 wFlags )
+{
+    return GetMenuString32A( hMenu, wItemID, str, nMaxSiz, wFlags );
+}
+
+
+/*******************************************************************
+ *         GetMenuString32A    (USER32.267)
+ */
+INT32 GetMenuString32A( HMENU32 hMenu, UINT32 wItemID,
+                        LPSTR str, INT32 nMaxSiz, UINT32 wFlags )
 {
     MENUITEM *item;
 
-    dprintf_menu( stddeb, "GetMenuString: menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
+    dprintf_menu( stddeb, "GetMenuString32A: menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
                  hMenu, wItemID, str, nMaxSiz, wFlags );
     if (!str || !nMaxSiz) return 0;
     str[0] = '\0';
     if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
     if (!IS_STRING_ITEM(item->item_flags)) return 0;
     lstrcpyn32A( str, item->text, nMaxSiz );
-    dprintf_menu( stddeb, "GetMenuString: returning '%s'\n", str );
+    dprintf_menu( stddeb, "GetMenuString32A: returning '%s'\n", str );
     return strlen(str);
 }
 
 
-/**********************************************************************
- *			HiliteMenuItem		[USER.162]
+/*******************************************************************
+ *         GetMenuString32W    (USER32.268)
  */
-BOOL HiliteMenuItem(HWND hWnd, HMENU16 hMenu, UINT wItemID, UINT wHilite)
+INT32 GetMenuString32W( HMENU32 hMenu, UINT32 wItemID,
+                        LPWSTR str, INT32 nMaxSiz, UINT32 wFlags )
+{
+    MENUITEM *item;
+
+    dprintf_menu( stddeb, "GetMenuString32W: menu=%04x item=%04x ptr=%p len=%d flags=%04x\n",
+                 hMenu, wItemID, str, nMaxSiz, wFlags );
+    if (!str || !nMaxSiz) return 0;
+    str[0] = '\0';
+    if (!(item = MENU_FindItem( &hMenu, &wItemID, wFlags ))) return 0;
+    if (!IS_STRING_ITEM(item->item_flags)) return 0;
+    lstrcpynAtoW( str, item->text, nMaxSiz );
+    return lstrlen32W(str);
+}
+
+
+/**********************************************************************
+ *         HiliteMenuItem16    (USER.162)
+ */
+BOOL16 HiliteMenuItem16( HWND16 hWnd, HMENU16 hMenu, UINT16 wItemID,
+                         UINT16 wHilite )
+{
+    return HiliteMenuItem32( hWnd, hMenu, wItemID, wHilite );
+}
+
+
+/**********************************************************************
+ *         HiliteMenuItem32    (USER32.317)
+ */
+BOOL32 HiliteMenuItem32( HWND32 hWnd, HMENU32 hMenu, UINT32 wItemID,
+                         UINT32 wHilite )
 {
     LPPOPUPMENU menu;
     dprintf_menu(stddeb,"HiliteMenuItem(%04x, %04x, %04x, %04x);\n", 
@@ -2209,9 +2275,18 @@
 
 
 /**********************************************************************
- *			GetMenuState		[USER.250]
+ *         GetMenuState16    (USER.250)
  */
-UINT GetMenuState(HMENU16 hMenu, UINT wItemID, UINT wFlags)
+UINT16 GetMenuState16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
+{
+    return GetMenuState32( hMenu, wItemID, wFlags );
+}
+
+
+/**********************************************************************
+ *         GetMenuState32    (USER32.266)
+ */
+UINT32 GetMenuState32( HMENU32 hMenu, UINT32 wItemID, UINT32 wFlags )
 {
     MENUITEM *item;
     dprintf_menu(stddeb,"GetMenuState(%04x, %04x, %04x);\n", 
@@ -2228,28 +2303,52 @@
 
 
 /**********************************************************************
- *			GetMenuItemCount		[USER.263]
+ *         GetMenuItemCount16    (USER.263)
  */
-INT GetMenuItemCount(HMENU16 hMenu)
+INT16 GetMenuItemCount16( HMENU16 hMenu )
 {
-	LPPOPUPMENU	menu;
-	dprintf_menu(stddeb,"GetMenuItemCount(%04x);\n", hMenu);
-	menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
-	if (menu == NULL || menu->wMagic != MENU_MAGIC) return (UINT)-1;
-	dprintf_menu(stddeb,"GetMenuItemCount(%04x) return %d \n", 
-		     hMenu, menu->nItems);
-	return menu->nItems;
+    LPPOPUPMENU	menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
+    if (!menu || (menu->wMagic != MENU_MAGIC)) return -1;
+    dprintf_menu( stddeb,"GetMenuItemCount16(%04x) returning %d\n", 
+                  hMenu, menu->nItems );
+    return menu->nItems;
 }
 
 
 /**********************************************************************
- *			GetMenuItemID			[USER.264]
+ *         GetMenuItemCount32    (USER32.261)
  */
-UINT GetMenuItemID(HMENU16 hMenu, int nPos)
+INT32 GetMenuItemCount32( HMENU32 hMenu )
+{
+    LPPOPUPMENU	menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
+    if (!menu || (menu->wMagic != MENU_MAGIC)) return -1;
+    dprintf_menu( stddeb,"GetMenuItemCount32(%04x) returning %d\n", 
+                  hMenu, menu->nItems );
+    return menu->nItems;
+}
+
+
+/**********************************************************************
+ *         GetMenuItemID16    (USER.264)
+ */
+UINT16 GetMenuItemID16( HMENU16 hMenu, INT16 nPos )
 {
     LPPOPUPMENU	menu;
 
-    dprintf_menu(stddeb,"GetMenuItemID(%04x, %d);\n", hMenu, nPos);
+    if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu))) return -1;
+    if ((nPos < 0) || (nPos >= menu->nItems)) return -1;
+    if (menu->items[nPos].item_flags & MF_POPUP) return -1;
+    return menu->items[nPos].item_id;
+}
+
+
+/**********************************************************************
+ *         GetMenuItemID32    (USER32.262)
+ */
+UINT32 GetMenuItemID32( HMENU32 hMenu, INT32 nPos )
+{
+    LPPOPUPMENU	menu;
+
     if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu))) return -1;
     if ((nPos < 0) || (nPos >= menu->nItems)) return -1;
     if (menu->items[nPos].item_flags & MF_POPUP) return -1;
@@ -2263,10 +2362,12 @@
 BOOL16 InsertMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
                      UINT16 id, SEGPTR data )
 {
+    UINT32 pos32 = (UINT32)pos;
+    if ((pos == (UINT16)-1) && (flags & MF_BYPOSITION)) pos32 = (UINT32)-1;
     if (IS_STRING_ITEM(flags) && data)
-        return InsertMenu32A( hMenu, (INT32)(INT16)pos, flags, id,
+        return InsertMenu32A( hMenu, pos32, flags, id,
                               (LPSTR)PTR_SEG_TO_LIN(data) );
-    return InsertMenu32A( hMenu, (INT32)(INT16)pos, flags, id, (LPSTR)data );
+    return InsertMenu32A( hMenu, pos32, flags, id, (LPSTR)data );
 }
 
 
@@ -2288,7 +2389,7 @@
 
     if (!(MENU_SetItemData( item, flags, id, str )))
     {
-        RemoveMenu( hMenu, pos, flags );
+        RemoveMenu32( hMenu, pos, flags );
         return FALSE;
     }
 
@@ -2348,9 +2449,18 @@
 
 
 /**********************************************************************
- *			RemoveMenu		[USER.412]
+ *         RemoveMenu16    (USER.412)
  */
-BOOL RemoveMenu(HMENU16 hMenu, UINT nPos, UINT wFlags)
+BOOL16 RemoveMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
+{
+    return RemoveMenu32( hMenu, nPos, wFlags );
+}
+
+
+/**********************************************************************
+ *         RemoveMenu32    (USER32.440)
+ */
+BOOL32 RemoveMenu32( HMENU32 hMenu, UINT32 nPos, UINT32 wFlags )
 {
     LPPOPUPMENU	menu;
     MENUITEM *item;
@@ -2384,15 +2494,24 @@
 
 
 /**********************************************************************
- *			DeleteMenu		[USER.413]
+ *         DeleteMenu16    (USER.413)
  */
-BOOL DeleteMenu(HMENU16 hMenu, UINT nPos, UINT wFlags)
+BOOL16 DeleteMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
+{
+    return DeleteMenu32( hMenu, nPos, wFlags );
+}
+
+
+/**********************************************************************
+ *         DeleteMenu32    (USER32.128)
+ */
+BOOL32 DeleteMenu32( HMENU32 hMenu, UINT32 nPos, UINT32 wFlags )
 {
     MENUITEM *item = MENU_FindItem( &hMenu, &nPos, wFlags );
     if (!item) return FALSE;
-    if (item->item_flags & MF_POPUP) DestroyMenu( (HMENU16)item->item_id );
+    if (item->item_flags & MF_POPUP) DestroyMenu32( (HMENU32)item->item_id );
       /* nPos is now the position of the item */
-    RemoveMenu( hMenu, nPos, wFlags | MF_BYPOSITION );
+    RemoveMenu32( hMenu, nPos, wFlags | MF_BYPOSITION );
     return TRUE;
 }
 
@@ -2404,9 +2523,9 @@
                      UINT16 id, SEGPTR data )
 {
     if (IS_STRING_ITEM(flags))
-        return ModifyMenu32A( hMenu, (INT32)(INT16)pos, flags, id,
+        return ModifyMenu32A( hMenu, pos, flags, id,
                               (LPSTR)PTR_SEG_TO_LIN(data) );
-    return ModifyMenu32A( hMenu, (INT32)(INT16)pos, flags, id, (LPSTR)data );
+    return ModifyMenu32A( hMenu, pos, flags, id, (LPSTR)data );
 }
 
 
@@ -2417,8 +2536,6 @@
                       UINT32 id, LPCSTR str )
 {
     MENUITEM *item;
-    HMENU16 hMenu16 = hMenu;
-    UINT16 pos16 = pos;
 
     if (IS_STRING_ITEM(flags))
     {
@@ -2432,7 +2549,7 @@
                       hMenu, pos, flags, id, (DWORD)str );
     }
 
-    if (!(item = MENU_FindItem( &hMenu16, &pos16, flags ))) return FALSE;
+    if (!(item = MENU_FindItem( &hMenu, &pos, flags ))) return FALSE;
     return MENU_SetItemData( item, flags, id, str );
 }
 
@@ -2457,14 +2574,23 @@
 
 
 /**********************************************************************
- *			CreatePopupMenu		[USER.415]
+ *         CreatePopupMenu16    (USER.415)
  */
-HMENU16 CreatePopupMenu()
+HMENU16 CreatePopupMenu16(void)
 {
-    HMENU16 hmenu;
+    return CreatePopupMenu32();
+}
+
+
+/**********************************************************************
+ *         CreatePopupMenu32    (USER32.81)
+ */
+HMENU32 CreatePopupMenu32(void)
+{
+    HMENU32 hmenu;
     POPUPMENU *menu;
 
-    if (!(hmenu = CreateMenu())) return 0;
+    if (!(hmenu = CreateMenu32())) return 0;
     menu = (POPUPMENU *) USER_HEAP_LIN_ADDR( hmenu );
     menu->wFlags |= MF_POPUP;
     return hmenu;
@@ -2472,19 +2598,29 @@
 
 
 /**********************************************************************
- *			GetMenuCheckMarkDimensions	[USER.417]
+ *         GetMenuCheckMarkDimensions    (USER.417) (USER32.257)
  */
-DWORD GetMenuCheckMarkDimensions()
+DWORD GetMenuCheckMarkDimensions(void)
 {
     return MAKELONG( check_bitmap_width, check_bitmap_height );
 }
 
 
 /**********************************************************************
- *			SetMenuItemBitmaps	[USER.418]
+ *         SetMenuItemBitmaps16    (USER.418)
  */
-BOOL SetMenuItemBitmaps(HMENU16 hMenu, UINT nPos, UINT wFlags,
-                        HBITMAP16 hNewUnCheck, HBITMAP16 hNewCheck)
+BOOL16 SetMenuItemBitmaps16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags,
+                             HBITMAP16 hNewUnCheck, HBITMAP16 hNewCheck )
+{
+    return SetMenuItemBitmaps32( hMenu, nPos, wFlags, hNewUnCheck, hNewCheck );
+}
+
+
+/**********************************************************************
+ *         SetMenuItemBitmaps32    (USER32.489)
+ */
+BOOL32 SetMenuItemBitmaps32( HMENU32 hMenu, UINT32 nPos, UINT32 wFlags,
+                             HBITMAP32 hNewUnCheck, HBITMAP32 hNewCheck )
 {
     MENUITEM *item;
     dprintf_menu(stddeb,"SetMenuItemBitmaps(%04x, %04x, %04x, %04x, %04x)\n",
@@ -2509,15 +2645,22 @@
 
 
 /**********************************************************************
- *			CreateMenu		[USER.151]
+ *         CreateMenu16    (USER.151)
  */
-HMENU16 CreateMenu()
+HMENU16 CreateMenu16(void)
 {
-    HMENU16 hMenu;
+    return CreateMenu32();
+}
+
+
+/**********************************************************************
+ *         CreateMenu32    (USER32.80)
+ */
+HMENU32 CreateMenu32(void)
+{
+    HMENU32 hMenu;
     LPPOPUPMENU menu;
-    dprintf_menu(stddeb,"CreateMenu !\n");
-    if (!(hMenu = USER_HEAP_ALLOC( sizeof(POPUPMENU) )))
-	return 0;
+    if (!(hMenu = USER_HEAP_ALLOC( sizeof(POPUPMENU) ))) return 0;
     menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
     menu->wFlags = 0;
     menu->wMagic = MENU_MAGIC;
@@ -2528,18 +2671,27 @@
     menu->hWnd   = 0;
     menu->items  = NULL;
     menu->FocusedItem = NO_SELECTED_ITEM;
-    dprintf_menu(stddeb,"CreateMenu // return %04x\n", hMenu);
+    dprintf_menu( stddeb, "CreateMenu: return %04x\n", hMenu );
     return hMenu;
 }
 
 
 /**********************************************************************
- *			DestroyMenu		[USER.152]
+ *         DestroyMenu16    (USER.152)
  */
-BOOL DestroyMenu(HMENU16 hMenu)
+BOOL16 DestroyMenu16( HMENU16 hMenu )
+{
+    return DestroyMenu32( hMenu );
+}
+
+
+/**********************************************************************
+ *         DestroyMenu32    (USER32.133)
+ */
+BOOL32 DestroyMenu32( HMENU32 hMenu )
 {
     LPPOPUPMENU lppop;
-    dprintf_menu(stddeb,"DestroyMenu (%04x) !\n", hMenu);
+    dprintf_menu(stddeb,"DestroyMenu(%04x)\n", hMenu);
 
     if (hMenu == 0) return FALSE;
     /* Silently ignore attempts to destroy default system menu */
@@ -2547,7 +2699,9 @@
     lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
     if (!lppop || (lppop->wMagic != MENU_MAGIC)) return FALSE;
     lppop->wMagic = 0;  /* Mark it as destroyed */
-    if ((lppop->wFlags & MF_POPUP) && lppop->hWnd && (!pTopPWnd || (lppop->hWnd != pTopPWnd->hwndSelf)))
+    if ((lppop->wFlags & MF_POPUP) &&
+        lppop->hWnd &&
+        (!pTopPWnd || (lppop->hWnd != pTopPWnd->hwndSelf)))
         DestroyWindow( lppop->hWnd );
 
     if (lppop->items)
@@ -2557,21 +2711,30 @@
         for (i = lppop->nItems; i > 0; i--, item++)
         {
             if (item->item_flags & MF_POPUP)
-                DestroyMenu( (HMENU16)item->item_id );
+                DestroyMenu32( (HMENU32)item->item_id );
 	    if (IS_STRING_ITEM(item->item_flags) && item->text)
                 HeapFree( SystemHeap, 0, item->text );
         }
         HeapFree( SystemHeap, 0, lppop->items );
     }
     USER_HEAP_FREE( hMenu );
-    dprintf_menu(stddeb,"DestroyMenu (%04x) // End !\n", hMenu);
     return TRUE;
 }
 
+
 /**********************************************************************
- *			GetSystemMenu		[USER.156]
+ *         GetSystemMenu16    (USER.156)
  */
-HMENU16 GetSystemMenu(HWND hWnd, BOOL bRevert)
+HMENU16 GetSystemMenu16( HWND16 hWnd, BOOL16 bRevert )
+{
+    return GetSystemMenu32( hWnd, bRevert );
+}
+
+
+/**********************************************************************
+ *         GetSystemMenu32    (USER32.290)
+ */
+HMENU32 GetSystemMenu32( HWND32 hWnd, BOOL32 bRevert )
 {
     WND *wndPtr = WIN_FindWndPtr( hWnd );
     if (!wndPtr) return 0;
@@ -2582,113 +2745,148 @@
         return wndPtr->hSysMenu;
     }
     if (!bRevert) return wndPtr->hSysMenu;
-    if (wndPtr->hSysMenu) DestroyMenu(wndPtr->hSysMenu);
+    if (wndPtr->hSysMenu) DestroyMenu32(wndPtr->hSysMenu);
     wndPtr->hSysMenu = MENU_CopySysMenu();
     return wndPtr->hSysMenu;
 }
 
 
 /*******************************************************************
- *         SetSystemMenu    (USER.280)
+ *         SetSystemMenu16    (USER.280)
  */
-BOOL SetSystemMenu( HWND hwnd, HMENU16 hMenu )
+BOOL16 SetSystemMenu16( HWND16 hwnd, HMENU16 hMenu )
+{
+    return SetSystemMenu32( hwnd, hMenu );
+}
+
+
+/*******************************************************************
+ *         SetSystemMenu32    (USER32.507)
+ */
+BOOL32 SetSystemMenu32( HWND32 hwnd, HMENU32 hMenu )
 {
     WND *wndPtr;
 
     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return FALSE;
     if (wndPtr->hSysMenu && (wndPtr->hSysMenu != MENU_DefSysMenu))
-        DestroyMenu( wndPtr->hSysMenu );
+        DestroyMenu32( wndPtr->hSysMenu );
     wndPtr->hSysMenu = hMenu;
     return TRUE;
 }
 
 
 /**********************************************************************
- *			GetMenu		[USER.157]
+ *         GetMenu16    (USER.157)
  */
-HMENU16 GetMenu(HWND hWnd) 
-{ 
-	WND * wndPtr = WIN_FindWndPtr(hWnd);
-	if (wndPtr == NULL) return 0;
-	return (HMENU16)wndPtr->wIDmenu;
-}
-
-
-/**********************************************************************
- * 			SetMenu 	[USER.158]
- */
-BOOL SetMenu(HWND hWnd, HMENU16 hMenu)
+HMENU16 GetMenu16( HWND16 hWnd ) 
 {
-	LPPOPUPMENU lpmenu;
-	WND * wndPtr = WIN_FindWndPtr(hWnd);
-	if (wndPtr == NULL) {
-		fprintf(stderr,"SetMenu(%04x, %04x) // Bad window handle !\n",
-			hWnd, hMenu);
-		return FALSE;
-		}
-	dprintf_menu(stddeb,"SetMenu(%04x, %04x);\n", hWnd, hMenu);
-	if (GetCapture32() == hWnd) ReleaseCapture();
-	wndPtr->wIDmenu = (UINT)hMenu;
-	if (hMenu != 0)
-	{
-	    lpmenu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu);
-	    if (lpmenu == NULL) {
-		fprintf(stderr,"SetMenu(%04x, %04x) // Bad menu handle !\n", 
-			hWnd, hMenu);
-		return FALSE;
-		}
-	    lpmenu->hWnd = hWnd;
-	    lpmenu->wFlags &= ~MF_POPUP;  /* Can't be a popup */
-	    lpmenu->Height = 0;  /* Make sure we recalculate the size */
-	}
-        if (IsWindowVisible(hWnd))
-            SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
-                          SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
-	return TRUE;
+    WND * wndPtr = WIN_FindWndPtr(hWnd);
+    if (wndPtr) return (HMENU16)wndPtr->wIDmenu;
+    return 0;
+}
+
+
+/**********************************************************************
+ *         GetMenu32    (USER32.256)
+ */
+HMENU32 GetMenu32( HWND32 hWnd ) 
+{ 
+    WND * wndPtr = WIN_FindWndPtr(hWnd);
+    if (wndPtr) return (HMENU32)wndPtr->wIDmenu;
+    return 0;
+}
+
+
+/**********************************************************************
+ *         SetMenu16    (USER.158)
+ */
+BOOL16 SetMenu16( HWND16 hWnd, HMENU16 hMenu )
+{
+    return SetMenu32( hWnd, hMenu );
+}
+
+
+/**********************************************************************
+ *         SetMenu32    (USER32.486)
+ */
+BOOL32 SetMenu32( HWND32 hWnd, HMENU32 hMenu )
+{
+    LPPOPUPMENU lpmenu;
+    WND * wndPtr = WIN_FindWndPtr(hWnd);
+    if (!wndPtr) return FALSE;
+    dprintf_menu(stddeb,"SetMenu(%04x, %04x);\n", hWnd, hMenu);
+    if (GetCapture32() == hWnd) ReleaseCapture();
+    wndPtr->wIDmenu = (UINT32)hMenu;
+    if (hMenu != 0)
+    {
+        if (!(lpmenu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu))) return FALSE;
+        lpmenu->hWnd = hWnd;
+        lpmenu->wFlags &= ~MF_POPUP;  /* Can't be a popup */
+        lpmenu->Height = 0;  /* Make sure we recalculate the size */
+    }
+    if (IsWindowVisible(hWnd))
+        SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+                      SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+    return TRUE;
 }
 
 
 
 /**********************************************************************
- *			GetSubMenu		[USER.159]
+ *         GetSubMenu16    (USER.159)
  */
-HMENU16 GetSubMenu(HMENU16 hMenu, short nPos)
+HMENU16 GetSubMenu16( HMENU16 hMenu, INT16 nPos )
+{
+    return GetSubMenu32( hMenu, nPos );
+}
+
+
+/**********************************************************************
+ *         GetSubMenu32    (USER32.287)
+ */
+HMENU32 GetSubMenu32( HMENU32 hMenu, INT32 nPos )
 {
     LPPOPUPMENU lppop;
 
-    dprintf_menu(stddeb,"GetSubMenu (%04x, %04X) !\n", hMenu, nPos);
     if (!(lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR(hMenu))) return 0;
-    if ((UINT)nPos >= lppop->nItems) return 0;
+    if ((UINT32)nPos >= lppop->nItems) return 0;
     if (!(lppop->items[nPos].item_flags & MF_POPUP)) return 0;
-    return (HMENU16)lppop->items[nPos].item_id;
+    return (HMENU32)lppop->items[nPos].item_id;
 }
 
 
 /**********************************************************************
- *			DrawMenuBar		[USER.160]
+ *         DrawMenuBar16    (USER.160)
  */
-void DrawMenuBar(HWND hWnd)
+void DrawMenuBar16( HWND16 hWnd )
 {
-	WND		*wndPtr;
-	LPPOPUPMENU lppop;
-	dprintf_menu(stddeb,"DrawMenuBar (%04x)\n", hWnd);
-	wndPtr = WIN_FindWndPtr(hWnd);
-	if (wndPtr != NULL && (wndPtr->dwStyle & WS_CHILD) == 0 && 
-		wndPtr->wIDmenu != 0) {
-		dprintf_menu(stddeb,"DrawMenuBar wIDmenu=%04X \n", 
-			     wndPtr->wIDmenu);
-		lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR((HMENU16)wndPtr->wIDmenu);
-		if (lppop == NULL) return;
+    DrawMenuBar32( hWnd );
+}
 
-		lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
-		SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
-			    SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
-	    }
+
+/**********************************************************************
+ *         DrawMenuBar32    (USER32.160)
+ */
+BOOL32 DrawMenuBar32( HWND32 hWnd )
+{
+    LPPOPUPMENU lppop;
+    WND *wndPtr = WIN_FindWndPtr(hWnd);
+    if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && wndPtr->wIDmenu)
+    {
+        lppop = (LPPOPUPMENU) USER_HEAP_LIN_ADDR((HMENU16)wndPtr->wIDmenu);
+        if (lppop == NULL) return FALSE;
+
+        lppop->Height = 0; /* Make sure we call MENU_MenuBarCalcSize */
+        SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+                      SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+        return TRUE;
+    }
+    return FALSE;
 }
 
 
 /***********************************************************************
- *           EndMenu   (USER.187)
+ *           EndMenu   (USER.187) (USER32.174)
  */
 void EndMenu(void)
 {
@@ -2700,15 +2898,17 @@
 /***********************************************************************
  *           LookupMenuHandle   (USER.217)
  */
-HMENU16 LookupMenuHandle( HMENU16 hmenu, INT id )
+HMENU16 LookupMenuHandle( HMENU16 hmenu, INT16 id )
 {
-    if (!MENU_FindItem( &hmenu, &id, MF_BYCOMMAND )) return 0;
-    else return hmenu;
+    HMENU32 hmenu32 = hmenu;
+    INT32 id32 = id;
+    if (!MENU_FindItem( &hmenu32, &id32, MF_BYCOMMAND )) return 0;
+    else return hmenu32;
 }
 
 
 /**********************************************************************
- *	    LoadMenu    (USER.150)
+ *	    LoadMenu16    (USER.150)
  */
 HMENU16 LoadMenu16( HINSTANCE16 instance, SEGPTR name )
 {
@@ -2781,10 +2981,10 @@
     }
     offset = GET_WORD(p);
     p += sizeof(WORD) + offset;
-    if (!(hMenu = CreateMenu())) return 0;
+    if (!(hMenu = CreateMenu32())) return 0;
     if (!MENU_ParseResource( p, hMenu, FALSE ))
     {
-        DestroyMenu( hMenu );
+        DestroyMenu32( hMenu );
         return 0;
     }
     return hMenu;
@@ -2811,10 +3011,10 @@
     }
     offset = GET_WORD(p);
     p += sizeof(WORD) + offset;
-    if (!(hMenu = CreateMenu())) return 0;
+    if (!(hMenu = CreateMenu32())) return 0;
     if (!MENU_ParseResource( p, hMenu, TRUE ))
     {
-        DestroyMenu( hMenu );
+        DestroyMenu32( hMenu );
         return 0;
     }
     return hMenu;
@@ -2832,9 +3032,20 @@
 
 
 /**********************************************************************
- *		IsMenu    (USER.358)
+ *		IsMenu16    (USER.358)
  */
-BOOL IsMenu( HMENU16 hmenu )
+BOOL16 IsMenu16( HMENU16 hmenu )
+{
+    LPPOPUPMENU menu;
+    if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR( hmenu ))) return FALSE;
+    return (menu->wMagic == MENU_MAGIC);
+}
+
+
+/**********************************************************************
+ *		IsMenu32    (USER32.345)
+ */
+BOOL32 IsMenu32( HMENU32 hmenu )
 {
     LPPOPUPMENU menu;
     if (!(menu = (LPPOPUPMENU) USER_HEAP_LIN_ADDR( hmenu ))) return FALSE;
diff --git a/controls/oldlbox.c b/controls/oldlbox.c
index 4c256c9..1eef33c 100644
--- a/controls/oldlbox.c
+++ b/controls/oldlbox.c
@@ -23,10 +23,7 @@
 #include "windows.h"
 #include "win.h"
 #include "gdi.h"
-#include "msdos.h"
 #include "listbox.h"
-#include "dos_fs.h"
-#include "drive.h"
 #include "heap.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -698,81 +695,6 @@
 
 LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec)
 {
-#if 0
-    char 	mask[13];
-    char*	temp = NULL;
-    const char*	ptr;
-    int 	skip, count;
-    LONG 	ret;
-    DOS_DIRENT 	entry;
-    char *path, *p;
-
-    dprintf_listbox(stddeb, "ListBoxDirectory: '%s' %04x\n", filespec, attrib);
-    if (!filespec) return LB_ERR;
-    if (!(ptr = DOSFS_GetUnixFileName( filespec, FALSE ))) return LB_ERR;
-    path = xstrdup(ptr);
-    p = strrchr( path, '/' );
-    *p++ = '\0';
-    if (!(ptr = DOSFS_ToDosFCBFormat( p )) || 
-        !(temp = SEGPTR_ALLOC( sizeof(char) * 16 )) )
-    {
-        free( path );
-        return LB_ERR;
-    }
-
-    strcpy( mask, ptr );
-
-    dprintf_listbox(stddeb, "ListBoxDirectory: path=%s mask=%s\n", path, mask);
-
-    skip = ret = 0;
-    attrib &= ~FA_LABEL;
-    while ((count = DOSFS_FindNext( path, mask, NULL, 0,
-                                    attrib, skip, &entry )) > 0)
-    {
-        skip += count;
-        if (entry.attr & FA_DIRECTORY)
-        {
-            if ((attrib & DDL_DIRECTORY) && strcmp(entry.name, ".          "))
-            {
-                sprintf(temp, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) );
-                AnsiLower( temp );
-                if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break;
-            }
-        }
-        else  /* not a directory */
-        {
-            if (!(attrib & DDL_EXCLUSIVE) ||
-                ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) ==
-                 (entry.attr & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE))))
-            {
-                strcpy( temp, DOSFS_ToDosDTAFormat( entry.name ) );
-                AnsiLower( temp );
-                if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break;
-            }
-        }
-
-        dprintf_listbox(stddeb,"\tn - %i, file '%s'\n", count, temp); 
-    }
-    if (attrib & DDL_DRIVES)
-    {
-        int x;
-	DWORD oldstyle = lphl->dwStyle;
-	    
-	lphl->dwStyle &= ~LBS_SORT;
-        strcpy( temp, "[-a-]" );
-        for (x = 0; x < MAX_DOS_DRIVES; x++, temp[2]++)
-        {
-            if (DRIVE_IsValid(x))
-                if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break;
-        }
-	lphl->dwStyle = oldstyle;
-    }
-
-    free( path );
-    SEGPTR_FREE( temp );
-
-    return ret;
-#endif
     return 0;
 }
 
diff --git a/controls/widgets.c b/controls/widgets.c
index a884757..0d5e219 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -18,8 +18,12 @@
 
 /* Window procedures */
 
+extern LRESULT EditWndProc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
+                            LPARAM lParam );
 extern LRESULT ListBoxWndProc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
                                LPARAM lParam );
+extern LRESULT PopupMenuWndProc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
+                                 LPARAM lParam );
 
 /* Win16 class info */
 
@@ -42,12 +46,6 @@
       8, 0, "ComboBoxWndProc", "ComboBox" },
     { CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS,
       8, 0, "ComboLBoxWndProc", "ComboLBox" },
-    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
-      sizeof(DWORD), 0, "EditWndProc", "Edit" },
-    { CS_GLOBALCLASS | CS_SAVEBITS,
-      sizeof(HMENU32), 0, "PopupMenuWndProc", POPUPMENU_CLASS_NAME },
-    { CS_GLOBALCLASS | CS_SAVEBITS,
-      DLGWINDOWEXTRA, 0, "DefDlgProc", DIALOG_CLASS_NAME },
     { CS_GLOBALCLASS, sizeof(MDICLIENTINFO),
       STOCK_LTGRAY_BRUSH, "MDIClientWndProc", "MDIClient" }
 };
@@ -62,11 +60,17 @@
     { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
       ButtonWndProc, 0, sizeof(BUTTONINFO), 0, 0, 0, 0, 0, "Button" },
     { CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,
+      EditWndProc, 0, sizeof(void *), 0, 0, 0, 0, 0, "Edit" },
+    { CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,
       ListBoxWndProc, 0, sizeof(void *), 0, 0, 0, 0, 0, "ListBox" },
+    { CS_GLOBALCLASS | CS_SAVEBITS, PopupMenuWndProc,
+      0, sizeof(HMENU32), 0, 0, 0, 0, 0, POPUPMENU_CLASS_NAME },
     { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
       ScrollBarWndProc, 0, sizeof(SCROLLBAR_INFO), 0, 0, 0, 0, 0, "ScrollBar"},
     { CS_GLOBALCLASS, DesktopWndProc, 0, sizeof(DESKTOPINFO),
-      0, 0, 0, 0, 0, DESKTOP_CLASS_NAME }
+      0, 0, 0, 0, 0, DESKTOP_CLASS_NAME },
+    { CS_GLOBALCLASS | CS_SAVEBITS, DefDlgProc32A, 0, DLGWINDOWEXTRA,
+      0, 0, 0, 0, 0, DIALOG_CLASS_NAME }
 };
 
 #define NB_BUILTIN_CLASSES32 \
diff --git a/debugger/Makefile.in b/debugger/Makefile.in
index 6a3634c..3f5d49d 100644
--- a/debugger/Makefile.in
+++ b/debugger/Makefile.in
@@ -8,14 +8,18 @@
 C_SRCS = \
 	break.c \
 	db_disasm.c \
+	display.c \
 	editline.c \
+	expr.c \
 	hash.c \
 	info.c \
 	memory.c \
 	msc.c	\
 	registers.c \
+	source.c \
 	stabs.c	\
-	stack.c
+	stack.c \
+	types.c
 
 GEN_C_SRCS = \
 	y.tab.c \
@@ -23,6 +27,12 @@
 
 all: $(MODULE).o
 
+#
+# This is a special test program that helps debug the internal debugger.
+#
+debug: $(MODULE).o dbgmain.o ../misc/xmalloc.o
+	$(CC) -o debug $(MODULE).o dbgmain.o ../misc/xmalloc.o
+
 @MAKE_RULES@
 
 y.tab.c y.tab.h: dbg.y
diff --git a/debugger/README b/debugger/README
index 5715339..02cad9b 100644
--- a/debugger/README
+++ b/debugger/README
@@ -1,17 +1,423 @@
-
 	This is the core of the Wine debugger.  Many pieces have been
-shamelessly stolen - the reverse assember was stolen from gdb more or
+shamelessly stolen - the reverse assember was stolen from Mach more or
 less intact.  It turns out that there are two variables that are set
 differently if you are reverse assembling 16 bit code, and on the
-whole it seems to work.  There may be bugs for all I know.
+whole it seems to work.
 
-	As far as non-linux systems are concerned, I simply ripped off
-the linux configuration files from gdb.  Other systems may be close
-enough for these to work properly, but some tweaking may be required.
+NEWS:
 
-	I apologize for the non-portability of this, but I wrote the
-whole thing in about 4 hours, most of the time spent debugging a
-stupid mistake in the parser.
+	The internal debugger has *tons* more capability than it did before.
+I have enclosed some examples that show usage at the end of this file.
+New features include:
 
--Eric
+	1) Ability of debugger to read debug information from wine executable
+*and* from Win32 executables.  Local variable and line number information is
+also read and processed.
 
+	2) The internal debugger is capable of 'stepping' to the next
+line number, just like gdb.  Examples of the commands are:
+
+	step
+	stepi
+	si
+	step 3
+	si 5
+	next
+	nexti
+	cont 4
+	finish
+
+All of these should be exactly like how gdb does things.
+
+	3) The internal debugger now has a sense of what source file and line
+number a given PC is at.  New commands to support this are just like gdb,
+and include:
+
+	list
+	dir
+	show dir
+
+there are a variety of formats of arguments for the list command.  All
+permutations supported by gdb should also be supported.
+
+	4) The internal debugger knows about datatypes of various objects,
+for both Win32 *and* the debugging information in the wine executable itself.
+I have enclosed an example of how this works at the end.
+
+	5) There are more ways the 'b' command can be used to set breakpoints.
+Examples are:
+
+	b *0x8190000
+	b 1100
+	b Usage
+	b
+
+I don't think this covers all of the permutations that gdb accepts (this should
+be cleaned up someday so that all possibilities are acceptable).
+
+	6)  The 'print' and 'x' commands should behave more or less exactly
+as they do under gdb.  The difference is that the way the data is presented
+will be slightly different, but the content should be fundamentally the same.
+
+	7) The internal debugger now supports conditional breakpoints, and
+automatic display expressions.  An example is at the end of this file.  The
+syntax and usage should be identical to that of gdb.
+
+NOTES:
+
+	If it weren't for the fact that gdb doesn't grok the Win32 debug
+information, you could just use gdb.  The internal debugger should be able
+to read and use debugging information for both Win32 and also for the
+Wine executable, making it possible to debug the combination of the two
+together as if it were one large (very large) entity.
+
+LIMITATIONS AND DIFFERENCES FROM GDB:
+
+	You cannot use type casts in expressions that you give to the
+debugger.  The hardest part about adding support for this is fixing
+the parser/lexer to know when it is handling a type cast, and when it
+is handling any other type of parenthesized expression.  With lexer
+states, it may be possible to keep track of what we would expect at
+any given moment, but it would be tedious to go through and make sure
+that the state is set up correctly for all of the different operators
+and characters that we accept, and I am not yet convinced that this would
+even work.
+
+	You cannot set a breakpoint by file and line number as you can
+with gdb.  Adding support for this wouldn't be all that tough, I guess, but
+it would be a nuisance.   You can set a breakpoint given a function and
+line number, however.  An example would be 'b main:2993'.  It turns out
+that the way the internal data structures are arranged it is a whole lot
+easier to do things in this way than it would be to try and get the
+source:line type of breakpoint working, but it would probably be worth it
+to try.
+
+	Getting stack traces through Wine itself can be a bit tricky.
+This is because by default the thing is built with optimization
+enabled, and as a result sometimes functions don't get frames, and
+lots of variables are optimized into registers.  You can turn off
+optimization for a few key source files if it will help you.
+
+	Memory consumption is getting to be a real problem.  I think 32Mb is
+no longer sufficient to debug wine - 48 or 64 is probably a whole lot better.
+Unfortunately I cannot shut down X to save memory :-).
+
+*************************************************************************
+EXAMPLES:
+
+	Here is an example of how I tracked down a bug in Wine.  The program
+is something that just maps and dumps the contents of a Win32 executable.
+It was dying for some reason.
+
+Start the first time through.
+
+bash$ ls -l dumpexe.exe 
+-rw-rw-r--   1 eric     devel      168448 Jan  4 13:51 dumpexe.exe
+bash$ ./wine -debug './dumpexe.exe -symbol ./dumpexe.exe'
+Warning: invalid dir 'e:\test' in path, deleting it.
+Win32 task 'W32SXXXX': Breakpoint 1 at 0x081a3450
+Loading symbols from ELF file ./wine...
+Loading symbols from ELF file /usr/X11R6/lib/libXpm.so.4.6...
+Loading symbols from ELF file /usr/X11R6/lib/libSM.so.6.0...
+Loading symbols from ELF file /usr/X11R6/lib/libICE.so.6.0...
+Loading symbols from ELF file /usr/X11R6/lib/libXext.so.6.0...
+Loading symbols from ELF file /usr/X11R6/lib/libX11.so.6.0...
+Loading symbols from ELF file /lib/libm.so.5.0.5...
+Loading symbols from ELF file /lib/libc.so.5.2.18...
+Loading symbols from ELF file /lib/ld-linux.so.1...
+Loading symbols from Win32 file ./dumpexe.exe...
+Stopped on breakpoint 1 at 0x081a3450 (_mainCRTStartup)
+In 32 bit mode.
+*** Invalid address 0x414c5ff8 (KERNEL32_NULL_THUNK_DATA+0x3930ee6c)
+0x081a3450 (_mainCRTStartup):  movl	%fs:0,%eax
+Wine-dbg>b DumpFile
+Breakpoint 2 at 0x081a0078 (DumpFile+0x9 [dumpexe.c:2723])
+Wine-dbg>c
+Dump File: ./dumpexe.exe
+Stopped on breakpoint 2 at 0x081a0078 (DumpFile+0x9 [dumpexe.c:2723])
+Enter path to file dumpexe.c: ../de
+2723		HANDLE			  hFile = NULL;
+0x081a0078 (DumpFile+0x9 [dumpexe.c:2723]):  movl	$0x0,0xfffffff4(%ebp)
+Wine-dbg>list
+2723		HANDLE			  hFile = NULL;
+2724		HANDLE			  hMap  = NULL;
+2725		PSTR			  lpMap = NULL;
+2726		DWORD			  dwFileSize     = 0;
+2727		DWORD			  dwFileSizeHigh = 0;
+2728	
+2729		PIMAGE_DOS_HEADER	  lpImageDOS  = NULL;
+2730		PIMAGE_FILE_HEADER	  lpImageFile = NULL;
+2731		PIMAGE_NT_HEADERS	  lpImageNT   = NULL;
+2732	
+2733		/*
+Wine-dbg>n 10
+2747		dwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
+0x081a00ea (DumpFile+0x7b [dumpexe.c:2747]):  leal	0xfffffff0(%ebp),%eax
+Wine-dbg>n
+2749		    && (GetLastError() != NO_ERROR) )

+0x081a00fb (DumpFile+0x8c [dumpexe.c:2749]):  cmpl	$-1,0xffffffe8(%ebp)
+Wine-dbg>x/d dwFileSize
+x/d dwFileSize

+ 168448
+Wine-dbg>n
+2758					 PAGE_READONLY, 0, 0, (LPSTR) NULL);
+0x081a0124 (DumpFile+0xb5 [dumpexe.c:2758]):  pushl	$0x0
+Wine-dbg>list 2750
+list 2750

+2750		{
+2751			Fatal("Cannot get size of file %s", lpFileName);
+2752		}
+2753		
+2754		/*
+2755		 * map the file
+2756		 */
+2757		hMap = CreateFileMapping(hFile, (LPSECURITY_ATTRIBUTES) NULL,
+2758					 PAGE_READONLY, 0, 0, (LPSTR) NULL);
+2759		if( hMap == NULL )
+2760		{
+Wine-dbg>n
+2759		if( hMap == NULL )
+0x081a013b (DumpFile+0xcc [dumpexe.c:2759]):  cmpl	$0,0xfffffffc(%ebp)
+Wine-dbg>x hMap
+ 08e48c30
+Wine-dbg>n
+2767		lpMap = (LPSTR) MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
+0x081a0156 (DumpFile+0xe7 [dumpexe.c:2767]):  pushl	$0x0
+Wine-dbg>n
+2768		if( lpMap == NULL )
+0x081a016b (DumpFile+0xfc [dumpexe.c:2768]):  cmpl	$0,0xffffffe0(%ebp)
+Wine-dbg>print lpMap
+0x414c5f40
+Wine-dbg>x lpMap
+ 40007000
+Wine-dbg> x/10x 0x40007000
+ x/10x 0x40007000

+0x40007000 (KERNEL32_NULL_THUNK_DATA+0x37e4fe74): *** Invalid address 0x40007000 (KERNEL32_NULL_THUNK_DATA+0x37e4fe74)
+Wine-dbg>quit
+$
+
+*******************************************************************
+The first time through, we find that MapViewOfFile isn't mapping the file
+correctly into the virtual address space.  Try running again, and step into
+MapViewOfFile to figure out what went wrong.
+*******************************************************************
+
+
+bash$ ./wine -debug './dumpexe.exe -symbol ./dumpexe.exe'
+Warning: invalid dir 'e:\test' in path, deleting it.
+Win32 task 'W32SXXXX': Breakpoint 1 at 0x081a3450
+Loading symbols from ELF file ./wine...
+Loading symbols from ELF file /usr/X11R6/lib/libXpm.so.4.6...
+Loading symbols from ELF file /usr/X11R6/lib/libSM.so.6.0...
+Loading symbols from ELF file /usr/X11R6/lib/libICE.so.6.0...
+Loading symbols from ELF file /usr/X11R6/lib/libXext.so.6.0...
+Loading symbols from ELF file /usr/X11R6/lib/libX11.so.6.0...
+Loading symbols from ELF file /lib/libm.so.5.0.5...
+Loading symbols from ELF file /lib/libc.so.5.2.18...
+Loading symbols from ELF file /lib/ld-linux.so.1...
+Loading symbols from Win32 file ./dumpexe.exe...
+Stopped on breakpoint 1 at 0x081a3450 (_mainCRTStartup)
+In 32 bit mode.
+*** Invalid address 0x414c5ff8 (KERNEL32_NULL_THUNK_DATA+0x3930ee6c)
+0x081a3450 (_mainCRTStartup):  movl	%fs:0,%eax
+Wine-dbg>b DumpFile:2767
+Breakpoint 2 at 0x081a0156 (DumpFile+0xe7 [dumpexe.c:2767])
+Wine-dbg>c
+Dump File: ./dumpexe.exe

+Stopped on breakpoint 2 at 0x081a0156 (DumpFile+0xe7 [dumpexe.c:2767])
+Enter path to file dumpexe.c: ../de
+2767		lpMap = (LPSTR) MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
+0x081a0156 (DumpFile+0xe7 [dumpexe.c:2767]):  pushl	$0x0
+Wine-dbg>step
+390	0385 stdcall MapViewOfFile(long long long long long) MapViewOfFile
+0x080d793c (KERNEL32_385 [kernel32.spec:390]):  pushl	%ebp
+Wine-dbg>step
+223	    if (!debugging_relay) return;
+0x080c83dc (RELAY_DebugCallFrom32+0xc [relay.c:223]):  cmpw	$0,0x644a
+Wine-dbg>
+244	}
+0x080c848e (RELAY_DebugCallFrom32+0xbe [relay.c:244]):  leal	0xfffffff4(%ebp),%esp
+Wine-dbg>
+103	    return MapViewOfFileEx(handle,access,offhi,offlo,size,0);
+0x080911a4 (MapViewOfFile+0x14 [file.c:103]):  pushl	$0x0
+Wine-dbg>
+113	    FILEMAP_OBJECT *fmap = (FILEMAP_OBJECT*)handle;
+0x080911cf (MapViewOfFileEx+0xf [file.c:113]):  movl	0x8(%ebp),%esi
+Wine-dbg>n
+115	    if (!size) size = fmap->size;
+0x080911d2 (MapViewOfFileEx+0x12 [file.c:115]):  testl	%ebx,%ebx
+Wine-dbg>list
+list

+115	    if (!size) size = fmap->size;
+116	    if (!size) size = 1;
+117	    return mmap ((caddr_t)st, size, fmap->prot, 
+118	                 MAP_ANON|MAP_PRIVATE, 
+119			 FILE_GetUnixHandle(fmap->hfile),
+120			 offlo);
+121	}
+122	
+123	/***********************************************************************
+124	 *           UnmapViewOfFile                  (KERNEL32.385)
+125	 */
+Wine-dbg>x size
+ 00000000
+Wine-dbg>n
+116	    if (!size) size = 1;
+0x080911d9 (MapViewOfFileEx+0x19 [file.c:116]):  testl	%ebx,%ebx
+Wine-dbg>x size
+ 00000000
+Wine-dbg>n
+117	    return mmap ((caddr_t)st, size, fmap->prot, 
+0x080911e2 (MapViewOfFileEx+0x22 [file.c:117]):  pushl	%eax
+Wine-dbg>x size
+ 00000000
+Wine-dbg>info local
+MapViewOfFileEx:handle == 0x08e48c90
+MapViewOfFileEx:access == 0x00000004
+MapViewOfFileEx:offhi == 0x00000000
+MapViewOfFileEx:offlo == 0x00000000
+MapViewOfFileEx:size == 0x00000000
+MapViewOfFileEx:st == 0x00000000
+MapViewOfFileEx:offlo optimized into register $eax 
+MapViewOfFileEx:size optimized into register $ebx 
+MapViewOfFileEx:st optimized into register $edi 
+MapViewOfFileEx:fmap optimized into register $esi 
+Wine-dbg>print $ebx
+0x0001
+Wine-dbg>bt
+bt

+Backtrace:
+=>0 0x080911e2 (MapViewOfFileEx+0x22 [file.c:117])
+  1 0x080911b0 (MapViewOfFile+0x20(handle=0x8e48c90, access=0x4, offhi=0x0, offlo=0x0, size=0x0) [file.c:104])
+  2 0x08104ab5 (CallFrom32_stdcall_5+0x25 [callfrom32.s])
+  3 0x081a0168 (DumpFile+0xf9(lpFileName=0x414c61ed) [dumpexe.c:2767])
+  4 0x081a0c35 (main+0x410(argc=0x3, argv=0x414c61cc) [dumpexe.c:3078])
+  5 0x081a3514 (_mainCRTStartup+0xc4)
+  6 0x0810549f (Code_Start+0x13 [callto32.s])
+  7 0x0802fdac (TASK_CallToStart+0x8c [task.c:373])
+
+Wine-dbg>
+
+*******************************************************************
+Notice that you can step through the thunks into our own transfer
+routines.   You will notice that the source line displays as something
+like:
+
+390	0385 stdcall MapViewOfFile(long long long long long) MapViewOfFile
+
+This is just the source line from the spec file that caused the transfer
+routine to be generated.  From this you can step again, and you step
+into the relay logging code - keep stepping and you eventually step into
+the actual function that does the dirty work.
+
+	At this point an examination of the source to the Win32 program
+and an examination of the source to win32/file.s showed where the problem
+was.  When you specify 0 for the size of the object in CreateFileMapping,
+it is supposed to use the entire size of the file as the size of the
+object.  Instead we were just blindly copying the number over.
+
+*******************************************************************
+
+Wine-dbg>b main
+Breakpoint 1 at 0x080108c0 (main [dbgmain.c:213])
+Wine-dbg>print breakpoints[1]
+{addr={type=0x08043000, seg=0, off=134285504}, addrlen=' ', opcode='U', enabled=1, skipcount=0, in_use=1}
+
+Wine-dbg> print breakpoints[1].enabled
+1
+Wine-dbg>set breakpoints[0].enabled = 0
+Wine-dbg>print breakpoints[0].enabled
+0
+
+Wine-dbg>print type_hash_table[1]->type
+STRUCT
+
+Wine-dbg>print type_hash_table[1]
+0x08072020
+Wine-dbg>print *type_hash_table[1]
+print *type_hash_table[1]

+{type=STRUCT, next=0x00000000, name="LOGPALETTE", un={basic={basic_type=8, output_format=" V M", basic_size=-128, b_signed=0}, bitfield={bitoff=8, nbits=0, basetype=0x081d56c0}, pointer={pointsto=0x00000008}, funct={rettype=0x00000008}, array={start=8, end=136140480, basictype=0x08043e80}, structure={size=8, members=0x081d56c0}, enumeration={members=0x00000008}}}
+Wine-dbg>
+
+*******************************************************************
+
+	This example shows how you can print out various data structures.
+Note that enumerated types are displayed in the symbolic form, and strings
+are displayed in the expected manner.
+
+	You can use the set command to set more or less anything.  Note
+however that you cannot use enumerated types on the RHS of the expression.
+
+	Finally, type casts are not yet supported in the expression
+handling.  There is sufficient information stored internally to be
+able to handle this - the main challenge is that the parser would
+need to be fixed to correctly parse the type cast.
+
+*******************************************************************
+
+
+Wine-dbg>list
+2986            if( argc <= 1 )
+2987            {
+2988                    Usage(argv[0]);
+2989            }
+2990
+2991            for( i = 1; i < argc; i++ )
+2992            {
+2993                    if( strncmp(argv[i], "-dos", sizeof("-dos") - 1) == 0 )
+2994                    {
+2995                            DmpCtrl.bDumpDOSHeader = TRUE;
+2996                    }
+Wine-dbg>b 2993
+Breakpoint 3 at 0x081a8861 (main+0x3c [dumpexe.c:2993])
+Wine-dbg>condition 3 i == 2
+Wine-dbg>c
+Stopped on breakpoint 3 at 0x081a8861 (main+0x3c [dumpexe.c:2993])
+2993                    if( strncmp(argv[i], "-dos", sizeof("-dos") - 1) == 0 )
+0x081a8861 (main+0x3c [dumpexe.c:2993]):  pushl $0x4
+Wine-dbg>print i
+2
+Wine-dbg>print argv[i]
+"./dumpexe.exe"
+
+*******************************************************************
+
+	This example shows how to use conditional breakpoints.
+	Here is another one that demonstrates another cool feature
+	conditional breakpoints that involve a function call:
+
+		condition 3 strcmp(argv[i], "./dumpexe.exe") == 0
+
+*******************************************************************
+
+
+Wine-dbg>list
+2986            if( argc <= 1 )
+2987            {
+2988                    Usage(argv[0]);
+2989            }
+2990
+2991            for( i = 1; i < argc; i++ )
+2992            {
+2993                    if( strncmp(argv[i], "-dos", sizeof("-dos") - 1) == 0 )
+2994                    {
+2995                            DmpCtrl.bDumpDOSHeader = TRUE;
+2996                    }
+Wine-dbg>b 2993
+Breakpoint 3 at 0x081a8861 (main+0x3c [dumpexe.c:2993])
+Wine-dbg>condition 3 strcmp(argv[i], "./dumpexe.exe") == 0
+Wine-dbg>info break
+Breakpoints:
+1: y 0x081ab450 (_mainCRTStartup)
+2: y 0x081a882e (main+0x9 [dumpexe.c:2986])
+3: y 0x081a8861 (main+0x3c [dumpexe.c:2993])
+                stop when  ( strcmp(( argv[i] ), "./dumpexe.exe") == 0 )
+Wine-dbg>c
+Stopped on breakpoint 3 at 0x081a8861 (main+0x3c [dumpexe.c:2993])
+2993                    if( strncmp(argv[i], "-dos", sizeof("-dos") - 1) == 0 )
+0x081a8861 (main+0x3c [dumpexe.c:2993]):  pushl $0x4
+Wine-dbg>print i
+2
+Wine-dbg>print argv[i]  
+"./dumpexe.exe"
+Wine-dbg>
diff --git a/debugger/TODO b/debugger/TODO
index 54de7a6..3544b12 100644
--- a/debugger/TODO
+++ b/debugger/TODO
@@ -3,28 +3,42 @@
 possible to me right now.   In no particular order.  If someone else
 wants to dig in, feel free.
 
-1) Some kind of crude display capability.  Not too hard, I guess.
-	Just keep a list of addresses, counts and formats that we
-	want displayed each time we enter the debugger.
-
-2) Some kind of single step capability.
-	I am not sure - I think you just set a flag
-	in AFLAGS, and you get an interrupt back again.
-	The signal type would proabably be different, however,
-	but Wine could easily be patched to accept this one as well.
-	The main problem with this is that gdb normally runs in a
-	separate process so it is easy to single step second process.
-	Here we are all part of the same process.  Perhaps we could look
-	ahead to the end of the instruction and set another breakpoint?
-
-3) Some kind of breakpoint capability.
-	Requires single step.  When we restart, we
-	remove the breakpoint, single step one instruction
-	replace the breakpoint, and then continue.
-
-4) Some kind of watchpoint capability.  Pretty easy once we have a
+1) Some kind of watchpoint capability.  Pretty easy once we have a
 	single step capability, but we end up running the program
-	really slowly one instruction at a time.
+	really slowly one instruction at a time.  Use hardware debug
+	registers for this???
 
-5) Some kind of .wdbinit file.
+2) Some kind of .wdbinit file.
 
+3) Add 'info line' command.  Not all *that* useful, but it would tell you
+	the range of PC for a given source line.
+
+4) Add search directory list for PDB files.  We have the path in the
+	DOS notation (i.e. C:\foo\bar\xxx.c), which may be a useful hint.
+	Maybe not.
+
+5) Add support for emacs mode so that you  can run under emacs and have
+	the source pop up automatically.  Only useful once the list command
+	is implemented.
+
+6 Add support for Borland.  I have heard rumors that Borland is forthcoming
+	with info about how their stuff works, so this might not be that
+	bad.
+
+7 Add support for Win16.  Not sure if this is really worth the trouble.  How
+	much are people really going to use this in the long run???
+
+8) Some of the newer displays are still a little bit sparse on information.
+	Make these more like gdb.
+
+9) Don't bother to disassemble an instruction when we stop at a breakpoint
+	and if we have a valid source line we are displaying.
+
+10) Add support for '/i', etc in display command.  Make sure 'display/i $eip'
+	does the correct thing, and then skip automatic disassembly completely.
+
+11)	Limit amount of information displayed with print command.
+
+12)	Make sure operator precedence works OK.
+
+****************
diff --git a/debugger/break.c b/debugger/break.c
index eb97f6c..5cf164f 100644
--- a/debugger/break.c
+++ b/debugger/break.c
@@ -14,15 +14,17 @@
 
 #define INT3          0xcc   /* int 3 opcode */
 
-#define MAX_BREAKPOINTS 25
+#define MAX_BREAKPOINTS 100
 
 typedef struct
 {
-    DBG_ADDR    addr;
-    BYTE        addrlen;
-    BYTE        opcode;
-    BOOL16      enabled;
-    BOOL16      in_use;
+    DBG_ADDR      addr;
+    BYTE          addrlen;
+    BYTE          opcode;
+    BOOL16        enabled;
+    WORD	  skipcount;
+    BOOL16        in_use;
+    struct expr * condition;
 } BREAKPOINT;
 
 static BREAKPOINT breakpoints[MAX_BREAKPOINTS];
@@ -65,7 +67,7 @@
  * Determine if the instruction at CS:EIP is an instruction that
  * we need to step over (like a call or a repetitive string move).
  */
-static BOOL32 DEBUG_IsStepOverInstr(void)
+static BOOL32 DEBUG_IsStepOverInstr()
 {
     BYTE *instr = (BYTE *)PTR_SEG_OFF_TO_LIN( CS_reg(&DEBUG_context),
                                               EIP_reg(&DEBUG_context) );
@@ -126,6 +128,31 @@
 
 
 /***********************************************************************
+ *           DEBUG_IsFctReturn
+ *
+ * Determine if the instruction at CS:EIP is an instruction that
+ * is a function return.
+ */
+BOOL32 DEBUG_IsFctReturn(void)
+{
+    BYTE *instr = (BYTE *)PTR_SEG_OFF_TO_LIN( CS_reg(&DEBUG_context),
+                                              EIP_reg(&DEBUG_context) );
+
+    for (;;)
+    {
+        switch(*instr)
+        {
+	case 0xc2:
+	case 0xc3:
+	  return TRUE;
+        default:
+            return FALSE;
+        }
+    }
+}
+
+
+/***********************************************************************
  *           DEBUG_SetBreakpoints
  *
  * Set or remove all the breakpoints.
@@ -205,6 +232,7 @@
     breakpoints[num].opcode  = *p;
     breakpoints[num].enabled = TRUE;
     breakpoints[num].in_use  = TRUE;
+    breakpoints[num].skipcount = 0;
     fprintf( stderr, "Breakpoint %d at ", num );
     DEBUG_PrintAddress( &breakpoints[num].addr, breakpoints[num].addrlen,
 			TRUE );
@@ -226,6 +254,7 @@
     }
     breakpoints[num].enabled = FALSE;
     breakpoints[num].in_use  = FALSE;
+    breakpoints[num].skipcount = 0;
 }
 
 
@@ -242,6 +271,7 @@
         return;
     }
     breakpoints[num].enabled = enable;
+    breakpoints[num].skipcount = 0;
 }
 
 
@@ -263,6 +293,12 @@
             DEBUG_PrintAddress( &breakpoints[i].addr, breakpoints[i].addrlen,
 				TRUE);
             fprintf( stderr, "\n" );
+	    if( breakpoints[i].condition != NULL )
+	      {
+		fprintf(stderr, "\t\tstop when  ");
+ 		DEBUG_DisplayExpr(breakpoints[i].condition);
+		fprintf(stderr, "\n");
+	      }
         }
     }
 }
@@ -274,10 +310,12 @@
  * Determine if we should continue execution after a SIGTRAP signal when
  * executing in the given mode.
  */
-BOOL32 DEBUG_ShouldContinue( enum exec_mode mode )
+BOOL32 DEBUG_ShouldContinue( enum exec_mode mode, int * count )
 {
     DBG_ADDR addr;
+    DBG_ADDR cond_addr;
     int bpnum;
+    struct list_id list;
 
       /* If not single-stepping, back up over the int3 instruction */
     if (!(EFL_reg(&DEBUG_context) & STEP_FLAG)) EIP_reg(&DEBUG_context)--;
@@ -291,20 +329,98 @@
 
     if ((bpnum != 0) && (bpnum != -1))
     {
+        if( breakpoints[bpnum].condition != NULL )
+	  {
+	    cond_addr = DEBUG_EvalExpr(breakpoints[bpnum].condition);
+	    if( cond_addr.type == NULL )
+	      {
+		/*
+		 * Something wrong - unable to evaluate this expression.
+		 */
+		fprintf(stderr, "Unable to evaluate expression ");
+ 		DEBUG_DisplayExpr(breakpoints[bpnum].condition);
+		fprintf(stderr, "\nTurning off condition\n");
+		DEBUG_AddBPCondition(bpnum, NULL);
+	      }
+	    else if( ! DEBUG_GetExprValue( &cond_addr, NULL) )
+	      {
+		return TRUE;
+	      }
+	  }
+
+        if( breakpoints[bpnum].skipcount > 0 )
+	  {
+	    breakpoints[bpnum].skipcount--;
+	    if( breakpoints[bpnum].skipcount > 0 )
+	      {
+		return TRUE;
+	      }
+	  }
         fprintf( stderr, "Stopped on breakpoint %d at ", bpnum );
         DEBUG_PrintAddress( &breakpoints[bpnum].addr,
                             breakpoints[bpnum].addrlen, TRUE );
         fprintf( stderr, "\n" );
+	
+	/*
+	 * See if there is a source file for this bp.  If so,
+	 * then dig it out and display one line.
+	 */
+	DEBUG_FindNearestSymbol( &addr, TRUE, NULL, 0, &list);
+	if( list.sourcefile != NULL )
+	  {
+	    DEBUG_List(&list, NULL, 0);
+	  }
         return FALSE;
     }
 
+    /*
+     * If our mode indicates that we are stepping line numbers,
+     * get the current function, and figure out if we are exactly
+     * on a line number or not.
+     */
+    if( mode == EXEC_STEP_OVER 
+	|| mode == EXEC_STEP_INSTR )
+      {
+	if( DEBUG_CheckLinenoStatus(&addr) == AT_LINENUMBER )
+	  {
+	    (*count)--;
+	  }
+      }
+    else if( mode == EXEC_STEPI_OVER 
+	|| mode == EXEC_STEPI_INSTR )
+
+      {
+	(*count)--;
+      }
+
+    if( *count > 0 || mode == EXEC_FINISH )
+      {
+	/*
+	 * We still need to execute more instructions.
+	 */
+	return TRUE;
+      }
+    
+    /*
+     * If we are about to stop, then print out the source line if we
+     * have it.
+     */
+    if( (mode != EXEC_CONT && mode != EXEC_FINISH) )
+      {
+	DEBUG_FindNearestSymbol( &addr, TRUE, NULL, 0, &list);
+	if( list.sourcefile != NULL )
+	  {
+	    DEBUG_List(&list, NULL, 0);
+	  }
+      }
+
     /* If there's no breakpoint and we are not single-stepping, then we     */
     /* must have encountered an int3 in the Windows program; let's skip it. */
     if ((bpnum == -1) && !(EFL_reg(&DEBUG_context) & STEP_FLAG))
         EIP_reg(&DEBUG_context)++;
 
       /* no breakpoint, continue if in continuous mode */
-    return (mode == EXEC_CONT);
+    return (mode == EXEC_CONT || mode == EXEC_FINISH);
 }
 
 
@@ -314,16 +430,102 @@
  * Set the breakpoints to the correct state to restart execution
  * in the given mode.
  */
-void DEBUG_RestartExecution( enum exec_mode mode, int instr_len )
+enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count )
 {
     DBG_ADDR addr;
+    DBG_ADDR addr2;
+    int bp;
+    int	delta;
+    int status;
+    unsigned int * value;
+    enum exec_mode ret_mode;
+    BYTE *instr;
 
     addr.seg = (CS_reg(&DEBUG_context) == WINE_CODE_SELECTOR) ?
                 0 : CS_reg(&DEBUG_context);
     addr.off = EIP_reg(&DEBUG_context);
 
-    if (DEBUG_FindBreakpoint( &addr ) != -1)
-        mode = EXEC_STEP_INSTR;  /* If there's a breakpoint, skip it */
+    /*
+     * This is the mode we will be running in after we finish.  We would like
+     * to be able to modify this in certain cases.
+     */
+    ret_mode = mode;
+
+    bp = DEBUG_FindBreakpoint( &addr ); 
+    if ( bp != -1 && bp != 0)
+      {
+	/*
+	 * If we have set a new value, then save it in the BP number.
+	 */
+	if( count != 0 && mode == EXEC_CONT )
+	  {
+	    breakpoints[bp].skipcount = count;
+	  }
+        mode = EXEC_STEPI_INSTR;  /* If there's a breakpoint, skip it */
+      }
+    else
+      {
+	if( mode == EXEC_CONT && count > 1 )
+	  {
+	    fprintf(stderr,"Not stopped at any breakpoint; argument ignored.\n");
+	  }
+      }
+    
+    if( mode == EXEC_FINISH && DEBUG_IsFctReturn() )
+      {
+	mode = ret_mode = EXEC_STEPI_INSTR;
+      }
+
+    instr = (BYTE *)PTR_SEG_OFF_TO_LIN( CS_reg(&DEBUG_context),
+					EIP_reg(&DEBUG_context) );
+    /*
+     * See if the function we are stepping into has debug info
+     * and line numbers.  If not, then we step over it instead.
+     * FIXME - we need to check for things like thunks or trampolines,
+     * as the actual function may in fact have debug info.
+     */
+    if( *instr == 0xe8 )
+      {
+	delta = *(unsigned int*) (instr + 1);
+	addr2 = addr;
+	DEBUG_Disasm(&addr2, FALSE);
+	addr2.off += delta;
+	
+	status = DEBUG_CheckLinenoStatus(&addr2);
+	/*
+	 * Anytime we have a trampoline, step over it.
+	 */
+	if( ((mode == EXEC_STEP_OVER) || (mode == EXEC_STEPI_OVER))
+	    && status == FUNC_IS_TRAMPOLINE )
+	  {
+#if 0
+	    fprintf(stderr, "Not stepping into trampoline at %x (no lines)\n",
+		    addr2.off);
+#endif
+	    mode = EXEC_STEP_OVER_TRAMPOLINE;
+	  }
+	
+	if( mode == EXEC_STEP_INSTR && status == FUNC_HAS_NO_LINES )
+	  {
+#if 0
+	    fprintf(stderr, "Not stepping into function at %x (no lines)\n",
+		    addr2.off);
+#endif
+	    mode = EXEC_STEP_OVER;
+	  }
+      }
+
+
+    if( mode == EXEC_STEP_INSTR )
+      {
+	if( DEBUG_CheckLinenoStatus(&addr) == FUNC_HAS_NO_LINES )
+	  {
+	    fprintf(stderr, "Single stepping until exit from function, \n");
+	    fprintf(stderr, "which has no line number information.\n");
+	    
+	    ret_mode = mode = EXEC_FINISH;
+	  }
+      }
 
     switch(mode)
     {
@@ -332,14 +534,35 @@
         DEBUG_SetBreakpoints( TRUE );
         break;
 
+    case EXEC_STEP_OVER_TRAMPOLINE:
+      /*
+       * This is the means by which we step over our conversion stubs
+       * in callfrom*.s and callto*.s.  We dig the appropriate address
+       * off the stack, and we set the breakpoint there instead of the
+       * address just after the call.
+       */
+      value = (unsigned int *) ESP_reg(&DEBUG_context) + 2;
+      addr.off = *value;
+      EFL_reg(&DEBUG_context) &= ~STEP_FLAG;
+      breakpoints[0].addr    = addr;
+      breakpoints[0].enabled = TRUE;
+      breakpoints[0].in_use  = TRUE;
+      breakpoints[0].skipcount = 0;
+      breakpoints[0].opcode  = *(BYTE *)DBG_ADDR_TO_LIN( &addr );
+      DEBUG_SetBreakpoints( TRUE );
+      break;
+
+    case EXEC_FINISH:
+    case EXEC_STEPI_OVER:  /* Stepping over a call */
     case EXEC_STEP_OVER:  /* Stepping over a call */
         if (DEBUG_IsStepOverInstr())
         {
             EFL_reg(&DEBUG_context) &= ~STEP_FLAG;
-            addr.off += instr_len;
+            DEBUG_Disasm(&addr, FALSE);
             breakpoints[0].addr    = addr;
             breakpoints[0].enabled = TRUE;
             breakpoints[0].in_use  = TRUE;
+	    breakpoints[0].skipcount = 0;
             breakpoints[0].opcode  = *(BYTE *)DBG_ADDR_TO_LIN( &addr );
             DEBUG_SetBreakpoints( TRUE );
             break;
@@ -347,7 +570,32 @@
         /* else fall through to single-stepping */
 
     case EXEC_STEP_INSTR: /* Single-stepping an instruction */
+    case EXEC_STEPI_INSTR: /* Single-stepping an instruction */
         EFL_reg(&DEBUG_context) |= STEP_FLAG;
         break;
     }
+    return ret_mode;
+}
+
+int
+DEBUG_AddBPCondition(int num, struct expr * exp)
+{
+    if ((num <= 0) || (num >= next_bp) || !breakpoints[num].in_use)
+    {
+        fprintf( stderr, "Invalid breakpoint number %d\n", num );
+        return FALSE;
+    }
+
+    if( breakpoints[num].condition != NULL )
+      {
+	DEBUG_FreeExpr(breakpoints[num].condition);
+	breakpoints[num].condition = NULL;
+      }
+
+    if( exp != NULL )
+      {
+	breakpoints[num].condition = DEBUG_CloneExpr(exp);
+      }
+
+   return TRUE;
 }
diff --git a/debugger/db_disasm.c b/debugger/db_disasm.c
index cb230c6..32e0d44 100644
--- a/debugger/db_disasm.c
+++ b/debugger/db_disasm.c
@@ -72,6 +72,13 @@
 static BOOL32 db_disasm_16 = FALSE;
 
 /*
+ * Flag to indicate whether we need to display instruction,
+ * or whether we just need to know the address of the next
+ * instruction.
+ */
+static BOOL32 db_display = FALSE;
+
+/*
  * Size attributes
  */
 #define	BYTE	0
@@ -1009,7 +1016,7 @@
         break;
     case LONG:
         {
-            DBG_ADDR address = { 0, addr };
+            DBG_ADDR address = { NULL, 0, addr };
             DEBUG_PrintAddress( &address, db_disasm_16 ? 16 : 32, TRUE );
         }
         break;
@@ -1057,6 +1064,11 @@
 	const char *	name;
 
 	get_value_inc(regmodrm, addr, 1, FALSE);
+	if( !db_display )
+	  {
+	    return;
+	  }
+
 	fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)];
 	mod = f_mod(regmodrm);
 	if (mod != 3) {
@@ -1128,7 +1140,7 @@
  * Disassemble instruction at 'addr'.  addr is changed to point to the
  * start of the next instruction.
  */
-void DEBUG_Disasm( DBG_ADDR *addr )
+void DEBUG_Disasm( DBG_ADDR *addr, int display )
 {
 	int	inst;
 	int	size;
@@ -1146,6 +1158,11 @@
 	int	len;
 	struct i_addr	address;
 
+	/*
+	 * Set this so we get can supress the printout if we need to.
+	 */
+	db_display = display;
+
         if (!addr->seg) db_disasm_16 = FALSE;
         else db_disasm_16 = !(GET_SEL_FLAGS(addr->seg) & LDT_FLAGS_32BIT);
 
@@ -1263,145 +1280,242 @@
 	}
 
 	if (i_size == SDEP) {
-	    if (size == WORD)
+	  if( db_display )
+	    {
+	      if (size == WORD)
 		fprintf(stderr,i_name);
-	    else
+	      else
 		fprintf(stderr,ip->i_extra);
+	    }
 	}
 	else {
-	    fprintf(stderr,i_name);
+	  if( db_display )
+	    {
+	      fprintf(stderr,i_name);
+	    }
 	    if (i_size != NONE) {
 		if (i_size == BYTE) {
-		    fprintf(stderr,"b");
+		  if( db_display )
+		    {
+		      fprintf(stderr,"b");
+		    }
 		    size = BYTE;
 		}
 		else if (i_size == WORD) {
-		    fprintf(stderr,"w");
+		  if( db_display )
+		    {
+		      fprintf(stderr,"w");
+		    }
 		    size = WORD;
 		}
 		else if (size == WORD)
-		    fprintf(stderr,"w");
+		  {
+		  if( db_display )
+		    {
+		      fprintf(stderr,"w");
+		    }
+		  }
 		else
-		    fprintf(stderr,"l");
+		  {
+		  if( db_display )
+		    {
+		      fprintf(stderr,"l");
+		    }
+		  }
 	    }
 	}
-	fprintf(stderr,"\t");
+	if( db_display )
+	  {
+	    fprintf(stderr,"\t");
+	  }
 	for (first = TRUE;
 	     i_mode != 0;
 	     i_mode >>= 8, first = FALSE)
 	{
-	    if (!first)
+	    if (!first && db_display)
 		fprintf(stderr,",");
 
 	    switch (i_mode & 0xFF) {
 
 		case E:
-		    db_print_address(seg, size, &address);
+		  if( db_display )
+		    {
+		      db_print_address(seg, size, &address);
+		    }
 		    break;
 
 		case Eind:
-		    fprintf(stderr,"*");
-		    db_print_address(seg, size, &address);
+		  if( db_display )
+		    {
+		      fprintf(stderr,"*");
+		      db_print_address(seg, size, &address);
+		    }
 		    break;
 
 		case Ew:
-		    db_print_address(seg, WORD, &address);
+		  if( db_display )
+		    {
+		      db_print_address(seg, WORD, &address);
+		    }
 		    break;
 
 		case Eb:
-		    db_print_address(seg, BYTE, &address);
+		  if( db_display )
+		    {
+		      db_print_address(seg, BYTE, &address);
+		    }
 		    break;
 
 		case R:
-		    fprintf(stderr,"%s", db_reg[size][f_reg(regmodrm)]);
+		  if( db_display )
+		    {
+		      fprintf(stderr,"%s", db_reg[size][f_reg(regmodrm)]);
+		    }
 		    break;
 
 		case Rw:
-		    fprintf(stderr,"%s", db_reg[WORD][f_reg(regmodrm)]);
+		  if( db_display )
+		    {
+		      fprintf(stderr,"%s", db_reg[WORD][f_reg(regmodrm)]);
+		    }
 		    break;
 
 		case Ri:
-		    fprintf(stderr,"%s", db_reg[size][f_rm(inst)]);
+		  if( db_display )
+		    {
+		      fprintf(stderr,"%s", db_reg[size][f_rm(inst)]);
+		    }
 		    break;
 
 		case S:
-		    fprintf(stderr,"%s", db_seg_reg[f_reg(regmodrm)]);
+		  if( db_display )
+		    {
+		      fprintf(stderr,"%s", db_seg_reg[f_reg(regmodrm)]);
+		    }
 		    break;
 
 		case Si:
-		    fprintf(stderr,"%s", db_seg_reg[f_reg(inst)]);
+		  if( db_display )
+		    {
+		      fprintf(stderr,"%s", db_seg_reg[f_reg(inst)]);
+		    }
 		    break;
 
 		case A:
-		    fprintf(stderr,"%s", db_reg[size][0]);	/* acc */
+		  if( db_display )
+		    {
+		      fprintf(stderr,"%s", db_reg[size][0]);	/* acc */
+		    }
 		    break;
 
 		case BX:
-		    if (seg)
+		  if( db_display )
+		    {
+		      if (seg)
 			fprintf(stderr,"%s:", seg);
-		    fprintf(stderr,"(%s)", short_addr ? "%bx" : "%ebx");
+		      fprintf(stderr,"(%s)", short_addr ? "%bx" : "%ebx");
+		    }
 		    break;
 
 		case CL:
-		    fprintf(stderr,"%%cl");
+		  if( db_display )
+		    {
+		      fprintf(stderr,"%%cl");
+		    }
 		    break;
 
 		case DX:
-		    fprintf(stderr,"%%dx");
+		  if( db_display )
+		    {
+		      fprintf(stderr,"%%dx");
+		    }
 		    break;
 
 		case SI:
-		    if (seg)
+		  if( db_display )
+		    {
+		      if (seg)
 			fprintf(stderr,"%s:", seg);
-		    fprintf(stderr,"(%s)", short_addr ? "%si" : "%esi");
+		      fprintf(stderr,"(%s)", short_addr ? "%si" : "%esi");
+		    }
 		    break;
 
 		case DI:
-		    fprintf(stderr,"%%es:(%s)", short_addr ? "%di" : "%edi");
+		  if( db_display )
+		    {
+		      fprintf(stderr,"%%es:(%s)", short_addr ? "%di" : "%edi");
+		    }
 		    break;
 
 		case CR:
-		    fprintf(stderr,"%%cr%d", f_reg(regmodrm));
+		  if( db_display )
+		    {
+		      fprintf(stderr,"%%cr%d", f_reg(regmodrm));
+		    }
 		    break;
 
 		case DR:
-		    fprintf(stderr,"%%dr%d", f_reg(regmodrm));
+		  if( db_display )
+		    {
+		      fprintf(stderr,"%%dr%d", f_reg(regmodrm));
+		    }
 		    break;
 
 		case TR:
-		    fprintf(stderr,"%%tr%d", f_reg(regmodrm));
+		  if( db_display )
+		    {
+		      fprintf(stderr,"%%tr%d", f_reg(regmodrm));
+		    }
 		    break;
 
 		case I:
 		    len = db_lengths[size];
 		    get_value_inc(imm, addr, len, FALSE);/* unsigned */
-		    fprintf(stderr,"$0x%x", imm);
+		    if( db_display )
+		      {
+			fprintf(stderr,"$0x%x", imm);
+		      }
 		    break;
 
 		case Is:
 		    len = db_lengths[size];
 		    get_value_inc(imm, addr, len, TRUE); /* signed */
-		    fprintf(stderr,"$%d", imm);
+		  if( db_display )
+		    {
+		      fprintf(stderr,"$%d", imm);
+		    }
 		    break;
 
 		case Ib:
 		    get_value_inc(imm, addr, 1, FALSE); /* unsigned */
-		    fprintf(stderr,"$0x%x", imm);
+		  if( db_display )
+		    {
+		      fprintf(stderr,"$0x%x", imm);
+		    }
 		    break;
 
 		case Ibs:
 		    get_value_inc(imm, addr, 1, TRUE); /* signed */
-		    fprintf(stderr,"$%d", imm);
+		  if( db_display )
+		    {
+		      fprintf(stderr,"$%d", imm);
+		    }
 		    break;
 
 		case Iw:
 		    get_value_inc(imm, addr, 2, FALSE); /* unsigned */
-		    fprintf(stderr,"$0x%x", imm);
+		  if( db_display )
+		    {
+		      fprintf(stderr,"$0x%x", imm);
+		    }
 		    break;
 
 		case Il:
 		    get_value_inc(imm, addr, 4, FALSE);
-		    fprintf(stderr,"$0x%x", imm);
+		  if( db_display )
+		    {
+		      fprintf(stderr,"$0x%x", imm);
+		    }
 		    break;
 
 		case O:
@@ -1411,6 +1525,11 @@
 		    else {
 			get_value_inc(displ, addr, 4, TRUE);
 		    }
+		    if( !db_display )
+		      {
+			break;
+		      }
+
 		    if (seg)
 			fprintf(stderr,"%s:%d",seg, displ);
 		    else
@@ -1419,6 +1538,11 @@
 
 		case Db:
 		    get_value_inc(displ, addr, 1, TRUE);
+		    if( !db_display )
+		      {
+			break;
+		      }
+
 		    if (short_addr) {
 			/* offset only affects low 16 bits */
 		        displ = (addr->off & 0xffff0000)
@@ -1439,15 +1563,25 @@
 			get_value_inc(displ, addr, 4, TRUE);
 			displ += addr->off;
 		    }
+		    if( !db_display )
+		      {
+			break;
+		      }
 		    db_task_printsym( displ, short_addr ? WORD : LONG);
 		    break;
 
 		case o1:
-		    fprintf(stderr,"$1");
+		  if( db_display )
+		    {
+		      fprintf(stderr,"$1");
+		    }
 		    break;
 
 		case o3:
-		    fprintf(stderr,"$3");
+		  if( db_display )
+		    {
+		      fprintf(stderr,"$3");
+		    }
 		    break;
 
 		case OS:
@@ -1457,8 +1591,12 @@
                                        short_addr ? 2 : 4, FALSE );
                         get_value_inc( address.seg, addr,  /* segment */
                                        2, FALSE );
-                        DEBUG_PrintAddress( &address, short_addr ? 16 : 32, 
-					    TRUE );
+			if( db_display )
+			  {
+			    DEBUG_PrintAddress( &address, short_addr ? 16 : 32, 
+						TRUE );
+			  }
+		      
                     }
 		    break;
 	    }
diff --git a/debugger/dbg.y b/debugger/dbg.y
index 4bc7fdf..8db0885 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -16,11 +16,14 @@
 #include "win.h"
 #include "debugger.h"
 
+#include "expr.h"
+
 extern FILE * yyin;
 unsigned int dbg_mode = 0;
 int curr_frame = 0;
 
 static enum exec_mode dbg_exec_mode = EXEC_CONT;
+static int dbg_exec_count = 0;
 
 void issue_prompt(void);
 void mode_command(int);
@@ -36,17 +39,18 @@
     enum debug_regs  reg;
     char *           string;
     int              integer;
+    struct list_id   listing;
+    struct expr *    expression;
 }
 
 %token tCONT tSTEP tLIST tNEXT tQUIT tHELP tBACKTRACE tINFO tWALK tUP tDOWN
-%token tENABLE tDISABLE tBREAK tDELETE tSET tMODE tPRINT tEXAM tDEFINE tABORT
+%token tENABLE tDISABLE tBREAK tDELETE tSET tMODE tPRINT tEXAM tABORT
 %token tCLASS tMODULE tSTACK tSEGMENTS tREGS tWND tQUEUE tLOCAL
-%token tNO_SYMBOL tEOL
-%token tSYMBOLFILE
-%token tFRAME
-
-
-%token <string> tIDENTIFIER
+%token tEOL tSTRING
+%token tFRAME tSHARE tCOND tDISPLAY tUNDISPLAY
+%token tSTEPI tNEXTI tFINISH tSHOW tDIR 
+%token <string> tPATH
+%token <string> tIDENTIFIER tSTRING
 %token <integer> tNUM tFORMAT
 %token <reg> tREG
 
@@ -62,14 +66,19 @@
 %left '&'
 %left OP_EQ OP_NE
 %left '<' '>' OP_LE OP_GE
-%left OP_SHL OP_SHR
+%left OP_SHL OP_SHR OP_DRF
 %left '+' '-'
 %left '*' '/' '%'
 %left OP_SIGN '!' '~' OP_DEREF /* OP_INC OP_DEC OP_ADDR */
+%left '.' '['
 %nonassoc ':'
 
-%type <integer> expr
-%type <address> addr segaddr symbol
+%type <expression> expr lval lvalue
+%type <address> expr_addr lval_addr
+%type <integer> expr_value
+%type <string> pathname
+
+%type <listing> list_arg
 
 %%
 
@@ -83,14 +92,28 @@
 command:
       tQUIT tEOL               { exit(0); }
     | tHELP tEOL               { DEBUG_Help(); }
-    | tCONT tEOL               { dbg_exec_mode = EXEC_CONT; return 0; }
-    | tSTEP tEOL               { dbg_exec_mode = EXEC_STEP_INSTR; return 0; }
-    | tNEXT tEOL               { dbg_exec_mode = EXEC_STEP_OVER; return 0; }
-    | tLIST tEOL               { DEBUG_List( NULL, 15 ); }
-    | tLIST addr tEOL          { DEBUG_List( &$2, 15 ); }
+    | tHELP tINFO tEOL         { DEBUG_HelpInfo(); }
+    | tCONT tEOL               { dbg_exec_count = 1; 
+				 dbg_exec_mode = EXEC_CONT; return 0; }
+    | tCONT tNUM tEOL          { dbg_exec_count = $2; 
+				 dbg_exec_mode = EXEC_CONT; return 0; }
+    | tSTEP tEOL               { dbg_exec_count = 1; 
+				 dbg_exec_mode = EXEC_STEP_INSTR; return 0; }
+    | tNEXT tEOL               { dbg_exec_count = 1; 
+				 dbg_exec_mode = EXEC_STEP_OVER; return 0; }
+    | tSTEP tNUM tEOL          { dbg_exec_count = $2; 
+				 dbg_exec_mode = EXEC_STEP_INSTR; return 0; }
+    | tNEXT tNUM tEOL          { dbg_exec_count = $2; 
+				 dbg_exec_mode = EXEC_STEP_OVER; return 0; }
+    | tSTEPI tEOL              { dbg_exec_count = 1; 
+				 dbg_exec_mode = EXEC_STEPI_INSTR; return 0; }
+    | tNEXTI tEOL              { dbg_exec_count = 1; 
+				 dbg_exec_mode = EXEC_STEPI_OVER; return 0; }
+    | tSTEPI tNUM tEOL         { dbg_exec_count = $2; 
+				 dbg_exec_mode = EXEC_STEPI_INSTR; return 0; }
+    | tNEXTI tNUM tEOL         { dbg_exec_count = $2; 
+				 dbg_exec_mode = EXEC_STEPI_OVER; return 0; }
     | tABORT tEOL              { kill(getpid(), SIGABRT); }
-    | tSYMBOLFILE tIDENTIFIER tEOL  { DEBUG_ReadSymbolTable( $2 ); }
-    | tDEFINE tIDENTIFIER addr tEOL { DEBUG_AddSymbol( $2, &$3, NULL ); }
     | tMODE tNUM tEOL          { mode_command($2); }
     | tENABLE tNUM tEOL        { DEBUG_EnableBreakpoint( $2, TRUE ); }
     | tDISABLE tNUM tEOL       { DEBUG_EnableBreakpoint( $2, FALSE ); }
@@ -100,7 +123,20 @@
     | tUP tNUM tEOL	       { DEBUG_SetFrame( curr_frame + $2 ); }
     | tDOWN tEOL	       { DEBUG_SetFrame( curr_frame - 1 );  }
     | tDOWN tNUM tEOL	       { DEBUG_SetFrame( curr_frame - $2 ); }
-    | tFRAME expr tEOL	       { DEBUG_SetFrame( $2 ); }
+    | tFRAME tNUM tEOL         { DEBUG_SetFrame( $2 ); }
+    | tFINISH tEOL	       { dbg_exec_count = 0;
+				 dbg_exec_mode = EXEC_FINISH; return 0; }
+    | tSHOW tDIR tEOL	       { DEBUG_ShowDir(); }
+    | tDIR pathname tEOL       { DEBUG_AddPath( $2 ); }
+    | tDIR tEOL		       { DEBUG_NukePath(); }
+    | tDISPLAY expr tEOL       { DEBUG_AddDisplay($2); }
+    | tDELETE tDISPLAY tNUM tEOL { DEBUG_DelDisplay( $3 ); }
+    | tDELETE tDISPLAY tEOL    { DEBUG_DelDisplay( -1 ); }
+    | tUNDISPLAY tNUM tEOL     { DEBUG_DelDisplay( $2 ); }
+    | tUNDISPLAY tEOL          { DEBUG_DelDisplay( -1 ); }
+    | tCOND tNUM tEOL          { DEBUG_AddBPCondition($2, NULL); }
+    | tCOND tNUM expr tEOL     { DEBUG_AddBPCondition($2, $3); }
+    | list_command
     | set_command
     | x_command
     | print_command
@@ -109,47 +145,110 @@
     | walk_command
 
 set_command:
-      tSET tREG '=' expr tEOL	     { DEBUG_SetRegister( $2, $4 ); }
-    | tSET '*' addr '=' expr tEOL    { DEBUG_WriteMemory( &$3, $5 ); }
-    | tSET tIDENTIFIER '=' addr tEOL { if (!DEBUG_SetSymbolValue( $2, &$4 ))
-                                       {
-                                           fprintf( stderr,
-                                                 "Symbol %s not found\n", $2 );
-                                           YYERROR;
-                                       }
-                                     }
+      tSET tREG '=' expr_value tEOL	   { DEBUG_SetRegister( $2, $4 ); 
+					     DEBUG_FreeExprMem(); }
+    | tSET lval_addr '=' expr_value tEOL   { DEBUG_WriteMemory( &$2, $4 ); 
+ 					     DEBUG_FreeExprMem(); }
+
+pathname:
+      tIDENTIFIER                    { $$ = $1; }
+    | tPATH			     { $$ = $1; }
+
+list_command:
+      tLIST tEOL               { DEBUG_List( NULL, NULL, 10 ); }
+    | tLIST '-' tEOL	       { DEBUG_List( NULL, NULL, -10 ); }
+    | tLIST list_arg tEOL      { DEBUG_List( & $2, NULL, 10 ); }
+    | tLIST ',' list_arg tEOL  { DEBUG_List( NULL, & $3, -10 ); }
+    | tLIST list_arg ',' list_arg tEOL { DEBUG_List( & $2, & $4, 0 ); }
+
+list_arg:
+      tNUM		       { $$.sourcefile = NULL; $$.line = $1; }
+    | pathname ':' tNUM	       { $$.sourcefile = $1; $$.line = $3; }
+    | tIDENTIFIER	       { DEBUG_GetFuncInfo( & $$, NULL, $1); }
+    | pathname ':' tIDENTIFIER { DEBUG_GetFuncInfo( & $$, $1, $3); }
+    | '*' expr_addr	       { DEBUG_FindNearestSymbol( & $2, FALSE, NULL, 
+							0, & $$ ); 
+ 					     DEBUG_FreeExprMem(); }
 
 x_command:
-      tEXAM addr tEOL          { DEBUG_ExamineMemory( &$2, 1, 'x'); }
-    | tEXAM tFORMAT addr tEOL  { DEBUG_ExamineMemory( &$3, $2>>8, $2&0xff ); }
+      tEXAM expr_addr tEOL     { DEBUG_ExamineMemory( &$2, 1, 'x'); 
+ 					     DEBUG_FreeExprMem(); }
+    | tEXAM tFORMAT expr_addr tEOL  { DEBUG_ExamineMemory( &$3, $2>>8, $2&0xff ); 
+ 					     DEBUG_FreeExprMem(); }
 
 print_command:
-      tPRINT addr tEOL         { DEBUG_Print( &$2, 1, 'x' ); }
-    | tPRINT tFORMAT addr tEOL { DEBUG_Print( &$3, $2 >> 8, $2 & 0xff ); }
+      tPRINT expr_addr tEOL    { DEBUG_Print( &$2, 1, 0, 0 ); 
+ 					     DEBUG_FreeExprMem(); }
+    | tPRINT tFORMAT expr_addr tEOL { DEBUG_Print( &$3, $2 >> 8, $2 & 0xff, 0 ); 
+ 					     DEBUG_FreeExprMem(); }
 
 break_command:
-      tBREAK '*' addr tEOL     { DEBUG_AddBreakpoint( &$3 ); }
-    | tBREAK symbol tEOL       { DEBUG_AddBreakpoint( &$2 ); }
-    | tBREAK symbol '+' expr tEOL { DBG_ADDR addr = $2;
-                                    addr.off += $4;
-                                    DEBUG_AddBreakpoint( &addr ); 
-                                  }
-    | tBREAK tEOL              { DBG_ADDR addr = { CS_reg(&DEBUG_context),
+      tBREAK '*' expr_addr tEOL { DEBUG_AddBreakpoint( &$3 ); 
+ 					     DEBUG_FreeExprMem(); }
+    | tBREAK tIDENTIFIER tEOL  { DBG_ADDR addr;
+				 if( DEBUG_GetSymbolValue($2, -1, &addr, TRUE) )
+				   {
+				     DEBUG_AddBreakpoint( &addr );
+				   }
+				 else
+				   {
+				     fprintf(stderr,"Unable to add breakpoint\n");
+				   }
+				}
+    | tBREAK tIDENTIFIER ':' tNUM tEOL  { DBG_ADDR addr;
+				 if( DEBUG_GetSymbolValue($2, $4, &addr, TRUE) )
+				   {
+				     DEBUG_AddBreakpoint( &addr );
+				   }
+				 else
+				   {
+				     fprintf(stderr,"Unable to add breakpoint\n");
+				   }
+				}
+    | tBREAK tNUM tEOL	       { struct name_hash *nh;
+				 DBG_ADDR addr = { NULL,
+						   CS_reg(&DEBUG_context),
+                                                   EIP_reg(&DEBUG_context) };
+
+				 DBG_FIX_ADDR_SEG( &addr, CS_reg(&DEBUG_context) );
+				 DEBUG_FindNearestSymbol(&addr, TRUE,
+							 &nh, 0, NULL);
+				 if( nh != NULL )
+				   {
+				     DEBUG_GetLineNumberAddr(nh, 
+						      $2, &addr, TRUE);
+				     DEBUG_AddBreakpoint( &addr );
+				   }
+				 else
+				   {
+				     fprintf(stderr,"Unable to add breakpoint\n");
+				   }
+                               }
+
+    | tBREAK tEOL              { DBG_ADDR addr = { NULL,
+						   CS_reg(&DEBUG_context),
                                                    EIP_reg(&DEBUG_context) };
                                  DEBUG_AddBreakpoint( &addr );
                                }
 
 info_command:
       tINFO tBREAK tEOL         { DEBUG_InfoBreakpoints(); }
-    | tINFO tCLASS expr tEOL    { CLASS_DumpClass( (CLASS *)$3 ); }
-    | tINFO tMODULE expr tEOL   { MODULE_DumpModule( $3 ); }
-    | tINFO tQUEUE expr tEOL    { QUEUE_DumpQueue( $3 ); }
+    | tINFO tCLASS expr_value tEOL    { CLASS_DumpClass( (CLASS *)$3 ); 
+ 					     DEBUG_FreeExprMem(); }
+    | tINFO tSHARE tEOL		{ DEBUG_InfoShare(); }
+    | tINFO tMODULE expr_value tEOL   { MODULE_DumpModule( $3 ); 
+ 					     DEBUG_FreeExprMem(); }
+    | tINFO tQUEUE expr_value tEOL    { QUEUE_DumpQueue( $3 ); 
+ 					     DEBUG_FreeExprMem(); }
     | tINFO tREGS tEOL          { DEBUG_InfoRegisters(); }
-    | tINFO tSEGMENTS expr tEOL { LDT_Print( SELECTOR_TO_ENTRY($3), 1 ); }
+    | tINFO tSEGMENTS expr_value tEOL { LDT_Print( SELECTOR_TO_ENTRY($3), 1 ); 
+ 					     DEBUG_FreeExprMem(); }
     | tINFO tSEGMENTS tEOL      { LDT_Print( 0, -1 ); }
     | tINFO tSTACK tEOL         { DEBUG_InfoStack(); }
-    | tINFO tWND expr tEOL      { WIN_DumpWindow( $3 ); } 
+    | tINFO tWND expr_value tEOL      { WIN_DumpWindow( $3 ); 
+ 					     DEBUG_FreeExprMem(); }
     | tINFO tLOCAL tEOL         { DEBUG_InfoLocals(); }
+    | tINFO tDISPLAY tEOL       { DEBUG_InfoDisplay(); }
 
 walk_command:
       tWALK tCLASS tEOL         { CLASS_WalkClasses(); }
@@ -158,70 +257,78 @@
     | tWALK tWND tEOL           { WIN_WalkWindows( 0, 0 ); }
     | tWALK tWND tNUM tEOL      { WIN_WalkWindows( $3, 0 ); }
 
-symbol:
-    tIDENTIFIER            { if (!DEBUG_GetSymbolValue( $1, -1, &$$ ))
-                             {
-                               fprintf( stderr, "Symbol %s not found\n", $1 );
-                               YYERROR;
-                             }
-                           }
-    | tIDENTIFIER ':' tNUM { if (!DEBUG_GetSymbolValue( $1, $3, &$$ ))
-                             {
-                               fprintf( stderr, "No code at %s:%d\n", $1, $3 );
-                               YYERROR;
-                             }
-                           }
+expr_addr:
+    expr			 { $$ = DEBUG_EvalExpr($1) }
 
-addr:
-      expr                       { $$.seg = 0xffffffff; $$.off = $1; }
-    | segaddr                    { $$ = $1; }
-
-segaddr:
-      expr ':' expr              { $$.seg = $1; $$.off = $3; }
-    | symbol                     { $$ = $1; }
-    | symbol '+' expr            { $$ = $1; $$.off += $3; }
-    | symbol '-' expr            { $$ = $1; $$.off -= $3; }
-
+expr_value:
+      expr        { DBG_ADDR addr  = DEBUG_EvalExpr($1);
+		    $$ = *(unsigned int *) addr.off; }
+/*
+ * The expr rule builds an expression tree.  When we are done, we call
+ * EvalExpr to evaluate the value of the expression.  The advantage of
+ * the two-step approach is that it is possible to save expressions for
+ * use in 'display' commands, and in conditional watchpoints.
+ */
 expr:
-      tNUM                       { $$ = $1; }
-    | tREG                       { $$ = DEBUG_GetRegister($1); }
-    | expr OP_LOR expr           { $$ = $1 || $3; }
-    | expr OP_LAND expr          { $$ = $1 && $3; }
-    | expr '|' expr              { $$ = $1 | $3; }
-    | expr '&' expr              { $$ = $1 & $3; }
-    | expr '^' expr              { $$ = $1 ^ $3; }
-    | expr OP_EQ expr            { $$ = $1 == $3; }
-    | expr '>' expr              { $$ = $1 > $3; }
-    | expr '<' expr              { $$ = $1 < $3; }
-    | expr OP_GE expr            { $$ = $1 >= $3; }
-    | expr OP_LE expr            { $$ = $1 <= $3; }
-    | expr OP_NE expr            { $$ = $1 != $3; }
-    | expr OP_SHL expr           { $$ = (unsigned)$1 << $3; }
-    | expr OP_SHR expr           { $$ = (unsigned)$1 >> $3; }
-    | expr '+' expr              { $$ = $1 + $3; }
-    | expr '-' expr              { $$ = $1 - $3; }
-    | expr '*' expr              { $$ = $1 * $3; }
-    | expr '/' expr              { if ($3) 
-                                       if ($3 == -1 && $1 == 0x80000000l)
-                                           yyerror ("Division overflow");
-                                       else $$ = $1 / $3;
-                                   else yyerror ("Division by zero");
-                                 }
-    | expr '%' expr              { if ($3) 
-                                       if ($3 == -1 && $1 == 0x80000000l)
-                                           $$ = 0; /* A sensible result in this case.  */
-                                       else $$ = $1 % $3;
-                                   else yyerror ("Division by zero");
-                                 }
-    | '-' expr %prec OP_SIGN     { $$ = -$2; }
+      tNUM                       { $$ = DEBUG_ConstExpr($1); }
+    | tSTRING			 { $$ = DEBUG_StringExpr($1); }
+    | tREG                       { $$ = DEBUG_RegisterExpr($1); }
+    | tIDENTIFIER		 { $$ = DEBUG_SymbolExpr($1); }
+    | expr OP_DRF tIDENTIFIER	 { $$ = DEBUG_StructPExpr($1, $3); } 
+    | expr '.' tIDENTIFIER	 { $$ = DEBUG_StructExpr($1, $3); } 
+    | tIDENTIFIER '(' ')'	 { $$ = DEBUG_CallExpr($1, 0); } 
+    | tIDENTIFIER '(' expr ')'	 { $$ = DEBUG_CallExpr($1, 1, $3); } 
+    | tIDENTIFIER '(' expr ',' expr ')'	 { $$ = DEBUG_CallExpr($1, 2, $3, 
+							       $5); } 
+    | tIDENTIFIER '(' expr ',' expr ',' expr ')'	 { $$ = DEBUG_CallExpr($1, 3, $3, $5, $7); } 
+    | tIDENTIFIER '(' expr ',' expr ',' expr ',' expr ')'	 { $$ = DEBUG_CallExpr($1, 3, $3, $5, $7, $9); } 
+    | tIDENTIFIER '(' expr ',' expr ',' expr ',' expr ',' expr ')'	 { $$ = DEBUG_CallExpr($1, 3, $3, $5, $7, $9, $11); } 
+    | expr '[' expr ']'		 { $$ = DEBUG_BinopExpr(EXP_OP_ARR, $1, $3); } 
+    | expr ':' expr		 { $$ = DEBUG_BinopExpr(EXP_OP_SEG, $1, $3); } 
+    | expr OP_LOR expr           { $$ = DEBUG_BinopExpr(EXP_OP_LOR, $1, $3); }
+    | expr OP_LAND expr          { $$ = DEBUG_BinopExpr(EXP_OP_LAND, $1, $3); }
+    | expr '|' expr              { $$ = DEBUG_BinopExpr(EXP_OP_OR, $1, $3); }
+    | expr '&' expr              { $$ = DEBUG_BinopExpr(EXP_OP_AND, $1, $3); }
+    | expr '^' expr              { $$ = DEBUG_BinopExpr(EXP_OP_XOR, $1, $3); }
+    | expr OP_EQ expr            { $$ = DEBUG_BinopExpr(EXP_OP_EQ, $1, $3); }
+    | expr '>' expr              { $$ = DEBUG_BinopExpr(EXP_OP_GT, $1, $3); }
+    | expr '<' expr              { $$ = DEBUG_BinopExpr(EXP_OP_LT, $1, $3); }
+    | expr OP_GE expr            { $$ = DEBUG_BinopExpr(EXP_OP_GE, $1, $3); }
+    | expr OP_LE expr            { $$ = DEBUG_BinopExpr(EXP_OP_LE, $1, $3); }
+    | expr OP_NE expr            { $$ = DEBUG_BinopExpr(EXP_OP_NE, $1, $3); }
+    | expr OP_SHL expr           { $$ = DEBUG_BinopExpr(EXP_OP_SHL, $1, $3); }
+    | expr OP_SHR expr           { $$ = DEBUG_BinopExpr(EXP_OP_SHR, $1, $3); }
+    | expr '+' expr              { $$ = DEBUG_BinopExpr(EXP_OP_ADD, $1, $3); }
+    | expr '-' expr              { $$ = DEBUG_BinopExpr(EXP_OP_SUB, $1, $3); }
+    | expr '*' expr              { $$ = DEBUG_BinopExpr(EXP_OP_MUL, $1, $3); }
+    | expr '/' expr              { $$ = DEBUG_BinopExpr(EXP_OP_DIV, $1, $3); }
+    | expr '%' expr              { $$ = DEBUG_BinopExpr(EXP_OP_REM, $1, $3); }
+    | '-' expr %prec OP_SIGN     { $$ = DEBUG_UnopExpr(EXP_OP_NEG, $2); }
     | '+' expr %prec OP_SIGN     { $$ = $2; }
-    | '!' expr                   { $$ = !$2; }
-    | '~' expr                   { $$ = ~$2; }
+    | '!' expr                   { $$ = DEBUG_UnopExpr(EXP_OP_NOT, $2); }
+    | '~' expr                   { $$ = DEBUG_UnopExpr(EXP_OP_LNOT, $2); }
     | '(' expr ')'               { $$ = $2; }
-/* For parser technical reasons we can't use "addr" here.  */
-    | '*' expr %prec OP_DEREF    { DBG_ADDR addr = { 0xffffffff, $2 };
-                                   $$ = DEBUG_ReadMemory( &addr ); }
-    | '*' segaddr %prec OP_DEREF { $$ = DEBUG_ReadMemory( &$2 ); }
+    | '*' expr %prec OP_DEREF    { $$ = DEBUG_UnopExpr(EXP_OP_DEREF, $2); }
+    | '&' expr %prec OP_DEREF    { $$ = DEBUG_UnopExpr(EXP_OP_ADDR, $2); }
+	
+/*
+ * The lvalue rule builds an expression tree.  This is a limited form
+ * of expression that is suitable to be used as an lvalue.
+ */
+lval_addr:
+    lval			 { $$ = DEBUG_EvalExpr($1) }
+
+lval:
+      lvalue                     { $$ = $1; }
+    | '*' expr			 { $$ = DEBUG_UnopExpr(EXP_OP_FORCE_DEREF, $2); }
+	
+lvalue:
+      tNUM                       { $$ = DEBUG_ConstExpr($1); }
+    | tREG                       { $$ = DEBUG_RegisterExpr($1); }
+    | tIDENTIFIER		 { $$ = DEBUG_SymbolExpr($1); }
+    | lvalue OP_DRF tIDENTIFIER	 { $$ = DEBUG_StructPExpr($1, $3); } 
+    | lvalue '.' tIDENTIFIER	 { $$ = DEBUG_StructExpr($1, $3); } 
+    | lvalue '[' expr ']'	 { $$ = DEBUG_BinopExpr(EXP_OP_ARR, $1, $3); } 
 	
 %%
 
@@ -249,7 +356,7 @@
     static int loaded_symbols = 0;
     static BOOL32 in_debugger = FALSE;
     char SymbolTableFile[256];
-    int instr_len = 0, newmode;
+    int newmode;
     BOOL32 ret_ok;
 #ifdef YYDEBUG
     yydebug = 0;
@@ -268,6 +375,12 @@
     if (!loaded_symbols)
     {
         loaded_symbols++;
+
+	/*
+	 * Initialize the type handling stuff.
+	 */
+	DEBUG_InitTypes();
+
 	/*
 	 * In some cases we can read the stabs information directly
 	 * from the executable.  If this is the case, we don't need
@@ -294,12 +407,22 @@
         DEBUG_LoadEntryPoints();
     }
 
-    if ((signal != SIGTRAP) || !DEBUG_ShouldContinue( dbg_exec_mode ))
+#if 0
+    fprintf(stderr, "Entering debugger 	PC=%x, mode=%d, count=%d\n",
+	    EIP_reg(&DEBUG_context),
+	    dbg_exec_mode, dbg_exec_count);
+    
+    sleep(1);
+#endif
+
+    if ((signal != SIGTRAP) || !DEBUG_ShouldContinue( dbg_exec_mode, 
+						      &dbg_exec_count ))
     {
         DBG_ADDR addr;
 
         addr.seg = CS_reg(&DEBUG_context);
         addr.off = EIP_reg(&DEBUG_context);
+	addr.type = NULL;
         DBG_FIX_ADDR_SEG( &addr, 0 );
 
         /* Put the display in a correct state */
@@ -314,6 +437,8 @@
         if (newmode != dbg_mode)
             fprintf(stderr,"In %d bit mode.\n", dbg_mode = newmode);
 
+	DEBUG_DoDisplay();
+
         if (signal != SIGTRAP)  /* This is a real crash, dump some info */
         {
             DEBUG_InfoRegisters();
@@ -326,6 +451,14 @@
             }
             DEBUG_BackTrace();
         }
+	else
+	{
+	  /*
+	   * Do a quiet backtrace so that we have an idea of what the situation
+	   * is WRT the source files.
+	   */
+	    DEBUG_SilentBackTrace();
+	}
 
         /* Show where we crashed */
         curr_frame = 0;
@@ -333,9 +466,8 @@
         fprintf(stderr,":  ");
         if (DBG_CHECK_READ_PTR( &addr, 1 ))
         {
-            DEBUG_Disasm( &addr );
+            DEBUG_Disasm( &addr, TRUE );
             fprintf(stderr,"\n");
-            instr_len = addr.off - EIP_reg(&DEBUG_context);
         }
 
         ret_ok = 0;
@@ -352,7 +484,17 @@
         } while (!ret_ok);
     }
 
-    DEBUG_RestartExecution( dbg_exec_mode, instr_len );
+    dbg_exec_mode = DEBUG_RestartExecution( dbg_exec_mode, dbg_exec_count );
+    /*
+     * This will have gotten absorbed into the breakpoint info
+     * if it was used.  Otherwise it would have been ignored.
+     * In any case, we don't mess with it any more.
+     */
+    if( dbg_exec_mode == EXEC_CONT )
+      {
+	dbg_exec_count = 0;
+      }
+
     in_debugger = FALSE;
 }
 
@@ -375,6 +517,7 @@
 {
     const char *module = MODULE_GetModuleName( GetExePtr(GetCurrentTask()) );
     fprintf( stderr, "%s called DebugBreak\n", module ? module : "???" );
+    DEBUG_context = *regs;
     DEBUG_Main( SIGTRAP );
 }
 
diff --git a/debugger/dbgmain.c b/debugger/dbgmain.c
new file mode 100644
index 0000000..9d3fb8c
--- /dev/null
+++ b/debugger/dbgmain.c
@@ -0,0 +1,232 @@
+/*
+ * File dbgmain.c - main wrapper for internal debugger test bed.
+ *
+ * Copyright (C) 1997, Eric Youngdale.
+ */
+#include <signal.h>
+
+#include <ldt.h>
+#include <windows.h>
+#include <toolhelp.h>
+#include <module.h>
+#include <debugger.h>
+#include <class.h>
+#include <X11/Xlib.h>
+
+#include "debugger.h"
+#include "peexe.h"
+
+ldt_copy_entry ldt_copy[LDT_SIZE];
+unsigned char ldt_flags_copy[LDT_SIZE];
+
+Display * display;
+
+int
+XUngrabPointer( Display * d, Time t)
+{
+  return(0);
+}
+
+int
+XUngrabServer( Display * d )
+{
+  return(0);
+}
+
+int
+XFlush(Display * d )
+{
+  return(0);
+}
+
+HTASK16    GetCurrentTask()
+{
+  exit(0);
+}
+
+HMODULE16  GetExePtr(HANDLE16 h)
+{
+  exit(0);
+}
+
+LPSTR MODULE_GetModuleName( HMODULE16 hModule )
+{
+  exit(0);
+}
+
+int PROFILE_GetWineIniString( const char *section, const char *key_name,
+                                     const char *def, char *buffer, int len )
+{
+  exit(0);
+}
+
+
+void CLASS_DumpClass( CLASS *class )
+{
+  exit(0);
+}
+
+void MODULE_DumpModule( HMODULE16 hmodule )
+{
+  exit(0);
+}
+
+void QUEUE_DumpQueue( HQUEUE16 hQueue )
+{
+  exit(0);
+}
+
+void WIN_DumpWindow( HWND32 hwnd )
+{
+  exit(0);
+}
+
+
+void CLASS_WalkClasses()
+{
+  exit(0);
+}
+
+void MODULE_WalkModules()
+{
+  exit(0);
+}
+
+void QUEUE_WalkQueues()
+{
+  exit(0);
+}
+
+void WIN_WalkWindows( HWND32 hwnd, int indent )
+{
+  exit(0);
+}
+
+NE_MODULE *MODULE_GetPtr( HMODULE16 hModule )
+{
+  exit(0);
+}
+
+FARPROC16 MODULE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
+{
+  exit(0);
+}
+
+void LDT_Print( int start, int length )
+{
+  exit(0);
+}
+
+LPVOID     GlobalLock16(HGLOBAL16 h)
+{
+  exit(0);
+}
+
+BOOL16 ModuleFirst(MODULEENTRY *lpModule)
+{
+  return 0;
+}
+
+BOOL16 ModuleNext(MODULEENTRY *lpModule)
+{
+  return 0;
+}
+
+BOOL16     IsBadReadPtr16(SEGPTR s,UINT16 o)
+{
+  exit(0);
+}
+
+BOOL32     IsBadReadPtr32(LPCVOID s,UINT32 o)
+{
+  exit(0);
+}
+
+struct qwert
+{
+  unsigned flag1:1;
+  unsigned flag3:3;
+  signed remain:11;
+  unsigned whatsup:17;
+} vvv;
+
+int xyzzy(const char * qwe, int ijk)
+{
+  return strlen(qwe) + ijk;
+}
+
+unsigned int * xxx;
+unsigned int * yyy;
+
+int xxx3[10];
+
+char vdv[100];
+
+struct deferred_debug_info
+{
+	struct deferred_debug_info	* next;
+	char				* load_addr;
+	char				* module_name;
+	char				* dbg_info;
+	int				  dbg_size;
+	struct PE_Debug_dir		* dbgdir;
+	struct pe_data			* pe;
+        struct pe_segment_table         * sectp;
+	int				  nsect;
+	short int			  dbg_index;			
+	char				  loaded;
+};
+
+struct CodeViewDebug
+{
+	char		    cv_nbtype[8];
+	unsigned int	    cv_timestamp;
+	char		    cv_unknown[4];
+	char		    cv_name[1];
+};
+
+test_pdbstuff()
+{
+  struct deferred_debug_info deefer;
+  struct PE_Debug_dir	dinfo;
+  struct CodeViewDebug cdebug;
+  struct pe_segment_table sects[10];
+
+  memset(&deefer, 0, sizeof(deefer));
+  memset(&dinfo, 0, sizeof(dinfo));
+  memset(&cdebug, 0, sizeof(cdebug));
+  memset(&sects, 0, sizeof(sects));
+
+  deefer.dbg_info = (char *) &cdebug;
+  dinfo.timestamp = 812932395;
+  cdebug.cv_timestamp = 833392137  /* 841951397 */;
+  deefer.dbgdir = &dinfo;
+  deefer.sectp = &sects;
+  deefer.nsect = 10;
+
+  DEBUG_InitTypes();
+  DEBUG_ProcessPDBFile(&deefer, "../dumpexe.pdb");
+}
+
+int
+main(int argc, char * argv[])
+{
+  extern char * DEBUG_argv0;
+  SIGCONTEXT  reg;
+  
+  strcpy(vdv, "This is a test");
+  memset(&vvv, 0xff, sizeof(vvv));
+  vvv.whatsup = 0;
+  vvv.flag3 = 0;
+  vvv.remain = 0x401;
+  DEBUG_argv0 = argv[0];
+  xxx = (unsigned int*) &vvv;
+  yyy = xxx + 5;
+  xxx3[5] = 7;
+
+  test_pdbstuff();
+
+  memset(&reg, 0, sizeof(reg));
+  wine_debug(SIGSEGV, &reg);
+  return 0;
+}
diff --git a/debugger/debug.l b/debugger/debug.l
index 1fc3770..5f6cce2 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -34,11 +34,23 @@
 DIGIT	   [0-9]
 HEXDIGIT   [0-9a-fA-F]
 FORMAT     [bcdiswx]
-IDENTIFIER [_a-zA-Z\.~][_a-zA-Z0-9\.~@]*
+IDENTIFIER [_a-zA-Z~][_a-zA-Z0-9~@]*
+PATHNAME   [/_a-zA-Z\.~][/_a-zA-Z0-9\.~@]*
+STRING     \"[^\n"]+\"
+
+%s FORMAT_EXPECTED
+%s PATH_EXPECTED
+%s INFO_CMD
+%s HELP_CMD
+%s DEL_CMD
+%s WALK_CMD
+%s SHOW_CMD
+%s NOCMD
 
 %%
 
-\n		{ syntax_error = 0; return tEOL; } /*Indicates end of command*/
+\n		{ BEGIN(0); syntax_error = 0; 
+		  return tEOL; } /*Indicates end of command.  Reset state. */
 
 "||"		{ return OP_LOR; }
 "&&"		{ return OP_LAND; }
@@ -48,16 +60,24 @@
 ">="		{ return OP_GE; }
 "<<"		{ return OP_SHL; }
 ">>"		{ return OP_SHR; }
-[-+<=>|&^()*/%:!~]	{ return *yytext; }
+"->"		{ return OP_DRF; }
+[-+<=>|&^()*/%:!~,\.]	{ return *yytext; }
+"["		{ return *yytext; }
+"]"		{ return *yytext; }
 
 "0x"{HEXDIGIT}+      { sscanf(yytext, "%x", &yylval.integer); return tNUM; }
 {DIGIT}+             { sscanf(yytext, "%d", &yylval.integer); return tNUM; }
 
-"/"{DIGIT}+{FORMAT}  { char * last;
+
+<FORMAT_EXPECTED>"/"{DIGIT}+{FORMAT}  { char * last;
                        yylval.integer = strtol( yytext+1, &last, NULL );
                        yylval.integer = (yylval.integer << 8) | *last;
                        return tFORMAT; }
-"/"{FORMAT}          { yylval.integer = (1 << 8) | yytext[1]; return tFORMAT; }
+
+
+<FORMAT_EXPECTED>"/"{FORMAT}          { yylval.integer = (1 << 8) | yytext[1]; return tFORMAT; }
+
+{STRING} { yylval.string = make_symbol(yytext); return tSTRING; }
 
 $pc     { yylval.reg = REG_EIP; return tREG; }
 $flags  { yylval.reg = REG_EFL; return tREG; }
@@ -86,49 +106,60 @@
 $fs     { yylval.reg = REG_FS;  return tREG; }
 $gs     { yylval.reg = REG_GS;  return tREG; }
 
-up				{ return tUP; }
-down|dow|do			{ return tDOWN; }
-frame|fram|fra|fr		{ return tFRAME; }
-locals|local|loca|loc		{ return tLOCAL; }
-info|inf|in			{ return tINFO; }
-show|sho|sh			{ return tINFO; }
-list|lis|li|l			{ return tLIST; }
-break|brea|bre|br|b		{ return tBREAK; }
-enable|enabl|enab|ena		{ return tENABLE;}
-disable|disabl|disab|disa|dis	{ return tDISABLE; }
-delete|delet|dele|del		{ return tDELETE; }
-quit|qui|qu|q			{ return tQUIT; }
-set|se				{ return tSET; }
-walk|w				{ return tWALK; }
-x				{ return tEXAM; }
+<INITIAL>info|inf|in			{ BEGIN(INFO_CMD); return tINFO; }
+<INITIAL>up				{ BEGIN(NOCMD); return tUP; }
+<INITIAL>down|dow|do			{ BEGIN(NOCMD); return tDOWN; }
+<INITIAL>frame|fram|fra|fr		{ BEGIN(NOCMD); return tFRAME; }
+<INITIAL>list|lis|li|l			{ BEGIN(PATH_EXPECTED); return tLIST; }
+<INITIAL>enable|enabl|enab|ena		{ BEGIN(NOCMD); return tENABLE;}
+<INITIAL>disable|disabl|disab|disa|dis	{ BEGIN(NOCMD); return tDISABLE; }
+<INITIAL,INFO_CMD,DEL_CMD>display|displa|displ|disp	{ BEGIN(NOCMD); return tDISPLAY; }
+<INITIAL>undisplay|undispla|undispl|undisp|undis|undi|und	{ BEGIN(NOCMD); return tUNDISPLAY; }
+<INITIAL>delete|delet|dele|del		{ BEGIN(DEL_CMD); return tDELETE; }
+<INITIAL>quit|qui|qu|q			{ BEGIN(NOCMD); return tQUIT; }
+<INITIAL>set|se				{ BEGIN(NOCMD); return tSET; }
+<INITIAL>walk|w				{ BEGIN(WALK_CMD); return tWALK; }
+<INITIAL>x				{ BEGIN(FORMAT_EXPECTED); return tEXAM; }
+<INITIAL>help|hel|he|"?"		{ BEGIN(HELP_CMD); return tHELP; }
 
-class|clas|cla                  { return tCLASS; }
-module|modul|modu|mod           { return tMODULE; }
-queue|queu|que			{ return tQUEUE; }
-registers|regs|reg|re		{ return tREGS; }
-segments|segment|segm|seg|se	{ return tSEGMENTS; }
-stack|stac|sta|st     		{ return tSTACK; }
-window|windo|wind|win|wnd	{ return tWND; }
+<INITIAL>backtrace|backtrac|backtra|backt|back|bac|ba|bt { BEGIN(NOCMD); return tBACKTRACE; }
+<INITIAL>where|wher|whe                  { BEGIN(NOCMD); return tBACKTRACE; }
 
-help|hel|he|"?"			{ return tHELP; }
+<INITIAL>cont|con|co|c   		{ BEGIN(NOCMD); return tCONT; }
+<INITIAL>condition|conditio|conditi|condit|condi|cond	{ BEGIN(NOCMD); return tCOND; }
+<INITIAL>step|ste|st|s   		{ BEGIN(NOCMD); return tSTEP; }
+<INITIAL>next|nex|ne|n   		{ BEGIN(NOCMD); return tNEXT; }
+<INITIAL>stepi|si	   		{ BEGIN(NOCMD); return tSTEPI; }
+<INITIAL>nexti|ni	   		{ BEGIN(NOCMD); return tNEXTI; }
+<INITIAL>finish|finis|fini|fin|fi	{ BEGIN(NOCMD); return tFINISH; }
 
-backtrace|backtrac|backtra|backt|back|bac|ba|bt { return tBACKTRACE; }
-where|wher|whe                  { return tBACKTRACE; }
+<INITIAL>abort|abor|abo         	{ BEGIN(NOCMD); return tABORT; }
+<INITIAL>print|prin|pri|pr|p		{ BEGIN(FORMAT_EXPECTED); return tPRINT; }
 
-cont|con|co|c   		{ return tCONT; }
-step|ste|st|s   		{ return tSTEP; }
-next|nex|ne|n   		{ return tNEXT; }
+<INITIAL>mode				{ BEGIN(NOCMD); return tMODE; }
+<INITIAL>show|sho|sh			{ BEGIN(SHOW_CMD); return tSHOW; }
 
-symbolfile|symbolfil|symbolfi|symbolf|symbol|symbo|symb { return tSYMBOLFILE; }
+<INFO_CMD,INITIAL>break|brea|bre|br|b	{ BEGIN(PATH_EXPECTED); return tBREAK; }
 
-define|defin|defi|def|de        { return tDEFINE; }
-abort|abor|abo         	        { return tABORT; }
-print|prin|pri|pr|p		{ return tPRINT; }
+<INFO_CMD>share|shar|sha		{ return tSHARE; }
+<INFO_CMD>locals|local|loca|loc		{ return tLOCAL; }
+<INFO_CMD,WALK_CMD>class|clas|cla                  { return tCLASS; }
+<INFO_CMD,WALK_CMD>module|modul|modu|mod  { return tMODULE; }
+<INFO_CMD,WALK_CMD>queue|queu|que			{ return tQUEUE; }
+<INFO_CMD>registers|regs|reg|re		{ return tREGS; }
+<INFO_CMD>segments|segment|segm|seg|se	{ return tSEGMENTS; }
+<INFO_CMD>stack|stac|sta|st     		{ return tSTACK; }
+<INFO_CMD,WALK_CMD>window|windo|wind|win|wnd	{ return tWND; }
+<HELP_CMD>info|inf|in                   { return tINFO; }
 
-mode				{ return tMODE; }
+<INITIAL,SHOW_CMD>directories|directorie|directori|director|directo|direct|direc|direc|dir { 
+			BEGIN(PATH_EXPECTED); return tDIR; }
 
 {IDENTIFIER}	{ yylval.string = make_symbol(yytext); return tIDENTIFIER; }
 
+<PATH_EXPECTED>{PATHNAME}	{ yylval.string = make_symbol(yytext); return tPATH; }
+
+
 [ \t]+        /* Eat up whitespace */
 
 .		{ if (syntax_error == 0)
@@ -137,6 +168,7 @@
                   }
 		}
 
+
 %%
 
 #ifndef yywrap
@@ -217,7 +249,7 @@
     }
 }
 
-static char *local_symbols[10];
+static char *local_symbols[30];
 static int next_symbol;
 
 char * make_symbol(char * symbol){
diff --git a/debugger/display.c b/debugger/display.c
new file mode 100644
index 0000000..b170026
--- /dev/null
+++ b/debugger/display.c
@@ -0,0 +1,127 @@
+/*
+ * File display.c - display handling for Wine internal debugger.
+ *
+ * Copyright (C) 1997, Eric Youngdale.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <neexe.h>
+#include "module.h"
+#include "selectors.h"
+#include "debugger.h"
+#include "toolhelp.h"
+#include "xmalloc.h"
+
+#include <stdarg.h>
+
+#define MAX_DISPLAY 25
+static struct expr * displaypoints[MAX_DISPLAY];
+
+int
+DEBUG_AddDisplay(struct expr * exp)
+{
+  int i;
+
+  /*
+   * First find a slot where we can store this display.
+   */
+  for(i=0; i < MAX_DISPLAY; i++ )
+    {
+      if( displaypoints[i] == NULL )
+	{
+	  displaypoints[i] = DEBUG_CloneExpr(exp);
+	  break;
+	}
+    }
+
+  return TRUE;
+}
+
+int
+DEBUG_InfoDisplay()
+{
+  int i;
+
+  /*
+   * First find a slot where we can store this display.
+   */
+  for(i=0; i < MAX_DISPLAY; i++ )
+    {
+      if( displaypoints[i] != NULL )
+	{
+	  fprintf(stderr, "%d : ", i+1);
+	  DEBUG_DisplayExpr(displaypoints[i]);
+	  fprintf(stderr, "\n");
+	}
+    }
+
+  return TRUE;
+}
+
+int
+DEBUG_DoDisplay()
+{
+  DBG_ADDR	addr;
+  int i;
+
+  /*
+   * First find a slot where we can store this display.
+   */
+  for(i=0; i < MAX_DISPLAY; i++ )
+    {
+      if( displaypoints[i] != NULL )
+	{
+	  addr = DEBUG_EvalExpr(displaypoints[i]);
+	  if( addr.type == NULL )
+	    {
+	      fprintf(stderr, "Unable to evaluate expression ");
+	      DEBUG_DisplayExpr(displaypoints[i]);
+	      fprintf(stderr, "\nDisabling...\n");
+	      DEBUG_DelDisplay(i);
+	    }
+	  else
+	    {
+	      fprintf(stderr, "%d  : ", i + 1);
+	      DEBUG_DisplayExpr(displaypoints[i]);
+	      fprintf(stderr, " = ");
+	      DEBUG_Print( &addr, 1, 0, 0);
+	    }
+	}
+    }
+
+  return TRUE;
+}
+
+int
+DEBUG_DelDisplay(int displaynum)
+{
+  int i;
+  
+  if( displaynum >= MAX_DISPLAY || displaynum == 0 || displaynum < -1 )
+    {
+      fprintf(stderr, "Invalid display number\n");
+      return TRUE;
+    }
+  if( displaynum == -1 )
+    {
+      for(i=0; i < MAX_DISPLAY; i++ )
+	{
+	  if( displaypoints[i] != NULL )
+	    {
+	      DEBUG_FreeExpr(displaypoints[i]);
+	      displaypoints[i] = NULL;
+	    }
+	}
+    }
+  else if( displaypoints[displaynum - 1] != NULL )
+    {
+      DEBUG_FreeExpr(displaypoints[displaynum - 1]);
+      displaypoints[displaynum - 1] = NULL;
+    }
+  return TRUE;
+}
diff --git a/debugger/expr.c b/debugger/expr.c
new file mode 100644
index 0000000..4bf78ef
--- /dev/null
+++ b/debugger/expr.c
@@ -0,0 +1,878 @@
+/*
+ * File expr.c - expression handling for Wine internal debugger.
+ *
+ * Copyright (C) 1997, Eric Youngdale.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <neexe.h>
+#include "module.h"
+#include "selectors.h"
+#include "debugger.h"
+#include "toolhelp.h"
+#include "xmalloc.h"
+
+#include "expr.h"
+
+#include <stdarg.h>
+
+struct expr
+{
+  unsigned int	perm;
+  unsigned int	type:31;
+  union
+  {
+    struct
+    {
+      int value;
+    } constant;
+
+    struct
+    {
+      const char * str;
+    } string;
+
+    struct
+    {
+      unsigned int value;
+    } u_const;
+
+    struct
+    {
+      const char * name;
+    } symbol;
+
+    struct
+    {
+      enum debug_regs reg;
+      int	      result;
+    } rgister;
+
+    struct
+    {
+      int unop_type;
+      struct expr * exp1;
+      int	      result;
+    } unop;
+
+    struct
+    {
+      int binop_type;
+      int result;
+      struct expr * exp1;
+      struct expr * exp2;
+    } binop;
+
+    struct
+    {
+      struct expr * exp1;
+      const char * element_name;
+      int result;
+    } structure;
+
+    struct
+    {
+      struct expr * base;
+      struct expr * index;
+    } array;
+
+    struct
+    {
+      const char  * funcname;
+      int	    nargs;
+      int	    result;
+      struct expr * arg[5];
+    } call;
+
+  } un;
+};
+
+#define EXPR_TYPE_CONST		0
+#define EXPR_TYPE_US_CONST	1
+#define EXPR_TYPE_SYMBOL	2
+#define EXPR_TYPE_REGISTER	3
+#define EXPR_TYPE_BINOP		4
+#define EXPR_TYPE_UNOP		5
+#define EXPR_TYPE_STRUCT	6
+#define EXPR_TYPE_PSTRUCT	7
+#define EXPR_TYPE_ARRAY		8
+#define EXPR_TYPE_CALL		9
+#define EXPR_TYPE_STRING	10
+
+static char expr_list[4096];
+static int next_expr_free = 0;
+
+/*
+ * This is how we turn an expression address into the actual value.
+ * This works well in the 32 bit domain - not sure at all about the
+ * 16 bit world.
+ */
+#define VAL(_exp)	DEBUG_GetExprValue(&_exp, NULL)
+
+static
+struct expr *
+DEBUG_GetFreeExpr()
+{
+  struct expr * rtn;
+
+  rtn =  (struct expr *) &expr_list[next_expr_free];
+
+  next_expr_free += sizeof(struct expr);
+  return rtn;
+}
+
+void
+DEBUG_FreeExprMem()
+{
+  next_expr_free = 0;
+}
+
+
+struct expr *
+DEBUG_RegisterExpr(enum debug_regs regno)
+{
+  struct expr * ex;
+
+  ex = DEBUG_GetFreeExpr();
+
+  ex->type        = EXPR_TYPE_REGISTER;
+  ex->un.rgister.reg = regno;
+  return ex;
+}
+
+struct expr *
+DEBUG_SymbolExpr(const char * name)
+{
+  struct expr * ex;
+
+  ex = DEBUG_GetFreeExpr();
+
+  ex->type        = EXPR_TYPE_SYMBOL;
+  ex->un.symbol.name = name;
+  return ex;
+}
+
+struct expr *
+DEBUG_ConstExpr(int value)
+{
+  struct expr * ex;
+
+  ex = DEBUG_GetFreeExpr();
+
+  ex->type        = EXPR_TYPE_CONST;
+  ex->un.constant.value = value;
+  return ex;
+}
+
+struct expr *
+DEBUG_StringExpr(const char * str)
+{
+  struct expr * ex;
+  char * pnt;
+  ex = DEBUG_GetFreeExpr();
+
+  ex->type        = EXPR_TYPE_STRING;
+  ex->un.string.str = str+1;
+  pnt = strrchr(ex->un.string.str, '"');
+  if( pnt != NULL )
+    {
+      *pnt =  '\0';
+    }
+  return ex;
+}
+
+struct expr *
+DEBUG_USConstExpr(unsigned int value)
+{
+  struct expr * ex;
+
+  ex = DEBUG_GetFreeExpr();
+
+  ex->type           = EXPR_TYPE_CONST;
+  ex->un.u_const.value = value;
+  return ex;
+}
+
+struct expr *
+DEBUG_BinopExpr(int operator_type, struct expr * exp1, struct expr * exp2)
+{
+  struct expr * ex;
+
+  ex = DEBUG_GetFreeExpr();
+
+  ex->type           = EXPR_TYPE_BINOP;
+  ex->un.binop.binop_type = operator_type;
+  ex->un.binop.exp1     = exp1;
+  ex->un.binop.exp2     = exp2;
+  return ex;
+}
+
+struct expr *
+DEBUG_UnopExpr(int operator_type, struct expr * exp1)
+{
+  struct expr * ex;
+
+  ex = DEBUG_GetFreeExpr();
+
+  ex->type           = EXPR_TYPE_UNOP;
+  ex->un.unop.unop_type = operator_type;
+  ex->un.unop.exp1      = exp1;
+  return ex;
+}
+
+struct expr *
+DEBUG_StructExpr(struct expr * exp, const char * element)
+{
+  struct expr * ex;
+
+  ex = DEBUG_GetFreeExpr();
+
+  ex->type           = EXPR_TYPE_STRUCT;
+  ex->un.structure.exp1 = exp;
+  ex->un.structure.element_name = element;
+  return ex;
+}
+
+struct expr *
+DEBUG_StructPExpr(struct expr * exp, const char * element)
+{
+  struct expr * ex;
+
+  ex = DEBUG_GetFreeExpr();
+
+  ex->type           = EXPR_TYPE_PSTRUCT;
+  ex->un.structure.exp1 = exp;
+  ex->un.structure.element_name = element;
+  return ex;
+}
+
+struct expr *
+DEBUG_CallExpr(const char * funcname, int nargs, ...)
+{
+  struct expr * ex;
+  va_list ap;
+  int i;
+
+  ex = DEBUG_GetFreeExpr();
+
+  ex->type           = EXPR_TYPE_CALL;
+  ex->un.call.funcname = funcname;
+  ex->un.call.nargs = nargs;
+
+  va_start(ap, nargs);
+  for(i=0; i < nargs; i++)
+    {
+      ex->un.call.arg[i] = va_arg(ap, struct expr *);
+    }
+  va_end(ap);
+  return ex;
+}
+
+DBG_ADDR
+DEBUG_EvalExpr(struct expr * exp)
+{
+  DBG_ADDR	rtn;
+  int		i;
+  DBG_ADDR	exp1;
+  DBG_ADDR	exp2;
+  unsigned int	cexp[5];
+  int		(*fptr)();
+  int		    scale1;
+  int		    scale2;
+  int		    scale3;
+  struct datatype * type1;
+  struct datatype * type2;
+
+  rtn.type = NULL;
+  rtn.off = NULL;
+  rtn.seg = NULL;
+
+  switch(exp->type)
+    {
+    case EXPR_TYPE_STRING:
+      rtn.type = DEBUG_TypeString;
+      rtn.off = (unsigned int) &exp->un.string.str;
+      rtn.seg = 0;
+      break;
+    case EXPR_TYPE_CONST:
+      rtn.type = DEBUG_TypeIntConst;
+      rtn.off = (unsigned int) &exp->un.constant.value;
+      rtn.seg = 0;
+      break;
+    case EXPR_TYPE_US_CONST:
+      rtn.type = DEBUG_TypeUSInt;
+      rtn.off = (unsigned int) &exp->un.u_const.value;
+      rtn.seg = 0;
+      break;
+    case EXPR_TYPE_SYMBOL:
+      if( !DEBUG_GetSymbolValue(exp->un.symbol.name, -1, &rtn, FALSE ) )
+	{
+	  rtn.type = NULL;
+	  rtn.off = 0;
+	  rtn.seg = 0;
+	};
+      break;
+    case EXPR_TYPE_PSTRUCT:
+      exp1 =  DEBUG_EvalExpr(exp->un.structure.exp1);
+      if( exp1.type == NULL )
+	{
+	  break;
+	}
+      rtn.off = DEBUG_TypeDerefPointer(&exp1, &type1);
+      if( type1 == NULL )
+	{
+	  break;
+	}
+      rtn.type = type1;
+      DEBUG_FindStructElement(&rtn, exp->un.structure.element_name,
+			      &exp->un.structure.result);
+      break;
+    case EXPR_TYPE_STRUCT:
+      exp1 =  DEBUG_EvalExpr(exp->un.structure.exp1);
+      if( exp1.type == NULL )
+	{
+	  break;
+	}
+      rtn = exp1;
+      DEBUG_FindStructElement(&rtn, exp->un.structure.element_name,
+			      &exp->un.structure.result);
+      break;
+    case EXPR_TYPE_CALL:
+      /*
+       * First, evaluate all of the arguments.  If any of them are not
+       * evaluable, then bail.
+       */
+      for(i=0; i < exp->un.call.nargs; i++)
+	{
+	  exp1  = DEBUG_EvalExpr(exp->un.call.arg[i]);
+	  if( exp1.type == NULL )
+	    {
+	      return rtn;
+	    }
+	  cexp[i] = DEBUG_GetExprValue(&exp1, NULL);
+	}
+
+      /*
+       * Now look up the address of the function itself.
+       */
+      if( !DEBUG_GetSymbolValue(exp->un.call.funcname, -1, &rtn, FALSE ) )
+	{
+	  fprintf(stderr, "Failed to find symbol\n");
+	  break;
+	};
+
+      fptr = (int (*)()) rtn.off;
+      switch(exp->un.call.nargs)
+	{
+	case 0:
+	  exp->un.call.result = (*fptr)();
+	  break;
+	case 1:
+	  exp->un.call.result = (*fptr)(cexp[0]);
+	  break;
+	case 2:
+	  exp->un.call.result = (*fptr)(cexp[0], cexp[1]);
+	  break;
+	case 3:
+	  exp->un.call.result = (*fptr)(cexp[0], cexp[1], cexp[2]);
+	  break;
+	case 4:
+	  exp->un.call.result = (*fptr)(cexp[0], cexp[1], cexp[2], cexp[3]);
+	  break;
+	case 5:
+	  exp->un.call.result = (*fptr)(cexp[0], cexp[1], cexp[2], cexp[3], cexp[4]);
+	  break;
+	}
+      rtn.type = DEBUG_TypeInt;
+      rtn.off = (unsigned int) &exp->un.call.result;
+      break;
+    case EXPR_TYPE_REGISTER:
+      rtn.type = DEBUG_TypeIntConst;
+      exp->un.rgister.result = DEBUG_GetRegister(exp->un.rgister.reg);
+      rtn.off = (unsigned int) &exp->un.rgister.result;
+      rtn.seg = 0;
+      break;
+    case EXPR_TYPE_BINOP:
+      exp1 = DEBUG_EvalExpr(exp->un.binop.exp1);
+      exp2 = DEBUG_EvalExpr(exp->un.binop.exp2);
+      if( exp1.type == NULL || exp2.type == NULL )
+	{
+	  break;
+	}
+      if( exp1.type == DEBUG_TypeIntConst && exp2.type == DEBUG_TypeIntConst )
+	{
+	  rtn.type = exp1.type;
+	}
+      else
+	{
+	  rtn.type = DEBUG_TypeInt;
+	}
+      rtn.off = (unsigned int) &exp->un.binop.result;
+      switch(exp->un.binop.binop_type)
+	{
+	case EXP_OP_ADD:
+	  type1 = DEBUG_GetPointerType(exp1.type);
+	  type2 = DEBUG_GetPointerType(exp2.type);
+	  scale1 = 1;
+	  scale2 = 1;
+	  if( type1 != NULL && type2 != NULL )
+	    {
+	      break;
+	    }
+	  else if( type1 != NULL )
+	    {
+	      scale2 = DEBUG_GetObjectSize(type1);
+	      rtn.type = exp1.type;
+	    }
+	  else if( type2 != NULL )
+	    {
+	      scale1 = DEBUG_GetObjectSize(type2);
+	      rtn.type = exp2.type;
+	    }
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) * scale1  + scale2 * VAL(exp2));
+	  break;
+	case EXP_OP_SUB:
+	  type1 = DEBUG_GetPointerType(exp1.type);
+	  type2 = DEBUG_GetPointerType(exp2.type);
+	  scale1 = 1;
+	  scale2 = 1;
+	  scale3 = 1;
+	  if( type1 != NULL && type2 != NULL )
+	    {
+	      if( type1 != type2 )
+		{
+		  break;
+		}
+	      scale3 = DEBUG_GetObjectSize(type1);
+	    }
+	  else if( type1 != NULL )
+	    {
+	      scale2 = DEBUG_GetObjectSize(type1);
+	      rtn.type = exp1.type;
+	    }
+
+	  else if( type2 != NULL )
+	    {
+	      scale1 = DEBUG_GetObjectSize(type2);
+	      rtn.type = exp2.type;
+	    }
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) - VAL(exp2)) / scale3;
+	  break;
+	case EXP_OP_SEG:
+	  rtn.seg = VAL(exp1);
+          exp->un.binop.result = VAL(exp2);
+	  break;
+	case EXP_OP_LOR:
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) || VAL(exp2));
+	  break;
+	case EXP_OP_LAND:
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) && VAL(exp2));
+	  break;
+	case EXP_OP_OR:
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) | VAL(exp2));
+	  break;
+	case EXP_OP_AND:
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) & VAL(exp2));
+	  break;
+	case EXP_OP_XOR:
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) ^ VAL(exp2));
+ 	  break;
+	case EXP_OP_EQ:
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) == VAL(exp2));
+	  break;
+	case EXP_OP_GT:
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) > VAL(exp2));
+	  break;
+	case EXP_OP_LT:
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) < VAL(exp2));
+	  break;
+	case EXP_OP_GE:
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) >= VAL(exp2));
+	  break;
+	case EXP_OP_LE:
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) <= VAL(exp2));
+	  break;
+	case EXP_OP_NE:
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) != VAL(exp2));
+	  break;
+	case EXP_OP_SHL:
+	  rtn.seg = 0;
+	  exp->un.binop.result = ((unsigned) VAL(exp1) << VAL(exp2));
+	  break;
+	case EXP_OP_SHR:
+	  rtn.seg = 0;
+	  exp->un.binop.result = ((unsigned) VAL(exp1) << VAL(exp2));
+	  break;
+	case EXP_OP_MUL:
+	  rtn.seg = 0;
+	  exp->un.binop.result = (VAL(exp1) * VAL(exp2));
+	  break;
+	case EXP_OP_DIV:
+	  if( VAL(exp2) != 0 )
+	    {
+	      rtn.seg = 0;
+	      exp->un.binop.result = (VAL(exp1) / VAL(exp2));
+	    }
+	  else
+	    {
+	      rtn.seg = 0;
+	      rtn.type = NULL;
+	      rtn.off = 0;
+	    }
+	  break;
+	case EXP_OP_REM:
+	  if( VAL(exp2) != 0 )
+	    {
+	      rtn.seg = 0;
+	      exp->un.binop.result = (VAL(exp1) % VAL(exp2));
+	    }
+	  else
+	    {
+	      rtn.seg = 0;
+	      rtn.type = NULL;
+	      rtn.off = 0;
+	    }
+	  break;
+	case EXP_OP_ARR:
+	  DEBUG_ArrayIndex(&exp1, &rtn, VAL(exp2));
+	  break;
+	default:
+	  break;
+	}
+      break;
+    case EXPR_TYPE_UNOP:
+      exp1 = DEBUG_EvalExpr(exp->un.unop.exp1);
+      if( exp1.type == NULL )
+	{
+	  break;
+	}
+      rtn.off = (unsigned int) &exp->un.unop.result;
+      if( exp1.type == DEBUG_TypeIntConst )
+	{
+	  rtn.type = exp1.type;
+	}
+      else
+	{
+	  rtn.type = DEBUG_TypeInt;
+	}
+      switch(exp->un.binop.binop_type)
+	{
+	case EXP_OP_NEG:
+	  rtn.seg = 0;
+	  exp->un.unop.result = -VAL(exp1);
+	  break;
+	case EXP_OP_NOT:
+	  rtn.seg = 0;
+	  exp->un.unop.result = !VAL(exp1);
+	  break;
+	case EXP_OP_LNOT:
+	  rtn.seg = 0;
+	  exp->un.unop.result = ~VAL(exp1);
+	  break;
+	case EXP_OP_DEREF:
+	  rtn.seg = 0;
+	  rtn.off = (unsigned int) DEBUG_TypeDerefPointer(&exp1, &rtn.type);
+	  break;
+	case EXP_OP_FORCE_DEREF:
+	  rtn.seg = 0;
+	  rtn.off = *(unsigned int *) exp1.off;
+	  break;
+	case EXP_OP_ADDR:
+	  rtn.seg = 0;
+	  rtn.type = DEBUG_FindOrMakePointerType(exp1.type);
+	  exp->un.unop.result = exp1.off;
+	  break;
+	}
+      break;
+    default:
+      fprintf(stderr,"Unexpected expression.\n");
+      exit(123);
+      break;
+    }
+
+  return rtn;
+}
+
+
+int
+DEBUG_DisplayExpr(struct expr * exp)
+{
+  int		i;
+
+
+  switch(exp->type)
+    {
+    case EXPR_TYPE_REGISTER:
+      DEBUG_PrintRegister(exp->un.rgister.reg);
+      break;
+    case EXPR_TYPE_US_CONST:
+      fprintf(stderr, "%ud", exp->un.u_const.value);
+      break;
+    case EXPR_TYPE_CONST:
+      fprintf(stderr, "%d", exp->un.u_const.value);
+      break;
+    case EXPR_TYPE_STRING:
+      fprintf(stderr, "\"%s\"", exp->un.string.str);
+      break;
+    case EXPR_TYPE_SYMBOL:
+      fprintf(stderr, "%s" , exp->un.symbol.name);
+      break;
+    case EXPR_TYPE_PSTRUCT:
+      DEBUG_DisplayExpr(exp->un.structure.exp1);
+      fprintf(stderr, "->%s", exp->un.structure.element_name);
+      break;
+    case EXPR_TYPE_STRUCT:
+      DEBUG_DisplayExpr(exp->un.structure.exp1);
+      fprintf(stderr, ".%s", exp->un.structure.element_name);
+      break;
+    case EXPR_TYPE_CALL:
+      /*
+       * First, evaluate all of the arguments.  If any of them are not
+       * evaluable, then bail.
+       */
+      fprintf(stderr, "%s(",exp->un.call.funcname);
+      for(i=0; i < exp->un.call.nargs; i++)
+	{
+	  DEBUG_DisplayExpr(exp->un.call.arg[i]);
+	  if( i != exp->un.call.nargs - 1 )
+	    {
+	      fprintf(stderr, ", ");
+	    }
+	}
+      fprintf(stderr, ")");
+      break;
+    case EXPR_TYPE_BINOP:
+      fprintf(stderr, "( ");
+      DEBUG_DisplayExpr(exp->un.binop.exp1);
+      switch(exp->un.binop.binop_type)
+	{
+	case EXP_OP_ADD:
+ 	  fprintf(stderr, " + ");
+	  break;
+	case EXP_OP_SUB:
+ 	  fprintf(stderr, " - ");
+	  break;
+	case EXP_OP_SEG:
+ 	  fprintf(stderr, ":");
+	  break;
+	case EXP_OP_LOR:
+ 	  fprintf(stderr, " || ");
+	  break;
+	case EXP_OP_LAND:
+ 	  fprintf(stderr, " && ");
+	  break;
+	case EXP_OP_OR:
+ 	  fprintf(stderr, " | ");
+	  break;
+	case EXP_OP_AND:
+ 	  fprintf(stderr, " & ");
+	  break;
+	case EXP_OP_XOR:
+ 	  fprintf(stderr, " ^ ");
+ 	  break;
+	case EXP_OP_EQ:
+ 	  fprintf(stderr, " == ");
+	  break;
+	case EXP_OP_GT:
+ 	  fprintf(stderr, " > ");
+	  break;
+	case EXP_OP_LT:
+ 	  fprintf(stderr, " < ");
+	  break;
+	case EXP_OP_GE:
+ 	  fprintf(stderr, " >= ");
+	  break;
+	case EXP_OP_LE:
+ 	  fprintf(stderr, " <= ");
+	  break;
+	case EXP_OP_NE:
+ 	  fprintf(stderr, " != ");
+	  break;
+	case EXP_OP_SHL:
+ 	  fprintf(stderr, " << ");
+	  break;
+	case EXP_OP_SHR:
+ 	  fprintf(stderr, " >> ");
+	  break;
+	case EXP_OP_MUL:
+ 	  fprintf(stderr, " * ");
+	  break;
+	case EXP_OP_DIV:
+ 	  fprintf(stderr, " / ");
+	  break;
+	case EXP_OP_REM:
+ 	  fprintf(stderr, " %% ");
+	  break;
+	case EXP_OP_ARR:
+ 	  fprintf(stderr, "[");
+	  break;
+	default:
+	  break;
+	}
+      DEBUG_DisplayExpr(exp->un.binop.exp2);
+      if( exp->un.binop.binop_type == EXP_OP_ARR )
+	{
+ 	  fprintf(stderr, "]");
+	}
+      fprintf(stderr, " )");
+      break;
+    case EXPR_TYPE_UNOP:
+      switch(exp->un.binop.binop_type)
+	{
+	case EXP_OP_NEG:
+ 	  fprintf(stderr, "-");
+	  break;
+	case EXP_OP_NOT:
+	  fprintf(stderr, "!");
+	  break;
+	case EXP_OP_LNOT:
+	  fprintf(stderr, "~");
+ 	  break;
+	case EXP_OP_DEREF:
+	  fprintf(stderr, "*");
+	  break;
+	case EXP_OP_ADDR:
+	  fprintf(stderr, "&");
+	  break;
+	}
+      DEBUG_DisplayExpr(exp->un.unop.exp1);
+      break;
+    default:
+      fprintf(stderr,"Unexpected expression.\n");
+      exit(123);
+      break;
+    }
+
+  return TRUE;
+}
+
+struct expr *
+DEBUG_CloneExpr(struct expr * exp)
+{
+  int		i;
+  struct expr * rtn;
+
+  rtn = (struct expr *) xmalloc(sizeof(struct expr));
+
+  /*
+   * First copy the contents of the expression itself.
+   */
+  *rtn = *exp;
+
+
+  switch(exp->type)
+    {
+    case EXPR_TYPE_REGISTER:
+    case EXPR_TYPE_US_CONST:
+    case EXPR_TYPE_CONST:
+      break;
+    case EXPR_TYPE_STRING:
+      rtn->un.string.str = xstrdup(exp->un.string.str);
+      break;
+    case EXPR_TYPE_SYMBOL:
+      rtn->un.symbol.name = xstrdup(exp->un.symbol.name);
+      break;
+    case EXPR_TYPE_PSTRUCT:
+    case EXPR_TYPE_STRUCT:
+      rtn->un.structure.exp1 = DEBUG_CloneExpr(exp->un.structure.exp1);
+      rtn->un.structure.element_name = xstrdup(exp->un.structure.element_name);
+      break;
+    case EXPR_TYPE_CALL:
+      /*
+       * First, evaluate all of the arguments.  If any of them are not
+       * evaluable, then bail.
+       */
+      for(i=0; i < exp->un.call.nargs; i++)
+	{
+	  rtn->un.call.arg[i]  = DEBUG_CloneExpr(exp->un.call.arg[i]);
+	}
+      rtn->un.call.funcname = xstrdup(exp->un.call.funcname);
+      break;
+    case EXPR_TYPE_BINOP:
+      rtn->un.binop.exp1 = DEBUG_CloneExpr(exp->un.binop.exp1);
+      rtn->un.binop.exp2 = DEBUG_CloneExpr(exp->un.binop.exp2);
+      break;
+    case EXPR_TYPE_UNOP:
+      rtn->un.unop.exp1 = DEBUG_CloneExpr(exp->un.unop.exp1);
+      break;
+    default:
+      fprintf(stderr,"Unexpected expression.\n");
+      exit(123);
+      break;
+    }
+
+  return rtn;
+}
+
+
+/*
+ * Recursively go through an expression tree and free all memory associated
+ * with it.
+ */
+int
+DEBUG_FreeExpr(struct expr * exp)
+{
+  int i;
+
+  switch(exp->type)
+    {
+    case EXPR_TYPE_REGISTER:
+    case EXPR_TYPE_US_CONST:
+    case EXPR_TYPE_CONST:
+      break;
+    case EXPR_TYPE_STRING:
+      free((char *) exp->un.string.str);
+      break;
+    case EXPR_TYPE_SYMBOL:
+      free((char *) exp->un.symbol.name);
+      break;
+    case EXPR_TYPE_PSTRUCT:
+    case EXPR_TYPE_STRUCT:
+      DEBUG_FreeExpr(exp->un.structure.exp1);
+      free((char *) exp->un.structure.element_name);
+      break;
+    case EXPR_TYPE_CALL:
+      /*
+       * First, evaluate all of the arguments.  If any of them are not
+       * evaluable, then bail.
+       */
+      for(i=0; i < exp->un.call.nargs; i++)
+	{
+	  DEBUG_FreeExpr(exp->un.call.arg[i]);
+	}
+      free((char *) exp->un.call.funcname);
+      break;
+    case EXPR_TYPE_BINOP:
+      DEBUG_FreeExpr(exp->un.binop.exp1);
+      DEBUG_FreeExpr(exp->un.binop.exp2);
+      break;
+    case EXPR_TYPE_UNOP:
+      DEBUG_FreeExpr(exp->un.unop.exp1);
+      break;
+    default:
+      fprintf(stderr,"Unexpected expression.\n");
+      exit(123);
+      break;
+    }
+
+  free(exp);
+  return TRUE;
+}
diff --git a/debugger/expr.h b/debugger/expr.h
new file mode 100644
index 0000000..c2d19bd
--- /dev/null
+++ b/debugger/expr.h
@@ -0,0 +1,26 @@
+#define EXP_OP_LOR		0x01
+#define EXP_OP_LAND		0x02
+#define EXP_OP_OR		0x03
+#define EXP_OP_AND		0x04
+#define EXP_OP_XOR		0x05
+#define EXP_OP_EQ		0x06
+#define EXP_OP_GT		0x07
+#define EXP_OP_LT		0x08
+#define EXP_OP_GE		0x09
+#define EXP_OP_LE		0x0a
+#define EXP_OP_NE		0x0b
+#define EXP_OP_SHL		0x0c
+#define EXP_OP_SHR		0x0d
+#define EXP_OP_ADD		0x0e
+#define EXP_OP_SUB		0x0f
+#define EXP_OP_MUL		0x10
+#define EXP_OP_DIV		0x11
+#define EXP_OP_REM		0x12
+#define EXP_OP_NEG		0x13
+#define EXP_OP_NOT		0x24
+#define EXP_OP_LNOT		0x25
+#define EXP_OP_DEREF		0x26
+#define EXP_OP_ADDR		0x27
+#define EXP_OP_ARR		0x28
+#define EXP_OP_SEG		0x29
+#define EXP_OP_FORCE_DEREF	0x2a
diff --git a/debugger/hash.c b/debugger/hash.c
index 0a9df01..2684ea0 100644
--- a/debugger/hash.c
+++ b/debugger/hash.c
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <limits.h>
 #include <sys/types.h>
 #include <neexe.h>
 #include "module.h"
@@ -16,21 +17,147 @@
 #include "toolhelp.h"
 #include "xmalloc.h"
 
-#define NR_NAME_HASH 128
+#define NR_NAME_HASH 16384
+
+static char * reg_name[] =
+{
+  "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
+};
+
+
+struct name_hash
+{
+    struct name_hash * next;		/* Used to look up within name hash */
+    char *             name;
+    char *             sourcefile;
+
+    int		       n_locals;
+    int		       locals_alloc;
+    WineLocals       * local_vars;
+  
+    int		       n_lines;
+    int		       lines_alloc;
+    WineLineNo       * linetab;
+
+    DBG_ADDR           addr;
+    unsigned short     flags;
+    unsigned short     breakpoint_offset;
+    unsigned int       symbol_size;
+};
+
+
+static BOOL32 DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr );
+static int sortlist_valid = FALSE;
+
+static int sorttab_nsym;
+static struct name_hash ** addr_sorttab = NULL;
 
 static struct name_hash * name_hash_table[NR_NAME_HASH];
 
 static unsigned int name_hash( const char * name )
 {
     unsigned int hash = 0;
+    unsigned int tmp;
     const char * p;
 
     p = name;
 
-    while (*p) hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++;
+    while (*p) 
+      {
+	hash = (hash << 4) + *p++;
+
+	if( (tmp = (hash & 0xf0000000)) )
+	  {
+	    hash ^= tmp >> 24;
+	  }
+	hash &= ~tmp;
+      }
     return hash % NR_NAME_HASH;
 }
 
+int
+DEBUG_cmp_sym(const void * p1, const void * p2)
+{
+  struct name_hash ** name1 = (struct name_hash **) p1;
+  struct name_hash ** name2 = (struct name_hash **) p2;
+
+  if( ((*name1)->flags & SYM_INVALID) != 0 )
+    {
+      return -1;
+    }
+
+  if( ((*name2)->flags & SYM_INVALID) != 0 )
+    {
+      return 1;
+    }
+
+  if( (*name1)->addr.seg > (*name2)->addr.seg )
+    {
+      return 1;
+    }
+
+  if( (*name1)->addr.seg < (*name2)->addr.seg )
+    {
+      return -1;
+    }
+
+  if( (*name1)->addr.off > (*name2)->addr.off )
+    {
+      return 1;
+    }
+
+  if( (*name1)->addr.off < (*name2)->addr.off )
+    {
+      return -1;
+    }
+
+  return 0;
+}
+
+/***********************************************************************
+ *           DEBUG_ResortSymbols
+ *
+ * Rebuild sorted list of symbols.
+ */
+static
+void
+DEBUG_ResortSymbols()
+{
+    struct name_hash *nh;
+    int		nsym = 0;
+    int		i;
+
+    for(i=0; i<NR_NAME_HASH; i++)
+    {
+        for (nh = name_hash_table[i]; nh; nh = nh->next)
+	  {
+	    nsym++;
+	  }
+    }
+
+    sorttab_nsym = nsym;
+    if( nsym == 0 )
+      {
+	return;
+      }
+
+    addr_sorttab = (struct name_hash **) xrealloc(addr_sorttab, 
+					 nsym * sizeof(struct name_hash *));
+
+    nsym = 0;
+    for(i=0; i<NR_NAME_HASH; i++)
+    {
+        for (nh = name_hash_table[i]; nh; nh = nh->next)
+	  {
+	    addr_sorttab[nsym++] = nh;
+	  }
+    }
+
+    qsort(addr_sorttab, nsym,
+	  sizeof(struct name_hash *), DEBUG_cmp_sym);
+    sortlist_valid = TRUE;
+
+}
 
 /***********************************************************************
  *           DEBUG_AddSymbol
@@ -38,42 +165,143 @@
  * Add a symbol to the table.
  */
 struct name_hash *
-DEBUG_AddSymbol( const char * name, const DBG_ADDR *addr, const char * source )
+DEBUG_AddSymbol( const char * name, const DBG_ADDR *addr, const char * source,
+		 int flags)
 {
     struct name_hash  * new;
+    struct name_hash *nh;
+    static char  prev_source[PATH_MAX] = {'\0', };
+    static char * prev_duped_source = NULL;
+    char * c;
     int hash;
 
+    hash = name_hash(name);
+    for (nh = name_hash_table[hash]; nh; nh = nh->next)
+    {
+ 	if( ((nh->flags & SYM_INVALID) != 0) && strcmp(name, nh->name) == 0 )
+        {
+ 	    nh->addr.off = addr->off;
+ 	    nh->addr.seg = addr->seg;
+ 	    if( nh->addr.type == NULL && addr->type != NULL )
+            {
+ 		nh->addr.type = addr->type;
+            }
+ 	    nh->flags &= ~SYM_INVALID;
+ 	    return nh;
+        }
+ 	if (nh->addr.seg == addr->seg &&
+ 	    nh->addr.off == addr->off &&
+ 	    strcmp(name, nh->name) == 0 )
+        {
+            return nh;
+        }
+    }
+
+    /*
+     * First see if we already have an entry for this symbol.  If so
+     * return it, so we don't end up with duplicates.
+     */
+    
     new = (struct name_hash *) xmalloc(sizeof(struct name_hash));
     new->addr = *addr;
     new->name = xstrdup(name);
 
     if( source != NULL )
       {
-	new->sourcefile = xstrdup(source);
+	/*
+	 * This is an enhancement to reduce memory consumption.  The idea
+	 * is that we duplicate a given string only once.  This is a big
+	 * win if there are lots of symbols defined in a given source file.
+	 */
+	if( strcmp(source, prev_source) == 0 )
+	  {
+	    new->sourcefile = prev_duped_source;
+	  }
+	else
+	  {
+	    strcpy(prev_source, source);
+	    prev_duped_source = new->sourcefile = xstrdup(source);
+	  }
       }
     else
       {
 	new->sourcefile = NULL;
       }
 
-    new->n_lines = 0;
-    new->lines_alloc = 0;
-    new->linetab = NULL;
+    new->n_lines	= 0;
+    new->lines_alloc	= 0;
+    new->linetab	= NULL;
 
-    new->n_locals = 0;
-    new->locals_alloc = 0;
-    new->local_vars = NULL;
+    new->n_locals	= 0;
+    new->locals_alloc	= 0;
+    new->local_vars	= NULL;
 
-    new->next = NULL;
-    hash = name_hash(name);
+    new->flags		= flags;
+    new->next		= NULL;
 
     /* Now insert into the hash table */
     new->next = name_hash_table[hash];
     name_hash_table[hash] = new;
 
+    /*
+     * Check some heuristics based upon the file name to see whether
+     * we want to step through this guy or not.  These are machine generated
+     * assembly files that are used to translate between the MS way of
+     * calling things and the GCC way of calling things.  In general we
+     * always want to step through.
+     */
+    if( source != NULL )
+      {
+	c = strrchr(source, '.');
+	if( c != NULL && strcmp(c, ".s") == 0 )
+	  {
+	    c = strrchr(source, '/');
+	    if( c != NULL )
+	      {
+		c++;
+		if(    (strcmp(c, "callfrom16.s") == 0)
+		    || (strcmp(c, "callto16.s") == 0)
+		    || (strcmp(c, "callfrom32.s") == 0)
+		    || (strcmp(c, "callto32.s") == 0) )
+		  {
+		    new->flags |= SYM_TRAMPOLINE;
+		  }
+	      }
+	  }
+      }
+
+    sortlist_valid = FALSE;
     return new;
 }
 
+BOOL32 DEBUG_Normalize(struct name_hash * nh )
+{
+
+  /*
+   * We aren't adding any more locals or linenumbers to this function.
+   * Free any spare memory that we might have allocated.
+   */
+  if( nh == NULL )
+    {
+      return TRUE;
+    }
+
+  if( nh->n_locals != nh->locals_alloc )
+    {
+      nh->locals_alloc = nh->n_locals;
+      nh->local_vars = xrealloc(nh->local_vars,
+				  nh->locals_alloc * sizeof(WineLocals));
+    }
+
+  if( nh->n_lines != nh->lines_alloc )
+    {
+      nh->lines_alloc = nh->n_lines;
+      nh->linetab = xrealloc(nh->linetab,
+			      nh->lines_alloc * sizeof(WineLineNo));
+    }
+
+  return TRUE;
+}
 
 /***********************************************************************
  *           DEBUG_GetSymbolValue
@@ -81,21 +309,33 @@
  * Get the address of a named symbol.
  */
 BOOL32 DEBUG_GetSymbolValue( const char * name, const int lineno, 
-			     DBG_ADDR *addr )
+			     DBG_ADDR *addr, int bp_flag )
 {
     char buffer[256];
-    int i;
     struct name_hash *nh;
 
     for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
+      {
+	if( (nh->flags & SYM_INVALID) != 0 )
+	  {
+	    continue;
+	  }
+
         if (!strcmp(nh->name, name)) break;
+      }
 
     if (!nh && (name[0] != '_'))
     {
         buffer[0] = '_';
         strcpy(buffer+1, name);
         for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
+	  {
+	    if( (nh->flags & SYM_INVALID) != 0 )
+	      {
+		continue;
+	      }
             if (!strcmp(nh->name, buffer)) break;
+	  }
     }
 
     /*
@@ -104,12 +344,31 @@
      * what, we have nothing more to do, so we let that function
      * decide what we ultimately return.
      */
-    if (!nh) return DEBUG_GetStackSymbolValue(name, addr);
+    if (!nh) 
+      {
+	return DEBUG_GetStackSymbolValue(name, addr);
+      }
 
+    return DEBUG_GetLineNumberAddr( nh, lineno, addr, bp_flag );
+}
+
+/***********************************************************************
+ *           DEBUG_GetLineNumberAddr
+ *
+ * Get the address of a named symbol.
+ */
+BOOL32 DEBUG_GetLineNumberAddr( struct name_hash * nh, const int lineno, 
+				DBG_ADDR *addr, int bp_flag )
+{
+    int i;
 
     if( lineno == -1 )
       {
 	*addr = nh->addr;
+	if( bp_flag )
+	  {
+	    addr->off += nh->breakpoint_offset;
+	  }
       }
     else
       {
@@ -164,6 +423,7 @@
 
     if (!nh) return FALSE;
     nh->addr = *addr;
+    nh->flags &= SYM_INVALID;
     DBG_FIX_ADDR_SEG( &nh->addr, DS_reg(&DEBUG_context) );
     return TRUE;
 }
@@ -178,39 +438,156 @@
  */
 const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag,
 				      struct name_hash ** rtn,
-				      unsigned int ebp)
+				      unsigned int ebp,
+				      struct list_id * source)
 {
     static char name_buffer[MAX_PATH + 256];
     static char arglist[1024];
     static char argtmp[256];
     struct name_hash * nearest = NULL;
-    struct name_hash * nh;
-    unsigned int nearest_address = 0;
+    int mid, high, low;
     unsigned	int * ptr;
     int lineno;
     char * lineinfo, *sourcefile;
     int i;
     char linebuff[16];
 
-    *rtn = NULL;
+    if( rtn != NULL )
+      {
+	*rtn = NULL;
+      }
 
-    for(i=0; i<NR_NAME_HASH; i++)
-    {
-        for (nh = name_hash_table[i]; nh; nh = nh->next)
-            if (nh->addr.seg == addr->seg &&
-                nh->addr.off <= addr->off &&
-                nh->addr.off >= nearest_address)
-            {
-                nearest_address = nh->addr.off;
-                nearest = nh;
-            }
-    }
+    if( source != NULL )
+      {
+ 	source->sourcefile = NULL;
+	source->line = -1;
+      }
+
+    if( sortlist_valid == FALSE )
+      {
+	DEBUG_ResortSymbols();
+      }
+
+    if( sortlist_valid == FALSE )
+      {
+	return NULL;
+      }
+
+    /*
+     * FIXME  - use the binary search that we added to
+     * the function DEBUG_CheckLinenoStatus.  Better yet, we should
+     * probably keep some notion of the current function so we don't
+     * have to search every time.
+     */
+    /*
+     * Binary search to find closest symbol.
+     */
+    low = 0;
+    high = sorttab_nsym;
+    if( addr_sorttab[0]->addr.seg > addr->seg
+	|| (   addr_sorttab[0]->addr.seg == addr->seg 
+	    && addr_sorttab[0]->addr.off > addr->off) )
+      {
+	nearest = NULL;
+      }
+    else if( addr_sorttab[high - 1]->addr.seg < addr->seg
+	|| (   addr_sorttab[high - 1]->addr.seg == addr->seg 
+	    && addr_sorttab[high - 1]->addr.off < addr->off) )
+      {
+	nearest = addr_sorttab[high - 1];
+      }
+    else
+      {
+	while(1==1)
+	  {
+	    mid = (high + low)/2;
+	    if( mid == low )
+	      {
+		/* 
+		 * See if there are any other entries that might also
+		 * have the same address, and would also have a line
+		 * number table.  
+		 */
+		if( mid > 0 && addr_sorttab[mid]->linetab == NULL )
+		  {
+		    if(    (addr_sorttab[mid - 1]->addr.seg ==
+			    addr_sorttab[mid]->addr.seg)
+			&& (addr_sorttab[mid - 1]->addr.off ==
+			    addr_sorttab[mid]->addr.off)
+		        && (addr_sorttab[mid - 1]->linetab != NULL) )
+		      {
+			mid--;
+		      }
+		  }
+
+		if(    (mid < sorttab_nsym - 1)
+		    && (addr_sorttab[mid]->linetab == NULL) )
+		  {
+		    if(    (addr_sorttab[mid + 1]->addr.seg ==
+			    addr_sorttab[mid]->addr.seg)
+			&& (addr_sorttab[mid + 1]->addr.off ==
+			    addr_sorttab[mid]->addr.off)
+		        && (addr_sorttab[mid + 1]->linetab != NULL) )
+		      {
+			mid++;
+		      }
+		  }
+		nearest = addr_sorttab[mid];
+#if 0
+		fprintf(stderr, "Found %x:%x when looking for %x:%x %x %s\n",
+			addr_sorttab[mid ]->addr.seg,
+			addr_sorttab[mid ]->addr.off,
+			addr->seg, addr->off,
+			addr_sorttab[mid ]->linetab,
+			addr_sorttab[mid ]->name);
+#endif
+		break;
+	      }
+	    if(    (addr_sorttab[mid]->addr.seg < addr->seg)
+		|| (   addr_sorttab[mid]->addr.seg == addr->seg 
+		    && addr_sorttab[mid]->addr.off <= addr->off) )
+	      {
+		low = mid;
+	      }
+	    else
+	      {
+		high = mid;
+	      }
+	  }
+      }
+
     if (!nearest) return NULL;
 
-    *rtn = nearest;
+    if( rtn != NULL )
+      {
+	*rtn = nearest;
+      }
+
+    /*
+     * Fill in the relevant bits to the structure so that we can
+     * locate the source and line for this bit of code.
+     */
+    if( source != NULL )
+      {
+	source->sourcefile = nearest->sourcefile;
+	if( nearest->linetab == NULL )
+	  {
+	    source->line = -1;
+	  }
+	else
+	  {
+	    source->line = nearest->linetab[0].line_number;
+	  }
+      }
+
     lineinfo = "";
     lineno = -1;
 
+    /*
+     * Prepare to display the argument list.  If ebp is specified, it is
+     * the framepointer for the function in question.  If not specified,
+     * we don't want the arglist.
+     */
     memset(arglist, '\0', sizeof(arglist));
     if( ebp != 0 )
       {
@@ -273,6 +650,10 @@
 	  {
 	    sprintf(linebuff, ":%d", lineno);
 	    lineinfo = linebuff;
+	    if( source != NULL )
+	      {
+		source->line = lineno;
+	      }
 	  }
 
         /* Remove the path from the file name */
@@ -343,7 +724,7 @@
         if (!(*cpnt) || *cpnt == '\n') continue;
 		
         nargs = sscanf(buffer, "%lx %c %s", &addr.off, &type, name);
-        DEBUG_AddSymbol( name, &addr, NULL );
+        DEBUG_AddSymbol( name, &addr, NULL, SYM_WINE );
     }
     fclose(symbolfile);
 }
@@ -383,7 +764,8 @@
             {
                 addr.seg = HIWORD(address);
                 addr.off = LOWORD(address);
-                DEBUG_AddSymbol( buffer, &addr, NULL );
+		addr.type = NULL;
+                DEBUG_AddSymbol( buffer, &addr, NULL, SYM_WIN32 | SYM_FUNC );
             }
         }
 
@@ -401,7 +783,8 @@
             {
                 addr.seg = HIWORD(address);
                 addr.off = LOWORD(address);
-                DEBUG_AddSymbol( buffer, &addr, NULL);
+		addr.type = NULL;
+                DEBUG_AddSymbol( buffer, &addr, NULL, SYM_WIN32);
             }
         }
     }
@@ -418,19 +801,20 @@
 
   if( func->n_lines + 1 >= func->lines_alloc )
     {
-      func->lines_alloc += 32;
-      func->linetab = realloc(func->linetab,
+      func->lines_alloc += 64;
+      func->linetab = xrealloc(func->linetab,
 			      func->lines_alloc * sizeof(WineLineNo));
     }
 
   func->linetab[func->n_lines].line_number = line_num;
   func->linetab[func->n_lines].pc_offset.seg = func->addr.seg;
   func->linetab[func->n_lines].pc_offset.off = func->addr.off + offset;
+  func->linetab[func->n_lines].pc_offset.type = NULL;
   func->n_lines++;
 }
 
 
-void
+struct wine_locals *
 DEBUG_AddLocal( struct name_hash * func, int regno, 
 		int offset,
 		int pc_start,
@@ -439,13 +823,13 @@
 {
   if( func == NULL )
     {
-      return;
+      return NULL;
     }
 
   if( func->n_locals + 1 >= func->locals_alloc )
     {
       func->locals_alloc += 32;
-      func->local_vars = realloc(func->local_vars,
+      func->local_vars = xrealloc(func->local_vars,
 			      func->locals_alloc * sizeof(WineLocals));
     }
 
@@ -454,6 +838,426 @@
   func->local_vars[func->n_locals].pc_start = pc_start;
   func->local_vars[func->n_locals].pc_end = pc_end;
   func->local_vars[func->n_locals].name = xstrdup(name);
+  func->local_vars[func->n_locals].type = NULL;
   func->n_locals++;
+
+  return &func->local_vars[func->n_locals - 1];
 }
 
+void
+DEBUG_DumpHashInfo()
+{
+  int i;
+  int depth;
+  struct name_hash *nh;
+
+  /*
+   * Utility function to dump stats about the hash table.
+   */
+    for(i=0; i<NR_NAME_HASH; i++)
+    {
+      depth = 0;
+      for (nh = name_hash_table[i]; nh; nh = nh->next)
+	{
+	  depth++;
+	}
+      fprintf(stderr, "Bucket %d: %d\n", i, depth);
+    }
+}
+
+/***********************************************************************
+ *           DEBUG_CheckLinenoStatus
+ *
+ * Find the symbol nearest to a given address.
+ * If ebp is specified as non-zero, it means we should dump the argument
+ * list into the string we return as well.
+ */
+int DEBUG_CheckLinenoStatus( const DBG_ADDR *addr)
+{
+    struct name_hash * nearest = NULL;
+    int mid, high, low;
+    int i;
+
+    if( sortlist_valid == FALSE )
+      {
+	DEBUG_ResortSymbols();
+      }
+
+    /*
+     * Binary search to find closest symbol.
+     */
+    low = 0;
+    high = sorttab_nsym;
+    if( addr_sorttab[0]->addr.seg > addr->seg
+	|| (   addr_sorttab[0]->addr.seg == addr->seg 
+	    && addr_sorttab[0]->addr.off > addr->off) )
+      {
+	nearest = NULL;
+      }
+    else if( addr_sorttab[high - 1]->addr.seg < addr->seg
+	|| (   addr_sorttab[high - 1]->addr.seg == addr->seg 
+	    && addr_sorttab[high - 1]->addr.off < addr->off) )
+      {
+	nearest = addr_sorttab[high - 1];
+      }
+    else
+      {
+	while(1==1)
+	  {
+	    mid = (high + low)/2;
+	    if( mid == low )
+	      {
+		/* 
+		 * See if there are any other entries that might also
+		 * have the same address, and would also have a line
+		 * number table.  
+		 */
+		if( mid > 0 && addr_sorttab[mid]->linetab == NULL )
+		  {
+		    if(    (addr_sorttab[mid - 1]->addr.seg ==
+			    addr_sorttab[mid]->addr.seg)
+			&& (addr_sorttab[mid - 1]->addr.off ==
+			    addr_sorttab[mid]->addr.off)
+		        && (addr_sorttab[mid - 1]->linetab != NULL) )
+		      {
+			mid--;
+		      }
+		  }
+
+		if(    (mid < sorttab_nsym - 1)
+		    && (addr_sorttab[mid]->linetab == NULL) )
+		  {
+		    if(    (addr_sorttab[mid + 1]->addr.seg ==
+			    addr_sorttab[mid]->addr.seg)
+			&& (addr_sorttab[mid + 1]->addr.off ==
+			    addr_sorttab[mid]->addr.off)
+		        && (addr_sorttab[mid + 1]->linetab != NULL) )
+		      {
+			mid++;
+		      }
+		  }
+		nearest = addr_sorttab[mid];
+#if 0
+		fprintf(stderr, "Found %x:%x when looking for %x:%x %x %s\n",
+			addr_sorttab[mid ]->addr.seg,
+			addr_sorttab[mid ]->addr.off,
+			addr->seg, addr->off,
+			addr_sorttab[mid ]->linetab,
+			addr_sorttab[mid ]->name);
+#endif
+		break;
+	      }
+	    if(    (addr_sorttab[mid]->addr.seg < addr->seg)
+		|| (   addr_sorttab[mid]->addr.seg == addr->seg 
+		    && addr_sorttab[mid]->addr.off <= addr->off) )
+	      {
+		low = mid;
+	      }
+	    else
+	      {
+		high = mid;
+	      }
+	  }
+      }
+
+    if (!nearest) return FUNC_HAS_NO_LINES;
+
+    if( nearest->flags & SYM_STEP_THROUGH )
+      {
+	/*
+	 * This will cause us to keep single stepping until
+	 * we get to the other side somewhere.
+	 */
+	return NOT_ON_LINENUMBER;
+      }
+
+    if( (nearest->flags & SYM_TRAMPOLINE) )
+      {
+	/*
+	 * This will cause us to keep single stepping until
+	 * we get to the other side somewhere.
+	 */
+	return FUNC_IS_TRAMPOLINE;
+      }
+
+    if( nearest->linetab == NULL )
+      {
+	return FUNC_HAS_NO_LINES;
+      }
+
+
+    /*
+     * We never want to stop on the first instruction of a function
+     * even if it has it's own linenumber.  Let the thing keep running
+     * until it gets past the function prologue.  We only do this if there
+     * is more than one line number for the function, of course.
+     */
+    if( nearest->addr.off == addr->off && nearest->n_lines > 1 )
+      {
+	return NOT_ON_LINENUMBER;
+      }
+
+    if( (nearest->sourcefile != NULL)
+	&& (addr->off - nearest->addr.off < 0x100000) )
+      {
+	/*
+	 * FIXME - this is an inefficient linear search.  A binary
+	 * search would be better if this gets to be a performance
+	 * bottleneck.
+	 */
+	for(i=0; i < nearest->n_lines; i++)
+	  {
+	    if( addr->off == nearest->linetab[i].pc_offset.off )
+	      {
+		return AT_LINENUMBER;
+	      }
+	    if( addr->off < nearest->linetab[i].pc_offset.off )
+	      {
+		break;
+	      }
+	  }
+
+	return NOT_ON_LINENUMBER;
+      }
+
+    return FUNC_HAS_NO_LINES;
+}
+
+/***********************************************************************
+ *           DEBUG_GetFuncInfo
+ *
+ * Find the symbol nearest to a given address.
+ * Returns sourcefile name and line number in a format that the listing
+ * handler can deal with.
+ */
+void
+DEBUG_GetFuncInfo( struct list_id * ret, const char * filename, 
+		   const char * name)
+{
+    char buffer[256];
+    char * pnt;
+    struct name_hash *nh;
+
+    for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
+      {
+	if( filename != NULL )
+	  {
+
+	    if( nh->sourcefile == NULL )
+	      {
+		continue;
+	      }
+
+	    pnt = strrchr(nh->sourcefile, '/');
+	    if( strcmp(nh->sourcefile, filename) != 0
+		&& (pnt == NULL || strcmp(pnt + 1, filename) != 0) )
+	      {
+		continue;
+	      }
+	  }
+        if (!strcmp(nh->name, name)) break;
+      }
+
+    if (!nh && (name[0] != '_'))
+    {
+        buffer[0] = '_';
+        strcpy(buffer+1, name);
+        for(nh = name_hash_table[name_hash(buffer)]; nh; nh = nh->next)
+	  {
+	    if( filename != NULL )
+	      {
+		if( nh->sourcefile == NULL )
+		  {
+		    continue;
+		  }
+
+		pnt = strrchr(nh->sourcefile, '/');
+		if( strcmp(nh->sourcefile, filename) != 0
+		    && (pnt == NULL || strcmp(pnt + 1, filename) != 0) )
+		  {
+		    continue;
+		  }
+	      }
+            if (!strcmp(nh->name, buffer)) break;
+	  }
+    }
+
+    if( !nh )
+      {
+	if( filename != NULL )
+	  {
+	    fprintf(stderr, "No such function %s in %s\n", name, filename);
+	  }
+	else
+	  {
+	    fprintf(stderr, "No such function %s\n", name);
+	  }
+	ret->sourcefile = NULL;
+	ret->line = -1;
+	return;
+      }
+
+    ret->sourcefile = nh->sourcefile;
+
+    /*
+     * Search for the specific line number.  If we don't find it,
+     * then return FALSE.
+     */
+    if( nh->linetab == NULL )
+      {
+	ret->line = -1;
+      }
+    else
+      {
+	ret->line = nh->linetab[0].line_number;
+      }
+}
+
+/***********************************************************************
+ *           DEBUG_GetStackSymbolValue
+ *
+ * Get the address of a named symbol from the current stack frame.
+ */
+static
+BOOL32 DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr )
+{
+  struct name_hash * curr_func;
+  unsigned int	     ebp;
+  unsigned int	     eip;
+  int		     i;
+
+  if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
+    {
+      return FALSE;
+    }
+
+  for(i=0; i < curr_func->n_locals; i++ )
+    {
+      /*
+       * Test the range of validity of the local variable.  This
+       * comes up with RBRAC/LBRAC stabs in particular.
+       */
+      if(    (curr_func->local_vars[i].pc_start != 0)
+	  && ((eip - curr_func->addr.off) 
+	      < curr_func->local_vars[i].pc_start) )
+	{
+	  continue;
+	}
+
+      if(    (curr_func->local_vars[i].pc_end != 0)
+	  && ((eip - curr_func->addr.off) 
+	      > curr_func->local_vars[i].pc_end) )
+	{
+	  continue;
+	}
+
+      if( strcmp(name, curr_func->local_vars[i].name) == 0 )
+	{
+	  /*
+	   * OK, we found it.  Now figure out what to do with this.
+	   */
+	  if( curr_func->local_vars[i].regno != 0 )
+	    {
+	      /*
+	       * Register variable.  We don't know how to treat
+	       * this yet.
+	       */
+	      return FALSE;
+	    }
+
+	  addr->seg = 0;
+	  addr->off = ebp + curr_func->local_vars[i].offset;
+	  addr->type = curr_func->local_vars[i].type;
+
+	  return TRUE;
+	}
+    }
+  return FALSE;
+}
+
+int
+DEBUG_InfoLocals()
+{
+  struct name_hash  * curr_func;
+  unsigned int	      ebp;
+  unsigned int	      eip;
+  int		      i;
+  unsigned int      * ptr;
+  int		      rtn = FALSE;
+
+  if( DEBUG_GetCurrentFrame(&curr_func, &eip, &ebp) == FALSE )
+    {
+      return FALSE;
+    }
+
+  for(i=0; i < curr_func->n_locals; i++ )
+    {
+      /*
+       * Test the range of validity of the local variable.  This
+       * comes up with RBRAC/LBRAC stabs in particular.
+       */
+      if(    (curr_func->local_vars[i].pc_start != 0)
+	  && ((eip - curr_func->addr.off) 
+	      < curr_func->local_vars[i].pc_start) )
+	{
+	  continue;
+	}
+
+      if(    (curr_func->local_vars[i].pc_end != 0)
+	  && ((eip - curr_func->addr.off) 
+	      > curr_func->local_vars[i].pc_end) )
+	{
+	  continue;
+	}
+      
+      if( curr_func->local_vars[i].offset == 0 )
+	{
+	  fprintf(stderr, "%s:%s optimized into register $%s \n",
+		  curr_func->name, curr_func->local_vars[i].name,
+		  reg_name[curr_func->local_vars[i].regno]);
+	}
+      else
+	{
+	  ptr = (unsigned int *) (ebp + curr_func->local_vars[i].offset);
+	  fprintf(stderr, "%s:%s == 0x%8.8x\n",
+		  curr_func->name, curr_func->local_vars[i].name,
+		  *ptr);
+	}
+    }
+
+  rtn = TRUE;
+
+  return (rtn);
+}
+
+int
+DEBUG_SetSymbolSize(struct name_hash * sym, unsigned int len)
+{
+  sym->symbol_size = len;
+
+  return TRUE;
+}
+
+int
+DEBUG_SetSymbolBPOff(struct name_hash * sym, unsigned int off)
+{
+  sym->breakpoint_offset = off;
+
+  return TRUE;
+}
+
+int
+DEBUG_GetSymbolAddr(struct name_hash * sym, DBG_ADDR * addr)
+{
+
+  *addr = sym->addr;
+
+  return TRUE;
+}
+
+int DEBUG_SetLocalSymbolType(struct wine_locals * sym, struct datatype * type)
+{
+  sym->type = type;
+
+  return TRUE;
+}
diff --git a/debugger/info.c b/debugger/info.c
index ee6ce29..6c5f4de 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -8,66 +8,56 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "debugger.h"
+#include "expr.h"
 
 /***********************************************************************
  *           DEBUG_Print
  *
  * Implementation of the 'print' command.
  */
-void DEBUG_Print( const DBG_ADDR *addr, int count, char format )
+void DEBUG_PrintBasic( const DBG_ADDR *addr, int count, char format )
 {
-    if (count != 1)
+  char * default_format;
+  long long int value;
+
+    if( addr->type == NULL )
     {
-        fprintf( stderr, "Count other than 1 is meaningless in 'print' command\n" );
-        return;
+      fprintf(stderr, "Unable to evaluate expression\n");
+      return;
     }
+  
+  default_format = NULL;
+  value = DEBUG_GetExprValue((DBG_ADDR *) addr, &default_format);
 
-    if (addr->seg && (addr->seg != 0xffffffff))
-    {
-        switch(format)
-        {
-	case 'x':
-            fprintf( stderr, "0x%04lx:", addr->seg );
-            break;
-
-	case 'd':
-            fprintf( stderr, "%ld:", addr->seg );
-            break;
-
-	case 'c':
-            break;  /* No segment to print */
-
-	case 'i':
-	case 's':
-	case 'w':
-	case 'b':
-            break;  /* Meaningless format */
-        }
-    }
-
-    switch(format)
+  switch(format)
     {
     case 'x':
-        if (addr->seg) fprintf( stderr, "0x%04lx\n", addr->off );
-        else fprintf( stderr, "0x%08lx\n", addr->off );
-        break;
-
+      if (addr->seg) fprintf( stderr, "0x%04lx", (long unsigned int) value );
+      else fprintf( stderr, "0x%08lx", (long unsigned int) value );
+      break;
+      
     case 'd':
-        fprintf( stderr, "%ld\n", addr->off );
-        break;
-
+      fprintf( stderr, "%ld\n", (long int) value );
+      break;
+      
     case 'c':
-        fprintf( stderr, "%d = '%c'\n",
-                 (char)(addr->off & 0xff), (char)(addr->off & 0xff) );
-        break;
-
+      fprintf( stderr, "%d = '%c'",
+	       (char)(value & 0xff), (char)(value & 0xff) );
+      break;
+      
     case 'i':
     case 's':
     case 'w':
     case 'b':
-        fprintf( stderr, "Format specifier '%c' is meaningless in 'print' command\n", format );
-        break;
+      fprintf( stderr, "Format specifier '%c' is meaningless in 'print' command\n", format );
+    case 0:
+      if( default_format != NULL )
+	{
+	  fprintf( stderr, default_format, value );
+	}
+      break;
     }
+
 }
 
 
@@ -76,17 +66,19 @@
  *
  * Print an 16- or 32-bit address, with the nearest symbol if any.
  */
-struct name_hash *
+struct symbol_info
 DEBUG_PrintAddress( const DBG_ADDR *addr, int addrlen, int flag )
 {
-    struct name_hash * nh;
-    const char *name = DEBUG_FindNearestSymbol( addr, flag, &nh, 0 );
+    struct symbol_info rtn;
+
+    const char *name = DEBUG_FindNearestSymbol( addr, flag, &rtn.sym, 0, 
+						&rtn.list );
 
     if (addr->seg) fprintf( stderr, "0x%04lx:", addr->seg );
     if (addrlen == 16) fprintf( stderr, "0x%04lx", addr->off );
     else fprintf( stderr, "0x%08lx", addr->off );
     if (name) fprintf( stderr, " (%s)", name );
-    return nh;
+    return rtn;
 }
 /***********************************************************************
  *           DEBUG_PrintAddressAndArgs
@@ -95,19 +87,21 @@
  * Similar to DEBUG_PrintAddress, but we print the arguments to
  * each function (if known).  This is useful in a backtrace.
  */
-struct name_hash *
+struct symbol_info
 DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr, int addrlen, 
 			   unsigned int ebp, int flag )
 {
-    struct name_hash * nh;
-    const char *name = DEBUG_FindNearestSymbol( addr, flag, &nh, ebp );
+    struct symbol_info rtn;
+
+    const char *name = DEBUG_FindNearestSymbol( addr, flag, &rtn.sym, ebp, 
+						&rtn.list );
 
     if (addr->seg) fprintf( stderr, "0x%04lx:", addr->seg );
     if (addrlen == 16) fprintf( stderr, "0x%04lx", addr->off );
     else fprintf( stderr, "0x%08lx", addr->off );
     if (name) fprintf( stderr, " (%s)", name );
 
-    return nh;
+    return rtn;
 }
 
 
@@ -121,23 +115,28 @@
     int i = 0;
     static const char * const helptext[] =
 {
-"The commands accepted by the Wine debugger are a small subset",
-"of the commands that gdb would accept.",
+"The commands accepted by the Wine debugger are a reasonable",
+"of the commands that gdb accepts.",
 "The commands currently are:",
 "  break [*<addr>]                        delete break bpnum",
 "  disable bpnum                          enable bpnum",
+"  condition <bpnum> [<expr>]",
+
 "  help                                   quit",
-"  bt                                     cont",
-"  step                                   next",
+"  bt                                     cont [N]",
+"  step [N]                               next [N]",
+"  stepi [N]                              nexti [N]",
 "  x <addr>                               print <expr>",
 "  set <reg> = <expr>                     set *<addr> = <expr>",
-"  symbolfile <filename>                  define <identifier> <addr>",
-"  up                                     down\n",
-"  list <addr>                            frame <n>\n",
+"  up                                     down",
+"  list <lines>                           frame <n>",
+"  finish                                 show dir",
+"  dir <path>                             display <expr>",
+"  delete display <disnum>                undisplay <disnum>\n",
 
 "Wine-specific commands:",
 "  mode [16,32]                           walk [wnd,class,queue] <handle>",
-"  info [reg,stack,break,segments,locals] info [wnd, queue] <handle>\n",
+"  info (see 'help info' for options)\n",
 
 "The 'x' command accepts repeat counts and formats (including 'i') in the",
 "same way that gdb does.\n",
@@ -155,25 +154,31 @@
 }
 
 
-
 /***********************************************************************
- *           DEBUG_List
+ *           DEBUG_HelpInfo
  *
- * Implementation of the 'list' command.
+ * Implementation of the 'help info' command.
  */
-void DEBUG_List( DBG_ADDR *addr, int count )
+void DEBUG_HelpInfo(void)
 {
-    static DBG_ADDR lasttime = { 0xffffffff, 0 };
+    int i = 0;
+    static const char * const infotext[] =
+{
+"The info commands allow you to get assorted bits of interesting stuff",
+"to be displayed.  The options are:",
+"  info break           Dumps information about breakpoints",
+"  info display         Shows auto-display expressions in use",
+"  info locals          Displays values of all local vars for current frame",
+"  info module          Displays information about all modules",
+"  info queue <handle>  Dumps queue information",
+"  info reg             Displays values in all registers at top of stack",
+"  info segments        Dumps information about all known segments",
+"  info share           Dumps information about shared libraries",
+"  info stack           Dumps information about top of stack",
+"  info wnd <handle>    Dumps information about all windows",
+"",
+NULL
+};
 
-    if (addr == NULL) addr = &lasttime;
-    DBG_FIX_ADDR_SEG( addr, CS_reg(&DEBUG_context) );
-    while (count-- > 0)
-    {
-        DEBUG_PrintAddress( addr, dbg_mode, FALSE );
-        fprintf( stderr, ":  " );
-        if (!DBG_CHECK_READ_PTR( addr, 1 )) return;
-        DEBUG_Disasm( addr );
-        fprintf (stderr, "\n");
-    }
-    lasttime = *addr;
+    while(infotext[i]) fprintf(stderr,"%s\n", infotext[i++]);
 }
diff --git a/debugger/memory.c b/debugger/memory.c
index 244fcde..f629194 100644
--- a/debugger/memory.c
+++ b/debugger/memory.c
@@ -142,15 +142,31 @@
  */
 void DEBUG_ExamineMemory( const DBG_ADDR *address, int count, char format )
 {
-    DBG_ADDR addr = *address;
-    unsigned char * pnt;
-    unsigned int * dump;
-    unsigned short int * wdump;
-    int i;
+    DBG_ADDR addr =	* address;
+    unsigned int	* dump;
+    int			  i;
+    unsigned char	* pnt;
+    struct datatype	* testtype;
+    unsigned short int	* wdump;
 
     DBG_FIX_ADDR_SEG( &addr, (format == 'i') ?
                              CS_reg(&DEBUG_context) : DS_reg(&DEBUG_context) );
 
+    /*
+     * Dereference pointer to get actual memory address we need to be
+     * reading.  We will use the same segment as what we have already,
+     * and hope that this is a sensible thing to do.
+     */
+    if( addr.type != NULL )
+      {
+	if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
+	DEBUG_TypeDerefPointer(&addr, &testtype);
+	if( testtype != NULL || addr.type == DEBUG_TypeIntConst )
+	  {
+	    addr.off = DEBUG_GetExprValue(&addr, NULL);
+	  }
+      }
+
     if (format != 'i' && count > 1)
     {
         DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
@@ -179,7 +195,7 @@
                     DEBUG_PrintAddress( &addr, dbg_mode, TRUE );
                     fprintf(stderr,": ");
                     if (!DBG_CHECK_READ_PTR( &addr, 1 )) return;
-                    DEBUG_Disasm( &addr );
+                    DEBUG_Disasm( &addr, TRUE );
                     fprintf(stderr,"\n");
 		}
 		return;
diff --git a/debugger/msc.c b/debugger/msc.c
index dc29ca9..1c1817b 100644
--- a/debugger/msc.c
+++ b/debugger/msc.c
@@ -8,26 +8,332 @@
  * that run under Windows-NT for example.  I doubt that this would work well
  * for 16 bit applications, but I don't think it really matters since the
  * file format is different, and we should never get in here in such cases.
+ *
+ * TODO:
+ *	Get 16 bit CV stuff working.
+ *	Add symbol size to internal symbol table.
  */
 
 #include <stdio.h>
-
+#include <stdlib.h>
 
 #include <sys/mman.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <limits.h>
-#include <strings.h>
+#include <string.h>
 #include <unistd.h>
 #include <malloc.h>
 
 #include "win.h"
 #include "pe_image.h"
+#include "peexe.h"
 #include "debugger.h"
 #include "peexe.h"
 #include "xmalloc.h"
 
 /*
+ * This is used so that we have some idea of what we are in fact loading
+ * at any given time.
+ */
+char * DEBUG_curr_module = NULL;
+
+/*
+ * This is an index we use to keep track of the debug information
+ * when we have multiple sources.  We use the same database to also
+ * allow us to do an 'info shared' type of deal, and we use the index
+ * to eliminate duplicates.
+ */
+static int DEBUG_next_index = 0;
+
+union any_size
+{
+  char		 * c;
+  short		 * s;
+  int		 * i;
+  unsigned int   * ui;
+};
+
+/*
+ * This is a convenience structure used to map portions of the
+ * line number table.
+ */
+struct startend
+{
+  unsigned int	  start;
+  unsigned int	  end;
+};
+
+/*
+ * This is how we reference the various record types.
+ */
+union codeview_symbol
+{
+  struct
+  {
+    short int	len;
+    short int	id;
+  } generic;
+
+  struct
+  {
+	short int	len;
+	short int	id;
+	unsigned int	offset;
+	unsigned short	seg;
+	unsigned short	symtype;
+	unsigned char	namelen;
+	unsigned char	name[1];
+  } data;
+
+  struct
+  {
+	short int	len;
+	short int	id;
+	unsigned int	pparent;
+	unsigned int	pend;
+	unsigned int	next;
+	unsigned int	offset;
+	unsigned short	segment;
+	unsigned short	thunk_len;
+	unsigned char	thtype;
+	unsigned char	namelen;
+	unsigned char	name[1];
+  } thunk;
+  struct
+  {
+	short int	len;
+	short int	id;
+	unsigned int	pparent;
+	unsigned int	pend;
+	unsigned int	next;
+	unsigned int	proc_len;
+	unsigned int	debug_start;
+	unsigned int	debug_end;
+	unsigned int	offset;
+	unsigned short	segment;
+	unsigned short	proctype;
+	unsigned char	flags;
+	unsigned char	namelen;
+	unsigned char	name[1];
+  } proc;
+  struct
+  {
+	short int	len;	/* Total length of this entry */
+	short int	id;		/* Always S_BPREL32 */
+	unsigned int	offset;	/* Stack offset relative to BP */
+	unsigned short	symtype;
+	unsigned char	namelen;
+	unsigned char	name[1];
+  } stack;
+};
+
+union codeview_type
+{
+  struct
+  {
+    short int	len;
+    short int	id;
+  } generic;
+
+  struct
+  {
+    short int		len;
+    short int		id;
+    short int		attribute;
+    short int		datatype;
+    unsigned char	variant[1];
+  } pointer;
+
+  struct
+  {
+    short int		len;
+    short int		id;
+    unsigned char	nbits;
+    unsigned char	bitoff;
+    unsigned short	type;
+  } bitfield;
+
+  struct
+  {
+    short int		len;
+    short int		id;
+    short int		elemtype;
+    short int		idxtype;
+    unsigned char	arrlen;
+    unsigned char	namelen;
+    unsigned char	name[1];
+  } array;
+
+  struct
+  {
+    short int		len;
+    short int		id;
+    short int		n_element;
+    short int		fieldlist;
+    short int		property;
+    short int		derived;
+    short int		vshape;
+    unsigned short	structlen;
+    unsigned char	namelen;
+    unsigned char	name[1];
+  } structure;
+
+  struct
+  {
+    short int		len;
+    short int		id;
+    short int		count;
+    short int		field;
+    short int		property;
+    unsigned short	un_len;
+    unsigned char	namelen;
+    unsigned char	name[1];
+  } t_union;
+
+  struct
+  {
+    short int		len;
+    short int		id;
+    short int		count;
+    short int		type;
+    short int		field;
+    short int		property;
+    unsigned char	namelen;
+    unsigned char	name[1];
+  } enumeration;
+
+  struct
+  {
+    short int		id;
+    short int		attribute;
+    unsigned short int	value;
+    unsigned char	namelen;
+    unsigned char	name[1];
+  } enumerate;
+
+  struct
+  {
+    short int		id;
+    short int		type;
+    short int		attribute;
+    unsigned short int	offset;
+    unsigned char	namelen;
+    unsigned char	name[1];
+  } member;
+
+  struct
+  {
+    short int		len;
+    short int		id;
+    short int		count;
+    short int		type;
+    short int		field;
+    short int		property;
+    unsigned char	namelen;
+    unsigned char	name[1];
+  } fieldlist;
+
+};
+
+#define S_BPREL32	0x200
+#define S_LDATA32	0x201
+#define S_GDATA32	0x202
+#define S_PUB32		0x203
+#define S_LPROC32	0x204
+#define S_GPROC32	0x205
+#define S_THUNK32	0x206
+#define S_BLOCK32	0x207
+#define S_WITH32	0x208
+#define S_LABEL32	0x209
+
+#define S_PROCREF	0x400
+#define S_DATAREF	0x401
+#define S_ALIGN		0x402
+#define S_UNKNOWN	0x403
+
+/*
+ * This covers the basic datatypes that VC++ seems to be using these days.
+ * 32 bit mode only.  There are additional numbers for the pointers in 16
+ * bit mode.  There are many other types listed in the documents, but these
+ * are apparently not used by the compiler, or represent pointer types
+ * that are not used.
+ */
+#define T_NOTYPE	0x0000	/* Notype */
+#define T_ABS		0x0001	/* Abs */
+#define T_VOID		0x0003	/* Void */
+#define T_CHAR		0x0010	/* signed char */
+#define T_SHORT		0x0011	/* short */
+#define T_LONG		0x0012	/* long */
+#define T_QUAD		0x0013	/* long long */
+#define T_UCHAR		0x0020	/* unsigned  char */
+#define T_USHORT	0x0021	/* unsigned short */
+#define T_ULONG		0x0022	/* unsigned long */
+#define T_UQUAD		0x0023	/* unsigned long long */
+#define T_REAL32	0x0040	/* float */
+#define T_REAL64	0x0041	/* double */
+#define T_RCHAR		0x0070	/* real char */
+#define T_WCHAR		0x0071	/* wide char */
+#define T_INT4		0x0074	/* int */
+#define T_UINT4		0x0075	/* unsigned int */
+
+#define T_32PVOID	0x0403	/* 32 bit near pointer to void */
+#define T_32PCHAR	0x0410  /* 16:32 near pointer to signed char */
+#define T_32PSHORT	0x0411  /* 16:32 near pointer to short */
+#define T_32PLONG	0x0412  /* 16:32 near pointer to int */
+#define T_32PQUAD	0x0413  /* 16:32 near pointer to long long */
+#define T_32PUCHAR	0x0420  /* 16:32 near pointer to unsigned char */
+#define T_32PUSHORT	0x0421  /* 16:32 near pointer to unsigned short */
+#define T_32PULONG	0x0422	/* 16:32 near pointer to unsigned int */
+#define T_32PUQUAD	0x0423  /* 16:32 near pointer to long long */
+#define T_32PREAL32	0x0440	/* 16:32 near pointer to float */
+#define T_32PREAL64	0x0441	/* 16:32 near pointer to float */
+#define T_32PRCHAR	0x0470	/* 16:32 near pointer to real char */
+#define T_32PWCHAR	0x0471	/* 16:32 near pointer to real char */
+#define T_32PINT4	0x0474	/* 16:32 near pointer to int */
+#define T_32PUINT4	0x0475  /* 16:32 near pointer to unsigned int */
+
+#define LF_MODIFIER	0x1
+#define LF_POINTER	0x2
+#define LF_ARRAY	0x3
+#define LF_CLASS	0x4
+#define LF_STRUCTURE	0x5
+#define LF_UNION	0x6
+#define LF_ENUMERATION	0x7
+#define LF_PROCEDURE	0x8
+#define LF_MFUNCTION	0x9
+#define LF_VTSHAPE	0xa
+#define LF_BARRAY	0xd
+#define LF_DIMARRAY	0x11
+#define LF_VFTPATH	0x12
+
+#define LF_SKIP		0x200
+#define LF_ARGLIST	0x201
+#define LF_FIELDLIST	0x204
+#define LF_DERIVED	0x205
+#define LF_BITFIELD	0x206
+
+#define LF_BCLASS	0x400
+#define LF_VBCLASS	0x401
+#define LF_IVBCLASS	0x402
+#define LF_ENUMERATE	0x403
+#define LF_FRIENDFCN	0x404
+#define LF_INDEX	0x405
+#define LF_MEMBER	0x406
+#define LF_STMEMBER	0x407
+#define LF_METHOD	0x408
+#define LF_NESTEDTYPE	0x409
+#define LF_VFUNCTAB	0x40a
+#define LF_FRIENDCLS	0x40b
+#define LF_ONEMETHOD	0x40c
+#define LF_FUNCOFF	0x40d
+
+#define MAX_BUILTIN_TYPES	0x480
+static struct datatype * cv_basic_types[MAX_BUILTIN_TYPES];
+static int num_cv_defined_types = 0;
+static struct datatype **cv_defined_types = NULL;
+
+/*
  * For the type CODEVIEW debug directory entries, the debug directory
  * points to a structure like this.  The cv_name field is the name
  * of an external .PDB file.
@@ -60,14 +366,19 @@
 };
 
 struct CoffLinenum {
-	unsigned int	VirtualAddr;
-	unsigned int	Linenum;
+	unsigned int		VirtualAddr;
+	unsigned short int	Linenum;
 };
 
 struct CoffFiles {
 	unsigned int	startaddr;
 	unsigned int	endaddr;
 	char	      * filename;
+	int		linetab_offset;
+	int		linecnt;
+	struct name_hash **entries;
+	int		       neps;
+	int		 neps_alloc;
 };
 
 
@@ -95,14 +406,118 @@
   char           Selection;
 } Section;
 
+/*
+ * These two structures are used in the directory within a .DBG file
+ * to locate the individual important bits that we might want to see.
+ */
+struct CV4_DirHead {
+  short unsigned int	   dhsize;
+  short unsigned int	   desize;
+  unsigned int		   ndir;
+  unsigned int		   next_offset;
+  unsigned int		   flags;
+};
+
+struct CV4_DirEnt {
+  short unsigned int	   subsect_number;
+  short unsigned int	   module_number;
+  unsigned int		   offset;
+  unsigned int		   size;
+};
+
+/*
+ * These are the values of interest that the subsect_number field takes.
+ */
+#define	sstAlignSym		0x125
+#define	sstSrcModule		0x127
+
+struct codeview_linetab_hdr
+{
+  unsigned int		   nline;
+  unsigned int		   segno;
+  unsigned int		   start;
+  unsigned int		   end;
+  char			 * sourcefile;
+  unsigned short	 * linetab;
+  unsigned int		 * offtab;
+};
+
+struct codeview_pdb_hdr
+{
+  char		ident[44];
+  unsigned int	blocksize;	   /* Extent size */
+  unsigned short loc_freelist;   /* freelist. */
+  unsigned short alloc_filesize; /* # extents allocated. */
+  unsigned int	toc_len;
+  unsigned int	unknown;
+  unsigned short toc_ext[1];	   /* array of extent #'s for toc. */
+};
+
+/*
+ * This is our own structure that we use to keep track of the contents
+ * of a PDB file.
+ */
+struct file_list
+{
+	int		record_len;
+	int		nextents;
+	short int     * extent_list;
+	unsigned int	linetab_offset;
+	unsigned int	linetab_len;
+};
+
+/*
+ * These are the structures that represent how the file table is set up
+ * within the PDB file.
+ */
+struct filetab_hdr
+{
+  unsigned short	tab1_file;
+  unsigned short	tab2_file;
+  unsigned short	gsym_file;
+  unsigned short	padding;
+  unsigned int		ftab_len;
+  unsigned int		fofftab_len;
+  unsigned int		hash_len;
+  unsigned int		strtab_len;
+};
+
+struct file_ent
+{
+  unsigned int		reserved1;
+  unsigned short	datasect_segment;
+  unsigned short	reserved2;
+  unsigned int		datasect_offset;
+  unsigned int		datasect_size;
+  unsigned int		datasect_flags;
+  unsigned short	reserved3;
+  unsigned short	index;
+  unsigned short	num6a;
+  unsigned short	file_number;
+  unsigned int		linetab_offset;
+  unsigned int		linetab_len;
+  unsigned int		num9;
+  unsigned int		num10;
+  unsigned int		num11;
+  unsigned char		filename[1];
+};
+
+/*
+ ********************************************************************
+ */
 struct deferred_debug_info
 {
 	struct deferred_debug_info	* next;
 	char				* load_addr;
+	char				* module_name;
 	char				* dbg_info;
 	int				  dbg_size;
 	struct PE_Debug_dir		* dbgdir;
 	struct pe_data			* pe;
+        struct pe_segment_table         * sectp;
+	int				  nsect;
+	short int			  dbg_index;			
+	char				  loaded;
 };
 
 struct deferred_debug_info * dbglist = NULL;
@@ -124,6 +539,329 @@
 #define IMAGE_SYM_CLASS_STATIC              0x3
 #define IMAGE_SYM_CLASS_FILE                0x67
 
+static 
+struct datatype * DEBUG_GetCVType(int typeno)
+{
+  struct datatype * dt = NULL;
+
+  /*
+   * Convert Codeview type numbers into something we can grok internally.
+   * Numbers < 0x1000 are all fixed builtin types.  Numbers from 0x1000 and
+   * up are all user defined (structs, etc).
+   */
+  if( typeno < 0x1000 )
+    {
+      if( typeno < MAX_BUILTIN_TYPES )
+	{
+	  dt = cv_basic_types[typeno];
+	}
+    }
+  else
+    {
+      if( typeno - 0x1000 < num_cv_defined_types )
+	{
+	  dt = cv_defined_types[typeno - 0x1000];
+	} 
+    }
+
+  return dt;
+}
+
+static int
+DEBUG_ParseTypeTable(char * table, int len)
+{
+  int				  arr_max;
+  int				  curr_type;
+  enum debug_type		  fieldtype;
+  int				  elem_size;
+  union any_size		  ptr;
+  union any_size		  ptr2;
+  struct datatype		* subtype;
+  char				  symname[256];
+  union codeview_type		* type;
+  union codeview_type		* type2;
+  struct datatype		* typeptr;
+
+  curr_type = 0x1000;
+
+  ptr = (union any_size) (table + 16);
+  while( ptr.c - table < len )
+    {
+      type = (union codeview_type *) ptr.c;
+
+      if( curr_type - 0x1000 >= num_cv_defined_types )
+	{
+	  num_cv_defined_types += 0x100;
+	  cv_defined_types = (struct datatype **) realloc(cv_defined_types,
+		  num_cv_defined_types * sizeof(struct datatype *));
+	  memset(cv_defined_types + num_cv_defined_types - 0x100,
+		 0,
+		 0x100 * sizeof(struct datatype *));
+	  if( cv_defined_types == NULL )
+	    {
+	      return FALSE;
+	    }
+	}
+
+      switch(type->generic.id)
+	{
+	case LF_POINTER:
+	  cv_defined_types[curr_type - 0x1000] = 
+	    DEBUG_FindOrMakePointerType(DEBUG_GetCVType(type->pointer.datatype));
+	  break;
+	case LF_ARRAY:
+	  if( type->array.arrlen >= 0x8000 )
+	    {
+	      /*
+	       * This is a numeric leaf, I am too lazy to handle this right
+	       * now.
+	       */
+	      fprintf(stderr, "Ignoring large numberic leaf.\n");
+	      break;
+	    }
+	  if( type->array.namelen != 0 )
+	    {
+	      memset(symname, 0, sizeof(symname));
+	      memcpy(symname, type->array.name, type->array.namelen);
+	      typeptr = DEBUG_NewDataType(ARRAY, symname);
+	    }
+	  else
+	    {
+	      typeptr = DEBUG_NewDataType(ARRAY, NULL);
+	    }
+	  cv_defined_types[curr_type - 0x1000] = typeptr;
+
+	  subtype = DEBUG_GetCVType(type->array.elemtype);
+	  if(    (subtype == NULL)
+	      || (elem_size = DEBUG_GetObjectSize(subtype)) == 0 )
+	    {
+	      arr_max = 0;
+	    }
+	  else
+	    {
+	      arr_max = type->array.arrlen / DEBUG_GetObjectSize(subtype);
+	    }
+
+	  DEBUG_SetArrayParams(typeptr, 0, arr_max, subtype);
+	  break;
+	case LF_FIELDLIST:
+	  /*
+	   * This is where the basic list of fields is defined for
+	   * structures and classes.
+	   *
+	   * First, we need to look ahead and see whether we are building
+	   * a fieldlist for an enum or a struct.
+	   */
+	  ptr2.i = ptr.i + 1;
+	  type2 = (union codeview_type *) ptr2.c;
+	  if( type2->member.id == LF_MEMBER )
+	    {
+	      typeptr = DEBUG_NewDataType(STRUCT, NULL);
+	      fieldtype = STRUCT;
+	    }
+	  else if( type2->member.id == LF_ENUMERATE )
+	    {
+	      typeptr = DEBUG_NewDataType(ENUM, NULL);
+	      fieldtype = ENUM;
+	    }
+	  else
+	    {
+	      break;
+	    }
+
+	  cv_defined_types[curr_type - 0x1000] = typeptr;
+	  while( ptr2.c < (ptr.c + ((type->generic.len + 3) & ~3)) )
+	    {
+	      type2 = (union codeview_type *) ptr2.c;
+	      if( type2->member.id == LF_MEMBER && fieldtype == STRUCT )
+		{
+		  memset(symname, 0, sizeof(symname));
+		  memcpy(symname, type2->member.name, type2->member.namelen);
+		  
+		  subtype = DEBUG_GetCVType(type2->member.type);
+		  elem_size = 0;
+		  if( subtype != NULL )
+		    {
+		      elem_size = DEBUG_GetObjectSize(subtype);
+		    }
+		  
+		  if( type2->member.offset >= 0x8000 )
+		    {
+		      /*
+		       * This is a numeric leaf, I am too lazy to handle this right
+		       * now.
+		       */
+		      fprintf(stderr, "Ignoring large numberic leaf.\n");
+		    }
+		  else
+		    {
+		      DEBUG_AddStructElement(typeptr, symname, subtype, 
+					     type2->member.offset << 3,
+					     elem_size << 3);
+		    }
+		}
+	      else if( type2->member.id == LF_ENUMERATE && fieldtype == ENUM )
+		{
+		  memset(symname, 0, sizeof(symname));
+		  memcpy(symname, type2->enumerate.name, type2->enumerate.namelen);
+		  
+		  if( type2->enumerate.value >= 0x8000 )
+		    {
+		      /*
+		       * This is a numeric leaf, I am too lazy to handle this right
+		       * now.
+		       */
+		      fprintf(stderr, "Ignoring large numberic leaf.\n");
+		    }
+		  else
+		    {
+		      DEBUG_AddStructElement(typeptr, symname, NULL, 
+					     type2->enumerate.value, 0);
+		    }
+		}
+	      else
+		{
+		  /*
+		   * Something else I have never seen before.  Either wrong type of
+		   * object in the fieldlist, or some other problem which I wouldn't
+		   * really know how to handle until it came up.
+		   */
+		  fprintf(stderr, "Unexpected entry in fieldlist\n");
+		  break;
+		}
+
+
+	      ptr2.c += ((type2->member.namelen + 9 + 3) & ~3);
+	    }
+	  break;
+	case LF_STRUCTURE:
+	case LF_CLASS:
+	  if( type->structure.structlen >= 0x8000 )
+	    {
+	      /*
+	       * This is a numeric leaf, I am too lazy to handle this right
+	       * now.
+	       */
+	      fprintf(stderr, "Ignoring large numberic leaf.\n");
+	      break;
+	    }
+	  memset(symname, 0, sizeof(symname));
+	  memcpy(symname, type->structure.name, type->structure.namelen);
+	  typeptr = DEBUG_NewDataType(STRUCT, symname);
+	  cv_defined_types[curr_type - 0x1000] = typeptr;
+
+	  /*
+	   * Now copy the relevant bits from the fieldlist that we specified.
+	   */
+	  subtype = DEBUG_GetCVType(type->structure.fieldlist);
+	  DEBUG_SetStructSize(typeptr, type->structure.structlen);
+
+	  if( subtype != NULL )
+	    {
+	      DEBUG_CopyFieldlist(typeptr, subtype);
+	    }
+	  break;
+	case LF_UNION:
+	  if( type->t_union.un_len >= 0x8000 )
+	    {
+	      /*
+	       * This is a numeric leaf, I am too lazy to handle this right
+	       * now.
+	       */
+	      fprintf(stderr, "Ignoring large numberic leaf.\n");
+	      break;
+	    }
+	  memset(symname, 0, sizeof(symname));
+	  memcpy(symname, type->t_union.name, type->t_union.namelen);
+	  typeptr = DEBUG_NewDataType(STRUCT, symname);
+	  cv_defined_types[curr_type - 0x1000] = typeptr;
+
+	  /*
+	   * Now copy the relevant bits from the fieldlist that we specified.
+	   */
+	  subtype = DEBUG_GetCVType(type->t_union.field);
+	  DEBUG_SetStructSize(typeptr, type->t_union.un_len);
+
+	  if( subtype != NULL )
+	    {
+	      DEBUG_CopyFieldlist(typeptr, subtype);
+	    }
+	  break;
+	case LF_BITFIELD:
+	  typeptr = DEBUG_NewDataType(BITFIELD, NULL);
+	  cv_defined_types[curr_type - 0x1000] = typeptr;
+	  DEBUG_SetBitfieldParams(typeptr, type->bitfield.bitoff,
+				  type->bitfield.nbits, 
+				  DEBUG_GetCVType(type->bitfield.type));
+	  break;
+	case LF_ENUMERATION:
+	  memset(symname, 0, sizeof(symname));
+	  memcpy(symname, type->enumeration.name, type->enumeration.namelen);
+	  typeptr = DEBUG_NewDataType(ENUM, symname);
+	  cv_defined_types[curr_type - 0x1000] = typeptr;
+
+	  /*
+	   * Now copy the relevant bits from the fieldlist that we specified.
+	   */
+	  subtype = DEBUG_GetCVType(type->enumeration.field);
+
+	  if( subtype != NULL )
+	    {
+	      DEBUG_CopyFieldlist(typeptr, subtype);
+	    }
+	  break;
+	case LF_DIMARRAY:
+	default:
+	  break;
+	}
+      curr_type++;
+      ptr.c += (type->generic.len + 3) & ~3;
+    }
+
+  return TRUE;
+}
+
+void
+DEBUG_InitCVDataTypes()
+{
+  /*
+   * These are the common builtin types that are used by VC++.
+   */
+  cv_basic_types[T_NOTYPE] = NULL;
+  cv_basic_types[T_ABS] = NULL;
+  cv_basic_types[T_VOID] = DEBUG_NewDataType(BASIC, "void");
+  cv_basic_types[T_CHAR] = DEBUG_NewDataType(BASIC, "char");
+  cv_basic_types[T_SHORT] = DEBUG_NewDataType(BASIC, "short int");
+  cv_basic_types[T_LONG] = DEBUG_NewDataType(BASIC, "long int");
+  cv_basic_types[T_QUAD] = DEBUG_NewDataType(BASIC, "long long int");
+  cv_basic_types[T_UCHAR] = DEBUG_NewDataType(BASIC, "unsigned char");
+  cv_basic_types[T_USHORT] = DEBUG_NewDataType(BASIC, "short unsigned int");
+  cv_basic_types[T_ULONG] = DEBUG_NewDataType(BASIC, "long unsigned int");
+  cv_basic_types[T_UQUAD] = DEBUG_NewDataType(BASIC, "long long unsigned int");
+  cv_basic_types[T_REAL32] = DEBUG_NewDataType(BASIC, "float");
+  cv_basic_types[T_REAL64] = DEBUG_NewDataType(BASIC, "double");
+  cv_basic_types[T_RCHAR] = DEBUG_NewDataType(BASIC, "char");
+  cv_basic_types[T_WCHAR] = DEBUG_NewDataType(BASIC, "short");
+  cv_basic_types[T_INT4] = DEBUG_NewDataType(BASIC, "int");
+  cv_basic_types[T_UINT4] = DEBUG_NewDataType(BASIC, "unsigned int");
+
+  cv_basic_types[T_32PVOID] = DEBUG_FindOrMakePointerType(cv_basic_types[T_VOID]);
+  cv_basic_types[T_32PCHAR] = DEBUG_FindOrMakePointerType(cv_basic_types[T_CHAR]);
+  cv_basic_types[T_32PSHORT] = DEBUG_FindOrMakePointerType(cv_basic_types[T_SHORT]);
+  cv_basic_types[T_32PLONG] = DEBUG_FindOrMakePointerType(cv_basic_types[T_LONG]);
+  cv_basic_types[T_32PQUAD] = DEBUG_FindOrMakePointerType(cv_basic_types[T_QUAD]);
+  cv_basic_types[T_32PUCHAR] = DEBUG_FindOrMakePointerType(cv_basic_types[T_UCHAR]);
+  cv_basic_types[T_32PUSHORT] = DEBUG_FindOrMakePointerType(cv_basic_types[T_USHORT]);
+  cv_basic_types[T_32PULONG] = DEBUG_FindOrMakePointerType(cv_basic_types[T_ULONG]);
+  cv_basic_types[T_32PUQUAD] = DEBUG_FindOrMakePointerType(cv_basic_types[T_UQUAD]);
+  cv_basic_types[T_32PREAL32] = DEBUG_FindOrMakePointerType(cv_basic_types[T_REAL32]);
+  cv_basic_types[T_32PREAL64] = DEBUG_FindOrMakePointerType(cv_basic_types[T_REAL64]);
+  cv_basic_types[T_32PRCHAR] = DEBUG_FindOrMakePointerType(cv_basic_types[T_RCHAR]);
+  cv_basic_types[T_32PWCHAR] = DEBUG_FindOrMakePointerType(cv_basic_types[T_WCHAR]);
+  cv_basic_types[T_32PINT4] = DEBUG_FindOrMakePointerType(cv_basic_types[T_INT4]);
+  cv_basic_types[T_32PUINT4] = DEBUG_FindOrMakePointerType(cv_basic_types[T_UINT4]);
+}
+
 /*
  * In this function, we keep track of deferred debugging information
  * that we may need later if we were to need to use the internal debugger.
@@ -133,16 +871,45 @@
 DEBUG_RegisterDebugInfo(int fd, struct pe_data * pe, 
 			int load_addr, u_long v_addr, u_long size)
 {
+  int			  has_codeview = FALSE;
   int			  rtn = FALSE;
+  int			  orig_size;
   struct PE_Debug_dir	* dbgptr;
   struct deferred_debug_info * deefer;
 
+  orig_size = size;
+  dbgptr = (struct PE_Debug_dir *) (load_addr + v_addr);
+  for(; size > 0; size -= sizeof(*dbgptr), dbgptr++ )
+    {
+      switch(dbgptr->type)
+	{
+	case IMAGE_DEBUG_TYPE_CODEVIEW:
+	case IMAGE_DEBUG_TYPE_MISC:
+	  has_codeview = TRUE;
+	  break;
+	}
+    }
+
+  size = orig_size;
   dbgptr = (struct PE_Debug_dir *) (load_addr + v_addr);
   for(; size > 0; size -= sizeof(*dbgptr), dbgptr++ )
     {
       switch(dbgptr->type)
 	{
 	case IMAGE_DEBUG_TYPE_COFF:
+	  /*
+	   * If we have both codeview and COFF debug info, ignore the
+	   * coff debug info as  it would just confuse us, and it is 
+	   * less complete.
+	   *
+	   * FIXME - this is broken - if we cannot find the PDB file, then
+	   * we end up with no debugging info at all.  In this case, we
+	   * should use the COFF info as a backup.
+	   */
+	  if( has_codeview )
+	    {
+	      break;
+	    }
 	case IMAGE_DEBUG_TYPE_CODEVIEW:
 	case IMAGE_DEBUG_TYPE_MISC:
 	  /*
@@ -179,21 +946,63 @@
 	  deefer->load_addr = (char *) load_addr;
 	  deefer->dbgdir = dbgptr;
 	  deefer->next = dbglist;
+	  deefer->loaded = FALSE;
+	  deefer->dbg_index = DEBUG_next_index;
+	  deefer->module_name = xstrdup(DEBUG_curr_module);
+
+	  deefer->sectp = pe->pe_seg;
+	  deefer->nsect = pe->pe_header->coff.NumberOfSections;
+
 	  dbglist = deefer;
 	  break;
 	default:
 	}
     }
 
+  DEBUG_next_index++;
+
   return (rtn);
 
 }
 
 /*
+ * ELF modules are also entered into the list - this is so that we
+ * can make 'info shared' types of displays possible.
+ */
+int
+DEBUG_RegisterELFDebugInfo(int load_addr, u_long size, char * name)
+{
+  struct deferred_debug_info * deefer;
+
+  deefer = (struct deferred_debug_info *) xmalloc(sizeof(*deefer));
+  deefer->pe = NULL;
+  
+  /*
+   * Read the important bits.  What we do after this depends
+   * upon the type, but this is always enough so we are able
+   * to proceed if we know what we need to do next.
+   */
+  deefer->dbg_size = size;
+  deefer->dbg_info = (char *) NULL;
+  
+  deefer->load_addr = (char *) load_addr;
+  deefer->dbgdir = NULL;
+  deefer->next = dbglist;
+  deefer->loaded = TRUE;
+  deefer->dbg_index = DEBUG_next_index;
+  deefer->module_name = xstrdup(name);
+  dbglist = deefer;
+
+  DEBUG_next_index++;
+
+  return (TRUE);
+}
+
+
+
+/*
  * Process COFF debugging information embedded in a Win32 application.
  *
- * FIXME - we need to process the source file information and the line
- * numbers.
  */
 static
 int
@@ -201,22 +1010,26 @@
 {
   struct CoffAuxSection * aux;
   struct CoffDebug   * coff;
-  struct CoffSymbol  * coff_sym;
-  struct CoffSymbol  * coff_symbol;
+  struct CoffFiles   * coff_files = NULL;
   struct CoffLinenum * coff_linetab;
   char		     * coff_strtab;
+  struct CoffSymbol  * coff_sym;
+  struct CoffSymbol  * coff_symbol;
+  struct CoffFiles   * curr_file = NULL;
   int		       i;
-  DBG_ADDR	       new_addr;
-  int		       rtn = FALSE;
-  int		       naux;
+  int		       j;
+  int		       k;
+  struct CoffLinenum * linepnt;
+  int		       linetab_indx;
   char		       namebuff[9];
   char		     * nampnt;
+  int		       naux;
+  DBG_ADDR	       new_addr;
   int		       nfiles = 0;
   int		       nfiles_alloc = 0;
-  struct CoffFiles   * coff_files = NULL;
-  struct CoffFiles   * curr_file = NULL;
-  char		     * this_file;
-  int		       j;
+  struct CoffFiles     orig_file;
+  int		       rtn = FALSE;
+  char		     * this_file = NULL;
 
   coff = (struct CoffDebug *) deefer->dbg_info;
 
@@ -224,6 +1037,8 @@
   coff_linetab = (struct CoffLinenum *) ((unsigned int) coff + coff->LinenumberOffset);
   coff_strtab = (char *) ((unsigned int) coff_symbol + 18*coff->N_Sym);
 
+  linetab_indx = 0;
+
   for(i=0; i < coff->N_Sym; i++ )
     {
       /*
@@ -252,6 +1067,15 @@
 	  curr_file->startaddr = 0xffffffff;
 	  curr_file->endaddr   = 0;
 	  curr_file->filename =  ((char *) coff_sym) + 18;
+	  curr_file->linetab_offset = -1;
+	  curr_file->linecnt = 0;
+	  curr_file->entries = NULL;
+	  curr_file->neps = curr_file->neps_alloc = 0;
+#if 0
+	  fprintf(stderr,"New file %s\n", curr_file->filename);
+#endif
+	  i += naux;
+	  continue;
 	}
 
       /*
@@ -262,9 +1086,67 @@
        */
       if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
 	  && (naux != 0)
+	  && (coff_sym->Type == 0)
 	  && (coff_sym->SectionNumber == 1) )
 	{
 	  aux = (struct CoffAuxSection *) ((unsigned int) coff_sym + 18);
+
+	  if( curr_file->linetab_offset != -1 )
+	    {
+#if 0
+	      fprintf(stderr, "Duplicating sect from %s: %x %x %x %d %d\n",
+		      curr_file->filename,
+		      aux->Length,
+		      aux->NumberOfRelocations,
+		      aux->NumberOfLinenumbers,
+		      aux->Number,
+		      aux->Selection);
+	      fprintf(stderr, "More sect %d %x %d %d %d\n", 
+		      coff_sym->SectionNumber,
+		      coff_sym->Value,
+		      coff_sym->Type,
+		      coff_sym->StorageClass,
+		      coff_sym->NumberOfAuxSymbols);
+#endif
+
+	      /*
+	       * Save this so we can copy bits from it.
+	       */
+	      orig_file = *curr_file;
+
+	      /*
+	       * Duplicate the file entry.  We have no way to describe
+	       * multiple text sections in our current way of handling things.
+	       */
+	      if( nfiles + 1 >= nfiles_alloc )
+		{
+		  nfiles_alloc += 10;
+		  coff_files = (struct CoffFiles *) realloc( coff_files,
+							     nfiles_alloc * sizeof(struct CoffFiles));
+		}
+	      curr_file = coff_files + nfiles;
+	      nfiles++;
+	      curr_file->startaddr = 0xffffffff;
+	      curr_file->endaddr   = 0;
+	      curr_file->filename = orig_file.filename;
+	      curr_file->linetab_offset = -1;
+	      curr_file->linecnt = 0;
+	      curr_file->entries = NULL;
+	      curr_file->neps = curr_file->neps_alloc = 0;
+	    }
+#if 0
+	  else
+	    {
+	      fprintf(stderr, "New text sect from %s: %x %x %x %d %d\n",
+		      curr_file->filename,
+		      aux->Length,
+		      aux->NumberOfRelocations,
+		      aux->NumberOfLinenumbers,
+		      aux->Number,
+		      aux->Selection);
+	    }
+#endif
+
 	  if( curr_file->startaddr > coff_sym->Value )
 	    {
 	      curr_file->startaddr = coff_sym->Value;
@@ -280,6 +1162,11 @@
 	      curr_file->endaddr = coff_sym->Value + aux->Length;
 	    }
 	  
+	  curr_file->linetab_offset = linetab_indx;
+	  curr_file->linecnt = aux->NumberOfLinenumbers;
+	  linetab_indx += aux->NumberOfLinenumbers;
+	  i += naux;
+	  continue;
 	}
 
       if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
@@ -302,9 +1189,28 @@
 	      nampnt = coff_strtab + coff_sym->N.Name.StrTaboff;
 	    }
 
+	  if( nampnt[0] == '_' )
+	    {
+	      nampnt++;
+	    }
+
 	  new_addr.seg = 0;
 	  new_addr.off = (int) (deefer->load_addr + coff_sym->Value);
-	  DEBUG_AddSymbol( nampnt, &new_addr, curr_file->filename );
+
+	  if( curr_file->neps + 1 >= curr_file->neps_alloc )
+	    {
+	      curr_file->neps_alloc += 10;
+	      curr_file->entries = (struct name_hash **) 
+		realloc( curr_file->entries, 
+			 curr_file->neps_alloc * sizeof(struct name_hash *));
+	    }
+#if 0
+	  fprintf(stderr,"\tAdding static symbol %s\n", nampnt);
+#endif
+	  curr_file->entries[curr_file->neps++] =
+	    DEBUG_AddSymbol( nampnt, &new_addr, this_file, SYM_WIN32 );
+	  i += naux;
+	  continue;
 	}
 
       if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
@@ -322,11 +1228,19 @@
 	      nampnt = coff_strtab + coff_sym->N.Name.StrTaboff;
 	    }
 
+
+	  if( nampnt[0] == '_' )
+	    {
+	      nampnt++;
+	    }
+
 	  new_addr.seg = 0;
 	  new_addr.off = (int) (deefer->load_addr + coff_sym->Value);
 
 #if 0
 	  fprintf(stderr, "%d: %x %s\n", i, new_addr.off, nampnt);
+
+	  fprintf(stderr,"\tAdding global symbol %s\n", nampnt);
 #endif
 
 	  /*
@@ -342,9 +1256,76 @@
 		  break;
 		}
 	    }
-	  DEBUG_AddSymbol( nampnt, &new_addr, this_file );
+	  if( coff_files[j].neps + 1 >= coff_files[j].neps_alloc )
+	    {
+	      coff_files[j].neps_alloc += 10;
+	      coff_files[j].entries = (struct name_hash **) 
+		realloc( coff_files[j].entries, 
+			 coff_files[j].neps_alloc * sizeof(struct name_hash *));
+	    }
+	  coff_files[j].entries[coff_files[j].neps++] =
+	    DEBUG_AddSymbol( nampnt, &new_addr, this_file, SYM_WIN32 );
+	  i += naux;
+	  continue;
+	}
+
+      if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL)
+          && (coff_sym->SectionNumber > 0) )
+	{
+	  /*
+	   * Similar to above, but for the case of data symbols.
+	   * These aren't treated as entrypoints.
+	   */
+	  if( coff_sym->N.Name.NotLong )
+	    {
+	      memcpy(namebuff, coff_sym->N.ShortName, 8);
+	      namebuff[8] = '\0';
+	      nampnt = &namebuff[0];
+	    }
+	  else
+	    {
+	      nampnt = coff_strtab + coff_sym->N.Name.StrTaboff;
+	    }
+
+
+	  if( nampnt[0] == '_' )
+	    {
+	      nampnt++;
+	    }
+
+	  new_addr.seg = 0;
+	  new_addr.off = (int) (deefer->load_addr + coff_sym->Value);
+
+#if 0
+	  fprintf(stderr, "%d: %x %s\n", i, new_addr.off, nampnt);
+
+	  fprintf(stderr,"\tAdding global data symbol %s\n", nampnt);
+#endif
+
+	  /*
+	   * Now we need to figure out which file this guy belongs to.
+	   */
+	  DEBUG_AddSymbol( nampnt, &new_addr, NULL, SYM_WIN32 );
+	  i += naux;
+	  continue;
 	}
 	  
+      if(    (coff_sym->StorageClass == IMAGE_SYM_CLASS_STATIC)
+	  && (naux == 0) )
+	{
+	  /*
+	   * Ignore these.  They don't have anything to do with
+	   * reality.
+	   */
+	  i += naux;
+	  continue;
+	}
+
+#if 0
+      fprintf(stderr,"Skipping unknown entry %d %d %d\n", coff_sym->StorageClass, 
+	      coff_sym->SectionNumber, naux);
+#endif
+
       /*
        * For now, skip past the aux entries.
        */
@@ -352,10 +1333,85 @@
       
     }
     
+  /*
+   * OK, we now should have a list of files, and we should have a list
+   * of entrypoints.  We need to sort the entrypoints so that we are
+   * able to tie the line numbers with the given functions within the
+   * file.
+   */
+  if( coff_files != NULL )
+    {
+      for(j=0; j < nfiles; j++)
+	{
+	  if( coff_files[j].entries != NULL )
+	    {
+	      qsort(coff_files[j].entries, coff_files[j].neps,
+		    sizeof(struct name_hash *), DEBUG_cmp_sym);
+	    }
+	}
+
+      /*
+       * Now pick apart the line number tables, and attach the entries
+       * to the given functions.
+       */
+      for(j=0; j < nfiles; j++)
+	{
+	  i = 0;
+	  for(k=0; k < coff_files[j].linecnt; k++)
+	    {
+	      /*
+	       * Another monstrosity caused by the fact that we are using
+	       * a 6 byte structure, and gcc wants to pad structures to 4 byte
+	       * boundaries.  Otherwise we could just index into an array.
+	       */
+	      linepnt = (struct CoffLinenum *) 
+		((unsigned int) coff_linetab + 
+		 6*(coff_files[j].linetab_offset + k));
+	      /*
+	       * If we have spilled onto the next entrypoint, then
+	       * bump the counter..
+	       */
+	      while(TRUE)
+		{
+		  DEBUG_GetSymbolAddr(coff_files[j].entries[i+1], &new_addr);
+		  if(   (i+1 < coff_files[j].neps)
+			&& (   ((unsigned int) deefer->load_addr + linepnt->VirtualAddr)
+			       >= new_addr.off) )
+		    {
+		      i++;
+		    }
+		  else
+		    {
+		      break;
+		    }
+		}
+
+	      /*
+	       * Add the line number.  This is always relative to the
+	       * start of the function, so we need to subtract that offset
+	       * first.
+	       */
+	      DEBUG_GetSymbolAddr(coff_files[j].entries[i], &new_addr);
+	      DEBUG_AddLineNumber(coff_files[j].entries[i], 
+				  linepnt->Linenum,
+				  (unsigned int) deefer->load_addr 
+				  + linepnt->VirtualAddr 
+				  - new_addr.off);
+	    }
+	}
+    }
+
   rtn = TRUE;
 
   if( coff_files != NULL )
     {
+      for(j=0; j < nfiles; j++)
+	{
+	  if( coff_files[j].entries != NULL )
+	    {
+	      free(coff_files[j].entries);
+	    }
+	}
       free(coff_files);
     }
 
@@ -363,15 +1419,887 @@
 
 }
 
+/*
+ * Process a codeview line number table.  Digestify the thing so that
+ * we can easily reference the thing when we process the rest of
+ * the information.
+ */
+static struct codeview_linetab_hdr *
+DEBUG_SnarfLinetab(char			     * linetab,
+		   int			       size)
+{
+  int				  file_segcount;
+  char				  filename[PATH_MAX];
+  unsigned int			* filetab;
+  char				* fn;
+  int				  i;
+  int				  k;
+  struct codeview_linetab_hdr   * lt_hdr;
+  unsigned int			* lt_ptr;
+  int				  nfile;
+  int				  nseg;
+  union any_size		  pnt;
+  union any_size		  pnt2;
+  struct startend		* start;
+  int				  this_seg;
+
+  /*
+   * Now get the important bits.
+   */
+  pnt = (union any_size) linetab;
+  nfile = *pnt.s++;
+  nseg = *pnt.s++;
+
+  filetab = (unsigned int *) pnt.c;
+
+  /*
+   * Now count up the number of segments in the file.
+   */
+  nseg = 0;
+  for(i=0; i<nfile; i++)
+    {
+      pnt2 = (union any_size) (linetab + filetab[i]);
+      nseg += *pnt2.s;
+    }
+
+  /*
+   * Next allocate the header we will be returning.
+   * There is one header for each segment, so that we can reach in
+   * and pull bits as required.
+   */
+  lt_hdr = (struct codeview_linetab_hdr *) 
+    xmalloc((nseg + 1) * sizeof(*lt_hdr));
+  if( lt_hdr == NULL )
+    {
+      goto leave;
+    }
+
+  memset(lt_hdr, 0, sizeof(*lt_hdr) * (nseg+1));
+
+  /*
+   * Now fill the header we will be returning, one for each segment.
+   * Note that this will basically just contain pointers into the existing
+   * line table, and we do not actually copy any additional information
+   * or allocate any additional memory.
+   */
+
+  this_seg = 0;
+  for(i=0; i<nfile; i++)
+    {
+      /*
+       * Get the pointer into the segment information.
+       */
+      pnt2 = (union any_size) (linetab + filetab[i]);
+      file_segcount = *pnt2.s;
+
+      pnt2.ui++;
+      lt_ptr = (unsigned int *) pnt2.c;
+      start = (struct startend *) (lt_ptr + file_segcount);
+
+      /*
+       * Now snarf the filename for all of the segments for this file.
+       */
+      fn = (unsigned char *) (start + file_segcount);
+      memset(filename, 0, sizeof(filename));
+      memcpy(filename, fn + 1, *fn);
+      fn = strdup(filename);
+
+      for(k = 0; k < file_segcount; k++, this_seg++)
+	{
+	  pnt2 = (union any_size) (linetab + lt_ptr[k]);
+	  lt_hdr[this_seg].start      = start[k].start;
+	  lt_hdr[this_seg].end	      = start[k].end;
+	  lt_hdr[this_seg].sourcefile = fn;
+	  lt_hdr[this_seg].segno      = *pnt2.s++;
+	  lt_hdr[this_seg].nline      = *pnt2.s++;
+	  lt_hdr[this_seg].offtab     =  pnt2.ui;
+	  lt_hdr[this_seg].linetab    = (unsigned short *) 
+	    (pnt2.ui + lt_hdr[this_seg].nline);
+	}
+    }
+
+leave:
+
+  return lt_hdr;
+
+}
+
+static int
+DEBUG_SnarfCodeView(      struct deferred_debug_info * deefer,
+			  char			     * cv_data,
+			  int			       size,
+			  struct codeview_linetab_hdr * linetab)
+{
+  struct name_hash	* curr_func = NULL;
+  struct wine_locals	* curr_sym = NULL;
+  int			  i;
+  int			  j;
+  int			  len;
+  DBG_ADDR		  new_addr;
+  int			  nsect;
+  union any_size	  ptr;
+  struct pe_segment_table * sectp;
+  union	codeview_symbol	* sym;
+  char			  symname[PATH_MAX];
+  struct name_hash	* thunk_sym = NULL;
+
+  ptr = (union any_size) cv_data;
+  nsect = deefer->nsect;
+  sectp = deefer->sectp;
+
+  /*
+   * Skip over the first word.  Don't really know what it means, but
+   * it is useless.
+   */
+  ptr.ui++;
+
+  /*
+   * Loop over the different types of records and whenever we
+   * find something we are interested in, record it and move on.
+   */
+  while( ptr.c - cv_data < size )
+    {
+      sym = (union codeview_symbol *) ptr.c;
+
+      if( sym->generic.len - sizeof(int) == (ptr.c - cv_data) )
+	{
+	  /*
+	   * This happens when we have indirect symbols that VC++ 4.2
+	   * sometimes uses when there isn't a line number table.
+	   * We ignore it - we will process and enter all of the
+	   * symbols in the global symbol table anyways, so there
+	   * isn't much point in keeping track of all of this crap.
+	   */
+	  break;
+	}
+
+      memset(symname, 0, sizeof(symname));
+      switch(sym->generic.id)
+	{
+	case S_GDATA32:
+	case S_LDATA32:
+	case S_PUB32:
+	  /*
+	   * First, a couple of sanity checks.
+	   */
+	  if( sym->data.namelen == 0 )
+	    {
+	      break;
+	    }
+
+	  if( sym->data.seg == 0 || sym->data.seg > nsect )
+	    {
+	      break;
+	    }
+
+	  /*
+	   * Global and local data symbols.  We don't associate these
+	   * with any given source file.
+	   */
+
+	  memcpy(symname, sym->data.name, sym->data.namelen);
+	  new_addr.seg = 0;
+	  new_addr.type = DEBUG_GetCVType(sym->data.symtype);
+	  new_addr.off = (unsigned int) deefer->load_addr + 
+	    sectp[sym->data.seg - 1].Virtual_Address + 
+	    sym->data.offset;
+	  DEBUG_AddSymbol( symname, &new_addr, NULL, SYM_WIN32 | SYM_DATA );
+	  break;
+	case S_THUNK32:
+	  /*
+	   * Sort of like a global function, but it just points
+	   * to a thunk, which is a stupid name for what amounts to
+	   * a PLT slot in the normal jargon that everyone else uses.
+	   */
+	  memcpy(symname, sym->thunk.name, sym->thunk.namelen);
+	  new_addr.seg = 0;
+	  new_addr.type = NULL;
+	  new_addr.off = (unsigned int) deefer->load_addr + 
+	    sectp[sym->thunk.segment - 1].Virtual_Address + 
+	    sym->thunk.offset;
+	  thunk_sym = DEBUG_AddSymbol( symname, &new_addr, NULL, 
+				       SYM_WIN32 | SYM_FUNC);
+	  DEBUG_SetSymbolSize(thunk_sym, sym->thunk.thunk_len);
+	  break;
+	case S_GPROC32:
+	case S_LPROC32:
+	  /*
+	   * Global and static functions.
+	   */
+	  memcpy(symname, sym->proc.name, sym->proc.namelen);
+	  new_addr.seg = 0;
+	  new_addr.type = DEBUG_GetCVType(sym->proc.proctype);
+	  new_addr.off = (unsigned int) deefer->load_addr + 
+	    sectp[sym->proc.segment - 1].Virtual_Address + 
+	    sym->proc.offset;
+	  /*
+	   * See if we can find a segment that this goes with.  If so,
+	   * it means that we also may have line number information
+	   * for this function.
+	   */
+	  for(i=0; linetab[i].linetab != NULL; i++)
+	    {
+	      if(     ((unsigned int) deefer->load_addr 
+		       + sectp[linetab[i].segno - 1].Virtual_Address 
+		       + linetab[i].start <= new_addr.off)
+		  &&  ((unsigned int) deefer->load_addr 
+		       + sectp[linetab[i].segno - 1].Virtual_Address 
+		       + linetab[i].end > new_addr.off) )
+		{
+		  break;
+		}
+	    }
+
+ 	  DEBUG_Normalize(curr_func);
+	  if( linetab[i].linetab == NULL )
+	    {
+	      curr_func = DEBUG_AddSymbol( symname, &new_addr, NULL,
+					   SYM_WIN32 | SYM_FUNC);
+	    }
+	  else
+	    {
+	      /*
+	       * First, create the entry.  Then dig through the linetab
+	       * and add whatever line numbers are appropriate for this
+	       * function.
+	       */
+	      curr_func = DEBUG_AddSymbol( symname, &new_addr, 
+					   linetab[i].sourcefile,
+					   SYM_WIN32 | SYM_FUNC);
+	      for(j=0; j < linetab[i].nline; j++)
+		{
+		  if( linetab[i].offtab[j] >= sym->proc.offset 
+		      && linetab[i].offtab[j] < sym->proc.offset 
+		      + sym->proc.proc_len )
+		    {
+		      DEBUG_AddLineNumber(curr_func, linetab[i].linetab[j],
+					  linetab[i].offtab[j] - sym->proc.offset);
+		    }
+		}
+
+	    }
+
+	  /*
+	   * Add information about where we should set breakpoints
+	   * in this function.
+	   */
+	  DEBUG_SetSymbolBPOff(curr_func, sym->proc.debug_start);
+	  DEBUG_SetSymbolSize(curr_func, sym->proc.proc_len);
+	  break;
+	case S_BPREL32:
+	  /*
+	   * Function parameters and stack variables.
+	   */
+	  memcpy(symname, sym->stack.name, sym->stack.namelen);
+	  curr_sym = DEBUG_AddLocal(curr_func, 
+			 0, 
+			 sym->stack.offset, 
+			 0, 
+			 0, 
+			 symname);
+	  DEBUG_SetLocalSymbolType(curr_sym, DEBUG_GetCVType(sym->stack.symtype));
+	  
+	  break;
+	default:
+	  break;
+	}
+
+      /*
+       * Adjust pointer to point to next entry, rounding up to a word
+       * boundary.  MS preserving alignment?  Stranger things have
+       * happened.
+       */
+      if( sym->generic.id == S_PROCREF
+	  || sym->generic.id == S_DATAREF
+	  || sym->generic.id == S_UNKNOWN )
+	{
+	  len = (sym->generic.len + 3) & ~3;
+	  len += ptr.c[16] + 1;
+	  ptr.c += (len + 3) & ~3;
+	}
+      else
+	{
+	  ptr.c += (sym->generic.len + 3) & ~3;
+	}
+    }
+
+  if( linetab != NULL )
+    {
+      free(linetab);
+    }
+
+  return TRUE;
+}
+
+
+/*
+ * Process PDB file which contains debug information.
+ *
+ * These are really weird beasts.  They are intended to be incrementally
+ * updated by the incremental linker, and this means that you need to 
+ * be able to remove and add information.  Thus the PDB file is sort of
+ * like a block structured device, with a freelist and lists of extent numbers
+ * that are used to get the relevant pieces.  In all cases seen so far, the
+ * blocksize is always 0x400 bytes.  The header has a field which apparently
+ * holds the blocksize, so if it ever changes we are safe.
+ *
+ * In general, every time we need to extract something from the pdb file,
+ * it is easier to copy it into another buffer so we have the information
+ * in one contiguous block rather than attempt to try and keep track of when
+ * we need to grab another extent from the pdb file.
+ *
+ * The thing that is a real pain about some MS stuff is that they choose
+ * data structures which are not representable in C.  Thus we have to
+ * hack around and diddle pointers.
+ */
+/* static */
+int
+DEBUG_ProcessPDBFile(struct deferred_debug_info * deefer, char * full_filename)
+{
+  char			      * addr = (char *) 0xffffffff;
+  unsigned int			blocksize;
+  unsigned int			bufflen = 0;
+  char			      * buffer = NULL;
+  unsigned short	      * extent_table;
+  int				fd = -1;
+  struct file_ent	      * fent;
+  char			      * filename;
+  struct file_list	      * filelist = NULL;
+  unsigned int			gsym_record = 0;
+  char			      * gsymtab = NULL;
+  struct filetab_hdr	      * hd;
+  int				i;
+  int				j;
+  unsigned int			last_extent;
+  struct codeview_linetab_hdr * linetab;
+  unsigned int			nblocks;
+  unsigned int			npair;
+  unsigned int			offset;
+  struct codeview_pdb_hdr     * pdbhdr;
+  unsigned int		      * pnt;
+  struct stat			statbuf;
+  int				status;
+  unsigned short	      * table;
+  char			      * toc;
+  unsigned int			toc_blocks;
+  
+  /*
+   * FIXME - we should use some kind of search path mechanism to locate
+   * PDB files.  Right now we just look in the current working directory,
+   * which works much of the time, I guess.  Ideally we should be able to
+   * map the filename back using the settings in wine.ini and perhaps
+   * we could find it there.  This bit of coding is left as an exercise
+   * for the reader. :-).
+   */
+  filename = strrchr(full_filename, '\\');
+  if( filename == NULL )
+    {
+      filename = full_filename;
+    }
+  else
+    {
+      filename++;
+    }
+
+  status = stat(filename, &statbuf);
+  if( status == -1 )
+    {
+      fprintf(stderr, "Unable to open .PDB file %s\n", filename);
+      goto leave;
+    }
+
+  /*
+   * Now open the file, so that we can mmap() it.
+   */
+  fd = open(filename, O_RDONLY);
+  if( fd == -1 )
+    {
+      fprintf(stderr, "Unable to open .DBG file %s\n", filename);
+      goto leave;
+    }
+
+
+  /*
+   * Now mmap() the file.
+   */
+  addr = mmap(0, statbuf.st_size, PROT_READ, 
+	      MAP_PRIVATE, fd, 0);
+
+  /*
+   * Now that we have the formalities over and done with, we need
+   * to find the table of contents for the PDB file.
+   */
+  pdbhdr = (struct codeview_pdb_hdr *) addr;
+  blocksize = pdbhdr->blocksize;
+  last_extent = (statbuf.st_size + blocksize - 1) / blocksize;
+
+  /*
+   * The TOC itself isn't always contiguous, so we need to extract a few
+   * extents from the file to form the TOC.
+   */
+  toc_blocks = (pdbhdr->toc_len + blocksize - 1) / blocksize;
+  toc = (char *) xmalloc(toc_blocks * blocksize);
+  table = pdbhdr->toc_ext;
+  for(i=0; i < toc_blocks; i++)
+    {
+      memcpy(toc + blocksize*i, addr + table[i]*blocksize, blocksize);
+    }
+
+  /*
+   * Next build our own table which will have the size and extent block
+   * list for each record in the PDB file.
+   *
+   * The TOC starts out with the number of files.  Then it is followed by
+   * (npair * 2*sizeof(int)) bytes of information, which are pairs of ints.
+   * The first one is the size of the record (in bytes), and the second one
+   * is something else which I haven't figured out yet.
+   */
+  pnt = (unsigned int *) toc;
+  npair = *pnt++;
+  extent_table = (unsigned short *) ((unsigned int) toc +
+				     npair * 2 * sizeof(int) + sizeof(int));
+
+  /*
+   * Sanity check.
+   */
+  if( sizeof(int) + 2*sizeof(int)*npair > pdbhdr->toc_len )
+    {
+      goto leave;
+    }
+  
+  filelist = (struct file_list *) xmalloc(npair * sizeof(*filelist));
+  if( filelist == NULL )
+    {
+      goto leave;
+    }
+  memset(filelist, 0, npair * sizeof(*filelist));
+
+  nblocks = 0;
+  for(i=0; i < npair; i++)
+    {
+      filelist[i].record_len = pnt[i*2];
+      filelist[i].nextents   = (filelist[i].record_len + blocksize - 1) 
+	/ blocksize;
+      filelist[i].extent_list = extent_table + nblocks;
+      nblocks += filelist[i].nextents;
+
+      /*
+       * These get filled in later when we parse one of the records.
+       */
+      filelist[i].linetab_offset = 0;
+      filelist[i].linetab_len = 0;
+    }
+
+  /*
+   * OK, now walk through the various records and pick out the bits we
+   * really want to see.  Some of the records are extra special, and
+   * we need to handle these a little bit differently.
+   */
+  for(i=0; i < npair; i++)
+    {
+      if( filelist[i].record_len == 0xffffffff )
+	{
+	  continue;
+	}
+
+      /*
+       * Make sure our buffer is large enough to hold the record.
+       */
+      if( bufflen < filelist[i].nextents * blocksize )
+	{
+	  bufflen = filelist[i].nextents * blocksize;
+	  buffer = (char *) realloc(buffer, bufflen);
+	}
+
+      /*
+       * Do this just for completeness.  It makes debugging easier
+       * if we have a clean indication of where the record ends.
+       */
+      memset(buffer, 0, filelist[i].nextents * blocksize);
+
+      /*
+       * Next, build the record using the extent list.
+       */
+      for(j=0; j < filelist[i].nextents; j++)
+	{
+	  memcpy(buffer + j * blocksize,
+		 addr + filelist[i].extent_list[j] * blocksize,
+		 blocksize);
+	}
+
+      pnt = (unsigned int *) buffer;
+
+      /*
+       * OK, now figure out what to do with it.
+       */
+
+      /*
+       * Always ignore the first entry.  It seems to contain a backup copy
+       * of the TOC (the last time the file was modified??)
+       */
+      if( i == 0 )
+	{
+	  continue;
+	}
+
+      /* 
+       * The second entry as a id block.  It contains a magic number
+       * to identify the compiler, plus it also contains the timestamp
+       * which must match the timestamp in the executable.  
+       */
+      if( i == 1 )
+	{
+
+	  if( ((*pnt != 19950623) && (*pnt != 19950814))
+	      || (filelist[i].record_len != 0x24)
+	      || (pnt[1] != ((struct CodeViewDebug *)(deefer->dbg_info))->cv_timestamp) )
+	    {
+	      goto leave;
+	    }
+	}
+
+      /*
+       * The third entry contains pointers to the global symbol table,
+       * plus it also contains additional information about each record
+       * in the PDB file.
+       */
+      if( i == 3 )
+	{
+	  hd = (struct filetab_hdr *) buffer;
+
+	  gsym_record = hd->gsym_file;
+	  gsymtab = (char *) xmalloc( filelist[gsym_record].nextents 
+				      * blocksize);
+	  memset(gsymtab, 0, filelist[gsym_record].nextents * blocksize);
+	  
+	  for(j=0; j < filelist[gsym_record].nextents; j++)
+	    {
+	      memcpy(gsymtab + j * blocksize,
+		     addr + filelist[gsym_record].extent_list[j] * blocksize,
+		     blocksize);
+	    }
+
+	  /*
+	   * This record also contains information about where in the
+	   * remaining records we will be able to find the start of the
+	   * line number table.  We could locate that bit using heuristics,
+	   * but since we have the info handy, we might as well use it.
+	   */
+	  offset = sizeof(*hd);
+	  while(1==1)
+	    {
+	      fent = (struct file_ent *) (buffer + offset);
+	      if( offset > hd->ftab_len )
+		{
+		  break;
+		}
+
+	      if( fent->file_number == 0 || fent->file_number >= npair )
+		{
+ 		  break;
+		}
+
+	      filelist[fent->file_number].linetab_offset = 
+		fent->linetab_offset;
+	      filelist[fent->file_number].linetab_len = 
+		fent->linetab_len;
+	      /*
+	       * Figure out the offset of the next entry.
+	       * There is a fixed part of the record and a variable
+	       * length filename which we must also skip past.
+	       */
+	      offset += ((unsigned int) &fent->filename - (unsigned int) fent)
+		+ strlen(fent->filename) + 1;
+	      offset += strlen(buffer+offset) + 1;
+	      offset = (offset + 3) & ~3;
+	    }
+	}
+      
+
+      /*
+       * Two different magic numbers used as dates.
+       * These indicate the 'type' table.
+       */
+      if(       *pnt == 19950410
+	     || *pnt == 19951122 )
+	{
+	  DEBUG_ParseTypeTable(buffer, filelist[i].record_len);
+	  continue;
+	}
+
+      /*
+       * This is something we really want to look at, since it contains
+       * real debug info.  Anything that doesn't match this can be
+       * ignored for now.
+       */
+      if( *pnt == 1 )
+	{
+	  /*
+	   * First, snag the line table, if we have one.  This always
+	   * occurs at the end of the record, so we take the linetab
+	   * offset as the end of the normal part of the record.
+	   */
+	  linetab = NULL;
+	  if( filelist[i].linetab_len != 0 )
+	    {
+	      linetab = DEBUG_SnarfLinetab(buffer + filelist[i].linetab_offset,
+					   filelist[i].linetab_len);
+	      DEBUG_SnarfCodeView(deefer, buffer,
+				  filelist[i].linetab_offset,
+				  linetab);
+	    }
+	  else
+	    {
+	      DEBUG_SnarfCodeView(deefer, buffer,
+				  filelist[i].record_len,
+				  linetab);
+	    }
+	  continue;
+	}
+    }
+
+  /*
+   * Finally, process the global symbol table itself.  There isn't
+   * a line number component to this, so we just toss everything
+   * into the mix and it all should work out.
+   */
+  if( gsym_record != 0 )
+    {
+      DEBUG_SnarfCodeView(deefer, gsymtab - sizeof(int), 
+			  filelist[gsym_record].record_len,
+			  NULL);
+    }
+  
+leave:
+
+  if( gsymtab != NULL )
+    {
+      free(gsymtab);
+      gsymtab = NULL;
+    }
+
+  if( buffer != NULL )
+    {
+      free(buffer);
+    }
+
+  if( filelist != NULL )
+    {
+      free(filelist);
+    }
+
+  if( addr != (char *) 0xffffffff )
+    {
+      munmap(addr, statbuf.st_size);
+    }
+
+  if( fd != -1 )
+    {
+      close(fd);
+    }
+
+  return TRUE;
+}
+
+/*
+ * Process DBG file which contains debug information.
+ */
+/* static */
+int
+DEBUG_ProcessDBGFile(struct deferred_debug_info * deefer, char * filename)
+{
+  char			      * addr = (char *) 0xffffffff;
+  char			      * codeview;
+  struct CV4_DirHead	      * codeview_dir;
+  struct CV4_DirEnt	      * codeview_dent;
+  struct PE_Debug_dir	      * dbghdr;
+  struct deferred_debug_info    deefer2;
+  int				fd = -1;
+  int				i;
+  int				j;
+  struct codeview_linetab_hdr * linetab;
+  int				nsect;
+  struct PE_DBG_FileHeader    * pdbg = NULL;
+  struct pe_segment_table     * sectp;
+  struct stat			statbuf;
+  int				status;
+  
+  status = stat(filename, &statbuf);
+  if( status == -1 )
+    {
+      fprintf(stderr, "Unable to open .DBG file %s\n", filename);
+      goto leave;
+    }
+
+  /*
+   * Now open the file, so that we can mmap() it.
+   */
+  fd = open(filename, O_RDONLY);
+  if( fd == -1 )
+    {
+      fprintf(stderr, "Unable to open .DBG file %s\n", filename);
+      goto leave;
+    }
+
+
+  /*
+   * Now mmap() the file.
+   */
+  addr = mmap(0, statbuf.st_size, PROT_READ, 
+	      MAP_PRIVATE, fd, 0);
+
+  pdbg = (struct PE_DBG_FileHeader *) addr;
+
+  if( pdbg->TimeDateStamp != deefer->dbgdir->timestamp )
+    {
+      fprintf(stderr, "Warning - %s has incorrect internal timestamp\n",
+	      filename);
+      goto leave;
+   }
+
+  fprintf(stderr, "Processing symbols from %s...\n", filename);
+
+  dbghdr = (struct PE_Debug_dir *) (  addr + sizeof(*pdbg) 
+		 + pdbg->NumberOfSections * sizeof(struct pe_segment_table) 
+		 + pdbg->ExportedNamesSize);
+
+  sectp = (struct pe_segment_table *) ((char *) pdbg + sizeof(*pdbg));
+  nsect = pdbg->NumberOfSections;
+
+  for( i=0; i < pdbg->DebugDirectorySize / sizeof(*pdbg); i++, dbghdr++ )
+    {
+      switch(dbghdr->type)
+		{
+		case IMAGE_DEBUG_TYPE_COFF:
+		  /*
+		   * Dummy up a deferred debug header to handle the
+		   * COFF stuff embedded within the DBG file.
+		   */
+		  memset((char *) &deefer2, 0, sizeof(deefer2));
+		  deefer2.dbg_info = (addr + dbghdr->dbgoff);
+		  deefer2.dbg_size = dbghdr->dbgsize;
+		  deefer2.load_addr = deefer->load_addr;
+
+		  DEBUG_ProcessCoff(&deefer2);
+		  break;
+		case IMAGE_DEBUG_TYPE_CODEVIEW:
+		  /*
+		   * This is the older format by which codeview stuff is 
+		   * stored, known as the 'NB09' format.  Newer executables
+		   * and dlls created by VC++ use PDB files instead, which
+		   * have lots of internal similarities, but the overall
+		   * format and structure is quite different.
+		   */
+		  codeview = (addr + dbghdr->dbgoff);
+
+		  /*
+		   * The first thing in the codeview section should be
+		   * an 'NB09' identifier.  As a sanity check, make sure
+		   * it is there.
+		   */
+		  if( *((unsigned int*) codeview) != 0x3930424e )
+		    {
+		      break;
+		    }
+		  
+		  /*
+		   * Next we need to find the directory.  This is easy too.
+		   */
+		  codeview_dir = (struct CV4_DirHead *) 
+		    (codeview + ((unsigned int*) codeview)[1]);
+
+		  /*
+		   * Some more sanity checks.  Make sure that everything
+		   * is as we expect it.
+		   */
+		  if( codeview_dir->next_offset != 0 
+		      || codeview_dir->dhsize != sizeof(*codeview_dir)
+		      || codeview_dir->desize != sizeof(*codeview_dent) )
+		    {
+		      break;
+		    }
+		  codeview_dent = (struct CV4_DirEnt *) (codeview_dir + 1);
+
+		  for(j=0; j < codeview_dir->ndir; j++, codeview_dent++)
+		    {
+		      if( codeview_dent->subsect_number == sstAlignSym )
+			{
+			  /*
+			   * Check the previous entry.  If it is a
+			   * sstSrcModule, it contains the line number
+			   * info for this file.
+			   */
+			  linetab = NULL;
+			  if( codeview_dent[1].module_number == codeview_dent[0].module_number
+			      && codeview_dent[1].subsect_number == sstSrcModule )
+			    {
+			      linetab = DEBUG_SnarfLinetab(
+					   codeview + codeview_dent[1].offset,
+					   codeview_dent[1].size);
+			    }
+
+			  if( codeview_dent[-1].module_number == codeview_dent[0].module_number
+			      && codeview_dent[-1].subsect_number == sstSrcModule )
+			    {
+			      linetab = DEBUG_SnarfLinetab(
+					   codeview + codeview_dent[-1].offset,
+					   codeview_dent[-1].size);
+			    }
+			  /*
+			   * Now process the CV stuff.
+			   */
+			  DEBUG_SnarfCodeView(deefer, 
+					      codeview + codeview_dent->offset,
+					      codeview_dent->size,
+					      linetab);
+			}
+		    }
+
+		  break;
+		default:
+		  break;
+		}
+    }
+leave:
+
+  if( addr != (char *) 0xffffffff )
+    {
+      munmap(addr, statbuf.st_size);
+    }
+
+  if( fd != -1 )
+    {
+      close(fd);
+    }
+
+  return TRUE;
+}
+
 int
 DEBUG_ProcessDeferredDebug()
 {
   struct deferred_debug_info * deefer;
   struct CodeViewDebug	     * cvd;
   struct MiscDebug	     * misc;
+  char			     * filename;
+  int			       last_proc = -1;
+
+  DEBUG_InitCVDataTypes();
 
   for(deefer = dbglist; deefer; deefer = deefer->next)
     {
+      if( deefer->loaded )
+	{
+	  continue;
+	}
+
+      if( last_proc != deefer->dbg_index )
+	{
+	  fprintf(stderr, "Loading symbols from Win32 file %s...\n", 
+		  deefer->module_name);
+	  last_proc = deefer->dbg_index;
+	}
+
       switch(deefer->dbgdir->type)
 	{
 	case IMAGE_DEBUG_TYPE_COFF:
@@ -389,18 +2317,47 @@
 	   * This is a pointer to a PDB file of some sort.
 	   */
 	  cvd = (struct CodeViewDebug *) deefer->dbg_info;
+
+	  if( strcmp(cvd->cv_nbtype, "NB10") != 0 )
+	    {
+	      /*
+	       * Whatever this is, we don't know how to deal with
+	       * it yet.
+	       */
+	      break;
+	    }
+	  DEBUG_ProcessPDBFile(deefer, cvd->cv_name);
 #if 0
 	  fprintf(stderr, "Processing PDB file %s\n", cvd->cv_name);
 #endif
 	  break;
 	case IMAGE_DEBUG_TYPE_MISC:
 	  /*
-	   * A pointer to a .DBG file of some sort.
+	   * A pointer to a .DBG file of some sort.  These files
+	   * can contain either CV4 or COFF information.  Open
+	   * the file, and try to do the right thing with it.
 	   */
 	  misc = (struct MiscDebug *) deefer->dbg_info;
-#if 0
-	  fprintf(stderr, "Processing DBG file %s\n", misc->Data);
-#endif
+
+	  filename = strrchr((char *) &misc->Data, '.');
+
+	  /*
+	   * Ignore the file if it doesn't have a .DBG extension.
+	   */
+	  if(    (filename == NULL)
+	      || (    (strcmp(filename, ".dbg") != 0)
+	           && (strcmp(filename, ".DBG") != 0)) )
+	    {
+	      break;
+	    }
+
+	  filename = (char *) &misc->Data;
+
+	  /*
+	   * Do the dirty deed...
+	   */
+	  DEBUG_ProcessDBGFile(deefer, filename);
+      
 	  break;
 	default:
 	  /*
@@ -410,4 +2367,34 @@
 	}
     }
   return TRUE;
+
 }
+
+/***********************************************************************
+ *           DEBUG_InfoShare
+ *
+ * Display shared libarary information.
+ */
+void DEBUG_InfoShare(void)
+{
+  struct deferred_debug_info * deefer;
+
+  fprintf(stderr,"Address\t\tModule\tName\n");
+
+  for(deefer = dbglist; deefer; deefer = deefer->next)
+    {
+      if( deefer->pe == NULL )
+	{
+	  fprintf(stderr,"0x%8.8x\t(ELF)\t%s\n", 
+		  (unsigned int) deefer->load_addr,
+		  deefer->module_name);
+	}
+      else
+	{
+	  fprintf(stderr,"0x%8.8x\t(Win32)\t%s\n", 
+		  (unsigned int) deefer->load_addr,
+		  deefer->module_name);
+	}
+    }
+}
+
diff --git a/debugger/registers.c b/debugger/registers.c
index 2ecaf6a..7c68f6a 100644
--- a/debugger/registers.c
+++ b/debugger/registers.c
@@ -48,6 +48,41 @@
 }
 
 
+int
+DEBUG_PrintRegister(enum debug_regs reg)
+{
+    switch(reg)
+    {
+        case REG_EAX: fprintf(stderr, "%%eax"); break;
+        case REG_EBX: fprintf(stderr, "%%ebx"); break;
+        case REG_ECX: fprintf(stderr, "%%ecx"); break;
+        case REG_EDX: fprintf(stderr, "%%edx"); break;
+        case REG_ESI: fprintf(stderr, "%%esi"); break;
+        case REG_EDI: fprintf(stderr, "%%edi"); break;
+        case REG_EBP: fprintf(stderr, "%%ebp"); break;
+        case REG_EFL: fprintf(stderr, "%%efl"); break;
+        case REG_EIP: fprintf(stderr, "%%eip"); break;
+        case REG_ESP: fprintf(stderr, "%%esp"); break;
+        case REG_AX:  fprintf(stderr, "%%ax"); break;
+        case REG_BX:  fprintf(stderr, "%%bx"); break;
+        case REG_CX:  fprintf(stderr, "%%cx"); break;
+        case REG_DX:  fprintf(stderr, "%%dx"); break;
+        case REG_SI:  fprintf(stderr, "%%si"); break;
+        case REG_DI:  fprintf(stderr, "%%di"); break;
+        case REG_BP:  fprintf(stderr, "%%bp"); break;
+        case REG_FL:  fprintf(stderr, "%%fl"); break;
+        case REG_IP:  fprintf(stderr, "%%ip"); break;
+        case REG_SP:  fprintf(stderr, "%%sp"); break;
+        case REG_CS:  fprintf(stderr, "%%cs"); break;
+        case REG_DS:  fprintf(stderr, "%%ds"); break;
+        case REG_ES:  fprintf(stderr, "%%es"); break;
+        case REG_SS:  fprintf(stderr, "%%ss"); break;
+        case REG_FS:  fprintf(stderr, "%%fs"); break;
+        case REG_GS:  fprintf(stderr, "%%gs"); break;
+    }
+    return TRUE;
+}
+
 /***********************************************************************
  *           DEBUG_GetRegister
  *
diff --git a/debugger/source.c b/debugger/source.c
new file mode 100644
index 0000000..d80d386
--- /dev/null
+++ b/debugger/source.c
@@ -0,0 +1,433 @@
+/*
+ * File source.c - source file handling for internal debugger.
+ *
+ * Copyright (C) 1997, Eric Youngdale.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <strings.h>
+#include <unistd.h>
+#include <malloc.h>
+
+#include "win.h"
+#include "pe_image.h"
+#include "peexe.h"
+#include "debugger.h"
+#include "peexe.h"
+#include "xmalloc.h"
+
+struct searchlist
+{
+  char * path;
+  struct searchlist * next;
+};
+
+
+struct open_filelist
+{
+  char			* path;
+  char			* real_path;
+  struct open_filelist  * next;
+  unsigned int		  size;
+  signed int		  nlines;
+  unsigned int		* linelist;
+};
+
+static struct open_filelist * ofiles;
+
+static struct searchlist * listhead;
+static char DEBUG_current_sourcefile[PATH_MAX];
+static int DEBUG_start_sourceline = -1;
+static int DEBUG_end_sourceline = -1;
+
+void
+DEBUG_ShowDir()
+{
+  struct searchlist * sl;
+
+  fprintf(stderr,"Search list :\n");
+  for(sl = listhead; sl; sl = sl->next)
+    {
+      fprintf(stderr, "\t%s\n", sl->path);
+    }
+  fprintf(stderr, "\n");
+}
+
+void
+DEBUG_AddPath(const char * path)
+{
+  struct searchlist * sl;
+
+  sl = (struct searchlist *) xmalloc(sizeof(struct searchlist));
+  if( sl == NULL )
+    {
+      return;
+    }
+
+  sl->next = listhead;
+  sl->path = xstrdup(path);
+  listhead = sl;
+}
+
+void
+DEBUG_NukePath()
+{
+  struct searchlist * sl;
+  struct searchlist * nxt;
+
+  for(sl = listhead; sl; sl = nxt)
+    {
+      nxt = sl->next;
+      free(sl->path);
+      free(sl);
+    }
+
+  listhead = NULL;
+}
+
+static
+void
+DEBUG_DisplaySource(char * sourcefile, int start, int end)
+{
+  char			      * addr;
+  char			        buffer[1024];
+  int				fd;
+  int				i;
+  struct open_filelist	      * ol;
+  int				nlines;
+  char			      * pnt;
+  struct searchlist	      * sl;
+  struct stat			statbuf;
+  int				status;
+  char				tmppath[PATH_MAX];
+
+  /*
+   * First see whether we have the file open already.  If so, then
+   * use that, otherwise we have to try and open it.
+   */
+  for(ol = ofiles; ol; ol = ol->next)
+    {
+      if( strcmp(ol->path, sourcefile) == 0 )
+	{
+	  break;
+	}
+    }
+
+  if( ol == NULL )
+    {
+      /*
+       * Try again, stripping the path from the opened file.
+       */
+      for(ol = ofiles; ol; ol = ol->next)
+	{
+	  pnt = strrchr(ol->path, '/');
+	  if( pnt != NULL && strcmp(pnt + 1, sourcefile) == 0 )
+	    {
+	      break;
+	    }
+	}
+      
+    }
+
+  if( ol == NULL )
+    {
+      /*
+       * See if this is a DOS style name or not.
+       */
+      pnt = strchr(sourcefile, '\\' );
+      if( pnt == NULL )
+	{
+	  pnt = strchr(sourcefile, '/' );
+	  if( pnt == NULL )
+	    {
+	      pnt = sourcefile;
+	    }
+	}
+
+      /*
+       * Crapola.  We need to try and open the file.
+       */
+      status = stat(sourcefile, &statbuf);
+      if( status != -1 )
+	{
+	  strcpy(tmppath, sourcefile);
+	}
+      else
+	{
+	  for(sl = listhead; sl; sl = sl->next)
+	    {
+	      strcpy(tmppath, sl->path);
+	      if( tmppath[strlen(tmppath)-1] != '/' )
+		{
+		  strcat(tmppath, "/");
+		}
+	      /*
+	       * Now append the base file name.
+	       */
+	      strcat(tmppath, pnt);
+	      
+	      status = stat(tmppath, &statbuf);
+	      if( status != -1 )
+		{
+		  break;
+		}
+	    }
+	  
+	  if( sl == NULL )
+	    {
+	      /*
+	       * Still couldn't find it.  Ask user for path to add.
+	       */
+	      fprintf(stderr,"Enter path to file %s: ", sourcefile);
+	      fgets(tmppath, sizeof(tmppath), stdin);
+	      
+	      if( tmppath[strlen(tmppath)-1] == '\n' )
+		{
+		  tmppath[strlen(tmppath)-1] = '\0';
+		}
+	      
+	      if( tmppath[strlen(tmppath)-1] != '/' )
+		{
+		  strcat(tmppath, "/");
+		}
+	      /*
+	       * Now append the base file name.
+	       */
+	      strcat(tmppath, pnt);
+	      
+	      status = stat(tmppath, &statbuf);
+	      if( status == -1 )
+		{
+		  /*
+		   * OK, I guess the user doesn't really want to see it
+		   * after all.
+		   */
+		  ol = (struct open_filelist *) xmalloc(sizeof(*ol));
+		  ol->path = xstrdup(sourcefile);
+		  ol->real_path = NULL;
+		  ol->next = ofiles;
+		  ol->nlines = 0;
+		  ol->linelist = NULL;
+		  ofiles = ol;
+		  fprintf(stderr,"Unable to open file %s\n", tmppath);
+		  return;
+		}
+	    }
+	}
+      /*
+       * Create header for file.
+       */
+      ol = (struct open_filelist *) xmalloc(sizeof(*ol));
+      ol->path = xstrdup(sourcefile);
+      ol->real_path = xstrdup(tmppath);
+      ol->next = ofiles;
+      ol->nlines = 0;
+      ol->linelist = NULL;
+      ol->size = statbuf.st_size;
+      ofiles = ol;
+
+      /*
+       * Now open and map the file.
+       */
+      fd = open(tmppath, O_RDONLY);
+      if( fd == -1 )
+	{
+	  return;
+	}
+
+      addr = mmap(0, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+      if( addr == (char *) -1 )
+	{
+	  return;
+	}
+
+      /*
+       * Now build up the line number mapping table.
+       */
+      ol->nlines = 1;
+      pnt = addr;
+      while(pnt < addr + ol->size )
+	{
+	  if( *pnt++ == '\n' )
+	    {
+	      ol->nlines++;
+	    }
+	}
+
+      ol->nlines++;
+      ol->linelist = (unsigned int*) xmalloc(ol->nlines * sizeof(unsigned int) );
+
+      nlines = 0;
+      pnt = addr;
+      ol->linelist[nlines++] = 0;
+      while(pnt < addr + ol->size )
+	{
+	  if( *pnt++ == '\n' )
+	    {
+	      ol->linelist[nlines++] = pnt - addr;
+	    }
+	}
+      ol->linelist[nlines++] = pnt - addr;
+
+    }
+  else
+    {
+      /*
+       * We know what the file is, we just need to reopen it and remap it.
+       */
+      fd = open(ol->real_path, O_RDONLY);
+      if( fd == -1 )
+	{
+	  return;
+	}
+      
+      addr = mmap(0, ol->size, PROT_READ, MAP_PRIVATE, fd, 0);
+      if( addr == (char *) -1 )
+	{
+	  return;
+	}
+    }
+  
+  /*
+   * All we need to do is to display the source lines here.
+   */
+  for(i=start - 1; i <= end - 1; i++)
+    {
+      if( i < 0 || i >= ol->nlines - 1)
+	{
+	  continue;
+	}
+
+      memset(&buffer, 0, sizeof(buffer));
+      if( ol->linelist[i+1] != ol->linelist[i] )
+	{
+	  memcpy(&buffer, addr + ol->linelist[i], 
+		 (ol->linelist[i+1] - ol->linelist[i]) - 1);
+	}
+      fprintf(stderr,"%d\t%s\n", i + 1,  buffer);
+    }
+
+  munmap(addr, ol->size);
+  close(fd);
+
+}
+
+void
+DEBUG_List(struct list_id * source1, struct list_id * source2,
+			 int delta)
+{
+  int    end;
+  int    start;
+  char * sourcefile;
+
+  /*
+   * We need to see what source file we need.  Hopefully we only have
+   * one specified, otherwise we might as well punt.
+   */
+  if( source1 != NULL 
+      && source2 != NULL 
+      && source1->sourcefile != NULL
+      && source2->sourcefile != NULL 
+      && strcmp(source1->sourcefile, source2->sourcefile) != 0 )
+    {
+      fprintf(stderr, "Ambiguous source file specification.\n");
+      return;
+    }
+
+  sourcefile = NULL;
+  if( source1 != NULL && source1->sourcefile != NULL )
+    {
+      sourcefile = source1->sourcefile;
+    }
+
+  if( sourcefile == NULL 
+      && source2 != NULL 
+      && source2->sourcefile != NULL )
+    {
+      sourcefile = source2->sourcefile;
+    }
+
+  if( sourcefile == NULL )
+    {
+      sourcefile = (char *) &DEBUG_current_sourcefile;
+    }
+
+  if( sourcefile == NULL )
+    {
+      fprintf(stderr, "No source file specified.\n");
+      return;
+    }
+
+  /*
+   * Now figure out the line number range to be listed.
+   */
+  start = -1;
+  end = -1;
+
+  if( source1 != NULL )
+    {
+      start = source1->line;
+    }
+
+  if( source2 != NULL )
+    {
+      end = source2->line;
+    }
+
+  if( start == -1 && end == -1 )
+    {
+      if( delta < 0 )
+	{
+	  end = DEBUG_start_sourceline;
+	  start = end + delta;
+	}
+      else
+	{
+	  start = DEBUG_end_sourceline;
+	  end = start + delta;
+	}
+    }
+  else if( start == -1 )
+    {
+      start = end + delta;
+    }
+  else if (end == -1)
+    {
+      end = start + delta;
+    }
+
+  /*
+   * Now call this function to do the dirty work.
+   */
+  DEBUG_DisplaySource(sourcefile, start, end);
+
+  if( sourcefile != (char *) &DEBUG_current_sourcefile )
+    {
+      strcpy(DEBUG_current_sourcefile, sourcefile);
+    }
+  DEBUG_start_sourceline = start;
+  DEBUG_end_sourceline = end;
+}
+
+
+
+#if 0
+main()
+{
+  int i, j;
+  DEBUG_AddPath("../../de");
+  while(1==1)
+    {
+      fscanf(stdin,"%d %d", &i, &j);
+      DEBUG_DisplaySource("dumpexe.c", i, j);
+    }
+  return 0;
+}
+#endif
diff --git a/debugger/stabs.c b/debugger/stabs.c
index 216ff4d..0c1ddf1 100644
--- a/debugger/stabs.c
+++ b/debugger/stabs.c
@@ -4,22 +4,34 @@
  * Copyright (C) 1996, Eric Youngdale.
  */
 
-#include <sys/mman.h>
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <limits.h>
 #include <stdio.h>
-#include <strings.h>
+#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
+#include <sys/mman.h>
 
 #include "win.h"
 #include "debugger.h"
+#include "xmalloc.h"
+
+#ifdef __svr4__
+#define __ELF__
+#endif
 
 #ifdef __ELF__
 #include <elf.h>
+#include <link.h>
+#else
+#include <a.out.h>
 #endif
 
+#ifndef N_UNDF
 #define N_UNDF		0x00
+#endif
+
 #define N_GSYM		0x20
 #define N_FUN		0x24
 #define N_STSYM		0x26
@@ -40,6 +52,13 @@
 
 
 /*
+ * This is how we translate stab types into our internal representations
+ * of datatypes.
+ */
+static struct datatype ** stab_types = NULL;
+static int num_stab_types = 0;
+
+/*
  * Set so that we know the main executable name and path.
  */
 char * DEBUG_argv0;
@@ -56,44 +75,394 @@
   unsigned long n_value;
 };
 
-#ifdef __ELF__
-
-int
-DEBUG_ParseStabs(char * addr, Elf32_Shdr * stabsect, Elf32_Shdr * stabstr)
+static void stab_strcpy(char * dest, const char * source)
 {
-  int i;
-  int ignore = FALSE;
-  int nstab;
-  struct stab_nlist * stab_ptr;
-  char * strs;
-  char * ptr;
-  char * xptr;
-  char currpath[PATH_MAX];
-  char symname[4096];
-  char * subpath = NULL;
-  DBG_ADDR     new_addr;
-  struct name_hash * curr_func = NULL;
-  int strtabinc;
+  /*
+   * A strcpy routine that stops when we hit the ':' character.
+   * Faster than copying the whole thing, and then nuking the
+   * ':'.
+   */
+  while(*source != '\0' && *source != ':')
+    {
+      *dest++ = *source++;
+    }
+  *dest++ = '\0';
+}
 
-  nstab = stabsect->sh_size / sizeof(struct stab_nlist);
-  stab_ptr = (struct stab_nlist *) (addr + stabsect->sh_offset);
-  strs  = (char *) (addr + stabstr->sh_offset);
+
+static 
+int
+DEBUG_ParseTypedefStab(char * ptr, const char * typename)
+{
+  int		    arrmax;
+  int		    arrmin;
+  char * c;
+  struct datatype * curr_type;
+  struct datatype * datatype;
+  char	            element_name[1024];
+  int		    offset;
+  int		    rtn = FALSE;
+  int		    size;
+  char		  * tc;
+  char		  * tc2;
+  int		    typenum;
+
+  /*
+   * Go from back to front.  First we go through and figure out what type numbers
+   * we need, and register those types.  Then we go in and fill the details.
+   */
+  for( c = strchr(ptr, '='); c != NULL; c = strchr(c + 1, '=') )
+    {
+      /*
+       * Back up until we get to a non-numeric character.  This is the type
+       * number.
+       */
+      tc = c - 1;
+      while( *tc >= '0' && *tc <= '9' )
+	{
+	  tc--;
+	}
+      typenum = atol(tc + 1);
+      if( num_stab_types <= typenum )
+	{
+	  num_stab_types = typenum + 32;
+	  stab_types = (struct datatype **) xrealloc(stab_types, 
+						     num_stab_types * sizeof(struct datatype *));
+	  if( stab_types == NULL )
+	    {
+	      goto leave;
+	    }
+	}
+
+      switch(c[1])
+	{
+	case '*':
+	  stab_types[typenum] = DEBUG_NewDataType(POINTER, NULL);
+	  break;
+	case 's':
+	case 'u':
+	  stab_types[typenum] = DEBUG_NewDataType(STRUCT, typename);
+	  break;
+	case 'a':
+	  stab_types[typenum] = DEBUG_NewDataType(ARRAY, NULL);
+	  break;
+	case '1':
+	case 'r':
+	  stab_types[typenum] = DEBUG_NewDataType(BASIC, typename);
+	  break;
+	case 'x':
+	  stab_strcpy(element_name, c + 3);
+	  stab_types[typenum] = DEBUG_NewDataType(STRUCT, element_name);
+	  break;
+	case 'e':
+	  stab_types[typenum] = DEBUG_NewDataType(ENUM, NULL);
+	  break;
+	case 'f':
+	  stab_types[typenum] = DEBUG_NewDataType(FUNC, NULL);
+	  break;
+	default:
+	  fprintf(stderr, "Unknown type.\n");
+	}
+      typename = NULL;
+    }
+
+     /*
+      * OK, now take a second sweep through.  Now we will be digging out the definitions
+      * of the various components, and storing them in the skeletons that we have already
+      * allocated.  We take a right-to left search as this is much easier to parse.
+      */
+  for( c = strrchr(ptr, '='); c != NULL; c = strrchr(ptr, '=') )
+    {
+      /*
+       * Back up until we get to a non-numeric character.  This is the type
+       * number.
+       */
+      tc = c - 1;
+      while( *tc >= '0' && *tc <= '9' )
+	{
+	  tc--;
+	}
+      typenum = atol(tc + 1);
+      curr_type = stab_types[typenum];
+
+      switch(c[1])
+	{
+	case 'x':
+	  tc = c + 3;
+	  while( *tc != ':' )
+	    {
+	      tc ++;
+	    }
+	  tc++;
+	  if( *tc == '\0' )
+	    {
+	      *c = '\0';
+	    }
+	  else
+	    {
+	      strcpy(c, tc);
+	    }
+
+	  break;
+	case '*':
+	case 'f':
+	  tc = c + 2;
+	  datatype = stab_types[strtol(tc, &tc, 10)];
+	  DEBUG_SetPointerType(curr_type, datatype);
+	  if( *tc == '\0' )
+	    {
+	      *c = '\0';
+	    }
+	  else
+	    {
+	      strcpy(c, tc);
+	    }
+	  break;
+	case '1':
+	case 'r':
+	  /*
+	   * We have already handled these above.
+	   */
+	  *c = '\0';
+	  break;
+	case 'a':
+	  tc  = c + 5;
+ 	  arrmin = strtol(tc, &tc, 10);
+	  tc++;
+ 	  arrmax = strtol(tc, &tc, 10);
+	  tc++;
+	  datatype = stab_types[strtol(tc, &tc, 10)];
+	  if( *tc == '\0' )
+	    {
+	      *c = '\0';
+	    }
+	  else
+	    {
+	      strcpy(c, tc);
+	    }
+	  
+	  DEBUG_SetArrayParams(curr_type, arrmin, arrmax, datatype);
+	  break;
+	case 's':
+	case 'u':
+	  tc = c + 2;
+	  DEBUG_SetStructSize(curr_type, strtol(tc, &tc, 10));
+	  /*
+	   * Now parse the individual elements of the structure/union.
+	   */
+	  while(*tc != ';')
+	    {
+	      tc2 = element_name;
+	      while(*tc != ':')
+		{
+		  *tc2++ = *tc++;
+		}
+	      tc++;
+	      *tc2++ = '\0';
+	      datatype = stab_types[strtol(tc, &tc, 10)];
+	      tc++;
+	      offset  = strtol(tc, &tc, 10);
+	      tc++;
+	      size  = strtol(tc, &tc, 10);
+	      tc++;
+	      DEBUG_AddStructElement(curr_type, element_name, datatype, offset, size);
+	    }
+	  if( *tc == '\0' )
+	    {
+	      *c = '\0';
+	    }
+	  else
+	    {
+	      strcpy(c, tc + 1);
+	    }
+	  break;
+	case 'e':
+	  tc = c + 2;
+	  /*
+	   * Now parse the individual elements of the structure/union.
+	   */
+	  while(*tc != ';')
+	    {
+	      tc2 = element_name;
+	      while(*tc != ':')
+		{
+		  *tc2++ = *tc++;
+		}
+	      tc++;
+	      *tc2++ = '\0';
+	      offset  = strtol(tc, &tc, 10);
+	      tc++;
+	      DEBUG_AddStructElement(curr_type, element_name, NULL, offset, 0);
+	    }
+	  if( *tc == '\0' )
+	    {
+	      *c = '\0';
+	    }
+	  else
+	    {
+	      strcpy(c, tc + 1);
+	    }
+	  break;
+	default:
+	  fprintf(stderr, "Unknown type.\n");
+	  break;
+	}
+    }
+
+  rtn = TRUE;
+
+leave:
+
+  return rtn;
+
+}
+
+static struct datatype *
+DEBUG_ParseStabType(const char * stab)
+{
+  char * c;
+  int    typenum;
+
+  /*
+   * Look through the stab definition, and figure out what datatype
+   * this represents.  If we have something we know about, assign the
+   * type.
+   */
+  c = strchr(stab, ':');
+  if( c == NULL )
+    {
+      return NULL;
+    }
+
+  c++;
+  /*
+   * The next character says more about the type (i.e. data, function, etc)
+   * of symbol.  Skip it.
+   */
+  c++;
+
+  typenum = atol(c);
+
+  if( typenum < num_stab_types && stab_types[typenum] != NULL )
+    {
+      return stab_types[typenum];
+    }
+
+  return NULL;
+}
+
+static 
+int
+DEBUG_ParseStabs(char * addr, unsigned int load_offset,
+		 unsigned int staboff, int stablen, 
+		 unsigned int strtaboff, int strtablen)
+{
+  struct name_hash    * curr_func = NULL;
+  struct wine_locals  * curr_loc = NULL;
+  struct name_hash    * curr_sym = NULL;
+  char			currpath[PATH_MAX];
+  int			i;
+  int			ignore = FALSE;
+  int			last_nso = -1;
+  int			len;
+  DBG_ADDR		new_addr;
+  int			nstab;
+  char		      * ptr;
+  char		      * stabbuff;
+  int			stabbufflen;
+  struct stab_nlist   * stab_ptr;
+  char		      * strs;
+  int			strtabinc;
+  char		      * subpath = NULL;
+  char			symname[4096];
+
+  nstab = stablen / sizeof(struct stab_nlist);
+  stab_ptr = (struct stab_nlist *) (addr + staboff);
+  strs  = (char *) (addr + strtaboff);
 
   memset(currpath, 0, sizeof(currpath));
 
+  /*
+   * Allocate a buffer into which we can build stab strings for cases
+   * where the stab is continued over multiple lines.
+   */
+  stabbufflen = 65536;
+  stabbuff = (char *) xmalloc(stabbufflen);
+  if( stabbuff == NULL )
+    {
+      goto leave;
+    }
+
   strtabinc = 0;
+  stabbuff[0] = '\0';
   for(i=0; i < nstab; i++, stab_ptr++ )
     {
       ptr = strs + (unsigned int) stab_ptr->n_un.n_name;
+      if( ptr[strlen(ptr) - 1] == '\\' )
+	{
+	  /*
+	   * Indicates continuation.  Append this to the buffer, and go onto the
+	   * next record.  Repeat the process until we find a stab without the
+	   * '/' character, as this indicates we have the whole thing.
+	   */
+	  len = strlen(ptr);
+	  if( strlen(stabbuff) + len > stabbufflen )
+	    {
+	      stabbufflen += 65536;
+	      stabbuff = (char *) xrealloc(stabbuff, stabbufflen);
+	      if( stabbuff == NULL )
+		{
+		  goto leave;
+		}
+	    }
+	  strncat(stabbuff, ptr, len - 1);
+	  continue;
+	}
+      else if( stabbuff[0] != '\0' )
+	{
+	  strcat( stabbuff, ptr);
+	  ptr = stabbuff;
+	}
+
+      if( strchr(ptr, '=') != NULL )
+	{
+	  /*
+	   * The stabs aren't in writable memory, so copy it over so we are
+	   * sure we can scribble on it.
+	   */
+	  if( ptr != stabbuff )
+	    {
+	      strcpy(stabbuff, ptr);
+	      ptr = stabbuff;
+	    }
+	  stab_strcpy(symname, ptr);
+	  DEBUG_ParseTypedefStab(ptr, symname);
+	}
+
       switch(stab_ptr->n_type)
 	{
 	case N_GSYM:
 	  /*
-	   * These are useless.  They have no value, and you have to
+	   * These are useless with ELF.  They have no value, and you have to
 	   * read the normal symbol table to get the address.  Thus we
 	   * ignore them, and when we process the normal symbol table
 	   * we should do the right thing.
+	   *
+	   * With a.out, they actually do make some amount of sense.
 	   */
+	  new_addr.seg = 0;
+	  new_addr.type = DEBUG_ParseStabType(ptr);
+	  new_addr.off = load_offset + stab_ptr->n_value;
+
+	  stab_strcpy(symname, ptr);
+#ifdef __ELF__
+	  curr_sym = DEBUG_AddSymbol( symname, &new_addr, currpath,
+				      SYM_WINE | SYM_DATA | SYM_INVALID);
+#else
+	  curr_sym = DEBUG_AddSymbol( symname, &new_addr, currpath, 
+				      SYM_WINE | SYM_DATA );
+#endif
+	  break;
 	case N_RBRAC:
 	case N_LBRAC:
 	  /*
@@ -110,15 +479,12 @@
 	   * These are static symbols and BSS symbols.
 	   */
 	  new_addr.seg = 0;
-	  new_addr.off = stab_ptr->n_value;
+	  new_addr.type = DEBUG_ParseStabType(ptr);
+	  new_addr.off = load_offset + stab_ptr->n_value;
 
-	  strcpy(symname, ptr);
-	  xptr = strchr(symname, ':');
-	  if( xptr != NULL )
-	    {
-	      *xptr = '\0';
-	    }
-	  DEBUG_AddSymbol( symname, &new_addr, currpath );
+	  stab_strcpy(symname, ptr);
+	  curr_sym = DEBUG_AddSymbol( symname, &new_addr, currpath, 
+				      SYM_WINE | SYM_DATA );
 	  break;
 	case N_PSYM:
 	  /*
@@ -127,41 +493,32 @@
 	  if(     (curr_func != NULL)
 	       && (stab_ptr->n_value != 0) )
 	    {
-	      strcpy(symname, ptr);
-	      xptr = strchr(symname, ':');
-	      if( xptr != NULL )
-		{
-		  *xptr = '\0';
-		}
-	      DEBUG_AddLocal(curr_func, 0, 
-			     stab_ptr->n_value, 0, 0, symname);
+	      stab_strcpy(symname, ptr);
+	      curr_loc = DEBUG_AddLocal(curr_func, 0, 
+					stab_ptr->n_value, 0, 0, symname);
+	      DEBUG_SetLocalSymbolType( curr_loc, DEBUG_ParseStabType(ptr));
 	    }
 	  break;
 	case N_RSYM:
 	  if( curr_func != NULL )
 	    {
-	      strcpy(symname, ptr);
-	      xptr = strchr(symname, ':');
-	      if( xptr != NULL )
-		{
-		  *xptr = '\0';
-		}
-	      DEBUG_AddLocal(curr_func, stab_ptr->n_value, 0, 0, 0, symname);
+	      stab_strcpy(symname, ptr);
+	      curr_loc = DEBUG_AddLocal(curr_func, stab_ptr->n_value, 0, 0, 0, symname);
+	      DEBUG_SetLocalSymbolType( curr_loc, DEBUG_ParseStabType(ptr));
 	    }
 	  break;
 	case N_LSYM:
 	  if(     (curr_func != NULL)
 	       && (stab_ptr->n_value != 0) )
 	    {
-	      strcpy(symname, ptr);
-	      xptr = strchr(symname, ':');
-	      if( xptr != NULL )
-		{
-		  *xptr = '\0';
-		}
+	      stab_strcpy(symname, ptr);
 	      DEBUG_AddLocal(curr_func, 0, 
 			     stab_ptr->n_value, 0, 0, symname);
 	    }
+	  else if (curr_func == NULL)
+	    {
+	      stab_strcpy(symname, ptr);
+	    }
 	  break;
 	case N_SLINE:
 	  /*
@@ -170,12 +527,29 @@
 	   */
 	  if( curr_func != NULL )
 	    {
+#ifdef __ELF__
 	      DEBUG_AddLineNumber(curr_func, stab_ptr->n_desc, 
 				  stab_ptr->n_value);
+#else
+#if 0
+	      /*
+	       * This isn't right.  The order of the stabs is different under
+	       * a.out, and as a result we would end up attaching the line
+	       * number to the wrong function.
+	       */
+	      DEBUG_AddLineNumber(curr_func, stab_ptr->n_desc, 
+				  stab_ptr->n_value - curr_func->addr.off);
+#endif
+#endif
 	    }
 	  break;
 	case N_FUN:
 	  /*
+	   * First, clean up the previous function we were working on.
+	   */
+	  DEBUG_Normalize(curr_func);
+
+	  /*
 	   * For now, just declare the various functions.  Later
 	   * on, we will add the line number information and the
 	   * local symbols.
@@ -183,7 +557,8 @@
 	  if( !ignore )
 	    {
 	      new_addr.seg = 0;
-	      new_addr.off = stab_ptr->n_value;
+	      new_addr.type = DEBUG_ParseStabType(ptr);
+	      new_addr.off = load_offset + stab_ptr->n_value;
 	      /*
 	       * Copy the string to a temp buffer so we
 	       * can kill everything after the ':'.  We do
@@ -191,13 +566,9 @@
 	       * all of the pages related to the stabs, and that
 	       * sucks up swap space like crazy.
 	       */
-	      strcpy(symname, ptr);
-	      xptr = strchr(symname, ':');
-	      if( xptr != NULL )
-		{
-		  *xptr = '\0';
-		}
-	      curr_func = DEBUG_AddSymbol( symname, &new_addr, currpath );
+	      stab_strcpy(symname, ptr);
+	      curr_func = DEBUG_AddSymbol( symname, &new_addr, currpath,
+					   SYM_WINE | SYM_FUNC);
 	    }
 	  else
 	    {
@@ -213,19 +584,40 @@
 	   * This indicates a new source file.  Append the records
 	   * together, to build the correct path name.
 	   */
+#ifndef __ELF__
+	  /*
+	   * With a.out, there is no NULL string N_SO entry at the end of
+	   * the file.  Thus when we find non-consecutive entries,
+	   * we consider that a new file is started.
+	   */
+	  if( last_nso < i-1 )
+	    {
+	      currpath[0] = '\0';
+	      DEBUG_Normalize(curr_func);
+	      curr_func = NULL;
+	    }
+#endif
+
 	  if( *ptr == '\0' )
 	    {
 	      /*
 	       * Nuke old path.
 	       */
 	      currpath[0] = '\0';
+	      DEBUG_Normalize(curr_func);
 	      curr_func = NULL;
+	      /*
+	       * The datatypes that we would need to use are reset when
+	       * we start a new file.
+	       */
+	      memset(stab_types, 0, num_stab_types * sizeof(stab_types));
 	    }
 	  else
 	    {
 	      strcat(currpath, ptr);
 	      subpath = ptr;
 	    }
+	  last_nso = i;
 	  break;
 	case N_SOL:
 	  /*
@@ -240,12 +632,14 @@
 	  else
 	    {
 	      ignore = TRUE;
+	      DEBUG_Normalize(curr_func);
 	      curr_func = NULL;
 	    }
 	  break;
 	case N_UNDF:
 	  strs += strtabinc;
 	  strtabinc = stab_ptr->n_value;
+ 	  DEBUG_Normalize(curr_func);
 	  curr_func = NULL;
 	  break;
 	case N_OPT:
@@ -263,20 +657,128 @@
 	default:
 	  break;
 	}
+
+      stabbuff[0] = '\0';
+
 #if 0
       fprintf(stderr, "%d %x %s\n", stab_ptr->n_type, 
 	      (unsigned int) stab_ptr->n_value,
 	      strs + (unsigned int) stab_ptr->n_un.n_name);
 #endif
     }
+
+leave:
+
+  if( stab_types != NULL )
+    {
+      free(stab_types);
+      stab_types = NULL;
+      num_stab_types = 0;
+    }
+
   return TRUE;
 }
 
+#ifdef __ELF__
+
+/*
+ * Walk through the entire symbol table and add any symbols we find there.
+ * This can be used in cases where we have stripped ELF shared libraries,
+ * or it can be used in cases where we have data symbols for which the address
+ * isn't encoded in the stabs.
+ *
+ * This is all really quite easy, since we don't have to worry about line
+ * numbers or local data variables.
+ */
+static
 int
-DEBUG_ReadExecutableDbgInfo(void)
+DEBUG_ProcessElfSymtab(char * addr, unsigned int load_offset,
+		       Elf32_Shdr * symtab, Elf32_Shdr * strtab)
+{
+  char		* curfile = NULL;
+  struct name_hash * curr_sym = NULL;
+  int		  flags;
+  int		  i;
+  DBG_ADDR        new_addr;
+  int		  nsym;
+  char		* strp;
+  char		* symname;
+  Elf32_Sym	* symp;
+
+
+  symp = (Elf32_Sym *) (addr + symtab->sh_offset);
+  nsym = symtab->sh_size / sizeof(*symp);
+  strp = (char *) (addr + strtab->sh_offset);
+
+  for(i=0; i < nsym; i++, symp++)
+    {
+      /*
+       * Ignore certain types of entries which really aren't of that much
+       * interest.
+       */
+      if( ELF32_ST_TYPE(symp->st_info) == STT_SECTION )
+	{
+	  continue;
+	}
+
+      symname = strp + symp->st_name;
+
+      /*
+       * Save the name of the current file, so we have a way of tracking
+       * static functions/data.
+       */
+      if( ELF32_ST_TYPE(symp->st_info) == STT_FILE )
+	{
+	  curfile = symname;
+	  continue;
+	}
+
+
+      /*
+       * See if we already have something for this symbol.
+       * If so, ignore this entry, because it would have come from the
+       * stabs or from a previous symbol.  If the value is different,
+       * we will have to keep the darned thing, because there can be
+       * multiple local symbols by the same name.
+       */
+      if(    (DEBUG_GetSymbolValue(symname, -1, &new_addr, FALSE ) == TRUE)
+	  && (new_addr.off == (load_offset + symp->st_value)) )
+	{
+	  continue;
+	}
+
+      new_addr.seg = 0;
+      new_addr.type = NULL;
+      new_addr.off = load_offset + symp->st_value;
+      flags = SYM_WINE | (ELF32_ST_BIND(symp->st_info) == STT_FUNC 
+			  ? SYM_FUNC : SYM_DATA);
+      if( ELF32_ST_BIND(symp->st_info) == STB_GLOBAL )
+	{
+	  curr_sym = DEBUG_AddSymbol( symname, &new_addr, NULL, flags );
+	}
+      else
+	{
+	  curr_sym = DEBUG_AddSymbol( symname, &new_addr, curfile, flags );
+	}
+
+      /*
+       * Record the size of the symbol.  This can come in handy in
+       * some cases.  Not really used yet, however.
+       */
+      if(  symp->st_size != 0 )
+	{
+	  DEBUG_SetSymbolSize(curr_sym, symp->st_size);
+	}
+    }
+
+  return TRUE;
+}
+
+static
+int
+DEBUG_ProcessElfObject(char * filename, unsigned int load_offset)
 {
   int			rtn = FALSE;
-  char		      * exe_name;
   struct stat		statbuf;
   int			fd = -1;
   int			status;
@@ -289,6 +791,239 @@
   int			stabsect;
   int			stabstrsect;
 
+
+  /*
+   * Make sure we can stat and open this file.
+   */
+  if( filename == NULL )
+    {
+      goto leave;
+    }
+
+  status = stat(filename, &statbuf);
+  if( status == -1 )
+    {
+      goto leave;
+    }
+
+  /*
+   * Now open the file, so that we can mmap() it.
+   */
+  fd = open(filename, O_RDONLY);
+  if( fd == -1 )
+    {
+      goto leave;
+    }
+
+
+  /*
+   * Now mmap() the file.
+   */
+  addr = mmap(0, statbuf.st_size, PROT_READ, 
+	      MAP_PRIVATE, fd, 0);
+
+  /*
+   * Give a nice status message here...
+   */
+  fprintf(stderr, "Loading symbols from ELF file %s...\n", filename);
+
+  /*
+   * Next, we need to find a few of the internal ELF headers within
+   * this thing.  We need the main executable header, and the section
+   * table.
+   */
+  ehptr = (Elf32_Ehdr *) addr;
+
+  if( load_offset == NULL )
+    {
+      DEBUG_RegisterELFDebugInfo(ehptr->e_entry, statbuf.st_size, filename);
+    }
+  else
+    {
+      DEBUG_RegisterELFDebugInfo(load_offset, statbuf.st_size, filename);
+    }
+
+  spnt = (Elf32_Shdr *) (addr + ehptr->e_shoff);
+  nsect = ehptr->e_shnum;
+  shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
+
+  stabsect = stabstrsect = -1;
+
+  for(i=0; i < nsect; i++)
+    {
+      if( strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0 )
+	{
+	  stabsect = i;
+	}
+
+      if( strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0 )
+	{
+	  stabstrsect = i;
+	}
+    }
+
+  if( stabsect == -1 || stabstrsect == -1 )
+    {
+      goto leave;
+    }
+
+  /*
+   * OK, now just parse all of the stabs.
+   */
+  rtn = DEBUG_ParseStabs(addr, load_offset, 
+			 spnt[stabsect].sh_offset,
+			 spnt[stabsect].sh_size,
+			 spnt[stabstrsect].sh_offset,
+			 spnt[stabstrsect].sh_size);
+
+  if( rtn != TRUE )
+    {
+      goto leave;
+    }
+
+  for(i=0; i < nsect; i++)
+    {
+      if(    (strcmp(shstrtab + spnt[i].sh_name, ".symtab") == 0)
+	  && (spnt[i].sh_type == SHT_SYMTAB) )
+	{
+	  DEBUG_ProcessElfSymtab(addr, load_offset, 
+				 spnt + i, spnt + spnt[i].sh_link);
+	}
+
+      if(    (strcmp(shstrtab + spnt[i].sh_name, ".dynsym") == 0)
+	  && (spnt[i].sh_type == SHT_DYNSYM) )
+	{
+	  DEBUG_ProcessElfSymtab(addr, load_offset, 
+				 spnt + i, spnt + spnt[i].sh_link);
+	}
+    }
+
+leave:
+
+  if( addr != (char *) 0xffffffff )
+    {
+      munmap(addr, statbuf.st_size);
+    }
+
+  if( fd != -1 )
+    {
+      close(fd);
+    }
+
+  return (rtn);
+
+}
+
+int
+DEBUG_ReadExecutableDbgInfo(void)
+{
+  Elf32_Ehdr	      * ehdr;
+  char		      * exe_name;
+  Elf32_Dyn	      * dynpnt;
+  struct r_debug      * dbg_hdr;
+  struct link_map     * lpnt = NULL;
+  extern Elf32_Dyn      _DYNAMIC[];
+  int			rtn = FALSE;
+
+  exe_name = DEBUG_argv0;
+
+  /*
+   * Make sure we can stat and open this file.
+   */
+  if( exe_name == NULL )
+    {
+      goto leave;
+    }
+
+  DEBUG_ProcessElfObject(exe_name, 0);
+
+  /*
+   * Finally walk the tables that the dynamic loader maintains to find all
+   * of the other shared libraries which might be loaded.  Perform the
+   * same step for all of these.
+   */
+  dynpnt = _DYNAMIC;
+  if( dynpnt == NULL )
+    {
+      goto leave;
+    }
+
+  /*
+   * Now walk the dynamic section (of the executable, looking for a DT_DEBUG
+   * entry.
+   */
+  for(; dynpnt->d_tag != DT_NULL; dynpnt++)
+    {
+      if( dynpnt->d_tag == DT_DEBUG )
+	{
+	  break;
+	}
+    }
+
+  if(    (dynpnt->d_tag != DT_DEBUG)
+      || (dynpnt->d_un.d_ptr == NULL) )
+    {
+      goto leave;
+    }
+
+  /*
+   * OK, now dig into the actual tables themselves.
+   */
+  dbg_hdr = (struct r_debug *) dynpnt->d_un.d_ptr;
+  lpnt = dbg_hdr->r_map;
+
+  /*
+   * Now walk the linked list.  In all known ELF implementations,
+   * the dynamic loader maintains this linked list for us.  In some
+   * cases the first entry doesn't appear with a name, in other cases it
+   * does.
+   */
+  for(; lpnt; lpnt = lpnt->l_next )
+    {
+      /*
+       * We already got the stuff for the executable using the
+       * argv[0] entry above.  Here we only need to concentrate on any
+       * shared libraries which may be loaded.
+       */
+      ehdr = (Elf32_Ehdr *) lpnt->l_addr;
+      if( (lpnt->l_addr == NULL) || (ehdr->e_type != ET_DYN) )
+	{
+	  continue;
+	}
+
+      if( lpnt->l_name != NULL )
+	{
+	  DEBUG_ProcessElfObject(lpnt->l_name, lpnt->l_addr);
+	}
+    }
+
+  rtn = TRUE;
+
+leave:
+
+  return (rtn);
+
+}
+
+#else	/* !__ELF__ */
+
+#ifdef linux
+/*
+ * a.out linux.
+ */
+int
+DEBUG_ReadExecutableDbgInfo(void)
+{
+  char		      * addr = (char *) 0xffffffff;
+  char		      * exe_name;
+  struct exec	      * ahdr;
+  int			fd = -1;
+  int			rtn = FALSE;
+  unsigned int		staboff;
+  struct stat		statbuf;
+  int			status;
+  unsigned int		stroff;
+
   exe_name = DEBUG_argv0;
 
   /*
@@ -321,40 +1056,22 @@
   addr = mmap(0, statbuf.st_size, PROT_READ, 
 	      MAP_PRIVATE, fd, 0);
 
-  /*
-   * Next, we need to find a few of the internal ELF headers within
-   * this thing.  We need the main executable header, and the section
-   * table.
-   */
-  ehptr = (Elf32_Ehdr *) addr;
-  spnt = (Elf32_Shdr *) (addr + ehptr->e_shoff);
-  nsect = ehptr->e_shnum;
-  shstrtab = (addr + spnt[ehptr->e_shstrndx].sh_offset);
+  ahdr = (struct exec *) addr;
 
-  stabsect = stabstrsect = -1;
-
-  for(i=0; i < nsect; i++)
-    {
-      if( strcmp(shstrtab + spnt[i].sh_name, ".stab") == 0 )
-	{
-	  stabsect = i;
-	}
-
-      if( strcmp(shstrtab + spnt[i].sh_name, ".stabstr") == 0 )
-	{
-	  stabstrsect = i;
-	}
-    }
-
-  if( stabsect == -1 || stabstrsect == -1 )
-    {
-      goto leave;
-    }
+  staboff = N_SYMOFF(*ahdr);
+  stroff = N_STROFF(*ahdr);
+  rtn = DEBUG_ParseStabs(addr, 0, 
+			 staboff, 
+			 ahdr->a_syms,
+			 stroff,
+			 statbuf.st_size - stroff);
 
   /*
-   * OK, now just parse all of the stabs.
+   * Give a nice status message here...
    */
-  rtn = DEBUG_ParseStabs(addr, spnt + stabsect, spnt + stabstrsect);
+  fprintf(stderr, "Loading symbols from a.out file %s...\n", exe_name);
+
+  rtn = TRUE;
 
 leave:
 
@@ -371,13 +1088,15 @@
   return (rtn);
 
 }
-
-#else	/* !__ELF__ */
-
+#else
+/*
+ * Non-linux, non-ELF platforms.
+ */
 int
 DEBUG_ReadExecutableDbgInfo(void)
 {
 return FALSE;
 }
+#endif
 
 #endif  /* __ELF__ */
diff --git a/debugger/stack.c b/debugger/stack.c
index adc4e88..8c668ad 100644
--- a/debugger/stack.c
+++ b/debugger/stack.c
@@ -19,17 +19,14 @@
 struct bt_info
 {
   unsigned int	     eip;
+  unsigned int	     ess;
   unsigned int	     ebp;
-  struct name_hash * frame;
+  struct symbol_info frame;
 };
 
 static int nframe;
 static struct bt_info * frames = NULL;
 int curr_frame;
-static char * reg_name[] =
-{
-  "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
-};
 
 typedef struct
 {
@@ -62,12 +59,14 @@
     {  /* 32-bit mode */
         addr.seg = 0;
         addr.off = ESP_reg(&DEBUG_context);
+	addr.type = NULL;
         DEBUG_ExamineMemory( &addr, 24, 'x' );
     }
     else  /* 16-bit mode */
     {
         addr.seg = SS_reg(&DEBUG_context);
         addr.off = SP_reg(&DEBUG_context);
+	addr.type = NULL;
         DEBUG_ExamineMemory( &addr, 24, 'w' );
     }
     fprintf(stderr,"\n");
@@ -153,94 +152,76 @@
 }
 
 /***********************************************************************
- *           DEBUG_GetSymbolValue
+ *           DEBUG_SilentBackTrace
  *
- * Get the address of a named symbol from the current stack frame.
+ * Display a stack back-trace.
  */
-BOOL32 DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr )
+void DEBUG_SilentBackTrace(void)
 {
-  struct name_hash * curr_func;
-  int		     i;
+    DBG_ADDR addr;
+    int frameno = 0;
 
-  /*
-   * If we don't have a valid backtrace, then just return.
-   */
-  if( frames == NULL )
+    nframe = 1;
+    if (frames) free( frames );
+    frames = (struct bt_info *) xmalloc( sizeof(struct bt_info) );
+
+    if (SS_reg(&DEBUG_context) == WINE_DATA_SELECTOR)  /* 32-bit mode */
     {
-      return FALSE;
+        addr.seg = 0;
+        addr.off = EIP_reg(&DEBUG_context);
+	frames[0].eip = addr.off;
+	DEBUG_FindNearestSymbol( &addr, TRUE, &frames[0].frame.sym, 0, 
+						&frames[0].frame.list);
+	frames[0].ebp = addr.off = EBP_reg(&DEBUG_context);
+	frameno++;
+
+        while (addr.off)
+        {
+            FRAME32 *frame = (FRAME32 *)addr.off;
+            if (!DBG_CHECK_READ_PTR( &addr, sizeof(FRAME32) )) return;
+            if (!frame->ip) break;
+            nframe++;
+            frames = (struct bt_info *)xrealloc(frames,
+                                                nframe*sizeof(struct bt_info));
+            addr.off = frame->ip;
+	    frames[frameno].eip = addr.off;
+	    frames[frameno].ebp = frame->bp;
+	    DEBUG_FindNearestSymbol( &addr, TRUE, 
+				     &frames[frameno].frame.sym, frame->bp, 
+				     &frames[frameno].frame.list);
+	    frameno++;
+            addr.off = frame->bp;
+        }
     }
-
-  curr_func = frames[curr_frame].frame;
-
-  /*
-   * If we don't know what the current function is, then we also have
-   * nothing to report here.
-   */
-  if( curr_func == NULL )
-    {
-      return FALSE;
-    }
-
-  for(i=0; i < curr_func->n_locals; i++ )
+    else  /* 16-bit mode */
     {
       /*
-       * Test the range of validity of the local variable.  This
-       * comes up with RBRAC/LBRAC stabs in particular.
+       * Not implemented here.  I am not entirely sure how best to handle
+       * this stuff.
        */
-      if(    (curr_func->local_vars[i].pc_start != 0)
-	  && ((frames[curr_frame].eip - curr_func->addr.off) 
-	      < curr_func->local_vars[i].pc_start) )
-	{
-	  continue;
-	}
-
-      if(    (curr_func->local_vars[i].pc_end != 0)
-	  && ((frames[curr_frame].eip - curr_func->addr.off) 
-	      > curr_func->local_vars[i].pc_end) )
-	{
-	  continue;
-	}
-
-      if( strcmp(name, curr_func->local_vars[i].name) == 0 )
-	{
-	  /*
-	   * OK, we found it.  Now figure out what to do with this.
-	   */
-	  if( curr_func->local_vars[i].regno != 0 )
-	    {
-	      /*
-	       * Register variable.  We don't know how to treat
-	       * this yet.
-	       */
-	      return FALSE;
-	    }
-
-	  addr->seg = 0;
-	  addr->off = frames[curr_frame].ebp + curr_func->local_vars[i].offset;
-
-	  return TRUE;
-	}
     }
-  return FALSE;
 }
 
 int
 DEBUG_SetFrame(int newframe)
 {
   int		rtn = FALSE;
-  /*
-   * Nothing for now.  Add support later.
-   */
 
   curr_frame = newframe;
+
+  if( curr_frame >= nframe )
+    {
+      curr_frame = nframe - 1;
+    }
+
   if( curr_frame < 0 )
     {
       curr_frame = 0;
     }
 
-  if( curr_frame >= nframe )
+   if( frames[curr_frame].frame.list.sourcefile != NULL )
     {
-      curr_frame = nframe - 1;
+      DEBUG_List(&frames[curr_frame].frame.list, NULL, 0);
     }
 
   rtn = TRUE;
@@ -248,13 +229,9 @@
 }
 
 int
-DEBUG_InfoLocals()
+DEBUG_GetCurrentFrame(struct name_hash ** name, unsigned int * eip,
+		      unsigned int * ebp)
 {
-  struct name_hash * curr_func;
-  int		     i;
-  int		rtn = FALSE;
-  unsigned	int * ptr;
-
   /*
    * If we don't have a valid backtrace, then just return.
    */
@@ -263,54 +240,19 @@
       return FALSE;
     }
 
-  curr_func = frames[curr_frame].frame;
-
   /*
    * If we don't know what the current function is, then we also have
    * nothing to report here.
    */
-  if( curr_func == NULL )
+  if( frames[curr_frame].frame.sym == NULL )
     {
       return FALSE;
     }
 
-  for(i=0; i < curr_func->n_locals; i++ )
-    {
-      /*
-       * Test the range of validity of the local variable.  This
-       * comes up with RBRAC/LBRAC stabs in particular.
-       */
-      if(    (curr_func->local_vars[i].pc_start != 0)
-	  && ((frames[curr_frame].eip - curr_func->addr.off) 
-	      < curr_func->local_vars[i].pc_start) )
-	{
-	  continue;
-	}
+  *name = frames[curr_frame].frame.sym;
+  *eip = frames[curr_frame].eip;
+  *ebp = frames[curr_frame].ebp;
 
-      if(    (curr_func->local_vars[i].pc_end != 0)
-	  && ((frames[curr_frame].eip - curr_func->addr.off) 
-	      > curr_func->local_vars[i].pc_end) )
-	{
-	  continue;
-	}
-      
-      if( curr_func->local_vars[i].offset == 0 )
-	{
-	  fprintf(stderr, "%s:%s optimized into register $%s \n",
-		  curr_func->name, curr_func->local_vars[i].name,
-		  reg_name[curr_func->local_vars[i].regno]);
-	}
-      else
-	{
-	  ptr = (unsigned int *) (frames[curr_frame].ebp 
-				   + curr_func->local_vars[i].offset);
-	  fprintf(stderr, "%s:%s == 0x%8.8x\n",
-		  curr_func->name, curr_func->local_vars[i].name,
-		  *ptr);
-	}
-    }
-
-  rtn = TRUE;
-
-  return (rtn);
+  return TRUE;
 }
+
diff --git a/debugger/types.c b/debugger/types.c
new file mode 100644
index 0000000..581d096
--- /dev/null
+++ b/debugger/types.c
@@ -0,0 +1,809 @@
+/*
+ * File types.c - datatype handling stuff for internal debugger.
+ *
+ * Copyright (C) 1997, Eric Youngdale.
+ *
+ * This really doesn't do much at the moment, but it forms the framework
+ * upon which full support for datatype handling will eventually be hung.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <assert.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include <strings.h>
+#include <unistd.h>
+#include <malloc.h>
+
+#include "win.h"
+#include "pe_image.h"
+#include "peexe.h"
+#include "debugger.h"
+#include "peexe.h"
+#include "xmalloc.h"
+
+#define NR_TYPE_HASH 521
+
+struct en_values
+{
+  struct en_values* next;
+  char		  * name;
+  int		    value;
+};
+
+struct member
+{
+  struct member   * next;
+  char		  * name;
+  struct datatype * type;
+  int		    offset;
+  int		    size;
+};
+
+struct datatype
+{
+  enum	debug_type type;
+  struct datatype * next;
+  char * name;
+  union
+  {
+    struct
+    {
+      char    basic_type;
+      char  * output_format;
+      char    basic_size;
+      unsigned b_signed:1;
+    } basic;
+    struct
+    {
+      unsigned short bitoff;
+      unsigned short nbits;
+      struct datatype * basetype;
+    } bitfield;
+
+    struct
+    {
+      struct datatype * pointsto;
+    } pointer;
+    struct
+    {
+      struct datatype * rettype;
+    } funct;
+    struct
+    {
+      int		start;
+      int		end;
+      struct datatype * basictype;
+    } array;
+    struct
+    {
+      int		size;
+      struct member * members;
+    } structure;
+    struct
+    {
+      struct en_values * members;
+    } enumeration;
+  } un;
+};
+
+#define	BASIC_INT		1
+#define BASIC_CHAR		2
+#define BASIC_LONG		3
+#define BASIC_UINT		4
+#define BASIC_LUI		5
+#define BASIC_LONGLONG		6
+#define BASIC_ULONGLONGI	7
+#define BASIC_SHORT		8
+#define BASIC_SHORTUI		9
+#define BASIC_SCHAR		10
+#define BASIC_UCHAR		11
+#define BASIC_FLT		12
+#define BASIC_LONG_DOUBLE	13
+#define BASIC_DOUBLE		14
+#define BASIC_CMPLX_INT		15
+#define BASIC_CMPLX_FLT		16
+#define BASIC_CMPLX_DBL		17
+#define BASIC_CMPLX_LONG_DBL	18
+#define BASIC_VOID		19
+
+struct datatype * DEBUG_TypeInt = NULL;
+struct datatype * DEBUG_TypeIntConst = NULL;
+struct datatype * DEBUG_TypeUSInt = NULL;
+struct datatype * DEBUG_TypeString = NULL;
+
+/*
+ * All of the types that have been defined so far.
+ */
+static struct datatype * type_hash_table[NR_TYPE_HASH + 1];
+static struct datatype * pointer_types = NULL;
+
+static unsigned int type_hash( const char * name )
+{
+    unsigned int hash = 0;
+    unsigned int tmp;
+    const char * p;
+
+    p = name;
+
+    while (*p) 
+      {
+	hash = (hash << 4) + *p++;
+
+	if( (tmp = (hash & 0xf0000000)) )
+	  {
+	    hash ^= tmp >> 24;
+	  }
+	hash &= ~tmp;
+      }
+    return hash % NR_TYPE_HASH;
+}
+
+
+static struct datatype *
+DEBUG_InitBasic(int type, char * name, int size, int b_signed, 
+			    char * output_format)
+{
+  int hash;
+
+  struct datatype * dt;
+  dt = (struct datatype *) xmalloc(sizeof(struct datatype));
+
+  if( dt != NULL )
+    {
+      if( name != NULL )
+	{
+	  hash = type_hash(name);
+	}
+      else
+	{
+	  hash = NR_TYPE_HASH;
+	}
+
+      dt->type = BASIC;
+      dt->name = name;
+      dt->next = type_hash_table[hash];
+      type_hash_table[hash] = dt;
+      dt->un.basic.basic_type = type;
+      dt->un.basic.basic_size = size;
+      dt->un.basic.b_signed = b_signed;
+      dt->un.basic.output_format = output_format;
+    }
+
+  return dt;
+}
+
+struct datatype *
+DEBUG_NewDataType(enum debug_type xtype, const char * typename)
+{
+  struct datatype * dt = NULL;
+  int hash;
+
+  /*
+   * The last bucket is special, and is used to hold typeless names.
+   */
+  if( typename == NULL )
+    {
+      hash = NR_TYPE_HASH;
+    }
+  else
+    {
+      hash = type_hash(typename);
+    }
+
+  if( typename != NULL )
+    {
+      for( dt = type_hash_table[hash]; dt; dt = dt->next )
+	{
+	  if( xtype != dt->type || dt->name == NULL 
+	      || dt->name[0] != typename[0])
+	    {
+	      continue;
+	    }
+	  	  
+	  if( strcmp(dt->name, typename) == 0 )
+	    {
+	      return dt;
+	    }
+	}
+    }
+
+  if( dt == NULL )
+    {
+      dt = (struct datatype *) xmalloc(sizeof(struct datatype));
+      
+      if( dt != NULL )
+	{
+	  memset(dt, 0, sizeof(*dt));
+      
+	  dt->type = xtype;
+	  if( typename != NULL )
+	    {
+	      dt->name = xstrdup(typename);
+	    }
+	  else
+	    {
+	      dt->name = NULL;
+	    }
+	  if( xtype == POINTER )
+	    {
+	      dt->next = pointer_types;
+	      pointer_types = dt;
+	    }
+	  else
+	    {
+	      dt->next = type_hash_table[hash];
+	      type_hash_table[hash] = dt;
+	    }
+	}
+    }
+
+  return dt;
+}
+
+struct datatype *
+DEBUG_FindOrMakePointerType(struct datatype * reftype)
+{
+  struct datatype * dt = NULL;
+
+  if( reftype != NULL )
+    {
+      for( dt = pointer_types; dt; dt = dt->next )
+	{
+	  if( dt->type != POINTER )
+	    {
+	      continue;
+	    }
+	  	  
+	  if( dt->un.pointer.pointsto == reftype )
+	    {
+	      return dt;
+	    }
+	}
+    }
+
+  if( dt == NULL )
+    {
+      dt = (struct datatype *) xmalloc(sizeof(struct datatype));
+      
+      if( dt != NULL )
+	{
+	  dt->type = POINTER;
+	  dt->un.pointer.pointsto = reftype;
+	  dt->next = pointer_types;
+	  pointer_types = dt;
+	}
+    }
+
+  return dt;
+}
+
+void
+DEBUG_InitTypes()
+{
+  static int beenhere = 0;
+  struct datatype * chartype;
+
+  if( beenhere++ != 0 )
+    {
+      return;
+    }
+
+  /*
+   * Special version of int used with constants of various kinds.
+   */
+  DEBUG_TypeIntConst = DEBUG_InitBasic(BASIC_INT,NULL,4,1,"%d");
+
+  /*
+   * Initialize a few builtin types.
+   */
+
+
+  DEBUG_TypeInt = DEBUG_InitBasic(BASIC_INT,"int",4,1,"%d");
+  chartype = DEBUG_InitBasic(BASIC_CHAR,"char",1,1,"'%c'");
+  DEBUG_InitBasic(BASIC_LONG,"long int",4,1,"%d");
+  DEBUG_TypeUSInt = DEBUG_InitBasic(BASIC_UINT,"unsigned int",4,0,"%d");
+  DEBUG_InitBasic(BASIC_LUI,"long unsigned int",4,0,"%d");
+  DEBUG_InitBasic(BASIC_LONGLONG,"long long int",8,1,"%ld");
+  DEBUG_InitBasic(BASIC_ULONGLONGI,"long long unsigned int",8,0,"%ld");
+  DEBUG_InitBasic(BASIC_SHORT,"short int",2,1,"%d");
+  DEBUG_InitBasic(BASIC_SHORTUI,"short unsigned int",2,0,"%d");
+  DEBUG_InitBasic(BASIC_SCHAR,"signed char",1,1,"'%c'");
+  DEBUG_InitBasic(BASIC_UCHAR,"unsigned char",1,0,"'%c'");
+  DEBUG_InitBasic(BASIC_FLT,"float",4,0,"%f");
+  DEBUG_InitBasic(BASIC_LONG_DOUBLE,"double",8,0,"%lf");
+  DEBUG_InitBasic(BASIC_DOUBLE,"long double",12,0,NULL);
+  DEBUG_InitBasic(BASIC_CMPLX_INT,"complex int",8,1,NULL);
+  DEBUG_InitBasic(BASIC_CMPLX_FLT,"complex float",8,0,NULL);
+  DEBUG_InitBasic(BASIC_CMPLX_DBL,"complex double",16,0,NULL);
+  DEBUG_InitBasic(BASIC_CMPLX_LONG_DBL,"complex long double",24,0,NULL);
+  DEBUG_InitBasic(BASIC_VOID,"void",0,0,NULL);
+
+  DEBUG_TypeString = DEBUG_NewDataType(POINTER, NULL);
+  DEBUG_SetPointerType(DEBUG_TypeString, chartype);
+
+  /*
+   * Now initialize the builtins for codeview.
+   */
+  DEBUG_InitCVDataTypes();
+
+}
+
+long long int
+DEBUG_GetExprValue(DBG_ADDR * addr, char ** format)
+{
+  unsigned int rtn;
+  struct datatype * type2 = NULL;
+  struct en_values * e;
+  char * def_format = "0x%x";
+
+  rtn = 0;
+  assert(addr->type != NULL);
+
+  switch(addr->type->type)
+    {
+    case BASIC:
+      memcpy(&rtn, (char *) addr->off, addr->type->un.basic.basic_size);
+      if(    (addr->type->un.basic.b_signed)
+	  && ((addr->type->un.basic.basic_size & 3) != 0)
+	  && ((rtn >> (addr->type->un.basic.basic_size * 8 - 1)) != 0) )
+	{
+	  rtn = rtn | ((-1) << (addr->type->un.basic.basic_size * 8));
+	}
+      if( addr->type->un.basic.output_format != NULL )
+	{
+	  def_format = addr->type->un.basic.output_format;
+	}
+
+      /*
+       * Check for single character prints that are out of range.
+       */
+      if( addr->type->un.basic.basic_size == 1
+	  && strcmp(def_format, "'%c'") == 0 
+	  && ((rtn < 0x20) || (rtn > 0x80)) )
+	{
+	  def_format = "%d";
+	}
+      break;
+    case POINTER:
+      if (!DBG_CHECK_READ_PTR( addr, 1 )) return 0;
+      rtn = (unsigned int)  *((unsigned char **)addr->off);
+      type2 = addr->type->un.pointer.pointsto;
+      if( type2->type == BASIC && type2->un.basic.basic_size == 1 )
+	{
+	  def_format = "\"%s\"";
+	  break;
+	}
+      else
+	{
+	  def_format = "0x%8.8x";
+	}
+      break;
+    case ARRAY:
+    case STRUCT:
+      if (!DBG_CHECK_READ_PTR( addr, 1 )) return 0;
+      rtn = (unsigned int)  *((unsigned char **)addr->off);
+      def_format = "0x%8.8x";
+      break;
+    case ENUM:
+      rtn = (unsigned int)  *((unsigned char **)addr->off);
+      for(e = addr->type->un.enumeration.members; e; e = e->next )
+	{
+	  if( e->value == rtn )
+	    {
+	      break;
+	    }
+	}
+      if( e != NULL )
+	{
+	  rtn = (int) e->name;
+	  def_format = "%s";
+	}
+      else
+	{
+	  def_format = "%d";
+	}
+      break;
+    default:
+      rtn = 0;
+      break;
+    }
+
+
+  if( format != NULL )
+    {
+      *format = def_format;
+    }
+  return rtn;
+}
+
+unsigned int
+DEBUG_TypeDerefPointer(DBG_ADDR * addr, struct datatype ** newtype)
+{
+  /*
+   * Make sure that this really makes sense.
+   */
+  if( addr->type->type != POINTER )
+    {
+      *newtype = NULL;
+      return 0;
+    }
+
+  *newtype = addr->type->un.pointer.pointsto;
+  return *(unsigned int*) (addr->off);
+}
+
+unsigned int
+DEBUG_FindStructElement(DBG_ADDR * addr, const char * ele_name, int * tmpbuf)
+{
+  struct member * m;
+  unsigned int    mask;
+
+  /*
+   * Make sure that this really makes sense.
+   */
+  if( addr->type->type != STRUCT )
+    {
+      addr->type = NULL;
+      return FALSE;
+    }
+
+  for(m = addr->type->un.structure.members; m; m = m->next)
+    {
+      if( strcmp(m->name, ele_name) == 0 )
+	{
+	  addr->type = m->type;
+	  if( (m->offset & 7) != 0 || (m->size & 7) != 0)
+	    {
+	      /*
+	       * Bitfield operation.  We have to extract the field and store
+	       * it in a temporary buffer so that we get it all right.
+	       */
+	      *tmpbuf = ((*(int* ) (addr->off + (m->offset >> 3))) >> (m->offset & 7));
+	      addr->off = (int) tmpbuf;
+
+	      mask = 0xffffffff << (m->size);
+	      *tmpbuf &= ~mask;
+	      /*
+	       * OK, now we have the correct part of the number.
+	       * Check to see whether the basic type is signed or not, and if so,
+	       * we need to sign extend the number.
+	       */
+	      if( m->type->type == BASIC && m->type->un.basic.b_signed != 0
+		  && (*tmpbuf & (1 << (m->size - 1))) != 0 )
+		{
+		  *tmpbuf |= mask;
+		}
+	    }
+	  else
+	    {
+	      addr->off += (m->offset >> 3);
+	    }
+	  return TRUE;
+	}
+    }
+
+  addr->type = NULL;
+  return FALSE;
+}
+
+int
+DEBUG_SetStructSize(struct datatype * dt, int size)
+{
+  assert(dt->type == STRUCT);
+  dt->un.structure.size = size;
+  dt->un.structure.members = NULL;
+
+  return TRUE;
+}
+
+int
+DEBUG_CopyFieldlist(struct datatype * dt, struct datatype * dt2)
+{
+
+  assert( dt->type == dt2->type && ((dt->type == STRUCT) || (dt->type == ENUM)));
+
+  if( dt->type == STRUCT )
+    {
+      dt->un.structure.members = dt2->un.structure.members;
+    }
+  else
+    {
+      dt->un.enumeration.members = dt2->un.enumeration.members;
+    }
+
+  return TRUE;
+}
+
+int
+DEBUG_AddStructElement(struct datatype * dt, char * name, struct datatype * type, 
+		       int offset, int size)
+{
+  struct member * m;
+  struct member * last;
+  struct en_values * e;
+
+  if( dt->type == STRUCT )
+    {
+      for(last = dt->un.structure.members; last; last = last->next)
+	{
+	  if(    (last->name[0] == name[0]) 
+	      && (strcmp(last->name, name) == 0) )
+	    {
+	      return TRUE;
+	    }
+	  if( last->next == NULL )
+	    {
+	      break;
+	    }
+	}
+      m = (struct member *) xmalloc(sizeof(struct member));
+      if( m == FALSE )
+	{
+	  return FALSE;
+	}
+      
+      m->name = xstrdup(name);
+      m->type = type;
+      m->offset = offset;
+      m->size = size;
+      if( last == NULL )
+	{
+	  m->next = dt->un.structure.members;
+	  dt->un.structure.members = m;
+	}
+      else
+	{
+	  last->next = m;
+	  m->next = NULL;
+	}
+      /*
+       * If the base type is bitfield, then adjust the offsets here so that we
+       * are able to look things up without lots of falter-all.
+       */
+      if( type->type == BITFIELD )
+	{
+	  m->offset += m->type->un.bitfield.bitoff;
+	  m->size = m->type->un.bitfield.nbits;
+	  m->type = m->type->un.bitfield.basetype;
+	}
+    }
+  else if( dt->type == ENUM )
+    {
+      e = (struct en_values *) xmalloc(sizeof(struct en_values));
+      if( e == FALSE )
+	{
+	  return FALSE;
+	}
+      
+      e->name = xstrdup(name);
+      e->value = offset;
+      e->next = dt->un.enumeration.members;
+      dt->un.enumeration.members = e;
+    }
+  else
+    {
+      assert(FALSE);
+    }
+  return TRUE;
+}
+
+struct datatype * 
+DEBUG_GetPointerType(struct datatype * dt)
+{
+  if( dt->type == POINTER )
+    {
+      return dt->un.pointer.pointsto;
+    }
+
+  return NULL;
+}
+
+int
+DEBUG_SetPointerType(struct datatype * dt, struct datatype * dt2)
+{
+  switch(dt->type)
+    {
+    case POINTER:
+      dt->un.pointer.pointsto = dt2;
+      break;
+    case FUNC:
+      dt->un.funct.rettype = dt2;
+      break;
+    default:
+      assert(FALSE);
+    }
+
+  return TRUE;
+}
+
+int
+DEBUG_SetArrayParams(struct datatype * dt, int min, int max, struct datatype * dt2)
+{
+  assert(dt->type == ARRAY);
+  dt->un.array.start = min;
+  dt->un.array.end   = max;
+  dt->un.array.basictype = dt2;
+
+  return TRUE;
+}
+
+int
+DEBUG_SetBitfieldParams(struct datatype * dt, int offset, int nbits, 
+			struct datatype * dt2)
+{
+  assert(dt->type == BITFIELD);
+  dt->un.bitfield.bitoff   = offset;
+  dt->un.bitfield.nbits    = nbits;
+  dt->un.bitfield.basetype = dt2;
+
+  return TRUE;
+}
+
+int DEBUG_GetObjectSize(struct datatype * dt)
+{
+  if( dt == NULL )
+    {
+      return 0;
+    }
+
+  switch(dt->type)
+    {
+    case BASIC:
+      return dt->un.basic.basic_size;
+    case POINTER:
+      return sizeof(int *);
+    case STRUCT:
+      return dt->un.structure.size;
+    case ENUM:
+      return sizeof(int);
+    case ARRAY:
+      return (dt->un.array.end - dt->un.array.start) 
+	* DEBUG_GetObjectSize(dt->un.array.basictype);
+    case BITFIELD:
+      /*
+       * Bitfields have to be handled seperately later on
+       * when we insert the element into the structure.
+       */
+      return 0;
+    case TYPEDEF:
+    case FUNC:
+    case CONST:
+      assert(FALSE);
+    }
+  return 0;
+}
+
+unsigned int
+DEBUG_ArrayIndex(DBG_ADDR * addr, DBG_ADDR * result, int index)
+{
+  int size;
+
+  /*
+   * Make sure that this really makes sense.
+   */
+  if( addr->type->type == POINTER )
+    {
+      /*
+       * Get the base type, so we know how much to index by.
+       */
+      size = DEBUG_GetObjectSize(addr->type->un.pointer.pointsto);
+      result->type = addr->type->un.pointer.pointsto;
+      result->off = (*(unsigned int*) (addr->off)) + size * index;
+    }
+  else if (addr->type->type == ARRAY)
+    {
+      size = DEBUG_GetObjectSize(addr->type->un.array.basictype);
+      result->type = addr->type->un.array.basictype;
+      result->off = addr->off + size * (index - addr->type->un.array.start);
+    }
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *           DEBUG_Print
+ *
+ * Implementation of the 'print' command.
+ */
+void DEBUG_Print( const DBG_ADDR *addr, int count, char format, int level )
+{
+  DBG_ADDR	  addr1;
+  int		  i;
+  struct member * m;
+  char		* pnt;
+  int		  size;
+  long long int   value;
+
+  if (count != 1)
+    {
+      fprintf( stderr, "Count other than 1 is meaningless in 'print' command\n" );
+      return;
+    }
+  
+  if( addr->type == NULL )
+    {
+      fprintf(stderr, "Unable to evaluate expression\n");
+      return;
+    }
+  
+  if( format == 'i' || format == 's' || format == 'w' || format == 'b' )
+    {
+      fprintf( stderr, "Format specifier '%c' is meaningless in 'print' command\n", format );
+      format = '\0';
+    }
+
+  switch(addr->type->type)
+    {
+    case BASIC:
+    case ENUM:
+    case CONST:
+    case POINTER:
+      DEBUG_PrintBasic(addr, 1, format);
+      break;
+    case STRUCT:
+      fprintf(stderr, "{");
+      for(m = addr->type->un.structure.members; m; m = m->next)
+	{
+	  addr1 = *addr;
+	  DEBUG_FindStructElement(&addr1, m->name,
+				  (int *) &value);
+	  fprintf(stderr, "%s=", m->name);
+	  DEBUG_Print(&addr1, 1, format, level + 1);
+	  if( m->next != NULL )
+	    {
+	      fprintf(stderr, ", ");
+	    }
+	}
+      fprintf(stderr, "}");
+      break;
+    case ARRAY:
+      /*
+       * Loop over all of the entries, printing stuff as we go.
+       */
+      size = DEBUG_GetObjectSize(addr->type->un.array.basictype);
+      if( size == 1 )
+	{
+	  /*
+	   * Special handling for character arrays.
+	   */
+	  pnt = (char *) addr->off;
+	  fprintf(stderr, "\"");
+	  for( i=addr->type->un.array.start; i < addr->type->un.array.end; i++ )
+	    {
+	      fputc(*pnt++, stderr);
+	    }
+	  fprintf(stderr, "\"");
+	  break;
+	}
+      addr1 = *addr;
+      addr1.type = addr->type->un.array.basictype;
+      fprintf(stderr, "{");
+      for( i=addr->type->un.array.start; i <= addr->type->un.array.end; i++ )
+	{
+	  DEBUG_Print(&addr1, 1, format, level + 1);
+	  addr1.off += size;
+	  if( i == addr->type->un.array.end )
+	    {
+	      fprintf(stderr, "}");
+	    }
+	  else
+	    {
+	      fprintf(stderr, ", ");
+	    }
+	}
+      break;
+    default:
+      assert(FALSE);
+      break;
+    }
+
+  if( level == 0 )
+    {
+      fprintf(stderr, "\n");
+    }
+}
diff --git a/documentation/wine_os2.txt b/documentation/wine_os2.txt
new file mode 100644
index 0000000..9b1c0e3
--- /dev/null
+++ b/documentation/wine_os2.txt
@@ -0,0 +1,35 @@
+	Running & Compiling WINE in OS/2
+
+Here is what you need to (try to) compile Wine for OS/2:
+EMX 0.9c (fix 2)
+XFree86 3.2 OS/2 (with development libraries)
+bash, gnu make, grep, tar, bison, flex
+sed (a working copy of)
+diff and patch are recommended
+
+To compile:
+sh
+tools/make_os2.sh
+make depend
+make (make doesn't work yet... I will need to do some others patch, or
+      you may do it...)
+
+Currently:
+- configure and make depend work...
+- make doesn't work
+- the selectors numbers (0) are wrong...
+
+What needs to be redone:
+File functions, I/O access (do it!), Interrupt (if int unknow, call
+current RealMode one...), verify that everything is thread safe (how
+does Win95/NT handle multi-thread?), move X functions in some files
+(and make a wrapper, to use PM instead latter), etc...
+
+The good things:
+- OS/2 have DOS interrupts
+- OS/2 have I/O port access
+- OS/2 have multi-thread
+- Merlin have Open32 (to be used later...)
+
+Robert Pouliot <krynos@clic.net>
+January 9, 1997
diff --git a/files/directory.c b/files/directory.c
index 157fea4..1c64f74 100644
--- a/files/directory.c
+++ b/files/directory.c
@@ -6,13 +6,13 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <errno.h>
 
 #include "windows.h"
 #include "winerror.h"
-#include "dos_fs.h"
 #include "drive.h"
 #include "file.h"
 #include "heap.h"
@@ -43,25 +43,20 @@
                         char **dos_path, char **unix_path )
 {
     char path[MAX_PATHNAME_LEN];
-    const char *dos_name ,*unix_name;
+    DOS_FULL_NAME full_name;
+
     BY_HANDLE_FILE_INFORMATION info;
 
     PROFILE_GetWineIniString( "wine", keyname, defval, path, sizeof(path) );
-    if (!(unix_name = DOSFS_GetUnixFileName( path, TRUE )) ||
-        !FILE_Stat( unix_name, &info ) ||
+    if (!DOSFS_GetFullName( path, TRUE, &full_name ) ||
+        !FILE_Stat( full_name.long_name, &info ) ||
         !(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
     {
         fprintf(stderr, "Invalid path '%s' for %s directory\n", path, keyname);
         return 0;
     }
-    if (!(dos_name = DOSFS_GetDosTrueName( unix_name, TRUE )))
-    {
-        fprintf( stderr, "Could not get DOS name for %s directory '%s'\n",
-                 keyname, unix_name );
-        return 0;
-    }
-    *unix_path = HEAP_strdupA( SystemHeap, 0, unix_name );
-    *dos_path  = HEAP_strdupA( SystemHeap, 0, dos_name );
+    *unix_path = HEAP_strdupA( SystemHeap, 0, full_name.long_name );
+    *dos_path  = HEAP_strdupA( SystemHeap, 0, full_name.short_name );
     return 1;
 }
 
@@ -72,7 +67,7 @@
 void DIR_ParseWindowsPath( char *path )
 {
     char *p;
-    const char *dos_name ,*unix_name;
+    DOS_FULL_NAME full_name;
     BY_HANDLE_FILE_INFORMATION info;
     int i;
 
@@ -87,22 +82,18 @@
                      MAX_PATH_ELEMENTS );
             break;
         }
-        if (!(unix_name = DOSFS_GetUnixFileName( path, TRUE )) ||
-            !FILE_Stat( unix_name, &info ) ||
+        if (!DOSFS_GetFullName( path, TRUE, &full_name ) ||
+            !FILE_Stat( full_name.long_name, &info ) ||
             !(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
         {
             fprintf(stderr,"Warning: invalid dir '%s' in path, deleting it.\n",
                     path );
             continue;
         }
-        if (!(dos_name = DOSFS_GetDosTrueName( unix_name, TRUE )))
-        {
-            fprintf( stderr, "Warning: could not get DOS name for '%s' in path, deleting it.\n",
-                     unix_name );
-            continue;
-        }
-        DIR_UnixPath[DIR_PathElements] = HEAP_strdupA(SystemHeap,0,unix_name);
-        DIR_DosPath[DIR_PathElements]  = HEAP_strdupA(SystemHeap,0,dos_name);
+        DIR_UnixPath[DIR_PathElements] = HEAP_strdupA( SystemHeap, 0,
+                                                       full_name.long_name );
+        DIR_DosPath[DIR_PathElements]  = HEAP_strdupA( SystemHeap, 0,
+                                                       full_name.short_name );
         DIR_PathElements++;
     }
 
@@ -137,9 +128,8 @@
     }
     else
     {
-        cwd = DOSFS_GetDosTrueName( path, TRUE );
         DRIVE_SetCurrentDrive( drive );
-        DRIVE_Chdir( drive, cwd + 2 );
+        DRIVE_Chdir( drive, cwd );
     }
 
     if (!(DIR_GetPath( "windows", "c:\\windows",
@@ -344,7 +334,8 @@
  */
 BOOL32 CreateDirectory32A( LPCSTR path, LPSECURITY_ATTRIBUTES lpsecattribs )
 {
-    const char *unixName;
+    DOS_FULL_NAME full_name;
+    LPCSTR unixName;
 
     dprintf_file( stddeb, "CreateDirectory32A(%s,%p)\n", path, lpsecattribs );
     if ((unixName = DOSFS_IsDevice( path )) != NULL)
@@ -353,8 +344,8 @@
         DOS_ERROR( ER_AccessDenied, EC_AccessDenied, SA_Abort, EL_Disk );
         return FALSE;
     }
-    if (!(unixName = DOSFS_GetUnixFileName( path, FALSE ))) return 0;
-    if ((mkdir( unixName, 0777 ) == -1) && (errno != EEXIST))
+    if (!DOSFS_GetFullName( path, FALSE, &full_name )) return 0;
+    if ((mkdir( full_name.long_name, 0777 ) == -1) && (errno != EEXIST))
     {
         FILE_SetDosError();
         return FALSE;
@@ -409,7 +400,8 @@
  */
 BOOL32 RemoveDirectory32A( LPCSTR path )
 {
-    const char *unixName;
+    DOS_FULL_NAME full_name;
+    LPCSTR unixName;
 
     dprintf_file(stddeb, "RemoveDirectory: '%s'\n", path );
 
@@ -419,8 +411,8 @@
         DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
         return FALSE;
     }
-    if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return FALSE;
-    if (rmdir( unixName ) == -1)
+    if (!DOSFS_GetFullName( path, TRUE, &full_name )) return FALSE;
+    if (rmdir( full_name.long_name ) == -1)
     {
         FILE_SetDosError();
         return FALSE;
@@ -442,6 +434,56 @@
 
 
 /***********************************************************************
+ *           DIR_TryPath
+ *
+ * Helper function for DIR_SearchPath.
+ */
+static BOOL32 DIR_TryPath( LPCSTR unix_dir, LPCSTR dos_dir, LPCSTR name,
+                           DOS_FULL_NAME *full_name )
+{
+    LPSTR p_l = full_name->long_name + strlen(unix_dir) + 1;
+    LPSTR p_s = full_name->short_name + strlen(dos_dir) + 1;
+
+    if ((p_s >= full_name->short_name + sizeof(full_name->short_name) - 14) ||
+        (p_l >= full_name->long_name + sizeof(full_name->long_name) - 1))
+    {
+        DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
+        return FALSE;
+    }
+    if (!DOSFS_FindUnixName( unix_dir, name, p_l,
+                   sizeof(full_name->long_name) - (p_l - full_name->long_name),
+                   p_s, DRIVE_GetFlags( dos_dir[0] - 'A' ) ))
+        return FALSE;
+    strcpy( full_name->long_name, unix_dir );
+    p_l[-1] = '/';
+    strcpy( full_name->short_name, dos_dir );
+    p_s[-1] = '\\';
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           DIR_TryModulePath
+ *
+ * Helper function for DIR_SearchPath.
+ */
+static BOOL32 DIR_TryModulePath( LPCSTR name, DOS_FULL_NAME *full_name )
+{
+    /* FIXME: for now, GetModuleFileName32A can't return more */
+    /* than OFS_MAXPATHNAME. This may change with Win32. */
+    char buffer[OFS_MAXPATHNAME];
+    LPSTR p;
+
+    if (!GetCurrentTask()) return FALSE;
+    GetModuleFileName32A( GetCurrentTask(), buffer, sizeof(buffer) );
+    if (!(p = strrchr( buffer, '\\' ))) return FALSE;
+    if (sizeof(buffer) - (++p - buffer) <= strlen(name)) return FALSE;
+    strcpy( p, name );
+    return DOSFS_GetFullName( buffer, TRUE, full_name );
+}
+
+
+/***********************************************************************
  *           DIR_SearchPath
  *
  * Implementation of SearchPath32A. 'win32' specifies whether the search
@@ -450,17 +492,24 @@
  * FIXME: should return long path names.
  */
 DWORD DIR_SearchPath( LPCSTR path, LPCSTR name, LPCSTR ext,
-                      DWORD buflen, LPSTR buffer, LPSTR *lastpart,
-                      BOOL32 win32 )
+                      DOS_FULL_NAME *full_name, BOOL32 win32 )
 {
     DWORD len;
-    LPSTR tmp;
+    LPCSTR p;
     int i;
+    LPSTR tmp = NULL;
+    BOOL32 ret = TRUE;
 
     /* First check the supplied parameters */
 
-    if (strchr( name, '.' )) ext = NULL;  /* Ignore the specified extension */
+    if (!(p = strrchr( name, '\\' ))) p = name;
+    if (!(p = strrchr( p, '/' ))) p = name;
+    if (strchr( p, '.' )) ext = NULL;  /* Ignore the specified extension */
+    if ((*name && (name[1] == ':')) ||
+        strchr( name, '/' ) || strchr( name, '\\' ))
+        path = NULL;  /* Ignore path if name already contains a path */
     if (path && !*path) path = NULL;  /* Ignore empty path */
+
     len = strlen(name);
     if (ext) len += strlen(ext);
     if (path) len += strlen(path) + 1;
@@ -482,110 +531,52 @@
         }
         else strcpy( tmp, name );
         if (ext) strcat( tmp, ext );
+        name = tmp;
     }
-    else tmp = (LPSTR)name;
     
     /* If we have an explicit path, everything's easy */
 
-    if (path || (*tmp && (tmp[1] == ':')) ||
-        strchr( tmp, '/' ) || strchr( tmp, '\\' ))
+    if (path || (*name && (name[1] == ':')) ||
+        strchr( name, '/' ) || strchr( name, '\\' ))
     {
-        if (!DOSFS_GetUnixFileName( tmp, TRUE )) goto not_found;
-        lstrcpyn32A( buffer, tmp, buflen );
-        if (tmp != name) HeapFree( GetProcessHeap(), 0, tmp );
-        return len;
+        ret = DOSFS_GetFullName( name, TRUE, full_name );
+        goto done;
     }
 
     /* Try the path of the current executable (for Win32 search order) */
 
-    if (win32 && GetCurrentTask())
-    {
-        LPSTR p;
-        GetModuleFileName32A( GetCurrentTask(), buffer, buflen );
-        if ((p = strrchr( buffer, '\\' )))
-        {
-            lstrcpyn32A( p + 1, tmp, (INT32)buflen - (p - buffer) );
-            if (DOSFS_GetUnixFileName( buffer, TRUE ))
-            {
-                *p = '\0';
-                goto found;
-            }
-        }
-    }
+    if (win32 && DIR_TryModulePath( name, full_name )) goto done;
 
     /* Try the current directory */
 
-    if (DOSFS_GetUnixFileName( tmp, TRUE ))
-    {
-        GetCurrentDirectory32A( buflen, buffer );
-        goto found;
-    }
+    if (DOSFS_GetFullName( name, TRUE, full_name )) goto done;
 
     /* Try the Windows directory */
 
-    if (DOSFS_FindUnixName( DIR_WindowsUnixDir, name, NULL, 0,
-                            DRIVE_GetFlags( DIR_WindowsDosDir[0] - 'A' ) ))
-    {
-        lstrcpyn32A( buffer, DIR_WindowsDosDir, buflen );
-        goto found;
-    }
+    if (DIR_TryPath( DIR_WindowsUnixDir, DIR_WindowsDosDir, name, full_name ))
+        goto done;
 
     /* Try the Windows system directory */
 
-    if (DOSFS_FindUnixName( DIR_SystemUnixDir, name, NULL, 0,
-                            DRIVE_GetFlags( DIR_SystemDosDir[0] - 'A' ) ))
-    {
-        lstrcpyn32A( buffer, DIR_SystemDosDir, buflen );
-        goto found;
-    }
+    if (DIR_TryPath( DIR_SystemUnixDir, DIR_SystemDosDir, name, full_name ))
+        goto done;
 
     /* Try the path of the current executable (for Win16 search order) */
 
-    if (!win32 && GetCurrentTask())
-    {
-        LPSTR p;
-        GetModuleFileName32A( GetCurrentTask(), buffer, buflen );
-        if ((p = strrchr( buffer, '\\' )))
-        {
-            lstrcpyn32A( p + 1, tmp, (INT32)buflen - (p - buffer) );
-            if (DOSFS_GetUnixFileName( buffer, TRUE ))
-            {
-                *p = '\0';
-                goto found;
-            }
-        }
-    }
+    if (!win32 && DIR_TryModulePath( name, full_name )) goto done;
+
     /* Try all directories in path */
 
     for (i = 0; i < DIR_PathElements; i++)
     {
-        if (DOSFS_FindUnixName( DIR_UnixPath[i], name, NULL, 0,
-                                DRIVE_GetFlags( DIR_DosPath[i][0] - 'A' ) ))
-        {
-            lstrcpyn32A( buffer, DIR_DosPath[i], buflen );
-            goto found;
-        }
+        if (DIR_TryPath( DIR_UnixPath[i], DIR_DosPath[i], name, full_name ))
+            goto done;
     }
 
-not_found:
-    if (tmp != name) HeapFree( GetProcessHeap(), 0, tmp );
-    SetLastError( ERROR_FILE_NOT_FOUND );
-    DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
-    return 0;
-
-found:
-    len = strlen(buffer);
-    if (lastpart) *lastpart = buffer + len + 1;
-    if (len + 1 < buflen)
-    {
-        buffer += len;
-        *buffer++ = '\\';
-        buflen -= len + 1;
-        lstrcpyn32A( buffer, tmp, buflen );
-    }
-    len += strlen(tmp) + 1;
-    if (tmp != name) HeapFree( GetProcessHeap(), 0, tmp );
-    return len;
+    ret = FALSE;
+done:
+    if (tmp) HeapFree( GetProcessHeap(), 0, tmp );
+    return ret;
 }
 
 
@@ -595,7 +586,17 @@
 DWORD SearchPath32A( LPCSTR path, LPCSTR name, LPCSTR ext, DWORD buflen,
                      LPSTR buffer, LPSTR *lastpart )
 {
-    return DIR_SearchPath( path, name, ext, buflen, buffer, lastpart, TRUE );
+    LPSTR p, res;
+    DOS_FULL_NAME full_name;
+
+    if (!DIR_SearchPath( path, name, ext, &full_name, TRUE )) return 0;
+    lstrcpyn32A( buffer, full_name.short_name, buflen );
+    res = full_name.long_name +
+              strlen(DRIVE_GetRoot( full_name.short_name[0] - 'A' ));
+    if (*res && (buflen > 3)) lstrcpyn32A( buffer + 3, res + 1, buflen - 3 );
+    for (p = buffer; *p; p++) if (*p == '/') *p = '\\';
+    if (lastpart) *lastpart = strrchr( buffer, '\\' ) + 1;
+    return *res ? strlen(res) + 2 : 3;
 }
 
 
@@ -605,25 +606,30 @@
 DWORD SearchPath32W( LPCWSTR path, LPCWSTR name, LPCWSTR ext, DWORD buflen,
                      LPWSTR buffer, LPWSTR *lastpart )
 {
+    LPWSTR p;
+    LPSTR res;
+    DOS_FULL_NAME full_name;
+
     LPSTR pathA = HEAP_strdupWtoA( GetProcessHeap(), 0, path );
     LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
     LPSTR extA  = HEAP_strdupWtoA( GetProcessHeap(), 0, ext );
-    LPSTR lastpartA;
-    LPSTR bufferA = HeapAlloc( GetProcessHeap(), 0, buflen + 1 );
-
-    DWORD ret = DIR_SearchPath( pathA, nameA, extA, buflen, bufferA,
-                                &lastpartA, TRUE );
-    lstrcpyAtoW( buffer, bufferA );
-    if (lastpart)
-    {
-        if (lastpartA) *lastpart = buffer + (lastpartA - bufferA);
-        else *lastpart = NULL;
-    }
-    HeapFree( GetProcessHeap(), 0, bufferA );
+    DWORD ret = DIR_SearchPath( pathA, nameA, extA, &full_name, TRUE );
     HeapFree( GetProcessHeap(), 0, extA );
     HeapFree( GetProcessHeap(), 0, nameA );
     HeapFree( GetProcessHeap(), 0, pathA );
-    return ret;
+    if (!ret) return 0;
+
+    lstrcpynAtoW( buffer, full_name.short_name, buflen );
+    res = full_name.long_name +
+              strlen(DRIVE_GetRoot( full_name.short_name[0] - 'A' ));
+    if (*res && (buflen > 3)) lstrcpynAtoW( buffer + 3, res + 1, buflen - 3 );
+    for (p = buffer; *p; p++) if (*p == '/') *p = '\\';
+    if (lastpart)
+    {
+        for (p = *lastpart = buffer; *p; p++)
+            if (*p == '\\') *lastpart = p + 1;
+    }
+    return *res ? strlen(res) + 2 : 3;
 }
 
 
diff --git a/files/dos_fs.c b/files/dos_fs.c
index fb3c0e7..9b081a0 100644
--- a/files/dos_fs.c
+++ b/files/dos_fs.c
@@ -22,7 +22,6 @@
 
 #include "windows.h"
 #include "winerror.h"
-#include "dos_fs.h"
 #include "drive.h"
 #include "file.h"
 #include "heap.h"
@@ -31,13 +30,12 @@
 #include "debug.h"
 
 /* Define the VFAT ioctl to get both short and long file names */
-#if 0  /* not working yet */
+/* FIXME: is it possible to get this to work on other systems? */
 #ifdef linux
 #define VFAT_IOCTL_READDIR_BOTH  _IOR('r', 1, long)
 #else   /* linux */
 #undef VFAT_IOCTL_READDIR_BOTH  /* just in case... */
 #endif  /* linux */
-#endif
 
 /* Chars we don't want to see in DOS file names */
 #define INVALID_DOS_CHARS  "*?<>|\"+=,;[] \345"
@@ -58,6 +56,7 @@
     { "COM4", "" }
 };
 
+
 #define GET_DRIVE(path) \
     (((path)[1] == ':') ? toupper((path)[0]) - 'A' : DOSFS_CurDrive)
 
@@ -134,47 +133,17 @@
 
 
 /***********************************************************************
- *           DOSFS_CheckDotDot
- *
- * Remove all '.' and '..' at the beginning of 'name'.
- */
-static const char * DOSFS_CheckDotDot( const char *name, char *buffer,
-                                       char sep , int *len )
-{
-    char *p = buffer + strlen(buffer);
-
-    while (*name == '.')
-    {
-        if (IS_END_OF_NAME(name[1]))
-        {
-            name++;
-            while ((*name == '\\') || (*name == '/')) name++;
-        }
-        else if ((name[1] == '.') && IS_END_OF_NAME(name[2]))
-        {
-            name += 2;
-            while ((*name == '\\') || (*name == '/')) name++;
-            while ((p > buffer) && (*p != sep)) { p--; (*len)++; }
-            *p = '\0';  /* Remove trailing separator */
-        }
-        else break;
-    }
-    return name;
-}
-
-
-/***********************************************************************
  *           DOSFS_ToDosFCBFormat
  *
  * Convert a file name to DOS FCB format (8+3 chars, padded with blanks),
  * expanding wild cards and converting to upper-case in the process.
  * File name can be terminated by '\0', '\\' or '/'.
- * Return NULL if the name is not a valid DOS name.
+ * Return FALSE if the name is not a valid DOS name.
+ * 'buffer' must be at least 12 characters long.
  */
-const char *DOSFS_ToDosFCBFormat( const char *name )
+BOOL32 DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer )
 {
     static const char invalid_chars[] = INVALID_DOS_CHARS;
-    static char buffer[12];
     const char *p = name;
     int i;
 
@@ -188,7 +157,7 @@
             buffer[1] = '.';
             p++;
         }
-        return (!*p || (*p == '/') || (*p == '\\')) ? buffer : NULL;
+        return (!*p || (*p == '/') || (*p == '\\'));
     }
 
     for (i = 0; i < 8; i++)
@@ -208,7 +177,7 @@
             buffer[i] = '?';
             break;
         default:
-            if (strchr( invalid_chars, *p )) return NULL;
+            if (strchr( invalid_chars, *p )) return FALSE;
             buffer[i] = toupper(*p);
             p++;
             break;
@@ -223,7 +192,7 @@
     else
     {
         /* Check if name too long */
-        if (*p && (*p != '/') && (*p != '\\') && (*p != '.')) return NULL;
+        if (*p && (*p != '/') && (*p != '\\') && (*p != '.')) return FALSE;
     }
     if (*p == '.') p++;  /* Skip dot */
 
@@ -237,7 +206,7 @@
             buffer[i] = ' ';
             break;
         case '.':
-            return NULL;  /* Second extension not allowed */
+            return FALSE;  /* Second extension not allowed */
         case '?':
             p++;
             /* fall through */
@@ -245,14 +214,14 @@
             buffer[i] = '?';
             break;
         default:
-            if (strchr( invalid_chars, *p )) return NULL;
+            if (strchr( invalid_chars, *p )) return FALSE;
             buffer[i] = toupper(*p);
             p++;
             break;
         }
     }
     buffer[11] = '\0';
-    return buffer;
+    return TRUE;
 }
 
 
@@ -262,11 +231,10 @@
  * Convert a file name from FCB to DTA format (name.ext, null-terminated)
  * converting to upper-case in the process.
  * File name can be terminated by '\0', '\\' or '/'.
- * Return NULL if the name is not a valid DOS name.
+ * 'buffer' must be at least 13 characters long.
  */
-const char *DOSFS_ToDosDTAFormat( const char *name )
+static void DOSFS_ToDosDTAFormat( LPCSTR name, LPSTR buffer )
 {
-    static char buffer[13];
     char *p;
 
     memcpy( buffer, name, 8 );
@@ -276,7 +244,6 @@
     for (p += 3; p[-1] == ' '; p--);
     if (p[-1] == '.') p--;
     *p = '\0';
-    return buffer;
 }
 
 
@@ -397,13 +364,11 @@
 #ifdef VFAT_IOCTL_READDIR_BOTH
     if (dir->fd != -1)
     {
-        LPCSTR fcb_name;
         if (ioctl( dir->fd, VFAT_IOCTL_READDIR_BOTH, (long)dir->dirent ) == -1)
             return FALSE;
         if (!dir->dirent[0].d_reclen) return FALSE;
-        fcb_name = DOSFS_ToDosFCBFormat( dir->dirent[0].d_name );
-        if (fcb_name) strcpy( dir->short_name, fcb_name );
-        else dir->short_name[0] = '\0';
+        if (!DOSFS_ToDosFCBFormat( dir->dirent[0].d_name, dir->short_name ))
+            dir->short_name[0] = '\0';
         *short_name = dir->short_name;
         if (dir->dirent[1].d_name[0]) *long_name = dir->dirent[1].d_name;
         else *long_name = dir->dirent[0].d_name;
@@ -419,80 +384,20 @@
 
 
 /***********************************************************************
- *           DOSFS_ToDosDateTime
- *
- * Convert a Unix time in the DOS date/time format.
- */
-void DOSFS_ToDosDateTime( time_t unixtime, WORD *pDate, WORD *pTime )
-{
-    struct tm *tm = localtime( &unixtime );
-    if (pTime)
-        *pTime = (tm->tm_hour << 11) + (tm->tm_min << 5) + (tm->tm_sec / 2);
-    if (pDate)
-        *pDate = ((tm->tm_year - 80) << 9) + ((tm->tm_mon + 1) << 5)
-                 + tm->tm_mday;
-}
-
-/***********************************************************************
- *           DOSFS_DosDateTimeToUnixTime
- *
- * Convert from the DOS (FAT) date/time format into Unix time
- * (borrowed from files/file.c)
- */
-time_t DOSFS_DosDateTimeToUnixTime( WORD date, WORD time )
-{
-    struct tm newtm;
-
-    newtm.tm_sec  = (time & 0x1f) * 2;
-    newtm.tm_min  = (time >> 5) & 0x3f;
-    newtm.tm_hour = (time >> 11);
-    newtm.tm_mday = (date & 0x1f);
-    newtm.tm_mon  = ((date >> 5) & 0x0f) - 1;
-    newtm.tm_year = (date >> 9) + 80;
-    return mktime( &newtm );
-}
-
-
-/***********************************************************************
- *           DOSFS_UnixTimeToFileTime
- *
- * Convert a Unix time to FILETIME format.
- */
-void DOSFS_UnixTimeToFileTime( time_t unixtime, FILETIME *filetime )
-{
-    /* FIXME :-) */
-    filetime->dwLowDateTime  = unixtime;
-    filetime->dwHighDateTime = 0;
-}
-
-
-/***********************************************************************
- *           DOSFS_FileTimeToUnixTime
- *
- * Convert a FILETIME format to Unix time.
- */
-time_t DOSFS_FileTimeToUnixTime( const FILETIME *filetime )
-{
-    /* FIXME :-) */
-    return filetime->dwLowDateTime;
-}
-
-
-/***********************************************************************
  *           DOSFS_Hash
  *
  * Transform a Unix file name into a hashed DOS name. If the name is a valid
  * DOS name, it is converted to upper-case; otherwise it is replaced by a
  * hashed version that fits in 8.3 format.
  * File name can be terminated by '\0', '\\' or '/'.
+ * 'buffer' must be at least 13 characters long.
  */
-static const char *DOSFS_Hash( const char *name, int dir_format,
-                               int ignore_case )
+static void DOSFS_Hash( LPCSTR name, LPSTR buffer, BOOL32 dir_format,
+                        BOOL32 ignore_case )
 {
     static const char invalid_chars[] = INVALID_DOS_CHARS "~.";
     static const char hash_chars[32] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345";
 
-    static char buffer[13];
     const char *p, *ext;
     char *dst;
     unsigned short hash;
@@ -508,7 +413,7 @@
             buffer[0] = '.';
             if (!dir_format) buffer[1] = buffer[2] = '\0';
             if (name[1] == '.') buffer[1] = '.';
-            return buffer;
+            return;
         }
 
         /* Simply copy the name, converting to uppercase */
@@ -523,55 +428,53 @@
                 *dst++ = toupper(*name);
         }
         if (!dir_format) *dst = '\0';
+        return;
+    }
+
+    /* Compute the hash code of the file name */
+    /* If you know something about hash functions, feel free to */
+    /* insert a better algorithm here... */
+    if (ignore_case)
+    {
+        for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
+            hash = (hash<<3) ^ (hash>>5) ^ tolower(*p) ^ (tolower(p[1]) << 8);
+        hash = (hash<<3) ^ (hash>>5) ^ tolower(*p); /* Last character*/
     }
     else
     {
-        /* Compute the hash code of the file name */
-        /* If you know something about hash functions, feel free to */
-        /* insert a better algorithm here... */
-        if (ignore_case)
-        {
-            for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
-                hash = (hash << 3) ^ (hash >> 5) ^ tolower(*p) ^ (tolower(p[1]) << 8);
-            hash = (hash << 3) ^ (hash >> 5) ^ tolower(*p); /* Last character*/
-        }
-        else
-        {
-            for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
-                hash = (hash << 3) ^ (hash >> 5) ^ *p ^ (p[1] << 8);
-            hash = (hash << 3) ^ (hash >> 5) ^ *p;  /* Last character */
-        }
-
-        /* Find last dot for start of the extension */
-        for (p = name+1, ext = NULL; !IS_END_OF_NAME(*p); p++)
-            if (*p == '.') ext = p;
-        if (ext && IS_END_OF_NAME(ext[1]))
-            ext = NULL;  /* Empty extension ignored */
-
-        /* Copy first 4 chars, replacing invalid chars with '_' */
-        for (i = 4, p = name, dst = buffer; i > 0; i--, p++)
-        {
-            if (IS_END_OF_NAME(*p) || (p == ext)) break;
-            *dst++ = strchr( invalid_chars, *p ) ? '_' : toupper(*p);
-        }
-        /* Pad to 5 chars with '~' */
-        while (i-- >= 0) *dst++ = '~';
-
-        /* Insert hash code converted to 3 ASCII chars */
-        *dst++ = hash_chars[(hash >> 10) & 0x1f];
-        *dst++ = hash_chars[(hash >> 5) & 0x1f];
-        *dst++ = hash_chars[hash & 0x1f];
-
-        /* Copy the first 3 chars of the extension (if any) */
-        if (ext)
-        {
-            if (!dir_format) *dst++ = '.';
-            for (i = 3, ext++; (i > 0) && !IS_END_OF_NAME(*ext); i--, ext++)
-                *dst++ = strchr( invalid_chars, *ext ) ? '_' : toupper(*ext);
-        }
-        if (!dir_format) *dst = '\0';
+        for (p = name, hash = 0xbeef; !IS_END_OF_NAME(p[1]); p++)
+            hash = (hash << 3) ^ (hash >> 5) ^ *p ^ (p[1] << 8);
+        hash = (hash << 3) ^ (hash >> 5) ^ *p;  /* Last character */
     }
-    return buffer;
+
+    /* Find last dot for start of the extension */
+    for (p = name+1, ext = NULL; !IS_END_OF_NAME(*p); p++)
+        if (*p == '.') ext = p;
+    if (ext && IS_END_OF_NAME(ext[1]))
+        ext = NULL;  /* Empty extension ignored */
+
+    /* Copy first 4 chars, replacing invalid chars with '_' */
+    for (i = 4, p = name, dst = buffer; i > 0; i--, p++)
+    {
+        if (IS_END_OF_NAME(*p) || (p == ext)) break;
+        *dst++ = strchr( invalid_chars, *p ) ? '_' : toupper(*p);
+    }
+    /* Pad to 5 chars with '~' */
+    while (i-- >= 0) *dst++ = '~';
+
+    /* Insert hash code converted to 3 ASCII chars */
+    *dst++ = hash_chars[(hash >> 10) & 0x1f];
+    *dst++ = hash_chars[(hash >> 5) & 0x1f];
+    *dst++ = hash_chars[hash & 0x1f];
+
+    /* Copy the first 3 chars of the extension (if any) */
+    if (ext)
+    {
+        if (!dir_format) *dst++ = '.';
+        for (i = 3, ext++; (i > 0) && !IS_END_OF_NAME(*ext); i--, ext++)
+            *dst++ = strchr( invalid_chars, *ext ) ? '_' : toupper(*ext);
+    }
+    if (!dir_format) *dst = '\0';
 }
 
 
@@ -581,31 +484,34 @@
  * Find the Unix file name in a given directory that corresponds to
  * a file name (either in Unix or DOS format).
  * File name can be terminated by '\0', '\\' or '/'.
- * Return 1 if OK, 0 if no file name matches.
+ * Return TRUE if OK, FALSE if no file name matches.
+ *
+ * 'long_buf' must be at least 'long_len' characters long. If the long name
+ * turns out to be larger than that, the function returns FALSE.
+ * 'short_buf' must be at least 13 characters long.
  */
-BOOL32 DOSFS_FindUnixName( const char *path, const char *name,
-                           char *buffer, int maxlen, UINT32 drive_flags )
+BOOL32 DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf,
+                           INT32 long_len, LPSTR short_buf, BOOL32 ignore_case)
 {
     DOS_DIR *dir;
     LPCSTR long_name, short_name;
-    char dos_name[12];
+    char dos_name[12], tmp_buf[13];
     BOOL32 ret;
 
     const char *p = strchr( name, '/' );
     int len = p ? (int)(p - name) : strlen(name);
+    if ((p = strchr( name, '\\' ))) len = MIN( (int)(p - name), len );
+    if (long_len < len + 1) return FALSE;
 
     dprintf_dosfs( stddeb, "DOSFS_FindUnixName: %s,%s\n", path, name );
 
-    if ((p = strchr( name, '\\' ))) len = MIN( (int)(p - name), len );
-
-    dos_name[0] = '\0';
-    if ((p = DOSFS_ToDosFCBFormat( name ))) strcpy( dos_name, p );
+    if (!DOSFS_ToDosFCBFormat( name, dos_name )) dos_name[0] = '\0';
 
     if (!(dir = DOSFS_OpenDir( path )))
     {
         dprintf_dosfs( stddeb, "DOSFS_FindUnixName(%s,%s): can't open dir\n",
                        path, name );
-        return 0;
+        return FALSE;
     }
 
     while ((ret = DOSFS_ReadDir( dir, &long_name, &short_name )))
@@ -613,7 +519,7 @@
         /* Check against Unix name */
         if (len == strlen(long_name))
         {
-            if (drive_flags & DRIVE_CASE_SENSITIVE)
+            if (!ignore_case)
             {
                 if (!lstrncmp32A( long_name, name, len )) break;
             }
@@ -626,14 +532,29 @@
         {
             /* Check against hashed DOS name */
             if (!short_name)
-                short_name = DOSFS_Hash( long_name, TRUE,
-                                       !(drive_flags & DRIVE_CASE_SENSITIVE) );
+            {
+                DOSFS_Hash( long_name, tmp_buf, TRUE, ignore_case );
+                short_name = tmp_buf;
+            }
             if (!strcmp( dos_name, short_name )) break;
         }
     }
-    if (ret && buffer) lstrcpyn32A( buffer, long_name, maxlen );
-    dprintf_dosfs( stddeb, "DOSFS_FindUnixName(%s,%s) -> %s\n",
-                   path, name, ret ? long_name : "** Not found **" );
+    if (ret)
+    {
+        if (long_buf) strcpy( long_buf, long_name );
+        if (short_buf)
+        {
+            if (short_name)
+                DOSFS_ToDosDTAFormat( short_name, short_buf );
+            else
+                DOSFS_Hash( long_name, short_buf, FALSE, ignore_case );
+        }
+        dprintf_dosfs( stddeb, "DOSFS_FindUnixName(%s,%s) -> %s (%s)\n",
+                       path, name, long_name, short_buf ? short_buf : "***");
+    }
+    else
+        dprintf_dosfs(stddeb,"DOSFS_FindUnixName(%s,%s) -> ** Not found **\n",
+                      path, name );
     DOSFS_CloseDir( dir );
     return ret;
 }
@@ -702,168 +623,278 @@
 
 
 /***********************************************************************
- *           DOSFS_GetUnixFileName
+ *           DOSFS_GetFullName
  *
- * Convert a file name (DOS or mixed DOS/Unix format) to a valid Unix name.
- * Return NULL if one of the path components does not exist. The last path
+ * Convert a file name (DOS or mixed DOS/Unix format) to a valid
+ * Unix name / short DOS name pair.
+ * Return FALSE if one of the path components does not exist. The last path
  * component is only checked if 'check_last' is non-zero.
+ * The buffers pointed to by 'long_buf' and 'short_buf' must be
+ * at least MAX_PATHNAME_LEN long.
  */
-const char * DOSFS_GetUnixFileName( const char * name, int check_last )
+BOOL32 DOSFS_GetFullName( LPCSTR name, BOOL32 check_last, DOS_FULL_NAME *full )
 {
-    static char buffer[MAX_PATHNAME_LEN];
-    int drive, len;
     BOOL32 found;
     UINT32 flags;
-    char *p, *root;
+    char *p_l, *p_s, *root;
 
-    dprintf_dosfs( stddeb, "DOSFS_GetUnixFileName: %s\n", name );
+    dprintf_dosfs( stddeb, "DOSFS_GetFullName: %s (last=%d)\n",
+                   name, check_last );
 
-    if ((drive = DOSFS_GetPathDrive( &name )) == -1) return NULL;
-    flags = DRIVE_GetFlags(drive);
-    lstrcpyn32A( buffer, DRIVE_GetRoot(drive), MAX_PATHNAME_LEN );
-    if (buffer[1]) root = buffer + strlen(buffer);
-    else root = buffer;  /* root directory */
+    if ((full->drive = DOSFS_GetPathDrive( &name )) == -1) return FALSE;
+    flags = DRIVE_GetFlags( full->drive );
 
-    if ((*name == '\\') || (*name == '/'))
+    lstrcpyn32A( full->long_name, DRIVE_GetRoot( full->drive ),
+                 sizeof(full->long_name) );
+    if (full->long_name[1]) root = full->long_name + strlen(full->long_name);
+    else root = full->long_name;  /* root directory */
+
+    strcpy( full->short_name, "A:\\" );
+    full->short_name[0] += full->drive;
+
+    if ((*name == '\\') || (*name == '/'))  /* Absolute path */
     {
         while ((*name == '\\') || (*name == '/')) name++;
     }
-    else
+    else  /* Relative path */
     {
-        lstrcpyn32A( root + 1, DRIVE_GetUnixCwd(drive),
-                     MAX_PATHNAME_LEN - (int)(root - buffer) - 1 );
+        lstrcpyn32A( root + 1, DRIVE_GetUnixCwd( full->drive ),
+                     sizeof(full->long_name) - (root - full->long_name) - 1 );
         if (root[1]) *root = '/';
+        lstrcpyn32A( full->short_name + 3, DRIVE_GetDosCwd( full->drive ),
+                     sizeof(full->short_name) - 3 );
     }
 
-    p = buffer[1] ? buffer + strlen(buffer) : buffer;
-    len = MAX_PATHNAME_LEN - strlen(buffer);
+    p_l = full->long_name[1] ? full->long_name + strlen(full->long_name)
+                             : full->long_name;
+    p_s = full->short_name[3] ? full->short_name + strlen(full->short_name)
+                              : full->short_name + 2;
     found = TRUE;
+
     while (*name && found)
     {
-        const char *newname = DOSFS_CheckDotDot( name, root, '/', &len );
-        if (newname != name)
+        /* Check for '.' and '..' */
+
+        if (*name == '.')
         {
-            p = root + strlen(root);
-            name = newname;
-            continue;
+            if (IS_END_OF_NAME(name[1]))
+            {
+                name++;
+                while ((*name == '\\') || (*name == '/')) name++;
+                continue;
+            }
+            else if ((name[1] == '.') && IS_END_OF_NAME(name[2]))
+            {
+                name += 2;
+                while ((*name == '\\') || (*name == '/')) name++;
+                while ((p_l > root) && (*p_l != '/')) p_l--;
+                while ((p_s > full->short_name + 2) && (*p_s != '\\')) p_s--;
+                *p_l = *p_s = '\0';  /* Remove trailing separator */
+                continue;
+            }
         }
-        if (len <= 1)
+
+        /* Make sure buffers are large enough */
+
+        if ((p_s >= full->short_name + sizeof(full->short_name) - 14) ||
+            (p_l >= full->long_name + sizeof(full->long_name) - 1))
         {
             DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
-            return NULL;
+            return FALSE;
         }
-        if ((found = DOSFS_FindUnixName( buffer, name, p+1, len-1, flags )))
+
+        /* Get the long and short name matching the file name */
+
+        if ((found = DOSFS_FindUnixName( full->long_name, name, p_l + 1,
+                         sizeof(full->long_name) - (p_l - full->long_name) - 1,
+                         p_s + 1, !(flags & DRIVE_CASE_SENSITIVE) )))
         {
-            *p = '/';
-            len -= strlen(p);
-            p += strlen(p);
+            *p_l++ = '/';
+            p_l   += strlen(p_l);
+            *p_s++ = '\\';
+            p_s   += strlen(p_s);
             while (!IS_END_OF_NAME(*name)) name++;
         }
         else if (!check_last)
         {
-            *p++ = '/';
-            for (len--; !IS_END_OF_NAME(*name) && (len > 1); name++, len--)
-                *p++ = tolower(*name);
-            *p = '\0';
+            *p_l++ = '/';
+            *p_s++ = '\\';
+            while (!IS_END_OF_NAME(*name) &&
+                   (p_s < full->short_name + sizeof(full->short_name) - 1) &&
+                   (p_l < full->long_name + sizeof(full->long_name) - 1))
+            {
+                *p_l++ = *p_s++ = tolower(*name);
+                name++;
+            }
+            *p_l = *p_s = '\0';
         }
         while ((*name == '\\') || (*name == '/')) name++;
     }
+
     if (!found)
     {
         if (check_last)
         {
             DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
-            return NULL;
+            return FALSE;
         }
         if (*name)  /* Not last */
         {
             DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
-            return NULL;
+            return FALSE;
         }
     }
-    if (!buffer[0]) strcpy( buffer, "/" );
-    dprintf_dosfs( stddeb, "DOSFS_GetUnixFileName: returning %s\n", buffer );
-    return buffer;
+    if (!full->long_name[0]) strcpy( full->long_name, "/" );
+    if (!full->short_name[2]) strcpy( full->short_name + 2, "\\" );
+    dprintf_dosfs( stddeb, "DOSFS_GetFullName: returning %s = %s\n",
+                   full->long_name, full->short_name );
+    return TRUE;
 }
 
 
 /***********************************************************************
- *           DOSFS_GetDosTrueName
- *
- * Convert a file name (DOS or Unix format) to a complete DOS name.
- * Return NULL if the path name is invalid or too long.
- * The unix_format flag is a hint that the file name is in Unix format.
+ *           GetShortPathName32A   (KERNEL32.271)
  */
-const char * DOSFS_GetDosTrueName( const char *name, int unix_format )
+DWORD GetShortPathName32A( LPCSTR longpath, LPSTR shortpath, DWORD shortlen )
 {
-    static char buffer[MAX_PATHNAME_LEN];
-    int drive, len;
-    UINT32 flags;
+    DOS_FULL_NAME full_name;
+
+    /* FIXME: is it correct to always return a fully qualified short path? */
+    if (!DOSFS_GetFullName( longpath, TRUE, &full_name )) return 0;
+    lstrcpyn32A( shortpath, full_name.short_name, shortlen );
+    return strlen( full_name.short_name );
+}
+
+
+/***********************************************************************
+ *           GetShortPathName32W   (KERNEL32.272)
+ */
+DWORD GetShortPathName32W( LPCWSTR longpath, LPWSTR shortpath, DWORD shortlen )
+{
+    DOS_FULL_NAME full_name;
+    DWORD ret = 0;
+    LPSTR longpathA = HEAP_strdupWtoA( GetProcessHeap(), 0, longpath );
+
+    /* FIXME: is it correct to always return a fully qualified short path? */
+    if (DOSFS_GetFullName( longpathA, TRUE, &full_name ))
+    {
+        ret = strlen( full_name.short_name );
+        lstrcpynAtoW( shortpath, full_name.short_name, shortlen );
+    }
+    HeapFree( GetProcessHeap(), 0, longpathA );
+    return ret;
+}
+
+
+/***********************************************************************
+ *           DOSFS_DoGetFullPathName
+ *
+ * Implementation of GetFullPathName32A/W.
+ */
+static DWORD DOSFS_DoGetFullPathName( LPCSTR name, DWORD len, LPSTR result,
+                                      BOOL32 unicode )
+{
+    char buffer[MAX_PATHNAME_LEN];
+    int drive;
     char *p;
 
-    dprintf_dosfs( stddeb, "DOSFS_GetDosTrueName(%s,%d)\n", name, unix_format);
+    dprintf_dosfs( stddeb, "GetFullPathName: converting %s\n", name );
 
-    if ((drive = DOSFS_GetPathDrive( &name )) == -1) return NULL;
+    if ((drive = DOSFS_GetPathDrive( &name )) == -1) return 0;
     p = buffer;
     *p++ = 'A' + drive;
     *p++ = ':';
-    if (IS_END_OF_NAME(*name))
+    if (IS_END_OF_NAME(*name))  /* Absolute path */
     {
         while ((*name == '\\') || (*name == '/')) name++;
     }
-    else
+    else  /* Relative path */
     {
         *p++ = '\\';
         lstrcpyn32A( p, DRIVE_GetDosCwd(drive), sizeof(buffer) - 3 );
         if (*p) p += strlen(p); else p--;
     }
     *p = '\0';
-    len = MAX_PATHNAME_LEN - (int)(p - buffer);
-    flags = DRIVE_GetFlags(drive);
 
     while (*name)
     {
-        const char *newname = DOSFS_CheckDotDot( name, buffer+2, '\\', &len );
-        if (newname != name)
+        if (*name == '.')
         {
-            p = buffer + strlen(buffer);
-            name = newname;
-            continue;
+            if (IS_END_OF_NAME(name[1]))
+            {
+                name++;
+                while ((*name == '\\') || (*name == '/')) name++;
+                continue;
+            }
+            else if ((name[1] == '.') && IS_END_OF_NAME(name[2]))
+            {
+                name += 2;
+                while ((*name == '\\') || (*name == '/')) name++;
+                while ((p > buffer + 2) && (*p != '\\')) p--;
+                *p = '\0';  /* Remove trailing separator */
+                continue;
+            }
         }
-        if (len <= 1)
+        if (p >= buffer + sizeof(buffer) - 1)
         {
             DOS_ERROR( ER_PathNotFound, EC_NotFound, SA_Abort, EL_Disk );
-            return NULL;
+            return 0;
         }
         *p++ = '\\';
-        if (unix_format)  /* Hash it into a DOS name */
-        {
-            lstrcpyn32A( p, DOSFS_Hash( name, FALSE,
-                                     !(flags & DRIVE_CASE_SENSITIVE) ),
-                         len );
-            len -= strlen(p);
-            p += strlen(p);
-            while (!IS_END_OF_NAME(*name)) name++;
-        }
-        else  /* Already DOS format, simply upper-case it */
-        {
-            while (!IS_END_OF_NAME(*name) && (len > 1))
-            {
-                *p++ = toupper(*name);
-                name++;
-                len--;
-            }
-            *p = '\0';
-        }
+        while (!IS_END_OF_NAME(*name) && (p < buffer + sizeof(buffer) - 1))
+            *p++ = *name++;
+        *p = '\0';
         while ((*name == '\\') || (*name == '/')) name++;
     }
+
     if (!buffer[2])
     {
         buffer[2] = '\\';
         buffer[3] = '\0';
     }
-    dprintf_dosfs( stddeb, "DOSFS_GetDosTrueName: returning %s\n", buffer );
-    return buffer;
+    if (!(DRIVE_GetFlags(drive) & DRIVE_CASE_PRESERVING))
+        CharUpper32A( buffer );
+
+    if (unicode) lstrcpynAtoW( (LPWSTR)result, buffer, len );
+    else lstrcpyn32A( result, buffer, len );
+
+    dprintf_dosfs( stddeb, "GetFullPathName: returning %s\n", buffer );
+    return strlen(buffer);
+}
+
+
+/***********************************************************************
+ *           GetFullPathName32A   (KERNEL32.272)
+ */
+DWORD GetFullPathName32A(LPCSTR name, DWORD len, LPSTR buffer, LPSTR *lastpart)
+{
+    DWORD ret = DOSFS_DoGetFullPathName( name, len, buffer, FALSE );
+    if (ret && lastpart)
+    {
+        LPSTR p = buffer + strlen(buffer);
+        while ((p > buffer + 2) && (*p != '\\')) p--;
+        *lastpart = p + 1;
+    }
+    return ret;
+}
+
+
+/***********************************************************************
+ *           GetFullPathName32W   (KERNEL32.273)
+ */
+DWORD GetFullPathName32W( LPCWSTR name, DWORD len, LPWSTR buffer,
+                          LPWSTR *lastpart )
+{
+    LPSTR nameA = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
+    DWORD ret = DOSFS_DoGetFullPathName( nameA, len, (LPSTR)buffer, TRUE );
+    HeapFree( GetProcessHeap(), 0, nameA );
+    if (ret && lastpart)
+    {
+        LPWSTR p = buffer + lstrlen32W(buffer);
+        while ((p > buffer + 2) && (*p != '\\')) p--;
+        *lastpart = p + 1;
+    }
+    return ret;
 }
 
 
@@ -885,6 +916,7 @@
     static int cur_pos = 0;
     static int drive_root = 0;
     char *p;
+    char dos_name[13];
     LPCSTR long_name, short_name;
     UINT32 flags;
     BY_HANDLE_FILE_INFORMATION info;
@@ -893,15 +925,14 @@
     {
         if (skip) return 0;
         entry->dwFileAttributes  = FILE_ATTRIBUTE_LABEL;
-        DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftCreationTime );
-        DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftLastAccessTime );
-        DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftLastWriteTime );
+        DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftCreationTime, 0 );
+        DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftLastAccessTime, 0 );
+        DOSFS_UnixTimeToFileTime( (time_t)0, &entry->ftLastWriteTime, 0 );
         entry->nFileSizeHigh     = 0;
         entry->nFileSizeLow      = 0;
         entry->dwReserved0       = 0;
         entry->dwReserved1       = 0;
-        strcpy( entry->cFileName,
-                DOSFS_ToDosDTAFormat( DRIVE_GetLabel( drive )) );
+        DOSFS_ToDosDTAFormat( DRIVE_GetLabel( drive ), entry->cFileName );
         strcpy( entry->cAlternateFileName, entry->cFileName );
         return 1;
     }
@@ -956,8 +987,11 @@
         if (short_mask)
         {
             if (!short_name)
-                short_name = DOSFS_Hash( long_name, TRUE,
-                                         !(flags & DRIVE_CASE_SENSITIVE) );
+            {
+                DOSFS_Hash( long_name, dos_name, TRUE,
+                            !(flags & DRIVE_CASE_SENSITIVE) );
+                short_name = dos_name;
+            }
             if (!DOSFS_MatchShort( short_mask, short_name )) continue;
         }
 
@@ -973,19 +1007,21 @@
 
         /* We now have a matching entry; fill the result and return */
 
-        if (!short_name)
-            short_name = DOSFS_Hash( long_name, TRUE,
-                                     !(flags & DRIVE_CASE_SENSITIVE) );
-
         entry->dwFileAttributes = info.dwFileAttributes;
         entry->ftCreationTime   = info.ftCreationTime;
         entry->ftLastAccessTime = info.ftLastAccessTime;
         entry->ftLastWriteTime  = info.ftLastWriteTime;
         entry->nFileSizeHigh    = info.nFileSizeHigh;
         entry->nFileSizeLow     = info.nFileSizeLow;
-        strcpy( entry->cAlternateFileName, DOSFS_ToDosDTAFormat(short_name) );
+
+        if (short_name)
+            DOSFS_ToDosDTAFormat( short_name, entry->cAlternateFileName );
+        else
+            DOSFS_Hash( long_name, entry->cAlternateFileName, FALSE,
+                        !(flags & DRIVE_CASE_SENSITIVE) );
+
         lstrcpyn32A( entry->cFileName, long_name, sizeof(entry->cFileName) );
-        if (!(flags & DRIVE_CASE_PRESERVING)) AnsiLower( entry->cFileName );
+        if (!(flags & DRIVE_CASE_PRESERVING)) CharLower32A( entry->cFileName );
         dprintf_dosfs( stddeb, "DOSFS_FindNext: returning %s (%s) %02lx %ld\n",
                        entry->cFileName, entry->cAlternateFileName,
                        entry->dwFileAttributes, entry->nFileSizeLow );
@@ -1004,17 +1040,17 @@
  */
 HANDLE16 FindFirstFile16( LPCSTR path, WIN32_FIND_DATA32A *data )
 {
+    DOS_FULL_NAME full_name;
     HGLOBAL16 handle;
     FIND_FIRST_INFO *info;
-    LPCSTR ptr;
 
     if (!path) return 0;
-    if (!(ptr = DOSFS_GetUnixFileName( path, FALSE )))
+    if (!DOSFS_GetFullName( path, FALSE, &full_name ))
         return INVALID_HANDLE_VALUE16;
     if (!(handle = GlobalAlloc16( GMEM_MOVEABLE, sizeof(FIND_FIRST_INFO) )))
         return INVALID_HANDLE_VALUE16;
     info = (FIND_FIRST_INFO *)GlobalLock16( handle );
-    info->path = HEAP_strdupA( SystemHeap, 0, ptr );
+    info->path = HEAP_strdupA( SystemHeap, 0, full_name.long_name );
     info->mask = strrchr( info->path, '/' );
     *(info->mask++) = '\0';
     if (path[0] && (path[1] == ':')) info->drive = toupper(*path) - 'A';
@@ -1156,72 +1192,34 @@
 
 
 /***********************************************************************
- *           GetShortPathName32A   (KERNEL32.271)
+ *           DOSFS_UnixTimeToFileTime
+ *
+ * Convert a Unix time to FILETIME format.
+ * The FILETIME structure is a 64-bit value representing the number of
+ * 100-nanosecond intervals since January 1, 1601.
+ * 'remainder' is the fraction of 100-ns intervals smaller than 1 second
+ * that couldn't be stored in the time_t value.
  */
-DWORD GetShortPathName32A( LPCSTR longpath, LPSTR shortpath, DWORD shortlen )
+void DOSFS_UnixTimeToFileTime( time_t unix_time, FILETIME *filetime,
+                               DWORD remainder )
 {
-    LPCSTR dostruename;
-
-    dprintf_dosfs( stddeb, "GetShortPathName32A(%s,%p,%ld)\n",
-                   longpath, shortpath, shortlen );
-
-    dostruename = DOSFS_GetDosTrueName( longpath, TRUE );
-    lstrcpyn32A( shortpath, dostruename, shortlen );
-    return strlen(dostruename);
+    /* FIXME :-) */
+    filetime->dwLowDateTime  = unix_time;
+    filetime->dwHighDateTime = 0;
 }
 
 
 /***********************************************************************
- *           GetShortPathNameW   (KERNEL32.272)
+ *           DOSFS_FileTimeToUnixTime
+ *
+ * Convert a FILETIME format to Unix time.
+ * If not NULL, 'remainder' contains the fractional part of the filetime.
  */
-DWORD GetShortPathName32W( LPCWSTR longpath, LPWSTR shortpath, DWORD shortlen )
+time_t DOSFS_FileTimeToUnixTime( const FILETIME *filetime, DWORD *remainder )
 {
-    LPSTR longpatha = HEAP_strdupWtoA( GetProcessHeap(), 0, longpath );
-    LPCSTR dostruename = DOSFS_GetDosTrueName( longpatha, TRUE );
-    HeapFree( GetProcessHeap(), 0, longpatha );
-    lstrcpynAtoW( shortpath, dostruename, shortlen );
-    return strlen(dostruename);
-}
-
-
-/***********************************************************************
- *           GetFullPathNameA   (KERNEL32.272)
- */
-DWORD GetFullPathName32A( LPCSTR fn, DWORD buflen, LPSTR buf, LPSTR *lastpart)
-{
-	dprintf_file(stddeb,"GetFullPathNameA(%s)\n",fn);
-	/* FIXME */
-        if (buf) {
-            lstrcpyn32A(buf,fn,buflen);
-            if (lastpart) {
-		*lastpart = strrchr(buf,'\\');
-		if (!*lastpart) *lastpart=buf;
-	    }
-	}
-	return strlen(fn);
-}
-
-/***********************************************************************
- *           GetFullPathName32W   (KERNEL32.273)
- */
-DWORD GetFullPathName32W(LPCWSTR fn,DWORD buflen,LPWSTR buf,LPWSTR *lastpart) {
-	LPWSTR  x;
-
-	dprintf_file(stddeb,"GetFullPathNameW(%p)\n",fn);
-	/* FIXME */
-	if (buf) {
-		lstrcpyn32W(buf,fn,buflen);
-		if (lastpart) {
-			x = buf+lstrlen32W(buf)-1;
-			while (x>=buf && *x!='\\')
-			x--;
-			if (x>=buf)
-				*lastpart=x;
-			else
-				*lastpart=buf;
-		}
-	}
-	return lstrlen32W(fn);
+    /* FIXME :-) */
+    if (remainder) *remainder = 0;
+    return filetime->dwLowDateTime;
 }
 
 
@@ -1230,8 +1228,15 @@
  */
 BOOL32 DosDateTimeToFileTime( WORD fatdate, WORD fattime, LPFILETIME ft )
 {
-    time_t unixtime = DOSFS_DosDateTimeToUnixTime(fatdate,fattime);
-    DOSFS_UnixTimeToFileTime(unixtime,ft);
+    struct tm newtm;
+
+    newtm.tm_sec  = (fattime & 0x1f) * 2;
+    newtm.tm_min  = (fattime >> 5) & 0x3f;
+    newtm.tm_hour = (fattime >> 11);
+    newtm.tm_mday = (fatdate & 0x1f);
+    newtm.tm_mon  = ((fatdate >> 5) & 0x0f) - 1;
+    newtm.tm_year = (fatdate >> 9) + 80;
+    DOSFS_UnixTimeToFileTime( mktime( &newtm ), ft, 0 );
     return TRUE;
 }
 
@@ -1242,8 +1247,13 @@
 BOOL32 FileTimeToDosDateTime( const FILETIME *ft, LPWORD fatdate,
                               LPWORD fattime )
 {
-    time_t unixtime = DOSFS_FileTimeToUnixTime(ft);
-    DOSFS_ToDosDateTime(unixtime,fatdate,fattime);
+    time_t unixtime = DOSFS_FileTimeToUnixTime( ft, NULL );
+    struct tm *tm = localtime( &unixtime );
+    if (fattime)
+        *fattime = (tm->tm_hour << 11) + (tm->tm_min << 5) + (tm->tm_sec / 2);
+    if (fatdate)
+        *fatdate = ((tm->tm_year - 80) << 9) + ((tm->tm_mon + 1) << 5)
+                   + tm->tm_mday;
     return TRUE;
 }
 
@@ -1254,11 +1264,12 @@
 BOOL32 LocalFileTimeToFileTime( const FILETIME *localft, LPFILETIME utcft )
 {
     struct tm *xtm;
+    DWORD remainder;
 
     /* convert from local to UTC. Perhaps not correct. FIXME */
-    xtm = gmtime((time_t*)&(localft->dwLowDateTime));
-    utcft->dwLowDateTime  = mktime(xtm);
-    utcft->dwHighDateTime = 0;
+    time_t unixtime = DOSFS_FileTimeToUnixTime( localft, &remainder );
+    xtm = gmtime( &unixtime );
+    DOSFS_UnixTimeToFileTime( mktime(xtm), utcft, remainder );
     return TRUE; 
 }
 
@@ -1269,11 +1280,12 @@
 BOOL32 FileTimeToLocalFileTime( const FILETIME *utcft, LPFILETIME localft )
 {
     struct tm *xtm;
+    DWORD remainder;
 
     /* convert from UTC to local. Perhaps not correct. FIXME */
-    xtm = localtime((time_t*)&(utcft->dwLowDateTime));
-    localft->dwLowDateTime  = mktime(xtm);
-    localft->dwHighDateTime = 0;
+    time_t unixtime = DOSFS_FileTimeToUnixTime( utcft, &remainder );
+    xtm = localtime( &unixtime );
+    DOSFS_UnixTimeToFileTime( mktime(xtm), localft, remainder );
     return TRUE; 
 }
 
@@ -1284,19 +1296,68 @@
 BOOL32 FileTimeToSystemTime( const FILETIME *ft, LPSYSTEMTIME syst )
 {
     struct tm *xtm;
-    time_t xtime = DOSFS_FileTimeToUnixTime(ft);
+    DWORD remainder;
+    time_t xtime = DOSFS_FileTimeToUnixTime( ft, &remainder );
     xtm = gmtime(&xtime);
-    syst->wYear      = xtm->tm_year;
-    syst->wMonth     = xtm->tm_mon;
-    syst->wDayOfWeek = xtm->tm_wday;
-    syst->wDay	     = xtm->tm_mday;
-    syst->wHour	     = xtm->tm_hour;
-    syst->wMinute    = xtm->tm_min;
-    syst->wSecond    = xtm->tm_sec;
-    syst->wMilliseconds	= 0; /* FIXME */
+    syst->wYear         = xtm->tm_year;
+    syst->wMonth        = xtm->tm_mon;
+    syst->wDayOfWeek    = xtm->tm_wday;
+    syst->wDay	        = xtm->tm_mday;
+    syst->wHour	        = xtm->tm_hour;
+    syst->wMinute       = xtm->tm_min;
+    syst->wSecond       = xtm->tm_sec;
+    syst->wMilliseconds	= remainder / 10000;
     return TRUE; 
 }
 
+/***********************************************************************
+ *           QueryDosDeviceA   (KERNEL32.413)
+ *
+ * returns array of strings terminated by \0, terminated by \0
+ */
+DWORD
+QueryDosDevice32A(LPCSTR devname,LPSTR target,DWORD bufsize)
+{
+    LPSTR s;
+    char  buffer[200];
+
+    dprintf_dosfs(stddeb,"QueryDosDevice(%s,...)\n",devname?devname:"<null>");
+    if (!devname) {
+	/* return known MSDOS devices */
+	lstrcpy32A(buffer,"CON COM1 COM2 LPT1 NUL ");
+	while ((s=strchr(buffer,' ')))
+		*s='\0';
+
+	lstrcpyn32A(target,buffer,bufsize);
+	return strlen(buffer);
+    }
+    lstrcpy32A(buffer,"\\DEV\\");
+    lstrcat32A(buffer,devname);
+    if (s=strchr(buffer,':'))
+    	*s='\0';
+    lstrcpyn32A(target,buffer,bufsize);
+    return strlen(buffer);
+}
+
+
+/***********************************************************************
+ *           QueryDosDeviceW   (KERNEL32.414)
+ *
+ * returns array of strings terminated by \0, terminated by \0
+ */
+DWORD
+QueryDosDevice32W(LPCWSTR devname,LPWSTR target,DWORD bufsize)
+{
+    LPSTR devnameA = devname?HEAP_strdupWtoA(GetProcessHeap(),0,devname):NULL;
+    LPSTR targetA = (LPSTR)HEAP_xalloc(GetProcessHeap(),0,bufsize);
+    DWORD ret = QueryDosDevice32A(devnameA,targetA,bufsize);
+
+    lstrcpynAtoW(target,targetA,bufsize);
+    if (devnameA) HeapFree(GetProcessHeap(),0,devnameA);
+    if (targetA) HeapFree(GetProcessHeap(),0,targetA);
+    return ret;
+}
+
 
 /***********************************************************************
  *           SystemTimeToFileTime   (KERNEL32.526)
@@ -1312,6 +1373,6 @@
     xtm.tm_hour	= syst->wHour;
     xtm.tm_min	= syst->wMinute;
     xtm.tm_sec	= syst->wSecond;
-    DOSFS_UnixTimeToFileTime(mktime(&xtm),ft);
+    DOSFS_UnixTimeToFileTime( mktime(&xtm), ft, syst->wMilliseconds * 10000 );
     return TRUE; 
 }
diff --git a/files/drive.c b/files/drive.c
index b876675..d59e02b 100644
--- a/files/drive.c
+++ b/files/drive.c
@@ -25,7 +25,6 @@
 
 #include "windows.h"
 #include "winbase.h"
-#include "dos_fs.h"
 #include "drive.h"
 #include "file.h"
 #include "heap.h"
@@ -410,8 +409,9 @@
  */
 int DRIVE_Chdir( int drive, const char *path )
 {
+    DOS_FULL_NAME full_name;
     char buffer[MAX_PATHNAME_LEN];
-    const char *unix_cwd, *dos_cwd;
+    LPSTR unix_cwd;
     BY_HANDLE_FILE_INFORMATION info;
     TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
 
@@ -420,31 +420,30 @@
     buffer[0] += drive;
     lstrcpyn32A( buffer + 2, path, sizeof(buffer) - 2 );
 
-    if (!(unix_cwd = DOSFS_GetUnixFileName( buffer, TRUE ))) return 0;
-    if (!FILE_Stat( unix_cwd, &info )) return 0;
+    if (!DOSFS_GetFullName( buffer, TRUE, &full_name )) return 0;
+    if (!FILE_Stat( full_name.long_name, &info )) return 0;
     if (!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
     {
         DOS_ERROR( ER_FileNotFound, EC_NotFound, SA_Abort, EL_Disk );
         return 0;
     }
-    unix_cwd += strlen( DOSDrives[drive].root );
+    unix_cwd = full_name.long_name + strlen( DOSDrives[drive].root );
     while (*unix_cwd == '/') unix_cwd++;
-    buffer[2] = '/';
-    lstrcpyn32A( buffer + 3, unix_cwd, sizeof(buffer) - 3 );
-    if (!(dos_cwd = DOSFS_GetDosTrueName( buffer, TRUE ))) return 0;
 
     dprintf_dosfs( stddeb, "DRIVE_Chdir(%c:): unix_cwd=%s dos_cwd=%s\n",
-                   'A' + drive, unix_cwd, dos_cwd + 3 );
+                   'A' + drive, unix_cwd, full_name.short_name + 3 );
 
     HeapFree( SystemHeap, 0, DOSDrives[drive].dos_cwd );
     HeapFree( SystemHeap, 0, DOSDrives[drive].unix_cwd );
-    DOSDrives[drive].dos_cwd  = HEAP_strdupA( SystemHeap, 0, dos_cwd + 3 );
+    DOSDrives[drive].dos_cwd  = HEAP_strdupA( SystemHeap, 0,
+                                              full_name.short_name + 3 );
     DOSDrives[drive].unix_cwd = HEAP_strdupA( SystemHeap, 0, unix_cwd );
 
     if (pTask && (pTask->curdrive & 0x80) && 
         ((pTask->curdrive & ~0x80) == drive))
     {
-        lstrcpyn32A( pTask->curdir, dos_cwd + 2, sizeof(pTask->curdir) );
+        lstrcpyn32A( pTask->curdir, full_name.short_name + 2,
+                     sizeof(pTask->curdir) );
         DRIVE_LastTask = GetCurrentTask();
     }
     return 1;
diff --git a/files/file.c b/files/file.c
index f841b81..048e58d 100644
--- a/files/file.c
+++ b/files/file.c
@@ -20,7 +20,6 @@
 
 #include "windows.h"
 #include "winerror.h"
-#include "dos_fs.h"
 #include "drive.h"
 #include "file.h"
 #include "global.h"
@@ -212,11 +211,8 @@
 
     if ((file->unix_handle = open( name, mode, 0666 )) == -1)
     {
-        if (Options.allowReadOnly && (mode == O_RDWR))
-        {
-            if ((file->unix_handle = open( name, O_RDONLY )) != -1)
-                fprintf( stderr, "Warning: could not open %s for writing, opening read-only.\n", name );
-        }
+        if (!Options.failReadOnly && (mode == O_RDWR))
+            file->unix_handle = open( name, O_RDONLY );
     }
     if ((file->unix_handle == -1) || (fstat( file->unix_handle, &st ) == -1))
     {
@@ -243,6 +239,7 @@
  */
 HFILE32 FILE_Open( LPCSTR path, INT32 mode )
 {
+    DOS_FULL_NAME full_name;
     const char *unixName;
 
     dprintf_file(stddeb, "FILE_Open: '%s' %04x\n", path, mode );
@@ -257,9 +254,11 @@
         }
     }
     else /* check for filename, don't check for last entry if creating */
-        if (!(unixName = DOSFS_GetUnixFileName( path, !(mode & O_CREAT) )))
+    {
+        if (!DOSFS_GetFullName( path, !(mode & O_CREAT), &full_name ))
             return HFILE_ERROR32;
-
+        unixName = full_name.long_name;
+    }
     return FILE_OpenUnixFile( unixName, mode );
 }
 
@@ -272,6 +271,7 @@
     HFILE32 handle;
     DOS_FILE *file;
     const char *unixName;
+    DOS_FULL_NAME full_name;
 
     dprintf_file(stddeb, "FILE_Create: '%s' %04x %d\n", path, mode, unique );
 
@@ -285,12 +285,12 @@
     if ((handle = FILE_Alloc( &file )) == INVALID_HANDLE_VALUE32)
         return INVALID_HANDLE_VALUE32;
 
-    if (!(unixName = DOSFS_GetUnixFileName( path, FALSE )))
+    if (!DOSFS_GetFullName( path, FALSE, &full_name ))
     {
         CloseHandle( handle );
         return INVALID_HANDLE_VALUE32;
     }
-    if ((file->unix_handle = open( unixName,
+    if ((file->unix_handle = open( full_name.long_name,
                            O_CREAT | O_TRUNC | O_RDWR | (unique ? O_EXCL : 0),
                            mode )) == -1)
     {
@@ -301,7 +301,7 @@
 
     /* File created OK, now fill the DOS_FILE */
 
-    file->unix_name = HEAP_strdupA( SystemHeap, 0, unixName );
+    file->unix_name = HEAP_strdupA( SystemHeap, 0, full_name.long_name );
     return handle;
 }
 
@@ -317,9 +317,9 @@
     if (S_ISDIR(st->st_mode))
         info->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
 
-    DOSFS_UnixTimeToFileTime( st->st_mtime, &info->ftCreationTime );
-    DOSFS_UnixTimeToFileTime( st->st_mtime, &info->ftLastWriteTime );
-    DOSFS_UnixTimeToFileTime( st->st_atime, &info->ftLastAccessTime );
+    DOSFS_UnixTimeToFileTime( st->st_mtime, &info->ftCreationTime, 0 );
+    DOSFS_UnixTimeToFileTime( st->st_mtime, &info->ftLastWriteTime, 0 );
+    DOSFS_UnixTimeToFileTime( st->st_atime, &info->ftLastAccessTime, 0 );
 
     info->dwVolumeSerialNumber = 0;  /* FIXME */
     info->nFileSizeHigh = 0;
@@ -385,9 +385,11 @@
  */
 DWORD GetFileAttributes32A( LPCSTR name )
 {
+    DOS_FULL_NAME full_name;
     BY_HANDLE_FILE_INFORMATION info;
 
-    if (!FILE_Stat( name, &info )) return -1;
+    if (!DOSFS_GetFullName( name, TRUE, &full_name )) return -1;
+    if (!FILE_Stat( full_name.long_name, &info )) return -1;
     return info.dwFileAttributes;
 }
 
@@ -500,8 +502,9 @@
 UINT32 GetTempFileName32A( LPCSTR path, LPCSTR prefix, UINT32 unique,
                            LPSTR buffer)
 {
-    LPSTR p;
+    DOS_FULL_NAME full_name;
     int i;
+    LPSTR p;
     UINT32 num = unique ? (unique & 0xffff) : time(NULL) & 0xffff;
 
     if (!path) return 0;
@@ -511,36 +514,38 @@
     for (i = 3; (i > 0) && (*prefix); i--) *p++ = *prefix++;
     sprintf( p, "%04x.tmp", num );
 
-    if (unique)
-    {
-        lstrcpyn32A( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 );
-        dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer );
-	if (-1==access(DOSFS_GetUnixFileName(buffer,TRUE),W_OK))
-	    fprintf(stderr,"Warning: GetTempFileName returns '%s', which doesn't seem to be writeable. Please check your configuration file if this generates a failure.\n",buffer);
-        return unique;
-    }
-
     /* Now try to create it */
 
-    do
+    if (!unique)
     {
-        HFILE32 handle;
-        if ((handle = FILE_Create(buffer,0666,TRUE)) != INVALID_HANDLE_VALUE32)
-        {  /* We created it */
-            dprintf_file( stddeb, "GetTempFileName: created %s\n", buffer );
-            CloseHandle( handle );
-            break;
-        }
-        if (DOS_ExtendedError != ER_FileExists) break;  /* No need to go on */
-        num++;
-        sprintf( p, "%04x.tmp", num );
-    } while (num != (unique & 0xffff));
+        do
+        {
+            HFILE32 handle = FILE_Create( buffer, 0666, TRUE );
+            if (handle != INVALID_HANDLE_VALUE32)
+            {  /* We created it */
+                dprintf_file( stddeb, "GetTempFileName: created %s\n", buffer);
+                CloseHandle( handle );
+                break;
+            }
+            if (DOS_ExtendedError != ER_FileExists)
+                break;  /* No need to go on */
+            num++;
+            sprintf( p, "%04x.tmp", num );
+        } while (num != (unique & 0xffff));
+    }
 
-    lstrcpyn32A( buffer, DOSFS_GetDosTrueName( buffer, FALSE ), 144 );
+    /* Get the full path name */
+
+    if (DOSFS_GetFullName( buffer, FALSE, &full_name ))
+    {
+        if (access( full_name.long_name, W_OK ) == -1)
+            fprintf( stderr,
+                     "Warning: GetTempFileName returns '%s', which doesn't seem to be writeable.\n"
+                     "Please check your configuration file if this generates a failure.\n",
+                     buffer);
+    }
     dprintf_file( stddeb, "GetTempFileName: returning %s\n", buffer );
-    if (-1==access(DOSFS_GetUnixFileName(buffer,TRUE),W_OK))
-	fprintf(stderr,"Warning: GetTempFileName returns '%s', which doesn't seem to be writeable. Please check your configuration file if this generates a failure.\n",buffer);
-    return num;
+    return unique ? unique : num;
 }
 
 
@@ -576,7 +581,7 @@
     HFILE32 hFileRet;
     FILETIME filetime;
     WORD filedatetime[2];
-    const char *unixName, *dosName;
+    DOS_FULL_NAME full_name;
     char *p;
     int unixMode;
 
@@ -589,9 +594,10 @@
 
     if (mode & OF_PARSE)
     {
-        if (!(dosName = DOSFS_GetDosTrueName( name, FALSE ))) goto error;
-        lstrcpyn32A( ofs->szPathName, dosName, sizeof(ofs->szPathName) );
-        ofs->fFixedDisk = (GetDriveType16( dosName[0]-'A' ) != DRIVE_REMOVABLE);
+        if (!GetFullPathName32A( name, sizeof(ofs->szPathName),
+                                 ofs->szPathName, NULL )) goto error;
+        ofs->fFixedDisk = (GetDriveType16( ofs->szPathName[0]-'A' )
+                           != DRIVE_REMOVABLE);
         dprintf_file( stddeb, "OpenFile(%s): OF_PARSE, res = '%s'\n",
                       name, ofs->szPathName );
         return 0;
@@ -604,8 +610,8 @@
     {
         if ((hFileRet = FILE_Create(name,0666,FALSE))== INVALID_HANDLE_VALUE32)
             goto error;
-        lstrcpyn32A( ofs->szPathName, DOSFS_GetDosTrueName( name, FALSE ),
-                     sizeof(ofs->szPathName) );
+        GetFullPathName32A( name, sizeof(ofs->szPathName),
+                            ofs->szPathName, NULL );
         goto success;
     }
 
@@ -614,11 +620,7 @@
     if ((mode & OF_SEARCH) && !(mode & OF_REOPEN))
     {
         /* First try the file name as is */
-        if ((unixName = DOSFS_GetUnixFileName( name, TRUE )) != NULL)
-        {
-            lstrcpyn32A( ofs->szPathName, name, sizeof(ofs->szPathName) );
-            goto found;
-        }
+        if (DOSFS_GetFullName( name, TRUE, &full_name )) goto found;
         /* Now remove the path */
         if (name[0] && (name[1] == ':')) name += 2;
         if ((p = strrchr( name, '\\' ))) name = p + 1;
@@ -628,20 +630,17 @@
 
     /* Now look for the file */
 
-    if (!DIR_SearchPath( NULL, name, NULL, sizeof(ofs->szPathName),
-                         ofs->szPathName, NULL, win32 ))
-        goto not_found;
-    if (!(unixName = DOSFS_GetUnixFileName( ofs->szPathName, TRUE )))
-        goto not_found;
+    if (!DIR_SearchPath( NULL, name, NULL, &full_name, win32 )) goto not_found;
 
 found:
-    dprintf_file( stddeb, "OpenFile: found '%s'\n", unixName );
-    lstrcpyn32A(ofs->szPathName, DOSFS_GetDosTrueName( ofs->szPathName, FALSE),
-                sizeof(ofs->szPathName) );
+    dprintf_file( stddeb, "OpenFile: found %s = %s\n",
+                  full_name.long_name, full_name.short_name );
+    lstrcpyn32A( ofs->szPathName, full_name.short_name,
+                 sizeof(ofs->szPathName) );
 
     if (mode & OF_DELETE)
     {
-        if (unlink( unixName ) == -1) goto not_found;
+        if (unlink( full_name.long_name ) == -1) goto not_found;
         dprintf_file( stddeb, "OpenFile(%s): OF_DELETE return = OK\n", name);
         return 1;
     }
@@ -657,8 +656,8 @@
         unixMode = O_RDONLY; break;
     }
 
-    if ((hFileRet = FILE_OpenUnixFile( unixName, unixMode )) == HFILE_ERROR32)
-        goto not_found;
+    hFileRet = FILE_OpenUnixFile( full_name.long_name, unixMode );
+    if (hFileRet == HFILE_ERROR32) goto not_found;
     GetFileTime( hFileRet, NULL, NULL, &filetime );
     FileTimeToDosDateTime( &filetime, &filedatetime[0], &filedatetime[1] );
     if ((mode & OF_VERIFY) && (mode & OF_REOPEN))
@@ -715,7 +714,7 @@
  */
 HFILE16 _lclose16( HFILE16 hFile )
 {
-    dprintf_file( stddeb, "_lclose: handle %d\n", hFile );
+    dprintf_file( stddeb, "_lclose16: handle %d\n", hFile );
     return CloseHandle( hFile ) ? 0 : HFILE_ERROR16;
 }
 
@@ -725,7 +724,7 @@
  */
 HFILE32 _lclose32( HFILE32 hFile )
 {
-    dprintf_file( stddeb, "_lclose: handle %d\n", hFile );
+    dprintf_file( stddeb, "_lclose32: handle %d\n", hFile );
     return CloseHandle( hFile ) ? 0 : HFILE_ERROR32;
 }
 
@@ -817,11 +816,44 @@
 
 
 /***********************************************************************
+ *           SetFilePointer   (KERNEL32.492)
+ */
+DWORD SetFilePointer( HFILE32 hFile, LONG distance, LONG *highword,
+                      DWORD method )
+{
+    DOS_FILE *file;
+    int origin, result;
+
+    if (highword && *highword)
+    {
+        fprintf( stderr, "SetFilePointer: 64-bit offsets not supported yet\n");
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return 0xffffffff;
+    }
+    dprintf_file( stddeb, "SetFilePointer: handle %d offset %ld origin %ld\n",
+                  hFile, distance, method );
+
+    if (!(file = FILE_GetFile( hFile ))) return 0xffffffff;
+    switch(method)
+    {
+        case 1:  origin = SEEK_CUR; break;
+        case 2:  origin = SEEK_END; break;
+        default: origin = SEEK_SET; break;
+    }
+
+    if ((result = lseek( file->unix_handle, distance, origin )) == -1)
+        FILE_SetDosError();
+    FILE_ReleaseFile( file );
+    return (DWORD)result;
+}
+
+
+/***********************************************************************
  *           _llseek16   (KERNEL.84)
  */
 LONG _llseek16( HFILE16 hFile, LONG lOffset, INT16 nOrigin )
 {
-    return _llseek32( hFile, lOffset, nOrigin );
+    return SetFilePointer( hFile, lOffset, NULL, nOrigin );
 }
 
 
@@ -830,24 +862,7 @@
  */
 LONG _llseek32( HFILE32 hFile, LONG lOffset, INT32 nOrigin )
 {
-    DOS_FILE *file;
-    int origin, result;
-
-    dprintf_file( stddeb, "_llseek: handle %d, offset %ld, origin %d\n", 
-                  hFile, lOffset, nOrigin);
-
-    if (!(file = FILE_GetFile( hFile ))) return HFILE_ERROR32;
-    switch(nOrigin)
-    {
-        case 1:  origin = SEEK_CUR; break;
-        case 2:  origin = SEEK_END; break;
-        default: origin = SEEK_SET; break;
-    }
-
-    if ((result = lseek( file->unix_handle, lOffset, origin )) == -1)
-        FILE_SetDosError();
-    FILE_ReleaseFile( file );
-    return result;
+    return SetFilePointer( hFile, lOffset, NULL, nOrigin );
 }
 
 
@@ -961,47 +976,27 @@
     HGLOBAL16 hPDB = GetCurrentPDB();
     PDB *pdb = (PDB *)GlobalLock16( hPDB );
     BYTE *files = PTR_SEG_TO_LIN( pdb->fileHandlesPtr );
-    WORD i;
 
     dprintf_file( stddeb, "SetHandleCount(%d)\n", count );
 
     if (count < 20) count = 20;  /* No point in going below 20 */
     else if (count > 254) count = 254;
 
-    /* If shrinking the table, make sure all extra file handles are closed */
-    if (count < pdb->nbFiles)
-    {
-        for (i = count; i < pdb->nbFiles; i++)
-            if (files[i] != 0xff)  /* File open */
-            {
-                DOS_ERROR( ER_TooManyOpenFiles, EC_ProgramError,
-                           SA_Abort, EL_Disk );
-                return pdb->nbFiles;
-            }
-    }
-
     if (count == 20)
     {
         if (pdb->nbFiles > 20)
         {
             memcpy( pdb->fileHandles, files, 20 );
-#ifdef WINELIB
-            GlobalFree32( (HGLOBAL32)pdb->fileHandlesPtr );
-            pdb->fileHandlesPtr = (SEGPTR)pdb->fileHandles;
-#else
-            GlobalFree16( GlobalHandle16( SELECTOROF(pdb->fileHandlesPtr) ));
+            GlobalFree16( pdb->hFileHandles );
             pdb->fileHandlesPtr = (SEGPTR)MAKELONG( 0x18,
                                                    GlobalHandleToSel( hPDB ) );
-#endif
+            pdb->hFileHandles = 0;
             pdb->nbFiles = 20;
         }
     }
     else  /* More than 20, need a new file handles table */
     {
         BYTE *newfiles;
-#ifdef WINELIB
-        newfiles = (BYTE *)GlobalAlloc32( GMEM_FIXED, count );
-#else
         HGLOBAL16 newhandle = GlobalAlloc16( GMEM_MOVEABLE, count );
         if (!newhandle)
         {
@@ -1009,21 +1004,16 @@
             return pdb->nbFiles;
         }
         newfiles = (BYTE *)GlobalLock16( newhandle );
-#endif  /* WINELIB */
+
         if (count > pdb->nbFiles)
         {
             memcpy( newfiles, files, pdb->nbFiles );
             memset( newfiles + pdb->nbFiles, 0xff, count - pdb->nbFiles );
         }
         else memcpy( newfiles, files, count );
-#ifdef WINELIB
-        if (pdb->nbFiles > 20) GlobalFree32( (HGLOBAL32)pdb->fileHandlesPtr );
-        pdb->fileHandlesPtr = (SEGPTR)newfiles;
-#else
-        if (pdb->nbFiles > 20)
-            GlobalFree16( GlobalHandle16( SELECTOROF(pdb->fileHandlesPtr) ));
+        if (pdb->nbFiles > 20) GlobalFree16( pdb->hFileHandles );
         pdb->fileHandlesPtr = WIN16_GlobalLock16( newhandle );
-#endif  /* WINELIB */
+        pdb->hFileHandles   = newhandle;
         pdb->nbFiles = count;
     }
     return pdb->nbFiles;
@@ -1095,6 +1085,7 @@
  */
 BOOL32 DeleteFile32A( LPCSTR path )
 {
+    DOS_FULL_NAME full_name;
     const char *unixName;
 
     dprintf_file(stddeb, "DeleteFile: '%s'\n", path );
@@ -1106,8 +1097,8 @@
         return FALSE;
     }
 
-    if (!(unixName = DOSFS_GetUnixFileName( path, TRUE ))) return FALSE;
-    if (unlink( unixName ) == -1)
+    if (!DOSFS_GetFullName( path, TRUE, &full_name )) return FALSE;
+    if (unlink( full_name.long_name ) == -1)
     {
         FILE_SetDosError();
         return FALSE;
@@ -1153,6 +1144,99 @@
 }
 
 
+/**************************************************************************
+ *           MoveFile32A   (KERNEL32.387)
+ */
+BOOL32 MoveFile32A( LPCSTR fn1, LPCSTR fn2 )
+{
+    DOS_FULL_NAME full_name1, full_name2;
+
+    dprintf_file( stddeb, "MoveFile32A(%s,%s)\n", fn1, fn2 );
+
+    if (!DOSFS_GetFullName( fn1, TRUE, &full_name1 )) return FALSE;
+    if (!DOSFS_GetFullName( fn2, FALSE, &full_name2 )) return FALSE;
+    /* FIXME: should not replace an existing file */
+    /* FIXME: should handle renaming across devices */
+    if (rename( full_name1.long_name, full_name2.long_name ) == -1)
+    {
+        FILE_SetDosError();
+        return FALSE;
+    }
+    return TRUE;
+}
+
+
+/**************************************************************************
+ *           MoveFile32W   (KERNEL32.390)
+ */
+BOOL32 MoveFile32W( LPCWSTR fn1, LPCWSTR fn2 )
+{
+    LPSTR afn1 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn1 );
+    LPSTR afn2 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn2 );
+    BOOL32 res = MoveFile32A( afn1, afn2 );
+    HeapFree( GetProcessHeap(), 0, afn1 );
+    HeapFree( GetProcessHeap(), 0, afn2 );
+    return res;
+}
+
+
+/**************************************************************************
+ *           CopyFile32A   (KERNEL32.36)
+ */
+BOOL32 CopyFile32A( LPCSTR source, LPCSTR dest, BOOL32 fail_if_exists )
+{
+    HFILE32 h1, h2;
+    BY_HANDLE_FILE_INFORMATION info;
+    UINT32 count;
+    BOOL32 ret = FALSE;
+    int mode;
+    char buffer[2048];
+
+    if ((h1 = _lopen32( source, OF_READ )) == HFILE_ERROR32) return FALSE;
+    if (!GetFileInformationByHandle( h1, &info ))
+    {
+        CloseHandle( h1 );
+        return FALSE;
+    }
+    mode = (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 0444 : 0666;
+    if ((h2 = FILE_Create( dest, mode, fail_if_exists )) == HFILE_ERROR32)
+    {
+        CloseHandle( h1 );
+        return FALSE;
+    }
+    while ((count = _lread32( h2, buffer, sizeof(buffer) )) > 0)
+    {
+        char *p = buffer;
+        while (count > 0)
+        {
+            INT32 res = _lwrite32( h2, p, count );
+            if (res <= 0) goto done;
+            p += res;
+            count -= res;
+        }
+    }
+    ret =  TRUE;
+done:
+    CloseHandle( h1 );
+    CloseHandle( h2 );
+    return ret;
+}
+
+
+/**************************************************************************
+ *           CopyFile32W   (KERNEL32.37)
+ */
+BOOL32 CopyFile32W( LPCWSTR source, LPCWSTR dest, BOOL32 fail_if_exists )
+{
+    LPSTR sourceA = HEAP_strdupWtoA( GetProcessHeap(), 0, source );
+    LPSTR destA   = HEAP_strdupWtoA( GetProcessHeap(), 0, dest );
+    BOOL32 ret = CopyFile32A( sourceA, destA, fail_if_exists );
+    HeapFree( GetProcessHeap(), 0, sourceA );
+    HeapFree( GetProcessHeap(), 0, destA );
+    return ret;
+}
+
+
 /***********************************************************************
  *              SetFileTime   (KERNEL32.493)
  */
@@ -1172,11 +1256,11 @@
 	lpLastWriteTime
     );
     if (lpLastAccessTime)
-	utimbuf.actime	= DOSFS_FileTimeToUnixTime(lpLastAccessTime);
+	utimbuf.actime	= DOSFS_FileTimeToUnixTime(lpLastAccessTime, NULL);
     else
 	utimbuf.actime	= 0; /* FIXME */
     if (lpLastWriteTime)
-	utimbuf.modtime	= DOSFS_FileTimeToUnixTime(lpLastWriteTime);
+	utimbuf.modtime	= DOSFS_FileTimeToUnixTime(lpLastWriteTime, NULL);
     else
 	utimbuf.modtime	= 0; /* FIXME */
     if (-1==utime(file->unix_name,&utimbuf))
diff --git a/files/profile.c b/files/profile.c
index 393fe48..06b8b70 100644
--- a/files/profile.c
+++ b/files/profile.c
@@ -11,7 +11,7 @@
 #include <string.h>
 
 #include "windows.h"
-#include "dos_fs.h"
+#include "file.h"
 #include "heap.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -36,6 +36,8 @@
     BOOL32           changed;
     PROFILESECTION  *section;
     char            *dos_name;
+    char            *unix_name;
+    char            *filename;
 } PROFILE;
 
 
@@ -332,8 +334,7 @@
     FILE *file = NULL;
 
     if (!CurProfile.changed || !CurProfile.dos_name) return TRUE;
-    if (!(unix_name = DOSFS_GetUnixFileName( CurProfile.dos_name, FALSE )) ||
-        !(file = fopen( unix_name, "w" )))
+    if (!(unix_name = CurProfile.unix_name) || !(file = fopen(unix_name, "w")))
     {
         /* Try to create it in $HOME/.wine */
         /* FIXME: this will need a more general solution */
@@ -343,7 +344,7 @@
             strcat( buffer, "/.wine/" );
             p = buffer + strlen(buffer);
             strcpy( p, strrchr( CurProfile.dos_name, '\\' ) + 1 );
-            AnsiLower( p );
+            CharLower32A( p );
             file = fopen( buffer, "w" );
             unix_name = buffer;
         }
@@ -372,24 +373,32 @@
  */
 static BOOL32 PROFILE_Open( LPCSTR filename )
 {
+    DOS_FULL_NAME full_name;
     char buffer[MAX_PATHNAME_LEN];
-    const char *dos_name, *unix_name;
     char *newdos_name, *p;
     FILE *file = NULL;
 
+    if (CurProfile.filename && !strcmp( filename, CurProfile.filename ))
+    {
+        dprintf_profile( stddeb, "PROFILE_Open(%s): already opened\n",
+                         filename );
+        return TRUE;
+    }
+
     if (strchr( filename, '/' ) || strchr( filename, '\\' ) || 
         strchr( filename, ':' ))
     {
-        if (!(dos_name = DOSFS_GetDosTrueName( filename, FALSE))) return FALSE;
+        if (!DOSFS_GetFullName( filename, FALSE, &full_name )) return FALSE;
     }
     else
     {
         GetWindowsDirectory32A( buffer, sizeof(buffer) );
         strcat( buffer, "\\" );
         strcat( buffer, filename );
-        if (!(dos_name = DOSFS_GetDosTrueName( buffer, FALSE ))) return FALSE;
+        if (!DOSFS_GetFullName( buffer, FALSE, &full_name )) return FALSE;
     }
-    if (CurProfile.dos_name && !strcmp( dos_name, CurProfile.dos_name ))
+    if (CurProfile.dos_name &&
+        !strcmp( full_name.short_name, CurProfile.dos_name ))
     {
         dprintf_profile( stddeb, "PROFILE_Open(%s): already opened\n",
                          filename );
@@ -398,12 +407,15 @@
 
     /* Flush the previous profile */
 
-    newdos_name = HEAP_strdupA( SystemHeap, 0, dos_name );
+    newdos_name = HEAP_strdupA( SystemHeap, 0, full_name.short_name );
     PROFILE_FlushFile();
     PROFILE_Free( CurProfile.section );
     if (CurProfile.dos_name) HeapFree( SystemHeap, 0, CurProfile.dos_name );
+    if (CurProfile.unix_name) HeapFree( SystemHeap, 0, CurProfile.unix_name );
+    if (CurProfile.filename) HeapFree( SystemHeap, 0, CurProfile.filename );
     CurProfile.section   = NULL;
     CurProfile.dos_name  = newdos_name;
+    CurProfile.filename  = HEAP_strdupA( SystemHeap, 0, filename );
 
     /* Try to open the profile file, first in $HOME/.wine */
 
@@ -414,15 +426,22 @@
         strcat( buffer, "/.wine/" );
         p = buffer + strlen(buffer);
         strcpy( p, strrchr( newdos_name, '\\' ) + 1 );
-        AnsiLower( p );
+        CharLower32A( p );
         if ((file = fopen( buffer, "r" )))
-            dprintf_profile( stddeb, "Found it in %s\n", buffer );
+        {
+            dprintf_profile( stddeb, "PROFILE_Open(%s): found it in %s\n",
+                             filename, buffer );
+            CurProfile.unix_name = HEAP_strdupA( SystemHeap, 0, buffer );
+        }
     }
 
-    if (!file && ((unix_name = DOSFS_GetUnixFileName( dos_name, TRUE ))))
+    if (!file)
     {
-        if ((file = fopen( unix_name, "r" )))
-            dprintf_profile( stddeb, "Found it in %s\n", unix_name );
+        CurProfile.unix_name = HEAP_strdupA( SystemHeap, 0,
+                                             full_name.long_name );
+        if ((file = fopen( full_name.long_name, "r" )))
+            dprintf_profile( stddeb, "PROFILE_Open(%s): found it in %s\n",
+                             filename, full_name.long_name );
     }
 
     if (file)
@@ -435,7 +454,6 @@
         /* Does not exist yet, we will create it in PROFILE_FlushFile */
         fprintf( stderr, "Warning: profile file %s not found\n", newdos_name );
     }
-    dprintf_profile( stddeb, "PROFILE_Open(%s): successful\n", filename );
     return TRUE;
 }
 
diff --git a/graphics/metafiledrv/Makefile.in b/graphics/metafiledrv/Makefile.in
index 1b0a161..5246a6c 100644
--- a/graphics/metafiledrv/Makefile.in
+++ b/graphics/metafiledrv/Makefile.in
@@ -7,8 +7,10 @@
 
 C_SRCS = \
 	bitblt.c \
+	graphics.c \
 	init.c \
-	mapping.c
+	mapping.c \
+	text.c
 
 all: $(MODULE).o
 
diff --git a/graphics/metafiledrv/graphics.c b/graphics/metafiledrv/graphics.c
new file mode 100644
index 0000000..f0fbc02
--- /dev/null
+++ b/graphics/metafiledrv/graphics.c
@@ -0,0 +1,190 @@
+/*
+ * Metafile driver graphics functions
+ *
+ * Copyright 1993, 1994 Alexandre Julliard
+ */
+
+#include <stdlib.h>
+#include "graphics.h"
+#include "gdi.h"
+#include "dc.h"
+#include "metafile.h"
+#include "region.h"
+#include "xmalloc.h"
+#include "metafiledrv.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/**********************************************************************
+ *	     MFDRV_MoveToEx
+ */
+BOOL32
+MFDRV_MoveToEx(DC *dc,INT32 x,INT32 y,LPPOINT32 pt)
+{
+    if (!MF_MetaParam2(dc,META_MOVETO,x,y))
+    	return FALSE;
+
+    if (pt)
+    {
+	pt->x = dc->w.CursPosX;
+	pt->y = dc->w.CursPosY;
+    }
+    dc->w.CursPosX = x;
+    dc->w.CursPosY = y;
+    return TRUE;
+}
+
+/***********************************************************************
+ *           MFDRV_LineTo
+ */
+BOOL32
+MFDRV_LineTo( DC *dc, INT32 x, INT32 y )
+{
+     return MF_MetaParam2(dc, META_LINETO, x, y);
+}
+
+
+/***********************************************************************
+ *           MFDRV_Arc
+ */
+BOOL32 
+MFDRV_Arc( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
+           INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
+{
+     return MF_MetaParam8(dc, META_ARC, left, top, right, bottom,
+			  xstart, ystart, xend, yend);
+}
+
+
+/***********************************************************************
+ *           MFDRV_Pie
+ */
+BOOL32
+MFDRV_Pie( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
+           INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
+{
+    return MF_MetaParam8(dc, META_PIE, left, top, right, bottom,
+			 xstart, ystart, xend, yend);
+}
+
+
+/***********************************************************************
+ *           MFDRV_Chord
+ */
+BOOL32
+MFDRV_Chord( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
+             INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
+{
+    return MF_MetaParam8(dc, META_CHORD, left, top, right, bottom,
+			 xstart, ystart, xend, yend);
+}
+
+/***********************************************************************
+ *           MFDRV_Ellipse
+ */
+BOOL32
+MFDRV_Ellipse( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom )
+{
+    return MF_MetaParam4(dc, META_ELLIPSE, left, top, right, bottom);
+}
+
+/***********************************************************************
+ *           MFDRV_Rectangle
+ */
+BOOL32
+MFDRV_Rectangle(DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom)
+{
+    return MF_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
+}
+
+/***********************************************************************
+ *           MFDRV_RoundRect
+ */
+BOOL32 
+MFDRV_RoundRect( DC *dc, INT32 left, INT32 top, INT32 right,
+                 INT32 bottom, INT32 ell_width, INT32 ell_height )
+{
+    return MF_MetaParam6(dc, META_ROUNDRECT, left, top, right, bottom,
+			 ell_width, ell_height);
+}
+
+/***********************************************************************
+ *           MFDRV_SetPixel
+ */
+COLORREF
+MFDRV_SetPixel( DC *dc, INT32 x, INT32 y, COLORREF color )
+{
+    return MF_MetaParam4(dc, META_SETPIXEL, x, y,HIWORD(color),LOWORD(color)); 
+}
+
+
+/**********************************************************************
+ *          MFDRV_Polyline
+ */
+BOOL32
+MFDRV_Polyline( DC *dc, const LPPOINT32 pt, INT32 count )
+{
+    register int i;
+    LPPOINT16	pt16;
+    BOOL16	ret;
+
+    pt16 = (LPPOINT16)xmalloc(sizeof(POINT16)*count);
+    for (i=count;i--;) CONV_POINT32TO16(&(pt[i]),&(pt16[i]));
+    ret = MF_MetaPoly(dc, META_POLYLINE, pt16, count); 
+
+    free(pt16);
+    return ret;
+}
+
+
+/**********************************************************************
+ *          MFDRV_Polygon
+ */
+BOOL32
+MFDRV_Polygon( DC *dc, LPPOINT32 pt, INT32 count )
+{
+    register int i;
+    LPPOINT16	pt16;
+    BOOL16	ret;
+
+    pt16 = (LPPOINT16)xmalloc(sizeof(POINT16)*count);
+    for (i=count;i--;) CONV_POINT32TO16(&(pt[i]),&(pt16[i]));
+    ret = MF_MetaPoly(dc, META_POLYGON, pt16, count); 
+
+    free(pt16);
+    return ret;
+}
+
+
+/**********************************************************************
+ *          PolyPolygon
+ */
+BOOL32 
+MFDRV_PolyPolygon( DC *dc, LPPOINT32 pt, LPINT32 counts, UINT32 polygons)
+{
+    int		i,j;
+    LPPOINT16	pt16;
+    LPPOINT32	curpt=pt;
+    BOOL32	ret;
+
+    for (i=0;i<polygons;i++) {
+    	pt16=(LPPOINT16)xmalloc(sizeof(POINT16)*counts[i]);
+	for (j=counts[i];j--;) CONV_POINT32TO16(&(curpt[j]),&(pt16[j]));
+	ret = MF_MetaPoly(dc, META_POLYGON, pt16, counts[i]);
+	free(pt16);
+	if (!ret)
+	    return FALSE;
+	curpt+=counts[i];
+    }
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *          MFDRV_ExtFloodFill
+ */
+BOOL32 
+MFDRV_ExtFloodFill( DC *dc, INT32 x, INT32 y, COLORREF color, UINT32 fillType )
+{
+    return MF_MetaParam4(dc,META_FLOODFILL,x,y,HIWORD(color),LOWORD(color)); 
+}
diff --git a/graphics/metafiledrv/init.c b/graphics/metafiledrv/init.c
index 93d38ca..6545c9e 100644
--- a/graphics/metafiledrv/init.c
+++ b/graphics/metafiledrv/init.c
@@ -16,41 +16,38 @@
 
 static const DC_FUNCTIONS MFDRV_Funcs =
 {
-    NULL,                            /* pArc */
+    MFDRV_Arc,                       /* pArc */
     MFDRV_BitBlt,                    /* pBitBlt */
-    NULL,                            /* pChord */
+    MFDRV_Chord,                     /* pChord */
     NULL,                            /* pCreateDC */
     MFDRV_DeleteDC,                  /* pDeleteDC */
     NULL,                            /* pDeleteObject */
-    NULL,                            /* pEllipse */
+    MFDRV_Ellipse,                   /* pEllipse */
     NULL,                            /* pEscape */
     NULL,                            /* pExcludeClipRect */
     NULL,                            /* pExcludeVisRect */
-    NULL,                            /* pExtFloodFill */
-    NULL,                            /* pExtTextOut */
-    NULL,                            /* pFillRgn */
-    NULL,                            /* pFloodFill */
-    NULL,                            /* pFrameRgn */
+    MFDRV_ExtFloodFill,              /* pExtFloodFill */
+    MFDRV_ExtTextOut,                /* pExtTextOut */
+    NULL /* no implementation */,    /* pGetPixel */
     NULL,                            /* pGetTextExtentPoint */
     NULL,                            /* pGetTextMetrics */
     NULL,                            /* pIntersectClipRect */
     NULL,                            /* pIntersectVisRect */
-    NULL,                            /* pInvertRgn */
-    NULL,                            /* pLineTo */
-    NULL,                            /* pMoveToEx */
+    MFDRV_LineTo,                    /* pLineTo */
+    MFDRV_MoveToEx,                  /* pMoveToEx */
     NULL,                            /* pOffsetClipRgn */
     MFDRV_OffsetViewportOrg,         /* pOffsetViewportOrg */
     MFDRV_OffsetWindowOrg,           /* pOffsetWindowOrg */
     NULL,                            /* pPaintRgn */
     MFDRV_PatBlt,                    /* pPatBlt */
-    NULL,                            /* pPie */
-    NULL,                            /* pPolyPolygon */
-    NULL,                            /* pPolygon */
-    NULL,                            /* pPolyline */
+    MFDRV_Pie,                       /* pPie */
+    MFDRV_PolyPolygon,               /* pPolyPolygon */
+    MFDRV_Polygon,                   /* pPolygon */
+    MFDRV_Polyline,                  /* pPolyline */
     NULL,                            /* pRealizePalette */
-    NULL,                            /* pRectangle */
+    MFDRV_Rectangle,                 /* pRectangle */
     NULL,                            /* pRestoreDC */
-    NULL,                            /* pRoundRect */
+    MFDRV_RoundRect,                 /* pRoundRect */
     NULL,                            /* pSaveDC */
     MFDRV_ScaleViewportExt,          /* pScaleViewportExt */
     MFDRV_ScaleWindowExt,            /* pScaleWindowExt */
@@ -63,7 +60,7 @@
     NULL,                            /* pSetDIBitsToDevice */
     MFDRV_SetMapMode,                /* pSetMapMode */
     NULL,                            /* pSetMapperFlags */
-    NULL,                            /* pSetPixel */
+    MFDRV_SetPixel,                  /* pSetPixel */
     NULL,                            /* pSetPolyFillMode */
     NULL,                            /* pSetROP2 */
     NULL,                            /* pSetRelAbs */
@@ -77,8 +74,7 @@
     MFDRV_SetWindowExt,              /* pSetWindowExt */
     MFDRV_SetWindowOrg,              /* pSetWindowOrg */
     MFDRV_StretchBlt,                /* pStretchBlt */
-    NULL,                            /* pStretchDIBits */
-    NULL                             /* pTextOut */
+    NULL                             /* pStretchDIBits */
 };
 
 
@@ -237,4 +233,3 @@
 {
     return !GlobalFree16( hmf );
 }
-
diff --git a/graphics/metafiledrv/text.c b/graphics/metafiledrv/text.c
new file mode 100644
index 0000000..c4caf1e
--- /dev/null
+++ b/graphics/metafiledrv/text.c
@@ -0,0 +1,39 @@
+/*
+ * metafile driver text functions
+ *
+ * Copyright 1993, 1994 Alexandre Julliard
+ *
+ */
+
+#include <stdlib.h>
+#include "windows.h"
+#include "dc.h"
+#include "gdi.h"
+#include "callback.h"
+#include "heap.h"
+#include "metafile.h"
+#include "metafiledrv.h"
+#include "stddebug.h"
+#include "debug.h"
+#include "xmalloc.h"
+
+
+/***********************************************************************
+ *           MFDRV_ExtTextOut
+ */
+BOOL32
+MFDRV_ExtTextOut( DC *dc, INT32 x, INT32 y, UINT32 flags,
+                  const RECT32 *lprect, LPCSTR str, UINT32 count,
+                  const INT32 *lpDx )
+{
+    RECT16	rect16;
+    LPINT16	lpdx16 = lpDx?(LPINT16)xmalloc(sizeof(INT16)*count):NULL;
+    BOOL32	ret;
+    int		i;
+
+    if (lprect)	CONV_RECT32TO16(lprect,&rect16);
+    if (lpdx16)	for (i=count;i--;) lpdx16[i]=lpDx[i];
+    ret=MF_ExtTextOut(dc,x,y,flags,lprect?&rect16:NULL,str,count,lpdx16);
+    if (lpdx16)	free(lpdx16);
+    return ret;
+}
diff --git a/graphics/win16drv/init.c b/graphics/win16drv/init.c
index 8d05cda..0f0399a 100644
--- a/graphics/win16drv/init.c
+++ b/graphics/win16drv/init.c
@@ -50,14 +50,11 @@
     NULL,                            /* pExcludeVisRect */
     NULL,                            /* pExtFloodFill */
     NULL,                            /* pExtTextOut */
-    NULL,                            /* pFillRgn */
-    NULL,                            /* pFloodFill */
-    NULL,                            /* pFrameRgn */
+    NULL,                            /* pGetPixel */
     WIN16DRV_GetTextExtentPoint,     /* pGetTextExtentPoint */
     WIN16DRV_GetTextMetrics,         /* pGetTextMetrics */
     NULL,                            /* pIntersectClipRect */
     NULL,                            /* pIntersectVisRect */
-    NULL,                            /* pInvertRgn */
     NULL,                            /* pLineTo */
     NULL,                            /* pMoveToEx */
     NULL,                            /* pOffsetClipRgn */
@@ -99,8 +96,7 @@
     NULL,                            /* pSetWindowExt (optional) */
     NULL,                            /* pSetWindowOrg (optional) */
     NULL,                            /* pStretchBlt */
-    NULL,                            /* pStretchDIBits */
-    NULL                             /* pTextOut */
+    NULL                             /* pStretchDIBits */
 };
 
 
diff --git a/graphics/x11drv/Makefile.in b/graphics/x11drv/Makefile.in
index 77883a2..1fd36db 100644
--- a/graphics/x11drv/Makefile.in
+++ b/graphics/x11drv/Makefile.in
@@ -9,7 +9,9 @@
 	bitblt.c \
 	clipping.c \
 	font.c \
-	init.c
+	graphics.c \
+	init.c \
+	text.c
 
 all: $(MODULE).o
 
diff --git a/graphics/x11drv/graphics.c b/graphics/x11drv/graphics.c
new file mode 100644
index 0000000..834384a
--- /dev/null
+++ b/graphics/x11drv/graphics.c
@@ -0,0 +1,678 @@
+/*
+ * X11 graphics driver graphics functions
+ *
+ * Copyright 1993,1994 Alexandre Julliard
+ */
+
+#include <math.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Intrinsic.h>
+#ifndef PI
+#define PI M_PI
+#endif
+#include <string.h>
+
+#include "x11drv.h"
+#include "bitmap.h"
+#include "gdi.h"
+#include "graphics.h"
+#include "dc.h"
+#include "bitmap.h"
+#include "callback.h"
+#include "metafile.h"
+#include "syscolor.h"
+#include "stddebug.h"
+#include "palette.h"
+#include "color.h"
+#include "region.h"
+#include "struct32.h"
+#include "debug.h"
+#include "xmalloc.h"
+
+
+/**********************************************************************
+ *	     X11DRV_MoveToEx
+ */
+BOOL32
+X11DRV_MoveToEx(DC *dc,INT32 x,INT32 y,LPPOINT32 pt) {
+    if (pt)
+    {
+	pt->x = dc->w.CursPosX;
+	pt->y = dc->w.CursPosY;
+    }
+    dc->w.CursPosX = x;
+    dc->w.CursPosY = y;
+    return TRUE;
+}
+
+/***********************************************************************
+ *           X11DRV_LineTo
+ */
+BOOL32
+X11DRV_LineTo( DC *dc, INT32 x, INT32 y )
+{
+    if (DC_SetupGCForPen( dc ))
+	XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, 
+		  dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
+		  dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
+		  dc->w.DCOrgX + XLPTODP( dc, x ),
+		  dc->w.DCOrgY + YLPTODP( dc, y ) );
+    dc->w.CursPosX = x;
+    dc->w.CursPosY = y;
+    return TRUE;
+}
+
+
+
+/***********************************************************************
+ *           GRAPH_DrawArc
+ *
+ * Helper functions for Arc(), Chord() and Pie().
+ * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
+ */
+static BOOL32
+X11DRV_DrawArc( DC *dc, INT32 left, INT32 top, INT32 right,
+                INT32 bottom, INT32 xstart, INT32 ystart,
+                INT32 xend, INT32 yend, INT32 lines )
+{
+    INT32 xcenter, ycenter, istart_angle, idiff_angle, tmp;
+    double start_angle, end_angle;
+    XPoint points[3];
+
+    left   = XLPTODP( dc, left );
+    top    = YLPTODP( dc, top );
+    right  = XLPTODP( dc, right );
+    bottom = YLPTODP( dc, bottom );
+    xstart = XLPTODP( dc, xstart );
+    ystart = YLPTODP( dc, ystart );
+    xend   = XLPTODP( dc, xend );
+    yend   = YLPTODP( dc, yend );
+    if ((left == right) || (top == bottom)) return FALSE;
+
+    xcenter = (right + left) / 2;
+    ycenter = (bottom + top) / 2;
+    start_angle = atan2( (double)(ycenter-ystart)*(right-left),
+			 (double)(xstart-xcenter)*(bottom-top) );
+    end_angle   = atan2( (double)(ycenter-yend)*(right-left),
+			 (double)(xend-xcenter)*(bottom-top) );
+    istart_angle = (INT32)(start_angle * 180 * 64 / PI);
+    idiff_angle  = (INT32)((end_angle - start_angle) * 180 * 64 / PI );
+    if (idiff_angle <= 0) idiff_angle += 360 * 64;
+    if (left > right) { tmp=left; left=right; right=tmp; }
+    if (top > bottom) { tmp=top; top=bottom; bottom=tmp; }
+
+      /* Fill arc with brush if Chord() or Pie() */
+
+    if ((lines > 0) && DC_SetupGCForBrush( dc ))
+    {
+        XSetArcMode( display, dc->u.x.gc, (lines==1) ? ArcChord : ArcPieSlice);
+        XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
+                 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+                 right-left-1, bottom-top-1, istart_angle, idiff_angle );
+    }
+
+      /* Draw arc and lines */
+
+    if (!DC_SetupGCForPen( dc )) return TRUE;
+    XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
+	      dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+	      right-left-1, bottom-top-1, istart_angle, idiff_angle );
+    if (!lines) return TRUE;
+
+    points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
+    points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
+    points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
+    points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
+    if (lines == 2)
+    {
+	points[2] = points[1];
+	points[1].x = dc->w.DCOrgX + xcenter;
+	points[1].y = dc->w.DCOrgY + ycenter;
+    }
+    XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
+	        points, lines+1, CoordModeOrigin );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           X11DRV_Arc
+ */
+BOOL32
+X11DRV_Arc( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
+            INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
+{
+    return X11DRV_DrawArc( dc, left, top, right, bottom,
+			   xstart, ystart, xend, yend, 0 );
+}
+
+
+/***********************************************************************
+ *           X11DRV_Pie
+ */
+BOOL32
+X11DRV_Pie( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
+            INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
+{
+    return X11DRV_DrawArc( dc, left, top, right, bottom,
+			   xstart, ystart, xend, yend, 2 );
+}
+
+/***********************************************************************
+ *           X11DRV_Chord
+ */
+BOOL32
+X11DRV_Chord( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom,
+              INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
+{
+    return X11DRV_DrawArc( dc, left, top, right, bottom,
+		  	   xstart, ystart, xend, yend, 1 );
+}
+
+
+/***********************************************************************
+ *           X11DRV_Ellipse
+ */
+BOOL32
+X11DRV_Ellipse( DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom )
+{
+    left   = XLPTODP( dc, left );
+    top    = YLPTODP( dc, top );
+    right  = XLPTODP( dc, right );
+    bottom = YLPTODP( dc, bottom );
+    if ((left == right) || (top == bottom)) return FALSE;
+
+    if (right < left) { INT32 tmp = right; right = left; left = tmp; }
+    if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
+    
+    if ((dc->u.x.pen.style == PS_INSIDEFRAME) &&
+        (dc->u.x.pen.width < right-left-1) &&
+        (dc->u.x.pen.width < bottom-top-1))
+    {
+        left   += dc->u.x.pen.width / 2;
+        right  -= (dc->u.x.pen.width + 1) / 2;
+        top    += dc->u.x.pen.width / 2;
+        bottom -= (dc->u.x.pen.width + 1) / 2;
+    }
+
+    if (DC_SetupGCForBrush( dc ))
+	XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
+		  dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		  right-left-1, bottom-top-1, 0, 360*64 );
+    if (DC_SetupGCForPen( dc ))
+	XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
+		  dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		  right-left-1, bottom-top-1, 0, 360*64 );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           X11DRV_Rectangle
+ */
+BOOL32
+X11DRV_Rectangle(DC *dc, INT32 left, INT32 top, INT32 right, INT32 bottom)
+{
+    INT32 width;
+    left   = XLPTODP( dc, left );
+    top    = YLPTODP( dc, top );
+    right  = XLPTODP( dc, right );
+    bottom = YLPTODP( dc, bottom );
+
+    if (right < left) { INT32 tmp = right; right = left; left = tmp; }
+    if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
+
+    if ((left == right) || (top == bottom))
+    {
+	if (DC_SetupGCForPen( dc ))
+	    XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, 
+		  dc->w.DCOrgX + left,
+		  dc->w.DCOrgY + top,
+		  dc->w.DCOrgX + right,
+		  dc->w.DCOrgY + bottom);
+	return TRUE;
+    }
+    width = dc->u.x.pen.width;
+    if (!width) width = 1;
+    if(dc->u.x.pen.style == PS_NULL) width = 0;
+
+    if ((dc->u.x.pen.style == PS_INSIDEFRAME) &&
+        (width < right-left) && (width < bottom-top))
+    {
+        left   += width / 2;
+        right  -= (width + 1) / 2;
+        top    += width / 2;
+        bottom -= (width + 1) / 2;
+    }
+
+    if (DC_SetupGCForBrush( dc ))
+	XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+		        dc->w.DCOrgX + left + (width + 1) / 2,
+		        dc->w.DCOrgY + top + (width + 1) / 2,
+		        right-left-width-1, bottom-top-width-1);
+    if (DC_SetupGCForPen( dc ))
+	XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+		        right-left-1, bottom-top-1 );
+    return TRUE;
+}
+
+/***********************************************************************
+ *           X11DRV_RoundRect
+ */
+BOOL32
+X11DRV_RoundRect( DC *dc, INT32 left, INT32 top, INT32 right,
+                  INT32 bottom, INT32 ell_width, INT32 ell_height )
+{
+    dprintf_graphics(stddeb, "X11DRV_RoundRect(%d %d %d %d  %d %d\n", 
+    	left, top, right, bottom, ell_width, ell_height);
+
+    left   = XLPTODP( dc, left );
+    top    = YLPTODP( dc, top );
+    right  = XLPTODP( dc, right );
+    bottom = YLPTODP( dc, bottom );
+    ell_width  = abs( ell_width * dc->vportExtX / dc->wndExtX );
+    ell_height = abs( ell_height * dc->vportExtY / dc->wndExtY );
+
+    /* Fix the coordinates */
+
+    if (right < left) { INT32 tmp = right; right = left; left = tmp; }
+    if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
+    if (ell_width > right - left) ell_width = right - left;
+    if (ell_height > bottom - top) ell_height = bottom - top;
+
+    if (DC_SetupGCForBrush( dc ))
+    {
+        if (ell_width && ell_height)
+        {
+            XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
+                      dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+                      ell_width, ell_height, 90 * 64, 90 * 64 );
+            XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
+                      dc->w.DCOrgX + left, dc->w.DCOrgY + bottom - ell_height,
+                      ell_width, ell_height, 180 * 64, 90 * 64 );
+            XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
+                      dc->w.DCOrgX + right - ell_width,
+                      dc->w.DCOrgY + bottom - ell_height,
+                      ell_width, ell_height, 270 * 64, 90 * 64 );
+            XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
+                      dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top,
+                      ell_width, ell_height, 0, 90 * 64 );
+        }
+        if (ell_width < right - left)
+        {
+            XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+                            dc->w.DCOrgX + left + ell_width / 2,
+                            dc->w.DCOrgY + top,
+                            right - left - ell_width, ell_height / 2 );
+            XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+                            dc->w.DCOrgX + left + ell_width / 2,
+                            dc->w.DCOrgY + bottom - (ell_height+1) / 2,
+                            right - left - ell_width, (ell_height+1) / 2 );
+        }
+        if  (ell_height < bottom - top)
+        {
+            XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+                            dc->w.DCOrgX + left,
+                            dc->w.DCOrgY + top + ell_height / 2,
+                            right - left, bottom - top - ell_height );
+        }
+    }
+    if (DC_SetupGCForPen(dc))
+    {
+        if (ell_width && ell_height)
+        {
+            XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
+                      dc->w.DCOrgX + left, dc->w.DCOrgY + top,
+                      ell_width, ell_height, 90 * 64, 90 * 64 );
+            XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
+                      dc->w.DCOrgX + left, dc->w.DCOrgY + bottom - ell_height,
+                      ell_width, ell_height, 180 * 64, 90 * 64 );
+            XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
+                      dc->w.DCOrgX + right - ell_width,
+                      dc->w.DCOrgY + bottom - ell_height,
+                      ell_width, ell_height, 270 * 64, 90 * 64 );
+            XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
+                      dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top,
+                      ell_width, ell_height, 0, 90 * 64 );
+	}
+        if (ell_width < right - left)
+        {
+            XDrawLine( display, dc->u.x.drawable, dc->u.x.gc, 
+                       dc->w.DCOrgX + left + ell_width / 2,
+                       dc->w.DCOrgY + top,
+                       dc->w.DCOrgX + right - ell_width / 2,
+                       dc->w.DCOrgY + top );
+            XDrawLine( display, dc->u.x.drawable, dc->u.x.gc, 
+                       dc->w.DCOrgX + left + ell_width / 2,
+                       dc->w.DCOrgY + bottom,
+                       dc->w.DCOrgX + right - ell_width / 2,
+                       dc->w.DCOrgY + bottom );
+        }
+        if (ell_height < bottom - top)
+        {
+            XDrawLine( display, dc->u.x.drawable, dc->u.x.gc, 
+                       dc->w.DCOrgX + right,
+                       dc->w.DCOrgY + top + ell_height / 2,
+                       dc->w.DCOrgX + right,
+                       dc->w.DCOrgY + bottom - ell_height / 2 );
+            XDrawLine( display, dc->u.x.drawable, dc->u.x.gc, 
+                       dc->w.DCOrgX + left,
+                       dc->w.DCOrgY + top + ell_height / 2,
+                       dc->w.DCOrgX + left,
+                       dc->w.DCOrgY + bottom - ell_height / 2 );
+        }
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           X11DRV_SetPixel
+ */
+COLORREF
+X11DRV_SetPixel( DC *dc, INT32 x, INT32 y, COLORREF color )
+{
+    Pixel pixel;
+    
+    x = dc->w.DCOrgX + XLPTODP( dc, x );
+    y = dc->w.DCOrgY + YLPTODP( dc, y );
+    pixel = COLOR_ToPhysical( dc, color );
+    
+    XSetForeground( display, dc->u.x.gc, pixel );
+    XSetFunction( display, dc->u.x.gc, GXcopy );
+    XDrawPoint( display, dc->u.x.drawable, dc->u.x.gc, x, y );
+
+    /* inefficient but simple... */
+
+    return COLOR_ToLogical(pixel);
+}
+
+
+/***********************************************************************
+ *           X11DRV_GetPixel
+ */
+COLORREF
+X11DRV_GetPixel( DC *dc, INT32 x, INT32 y )
+{
+    static Pixmap pixmap = 0;
+    XImage * image;
+    int pixel;
+
+    x = dc->w.DCOrgX + XLPTODP( dc, x );
+    y = dc->w.DCOrgY + YLPTODP( dc, y );
+    if (dc->w.flags & DC_MEMORY)
+    {
+        image = XGetImage( display, dc->u.x.drawable, x, y, 1, 1,
+                           AllPlanes, ZPixmap );
+    }
+    else
+    {
+        /* If we are reading from the screen, use a temporary copy */
+        /* to avoid a BadMatch error */
+        if (!pixmap) pixmap = XCreatePixmap( display, rootWindow,
+                                             1, 1, dc->w.bitsPerPixel );
+        XCopyArea( display, dc->u.x.drawable, pixmap, BITMAP_colorGC,
+                   x, y, 1, 1, 0, 0 );
+        image = XGetImage( display, pixmap, 0, 0, 1, 1, AllPlanes, ZPixmap );
+    }
+    pixel = XGetPixel( image, 0, 0 );
+    XDestroyImage( image );
+    
+    return COLOR_ToLogical(pixel);
+}
+
+
+/***********************************************************************
+ *           X11DRV_PaintRgn
+ */
+BOOL32
+X11DRV_PaintRgn( DC *dc, HRGN32 hrgn )
+{
+    RECT32 box;
+    HRGN32 tmpVisRgn, prevVisRgn;
+    HDC32  hdc = dc->hSelf; /* FIXME: should not mix dc/hdc this way */
+
+      /* Modify visible region */
+
+    if (!(prevVisRgn = SaveVisRgn( hdc ))) return FALSE;
+    if (!(tmpVisRgn = CreateRectRgn32( 0, 0, 0, 0 )))
+    {
+        RestoreVisRgn( hdc );
+        return FALSE;
+    }
+    CombineRgn32( tmpVisRgn, prevVisRgn, hrgn, RGN_AND );
+    SelectVisRgn( hdc, tmpVisRgn );
+    DeleteObject32( tmpVisRgn );
+
+      /* Fill the region */
+
+    GetRgnBox32( dc->w.hGCClipRgn, &box );
+    if (DC_SetupGCForBrush( dc ))
+	XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+		        dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
+		        box.right-box.left, box.bottom-box.top );
+
+      /* Restore the visible region */
+
+    RestoreVisRgn( hdc );
+    return TRUE;
+}
+
+/**********************************************************************
+ *          X11DRV_Polyline
+ */
+BOOL32
+X11DRV_Polyline( DC *dc, const LPPOINT32 pt, INT32 count )
+{
+    register int i;
+
+    if (DC_SetupGCForPen( dc ))
+	for (i = 0; i < count-1; i ++)
+	    XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,  
+		       dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
+		       dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
+		       dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
+		       dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *          X11DRV_Polygon
+ */
+BOOL32
+X11DRV_Polygon( DC *dc, LPPOINT32 pt, INT32 count )
+{
+    register int i;
+    XPoint *points;
+
+    points = (XPoint *) xmalloc (sizeof (XPoint) * (count+1));
+    for (i = 0; i < count; i++)
+    {
+	points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
+	points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
+    }
+    points[count] = points[0];
+
+    if (DC_SetupGCForBrush( dc ))
+	XFillPolygon( display, dc->u.x.drawable, dc->u.x.gc,
+		     points, count+1, Complex, CoordModeOrigin);
+
+    if (DC_SetupGCForPen ( dc ))
+	XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
+		   points, count+1, CoordModeOrigin );
+
+    free( points );
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *          X11DRV_PolyPolygon
+ */
+BOOL32 
+X11DRV_PolyPolygon( DC *dc, LPPOINT32 pt, LPINT32 counts, UINT32 polygons)
+{
+    HRGN32 hrgn;
+
+      /* FIXME: The points should be converted to device coords before */
+      /* creating the region. But as CreatePolyPolygonRgn is not */
+      /* really correct either, it doesn't matter much... */
+      /* At least the outline will be correct :-) */
+    hrgn = CreatePolyPolygonRgn32( pt, counts, polygons, dc->w.polyFillMode );
+    X11DRV_PaintRgn( dc, hrgn );
+    DeleteObject32( hrgn );
+
+      /* Draw the outline of the polygons */
+
+    if (DC_SetupGCForPen ( dc ))
+    {
+	int i, j, max = 0;
+	XPoint *points;
+
+	for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
+	points = (XPoint *) xmalloc( sizeof(XPoint) * (max+1) );
+
+	for (i = 0; i < polygons; i++)
+	{
+	    for (j = 0; j < counts[i]; j++)
+	    {
+		points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
+		points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
+		pt++;
+	    }
+	    points[j] = points[0];
+	    XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
+		        points, j + 1, CoordModeOrigin );
+	}
+	free( points );
+    }
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *          X11DRV_InternalFloodFill
+ *
+ * Internal helper function for flood fill.
+ * (xorg,yorg) is the origin of the X image relative to the drawable.
+ * (x,y) is relative to the origin of the X image.
+ */
+static void X11DRV_InternalFloodFill(XImage *image, DC *dc,
+                                     int x, int y,
+                                     int xOrg, int yOrg,
+                                     Pixel pixel, WORD fillType )
+{
+    int left, right;
+
+#define TO_FLOOD(x,y)  ((fillType == FLOODFILLBORDER) ? \
+                        (XGetPixel(image,x,y) != pixel) : \
+                        (XGetPixel(image,x,y) == pixel))
+
+    if (!TO_FLOOD(x,y)) return;
+
+      /* Find left and right boundaries */
+
+    left = right = x;
+    while ((left > 0) && TO_FLOOD( left-1, y )) left--;
+    while ((right < image->width) && TO_FLOOD( right, y )) right++;
+    XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+                    xOrg + left, yOrg + y, right-left, 1 );
+
+      /* Set the pixels of this line so we don't fill it again */
+
+    for (x = left; x < right; x++)
+    {
+        if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
+        else XPutPixel( image, x, y, ~pixel );
+    }
+
+      /* Fill the line above */
+
+    if (--y >= 0)
+    {
+        x = left;
+        while (x < right)
+        {
+            while ((x < right) && !TO_FLOOD(x,y)) x++;
+            if (x >= right) break;
+            while ((x < right) && TO_FLOOD(x,y)) x++;
+            X11DRV_InternalFloodFill(image, dc, x-1, y,
+                                     xOrg, yOrg, pixel, fillType );
+        }
+    }
+
+      /* Fill the line below */
+
+    if ((y += 2) < image->height)
+    {
+        x = left;
+        while (x < right)
+        {
+            while ((x < right) && !TO_FLOOD(x,y)) x++;
+            if (x >= right) break;
+            while ((x < right) && TO_FLOOD(x,y)) x++;
+            X11DRV_InternalFloodFill(image, dc, x-1, y,
+                                     xOrg, yOrg, pixel, fillType );
+        }
+    }
+#undef TO_FLOOD    
+}
+
+
+/**********************************************************************
+ *          X11DRV_DoFloodFill
+ *
+ * Main flood-fill routine.
+ */
+static BOOL32 X11DRV_DoFloodFill( DC *dc, RECT32 *rect, INT32 x, INT32 y,
+                                 COLORREF color, UINT32 fillType )
+{
+    XImage *image;
+
+    if (!(image = XGetImage( display, dc->u.x.drawable,
+                             dc->w.DCOrgX + rect->left,
+                             dc->w.DCOrgY + rect->top,
+                             rect->right - rect->left,
+                             rect->bottom - rect->top,
+                             AllPlanes, ZPixmap ))) return FALSE;
+
+    if (DC_SetupGCForBrush( dc ))
+    {
+          /* ROP mode is always GXcopy for flood-fill */
+        XSetFunction( display, dc->u.x.gc, GXcopy );
+        X11DRV_InternalFloodFill(image, dc,
+                                 XLPTODP(dc,x) - rect->left,
+                                 YLPTODP(dc,y) - rect->top,
+                                 dc->w.DCOrgX + rect->left,
+                                 dc->w.DCOrgY + rect->top,
+                                 COLOR_ToPhysical( dc, color ), fillType );
+    }
+
+    XDestroyImage( image );
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *          X11DRV_ExtFloodFill
+ */
+BOOL32
+X11DRV_ExtFloodFill( DC *dc, INT32 x, INT32 y, COLORREF color,
+                     UINT32 fillType )
+{
+    RECT32 rect;
+    HDC32	hdc = dc->hSelf; /* FIXME */
+
+    dprintf_graphics( stddeb, "X11DRV_ExtFloodFill %d,%d %06lx %d\n",
+                      x, y, color, fillType );
+
+    if (!PtVisible32( hdc, x, y )) return FALSE;
+    if (GetRgnBox32( dc->w.hGCClipRgn, &rect ) == ERROR) return FALSE;
+
+    return CallTo32_LargeStack( (int(*)())X11DRV_DoFloodFill, 6,
+                                dc, &rect, x, y, color, fillType );
+}
diff --git a/graphics/x11drv/init.c b/graphics/x11drv/init.c
index 5ceb736..799dec8 100644
--- a/graphics/x11drv/init.c
+++ b/graphics/x11drv/init.c
@@ -16,41 +16,38 @@
 
 static const DC_FUNCTIONS X11DRV_Funcs =
 {
-    NULL,                            /* pArc */
+    X11DRV_Arc,                      /* pArc */
     X11DRV_BitBlt,                   /* pBitBlt */
-    NULL,                            /* pChord */
+    X11DRV_Chord,                    /* pChord */
     X11DRV_CreateDC,                 /* pCreateDC */
     X11DRV_DeleteDC,                 /* pDeleteDC */
     NULL,                            /* pDeleteObject */
-    NULL,                            /* pEllipse */
+    X11DRV_Ellipse,                  /* pEllipse */
     NULL,                            /* pEscape */
     NULL,                            /* pExcludeClipRect */
     NULL,                            /* pExcludeVisRect */
-    NULL,                            /* pExtFloodFill */
-    NULL,                            /* pExtTextOut */
-    NULL,                            /* pFillRgn */
-    NULL,                            /* pFloodFill */
-    NULL,                            /* pFrameRgn */
+    X11DRV_ExtFloodFill,             /* pExtFloodFill */
+    X11DRV_ExtTextOut,               /* pExtTextOut */
+    X11DRV_GetPixel,                 /* pGetPixel */
     X11DRV_GetTextExtentPoint,       /* pGetTextExtentPoint */
     NULL,                            /* pGetTextMetrics */
     NULL,                            /* pIntersectClipRect */
     NULL,                            /* pIntersectVisRect */
-    NULL,                            /* pInvertRgn */
-    NULL,                            /* pLineTo */
-    NULL,                            /* pMoveToEx */
+    X11DRV_LineTo,                   /* pLineTo */
+    X11DRV_MoveToEx,                 /* pMoveToEx */
     NULL,                            /* pOffsetClipRgn */
     NULL,                            /* pOffsetViewportOrg (optional) */
     NULL,                            /* pOffsetWindowOrg (optional) */
-    NULL,                            /* pPaintRgn */
+    X11DRV_PaintRgn,                 /* pPaintRgn */
     X11DRV_PatBlt,                   /* pPatBlt */
-    NULL,                            /* pPie */
-    NULL,                            /* pPolyPolygon */
-    NULL,                            /* pPolygon */
-    NULL,                            /* pPolyline */
+    X11DRV_Pie,                      /* pPie */
+    X11DRV_PolyPolygon,              /* pPolyPolygon */
+    X11DRV_Polygon,                  /* pPolygon */
+    X11DRV_Polyline,                 /* pPolyline */
     NULL,                            /* pRealizePalette */
-    NULL,                            /* pRectangle */
+    X11DRV_Rectangle,                /* pRectangle */
     NULL,                            /* pRestoreDC */
-    NULL,                            /* pRoundRect */
+    X11DRV_RoundRect,                /* pRoundRect */
     NULL,                            /* pSaveDC */
     NULL,                            /* pScaleViewportExt (optional) */
     NULL,                            /* pScaleWindowExt (optional) */
@@ -63,7 +60,7 @@
     NULL,                            /* pSetDIBitsToDevice */
     NULL,                            /* pSetMapMode (optional) */
     NULL,                            /* pSetMapperFlags */
-    NULL,                            /* pSetPixel */
+    X11DRV_SetPixel,                 /* pSetPixel */
     NULL,                            /* pSetPolyFillMode */
     NULL,                            /* pSetROP2 */
     NULL,                            /* pSetRelAbs */
@@ -77,8 +74,7 @@
     NULL,                            /* pSetWindowExt (optional) */
     NULL,                            /* pSetWindowOrg (optional) */
     X11DRV_StretchBlt,               /* pStretchBlt */
-    NULL,                            /* pStretchDIBits */
-    NULL                             /* pTextOut */
+    NULL                             /* pStretchDIBits */
 };
 
 static DeviceCaps X11DRV_DevCaps;
diff --git a/graphics/x11drv/text.c b/graphics/x11drv/text.c
new file mode 100644
index 0000000..4ea2587
--- /dev/null
+++ b/graphics/x11drv/text.c
@@ -0,0 +1,260 @@
+/*
+ * X11 graphics driver text functions
+ *
+ * Copyright 1993,1994 Alexandre Julliard
+ */
+
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include "windows.h"
+#include "dc.h"
+#include "gdi.h"
+/*#include "callback.h"*/
+#include "heap.h"
+#include "x11drv.h"
+#include "stddebug.h"
+/* #define DEBUG_TEXT */
+#include "debug.h"
+#include "xmalloc.h"
+
+#define SWAP_INT(a,b)  { int t = a; a = b; b = t; }
+
+
+extern int CLIPPING_IntersectClipRect( DC * dc, short left, short top,
+                                       short right, short bottom, UINT16 flags);
+
+/***********************************************************************
+ *           X11DRV_ExtTextOut
+ */
+BOOL32
+X11DRV_ExtTextOut( DC *dc, INT32 x, INT32 y, UINT32 flags,
+                   const RECT32 *lprect, LPCSTR str, UINT32 count,
+                   const INT32 *lpDx )
+{
+    HRGN32	hRgnClip = 0;
+    int 	dir, ascent, descent, i;
+    XCharStruct info;
+    XFontStruct *font;
+    RECT32 	rect;
+
+    if (!DC_SetupGCForText( dc )) return TRUE;
+    font = dc->u.x.font.fstruct;
+
+    dprintf_text(stddeb,"ExtTextOut: hdc=%04x %d,%d '%*.*s', %d  flags=%d\n",
+                 dc->hSelf, x, y, count, count, str, count, flags);
+    if (lprect != NULL) dprintf_text(stddeb, "\trect=(%d,%d- %d,%d)\n",
+                                     lprect->left, lprect->top,
+                                     lprect->right, lprect->bottom );
+
+      /* Setup coordinates */
+
+    if (dc->w.textAlign & TA_UPDATECP)
+    {
+	x = dc->w.CursPosX;
+	y = dc->w.CursPosY;
+    }
+
+    if (flags & (ETO_OPAQUE | ETO_CLIPPED))  /* there's a rectangle */
+    {
+        if (!lprect)  /* not always */
+        {
+            SIZE32 sz;
+            if (flags & ETO_CLIPPED)  /* Can't clip with no rectangle */
+	      return FALSE;
+	    if (!X11DRV_GetTextExtentPoint( dc, str, count, &sz ))
+	      return FALSE;
+	    rect.left   = XLPTODP( dc, x );
+	    rect.right  = XLPTODP( dc, x+sz.cx );
+	    rect.top    = YLPTODP( dc, y );
+	    rect.bottom = YLPTODP( dc, y+sz.cy );
+	}
+	else
+	{
+	    rect.left   = XLPTODP( dc, lprect->left );
+	    rect.right  = XLPTODP( dc, lprect->right );
+	    rect.top    = YLPTODP( dc, lprect->top );
+	    rect.bottom = YLPTODP( dc, lprect->bottom );
+	}
+	if (rect.right < rect.left) SWAP_INT( rect.left, rect.right );
+	if (rect.bottom < rect.top) SWAP_INT( rect.top, rect.bottom );
+    }
+
+    x = XLPTODP( dc, x );
+    y = YLPTODP( dc, y );
+
+    dprintf_text(stddeb,"\treal coord: x=%i, y=%i, rect=(%d,%d-%d,%d)\n",
+			  x, y, rect.left, rect.top, rect.right, rect.bottom);
+
+      /* Draw the rectangle */
+
+    if (flags & ETO_OPAQUE)
+    {
+        XSetForeground( display, dc->u.x.gc, dc->w.backgroundPixel );
+        XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+                        dc->w.DCOrgX + rect.left, dc->w.DCOrgY + rect.top,
+                        rect.right-rect.left, rect.bottom-rect.top );
+    }
+    if (!count) return TRUE;  /* Nothing more to do */
+
+      /* Compute text starting position */
+
+    XTextExtents( font, str, count, &dir, &ascent, &descent, &info );
+
+    if (lpDx) /* have explicit character cell x offsets */
+    {
+	/* sum lpDx array and add the width of last character */
+
+        info.width = XTextWidth( font, str + count - 1, 1) + dc->w.charExtra;
+        if (str[count-1] == (char)dc->u.x.font.metrics.tmBreakChar)
+            info.width += dc->w.breakExtra;
+
+        for (i = 0; i < count; i++) info.width += lpDx[i];
+    }
+    else
+       info.width += count*dc->w.charExtra + dc->w.breakExtra*dc->w.breakCount;
+
+    switch( dc->w.textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER) )
+    {
+      case TA_LEFT:
+ 	  if (dc->w.textAlign & TA_UPDATECP)
+	      dc->w.CursPosX = XDPTOLP( dc, x + info.width );
+	  break;
+      case TA_RIGHT:
+	  x -= info.width;
+	  if (dc->w.textAlign & TA_UPDATECP) dc->w.CursPosX = XDPTOLP( dc, x );
+	  break;
+      case TA_CENTER:
+	  x -= info.width / 2;
+	  break;
+    }
+
+    switch( dc->w.textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
+    {
+      case TA_TOP:
+	  y += font->ascent;
+	  break;
+      case TA_BOTTOM:
+	  y -= font->descent;
+	  break;
+      case TA_BASELINE:
+	  break;
+    }
+
+      /* Set the clip region */
+
+    if (flags & ETO_CLIPPED)
+    {
+        hRgnClip = dc->w.hClipRgn;
+        CLIPPING_IntersectClipRect( dc, rect.left, rect.top, rect.right,
+                                    rect.bottom, CLIP_INTERSECT|CLIP_KEEPRGN );
+    }
+
+      /* Draw the text background if necessary */
+
+    if (dc->w.backgroundMode != TRANSPARENT)
+    {
+          /* If rectangle is opaque and clipped, do nothing */
+        if (!(flags & ETO_CLIPPED) || !(flags & ETO_OPAQUE))
+        {
+              /* Only draw if rectangle is not opaque or if some */
+              /* text is outside the rectangle */
+            if (!(flags & ETO_OPAQUE) ||
+                (x < rect.left) ||
+                (x + info.width >= rect.right) ||
+                (y-font->ascent < rect.top) ||
+                (y+font->descent >= rect.bottom))
+            {
+                XSetForeground( display, dc->u.x.gc, dc->w.backgroundPixel );
+                XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
+                                dc->w.DCOrgX + x,
+                                dc->w.DCOrgY + y - font->ascent,
+                                info.width,
+                                font->ascent + font->descent );
+            }
+        }
+    }
+    
+    /* Draw the text (count > 0 verified) */
+
+    XSetForeground( display, dc->u.x.gc, dc->w.textPixel );
+    if (!dc->w.charExtra && !dc->w.breakExtra && !lpDx)
+    {
+        XDrawString( display, dc->u.x.drawable, dc->u.x.gc, 
+                     dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
+    }
+    else  /* Now the fun begins... */
+    {
+        XTextItem *items, *pitem;
+	int delta;
+
+	/* allocate max items */
+
+        pitem = items = xmalloc( count * sizeof(XTextItem) );
+        delta = i = 0;
+        while (i < count)
+        {
+	    /* initialize text item with accumulated delta */
+
+            pitem->chars  = (char *)str + i;
+	    pitem->delta  = delta; 
+            pitem->nchars = 0;
+            pitem->font   = None;
+            delta = 0;
+
+	    /* stuff characters into the same XTextItem until new delta 
+	     * becomes  non-zero */
+
+	    do
+            {
+                if (lpDx) delta += lpDx[i] - XTextWidth( font, str + i, 1);
+                else
+                {
+                    delta += dc->w.charExtra;
+                    if (str[i] == (char)dc->u.x.font.metrics.tmBreakChar)
+                        delta += dc->w.breakExtra;
+                }
+                pitem->nchars++;
+            } 
+	    while ((++i < count) && !delta);
+            pitem++;
+        }
+
+        XDrawText( display, dc->u.x.drawable, dc->u.x.gc,
+                   dc->w.DCOrgX + x, dc->w.DCOrgY + y, items, pitem - items );
+        free( items );
+    }
+
+      /* Draw underline and strike-out if needed */
+
+    if (dc->u.x.font.metrics.tmUnderlined)
+    {
+	long linePos, lineWidth;       
+	if (!XGetFontProperty( font, XA_UNDERLINE_POSITION, &linePos ))
+	    linePos = font->descent-1;
+	if (!XGetFontProperty( font, XA_UNDERLINE_THICKNESS, &lineWidth ))
+	    lineWidth = 0;
+	else if (lineWidth == 1) lineWidth = 0;
+	XSetLineAttributes( display, dc->u.x.gc, lineWidth,
+			    LineSolid, CapRound, JoinBevel ); 
+        XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
+		   dc->w.DCOrgX + x, dc->w.DCOrgY + y + linePos,
+		   dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y + linePos );
+    }
+    if (dc->u.x.font.metrics.tmStruckOut)
+    {
+	long lineAscent, lineDescent;
+	if (!XGetFontProperty( font, XA_STRIKEOUT_ASCENT, &lineAscent ))
+	    lineAscent = font->ascent / 3;
+	if (!XGetFontProperty( font, XA_STRIKEOUT_DESCENT, &lineDescent ))
+	    lineDescent = -lineAscent;
+	XSetLineAttributes( display, dc->u.x.gc, lineAscent + lineDescent,
+			    LineSolid, CapRound, JoinBevel ); 
+	XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
+		   dc->w.DCOrgX + x, dc->w.DCOrgY + y - lineAscent,
+		   dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y - lineAscent );
+    }
+
+    if (flags & ETO_CLIPPED) SelectClipRgn32( dc->hSelf, hRgnClip );
+    return TRUE;
+}
diff --git a/if1632/Makefile.in b/if1632/Makefile.in
index 11222e0..e5de231 100644
--- a/if1632/Makefile.in
+++ b/if1632/Makefile.in
@@ -81,9 +81,6 @@
 
 $(SPEC_FILES): $(BUILD)
 
-$(BUILD) checkbuild:
-	cd $(TOPOBJDIR)/tools; $(SUBMAKE) build
-
 callfrom16.s: $(SPEC_FILES)
 	$(BUILD) -o $@ -callfrom16 `cat $(SPEC_FILES) | grep CallFrom16_ | sed 's/.*CallFrom16_\(.*\)/\1/' | sort | uniq`
 
diff --git a/if1632/advapi32.spec b/if1632/advapi32.spec
index 9ce2f08..1b5cc7d 100644
--- a/if1632/advapi32.spec
+++ b/if1632/advapi32.spec
@@ -198,7 +198,7 @@
 0193 stub SetThreadToken
 0194 stub SetTokenInformation
 0195 stub StartServiceA
-0196 stub StartServiceCtrlDispatcherA
-0197 stub StartServiceCtrlDispatcherW
+0196 stdcall StartServiceCtrlDispatcherA(ptr) StartServiceCtrlDispatcher32A
+0197 stdcall StartServiceCtrlDispatcherW(ptr) StartServiceCtrlDispatcher32W
 0198 stub StartServiceW
 0199 stub UnlockServiceDatabase
diff --git a/if1632/crtdll.spec b/if1632/crtdll.spec
index 728ea41..a7c6f88 100644
--- a/if1632/crtdll.spec
+++ b/if1632/crtdll.spec
@@ -3,9 +3,9 @@
 type	win32
 base	1
 
-001 cdecl ??2@YAPAXI@Z(long) CRTDLL_malloc
-002 cdecl ??3@YAXPAX@Z(long) CRTDLL_free
-003 stub ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z
+001 cdecl ??2@YAPAXI@Z(long) CRTDLL_new
+002 cdecl ??3@YAXPAX@Z(long) CRTDLL_delete
+003 cdecl ?_set_new_handler@@YAP6AHI@ZP6AHI@Z@Z(ptr) CRTDLL_set_new_handler
 004 stub _CIacos
 005 stub _CIasin
 006 stub _CIatan
diff --git a/if1632/gdi32.spec b/if1632/gdi32.spec
index 08f90e6..cc8f25f 100644
--- a/if1632/gdi32.spec
+++ b/if1632/gdi32.spec
@@ -61,8 +61,8 @@
 0054 stdcall CreatePatternBrush(long) CreatePatternBrush32
 0055 stdcall CreatePen(long long long) CreatePen32
 0056 stdcall CreatePenIndirect(ptr) CreatePenIndirect32
-0057 stub CreatePolyPolygonRgn
-0058 stub CreatePolygonRgn
+0057 stdcall CreatePolyPolygonRgn(ptr ptr long long) CreatePolyPolygonRgn32
+0058 stdcall CreatePolygonRgn(ptr long long) CreatePolygonRgn32
 0059 stdcall CreateRectRgn(long long long long) CreateRectRgn32
 0060 stdcall CreateRectRgnIndirect(ptr) CreateRectRgnIndirect32
 0061 stdcall CreateRoundRectRgn(long long long long long long)
@@ -276,7 +276,7 @@
 0268 stub PolyBezier
 0269 stub PolyBezierTo
 0270 stub PolyDraw
-0271 stub PolyPolygon
+0271 stdcall PolyPolygon(long ptr ptr long) PolyPolygon32
 0272 stub PolyPolyline
 0273 stub PolyTextOutA
 0274 stub PolyTextOutW
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 88456fd..f38b190 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -204,7 +204,7 @@
 204 stub SwapRecording
 205 stub CVWBreak
 206 pascal16 AllocSelectorArray(word) AllocSelectorArray
-207 return IsDBCSLeadByte 2 0
+207 pascal16 IsDBCSLeadByte(word) IsDBCSLeadByte16
 216 pascal   RegEnumKey(long long ptr long) RegEnumKey16
 217 pascal   RegOpenKey(long ptr ptr) RegOpenKey16
 218 pascal   RegCreateKey(long ptr ptr) RegCreateKey16
diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec
index 9fbd367..a9dcba4 100644
--- a/if1632/kernel32.spec
+++ b/if1632/kernel32.spec
@@ -39,7 +39,7 @@
 0034 stub ContinueDebugEvent
 0035 stub ConvertDefaultLocale
 0036 stdcall CopyFileA(ptr ptr long) CopyFile32A
-0037 stub CopyFileW
+0037 stdcall CopyFileW(ptr ptr long) CopyFile32W
 0038 stub CreateConsoleScreenBuffer
 0039 stdcall CreateDirectoryA(ptr ptr) CreateDirectory32A
 0040 stdcall CreateDirectoryExA(ptr ptr ptr) CreateDirectoryEx32A
@@ -143,8 +143,8 @@
 0138 stdcall FormatMessageA() WIN32_FormatMessage32A
 0139 stdcall FormatMessageW() WIN32_FormatMessage32W
 0140 stub FreeConsole
-0141 stdcall FreeEnvironmentStringsA(ptr)	FreeEnvironmentStringsA
-0142 stdcall FreeEnvironmentStringsW(ptr)	FreeEnvironmentStringsW
+0141 stdcall FreeEnvironmentStringsA(ptr) FreeEnvironmentStrings32A
+0142 stdcall FreeEnvironmentStringsW(ptr) FreeEnvironmentStrings32W
 0143 stdcall FreeLibrary(long) FreeLibrary32
 0144 stub FreeLibraryAndExitThread
 0145 stdcall FreeResource(long) FreeResource32
@@ -212,9 +212,9 @@
 0207 	stdcall GetDiskFreeSpaceW(ptr ptr ptr ptr ptr) GetDiskFreeSpace32W
 0208 stdcall GetDriveTypeA(ptr) GetDriveType32A
 0209 stdcall GetDriveTypeW(ptr) GetDriveType32W
-0210	stdcall GetEnvironmentStrings()	GetEnvironmentStrings
-0211 stub GetEnvironmentStringsA
-0212 stdcall GetEnvironmentStringsW() GetEnvironmentStringsW
+0210 stdcall GetEnvironmentStrings() GetEnvironmentStrings32A
+0211 stdcall GetEnvironmentStringsA() GetEnvironmentStrings32A
+0212 stdcall GetEnvironmentStringsW() GetEnvironmentStrings32W
 0213 stdcall GetEnvironmentVariableA(ptr ptr long) GetEnvironmentVariable32A
 0214 stdcall GetEnvironmentVariableW(ptr ptr long) GetEnvironmentVariable32W
 0215 stub GetExitCodeProcess
@@ -252,7 +252,7 @@
 0247 stub GetNumberOfConsoleMouseButtons
 0248    stdcall GetOEMCP() GetOEMCP
 0249 stub GetOverlappedResult
-0250 stub GetPriorityClass
+0250 stdcall GetPriorityClass(long) GetPriorityClass
 0251 stdcall GetPrivateProfileIntA(ptr ptr long ptr) GetPrivateProfileInt32A
 0252 stdcall GetPrivateProfileIntW(ptr ptr long ptr) GetPrivateProfileInt32W
 0253 stub GetPrivateProfileSectionA
@@ -296,9 +296,9 @@
 0291 stdcall GetTempFileNameW(ptr ptr long ptr) GetTempFileName32W
 0292 stdcall GetTempPathA(long ptr) GetTempPath32A
 0293 stdcall GetTempPathW(long ptr) GetTempPath32W
-0294	stdcall GetThreadContext(long ptr)	GetThreadContext
-0295 stub GetThreadLocale
-0296 stub GetThreadPriority
+0294 stdcall GetThreadContext(long ptr) GetThreadContext
+0295 stdcall GetThreadLocale() GetThreadLocale
+0296 stdcall GetThreadPriority(long) GetThreadPriority
 0297 stub GetThreadSelectorEntry
 0298 stub GetThreadTimes
 0299 stdcall GetTickCount() GetTickCount
@@ -360,8 +360,8 @@
 0355 stub IsBadStringPtrA
 0356 stub IsBadStringPtrW
 0357 stdcall IsBadWritePtr(ptr long)	WIN32_IsBadWritePtr
-0358 return IsDBCSLeadByte 4 0
-0359 stub IsDBCSLeadByteEx
+0358 stdcall IsDBCSLeadByte(long) IsDBCSLeadByte32
+0359 stdcall IsDBCSLeadByteEx(long long) IsDBCSLeadByteEx
 0360 stub IsValidCodePage
 0361 stdcall IsValidLocale(long long) IsValidLocale
 0362 stub LCMapStringA
@@ -415,8 +415,8 @@
 0410 stub PrepareTape
 0411 stub PulseEvent
 0412 stub PurgeComm
-0413 stub QueryDosDeviceA
-0414 stub QueryDosDeviceW
+0413 stdcall QueryDosDeviceA(ptr ptr long) QueryDosDevice32A
+0414 stdcall QueryDosDeviceW(ptr ptr long) QueryDosDevice32W
 0415 stdcall QueryPerformanceCounter(ptr) QueryPerformanceCounter
 0416 stub QueryPerformanceFrequency
 0417 stub QueryWin31IniFilesMappedToRegistry
@@ -505,20 +505,20 @@
 0500 stub SetLocaleInfoW
 0501 stub SetMailslotInfo
 0502 stub SetNamedPipeHandleState
-0503 stub SetPriorityClass
+0503 stdcall SetPriorityClass(long long) SetPriorityClass
 0504 stub SetProcessShutdownParameters
 0505 stub SetProcessWorkingSetSize
-0506 stub SetStdHandle
-0507    stdcall SetSystemTime(ptr) SetSystemTime
+0506 stdcall SetStdHandle(long long) SetStdHandle
+0507 stdcall SetSystemTime(ptr) SetSystemTime
 0508 stub SetSystemTimeAdjustment
 0509 stub SetTapeParameters
 0510 stub SetTapePosition
 0511 stdcall SetThreadAffinityMask(long long)	SetThreadAffinityMask
 0512 stub SetThreadContext
 0513 stub SetThreadLocale
-0514 stub SetThreadPriority
-0515    stdcall SetTimeZoneInformation(ptr) SetTimeZoneInformation
-0516    stdcall SetUnhandledExceptionFilter(ptr) SetUnhandledExceptionFilter
+0514 stdcall SetThreadPriority(long long) SetThreadPriority
+0515 stdcall SetTimeZoneInformation(ptr) SetTimeZoneInformation
+0516 stdcall SetUnhandledExceptionFilter(ptr) SetUnhandledExceptionFilter
 0517 stub SetVDMCurrentDirectories
 0518 stub SetVolumeLabelA
 0519 stub SetVolumeLabelW
diff --git a/if1632/ntdll.spec b/if1632/ntdll.spec
index 6fc3482..47d4d37 100644
--- a/if1632/ntdll.spec
+++ b/if1632/ntdll.spec
@@ -267,7 +267,7 @@
 263 stub RtlAddAuditAccessAce
 264 stub RtlAdjustPrivilege
 265 stub RtlAllocateAndInitializeSid
-266 stub RtlAllocateHeap
+266 stdcall RtlAllocateHeap(long long long) HeapAlloc
 267 stub RtlAnsiCharToUnicodeChar
 268 stub RtlAnsiStringToUnicodeSize
 269 stub RtlAnsiStringToUnicodeString
@@ -310,7 +310,7 @@
 306 stub RtlCreateAcl
 307 stub RtlCreateAndSetSD
 308 stub RtlCreateEnvironment
-309 stub RtlCreateHeap
+309 stdcall RtlCreateHeap(long long long) HeapCreate
 310 stub RtlCreateProcessParameters
 311 stub RtlCreateQueryDebugBuffer
 312 stub RtlCreateRegistryKey
@@ -375,7 +375,7 @@
 371 stub RtlFormatCurrentUserKeyPath
 372 stub RtlFormatMessage
 373 stub RtlFreeAnsiString
-374 stub RtlFreeHeap
+374 stdcall RtlFreeHeap(long long long) HeapFree
 375 stub RtlFreeOemString
 376 stub RtlFreeSid
 377 stub RtlFreeUnicodeString
@@ -494,7 +494,7 @@
 490 stub RtlSetTimeZoneInformation
 491 stub RtlSetUserFlagsHeap
 492 stub RtlSetUserValueHeap
-493 stub RtlSizeHeap
+493 stdcall RtlSizeHeap(long long long) HeapSize
 494 stub RtlSplay
 495 stub RtlStartRXact
 496 stdcall RtlSubAuthorityCountSid(ptr) RtlSubAuthorityCountSid
@@ -880,7 +880,7 @@
 876 stub _strupr
 877 stub _ultoa
 878 stub _vsnprintf
-879 stub _wcsicmp
+879 stdcall _wcsicmp(ptr ptr) lstrcmpi32W
 880 stub _wcslwr
 881 stub _wcsnicmp
 882 stub _wcsupr
diff --git a/if1632/relay.c b/if1632/relay.c
index cc9b839..712046e 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -186,9 +186,8 @@
  * 'stack' points to the called function address on the 32-bit stack.
  * Stack layout:
  *  ...        ...
- * (stack+12)  arg2
- * (stack+8)   arg1
- * (stack+4)   16-bit ds
+ * (stack+8)   arg2
+ * (stack+4)   arg1
  * (stack)     func to call
  */
 void RELAY_DebugCallTo16( int* stack, int nbargs )
@@ -196,8 +195,8 @@
     if (!debugging_relay) return;
 
     printf( "CallTo16(func=%04x:%04x,ds=%04x",
-            HIWORD(stack[0]), LOWORD(stack[0]), LOWORD(stack[1]) );
-    stack += 2;
+            HIWORD(stack[0]), LOWORD(stack[0]), CURRENT_DS );
+    stack++;
     while (nbargs--) printf( ",0x%04x", *stack++ );
     printf( ")\n" );
 }
diff --git a/if1632/user.spec b/if1632/user.spec
index dee73b5..c878724 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -148,20 +148,20 @@
 146 pascal16 GetClipboardFormatName(word ptr s_word) GetClipboardFormatName
 147 pascal16 SetClipboardViewer(word) SetClipboardViewer
 148 pascal16 GetClipboardViewer() GetClipboardViewer
-149 pascal16 ChangeClipboardChain(word ptr) ChangeClipboardChain
+149 pascal16 ChangeClipboardChain(word ptr) ChangeClipboardChain16
 150 pascal16 LoadMenu(word segptr) LoadMenu16
-151 pascal16 CreateMenu() CreateMenu
-152 pascal16 DestroyMenu(word) DestroyMenu
+151 pascal16 CreateMenu() CreateMenu16
+152 pascal16 DestroyMenu(word) DestroyMenu16
 153 pascal16 ChangeMenu(word word segptr word word) ChangeMenu16
-154 pascal16 CheckMenuItem(word word word) CheckMenuItem
-155 pascal16 EnableMenuItem(word word word) EnableMenuItem
-156 pascal16 GetSystemMenu(word word) GetSystemMenu
-157 pascal16 GetMenu(word) GetMenu
-158 pascal16 SetMenu(word word) SetMenu
-159 pascal16 GetSubMenu(word word) GetSubMenu
-160 pascal16 DrawMenuBar(word) DrawMenuBar
-161 pascal16 GetMenuString(word word ptr s_word word) GetMenuString
-162 pascal16 HiliteMenuItem(word word word word) HiliteMenuItem
+154 pascal16 CheckMenuItem(word word word) CheckMenuItem16
+155 pascal16 EnableMenuItem(word word word) EnableMenuItem16
+156 pascal16 GetSystemMenu(word word) GetSystemMenu16
+157 pascal16 GetMenu(word) GetMenu16
+158 pascal16 SetMenu(word word) SetMenu16
+159 pascal16 GetSubMenu(word word) GetSubMenu16
+160 pascal16 DrawMenuBar(word) DrawMenuBar16
+161 pascal16 GetMenuString(word word ptr s_word word) GetMenuString16
+162 pascal16 HiliteMenuItem(word word word word) HiliteMenuItem16
 163 pascal16 CreateCaret(word word word word) CreateCaret
 164 pascal16 DestroyCaret() DestroyCaret
 165 pascal16 SetCaretPos(word word) SetCaretPos
@@ -252,7 +252,7 @@
 247 pascal16 GetCursor() GetCursor
 248 pascal16 GetOpenClipboardWindow() GetOpenClipboardWindow
 249 pascal16 GetAsyncKeyState(word) GetAsyncKeyState
-250 pascal16 GetMenuState(word word word) GetMenuState
+250 pascal16 GetMenuState(word word word) GetMenuState16
 251 pascal   SendDriverMessage(word word long long) SendDriverMessage
 252 pascal16 OpenDriver(ptr ptr long) OpenDriver
 253 pascal   CloseDriver(word long long) CloseDriver
@@ -266,8 +266,8 @@
              DeferWindowPos
 261 pascal16 EndDeferWindowPos(word) EndDeferWindowPos
 262 pascal16 GetWindow(word word) GetWindow
-263 pascal16 GetMenuItemCount(word) GetMenuItemCount
-264 pascal16 GetMenuItemID(word word) GetMenuItemID
+263 pascal16 GetMenuItemCount(word) GetMenuItemCount16
+264 pascal16 GetMenuItemID(word word) GetMenuItemID16
 265 pascal16 ShowOwnedPopups(word word) ShowOwnedPopups
 266 pascal16 SetMessageQueue(word) SetMessageQueue
 267 pascal16 ShowScrollBar(word word word) ShowScrollBar16
@@ -283,7 +283,7 @@
 277 pascal16 GetDlgCtrlID(word) GetDlgCtrlID
 278 pascal16 GetDesktopHwnd() GetDesktopHwnd
 279 stub OldSetDeskPattern
-280 stub SetSystemMenu
+280 pascal16 SetSystemMenu(word word) SetSystemMenu16
 281 pascal16 GetSysColorBrush(word) GetSysColorBrush16
 282 pascal16 SelectPalette(word word word) SelectPalette
 283 pascal16 RealizePalette(word) RealizePalette
@@ -324,7 +324,7 @@
 343 stub GetFilePortName
 356 stub LoadDIBCursorHandler
 357 stub LoadDIBIconHandler
-358 pascal16 IsMenu(word) IsMenu
+358 pascal16 IsMenu(word) IsMenu16
 359 pascal16 GetDCEx(word word long) GetDCEx16
 362 pascal16 DCHook(word word long long) DCHook
 364 stub LookupIconIDFromDirectoryEx
@@ -364,13 +364,13 @@
 409 stub InitThreadInput
 410 pascal16 InsertMenu(word word word word segptr) InsertMenu16
 411 pascal16 AppendMenu(word word word segptr) AppendMenu16
-412 pascal16 RemoveMenu(word word word) RemoveMenu
-413 pascal16 DeleteMenu(word word word) DeleteMenu
+412 pascal16 RemoveMenu(word word word) RemoveMenu16
+413 pascal16 DeleteMenu(word word word) DeleteMenu16
 414 pascal16 ModifyMenu(word word word word segptr) ModifyMenu16
-415 pascal16 CreatePopupMenu() CreatePopupMenu
+415 pascal16 CreatePopupMenu() CreatePopupMenu16
 416 pascal16 TrackPopupMenu(word word s_word s_word s_word word ptr) TrackPopupMenu16
 417 pascal   GetMenuCheckMarkDimensions() GetMenuCheckMarkDimensions
-418 pascal16 SetMenuItemBitmaps(word word word word word) SetMenuItemBitmaps
+418 pascal16 SetMenuItemBitmaps(word word word word word) SetMenuItemBitmaps16
 420 pascal16 wsprintf() WIN16_wsprintf16
 421 pascal16 wvsprintf(ptr ptr ptr) wvsprintf16
 422 pascal16 DlgDirSelectEx(word ptr word word) DlgDirSelectEx16
@@ -379,14 +379,14 @@
 428 stub TileWindows
 429 stub CascadeWindows
 430 pascal16 lstrcmp(ptr ptr) lstrcmp16
-431 pascal   AnsiUpper(segptr) WIN16_AnsiUpper
-432 pascal   AnsiLower(segptr) WIN16_AnsiLower
+431 pascal   AnsiUpper(segptr) AnsiUpper16
+432 pascal   AnsiLower(segptr) AnsiLower16
 433 pascal16 IsCharAlpha(byte) IsCharAlpha16
 434 pascal16 IsCharAlphanumeric(byte) IsCharAlphanumeric16
 435 pascal16 IsCharUpper(byte) IsCharUpper16
 436 pascal16 IsCharLower(byte) IsCharLower16
-437 pascal16 AnsiUpperBuff(ptr word) AnsiUpperBuff
-438 pascal16 AnsiLowerBuff(ptr word) AnsiLowerBuff
+437 pascal16 AnsiUpperBuff(ptr word) AnsiUpperBuff16
+438 pascal16 AnsiLowerBuff(ptr word) AnsiLowerBuff16
 441 stub InsertMenuItem
 443 stub GetMenuItemInfo
 445 pascal   DefFrameProc(word word word word long) DefFrameProc16
@@ -413,8 +413,8 @@
 466 pascal16 DrawFocusRect(word ptr) DrawFocusRect16
 470 stub StringFunc
 471 pascal16 lstrcmpi(ptr ptr) lstrcmpi16
-472 pascal   AnsiNext(segptr) AnsiNext
-473 pascal   AnsiPrev(segptr segptr) AnsiPrev
+472 pascal   AnsiNext(segptr) AnsiNext16
+473 pascal   AnsiPrev(segptr segptr) AnsiPrev16
 475 pascal16 SetScrollInfo(word s_word ptr word) SetScrollInfo16
 476 pascal16 GetScrollInfo(word s_word ptr) GetScrollInfo16
 477 stub GetKeyboardLayoutName
diff --git a/if1632/user32.spec b/if1632/user32.spec
index 3f5f9e8..41bc522 100644
--- a/if1632/user32.spec
+++ b/if1632/user32.spec
@@ -23,7 +23,7 @@
 0018 stdcall CallWindowProcW(ptr long long long long) CallWindowProc32W
 0019 stub CascadeChildWindows
 0020 stub CascadeWindows
-0021 stub ChangeClipboardChain
+0021 stdcall ChangeClipboardChain(long long) ChangeClipboardChain32
 0022 stdcall ChangeMenuA(long long ptr long long) ChangeMenu32A
 0023 stdcall ChangeMenuW(long long ptr long long) ChangeMenu32W
 0024 stdcall CharLowerA(ptr) CharLower32A
@@ -47,7 +47,7 @@
 0042 stdcall CharUpperBuffW(ptr long) CharUpperBuff32W
 0043 stdcall CharUpperW(ptr) CharUpper32W
 0044 stdcall CheckDlgButton(long long long) CheckDlgButton
-0045 stdcall CheckMenuItem(long long long) CheckMenuItem
+0045 stdcall CheckMenuItem(long long long) CheckMenuItem32
 0046 stub CheckMenuRadioItem
 0047 stdcall CheckRadioButton(long long long long) CheckRadioButton
 0048 stdcall ChildWindowFromPoint(long long long) ChildWindowFromPoint32
@@ -82,8 +82,8 @@
 0077 stub CreateIconIndirect
 0078 stub CreateMDIWindowA
 0079 stub CreateMDIWindowW
-0080 stdcall CreateMenu() CreateMenu
-0081 stdcall CreatePopupMenu() CreatePopupMenu
+0080 stdcall CreateMenu() CreateMenu32
+0081 stdcall CreatePopupMenu() CreatePopupMenu32
 0082 stdcall CreateWindowExA(long ptr ptr long long long long long 
 				long long long ptr) CreateWindowEx32A
 0083 stdcall CreateWindowExW(long ptr ptr long long long long long 
@@ -132,12 +132,12 @@
 0125 stdcall DefWindowProcA(long long long long) DefWindowProc32A
 0126 stdcall DefWindowProcW(long long long long) DefWindowProc32W
 0127 stdcall DeferWindowPos(long long long long long long long long) DeferWindowPos
-0128 stdcall DeleteMenu(long long long) DeleteMenu
+0128 stdcall DeleteMenu(long long long) DeleteMenu32
 0129 stub DestroyAcceleratorTable
 0130 stdcall DestroyCaret() DestroyCaret
 0131 stub DestroyCursor
 0132 stub DestroyIcon
-0133 stdcall DestroyMenu(long) DestroyMenu
+0133 stdcall DestroyMenu(long) DestroyMenu32
 0134 stdcall DestroyWindow(long) DestroyWindow
 0135 stdcall DialogBoxIndirectParamA(long ptr long ptr long) DialogBoxIndirectParam32A
 0136 stub DialogBoxIndirectParamAorW
@@ -164,7 +164,7 @@
 0157 stdcall DrawFrameControl(long ptr long long) DrawFrameControl32
 0158 stdcall DrawIcon(long long long long) DrawIcon
 0159 stub DrawIconEx
-0160 stdcall DrawMenuBar(long) DrawMenuBar
+0160 stdcall DrawMenuBar(long) DrawMenuBar32
 0161 stub DrawStateA
 0162 stub DrawStateW
 0163 stdcall DrawTextA(long ptr long ptr long) DrawText32A
@@ -172,13 +172,13 @@
 0165 stub DrawTextExW
 0166 stdcall DrawTextW(long ptr long ptr long) DrawText32W
 0167 stub EditWndProc
-0168 stdcall EmptyClipboard()				EmptyClipboard
-0169 stdcall EnableMenuItem(long long long) EnableMenuItem
+0168 stdcall EmptyClipboard() EmptyClipboard
+0169 stdcall EnableMenuItem(long long long) EnableMenuItem32
 0170 stdcall EnableScrollBar(long long long) EnableScrollBar32
 0171 stdcall EnableWindow(long long) EnableWindow
 0172 stdcall EndDeferWindowPos(long) EndDeferWindowPos
 0173 stdcall EndDialog(long long) EndDialog
-0174 stub EndMenu
+0174 stdcall EndMenu() EndMenu
 0175 stdcall EndPaint(long ptr) EndPaint32
 0176 stub EndTask
 0177 stdcall EnumChildWindows(long ptr long) THUNK_EnumChildWindows32
@@ -260,19 +260,19 @@
 0253 stub GetKeyboardState
 0254 stub GetKeyboardType
 0255 stub GetLastActivePopup
-0256 stdcall GetMenu(long) GetMenu
-0257 stub GetMenuCheckMarkDimensions
+0256 stdcall GetMenu(long) GetMenu32
+0257 stdcall GetMenuCheckMarkDimensions() GetMenuCheckMarkDimensions
 0258 stub GetMenuContextHelpId
 0259 stub GetMenuDefaultItem
 0260 stub GetMenuIndex
-0261 stdcall GetMenuItemCount(long) GetMenuItemCount
-0262 stdcall GetMenuItemID(long long) GetMenuItemID
+0261 stdcall GetMenuItemCount(long) GetMenuItemCount32
+0262 stdcall GetMenuItemID(long long) GetMenuItemID32
 0263 stub GetMenuItemInfoA
 0264 stub GetMenuItemInfoW
 0265 stub GetMenuItemRect
-0266 stdcall GetMenuState(long long long) GetMenuState
-0267 stdcall GetMenuStringA(long long ptr long long) GetMenuString
-0268 stub GetMenuStringW
+0266 stdcall GetMenuState(long long long) GetMenuState32
+0267 stdcall GetMenuStringA(long long ptr long long) GetMenuString32A
+0268 stdcall GetMenuStringW(long long ptr long long) GetMenuString32W
 0269 stdcall GetMessageA(ptr long long long) USER32_GetMessageA
 0270 stub GetMessageExtraInfo
 0271 stub GetMessagePos
@@ -291,10 +291,10 @@
 0284 stdcall GetScrollPos(long long) GetScrollPos32
 0285 stdcall GetScrollRange(long long ptr ptr) GetScrollRange32
 0286 return GetShellWindow 0 0
-0287 stdcall GetSubMenu(long long) GetSubMenu
+0287 stdcall GetSubMenu(long long) GetSubMenu32
 0288 stdcall GetSysColor(long) GetSysColor
 0289 stdcall GetSysColorBrush(long) GetSysColorBrush32
-0290 stdcall GetSystemMenu(long long) GetSystemMenu
+0290 stdcall GetSystemMenu(long long) GetSystemMenu32
 0291 stdcall GetSystemMetrics(long) GetSystemMetrics
 0292 stdcall GetTabbedTextExtentA(long ptr long long ptr) GetTabbedTextExtent
 0293 stub GetTabbedTextExtentW
@@ -321,7 +321,7 @@
 0314 stub GrayStringA
 0315 stub GrayStringW
 0316 stdcall HideCaret(long) HideCaret
-0317 stub HiliteMenuItem
+0317 stdcall HiliteMenuItem(long long long long) HiliteMenuItem32
 0318 stub ImpersonateDdeClientWindow
 0319 stub InSendMessage
 0320 stdcall InflateRect(ptr long long) InflateRect32
@@ -349,7 +349,7 @@
 0342 stub IsDialogMessageW
 0343 stdcall IsDlgButtonChecked(long long) IsDlgButtonChecked
 0344 stdcall IsIconic(long) IsIconic
-0345 stdcall IsMenu(long) IsMenu
+0345 stdcall IsMenu(long) IsMenu32
 0346 stdcall IsRectEmpty(ptr) IsRectEmpty32
 0347 stdcall IsWindow(long) IsWindow
 0348 stdcall IsWindowEnabled(long) IsWindowEnabled
@@ -444,7 +444,7 @@
 0437 stdcall RegisterWindowMessageW(ptr) RegisterWindowMessage32W
 0438 stdcall ReleaseCapture() ReleaseCapture
 0439 stdcall ReleaseDC(long long) ReleaseDC32
-0440 stdcall RemoveMenu(long long long) RemoveMenu
+0440 stdcall RemoveMenu(long long long) RemoveMenu32
 0441 stdcall RemovePropA(long ptr) RemoveProp32A
 0442 stdcall RemovePropW(long ptr) RemoveProp32W
 0443 stub ReplyMessage
@@ -490,10 +490,10 @@
 0483 stub SetKeyboardState
 0484 stdcall SetLastErrorEx(long long) SetLastErrorEx
 0485 stub SetLogonNotifyWindow
-0486 stdcall SetMenu(long long) SetMenu
+0486 stdcall SetMenu(long long) SetMenu32
 0487 stub SetMenuContextHelpId
 0488 stub SetMenuDefaultItem
-0489 stub SetMenuItemBitmaps
+0489 stdcall SetMenuItemBitmaps(long long long long long) SetMenuItemBitmaps32
 0490 stub SetMenuItemInfoA
 0491 stub SetMenuItemInfoW
 0492 stub SetMessageExtraInfo
@@ -511,7 +511,7 @@
 0504 stub SetSysColors
 0505 stub SetSysColorsTemp
 0506 stub SetSystemCursor
-0507 stub SetSystemMenu
+0507 stdcall SetSystemMenu(long long) SetSystemMenu32
 0508 stdcall SetSystemTimer(long long long ptr) SetSystemTimer32
 0509 stub SetThreadDesktop
 0510 stdcall SetTimer(long long long ptr) SetTimer32
diff --git a/if1632/wprocs.spec b/if1632/wprocs.spec
index 70970d0..0dee94c 100644
--- a/if1632/wprocs.spec
+++ b/if1632/wprocs.spec
@@ -5,9 +5,6 @@
 2  pascal StaticWndProc(word word word long) StaticWndProc
 3  pascal ScrollBarWndProc(word word word long) ScrollBarWndProc
 5  pascal ComboBoxWndProc(word word word long) ComboBoxWndProc
-6  pascal EditWndProc(word word word long) EditWndProc
-7  pascal PopupMenuWndProc(word word word long) PopupMenuWndProc
-9  pascal DefDlgProc(word word word long) DefDlgProc16
 10 pascal MDIClientWndProc(word word word long) MDIClientWndProc
 14 pascal FileOpenDlgProc(word word word long) FileOpenDlgProc
 15 pascal FileSaveDlgProc(word word word long) FileSaveDlgProc
diff --git a/include/accel.h b/include/accel.h
index b8e5690..7c3ad95 100644
--- a/include/accel.h
+++ b/include/accel.h
@@ -5,6 +5,9 @@
  *
  */
 
+#ifndef __WINE_ACCEL_H
+#define __WINE_ACCEL_H
+
 #include "windows.h"
 
 typedef struct {
@@ -23,3 +26,5 @@
 #define CONTROL_ACCEL	0x08
 #define ALT_ACCEL       0x10
 #define SYSTEM_ACCEL	0x80
+
+#endif  /* __WINE_ACCEL_H */
diff --git a/include/atom.h b/include/atom.h
index 3c6f057..3fcc757 100644
--- a/include/atom.h
+++ b/include/atom.h
@@ -4,8 +4,8 @@
  * Copyright 1993 Alexandre Julliard
  */
 
-#ifndef ATOM_H
-#define ATOM_H
+#ifndef __WINE_ATOM_H
+#define __WINE_ATOM_H
 
 #include "windows.h"
 
@@ -25,4 +25,4 @@
     HANDLE16    entries[1];
 } ATOMTABLE;
 
-#endif  /* ATOM_H */
+#endif  /* __WINE_ATOM_H */
diff --git a/include/button.h b/include/button.h
index ae1b6fe..b0c7a1f 100644
--- a/include/button.h
+++ b/include/button.h
@@ -4,8 +4,8 @@
  * Copyright 1994 Alexandre Julliard
  */
 
-#ifndef BUTTON_H
-#define BUTTON_H
+#ifndef __WINE_BUTTON_H
+#define __WINE_BUTTON_H
 
 #include "windows.h"
 
@@ -31,4 +31,4 @@
 extern LRESULT ButtonWndProc( HWND32 hWnd, UINT32 uMsg,
                               WPARAM32 wParam, LPARAM lParam );
 
-#endif  /* BUTTON_H */
+#endif  /* __WINE_BUTTON_H */
diff --git a/include/class.h b/include/class.h
index e02bec7..faa94c7 100644
--- a/include/class.h
+++ b/include/class.h
@@ -4,8 +4,8 @@
  * Copyright 1993 Alexandre Julliard
  */
 
-#ifndef CLASS_H
-#define CLASS_H
+#ifndef __WINE_CLASS_H
+#define __WINE_CLASS_H
 
 #include "windows.h"
 #include "winproc.h"
@@ -40,4 +40,4 @@
 extern void CLASS_FreeModuleClasses( HMODULE16 hModule );
 extern CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE16 hinstance );
 
-#endif  /* CLASS_H */
+#endif  /* __WINE_CLASS_H */
diff --git a/include/comm.h b/include/comm.h
index 0d3df44..5f2b0af 100644
--- a/include/comm.h
+++ b/include/comm.h
@@ -1,5 +1,5 @@
-#ifndef COMM_H
-#define COMM_H
+#ifndef __WINE_COMM_H
+#define __WINE_COMM_H
 
 #define MAX_PORTS   16
 
@@ -14,4 +14,4 @@
 
 extern void COMM_Init(void);
 
-#endif  /* COMM_H */
+#endif  /* __WINE_COMM_H */
diff --git a/include/crtdll.h b/include/crtdll.h
index beb87cc..916e9b4 100644
--- a/include/crtdll.h
+++ b/include/crtdll.h
@@ -1,5 +1,5 @@
-#ifndef _WINE_CRTDLL_H
-#define _WINE_CRTDLL_H
+#ifndef __WINE_CRTDLL_H
+#define __WINE_CRTDLL_H
 
 #define CRTDLL_LC_ALL		0
 #define CRTDLL_LC_COLLATE	1
diff --git a/include/dce.h b/include/dce.h
index b21ec2a..368174c 100644
--- a/include/dce.h
+++ b/include/dce.h
@@ -4,8 +4,8 @@
  * Copyright 1993 Alexandre Julliard
  */
 
-#ifndef DCE_H
-#define DCE_H
+#ifndef __WINE_DCE_H
+#define __WINE_DCE_H
 
 #include "windows.h"
 #include "win.h"
@@ -50,4 +50,4 @@
 extern void  DCE_FreeDCE( DCE *dce );
 extern INT16 DCE_ExcludeRgn( HDC32, WND*, HRGN32 );
 
-#endif  /* DCE_H */
+#endif  /* __WINE_DCE_H */
diff --git a/include/debugger.h b/include/debugger.h
index 5a69215..13779d0 100644
--- a/include/debugger.h
+++ b/include/debugger.h
@@ -14,17 +14,58 @@
 
 #define STEP_FLAG 0x100 /* single step flag */
 
+#define SYM_FUNC	 0x0
+#define SYM_DATA	 0x1
+#define SYM_WIN32	 0x2
+#define SYM_WINE	 0x4
+#define SYM_INVALID	 0x8
+#define SYM_TRAMPOLINE	 0x10
+#define SYM_STEP_THROUGH 0x20
+
+enum	debug_type {BASIC, CONST, POINTER, ARRAY, STRUCT, ENUM, TYPEDEF, FUNC, BITFIELD};
+
+
+/*
+ * Return values for DEBUG_CheckLinenoStatus.  Used to determine
+ * what to do when the 'step' command is given.
+ */
+#define FUNC_HAS_NO_LINES	(0)
+#define NOT_ON_LINENUMBER	(1)
+#define AT_LINENUMBER		(2)
+#define FUNC_IS_TRAMPOLINE	(3)
+
+/*
+ * For constants generated by the parser, we use this datatype
+ */
+extern struct datatype * DEBUG_TypeInt;
+extern struct datatype * DEBUG_TypeIntConst;
+extern struct datatype * DEBUG_TypeUSInt;
+extern struct datatype * DEBUG_TypeString;
+
 typedef struct
 {
+    struct datatype * type;
     DWORD seg;  /* 0xffffffff means current default segment (cs or ds) */
     DWORD off;
 } DBG_ADDR;
 
+struct list_id
+{
+    char * sourcefile;
+    int    line;
+};
+
 struct  wine_lines {
   unsigned long		line_number;
   DBG_ADDR		pc_offset;
 };
 
+struct symbol_info
+{
+  struct name_hash * sym;
+  struct list_id     list;
+};
+
 typedef struct wine_lines WineLineNo;
 
 /*
@@ -34,30 +75,15 @@
  */
 struct  wine_locals {
   unsigned int		regno:8;	/* For register symbols */
-  unsigned int		offset:24;	/* offset from esp/ebp to symbol */
+  signed int		offset:24;	/* offset from esp/ebp to symbol */
   unsigned int		pc_start;	/* For RBRAC/LBRAC */
   unsigned int		pc_end;		/* For RBRAC/LBRAC */
   char		      * name;		/* Name of symbol */
+  struct datatype     * type;		/* Datatype of symbol */
 };
 
 typedef struct wine_locals WineLocals;
 
-struct name_hash
-{
-    struct name_hash * next;
-    char *             name;
-    char *             sourcefile;
-
-    int		       n_locals;
-    int		       locals_alloc;
-    WineLocals       * local_vars;
-  
-    int		       n_lines;
-    int		       lines_alloc;
-    WineLineNo       * linetab;
-
-    DBG_ADDR           addr;
-};
 
 #define DBG_FIX_ADDR_SEG(addr,default) \
     { if ((addr)->seg == 0xffffffff) (addr)->seg = (default); \
@@ -97,8 +123,16 @@
 enum exec_mode
 {
     EXEC_CONT,       /* Continuous execution */
-    EXEC_STEP_OVER,  /* Stepping over a call */
-    EXEC_STEP_INSTR  /* Single-stepping an instruction */
+    EXEC_STEP_OVER,  /* Stepping over a call to next source line */
+    EXEC_STEP_INSTR,  /* Step to next source line, stepping in if needed */
+    EXEC_STEPI_OVER,  /* Stepping over a call */
+    EXEC_STEPI_INSTR,  /* Single-stepping an instruction */
+    EXEC_FINISH,		/* Step until we exit current frame */
+    EXEC_STEP_OVER_TRAMPOLINE  /* Step over trampoline.  Requires that
+				* we dig the real return value off the stack
+				* and set breakpoint there - not at the
+				* instr just after the call.
+				*/
 };
 
 extern CONTEXT DEBUG_context;  /* debugger/registers.c */
@@ -112,40 +146,91 @@
 extern void DEBUG_EnableBreakpoint( int num, BOOL32 enable );
 extern void DEBUG_InfoBreakpoints(void);
 extern BOOL32 DEBUG_HandleTrap(void);
-extern BOOL32 DEBUG_ShouldContinue( enum exec_mode mode );
-extern void DEBUG_RestartExecution( enum exec_mode mode, int instr_len );
+extern BOOL32 DEBUG_ShouldContinue( enum exec_mode mode, int * count );
+extern enum exec_mode DEBUG_RestartExecution( enum exec_mode mode, int count );
+extern BOOL32 DEBUG_IsFctReturn(void);
 
   /* debugger/db_disasm.c */
-extern void DEBUG_Disasm( DBG_ADDR *addr );
+extern void DEBUG_Disasm( DBG_ADDR *addr, int display );
+
+  /* debugger/expr.c */
+extern void DEBUG_FreeExprMem(void);
+struct expr * DEBUG_RegisterExpr(enum debug_regs);
+struct expr * DEBUG_SymbolExpr(const char * name);
+struct expr * DEBUG_ConstExpr(int val);
+struct expr * DEBUG_StringExpr(const char * str);
+struct expr * DEBUG_SegAddr(struct expr *, struct expr *);
+struct expr * DEBUG_USConstExpr(unsigned int val);
+struct expr * DEBUG_BinopExpr(int oper, struct expr *, struct expr *);
+struct expr * DEBUG_UnopExpr(int oper, struct expr *);
+struct expr * DEBUG_StructPExpr(struct expr *, const char * element);
+struct expr * DEBUG_StructExpr(struct expr *, const char * element);
+struct expr * DEBUG_ArrayExpr(struct expr *, struct expr * index);
+struct expr * DEBUG_CallExpr(const char *, int nargs, ...);
+extern   int  DEBUG_ExprValue(DBG_ADDR *, unsigned int *);
+DBG_ADDR DEBUG_EvalExpr(struct expr *);
+extern int DEBUG_AddDisplay(struct expr * exp);
+extern int DEBUG_DelDisplay(int displaynum);
+extern struct expr * DEBUG_CloneExpr(struct expr * exp);
+extern int DEBUG_FreeExpr(struct expr * exp);
+extern int DEBUG_DisplayExpr(struct expr * exp);
+
+  /* more debugger/break.c */
+extern int DEBUG_AddBPCondition(int bpnum, struct expr * exp);
+
+  /* debugger/display.c */
+extern int DEBUG_DoDisplay(void);
+extern int DEBUG_AddDisplay(struct expr * exp);
+extern int DEBUG_DoDisplay(void);
+extern int DEBUG_DelDisplay(int displaynum);
+extern int DEBUG_InfoDisplay(void);
 
   /* debugger/hash.c */
 extern struct name_hash * DEBUG_AddSymbol( const char *name, 
 					   const DBG_ADDR *addr,
+					   const char * sourcefile,
+					   int flags);
+extern struct name_hash * DEBUG_AddInvSymbol( const char *name, 
+					   const DBG_ADDR *addr,
 					   const char * sourcefile);
 extern BOOL32 DEBUG_GetSymbolValue( const char * name, const int lineno,
-				    DBG_ADDR *addr );
+				    DBG_ADDR *addr, int );
 extern BOOL32 DEBUG_SetSymbolValue( const char * name, const DBG_ADDR *addr );
 extern const char * DEBUG_FindNearestSymbol( const DBG_ADDR *addr, int flag,
 					     struct name_hash ** rtn,
-					     unsigned int ebp);
+					     unsigned int ebp,
+					     struct list_id * source);
 extern void DEBUG_ReadSymbolTable( const char * filename );
 extern void DEBUG_LoadEntryPoints(void);
 extern void DEBUG_AddLineNumber( struct name_hash * func, int line_num, 
 		     unsigned long offset );
-extern void DEBUG_AddLocal( struct name_hash * func, int regno, 
+extern struct wine_locals *
+            DEBUG_AddLocal( struct name_hash * func, int regno, 
 			    int offset,
 			    int pc_start,
 			    int pc_end,
 			    char * name);
+extern int DEBUG_CheckLinenoStatus(const DBG_ADDR *addr);
+extern void DEBUG_GetFuncInfo(struct list_id * ret, const char * file, 
+			      const char * func);
+extern int DEBUG_SetSymbolSize(struct name_hash * sym, unsigned int len);
+extern int DEBUG_SetSymbolBPOff(struct name_hash * sym, unsigned int len);
+extern int DEBUG_GetSymbolAddr(struct name_hash * sym, DBG_ADDR * addr);
+extern int DEBUG_cmp_sym(const void * p1, const void * p2);
+extern BOOL32 DEBUG_GetLineNumberAddr( struct name_hash *, const int lineno, 
+				DBG_ADDR *addr, int bp_flag );
 
+extern int DEBUG_SetLocalSymbolType(struct wine_locals * sym, 
+				    struct datatype * type);
+BOOL32 DEBUG_Normalize(struct name_hash * nh );
 
   /* debugger/info.c */
-extern void DEBUG_Print( const DBG_ADDR *addr, int count, char format );
-extern struct name_hash * DEBUG_PrintAddress( const DBG_ADDR *addr, 
+extern void DEBUG_PrintBasic( const DBG_ADDR *addr, int count, char format );
+extern struct symbol_info DEBUG_PrintAddress( const DBG_ADDR *addr, 
 					      int addrlen, int flag );
 extern void DEBUG_Help(void);
-extern void DEBUG_List( DBG_ADDR *addr, int count );
-extern struct name_hash * DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr, 
+extern void DEBUG_HelpInfo(void);
+extern struct symbol_info DEBUG_PrintAddressAndArgs( const DBG_ADDR *addr, 
 						     int addrlen, 
 						     unsigned int ebp, 
 						     int flag );
@@ -164,13 +249,17 @@
 extern BOOL32 DEBUG_ValidateRegisters(void);
 extern void DEBUG_SetSigContext( const SIGCONTEXT *sigcontext );
 extern void DEBUG_GetSigContext( SIGCONTEXT *sigcontext );
+extern int DEBUG_PrintRegister(enum debug_regs reg);
 
   /* debugger/stack.c */
 extern void DEBUG_InfoStack(void);
 extern void DEBUG_BackTrace(void);
-extern BOOL32 DEBUG_GetStackSymbolValue( const char * name, DBG_ADDR *addr );
+extern void DEBUG_SilentBackTrace(void);
 extern int  DEBUG_InfoLocals(void);
 extern int  DEBUG_SetFrame(int newframe);
+extern int  DEBUG_GetCurrentFrame(struct name_hash ** name, 
+				  unsigned int * eip,
+				  unsigned int * ebp);
 
   /* debugger/stabs.c */
 extern int DEBUG_ReadExecutableDbgInfo(void);
@@ -179,6 +268,42 @@
 extern int DEBUG_RegisterDebugInfo(int, struct pe_data *pe,
 				   int, unsigned long, unsigned long);
 extern int DEBUG_ProcessDeferredDebug(void);
+extern int DEBUG_RegisterELFDebugInfo(int load_addr, u_long size, char * name);
+extern void DEBUG_InfoShare(void);
+extern void DEBUG_InitCVDataTypes(void);
+
+  /* debugger/types.c */
+extern void DEBUG_InitTypes(void);
+extern struct datatype * DEBUG_NewDataType(enum debug_type xtype, 
+					   const char * typename);
+extern unsigned int 
+DEBUG_TypeDerefPointer(DBG_ADDR * addr, struct datatype ** newtype);
+extern int DEBUG_AddStructElement(struct datatype * dt, 
+				  char * name, struct datatype * type, 
+				  int offset, int size);
+extern int DEBUG_SetStructSize(struct datatype * dt, int size);
+extern int DEBUG_SetPointerType(struct datatype * dt, struct datatype * dt2);
+extern int DEBUG_SetArrayParams(struct datatype * dt, int min, int max,
+				struct datatype * dt2);
+extern void DEBUG_Print( const DBG_ADDR *addr, int count, char format, int level );
+extern unsigned int DEBUG_FindStructElement(DBG_ADDR * addr, 
+					    const char * ele_name, int * tmpbuf);
+extern struct datatype * DEBUG_GetPointerType(struct datatype * dt);
+extern int DEBUG_GetObjectSize(struct datatype * dt);
+extern unsigned int DEBUG_ArrayIndex(DBG_ADDR * addr, DBG_ADDR * result, int index);
+extern struct datatype * DEBUG_FindOrMakePointerType(struct datatype * reftype);
+extern long long int DEBUG_GetExprValue(DBG_ADDR * addr, char ** format);
+extern int DEBUG_SetBitfieldParams(struct datatype * dt, int offset, 
+				   int nbits, struct datatype * dt2);
+extern int DEBUG_CopyFieldlist(struct datatype * dt, struct datatype * dt2);
+
+
+  /* debugger/source.c */
+extern void DEBUG_ShowDir(void);
+extern void DEBUG_AddPath(const char * path);
+extern void DEBUG_List(struct list_id * line1, struct list_id * line2,  
+		       int delta);
+extern void DEBUG_NukePath(void);
 
   /* debugger/dbg.y */
 extern void DEBUG_EnterDebugger(void);
diff --git a/include/desktop.h b/include/desktop.h
index 44ced36..129f96e 100644
--- a/include/desktop.h
+++ b/include/desktop.h
@@ -4,8 +4,8 @@
  * Copyright 1994 Alexandre Julliard
  */
 
-#ifndef DESKTOP_H
-#define DESKTOP_H
+#ifndef __WINE_DESKTOP_H
+#define __WINE_DESKTOP_H
 
 #include "windows.h"
 
@@ -21,4 +21,4 @@
 extern LRESULT DesktopWndProc( HWND32 hwnd, UINT32 message,
                                WPARAM32 wParam, LPARAM lParam );
 
-#endif  /* DESKTOP_H */
+#endif  /* __WINE_DESKTOP_H */
diff --git a/include/dialog.h b/include/dialog.h
index b9cb5f4..a9db72e 100644
--- a/include/dialog.h
+++ b/include/dialog.h
@@ -4,8 +4,8 @@
  * Copyright 1993 Alexandre Julliard
  */
 
-#ifndef DIALOG_H
-#define DIALOG_H
+#ifndef __WINE_DIALOG_H
+#define __WINE_DIALOG_H
 
 #include "windows.h"
 #include "winproc.h"
@@ -44,4 +44,4 @@
                                      WINDOWPROCTYPE procType );
 extern INT32 DIALOG_DoDialogBox( HWND32 hwnd, HWND32 owner );
 
-#endif  /* DIALOG_H */
+#endif  /* __WINE_DIALOG_H */
diff --git a/include/dlgs.h b/include/dlgs.h
index f7116ac..c77251f 100644
--- a/include/dlgs.h
+++ b/include/dlgs.h
@@ -2,8 +2,8 @@
 * dlgs.h -      Common dialog's dialog control ID numbers                     *
 ******************************************************************************/
 
-#ifndef DLGS_H
-#define DLGS_H
+#ifndef __WINE_DLGS_H
+#define __WINE_DLGS_H
 
 #define ctlFirst    0x0400
 #define ctlLast     0x04ff
@@ -183,4 +183,4 @@
 #define FORMATDLGORD31   1543
 #define FORMATDLGORD30   1544
 
-#endif  /* #ifdef DLGS_H */
+#endif  /* #ifdef __WINE_DLGS_H */
diff --git a/include/dos_fs.h b/include/dos_fs.h
deleted file mode 100644
index ec7a717..0000000
--- a/include/dos_fs.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * DOS file system declarations
- *
- * Copyright 1996 Alexandre Julliard
- */
-
-#ifndef __WINE_DOS_FS_H
-#define __WINE_DOS_FS_H
-
-#include <time.h>
-#include "windows.h"
-
-#define MAX_PATHNAME_LEN   1024
-
-#define IS_END_OF_NAME(ch)  (!(ch) || ((ch) == '/') || ((ch) == '\\'))
-
-extern void DOSFS_ToDosDateTime( time_t unixtime, WORD *pDate, WORD *pTime );
-extern time_t DOSFS_DosDateTimeToUnixTime(WORD,WORD);
-extern const char *DOSFS_ToDosFCBFormat( const char *name );
-extern const char *DOSFS_ToDosDTAFormat( const char *name );
-extern const char *DOSFS_IsDevice( const char *name );
-extern BOOL32 DOSFS_FindUnixName( const char *path, const char *name,
-                                  char *buffer, int maxlen,
-                                  UINT32 drive_flags );
-extern const char * DOSFS_GetUnixFileName( const char * name, int check_last );
-extern const char * DOSFS_GetDosTrueName( const char *name, int unix_format );
-extern int DOSFS_GetDosFileName( const char *name, char *buffer, int len );
-extern time_t DOSFS_FileTimeToUnixTime( const FILETIME *ft );
-extern void DOSFS_UnixTimeToFileTime(time_t unixtime,LPFILETIME ft);
-extern int DOSFS_FindNext( const char *path, const char *short_mask,
-                           const char *long_mask, int drive, BYTE attr,
-                           int skip, WIN32_FIND_DATA32A *entry );
-
-#endif /* __WINE_DOS_FS_H */
diff --git a/include/driver.h b/include/driver.h
index a033802..16ee0e2 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -2,6 +2,9 @@
  * Drivers definitions
  */
 
+#ifndef __WINE_DRIVER_H
+#define __WINE_DRIVER_H
+
 #define DRV_LOAD                0x0001
 #define DRV_ENABLE              0x0002
 #define DRV_OPEN                0x0003
@@ -64,5 +67,4 @@
 HDRVR16 GetNextDriver(HDRVR16, DWORD);
 BOOL16 GetDriverInfo(HDRVR16, DRIVERINFOSTRUCT16 *);
 
-
-
+#endif  /* __WINE_DRIVER_H */
diff --git a/include/file.h b/include/file.h
index 4856df6..a2bd376 100644
--- a/include/file.h
+++ b/include/file.h
@@ -7,9 +7,23 @@
 #ifndef __WINE_FILE_H
 #define __WINE_FILE_H
 
+#include <time.h>
 #include "windows.h"
 #include "handle32.h"
 
+#define MAX_PATHNAME_LEN   1024
+
+/* Definition of a full DOS file name */
+typedef struct
+{
+    char  long_name[MAX_PATHNAME_LEN];  /* Long pathname in Unix format */
+    char  short_name[MAX_PATHNAME_LEN]; /* Short pathname in DOS 8.3 format */
+    int   drive;
+} DOS_FULL_NAME;
+
+#define IS_END_OF_NAME(ch)  (!(ch) || ((ch) == '/') || ((ch) == '\\'))
+
+
 /* files/file.c */
 extern void FILE_Destroy( K32OBJ *ptr );
 extern void FILE_SetDosError(void);
@@ -29,7 +43,21 @@
 extern UINT32 DIR_GetDosPath( INT32 element, LPSTR path, UINT32 count );
 extern UINT32 DIR_GetUnixPath( INT32 element, LPSTR path, UINT32 count );
 extern DWORD DIR_SearchPath( LPCSTR path, LPCSTR name, LPCSTR ext,
-                             DWORD buflen, LPSTR buffer, LPSTR *lastpart,
-                             BOOL32 win32 );
+                             DOS_FULL_NAME *full_name, BOOL32 win32 );
+
+/* files/dos_fs.c */
+extern void DOSFS_UnixTimeToFileTime( time_t unixtime, LPFILETIME ft,
+                                      DWORD remainder );
+extern time_t DOSFS_FileTimeToUnixTime( const FILETIME *ft, DWORD *remainder );
+extern BOOL32 DOSFS_ToDosFCBFormat( LPCSTR name, LPSTR buffer );
+extern const char *DOSFS_IsDevice( const char *name );
+extern BOOL32 DOSFS_FindUnixName( LPCSTR path, LPCSTR name, LPSTR long_buf,
+                                  INT32 long_len, LPSTR short_buf,
+                                  BOOL32 ignore_case );
+extern BOOL32 DOSFS_GetFullName( LPCSTR name, BOOL32 check_last,
+                                 DOS_FULL_NAME *full );
+extern int DOSFS_FindNext( const char *path, const char *short_mask,
+                           const char *long_mask, int drive, BYTE attr,
+                           int skip, WIN32_FIND_DATA32A *entry );
 
 #endif  /* __WINE_FILE_H */
diff --git a/include/gdi.h b/include/gdi.h
index b00988e..ad48849 100644
--- a/include/gdi.h
+++ b/include/gdi.h
@@ -4,8 +4,8 @@
  * Copyright 1993 Alexandre Julliard
  */
 
-#ifndef GDI_H
-#define GDI_H
+#ifndef __WINE_GDI_H
+#define __WINE_GDI_H
 
 #include "windows.h"
 #include "ldt.h"
@@ -158,14 +158,11 @@
     INT32      (*pExcludeVisRect)(DC*,INT32,INT32,INT32,INT32);
     BOOL32     (*pExtFloodFill)(DC*,INT32,INT32,COLORREF,UINT32);
     BOOL32     (*pExtTextOut)(DC*,INT32,INT32,UINT32,const RECT32*,LPCSTR,UINT32,const INT32*);
-    BOOL32     (*pFillRgn)(DC*,HRGN32,HBRUSH32);
-    BOOL32     (*pFloodFill)(DC*,INT32,INT32,COLORREF);
-    BOOL32     (*pFrameRgn)(DC*,HRGN32,HBRUSH32,INT32,INT32);
+    COLORREF   (*pGetPixel)(DC*,INT32,INT32);
     BOOL32     (*pGetTextExtentPoint)(DC*,LPCSTR,INT32,LPSIZE32);
     BOOL32     (*pGetTextMetrics)(DC*,TEXTMETRIC32A*);
     INT32      (*pIntersectClipRect)(DC*,INT32,INT32,INT32,INT32);
     INT32      (*pIntersectVisRect)(DC*,INT32,INT32,INT32,INT32);
-    BOOL32     (*pInvertRgn)(DC*,HRGN32);
     BOOL32     (*pLineTo)(DC*,INT32,INT32);
     BOOL32     (*pMoveToEx)(DC*,INT32,INT32,LPPOINT32);
     INT32      (*pOffsetClipRgn)(DC*,INT32,INT32);
@@ -208,7 +205,6 @@
     BOOL32     (*pSetWindowOrg)(DC*,INT32,INT32);
     BOOL32     (*pStretchBlt)(DC*,INT32,INT32,INT32,INT32,DC*,INT32,INT32,INT32,INT32,DWORD);
     INT32      (*pStretchDIBits)(DC*,INT32,INT32,INT32,INT32,INT32,INT32,INT32,INT32,LPSTR,LPBITMAPINFO,WORD,DWORD);
-    BOOL32     (*pTextOut)(DC*,INT32,INT32,LPCSTR,INT32);
 } DC_FUNCTIONS;
 
   /* DC hook codes */
@@ -299,4 +295,4 @@
 extern int screenWidth, screenHeight, screenDepth;
 extern int desktopX, desktopY;   /* misc/main.c */
 
-#endif  /* GDI_H */
+#endif  /* __WINE_GDI_H */
diff --git a/include/handle32.h b/include/handle32.h
index a589091..7699eed 100644
--- a/include/handle32.h
+++ b/include/handle32.h
@@ -43,45 +43,4 @@
 extern void K32OBJ_IncCount( K32OBJ *ptr );
 extern void K32OBJ_DecCount( K32OBJ *ptr );
 
-
-/* The _*_OBJECT structures contain information needed about each
- * particular type of handle.  This information is a combination of
- * equivalent UNIX-style handles/descriptors and general information
- * that the Win32 API might request.
- *
- * The KERNEL_OBJECT structure must be the first member of any specific
- * kernel object type's structure.
- */
-
-typedef struct {
-    unsigned long       magic;
-} KERNEL_OBJECT;
-
-
-/* Object number definitions.  These numbers are used to
- * validate the kernel object by comparison against the
- * object's 'magic' value.
-  */
-#define KERNEL_OBJECT_UNUSED    2404554046UL
-#define KERNEL_OBJECT_THREAD    (KERNEL_OBJECT_UNUSED + 1)
-#define KERNEL_OBJECT_PROCESS   (KERNEL_OBJECT_UNUSED + 2)
-#define KERNEL_OBJECT_FILE      (KERNEL_OBJECT_UNUSED + 3)
-#define KERNEL_OBJECT_SEMAPHORE (KERNEL_OBJECT_UNUSED + 4)
-#define KERNEL_OBJECT_EVENT     (KERNEL_OBJECT_UNUSED + 5)
-#define KERNEL_OBJECT_REGKEY    (KERNEL_OBJECT_UNUSED + 6)
-#define KERNEL_OBJECT_FILEMAP   (KERNEL_OBJECT_UNUSED + 7)
-#define KERNEL_OBJECT_VRANGE    (KERNEL_OBJECT_UNUSED + 8)
-#define KERNEL_OBJECT_HEAP      (KERNEL_OBJECT_UNUSED + 9)
-#define KERNEL_OBJECT_HEAPITEM  (KERNEL_OBJECT_UNUSED + 10)
-
-/* Functions for checking kernel objects.
- */
-int ValidateKernelObject(KERNEL_OBJECT *ptr);
-
-/* For now, CreateKernelObject and ReleaseKernelObject will
- * simply map to malloc() and free().
- */
-#define CreateKernelObject(size) (malloc(size))
-#define ReleaseKernelObject(ptr) (free(ptr))
-
 #endif /* __WINE_HANDLE32_H */
diff --git a/include/lzexpand.h b/include/lzexpand.h
index b368272..a026793 100644
--- a/include/lzexpand.h
+++ b/include/lzexpand.h
@@ -3,6 +3,9 @@
  * Copyright 1996 Marcus Meissner
  */
 
+#ifndef __WINE_LZEXPAND_H
+#define __WINE_LZEXPAND_H
+
 #define LZERROR_BADINHANDLE	0xFFFF	/* -1 */
 #define LZERROR_BADOUTHANDLE	0xFFFE	/* -2 */
 #define LZERROR_READ		0xFFFD	/* -3 */
@@ -11,3 +14,5 @@
 #define LZERROR_GLOBLOCK	0xFFFA	/* -6 */
 #define LZERROR_BADVALUE	0xFFF9	/* -7 */
 #define LZERROR_UNKNOWNALG	0xFFF8	/* -8 */
+
+#endif  /* __WINE_LZEXPAND_H */
diff --git a/include/mdi.h b/include/mdi.h
index 564b40a..5db75b6 100644
--- a/include/mdi.h
+++ b/include/mdi.h
@@ -6,8 +6,8 @@
  * MDI structure definitions.
  */
 
-#ifndef MDI_H
-#define MDI_H
+#ifndef __WINE_MDI_H
+#define __WINE_MDI_H
 
 #include "windows.h"
 
@@ -43,5 +43,5 @@
     HWND   	self;
 } MDICLIENTINFO;
 
-#endif /* MDI_H */
+#endif /* __WINE_MDI_H */
 
diff --git a/include/menu.h b/include/menu.h
index 4cd9318..69ef851 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -5,16 +5,14 @@
 #ifndef __WINE_MENU_H
 #define __WINE_MENU_H
 
-extern BOOL MENU_Init(void);
-extern HMENU16 MENU_GetDefSysMenu(void);
-extern void MENU_InitSysMenuPopup(HMENU16 hmenu, DWORD style, DWORD clsStyle);
-extern UINT MENU_GetMenuBarHeight( HWND hwnd, UINT menubarWidth,
-				   int orgX, int orgY );
-extern void MENU_TrackMouseMenuBar( WND* , INT16 ht, POINT16 pt );
-extern void MENU_TrackKbdMenuBar( WND*, UINT16 wParam, INT16 vkey);
-extern UINT MENU_DrawMenuBar( HDC32 hDC, LPRECT16 lprect,
-			      HWND hwnd, BOOL suppress_draw );
-extern LRESULT PopupMenuWndProc( HWND hwnd, UINT message,
-                                 WPARAM16 wParam, LPARAM lParam );
+extern BOOL32 MENU_Init(void);
+extern HMENU32 MENU_GetDefSysMenu(void);
+extern void MENU_InitSysMenuPopup(HMENU32 hmenu, DWORD style, DWORD clsStyle);
+extern UINT32 MENU_GetMenuBarHeight( HWND32 hwnd, UINT32 menubarWidth,
+                                     INT32 orgX, INT32 orgY );
+extern void MENU_TrackMouseMenuBar( WND *wnd, INT32 ht, POINT32 pt );
+extern void MENU_TrackKbdMenuBar( WND *wnd, UINT32 wParam, INT32 vkey );
+extern UINT32 MENU_DrawMenuBar( HDC32 hDC, LPRECT32 lprect,
+                                HWND32 hwnd, BOOL32 suppress_draw );
 
 #endif /* __WINE_MENU_H */
diff --git a/include/metafile.h b/include/metafile.h
index 22e0b61..b511fce 100644
--- a/include/metafile.h
+++ b/include/metafile.h
@@ -4,8 +4,8 @@
  * Copyright  David W. Metcalfe, 1994
  */
 
-#ifndef METAFILE_H
-#define METAFILE_H
+#ifndef __WINE_METAFILE_H
+#define __WINE_METAFILE_H
 
 #include "windows.h"
 
@@ -37,5 +37,5 @@
 		   short heightDest, DC *dcSrc, short xSrc, short ySrc, 
 		   short widthSrc, short heightSrc, DWORD rop);
 
-#endif   /* METAFILE_H */
+#endif   /* __WINE_METAFILE_H */
 
diff --git a/include/metafiledrv.h b/include/metafiledrv.h
index 91027a8..dfb4b92 100644
--- a/include/metafiledrv.h
+++ b/include/metafiledrv.h
@@ -43,5 +43,33 @@
                                       INT32 xDenom, INT32 yNum, INT32 yDenom );
 extern BOOL32 MFDRV_ScaleWindowExt( struct tagDC *dc, INT32 xNum, INT32 xDenom,
                                     INT32 yNum, INT32 yDenom );
+extern BOOL32 MFDRV_MoveToEx(struct tagDC *dc, INT32 x, INT32 y, LPPOINT32 pt);
+extern BOOL32 MFDRV_LineTo( struct tagDC *dc, INT32 x, INT32 y );
+extern BOOL32 MFDRV_Arc( struct tagDC *dc, INT32 left, INT32 top, INT32 right,
+			 INT32 bottom, INT32 xstart, INT32 ystart, INT32 xend,
+			 INT32 yend );
+extern BOOL32 MFDRV_Pie( struct tagDC *dc, INT32 left, INT32 top, INT32 right,
+			 INT32 bottom, INT32 xstart, INT32 ystart, INT32 xend,
+			 INT32 yend );
+extern BOOL32 MFDRV_Chord( struct tagDC *dc, INT32 left, INT32 top, INT32 right,
+			   INT32 bottom, INT32 xstart, INT32 ystart, INT32 xend,
+			   INT32 yend );
+extern BOOL32 MFDRV_Ellipse( struct tagDC *dc, INT32 left, INT32 top,
+			     INT32 right, INT32 bottom );
+extern BOOL32 MFDRV_Rectangle( struct tagDC *dc, INT32 left, INT32 top,
+			       INT32 right, INT32 bottom);
+extern BOOL32 MFDRV_RoundRect( struct tagDC *dc, INT32 left, INT32 top,
+			       INT32 right, INT32 bottom, INT32 ell_width,
+			       INT32 ell_height );
+extern COLORREF MFDRV_SetPixel( struct tagDC *dc, INT32 x, INT32 y, COLORREF color );
+extern BOOL32 MFDRV_Polyline( struct tagDC *dc, const LPPOINT32 pt,INT32 count);
+extern BOOL32 MFDRV_Polygon( struct tagDC *dc, LPPOINT32 pt, INT32 count );
+extern BOOL32 MFDRV_PolyPolygon( struct tagDC *dc, LPPOINT32 pt, LPINT32 counts,
+				 UINT32 polygons);
+extern BOOL32 MFDRV_ExtFloodFill( struct tagDC *dc, INT32 x, INT32 y,
+				  COLORREF color, UINT32 fillType );
+extern BOOL32 MFDRV_ExtTextOut( struct tagDC *dc, INT32 x, INT32 y,
+				UINT32 flags, const RECT32 *lprect, LPCSTR str,
+				UINT32 count, const INT32 *lpDx );
 
 #endif  /* __WINE_METAFILEDRV_H */
diff --git a/include/mmsystem.h b/include/mmsystem.h
index 91e7ef5..cd1c9b7 100644
--- a/include/mmsystem.h
+++ b/include/mmsystem.h
@@ -2,8 +2,8 @@
  * MMSYSTEM - Multimedia Wine Extension ... :-)
  */
 
-#ifndef MMSYSTEM_H
-#define MMSYSTEM_H
+#ifndef __WINE_MMSYSTEM_H
+#define __WINE_MMSYSTEM_H
 
 typedef LPSTR		    HPSTR;          /* a huge version of LPSTR */
 typedef LPCSTR			HPCSTR;         /* a huge version of LPCSTR */
@@ -1539,7 +1539,4 @@
 DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
 					DWORD dwParam1, DWORD dwParam2);
 
-#endif /* MMSYSTEM_H */
-
-
-
+#endif /* __WINE_MMSYSTEM_H */
diff --git a/include/module.h b/include/module.h
index f3a4522..3b52039 100644
--- a/include/module.h
+++ b/include/module.h
@@ -4,8 +4,8 @@
  * Copyright 1995 Alexandre Julliard
  */
 
-#ifndef _WINE_MODULE_H
-#define _WINE_MODULE_H
+#ifndef __WINE_MODULE_H
+#define __WINE_MODULE_H
 
 #include "wintypes.h"
 #include "pe_image.h"
@@ -140,4 +140,4 @@
 extern void NE_FixupPrologs( NE_MODULE *pModule );
 extern void NE_InitializeDLLs( HMODULE16 hModule );
 
-#endif  /* _WINE_MODULE_H */
+#endif  /* __WINE_MODULE_H */
diff --git a/include/msdos.h b/include/msdos.h
index 355aed7..111fbc7 100644
--- a/include/msdos.h
+++ b/include/msdos.h
@@ -1,5 +1,5 @@
-#ifndef __MSDOS_H
-#define __MSDOS_H
+#ifndef __WINE_MSDOS_H
+#define __WINE_MSDOS_H
 
 #include <dirent.h>
 #include "windows.h"
@@ -158,4 +158,4 @@
 #define EL_Serial            0x04
 #define EL_Memory            0x05
 
-#endif /* __MSDOS_H */
+#endif /* __WINE_MSDOS_H */
diff --git a/include/neexe.h b/include/neexe.h
index 7cc36e4..e425573 100644
--- a/include/neexe.h
+++ b/include/neexe.h
@@ -1,10 +1,8 @@
-/* $Id: neexe.h,v 1.4 1993/07/04 04:04:21 root Exp root $
- */
 /*
  * Copyright  Robert J. Amstadt, 1993
  */
-#ifndef NEEXE_H
-#define NEEXE_H
+#ifndef __WINE_NEEXE_H
+#define __WINE_NEEXE_H
 
 #include "wintypes.h"
 
@@ -229,4 +227,4 @@
 int  load_typeinfo  (int, struct resource_typeinfo_s *);
 int  load_nameinfo  (int, struct resource_nameinfo_s *);
 
-#endif /* NEEXE_H */
+#endif  /* __WINE_NEEXE_H */
diff --git a/include/nonclient.h b/include/nonclient.h
index e8a5980..64b8da1 100644
--- a/include/nonclient.h
+++ b/include/nonclient.h
@@ -21,5 +21,7 @@
 extern LONG NC_HandleNCLButtonDblClk( WND *pWnd, WPARAM16 wParam, LPARAM lParam);
 extern LONG NC_HandleSysCommand( HWND32 hwnd, WPARAM16 wParam, POINT16 pt );
 extern LONG NC_HandleSetCursor( HWND32 hwnd, WPARAM16 wParam, LPARAM lParam );
+extern void NC_DrawSysButton( HWND32 hwnd, HDC32 hdc, BOOL32 down );
+extern BOOL32 NC_GetSysPopupPos( WND* wndPtr, RECT32* rect );
 
 #endif /* __WINE_NONCLIENT_H */
diff --git a/include/ole2.h b/include/ole2.h
index 10a16e9..d3856d7 100644
--- a/include/ole2.h
+++ b/include/ole2.h
@@ -2,6 +2,9 @@
  *	ole2.h - Declarations for OLE2
  */
 
+#ifndef __WINE_OLE2_H
+#define __WINE_OLE2_H
+
 typedef LONG HRESULT;
 
 #define S_OK	0
@@ -10,3 +13,5 @@
 /* OLE version */
 #define rmm             23
 #define rup            639
+
+#endif  /* __WINE_OLE2_H */
diff --git a/include/options.h b/include/options.h
index 9e430fc..6fcf570 100644
--- a/include/options.h
+++ b/include/options.h
@@ -4,8 +4,8 @@
  * Copyright 1994 Alexandre Julliard
  */
 
-#ifndef OPTIONS_H
-#define OPTIONS_H
+#ifndef __WINE_OPTIONS_H
+#define __WINE_OPTIONS_H
 
 #include "wintypes.h"
 
@@ -50,7 +50,7 @@
     int    backingstore;    /* Use backing store */
     short  cmdShow;
     int    debug;
-    int    allowReadOnly;   /* Opening a read only file will succeed even
+    int    failReadOnly;    /* Opening a read only file will fail
 			       if write access is requested */
     WINE_MODE mode;         /* Start Wine in selected mode
 			       (standard/enhanced) */
@@ -70,4 +70,4 @@
 extern int PROFILE_GetWineIniInt( const char *section, const char *key_name,
                                   int def );
 
-#endif
+#endif  /* __WINE_OPTIONS_H */
diff --git a/include/peexe.h b/include/peexe.h
index a7d5474..ca46e97 100644
--- a/include/peexe.h
+++ b/include/peexe.h
@@ -253,4 +253,22 @@
 #define IMAGE_REL_BASED_HIGHADJ			4
 #define IMAGE_REL_BASED_MIPS_JMPADDR	5
 
+/*
+ * This is the structure that appears at the very start of a .DBG file.
+ */
+struct PE_DBG_FileHeader {
+    unsigned short int Signature;
+    unsigned short int Flags;
+    unsigned short int Machine;
+    unsigned short int Characteristics;
+    unsigned int       TimeDateStamp;
+    unsigned int       CheckSum;
+    unsigned int       ImageBase;
+    unsigned int       SizeOfImage;
+    unsigned int       NumberOfSections;
+    unsigned int       ExportedNamesSize;
+    unsigned int       DebugDirectorySize;
+    unsigned int       Reserved[ 3 ];
+};
+
 #endif /* __WINE_PEEXE_H */
diff --git a/include/process.h b/include/process.h
index ca5670c..2c018e7 100644
--- a/include/process.h
+++ b/include/process.h
@@ -10,6 +10,7 @@
 #include "windows.h"
 #include "winbase.h"
 #include "handle32.h"
+#include "task.h"
 
 /* Process handle entry */
 typedef struct
@@ -29,13 +30,13 @@
 typedef struct
 {
     LPSTR           environ;          /* 00 Process environment strings */
-    DWORD           unknown1;         /* 04 Unknown */
+    DWORD           env_size;         /* 04 Environment size (was: Unknown) */
     LPSTR           cmd_line;         /* 08 Command line */
     LPSTR           cur_dir;          /* 0c Current directory */
     STARTUPINFO32A *startup_info;     /* 10 Startup information */
-    HANDLE32        hStdin;            /* 14 Handle for standard input */
-    HANDLE32        hStdout;           /* 18 Handle for standard output */
-    HANDLE32        hStderr;           /* 1c Handle for standard error */
+    HANDLE32        hStdin;           /* 14 Handle for standard input */
+    HANDLE32        hStdout;          /* 18 Handle for standard output */
+    HANDLE32        hStderr;          /* 1c Handle for standard error */
     DWORD           unknown2;         /* 20 Unknown */
     DWORD           inherit_console;  /* 24 Inherit console flag */
     DWORD           break_type;       /* 28 Console events flag */
@@ -66,7 +67,7 @@
     HANDLE32         system_heap;      /* 34 System heap to allocate handles */
     HTASK32          task;             /* 38 Win16 task */
     void            *mem_map_files;    /* 3c Pointer to mem-mapped files */
-    ENVDB           *env_DB;           /* 40 Environment database */
+    ENVDB           *env_db;           /* 40 Environment database */
     HANDLE_TABLE    *handle_table;     /* 44 Handle table */
     struct _PDB32   *parent;           /* 48 Parent process */
     void            *modref_list;      /* 4c MODREF list */
@@ -91,13 +92,15 @@
     WORD             error_mode;       /* b6 Error mode */
     K32OBJ          *load_done_evt;    /* b8 Event for process loading done */
     DWORD            unknown7;         /* bc Unknown */
+    DWORD            unknown8;         /* c0 Unknown (NT) */
+    LCID             locale;           /* c4 Locale to be queried by GetThreadLocale (NT) */
 } PDB32;
 
 extern HANDLE32 PROCESS_AllocHandle( K32OBJ *ptr, DWORD flags);
 extern K32OBJ *PROCESS_GetObjPtr( HANDLE32 handle, K32OBJ_TYPE type );
 extern BOOL32 PROCESS_SetObjPtr( HANDLE32 handle, K32OBJ *ptr, DWORD flags );
 
-extern PDB32 *PROCESS_Create(void);
+extern PDB32 *PROCESS_Create( TDB *pTask );
 extern void PROCESS_Destroy( K32OBJ *ptr );
 
 extern PDB32 *pCurrentProcess;
diff --git a/include/scroll.h b/include/scroll.h
index 90411dc..7090245 100644
--- a/include/scroll.h
+++ b/include/scroll.h
@@ -5,8 +5,8 @@
  * Copyright 1994 Alexandre Julliard
  */
 
-#ifndef SCROLL_H
-#define SCROLL_H
+#ifndef __WINE_SCROLL_H
+#define __WINE_SCROLL_H
 
 #include "windows.h"
 
@@ -26,4 +26,4 @@
 extern void SCROLL_HandleScrollEvent( HWND32 hwnd, INT32 nBar,
                                       UINT32 msg, POINT32 pt );
 
-#endif  /* SCROLL_H */
+#endif  /* __WINE_SCROLL_H */
diff --git a/include/selectors.h b/include/selectors.h
index b8e1196..f807403 100644
--- a/include/selectors.h
+++ b/include/selectors.h
@@ -40,6 +40,11 @@
 #define WINE_CODE_SELECTOR 0x17
 #endif  /* svr4 || SCO_DS */
 
+#ifdef __EMX__
+#define WINE_DATA_SELECTOR 0x00 /* FIXME: This is wrong */
+#define WINE_CODE_SELECTOR 0x00
+#endif  /* OS/2 */
+
 #else  /* WINELIB */
 
 #define WINE_DATA_SELECTOR 0x00
diff --git a/include/shell.h b/include/shell.h
index 49cade42..daebe80 100644
--- a/include/shell.h
+++ b/include/shell.h
@@ -1,8 +1,6 @@
 /*
  * 				Shell Library definitions
  */
-#include "wintypes.h"
-
 #ifndef __WINE_SHELL_H
 #define __WINE_SHELL_H
 
diff --git a/include/static.h b/include/static.h
index 42ebfe0..0dd624e 100644
--- a/include/static.h
+++ b/include/static.h
@@ -4,8 +4,8 @@
  * Copyright 1994 Alexandre Julliard
  */
 
-#ifndef STATIC_H
-#define STATIC_H
+#ifndef __WINE_STATIC_H
+#define __WINE_STATIC_H
 
 #include "windows.h"
 
@@ -19,4 +19,4 @@
 
 extern LRESULT StaticWndProc(HWND hWnd,UINT uMsg,WPARAM16 wParam,LPARAM lParam );
 
-#endif  /* STATIC_H */
+#endif  /* __WINE_STATIC_H */
diff --git a/include/stress.h b/include/stress.h
index 190e675..0d1ef93 100644
--- a/include/stress.h
+++ b/include/stress.h
@@ -1,5 +1,5 @@
-#ifndef __STRESS_H
-#define __STRESS_H
+#ifndef __WINE_STRESS_H
+#define __WINE_STRESS_H
 
 #include <windows.h>
 
@@ -27,4 +27,4 @@
 }
 #endif
 
-#endif /* __STRESS_H */
+#endif /* __WINE_STRESS_H */
diff --git a/include/string32.h b/include/string32.h
index 371b5cc..6c644a2 100644
--- a/include/string32.h
+++ b/include/string32.h
@@ -5,12 +5,12 @@
  *
  */
 
-#ifndef _STRING32_H
-#define _STRING32_H
+#ifndef __WINE_STRING32_H
+#define __WINE_STRING32_H
 
 #include "wintypes.h"
 
 LPWSTR	STRING32_DupAnsiToUni(LPCSTR src);
 LPWSTR	STRING32_strdupW(LPCWSTR);
 
-#endif
+#endif  /* __WINE_STRING32_H */
diff --git a/include/struct32.h b/include/struct32.h
index c0e88ce..81a60e1 100644
--- a/include/struct32.h
+++ b/include/struct32.h
@@ -3,12 +3,6 @@
 #define __WINE__STRUCT32_H
 #include "handle32.h"
 
-void STRUCT32_RECT32to16(const RECT32*,RECT16*);
-void STRUCT32_RECT16to32(const RECT16*,RECT32*);
-void STRUCT32_POINT32to16(const POINT32*,POINT16*);
-void STRUCT32_POINT16to32(const POINT16*,POINT32*);
-void STRUCT32_SIZE16to32(const SIZE16*, SIZE32*);
-
 extern void STRUCT32_MINMAXINFO32to16( const MINMAXINFO32*, MINMAXINFO16* );
 extern void STRUCT32_MINMAXINFO16to32( const MINMAXINFO16*, MINMAXINFO32* );
 extern void STRUCT32_WINDOWPOS32to16( const WINDOWPOS32*, WINDOWPOS16* );
diff --git a/include/syscolor.h b/include/syscolor.h
index c8fa8c9..f8bd654 100644
--- a/include/syscolor.h
+++ b/include/syscolor.h
@@ -4,8 +4,8 @@
  * Copyright  Alexandre Julliard, 1994
  */
 
-#ifndef SYSCOLOR_H
-#define SYSCOLOR_H
+#ifndef __WINE_SYSCOLOR_H
+#define __WINE_SYSCOLOR_H
 
 #include "windows.h"
 
@@ -37,4 +37,4 @@
 extern void SYSCOLOR_Init(void);
 extern struct SysColorObjects sysColorObjects;
 
-#endif  /* SYSCOLOR_H */
+#endif  /* __WINE_SYSCOLOR_H */
diff --git a/include/sysmetrics.h b/include/sysmetrics.h
index 52ffa6c..4d5de2f 100644
--- a/include/sysmetrics.h
+++ b/include/sysmetrics.h
@@ -4,8 +4,8 @@
  * Copyright 1994 Alexandre Julliard
  */
 
-#ifndef SYSMETRICS_H
-#define SYSMETRICS_H
+#ifndef __WINE_SYSMETRICS_H
+#define __WINE_SYSMETRICS_H
 
 #include "windows.h"
 
@@ -77,4 +77,4 @@
 extern void SYSMETRICS_Init(void);
 extern short sysMetrics[SM_CMETRICS+1];
 
-#endif
+#endif  /* __WINE_SYSMETRICS_H */
diff --git a/include/task.h b/include/task.h
index df65c60..70f79bc 100644
--- a/include/task.h
+++ b/include/task.h
@@ -4,8 +4,8 @@
  * Copyright 1995 Alexandre Julliard
  */
 
-#ifndef _WINE_TASK_H
-#define _WINE_TASK_H
+#ifndef __WINE_TASK_H
+#define __WINE_TASK_H
 
 #include "wintypes.h"
 
@@ -28,7 +28,8 @@
     WORD      reserved2[2];
     WORD      nbFiles;                 /* 32 Number of file handles */
     SEGPTR    fileHandlesPtr;          /* 34 Pointer to file handle table */
-    WORD      reserved3[18];
+    HANDLE16  hFileHandles;            /* 38 Handle to fileHandlesPtr */
+    WORD      reserved3[17];
     BYTE      fcb1[16];                /* 5c First FCB */
     BYTE      fcb2[20];                /* 6c Second FCB */
     BYTE      cmdLine[128];            /* 80 Command-line (first byte is len)*/
@@ -117,4 +118,4 @@
 extern void TASK_KillCurrentTask( INT16 exitCode );
 extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
 
-#endif /* _WINE_TASK_H */
+#endif /* __WINE_TASK_H */
diff --git a/include/toolhelp.h b/include/toolhelp.h
index c1d9836..dbebe81 100644
--- a/include/toolhelp.h
+++ b/include/toolhelp.h
@@ -1,5 +1,5 @@
-#ifndef __TOOLHELP_H
-#define __TOOLHELP_H
+#ifndef __WINE_TOOLHELP_H
+#define __WINE_TOOLHELP_H
 
 #include "windows.h"
 
@@ -343,4 +343,4 @@
     FARPROC16   lpfnErrorAddr;
     void      **lpBadParam;
 } NFYLOGPARAMERROR;
-#endif /* __TOOLHELP_H */
+#endif /* __WINE_TOOLHELP_H */
diff --git a/include/user.h b/include/user.h
index f22fa1a..cfb068b 100644
--- a/include/user.h
+++ b/include/user.h
@@ -4,8 +4,8 @@
  * Copyright 1993 Alexandre Julliard
  */
 
-#ifndef USER_H
-#define USER_H
+#ifndef __WINE_USER_H
+#define __WINE_USER_H
 
 #include "ldt.h"
 #include "local.h"
@@ -23,4 +23,4 @@
 #define USER_HEAP_SEG_ADDR(handle)  \
          ((handle) ? PTR_SEG_OFF_TO_SEGPTR(USER_HeapSel, (handle)) : (SEGPTR)0)
 
-#endif  /* USER_H */
+#endif  /* __WINE_USER_H */
diff --git a/include/win.h b/include/win.h
index 445ee3b..b8b778a 100644
--- a/include/win.h
+++ b/include/win.h
@@ -4,8 +4,8 @@
  * Copyright 1993 Alexandre Julliard
  */
 
-#ifndef WIN_H
-#define WIN_H
+#ifndef __WINE_WIN_H
+#define __WINE_WIN_H
 
 #include <X11/Xlib.h>
 
@@ -111,4 +111,4 @@
 extern Screen * screen;
 extern Window rootWindow;
 
-#endif  /* WIN_H */
+#endif  /* __WINE_WIN_H */
diff --git a/include/windows.h b/include/windows.h
index e0d8cd4..a65782d 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -2614,10 +2614,10 @@
 #define HWND_BROADCAST	    ((HWND)0xffff)
 
 /* SetWindowPos() hwndInsertAfter field values */
-#define HWND_TOP            ((HWND)0)
-#define HWND_BOTTOM         ((HWND)1)
-#define HWND_TOPMOST        ((HWND)-1)
-#define HWND_NOTOPMOST      ((HWND)-2)
+#define HWND_TOP            ((HWND32)0)
+#define HWND_BOTTOM         ((HWND32)1)
+#define HWND_TOPMOST        ((HWND32)-1)
+#define HWND_NOTOPMOST      ((HWND32)-2)
 
 /* Flags for TrackPopupMenu */
 #define TPM_LEFTBUTTON    0x0000
@@ -3279,52 +3279,137 @@
 #define ODS_FOCUS       0x0010
 
 /* Edit control styles */
-#define ES_LEFT         0x00000000L
-#define ES_CENTER       0x00000001L
-#define ES_RIGHT        0x00000002L
-#define ES_MULTILINE    0x00000004L
-#define ES_UPPERCASE    0x00000008L
-#define ES_LOWERCASE    0x00000010L
-#define ES_PASSWORD     0x00000020L
-#define ES_AUTOVSCROLL  0x00000040L
-#define ES_AUTOHSCROLL  0x00000080L
-#define ES_NOHIDESEL    0x00000100L
-#define ES_OEMCONVERT   0x00000400L
-#define ES_READONLY     0x00000800L
-#define ES_WANTRETURN   0x00001000L
+#define ES_LEFT         0x00000000
+#define ES_CENTER       0x00000001
+#define ES_RIGHT        0x00000002
+#define ES_MULTILINE    0x00000004
+#define ES_UPPERCASE    0x00000008
+#define ES_LOWERCASE    0x00000010
+#define ES_PASSWORD     0x00000020
+#define ES_AUTOVSCROLL  0x00000040
+#define ES_AUTOHSCROLL  0x00000080
+#define ES_NOHIDESEL    0x00000100
+#define ES_OEMCONVERT   0x00000400
+#define ES_READONLY     0x00000800
+#define ES_WANTRETURN   0x00001000
+#define ES_NUMBER       0x00002000
 
 /* Edit control messages */
-#define EM_GETSEL              (WM_USER+0)
-#define EM_SETSEL              (WM_USER+1)
-#define EM_GETRECT             (WM_USER+2)
-#define EM_SETRECT             (WM_USER+3)
-#define EM_SETRECTNP           (WM_USER+4)
-#define EM_LINESCROLL          (WM_USER+6)
-#define EM_GETMODIFY           (WM_USER+8)
-#define EM_SETMODIFY           (WM_USER+9)
-#define EM_GETLINECOUNT        (WM_USER+10)
-#define EM_LINEINDEX           (WM_USER+11)
-#define EM_SETHANDLE           (WM_USER+12)
-#define EM_GETHANDLE           (WM_USER+13)
-#define EM_LINELENGTH          (WM_USER+17)
-#define EM_REPLACESEL          (WM_USER+18)
-#define EM_GETLINE             (WM_USER+20)
-#define EM_LIMITTEXT           (WM_USER+21)
-#define EM_CANUNDO             (WM_USER+22)
-#define EM_UNDO                (WM_USER+23)
-#define EM_FMTLINES            (WM_USER+24)
-#define EM_LINEFROMCHAR        (WM_USER+25)
-#define EM_SETTABSTOPS         (WM_USER+27)
-#define EM_SETPASSWORDCHAR     (WM_USER+28)
-#define EM_EMPTYUNDOBUFFER     (WM_USER+29)
-#define EM_GETFIRSTVISIBLELINE (WM_USER+30)
-#define EM_SETREADONLY         (WM_USER+31)
-#define EM_SETWORDBREAKPROC    (WM_USER+32)
-#define EM_GETWORDBREAKPROC    (WM_USER+33)
-#define EM_GETPASSWORDCHAR     (WM_USER+34)
-/* Edit control undocumented messages */
-#define EM_SCROLL              (WM_USER+5)
-#define EM_GETTHUMB            (WM_USER+14)
+#define EM_GETSEL16                (WM_USER+0)
+#define EM_GETSEL32                0x00b0
+#define EM_GETSEL                  WINELIB_NAME(EM_GETSEL)
+#define EM_SETSEL16                (WM_USER+1)
+#define EM_SETSEL32                0x00b1
+#define EM_SETSEL                  WINELIB_NAME(EM_SETSEL)
+#define EM_GETRECT16               (WM_USER+2)
+#define EM_GETRECT32               0x00b2
+#define EM_GETRECT                 WINELIB_NAME(EM_GETRECT)
+#define EM_SETRECT16               (WM_USER+3)
+#define EM_SETRECT32               0x00b3
+#define EM_SETRECT                 WINELIB_NAME(EM_SETRECT)
+#define EM_SETRECTNP16             (WM_USER+4)
+#define EM_SETRECTNP32             0x00b4
+#define EM_SETRECTNP               WINELIB_NAME(EM_SETRECTNP)
+#define EM_SCROLL16                (WM_USER+5)
+#define EM_SCROLL32                0x00b5
+#define EM_SCROLL                  WINELIB_NAME(EM_SCROLL)
+#define EM_LINESCROLL16            (WM_USER+6)
+#define EM_LINESCROLL32            0x00b6
+#define EM_LINESCROLL              WINELIB_NAME(EM_LINESCROLL)
+#define EM_SCROLLCARET16           (WM_USER+7)
+#define EM_SCROLLCARET32           0x00b7
+#define EM_SCROLLCARET             WINELIB_NAME(EM_SCROLLCARET)
+#define EM_GETMODIFY16             (WM_USER+8)
+#define EM_GETMODIFY32             0x00b8
+#define EM_GETMODIFY               WINELIB_NAME(EM_GETMODIFY)
+#define EM_SETMODIFY16             (WM_USER+9)
+#define EM_SETMODIFY32             0x00b9
+#define EM_SETMODIFY               WINELIB_NAME(EM_SETMODIFY)
+#define EM_GETLINECOUNT16          (WM_USER+10)
+#define EM_GETLINECOUNT32          0x00ba
+#define EM_GETLINECOUNT            WINELIB_NAME(EM_GETLINECOUNT)
+#define EM_LINEINDEX16             (WM_USER+11)
+#define EM_LINEINDEX32             0x00bb
+#define EM_LINEINDEX               WINELIB_NAME(EM_LINEINDEX)
+#define EM_SETHANDLE16             (WM_USER+12)
+#define EM_SETHANDLE32             0x00bc
+#define EM_SETHANDLE               WINELIB_NAME(EM_SETHANDLE)
+#define EM_GETHANDLE16             (WM_USER+13)
+#define EM_GETHANDLE32             0x00bd
+#define EM_GETHANDLE               WINELIB_NAME(EM_GETHANDLE)
+#define EM_GETTHUMB16              (WM_USER+14)
+#define EM_GETTHUMB32              0x00be
+#define EM_GETTHUMB                WINELIB_NAME(EM_GETTHUMB)
+/* FIXME : missing from specs 0x00bf and 0x00c0 */
+#define EM_LINELENGTH16            (WM_USER+17)
+#define EM_LINELENGTH32            0x00c1
+#define EM_LINELENGTH              WINELIB_NAME(EM_LINELENGTH)
+#define EM_REPLACESEL16            (WM_USER+18)
+#define EM_REPLACESEL32            0x00c2
+#define EM_REPLACESEL              WINELIB_NAME(EM_REPLACESEL)
+/* FIXME : missing from specs 0x00c3 */
+#define EM_GETLINE16               (WM_USER+20)
+#define EM_GETLINE32               0x00c4
+#define EM_GETLINE                 WINELIB_NAME(EM_GETLINE)
+#define EM_LIMITTEXT16             (WM_USER+21)
+#define EM_LIMITTEXT32             0x00c5
+#define EM_LIMITTEXT               WINELIB_NAME(EM_LIMITTEXT)
+#define EM_CANUNDO16               (WM_USER+22)
+#define EM_CANUNDO32               0x00c6
+#define EM_CANUNDO                 WINELIB_NAME(EM_CANUNDO)
+#define EM_UNDO16                  (WM_USER+23)
+#define EM_UNDO32                  0x00c7
+#define EM_UNDO                    WINELIB_NAME(EM_UNDO)
+#define EM_FMTLINES16              (WM_USER+24)
+#define EM_FMTLINES32              0x00c8
+#define EM_FMTLINES                WINELIB_NAME(EM_FMTLINES)
+#define EM_LINEFROMCHAR16          (WM_USER+25)
+#define EM_LINEFROMCHAR32          0x00c9
+#define EM_LINEFROMCHAR            WINELIB_NAME(EM_LINEFROMCHAR)
+/* FIXME : missing from specs 0x00ca */
+#define EM_SETTABSTOPS16           (WM_USER+27)
+#define EM_SETTABSTOPS32           0x00cb
+#define EM_SETTABSTOPS             WINELIB_NAME(EM_SETTABSTOPS)
+#define EM_SETPASSWORDCHAR16       (WM_USER+28)
+#define EM_SETPASSWORDCHAR32       0x00cc
+#define EM_SETPASSWORDCHAR         WINELIB_NAME(EM_SETPASSWORDCHAR)
+#define EM_EMPTYUNDOBUFFER16       (WM_USER+29)
+#define EM_EMPTYUNDOBUFFER32       0x00cd
+#define EM_EMPTYUNDOBUFFER         WINELIB_NAME(EM_EMPTYUNDOBUFFER)
+#define EM_GETFIRSTVISIBLELINE16   (WM_USER+30)
+#define EM_GETFIRSTVISIBLELINE32   0x00ce
+#define EM_GETFIRSTVISIBLELINE     WINELIB_NAME(EM_GETFIRSTVISIBLELINE)
+#define EM_SETREADONLY16           (WM_USER+31)
+#define EM_SETREADONLY32           0x00cf
+#define EM_SETREADONLY             WINELIB_NAME(EM_SETREADONLY)
+#define EM_SETWORDBREAKPROC16      (WM_USER+32)
+#define EM_SETWORDBREAKPROC32      0x00d0
+#define EM_SETWORDBREAKPROC        WINELIB_NAME(EM_SETWORDBREAKPROC)
+#define EM_GETWORDBREAKPROC16      (WM_USER+33)
+#define EM_GETWORDBREAKPROC32      0x00d1
+#define EM_GETWORDBREAKPROC        WINELIB_NAME(EM_GETWORDBREAKPROC)
+#define EM_GETPASSWORDCHAR16       (WM_USER+34)
+#define EM_GETPASSWORDCHAR32       0x00d2
+#define EM_GETPASSWORDCHAR         WINELIB_NAME(EM_GETPASSWORDCHAR)
+#define EM_SETMARGINS16            WM_NULL /* not in win16 */
+#define EM_SETMARGINS32            0x00d3
+#define EM_SETMARGINS              WINELIB_NAME(EM_SETMARGINS)
+#define EM_GETMARGINS16            WM_NULL /* not in win16 */
+#define EM_GETMARGINS32            0x00d4
+#define EM_GETMARGINS              WINELIB_NAME(EM_GETMARGINS)
+#define EM_GETLIMITTEXT16          WM_NULL /* not in win16 */
+#define EM_GETLIMITTEXT32          0x00d5
+#define EM_GETLIMITTEXT            WINELIB_NAME(EM_GETLIMITTEXT)
+#define EM_POSFROMCHAR16           WM_NULL /* not in win16 */
+#define EM_POSFROMCHAR32           0x00d6
+#define EM_POSFROMCHAR             WINELIB_NAME(EM_POSFROMCHAR)
+#define EM_CHARFROMPOS16           WM_NULL /* not in win16 */
+#define EM_CHARFROMPOS32           0x00d7
+#define EM_CHARFROMPOS             WINELIB_NAME(EM_CHARFROMPOS)
+/* a name change since win95 */
+#define EM_SETLIMITTEXT16          WM_NULL /* no name change in win16 */
+#define EM_SETLIMITTEXT32          EM_LIMITTEXT32
+#define EM_SETLIMITTEXT            WINELIB_NAME(EM_SETLIMITTEXT)
 
 /* EDITWORDBREAKPROC code values */
 #define WB_LEFT         0
@@ -3341,6 +3426,11 @@
 #define EN_HSCROLL      0x0601
 #define EN_VSCROLL      0x0602
 
+/* New since win95 : EM_SETMARGIN parameters */
+#define EC_LEFTMARGIN	0x0001
+#define EC_RIGHTMARGIN	0x0002
+#define EC_USEFONTINFO	0xffff
+
 
 typedef struct
 {
@@ -4353,6 +4443,12 @@
 	LPWSTR	Buffer;
 } UNICODE_STRING,*LPUNICODE_STRING;
 
+/* {G,S}etPriorityClass */
+#define	NORMAL_PRIORITY_CLASS	0x00000020
+#define	IDLE_PRIORITY_CLASS	0x00000040
+#define	HIGH_PRIORITY_CLASS	0x00000080
+#define	REALTIME_PRIORITY_CLASS	0x00000100
+
 #pragma pack(4)
 
 /* Declarations for functions that exist only in Win16 */
@@ -4361,8 +4457,6 @@
 WORD       AllocDStoCSAlias(WORD);
 WORD       AllocSelector(WORD);
 WORD       AllocSelectorArray(WORD);
-LPSTR      AnsiLower(LPSTR);
-LPSTR      AnsiUpper(LPSTR);
 INT16      Catch(LPCATCHBUF);
 WORD       ChangeSelector(WORD,WORD);
 INT16      CloseComm(INT16);
@@ -4425,6 +4519,7 @@
 HTASK16    IsTaskLocked(void);
 BOOL16     LocalInit(HANDLE16,WORD,WORD);
 HTASK16    LockCurrentTask(BOOL16);
+HMENU16    LookupMenuHandle(HMENU16,INT16);
 DWORD      MoveTo(HDC16,INT16,INT16);
 DWORD      OffsetViewportOrg(HDC16,INT16,INT16);
 INT16      OffsetVisRgn(HDC16,INT16,INT16);
@@ -4474,6 +4569,9 @@
 BOOL32     Beep(DWORD,DWORD);
 BOOL32     ClearCommError(INT32,LPDWORD,LPCOMSTAT);
 BOOL32     CloseHandle(HANDLE32);
+BOOL32     CopyFile32A(LPCSTR,LPCSTR,BOOL32);
+BOOL32     CopyFile32W(LPCWSTR,LPCWSTR,BOOL32);
+#define    CopyFile WINELIB_NAME_AW(CopyFile)
 HFILE32    CreateFile32A(LPCSTR,DWORD,DWORD,LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE32);
 HFILE32    CreateFile32W(LPCWSTR,DWORD,DWORD,LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE32);
 #define    CreateFile WINELIB_NAME_AW(CreateFile)
@@ -4500,6 +4598,9 @@
 HRSRC32    FindResourceEx32W(HINSTANCE32,LPCWSTR,LPCWSTR,WORD);
 #define    FindResourceEx WINELIB_NAME_AW(FindResourceEx)
 BOOL32     FlushFileBuffers(HFILE32);
+BOOL32     FreeEnvironmentStrings32A(LPSTR);
+BOOL32     FreeEnvironmentStrings32W(LPWSTR);
+#define    FreeEnvironmentStrings WINELIB_NAME_AW(FreeEnvironmentStrings)
 UINT32     GetACP(void);
 LPCSTR     GetCommandLine32A();
 LPCWSTR    GetCommandLine32W();
@@ -4511,13 +4612,23 @@
 HANDLE32   GetCurrentThread(void);
 DWORD      GetCurrentThreadId(void);
 BOOL32     GetDCOrgEx(HDC32,LPPOINT32);
+LPSTR      GetEnvironmentStrings32A(void);
+LPWSTR     GetEnvironmentStrings32W(void);
+#define    GetEnvironmentStrings WINELIB_NAME_AW(GetEnvironmentStrings)
+DWORD      GetEnvironmentVariable32A(LPCSTR,LPSTR,DWORD);
+DWORD      GetEnvironmentVariable32W(LPCWSTR,LPWSTR,DWORD);
+#define    GetEnvironmentVariable WINELIB_NAME_AW(GetEnvironmentVariable)
 DWORD      GetFileInformationByHandle(HFILE32,BY_HANDLE_FILE_INFORMATION*);
 DWORD      GetFileSize(HFILE32,LPDWORD);
 BOOL32     GetFileTime(HFILE32,LPFILETIME,LPFILETIME,LPFILETIME);
 DWORD      GetFileType(HFILE32);
+DWORD      GetFullPathName32A(LPCSTR,DWORD,LPSTR,LPSTR*);
+DWORD      GetFullPathName32W(LPCWSTR,DWORD,LPWSTR,LPWSTR*);
+#define    GetFullPathName WINELIB_NAME_AW(GetFullPathName)
 VOID       GetLocalTime(LPSYSTEMTIME);
 DWORD      GetLogicalDrives(void);
 UINT32     GetOEMCP(void);
+DWORD      GetPriorityClass(HANDLE32);
 HANDLE32   GetProcessHeap(void);
 DWORD      GetShortPathName32A(LPCSTR,LPSTR,DWORD);
 DWORD      GetShortPathName32W(LPCWSTR,LPWSTR,DWORD);
@@ -4526,6 +4637,8 @@
 VOID       GetSystemInfo(LPSYSTEM_INFO);
 BOOL32     GetSystemPowerStatus(LPSYSTEM_POWER_STATUS);
 VOID       GetSystemTime(LPSYSTEMTIME);
+LCID       GetThreadLocale();
+INT32      GetThreadPriority(HANDLE32);
 VOID       GlobalMemoryStatus(LPMEMORYSTATUS);
 LPVOID     HeapAlloc(HANDLE32,DWORD,DWORD);
 DWORD      HeapCompact(HANDLE32,DWORD);
@@ -4537,6 +4650,7 @@
 DWORD      HeapSize(HANDLE32,DWORD,LPVOID);
 BOOL32     HeapUnlock(HANDLE32);
 BOOL32     HeapValidate(HANDLE32,DWORD,LPVOID);
+BOOL32     IsDBCSLeadByteEx(UINT32,BYTE);
 BOOL32     IsWindowUnicode(HWND32);
 BOOL32     IsValidLocale(DWORD,DWORD);
 BOOL32     LocalFileTimeToFileTime(const FILETIME*,LPFILETIME);
@@ -4544,6 +4658,9 @@
 BOOL32     MoveFile32A(LPCSTR,LPCSTR);
 BOOL32     MoveFile32W(LPCWSTR,LPCWSTR);
 #define    MoveFile WINELIB_NAME_AW(MoveFile)
+DWORD      QueryDosDevice32A(LPCSTR,LPSTR,DWORD);
+DWORD      QueryDosDevice32W(LPCWSTR,LPWSTR,DWORD);
+#define    QueryDosDevice WINELIB_NAME_AW(QueryDosDevice)
 BOOL32     QueryPerformanceCounter(LPLARGE_INTEGER);
 BOOL32     ReadConsole32A(HANDLE32,LPVOID,DWORD,LPDWORD,LPVOID);
 BOOL32     ReadConsole32W(HANDLE32,LPVOID,DWORD,LPDWORD,LPVOID);
@@ -4578,12 +4695,18 @@
 BOOL32     SetConsoleTitle32W(LPCWSTR);
 #define    SetConsoleTitle WINELIB_NAME_AW(SetConsoleTitle)
 BOOL32     SetEndOfFile(HFILE32);
+BOOL32     SetEnvironmentVariable32A(LPCSTR,LPCSTR);
+BOOL32     SetEnvironmentVariable32W(LPCWSTR,LPCWSTR);
+#define    SetEnvironmentVariable WINELIB_NAME_AW(SetEnvironmentVariable)
 DWORD      SetFilePointer(HFILE32,LONG,LPLONG,DWORD);
 BOOL32     SetFileTime(HFILE32,const FILETIME*,const FILETIME*,const FILETIME*);
 VOID       SetLastErrorEx(DWORD,DWORD);
-BOOL32     SetTimeZoneInformation(const LPTIME_ZONE_INFORMATION);
+BOOL32     SetPriorityClass(HANDLE32,DWORD);
+BOOL32     SetStdHandle(DWORD,HANDLE32);
 BOOL32     SetSystemPowerState(BOOL32,BOOL32);
 BOOL32     SetSystemTime(const SYSTEMTIME*);
+BOOL32     SetThreadPriority(HANDLE32,INT32);
+BOOL32     SetTimeZoneInformation(const LPTIME_ZONE_INFORMATION);
 VOID       Sleep(DWORD);
 BOOL32     SystemTimeToFileTime(const SYSTEMTIME*,LPFILETIME);
 BOOL32     TrackPopupMenuEx(HMENU32,UINT32,INT32,INT32,HWND32,LPTPMPARAMS);
@@ -4613,8 +4736,10 @@
 DWORD      GetAppCompatFlags(HTASK32);
 LONG       GetBitmapBits(HBITMAP32,LONG,LPVOID);
 WORD       GetClassWord(HWND32,INT32);
+DWORD      GetDialogBaseUnits(void);
 INT16      GetDlgCtrlID(HWND32);
 DWORD      GetLastError(void);
+DWORD      GetMenuCheckMarkDimensions(void);
 COLORREF   GetSysColor(INT32);
 DWORD      GetTickCount(void);
 INT16      GetUpdateRgn(HWND32,HRGN32,BOOL32);
@@ -4652,6 +4777,22 @@
 HGLOBAL16  AllocResource16(HINSTANCE16,HRSRC16,DWORD);
 HGLOBAL32  AllocResource32(HINSTANCE32,HRSRC32,DWORD);
 #define    AllocResource WINELIB_NAME(AllocResource)
+SEGPTR     AnsiLower16(SEGPTR);
+#define    AnsiLower32A CharLower32A
+#define    AnsiLower32W CharLower32W
+#define    AnsiLower WINELIB_NAME_AW(AnsiLower)
+UINT16     AnsiLowerBuff16(LPSTR,UINT16);
+#define    AnsiLowerBuff32A CharLowerBuff32A
+#define    AnsiLowerBuff32W CharLowerBuff32W
+#define    AnsiLowerBuff WINELIB_NAME_AW(AnsiLowerBuff)
+SEGPTR     AnsiNext16(SEGPTR);
+#define    AnsiNext32A CharNext32A
+#define    AnsiNext32W CharNext32W
+#define    AnsiNext WINELIB_NAME_AW(AnsiNext)
+SEGPTR     AnsiPrev16(SEGPTR,SEGPTR);
+#define    AnsiPrev32A CharPrev32A
+#define    AnsiPrev32W CharPrev32W
+#define    AnsiPrev WINELIB_NAME_AW(AnsiPrev)
 INT16      AnsiToOem16(LPCSTR,LPSTR);
 #define    AnsiToOem32A CharToOem32A
 #define    AnsiToOem32W CharToOem32W
@@ -4660,6 +4801,14 @@
 #define    AnsiToOemBuff32A CharToOemBuff32A
 #define    AnsiToOemBuff32W CharToOemBuff32W
 #define    AnsiToOemBuff WINELIB_NAME_AW(AnsiToOemBuff)
+SEGPTR     AnsiUpper16(SEGPTR);
+#define    AnsiUpper32A CharUpper32A
+#define    AnsiUpper32W CharUpper32W
+#define    AnsiUpper WINELIB_NAME_AW(AnsiUpper)
+UINT16     AnsiUpperBuff16(LPSTR,UINT16);
+#define    AnsiUpperBuff32A CharUpperBuff32A
+#define    AnsiUpperBuff32W CharUpperBuff32W
+#define    AnsiUpperBuff WINELIB_NAME_AW(AnsiUpperBuff)
 BOOL16     AppendMenu16(HMENU16,UINT16,UINT16,SEGPTR);
 BOOL32     AppendMenu32A(HMENU32,UINT32,UINT32,LPCSTR);
 BOOL32     AppendMenu32W(HMENU32,UINT32,UINT32,LPCWSTR);
@@ -4687,6 +4836,9 @@
 LRESULT    CallWindowProc32A(WNDPROC32,HWND32,UINT32,WPARAM32,LPARAM);
 LRESULT    CallWindowProc32W(WNDPROC32,HWND32,UINT32,WPARAM32,LPARAM);
 #define    CallWindowProc WINELIB_NAME_AW(CallWindowProc)
+BOOL16     ChangeClipboardChain16(HWND16,HWND16);
+BOOL32     ChangeClipboardChain32(HWND32,HWND32);
+#define    ChangeClipboardChain WINELIB_NAME(ChangeClipboardChain)
 BOOL16     ChangeMenu16(HMENU16,UINT16,SEGPTR,UINT16,UINT16);
 BOOL32     ChangeMenu32A(HMENU32,UINT32,LPCSTR,UINT32,UINT32);
 BOOL32     ChangeMenu32W(HMENU32,UINT32,LPCWSTR,UINT32,UINT32);
@@ -4721,6 +4873,9 @@
 BOOL32     CharToOemBuff32A(LPCSTR,LPSTR,DWORD);
 BOOL32     CharToOemBuff32W(LPCWSTR,LPSTR,DWORD);
 #define    CharToOemBuff WINELIB_NAME_AW(CharToOemBuff)
+BOOL16     CheckMenuItem16(HMENU16,UINT16,UINT16);
+DWORD      CheckMenuItem32(HMENU32,UINT32,UINT32);
+#define    CheckMenuItem WINELIB_NAME(CheckMenuItem)
 HWND16     ChildWindowFromPoint16(HWND16,POINT16);
 HWND32     ChildWindowFromPoint32(HWND32,POINT32);
 #define    ChildWindowFromPoint WINELIB_NAME(ChildWindowFromPoint)
@@ -4827,6 +4982,9 @@
 HDC32      CreateIC32A(LPCSTR,LPCSTR,LPCSTR,const DEVMODE32A*);
 HDC32      CreateIC32W(LPCWSTR,LPCWSTR,LPCWSTR,const DEVMODE32W*);
 #define    CreateIC WINELIB_NAME_AW(CreateIC)
+HMENU16    CreateMenu16(void);
+HMENU32    CreateMenu32(void);
+#define    CreateMenu WINELIB_NAME(CreateMenu)
 HDC16      CreateMetaFile16(LPCSTR);
 HDC32      CreateMetaFile32A(LPCSTR);
 HDC32      CreateMetaFile32W(LPCWSTR);
@@ -4846,6 +5004,9 @@
 HRGN16     CreatePolygonRgn16(const POINT16*,INT16,INT16);
 HRGN32     CreatePolygonRgn32(const POINT32*,INT32,INT32);
 #define    CreatePolygonRgn WINELIB_NAME(CreatePolygonRgn)
+HMENU16    CreatePopupMenu16(void);
+HMENU32    CreatePopupMenu32(void);
+#define    CreatePopupMenu WINELIB_NAME(CreatePopupMenu)
 HRGN16     CreateRectRgn16(INT16,INT16,INT16,INT16);
 HRGN32     CreateRectRgn32(INT32,INT32,INT32,INT32);
 #define    CreateRectRgn WINELIB_NAME(CreateRectRgn)
@@ -4899,12 +5060,18 @@
 BOOL32     DeleteFile32A(LPCSTR);
 BOOL32     DeleteFile32W(LPCWSTR);
 #define    DeleteFile WINELIB_NAME_AW(DeleteFile)
+BOOL16     DeleteMenu16(HMENU16,UINT16,UINT16);
+BOOL32     DeleteMenu32(HMENU32,UINT32,UINT32);
+#define    DeleteMenu WINELIB_NAME(DeleteMenu)
 BOOL16     DeleteMetaFile16(HMETAFILE16);
 BOOL32     DeleteMetaFile32(HMETAFILE32);
 #define    DeleteMetaFile WINELIB_NAME(DeleteMetaFile)
 BOOL16     DeleteObject16(HGDIOBJ16);
 BOOL32     DeleteObject32(HGDIOBJ32);
 #define    DeleteObject WINELIB_NAME(DeleteObject)
+BOOL16     DestroyMenu16(HMENU16);
+BOOL32     DestroyMenu32(HMENU32);
+#define    DestroyMenu WINELIB_NAME(DestroyMenu)
 INT16      DialogBox16(HINSTANCE16,SEGPTR,HWND16,DLGPROC16);
 #define    DialogBox32A(inst,template,owner,func) \
            DialogBoxParam32A(inst,template,owner,func,0)
@@ -4953,6 +5120,9 @@
 BOOL16     DrawFrameControl16(HDC16,LPRECT16,UINT16,UINT16);
 BOOL32     DrawFrameControl32(HDC32,LPRECT32,UINT32,UINT32);
 #define    DrawFrameControl WINELIB_NAME(DrawFrameControl)
+VOID       DrawMenuBar16(HWND16);
+BOOL32     DrawMenuBar32(HWND32);
+#define    DrawMenuBar WINELIB_NAME(DrawMenuBar)
 INT16      DrawText16(HDC16,LPCSTR,INT16,LPRECT16,UINT16);
 INT32      DrawText32A(HDC32,LPCSTR,INT32,LPRECT32,UINT32);
 INT32      DrawText32W(HDC32,LPCWSTR,INT32,LPRECT32,UINT32);
@@ -4960,6 +5130,9 @@
 BOOL16     Ellipse16(HDC16,INT16,INT16,INT16,INT16);
 BOOL32     Ellipse32(HDC32,INT32,INT32,INT32,INT32);
 #define    Ellipse WINELIB_NAME(Ellipse)
+BOOL16     EnableMenuItem16(HMENU16,UINT16,UINT16);
+BOOL32     EnableMenuItem32(HMENU32,UINT32,UINT32);
+#define    EnableMenuItem WINELIB_NAME(EnableMenuItem)
 BOOL16     EnableScrollBar16(HWND16,INT16,UINT16);
 BOOL32     EnableScrollBar32(HWND32,INT32,UINT32);
 #define    EnableScrollBar WINELIB_NAME(EnableScrollBar)
@@ -5194,6 +5367,22 @@
 INT16      GetMapMode16(HDC16);
 INT32      GetMapMode32(HDC32);
 #define    GetMapMode WINELIB_NAME(GetMapMode)
+HMENU16    GetMenu16(HWND16);
+HMENU32    GetMenu32(HWND32);
+#define    GetMenu WINELIB_NAME(GetMenu)
+INT16      GetMenuItemCount16(HMENU16);
+INT32      GetMenuItemCount32(HMENU32);
+#define    GetMenuItemCount WINELIB_NAME(GetMenuItemCount)
+UINT16     GetMenuItemID16(HMENU16,INT16);
+UINT32     GetMenuItemID32(HMENU32,INT32);
+#define    GetMenuItemID WINELIB_NAME(GetMenuItemID)
+UINT16     GetMenuState16(HMENU16,UINT16,UINT16);
+UINT32     GetMenuState32(HMENU32,UINT32,UINT32);
+#define    GetMenuState WINELIB_NAME(GetMenuState)
+INT16      GetMenuString16(HMENU16,UINT16,LPSTR,INT16,UINT16);
+INT32      GetMenuString32A(HMENU32,UINT32,LPSTR,INT32,UINT32);
+INT32      GetMenuString32W(HMENU32,UINT32,LPWSTR,INT32,UINT32);
+#define    GetMenuString WINELIB_NAME_AW(GetMenuString)
 INT16      GetModuleFileName16(HINSTANCE16,LPSTR,INT16);
 DWORD      GetModuleFileName32A(HMODULE32,LPSTR,DWORD);
 DWORD      GetModuleFileName32W(HMODULE32,LPWSTR,DWORD);
@@ -5264,6 +5453,9 @@
 INT16      GetStretchBltMode16(HDC16);
 INT32      GetStretchBltMode32(HDC32);
 #define    GetStretchBltMode WINELIB_NAME(GetStretchBltMode)
+HMENU16    GetSubMenu16(HMENU16,INT16);
+HMENU32    GetSubMenu32(HMENU32,INT32);
+#define    GetSubMenu WINELIB_NAME(GetSubMenu)
 HBRUSH16   GetSysColorBrush16(INT16);
 HBRUSH32   GetSysColorBrush32(INT32);
 #define    GetSysColorBrush WINELIB_NAME(GetSysColorBrush)
@@ -5274,6 +5466,9 @@
 UINT32     GetSystemDirectory32A(LPSTR,UINT32);
 UINT32     GetSystemDirectory32W(LPWSTR,UINT32);
 #define    GetSystemDirectory WINELIB_NAME_AW(GetSystemDirectory)
+HMENU16    GetSystemMenu16(HWND16,BOOL16);
+HMENU32    GetSystemMenu32(HWND32,BOOL32);
+#define    GetSystemMenu WINELIB_NAME(GetSystemMenu)
 UINT16     GetTempFileName16(BYTE,LPCSTR,UINT16,LPSTR);
 UINT32     GetTempFileName32A(LPCSTR,LPCSTR,UINT32,LPSTR);
 UINT32     GetTempFileName32W(LPCWSTR,LPCWSTR,UINT32,LPWSTR);
@@ -5390,6 +5585,9 @@
 BOOL16     GlobalUnlock16(HGLOBAL16);
 BOOL32     GlobalUnlock32(HGLOBAL32);
 #define    GlobalUnlock WINELIB_NAME(GlobalUnlock)
+BOOL16     HiliteMenuItem16(HWND16,HMENU16,UINT16,UINT16);
+BOOL32     HiliteMenuItem32(HWND32,HMENU32,UINT32,UINT32);
+#define    HiliteMenuItem WINELIB_NAME(HiliteMenuItem)
 void       InflateRect16(LPRECT16,INT16,INT16);
 void       InflateRect32(LPRECT32,INT32,INT32);
 #define    InflateRect WINELIB_NAME(InflateRect)
@@ -5450,6 +5648,12 @@
 BOOL32     IsCharUpper32A(CHAR);
 BOOL32     IsCharUpper32W(WCHAR);
 #define    IsCharUpper WINELIB_NAME_AW(IsCharUpper)
+BOOL16     IsDBCSLeadByte16(BYTE);
+BOOL32     IsDBCSLeadByte32(BYTE);
+#define    IsDBCSLeadByte WINELIB_NAME(IsDBCSLeadByte)
+BOOL16     IsMenu16(HMENU16);
+BOOL32     IsMenu32(HMENU32);
+#define    IsMenu WINELIB_NAME(IsMenu)
 BOOL16     IsRectEmpty16(const RECT16*);
 BOOL32     IsRectEmpty32(const RECT32*);
 #define    IsRectEmpty WINELIB_NAME(IsRectEmpty)
@@ -5732,6 +5936,9 @@
 BOOL32     RemoveDirectory32A(LPCSTR);
 BOOL32     RemoveDirectory32W(LPCWSTR);
 #define    RemoveDirectory WINELIB_NAME_AW(RemoveDirectory)
+BOOL16     RemoveMenu16(HMENU16,UINT16,UINT16);
+BOOL32     RemoveMenu32(HMENU32,UINT32,UINT32);
+#define    RemoveMenu WINELIB_NAME(RemoveMenu)
 HDC16      ResetDC16(HDC16,const DEVMODE16 *);
 HDC32      ResetDC32A(HDC32,const DEVMODE32A *);
 HDC32      ResetDC32W(HDC32,const DEVMODE32W *);
@@ -5818,9 +6025,6 @@
 void       SetDlgItemText32A(HWND32,INT32,LPCSTR);
 void       SetDlgItemText32W(HWND32,INT32,LPCWSTR);
 #define    SetDlgItemText WINELIB_NAME_AW(SetDlgItemText)
-BOOL32     SetEnvironmentVariable32A(LPCSTR,LPCSTR);
-BOOL32     SetEnvironmentVariable32W(LPCWSTR,LPCWSTR);
-#define    SetEnvironmentVariable WINELIB_NAME_AW(SetEnvironmentVariable)
 BOOL16     SetFileAttributes16(LPCSTR,DWORD);
 BOOL32     SetFileAttributes32A(LPCSTR,DWORD);
 BOOL32     SetFileAttributes32W(LPCWSTR,DWORD);
@@ -5837,6 +6041,12 @@
 INT16      SetMapMode16(HDC16,INT16);
 INT32      SetMapMode32(HDC32,INT32);
 #define    SetMapMode WINELIB_NAME(SetMapMode)
+BOOL16     SetMenu16(HWND16,HMENU16);
+BOOL32     SetMenu32(HWND32,HMENU32);
+#define    SetMenu WINELIB_NAME(SetMenu)
+BOOL16     SetMenuItemBitmaps16(HMENU16,UINT16,UINT16,HBITMAP16,HBITMAP16);
+BOOL32     SetMenuItemBitmaps32(HMENU32,UINT32,UINT32,HBITMAP32,HBITMAP32);
+#define    SetMenuItemBitmaps WINELIB_NAME(SetMenuItemBitmaps)
 COLORREF   SetPixel16(HDC16,INT16,INT16,COLORREF);
 COLORREF   SetPixel32(HDC32,INT32,INT32,COLORREF);
 #define    SetPixel WINELIB_NAME(SetPixel)
@@ -5877,6 +6087,9 @@
 UINT16     SetSystemTimer16(HWND16,UINT16,UINT16,TIMERPROC16);
 UINT32     SetSystemTimer32(HWND32,UINT32,UINT32,TIMERPROC32);
 #define    SetSystemTimer WINELIB_NAME(SetSystemTimer)
+BOOL16     SetSystemMenu16(HWND16,HMENU16);
+BOOL32     SetSystemMenu32(HWND32,HMENU32);
+#define    SetSystemMenu WINELIB_NAME(SetSystemMenu)
 UINT16     SetTextAlign16(HDC16,UINT16);
 UINT32     SetTextAlign32(HDC32,UINT32);
 #define    SetTextAlign WINELIB_NAME(SetTextAlign)
@@ -6131,18 +6344,12 @@
 ATOM       AddAtom(SEGPTR);
 INT        AddFontResource(LPCSTR);
 BOOL       AnimatePalette(HPALETTE16,UINT,UINT,LPPALETTEENTRY);
-UINT       AnsiLowerBuff(LPSTR,UINT);
-SEGPTR     AnsiNext(SEGPTR);
-SEGPTR     AnsiPrev(SEGPTR,SEGPTR);
-UINT       AnsiUpperBuff(LPSTR,UINT);
 BOOL       AnyPopup(void);
 UINT       ArrangeIconicWindows(HWND);
 HDWP16     BeginDeferWindowPos(INT);
 BOOL       BringWindowToTop(HWND);
 void       CalcChildScroll(HWND,WORD);
 BOOL       CallMsgFilter(SEGPTR,INT);
-BOOL       ChangeClipboardChain(HWND,HWND);
-INT        CheckMenuItem(HMENU16,UINT,UINT);
 BOOL       CloseClipboard(void);
 void       CloseSound(void);
 BOOL       CloseWindow(HWND);
@@ -6153,24 +6360,18 @@
 HCURSOR16  CreateCursor(HINSTANCE16,INT,INT,INT,INT,const BYTE*,const BYTE*);
 HGLOBAL16  CreateCursorIconIndirect(HINSTANCE16,CURSORICONINFO*,const BYTE*,const BYTE*);
 HICON16    CreateIcon(HINSTANCE16,INT,INT,BYTE,BYTE,const BYTE*,const BYTE*);
-HMENU16    CreateMenu(void);
 HPALETTE16 CreatePalette(const LOGPALETTE*);
-HMENU16    CreatePopupMenu(void);
 HDWP16     DeferWindowPos(HDWP16,HWND,HWND,INT,INT,INT,INT,UINT);
 ATOM       DeleteAtom(ATOM);
-BOOL       DeleteMenu(HMENU16,UINT,UINT);
 BOOL       DestroyCursor(HCURSOR16);
 BOOL       DestroyIcon(HICON16);
-BOOL       DestroyMenu(HMENU16);
 BOOL       DestroyWindow(HWND);
 LONG       DispatchMessage(const MSG16*);
 BOOL16     DragDetect(HWND16,POINT16);
 DWORD      DragObject(HWND, HWND, WORD, HANDLE16, WORD, HCURSOR16);
 BOOL       DrawIcon(HDC16,INT,INT,HICON16);
-void       DrawMenuBar(HWND);
 DWORD      DumpIcon(SEGPTR,WORD*,SEGPTR*,SEGPTR*);
 BOOL       EmptyClipboard(void);
-BOOL       EnableMenuItem(HMENU16,UINT,UINT);
 BOOL       EnableWindow(HWND,BOOL);
 BOOL       EndDeferWindowPos(HDWP16);
 UINT16     EnumClipboardFormats(UINT16);
@@ -6197,7 +6398,6 @@
 HCURSOR16  GetCursor(void);
 SEGPTR     GetDOSEnvironment(void);
 int        GetDeviceCaps(HDC16,WORD);
-DWORD      GetDialogBaseUnits(void);
 HWND       GetDlgItem(HWND,WORD);
 WORD       GetDlgItemInt(HWND,WORD,BOOL*,BOOL);
 WORD       GetDoubleClickTime(void);
@@ -6211,12 +6411,6 @@
 void       GetKeyboardState(BYTE*);
 int        GetKeyboardType(int);
 HWND       GetLastActivePopup(HWND);
-HMENU16    GetMenu(HWND);
-DWORD      GetMenuCheckMarkDimensions(void);
-INT        GetMenuItemCount(HMENU16);
-UINT       GetMenuItemID(HMENU16,int);
-UINT       GetMenuState(HMENU16,UINT,UINT);
-int        GetMenuString(HMENU16,UINT,LPSTR,short,UINT);
 BOOL       GetMessage(SEGPTR,HWND,UINT,UINT);
 LONG       GetMessageExtraInfo(void);
 DWORD      GetMessagePos(void);
@@ -6233,8 +6427,6 @@
 int        GetPriorityClipboardFormat(WORD*,short);
 DWORD      GetQueueStatus(UINT);
 BOOL       GetRasterizerCaps(LPRASTERIZER_STATUS,UINT);
-HMENU16    GetSubMenu(HMENU16,short);
-HMENU16    GetSystemMenu(HWND,BOOL);
 int        GetSystemMetrics(WORD);
 WORD       GetSystemPaletteEntries(HDC16,WORD,WORD,LPPALETTEENTRY);
 WORD       GetSystemPaletteUse(HDC16);
@@ -6252,7 +6444,6 @@
 void       GlobalUnfix(HGLOBAL16);
 SEGPTR     GlobalWire(HGLOBAL16);
 BOOL       GrayString(HDC16,HBRUSH16,GRAYSTRINGPROC16,LPARAM,INT,INT,INT,INT,INT);
-BOOL       HiliteMenuItem(HWND,HMENU16,UINT,UINT);
 BOOL       InSendMessage(void);
 WORD       InitAtomTable(WORD);
 BOOL       IsChild(HWND,HWND);
@@ -6260,14 +6451,12 @@
 BOOL       IsDialogMessage(HWND,LPMSG16);
 WORD       IsDlgButtonChecked(HWND,WORD);
 BOOL       IsIconic(HWND);
-BOOL       IsMenu(HMENU16);
 BOOL       IsValidMetaFile(HMETAFILE16);
 BOOL       IsWindowEnabled(HWND);
 BOOL       IsWindowVisible(HWND);
 BOOL       IsZoomed(HWND);
 HINSTANCE16 LoadModule(LPCSTR,LPVOID);
 FARPROC16  LocalNotify(FARPROC16);
-HMENU16    LookupMenuHandle(HMENU16,INT);
 WORD       MapVirtualKey(WORD,WORD);
 void       MessageBeep(WORD);
 BOOL       MoveWindow(HWND,short,short,short,short,BOOL);
@@ -6290,7 +6479,6 @@
 void       ProfStop(void);
 WORD       RealizeDefaultPalette(HDC16);
 BOOL       RemoveFontResource(LPSTR);
-BOOL       RemoveMenu(HMENU16,UINT,UINT);
 void       ReplyMessage(LRESULT);
 BOOL       ResizePalette(HPALETTE16,UINT);
 void       ScrollChildren(HWND,UINT,WPARAM16,LPARAM);
@@ -6309,8 +6497,6 @@
 WORD       SetHookFlags(HDC16,WORD);
 void       SetKeyboardState(BYTE*);
 DWORD      SetMapperFlags(HDC16,DWORD);
-BOOL       SetMenu(HWND,HMENU16);
-BOOL       SetMenuItemBitmaps(HMENU16,UINT,UINT,HBITMAP16,HBITMAP16);
 BOOL       SetMessageQueue(int);
 HMETAFILE16 SetMetaFileBits(HGLOBAL16);
 WORD       SetPaletteEntries(HPALETTE16,WORD,WORD,LPPALETTEENTRY);
diff --git a/include/winerror.h b/include/winerror.h
index c48cc69..6488e5e 100644
--- a/include/winerror.h
+++ b/include/winerror.h
@@ -1,3 +1,7 @@
+#ifndef __WINE_WINERROR_H
+#define __WINE_WINERROR_H
+
+
 extern int WIN32_LastError;
 
 /* ERROR_UNKNOWN is a placeholder for error conditions which haven't
@@ -30,3 +34,5 @@
 #define ERROR_IO_DEVICE             1117
 #define ERROR_POSSIBLE_DEADLOCK     1131
 #define ERROR_BAD_DEVICE            1200
+
+#endif  /* __WINE_WINERROR_H */
diff --git a/include/winnt.h b/include/winnt.h
index 654ec46..55a96a8 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -10,6 +10,7 @@
 #include "wintypes.h"
 
 /* Heap flags */
+
 #define HEAP_NO_SERIALIZE               0x00000001
 #define HEAP_GROWABLE                   0x00000002
 #define HEAP_GENERATE_EXCEPTIONS        0x00000004
@@ -138,4 +139,50 @@
 
 #endif  /* __WINE__ */
 
+/* Language IDs */
+
+#define LANG_NEUTRAL                     0x00
+#define LANG_ARABIC                      0x01
+#define LANG_AFRIKAANS                   0x36
+#define LANG_ALBANIAN                    0x1c
+#define LANG_BASQUE                      0x2d
+#define LANG_BULGARIAN                   0x02
+#define LANG_BYELORUSSIAN                0x23
+#define LANG_CATALAN                     0x03
+#define LANG_CHINESE                     0x04
+#define LANG_CROATIAN                    0x1a
+#define LANG_CZECH                       0x05
+#define LANG_DANISH                      0x06
+#define LANG_DUTCH                       0x13
+#define LANG_ENGLISH                     0x09
+#define LANG_ESTONIAN                    0x25
+#define LANG_FAEROESE                    0x38
+#define LANG_FARSI                       0x29
+#define LANG_FINNISH                     0x0b
+#define LANG_FRENCH                      0x0c
+#define LANG_GERMAN                      0x07
+#define LANG_GREEK                       0x08
+#define LANG_HEBREW                      0x0D
+#define LANG_HUNGARIAN                   0x0e
+#define LANG_ICELANDIC                   0x0f
+#define LANG_INDONESIAN                  0x21
+#define LANG_ITALIAN                     0x10
+#define LANG_JAPANESE                    0x11
+#define LANG_KOREAN                      0x12
+#define LANG_LATVIAN                     0x26
+#define LANG_LITHUANIAN                  0x27
+#define LANG_NORWEGIAN                   0x14
+#define LANG_POLISH                      0x15
+#define LANG_PORTUGUESE                  0x16
+#define LANG_ROMANIAN                    0x18
+#define LANG_RUSSIAN                     0x19
+#define LANG_SLOVAK                      0x1b
+#define LANG_SLOVENIAN                   0x24
+#define LANG_SORBIAN                     0x2e
+#define LANG_SPANISH                     0x0a
+#define LANG_SWEDISH                     0x1d
+#define LANG_THAI                        0x1e
+#define LANG_TURKISH                     0x1f
+#define LANG_UKRAINIAN                   0x22
+
 #endif  /* __WINE_WINNT_H */
diff --git a/include/x11drv.h b/include/x11drv.h
index 0c811a4..9372224 100644
--- a/include/x11drv.h
+++ b/include/x11drv.h
@@ -62,5 +62,38 @@
                                  INT32 widthDst, INT32 heightDst,
                                  struct tagDC *dcSrc, INT32 xSrc, INT32 ySrc,
                                  INT32 widthSrc, INT32 heightSrc, DWORD rop );
+extern BOOL32 X11DRV_MoveToEx( struct tagDC *dc, INT32 x, INT32 y,LPPOINT32 pt);
+extern BOOL32 X11DRV_LineTo( struct tagDC *dc, INT32 x, INT32 y);
+extern BOOL32 X11DRV_Arc( struct tagDC *dc, INT32 left, INT32 top, INT32 right,
+			  INT32 bottom, INT32 xstart, INT32 ystart, INT32 xend,
+			  INT32 yend );
+extern BOOL32 X11DRV_Pie( struct tagDC *dc, INT32 left, INT32 top, INT32 right,
+			  INT32 bottom, INT32 xstart, INT32 ystart, INT32 xend,
+			  INT32 yend );
+extern BOOL32 X11DRV_Chord( struct tagDC *dc, INT32 left, INT32 top,
+			    INT32 right, INT32 bottom, INT32 xstart,
+			    INT32 ystart, INT32 xend, INT32 yend );
+extern BOOL32 X11DRV_Ellipse( struct tagDC *dc, INT32 left, INT32 top,
+			      INT32 right, INT32 bottom );
+extern BOOL32 X11DRV_Rectangle(struct tagDC *dc, INT32 left, INT32 top,
+			      INT32 right, INT32 bottom);
+extern BOOL32 X11DRV_RoundRect( struct tagDC *dc, INT32 left, INT32 top,
+				INT32 right, INT32 bottom, INT32 ell_width,
+				INT32 ell_height );
+extern COLORREF X11DRV_SetPixel( struct tagDC *dc, INT32 x, INT32 y,
+				 COLORREF color );
+extern COLORREF X11DRV_GetPixel( struct tagDC *dc, INT32 x, INT32 y);
+extern BOOL32 X11DRV_PaintRgn( struct tagDC *dc, HRGN32 hrgn );
+extern BOOL32 X11DRV_Polyline( struct tagDC *dc,const LPPOINT32 pt,INT32 count);
+extern BOOL32 X11DRV_Polygon( struct tagDC *dc, LPPOINT32 pt, INT32 count );
+extern BOOL32 X11DRV_PolyPolygon( struct tagDC *dc, LPPOINT32 pt,
+				  LPINT32 counts, UINT32 polygons);
+
+extern BOOL32 X11DRV_ExtFloodFill( struct tagDC *dc, INT32 x, INT32 y,
+				   COLORREF color, UINT32 fillType );
+extern BOOL32 X11DRV_ExtTextOut( struct tagDC *dc, INT32 x, INT32 y,
+				 UINT32 flags, const RECT32 *lprect,
+				 LPCSTR str, UINT32 count, const INT32 *lpDx );
+
 
 #endif  /* __WINE_X11DRV_H */
diff --git a/library/miscstubs.c b/library/miscstubs.c
index e9c377f..8b94554 100644
--- a/library/miscstubs.c
+++ b/library/miscstubs.c
@@ -48,12 +48,10 @@
 extern LRESULT ColorDlgProc(HWND,UINT,WPARAM16,LPARAM);
 extern LRESULT ComboBoxWndProc(HWND,UINT,WPARAM16,LPARAM);
 extern LRESULT ComboLBoxWndProc(HWND,UINT,WPARAM16,LPARAM);
-extern LRESULT EditWndProc(HWND,UINT,WPARAM16,LPARAM);
 extern LRESULT FileOpenDlgProc(HWND,UINT,WPARAM16,LPARAM);
 extern LRESULT FileSaveDlgProc(HWND,UINT,WPARAM16,LPARAM);
 extern LRESULT FindTextDlgProc(HWND,UINT,WPARAM16,LPARAM);
 extern LRESULT MDIClientWndProc(HWND,UINT,WPARAM16,LPARAM);
-extern LRESULT PopupMenuWndProc(HWND,UINT,WPARAM16,LPARAM);
 extern LRESULT PrintDlgProc(HWND,UINT,WPARAM16,LPARAM);
 extern LRESULT PrintSetupDlgProc(HWND,UINT,WPARAM16,LPARAM);
 extern LRESULT ReplaceTextDlgProc(HWND,UINT,WPARAM16,LPARAM);
@@ -72,13 +70,10 @@
   MAP_STR_TO_PROC("ColorDlgProc",ColorDlgProc);
   MAP_STR_TO_PROC("ComboBoxWndProc",ComboBoxWndProc);
   MAP_STR_TO_PROC("ComboLBoxWndProc",ComboLBoxWndProc);
-  MAP_STR_TO_PROC("DefDlgProc",DefDlgProc16);
-  MAP_STR_TO_PROC("EditWndProc",EditWndProc);
   MAP_STR_TO_PROC("FileOpenDlgProc",FileOpenDlgProc);
   MAP_STR_TO_PROC("FileSaveDlgProc",FileSaveDlgProc);
   MAP_STR_TO_PROC("FindTextDlgProc",FindTextDlgProc);
   MAP_STR_TO_PROC("MDIClientWndProc",MDIClientWndProc);
-  MAP_STR_TO_PROC("PopupMenuWndProc",PopupMenuWndProc);
   MAP_STR_TO_PROC("PrintDlgProc",PrintDlgProc);
   MAP_STR_TO_PROC("PrintSetupDlgProc",PrintSetupDlgProc);
   MAP_STR_TO_PROC("ReplaceTextDlgProc",ReplaceTextDlgProc);
diff --git a/loader/module.c b/loader/module.c
index d49c705..e0b9f9d 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -12,7 +12,6 @@
 #include <unistd.h>
 #include "windows.h"
 #include "class.h"
-#include "dos_fs.h"
 #include "file.h"
 #include "global.h"
 #include "heap.h"
@@ -214,8 +213,8 @@
 int MODULE_OpenFile( HMODULE16 hModule )
 {
     NE_MODULE *pModule;
+    DOS_FULL_NAME full_name;
     char *name;
-    const char *unixName;
 
     static int cachedfd = -1;
 
@@ -227,8 +226,8 @@
     close( cachedfd );
     hCachedModule = hModule;
     name = NE_MODULE_NAME( pModule );
-    if (!(unixName = DOSFS_GetUnixFileName( name, TRUE )) ||
-        (cachedfd = open( unixName, O_RDONLY )) == -1)
+    if (!DOSFS_GetFullName( name, TRUE, &full_name ) ||
+        (cachedfd = open( full_name.long_name, O_RDONLY )) == -1)
         fprintf( stderr, "MODULE_OpenFile: can't open file '%s' for module %04x\n",
                  name, hModule );
     dprintf_module( stddeb, "MODULE_OpenFile: opened '%s' -> %d\n",
@@ -701,7 +700,7 @@
       /* Now copy and uppercase the string */
 
     strcpy( buffer, name );
-    AnsiUpper( buffer );
+    CharUpper32A( buffer );
     len = strlen( buffer );
 
       /* First search the resident names */
@@ -1022,6 +1021,7 @@
     WORD *pModRef, *pDLLs;
     HFILE32 hFile;
     int i;
+    extern char * DEBUG_curr_module;
 
     hModule = MODULE_FindModule( name );
 
@@ -1041,6 +1041,12 @@
             return 2;  /* File not found */
         }
 
+	/*
+	 * Record this so that the internal debugger gets some
+	 * record of what it is that we are working with.
+	 */
+	DEBUG_curr_module = name;
+
           /* Create the module structure */
 
         hModule = MODULE_LoadExeHeader( hFile, &ofs );
@@ -1482,7 +1488,8 @@
         if (!fork())
 	{
             /* Child process */
-            const char *unixfilename;
+            DOS_FULL_NAME full_name;
+            const char *unixfilename = NULL;
             const char *argv[256], **argptr;
             int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
                           nCmdShow == SW_SHOWMINNOACTIVE);
@@ -1491,7 +1498,10 @@
             if (strchr(filename, '/') ||
                 strchr(filename, ':') ||
                 strchr(filename, '\\'))
-                unixfilename = DOSFS_GetUnixFileName(filename, 1);
+            {
+                if (DOSFS_GetFullName( filename, TRUE, &full_name ))
+                    unixfilename = full_name.long_name;
+            }
             else unixfilename = filename;
 
             if (unixfilename)
diff --git a/loader/ne_resource.c b/loader/ne_resource.c
index 5da7e3d..cf885e8 100644
--- a/loader/ne_resource.c
+++ b/loader/ne_resource.c
@@ -14,7 +14,6 @@
 #include <unistd.h>
 #include "windows.h"
 #include "arch.h"
-#include "dos_fs.h"
 #include "global.h"
 #include "ldt.h"
 #include "module.h"
diff --git a/loader/pe_image.c b/loader/pe_image.c
index 7f58b4d..73c9ce9 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -87,6 +87,7 @@
   DBG_ADDR	daddr;
 
   daddr.seg = 0;
+  daddr.type = NULL;
   Module = ((char*)load_addr)+pe_exports->Name;
   dprintf_win32(stddeb,"\n*******EXPORT DATA*******\nModule name is %s, %ld functions, %ld names\n", 
 	 Module,
@@ -113,7 +114,7 @@
 	  daddr.off=load_addr+*functions;
 	  function++;
       }
-      DEBUG_AddSymbol(buffer,&daddr, NULL);
+      DEBUG_AddSymbol(buffer,&daddr, NULL, SYM_WIN32 | SYM_FUNC);
   }
 }
 
@@ -379,7 +380,7 @@
     DBG_ADDR	daddr;
 
 	daddr.seg=0;
-
+	daddr.type = NULL;
 	pe = xmalloc(sizeof(struct pe_data));
 	memset(pe,0,sizeof(struct pe_data));
 	pe->pe_header = xmalloc(sizeof(struct pe_header_s));
@@ -410,16 +411,23 @@
 	dprintf_win32(stddeb, "Load addr is %x\n",load_addr);
 	calc_vma_size(pe);
 
+#if 0
 	/* We use malloc here, while a huge part of that address space does
 	   not be supported by actual memory. It has to be contiguous, though.
 	   I don't know if mmap("/dev/null"); would do any better.
 	   What I'd really like to do is a Win32 style VirtualAlloc/MapViewOfFile
 	   sequence */
 	load_addr = pe->load_addr = (int)xmalloc(pe->vma_size);
+	memset( load_addr, 0, pe->vma_size);
+#else
+	load_addr =  pe->load_addr = VirtualAlloc( NULL, pe->vma_size,
+                                                   MEM_COMMIT,
+                                                   PAGE_EXECUTE_READWRITE );
+#endif
+
 	dprintf_win32(stddeb, "Load addr is really %x, range %x\n",
 		pe->load_addr, pe->vma_size);
 	
-	memset( (void *)load_addr, 0, pe->vma_size);
 
 	for(i=0; i < pe->pe_header->coff.NumberOfSections; i++)
 	{
@@ -456,11 +464,14 @@
 	}
 #endif
 
+#if 0
+	/* not needed, memory is zero */
         if(strcmp(pe->pe_seg[i].Name, ".bss") == 0)
             memset((void *)result, 0, 
                    pe->pe_seg[i].Virtual_Size ?
                    pe->pe_seg[i].Virtual_Size :
                    pe->pe_seg[i].Size_Of_Raw_Data);
+#endif
 
 	if(strcmp(pe->pe_seg[i].Name, ".idata") == 0)
 		pe->pe_import = (struct PE_Import_Directory *) result;
@@ -560,16 +571,16 @@
 				pe->pe_seg[i].Name
 			);
 			daddr.off=load_addr+pe->pe_seg[i].Virtual_Address;
-			DEBUG_AddSymbol(buffer,&daddr, NULL);
+			DEBUG_AddSymbol(buffer,&daddr, NULL, SYM_WIN32 | SYM_FUNC);
 		}
 		/* add entry point */
 		sprintf(buffer,"%s.EntryPoint",((char*)load_addr)+pe->pe_export->Name);
 		daddr.off=load_addr+pe->pe_header->opt_coff.AddressOfEntryPoint;
-		DEBUG_AddSymbol(buffer,&daddr, NULL);
+		DEBUG_AddSymbol(buffer,&daddr, NULL, SYM_WIN32 | SYM_FUNC);
 		/* add start of DLL */
 		daddr.off=load_addr;
 		DEBUG_AddSymbol(((char*)load_addr)+pe->pe_export->Name,&daddr,
-				NULL);
+				NULL, SYM_WIN32 | SYM_FUNC);
 	}
         return pe;
 }
diff --git a/loader/signal.c b/loader/signal.c
index e88fada..a2ea979 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -99,7 +99,11 @@
  */
 static void SIGNAL_child(void)
 {
-   wait4( 0, NULL, WNOHANG, NULL);
+#ifdef __svr4__
+    wait(NULL);
+#else
+    wait4( 0, NULL, WNOHANG, NULL);
+#endif
 }
 
 
diff --git a/loader/task.c b/loader/task.c
index 9443dfa..27cfcbe 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -11,7 +11,6 @@
 #include "windows.h"
 #include "task.h"
 #include "callback.h"
-#include "dos_fs.h"
 #include "file.h"
 #include "global.h"
 #include "instance.h"
@@ -508,6 +507,7 @@
     pTask->pdb.fileHandlesPtr =
         PTR_SEG_OFF_TO_SEGPTR( GlobalHandleToSel(pTask->hPDB),
                                (int)&((PDB *)0)->fileHandles );
+    pTask->pdb.hFileHandles = 0;
     memset( pTask->pdb.fileHandles, 0xff, sizeof(pTask->pdb.fileHandles) );
     pTask->pdb.environment    = hEnvironment;
     pTask->pdb.nbFiles        = 20;
@@ -535,7 +535,7 @@
 
     /* Create the Win32 part of the task */
 
-    pdb32 = PROCESS_Create();
+    pdb32 = PROCESS_Create( pTask );
     pTask->thdb = THREAD_Create( pdb32, 0 );
 
     /* Create the 32-bit stack frame */
@@ -592,14 +592,14 @@
     {
         if (pModule->flags & NE_FFLAGS_WIN32)
         {
-            DBG_ADDR addr = { 0, pModule->pe_module->load_addr + 
+            DBG_ADDR addr = { NULL, 0, pModule->pe_module->load_addr + 
                               pModule->pe_module->pe_header->opt_coff.AddressOfEntryPoint };
             fprintf( stderr, "Win32 task '%s': ", name );
             DEBUG_AddBreakpoint( &addr );
         }
         else
         {
-            DBG_ADDR addr = { pSegTable[pModule->cs-1].selector, pModule->ip };
+            DBG_ADDR addr = { NULL, pSegTable[pModule->cs-1].selector, pModule->ip };
             fprintf( stderr, "Win16 task '%s': ", name );
             DEBUG_AddBreakpoint( &addr );
         }
diff --git a/memory/global.c b/memory/global.c
index 747d64c..5c3998f 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -759,7 +759,11 @@
 
     if (info->dwSize < sizeof(MEMMANINFO)) return FALSE;
     GlobalMemoryStatus( &status );
+#ifdef __svr4__
+    info->wPageSize            = sysconf(_SC_PAGESIZE);
+#else
     info->wPageSize            = getpagesize();
+#endif
     info->dwLargestFreeBlock   = status.dwAvailVirtual;
     info->dwMaxPagesAvailable  = info->dwLargestFreeBlock / info->wPageSize;
     info->dwMaxPagesLockable   = info->dwMaxPagesAvailable;
diff --git a/memory/heap.c b/memory/heap.c
index 39cf885..494b115 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -952,7 +952,7 @@
     HEAP_MakeInUseBlockFree( subheap, pInUse );
 
     if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap );
-    SetLastError( 0 );
+/*    SetLastError( 0 ); */
 
     dprintf_heap( stddeb, "HeapFree(%08x,%08lx,%08lx): returning TRUE\n",
                   heap, flags, (DWORD)ptr );
diff --git a/memory/string.c b/memory/string.c
index fd8d9ea..b2b1e93 100644
--- a/memory/string.c
+++ b/memory/string.c
@@ -401,6 +401,15 @@
 
 
 /***********************************************************************
+ *           Copy   (GDI.250)
+ */
+void Copy( LPVOID src, LPVOID dst, WORD size )
+{
+    memcpy( dst, src, size );
+}
+
+
+/***********************************************************************
  *           RtlFillMemory   (KERNEL32.441)
  */
 VOID RtlFillMemory( LPVOID ptr, UINT32 len, UINT32 fill )
diff --git a/misc/clipboard.c b/misc/clipboard.c
index e3d5a61..aa7ba4d 100644
--- a/misc/clipboard.c
+++ b/misc/clipboard.c
@@ -648,9 +648,17 @@
 /**************************************************************************
  *			ChangeClipboardChain	[USER.149]
  */
-BOOL ChangeClipboardChain(HWND hWnd, HWND hWndNext)
+BOOL16 ChangeClipboardChain16(HWND16 hWnd, HWND16 hWndNext)
 {
-    BOOL bRet = 0;
+    return ChangeClipboardChain32(hWnd,hWndNext);
+}
+
+/**************************************************************************
+ *			ChangeClipboardChain	[USER32.21]
+ */
+BOOL32 ChangeClipboardChain32(HWND32 hWnd, HWND32 hWndNext)
+{
+    BOOL32 bRet = 0;
 
     dprintf_clipboard(stdnimp, "ChangeClipboardChain(%04x, %04x)\n", hWnd, hWndNext);
 
@@ -662,10 +670,11 @@
 
     if( hWnd == hWndViewer ) hWndViewer = hWndNext;
 
-    return 0;
+    return bRet;
 }
 
 
+
 /**************************************************************************
  *			IsClipboardFormatAvailable	[USER.193]
  */
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 1b55460..e729d41 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -16,7 +16,6 @@
 #include "dlgs.h"
 #include "module.h"
 #include "resource.h"
-#include "dos_fs.h"
 #include "drive.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -1486,9 +1485,9 @@
  }
  if (result)
  {
-  editpos=SendMessage16(hwnd,EM_GETSEL,0,0);
+  editpos=SendMessage16(hwnd,EM_GETSEL16,0,0);
   SetWindowText32A(hwnd,buffer);
-  SendMessage16(hwnd,EM_SETSEL,0,editpos);
+  SendMessage16(hwnd,EM_SETSEL16,0,editpos);
  }
  return value;
 }
@@ -1953,7 +1952,7 @@
       CC_SwitchToFullSize(hDlg,lpp->lpcc->rgbResult,NULL);
    res=TRUE;
    for (i=0x2bf;i<0x2c5;i++)
-     SendMessage16(GetDlgItem(hDlg,i),EM_LIMITTEXT,3,0);      /* max 3 digits:  xyz  */
+     SendMessage16(GetDlgItem(hDlg,i),EM_LIMITTEXT16,3,0);      /* max 3 digits:  xyz  */
    if (CC_HookCallChk(lpp->lpcc))
       res=CallWindowProc16(lpp->lpcc->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam);
    return res;
diff --git a/misc/crtdll.c b/misc/crtdll.c
index 0d83094..3d29bca 100644
--- a/misc/crtdll.c
+++ b/misc/crtdll.c
@@ -38,6 +38,9 @@
 UINT32 CRTDLL_winminor_dll;     /* CRTDLL.330 */
 UINT32 CRTDLL_winver_dll;       /* CRTDLL.331 */
 
+typedef VOID (*new_handler_type)(VOID);
+
+static new_handler_type new_handler;
 
 /*********************************************************************
  *                  _GetMainArgs  (CRTDLL.022)
@@ -654,6 +657,27 @@
 }
 
 /*********************************************************************
+ *                  new           (CRTDLL.001)
+ */
+VOID* CRTDLL_new(DWORD size)
+{
+    VOID* result;
+    if(!(result = HeapAlloc(GetProcessHeap(),0,size)) && new_handler)
+	(*new_handler)();
+    return result;
+}
+
+/*********************************************************************
+ *                  set_new_handler(CRTDLL.003)
+ */
+new_handler_type CRTDLL_set_new_handler(new_handler_type func)
+{
+    new_handler_type old_handler = new_handler;
+    new_handler = func;
+    return old_handler;
+}
+
+/*********************************************************************
  *                  calloc        (CRTDLL.350)
  */
 VOID* CRTDLL_calloc(DWORD size, DWORD count)
@@ -678,6 +702,14 @@
 }
 
 /*********************************************************************
+ *                  delete       (CRTDLL.002)
+ */
+VOID CRTDLL_delete(VOID* ptr)
+{
+    HeapFree(GetProcessHeap(),0,ptr);
+}
+
+/*********************************************************************
  *                  _strdup          (CRTDLL.285)
  */
 LPSTR CRTDLL__strdup(LPSTR ptr)
diff --git a/misc/keyboard.c b/misc/keyboard.c
index 4b5638c..25c7771 100644
--- a/misc/keyboard.c
+++ b/misc/keyboard.c
@@ -135,6 +135,9 @@
 int ToAscii(WORD wVirtKey, WORD wScanCode, LPSTR lpKeyState, 
 	LPVOID lpChar, WORD wFlags) 
 {
+#if 1
+	return EVENT_ToAscii(wVirtKey, wScanCode, lpKeyState, lpChar, wFlags);
+#else
 	char shift = lpKeyState[VK_SHIFT] < 0;
 	int i;
 
@@ -184,6 +187,7 @@
 	  *(BYTE*)lpChar = *(BYTE*)lpChar & 0x1f;
 	dprintf_keyboard(stddeb, "1 (%x)\n", *(BYTE*)lpChar);
 	return 1;
+#endif
 }
 
 DWORD OemKeyScan(WORD wOemChar)
diff --git a/misc/lstr.c b/misc/lstr.c
index 730b540..e8a683d 100644
--- a/misc/lstr.c
+++ b/misc/lstr.c
@@ -12,12 +12,12 @@
 #include <ctype.h>
 
 #include "windows.h"
+#include "winnt.h"	/* HEAP_ macros */
 #include "heap.h"
 #include "ldt.h"
 #include "module.h"
 #include "stddebug.h"
 #include "debug.h"
-#include "xmalloc.h"
 
 #define ToUpper(c)	toupper(c)
 #define ToLower(c)	tolower(c)
@@ -50,11 +50,9 @@
 }
 
 /***********************************************************************
- *           AnsiUpper   (USER.431)
+ *           AnsiUpper16   (USER.431)
  */
-
-/* 16-bit version */
-SEGPTR WIN16_AnsiUpper( SEGPTR strOrChar )
+SEGPTR AnsiUpper16( SEGPTR strOrChar )
 {
   /* I am not sure if the locale stuff works with toupper, but then again 
      I am not sure if the Linux libc locale stuffs works at all */
@@ -62,50 +60,28 @@
     /* uppercase only one char if strOrChar < 0x10000 */
     if (HIWORD(strOrChar))
     {
-        char *s = PTR_SEG_TO_LIN(strOrChar);
-        while (*s) {
-	    *s = ToUpper( *s );
-	    s++;
-	}
+        char *s;
+        for (s = PTR_SEG_TO_LIN(strOrChar); *s; s++) *s = toupper(*s);
         return strOrChar;
     }
     else return (SEGPTR)ToUpper( (int)strOrChar );
 }
 
-/* 32-bit version */
-LPSTR AnsiUpper(LPSTR strOrChar)
-{
-    char *s = strOrChar;
-  /* I am not sure if the locale stuff works with toupper, but then again 
-     I am not sure if the Linux libc locale stuffs works at all */
-
-    while (*s) {
-	*s = ToUpper( *s );
-	s++;
-    }
-    return strOrChar;
-}
-
 
 /***********************************************************************
- *           AnsiUpperBuff   (USER.437)
+ *           AnsiUpperBuff16   (USER.437)
  */
-UINT AnsiUpperBuff(LPSTR str,UINT len)
+UINT16 AnsiUpperBuff16( LPSTR str, UINT16 len )
 {
-  int i;
-  len=(len==0)?65536:len;
-
-  for(i=0;i<len;i++)
-    str[i]=toupper(str[i]);
-  return i;	
+    UINT32 count = len ? len : 65536;
+    for (; count; count--, str++) *str = toupper(*str);
+    return len;
 }
 
 /***********************************************************************
- *           AnsiLower   (USER.432)
+ *           AnsiLower16   (USER.432)
  */
-
-/* 16-bit version */
-SEGPTR WIN16_AnsiLower(SEGPTR strOrChar)
+SEGPTR AnsiLower16( SEGPTR strOrChar )
 {
   /* I am not sure if the locale stuff works with toupper, but then again 
      I am not sure if the Linux libc locale stuffs works at all */
@@ -113,57 +89,40 @@
     /* lowercase only one char if strOrChar < 0x10000 */
     if (HIWORD(strOrChar))
     {
-        char *s = PTR_SEG_TO_LIN( strOrChar );
-        while (*s) {	    
-	    *s = ToLower( *s );
-	    s++;
-	}
+        char *s;
+        for (s = PTR_SEG_TO_LIN( strOrChar ); *s; s++) *s = tolower( *s );
         return strOrChar;
     }
-    else return (SEGPTR)ToLower( (int)strOrChar );
-}
-
-/* 32-bit version */
-LPSTR AnsiLower(LPSTR strOrChar)
-{
-    char *s = strOrChar;
-  /* I am not sure if the locale stuff works with toupper, but then again 
-     I am not sure if the Linux libc locale stuffs works at all */
-
-    while (*s) {
-	*s = ToLower( *s );
-	s++;
-    }
-    return strOrChar;
+    else return (SEGPTR)tolower( (int)strOrChar );
 }
 
 
 /***********************************************************************
- *           AnsiLowerBuff   (USER.438)
+ *           AnsiLowerBuff16   (USER.438)
  */
-UINT AnsiLowerBuff(LPSTR str,UINT len)
+UINT16 AnsiLowerBuff16( LPSTR str, UINT16 len )
 {
-  int i;
-  len=(len==0)?65536:len;
-  i=0;
-
-  for(i=0;i<len;i++)
-    str[i]=tolower(str[i]);
- 
-  return i;	
+    UINT32 count = len ? len : 65536;
+    for (; count; count--, str++) *str = tolower(*str);
+    return len;
 }
 
 
-/* AnsiNext USER.472 */
-SEGPTR AnsiNext(SEGPTR current)
+/***********************************************************************
+ *           AnsiNext16   (USER.472)
+ */
+SEGPTR AnsiNext16(SEGPTR current)
 {
     return (*(char *)PTR_SEG_TO_LIN(current)) ? current + 1 : current;
 }
 
-/* AnsiPrev USER.473 */
-SEGPTR AnsiPrev( SEGPTR start, SEGPTR current)
+
+/***********************************************************************
+ *           AnsiPrev16   (USER.473)
+ */
+SEGPTR AnsiPrev16( SEGPTR start, SEGPTR current )
 {
-    return (current==start)?start:current-1;
+    return (current == start) ? start : current - 1;
 }
 
 
@@ -184,25 +143,29 @@
     HeapFree( GetProcessHeap(), 0, buffer );
 }
 
-/***********************************************************************
- *           CharNextA   (USER32.28)
- */
-LPSTR CharNext32A(LPCSTR x)
-{
-    if (*x) return (LPSTR)(x+1);
-    else return (LPSTR)x;
-}
 
 /***********************************************************************
- *           CharNextExA   (USER32.29)
+ *           CharNext32A   (USER32.28)
  */
-LPSTR CharNextEx32A(WORD codepage,LPCSTR x,DWORD flags)
+LPSTR CharNext32A( LPCSTR ptr )
 {
-    /* FIXME: add DBCS / codepage stuff */
-    if (*x) return (LPSTR)(x+1);
-    else return (LPSTR)x;
+    if (!*ptr) return (LPSTR)ptr;
+    if (IsDBCSLeadByte32( *ptr )) return (LPSTR)(ptr + 2);
+    return (LPSTR)(ptr + 1);
 }
 
+
+/***********************************************************************
+ *           CharNextEx32A   (USER32.29)
+ */
+LPSTR CharNextEx32A( WORD codepage, LPCSTR ptr, DWORD flags )
+{
+    if (!*ptr) return (LPSTR)ptr;
+    if (IsDBCSLeadByteEx( codepage, *ptr )) return (LPSTR)(ptr + 2);
+    return (LPSTR)(ptr + 1);
+}
+
+
 /***********************************************************************
  *           CharNextExW   (USER32.30)
  */
@@ -223,24 +186,35 @@
 }
 
 /***********************************************************************
- *           CharPrevA   (USER32.32)
+ *           CharPrev32A   (USER32.32)
  */
-LPSTR CharPrev32A(LPCSTR start,LPCSTR x)
+LPSTR CharPrev32A( LPCSTR start, LPCSTR ptr )
 {
-    if (x>start) return (LPSTR)(x-1);
-    else return (LPSTR)x;
+    while (*start && (start < ptr))
+    {
+        LPCSTR next = CharNext32A( start );
+        if (next > ptr) break;
+        start = next;
+    }
+    return (LPSTR)start;
 }
 
+
 /***********************************************************************
- *           CharPrevExA   (USER32.33)
+ *           CharPrevEx32A   (USER32.33)
  */
-LPSTR CharPrevEx32A(WORD codepage,LPCSTR start,LPCSTR x,DWORD flags)
+LPSTR CharPrevEx32A( WORD codepage, LPCSTR start, LPCSTR ptr, DWORD flags )
 {
-    /* FIXME: add DBCS / codepage stuff */
-    if (x>start) return (LPSTR)(x-1);
-    else return (LPSTR)x;
+    while (*start && (start < ptr))
+    {
+        LPCSTR next = CharNextEx32A( codepage, start, flags );
+        if (next > ptr) break;
+        start = next;
+    }
+    return (LPSTR)start;
 }
 
+
 /***********************************************************************
  *           CharPrevExW   (USER32.34)
  */
@@ -335,7 +309,7 @@
 }
 
 /***********************************************************************
- *           CharUpperA   (USER32.40)
+ *           CharUpper32A   (USER32.40)
  * FIXME: handle current locale
  */
 LPSTR CharUpper32A(LPSTR x)
@@ -521,15 +495,14 @@
 			LoadMessage32A(0,dwMessageId,dwLanguageId,from,bufsize+1);
 		}
 	}
-	target	= HeapAlloc( GetProcessHeap(), 0, 100);
+	target	= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
 	t	= target;
 	talloced= 100;
-	*t	= 0;
 
 #define ADD_TO_T(c) \
 	*t++=c;\
 	if (t-target == talloced) {\
-		target	= (char*)xrealloc(target,talloced*2);\
+		target	= (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
 		t	= target+talloced;\
 		talloced*=2;\
 	}
@@ -612,7 +585,7 @@
 		ADD_TO_T('\n');
 	talloced = strlen(target)+1;
 	if (nSize && talloced<nSize) {
-		target = (char*)xrealloc(target,nSize);
+		target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
 	}
 	if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
 		/* nSize is the MINIMUM size */
@@ -626,6 +599,7 @@
 			strlen(*(LPSTR*)lpBuffer):
 			strlen(lpBuffer);
 }
+#undef ADD_TO_T
 
 /***********************************************************************
  *           FormatMessageA   (KERNEL32.138) Emulator Version
@@ -705,15 +679,14 @@
                     LoadMessage32A(0,dwMessageId,dwLanguageId,from,bufsize+1);
 		}
 	}
-	target	= HeapAlloc( GetProcessHeap(), 0, 100 );
+	target	= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
 	t	= target;
 	talloced= 100;
-	*t	= 0;
 
 #define ADD_TO_T(c) \
 	*t++=c;\
 	if (t-target == talloced) {\
-		target	= (char*)xrealloc(target,talloced*2);\
+		target	= (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
 		t	= target+talloced;\
 		talloced*=2;\
 	}
@@ -805,7 +778,7 @@
 		ADD_TO_T('\n');
 	talloced = strlen(target)+1;
 	if (nSize && talloced<nSize)
-		target = (char*)xrealloc(target,nSize);
+		target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
 	if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
 		/* nSize is the MINIMUM size */
 		*((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced*2+2);
@@ -818,6 +791,7 @@
 			lstrlen32W(*(LPWSTR*)lpBuffer):
 			lstrlen32W(lpBuffer);
 }
+#undef ADD_TO_T
 
 /***********************************************************************
  *           FormatMessageA   (KERNEL32.138) Emulator Version
diff --git a/misc/main.c b/misc/main.c
index 5be6dbf..d1a4dcc3 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -108,7 +108,7 @@
     FALSE,          /* backing store */
     SW_SHOWNORMAL,  /* cmdShow */
     FALSE,
-    FALSE,          /* AllowReadOnly */
+    FALSE,          /* failReadOnly */
     MODE_ENHANCED,  /* Enhanced mode */
     FALSE,          /* IPC enabled */
 #ifdef DEFAULT_LANG
@@ -138,7 +138,7 @@
     { "-debug",         ".debug",           XrmoptionNoArg,  (caddr_t)"on" },
     { "-debugmsg",      ".debugmsg",        XrmoptionSepArg, (caddr_t)NULL },
     { "-dll",           ".dll",             XrmoptionSepArg, (caddr_t)NULL },
-    { "-allowreadonly", ".allowreadonly",   XrmoptionNoArg,  (caddr_t)"on" },
+    { "-failreadonly",  ".failreadonly",    XrmoptionNoArg,  (caddr_t)"on" },
     { "-mode",          ".mode",            XrmoptionSepArg, (caddr_t)NULL },
     { "-managed",       ".managed",         XrmoptionNoArg,  (caddr_t)"off"},
     { "-winver",        ".winver",          XrmoptionSepArg, (caddr_t)NULL }
@@ -150,7 +150,6 @@
   "Usage:  %s [options] program_name [arguments]\n" \
   "\n" \
   "Options:\n" \
-  "    -allowreadonly  Read only files may be opened in write mode\n" \
   "    -backingstore   Turn on backing store\n" \
   "    -debug          Enter debugger before starting application\n" \
   "    -debugmsg name  Turn debugging-messages on or off\n" \
@@ -158,6 +157,7 @@
   "    -desktop geom   Use a desktop window of the given geometry\n" \
   "    -display name   Use the specified display\n" \
   "    -dll name       Enable or disable built-in DLLs\n" \
+  "    -failreadonly   Read only files may not be opened in write mode\n" \
   "    -fixedmap       Use a \"standard\" color map\n" \
   "    -iconic         Start as an icon\n" \
   "    -ipc            Enable IPC facilities\n" \
@@ -433,8 +433,8 @@
 	Options.backingstore = TRUE;	
     if (MAIN_GetResource( db, ".debug", &value ))
 	Options.debug = TRUE;
-    if (MAIN_GetResource( db, ".allowreadonly", &value ))
-        Options.allowReadOnly = TRUE;
+    if (MAIN_GetResource( db, ".failreadonly", &value ))
+        Options.failReadOnly = TRUE;
     if (MAIN_GetResource( db, ".ipc", &value ))
         Options.ipc = TRUE;
     if (MAIN_GetResource( db, ".perfect", &value ))
@@ -870,32 +870,6 @@
 
 
 /***********************************************************************
- *      SetEnvironmentVariable32A   (KERNEL32.484)
- */
-BOOL32 SetEnvironmentVariable32A( LPCSTR lpName, LPCSTR lpValue )
-{
-    int rc;
-
-    rc = SetEnvironment(lpName, lpValue, lpValue?(strlen(lpValue)+1):0);
-    return (rc>0)?TRUE:FALSE;
-}
-
-
-/***********************************************************************
- *      SetEnvironmentVariable32W   (KERNEL32.485)
- */
-BOOL32 SetEnvironmentVariable32W( LPCWSTR lpName, LPCWSTR lpValue )
-{
-    LPSTR lpNameA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpName );
-    LPSTR lpValueA = HEAP_strdupWtoA( GetProcessHeap(), 0, lpValue );
-    BOOL32 ret = SetEnvironmentVariable32A(lpNameA,lpValueA);
-    HeapFree( GetProcessHeap(), 0, lpNameA );
-    HeapFree( GetProcessHeap(), 0, lpValueA );
-    return ret;
-}
-
-
-/***********************************************************************
  *	GetEnvironment (GDI.134)
  */
 int GetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nMaxSiz)
@@ -919,135 +893,6 @@
     return 0;
 }
 
-/***********************************************************************
- *      GetEnvironmentVariable32A   (KERNEL32.213)
- */
-DWORD GetEnvironmentVariable32A( LPSTR lpName, LPSTR lpValue, DWORD size )
-{
-    return GetEnvironment(lpName, lpValue, size);
-}
-
-/***********************************************************************
- *      GetEnvironmentVariable32W   (KERNEL32.214)
- */
-DWORD GetEnvironmentVariable32W( LPWSTR nameW, LPWSTR valW, DWORD size )
-{
-    LPSTR name = HEAP_strdupWtoA( GetProcessHeap(), 0, nameW );
-    LPSTR val  = valW ? HeapAlloc( GetProcessHeap(), 0, size ) : NULL;
-    DWORD res  = GetEnvironment( name, val, size );
-    HeapFree( GetProcessHeap(), 0, name );
-    if (val)
-    {
-        lstrcpyAtoW( valW, val );
-        HeapFree( GetProcessHeap(), 0, val );
-    }
-    return res;
-}
-
-/***********************************************************************
- *      GetEnvironmentStrings (KERNEL32.210)
- */
-LPVOID GetEnvironmentStrings(void)
-{
-    int count;
-    LPENVENTRY lpEnv;
-    char *envtable, *envptr;
-
-    /* Count the total number of bytes we'll need for the string
-     * table.  Include the trailing nuls and the final double nul.
-     */
-    count = 1;
-    lpEnv = lpEnvList;
-    while(lpEnv != NULL)
-    {
-        if(lpEnv->Name != NULL)
-        {
-            count += strlen(lpEnv->Name) + 1;
-            count += strlen(lpEnv->Value) + 1;
-        }
-        lpEnv = lpEnv->Next;
-    }
-
-    envtable = malloc(count);
-    if(envtable)
-    {
-        lpEnv = lpEnvList;
-        envptr = envtable;
-
-        while(lpEnv != NULL)
-        {
-            if(lpEnv->Name != NULL)
-            {
-                count = sprintf(envptr, "%s=%s", lpEnv->Name, lpEnv->Value);
-                envptr += count + 1;
-            }
-            lpEnv = lpEnv->Next;
-        }
-        *envptr = '\0';
-    }
-
-    return envtable;
-}
-
-
-LPVOID GetEnvironmentStringsW(void)
-{
-    int count,len;
-    LPENVENTRY lpEnv;
-    char *envtable, *envptr;
-	WCHAR *wenvtable;
-
-    /* Count the total number of bytes we'll need for the string
-     * table.  Include the trailing nuls and the final double nul.
-     */
-    count = 1;
-    lpEnv = lpEnvList;
-    while(lpEnv != NULL)
-    {
-        if(lpEnv->Name != NULL)
-        {
-            count += strlen(lpEnv->Name) + 1;
-            count += strlen(lpEnv->Value) + 1;
-        }
-        lpEnv = lpEnv->Next;
-    }
-
-	len=count;
-    envtable = malloc(count);
-    if(envtable)
-    {
-        lpEnv = lpEnvList;
-        envptr = envtable;
-
-        while(lpEnv != NULL)
-        {
-            if(lpEnv->Name != NULL)
-            {
-                count = sprintf(envptr, "%s=%s", lpEnv->Name, lpEnv->Value);
-                envptr += count + 1;
-            }
-            lpEnv = lpEnv->Next;
-        }
-        *envptr = '\0';
-    }
-
-	wenvtable = malloc(2*len);
-	for(count=0;count<len;count++)
-		wenvtable[count]=(WCHAR)envtable[count];
-	free(envtable);
-
-    return wenvtable;
-}
-
-void FreeEnvironmentStringsA(void *e)
-{
-	free(e);
-}
-
-void FreeEnvironmentStringsW(void* e)
-{
-	free(e);
-}
 
 /***********************************************************************
  *	GetTimerResolution (USER.14)
@@ -1291,14 +1136,6 @@
 
 
 /***********************************************************************
-*	COPY (GDI.250)
-*/
-void Copy(LPVOID lpSource, LPVOID lpDest, WORD nBytes)
-{
-	memcpy(lpDest, lpSource, nBytes);
-}
-
-/***********************************************************************
 *	SWAPMOUSEBUTTON (USER.186)
 */
 BOOL SwapMouseButton(BOOL fSwap)
diff --git a/misc/ole2nls.c b/misc/ole2nls.c
index a6b1e8b..3df0148 100644
--- a/misc/ole2nls.c
+++ b/misc/ole2nls.c
@@ -1155,6 +1155,112 @@
 	}
     break; /* LANG(0x0809) (U.K. English) */
 
+    case LANG_Ko: /* string using codepage 949 */
+        switch (LCType) {
+LOCVAL(LOCALE_ILANGUAGE,"18")
+LOCVAL(LOCALE_SLANGUAGE,"\307\321\261\271\276\356")
+LOCVAL(LOCALE_SENGLANGUAGE,"Korean")
+LOCVAL(LOCALE_SABBREVLANGNAME,"KOR")
+LOCVAL(LOCALE_SNATIVELANGNAME,"\307\321\261\271\276\356")
+LOCVAL(LOCALE_ICOUNTRY,"82")
+LOCVAL(LOCALE_SCOUNTRY,"\264\353\307\321\271\316\261\271")
+LOCVAL(LOCALE_SENGCOUNTRY,"Korea (South)")
+LOCVAL(LOCALE_SABBREVCTRYNAME,"KOR")
+LOCVAL(LOCALE_SNATIVECTRYNAME,"\264\353\307\321\271\316\261\271")
+LOCVAL(LOCALE_IDEFAULTLANGUAGE,"18")
+LOCVAL(LOCALE_IDEFAULTCOUNTRY,"82")
+LOCVAL(LOCALE_IDEFAULTCODEPAGE,"949")
+LOCVAL(LOCALE_IDEFAULTANSICODEPAGE,"949")
+LOCVAL(LOCALE_SLIST,",")
+LOCVAL(LOCALE_IMEASURE,"0")
+LOCVAL(LOCALE_SDECIMAL,".")
+LOCVAL(LOCALE_STHOUSAND,",")
+LOCVAL(LOCALE_SGROUPING,"3;0")
+LOCVAL(LOCALE_IDIGITS,"2")
+LOCVAL(LOCALE_ILZERO,"0")
+LOCVAL(LOCALE_INEGNUMBER,"1")
+LOCVAL(LOCALE_SNATIVEDIGITS,"0123456789")
+LOCVAL(LOCALE_SCURRENCY,"\\")
+LOCVAL(LOCALE_SINTLSYMBOL,"Won")
+LOCVAL(LOCALE_SMONDECIMALSEP,".")
+LOCVAL(LOCALE_SMONTHOUSANDSEP,",")
+LOCVAL(LOCALE_SMONGROUPING,"3;0")
+LOCVAL(LOCALE_ICURRDIGITS,"2")
+LOCVAL(LOCALE_IINTLCURRDIGITS,"2")
+LOCVAL(LOCALE_ICURRENCY,"3")
+LOCVAL(LOCALE_INEGCURR,"8")
+LOCVAL(LOCALE_SDATE,"/")
+LOCVAL(LOCALE_STIME,":")
+LOCVAL(LOCALE_SSHORTDATE,"yyyy/MM/dd")
+LOCVAL(LOCALE_SLONGDATE,"yyyy/MM/dd")
+LOCVAL(LOCALE_STIMEFORMAT,"h:mm:ss tt")
+LOCVAL(LOCALE_IDATE,"1")
+LOCVAL(LOCALE_ILDATE,"1")
+LOCVAL(LOCALE_ITIME,"1")
+LOCVAL(LOCALE_ITIMEMARKPOSN,"0")
+LOCVAL(LOCALE_ICENTURY,"0")
+LOCVAL(LOCALE_ITLZERO,"0")
+LOCVAL(LOCALE_IDAYLZERO,"0")
+LOCVAL(LOCALE_IMONLZERO,"0")
+LOCVAL(LOCALE_S1159,"\277\300\300\374")
+LOCVAL(LOCALE_S2359,"\277\300\310\304")
+LOCVAL(LOCALE_ICALENDARTYPE,"1")
+/* Korean Tangun Era calendar */
+LOCVAL(LOCALE_IOPTIONALCALENDAR,"5")
+LOCVAL(LOCALE_IFIRSTDAYOFWEEK,"6")
+LOCVAL(LOCALE_IFIRSTWEEKOFYEAR,"0")
+LOCVAL(LOCALE_SDAYNAME1,"\277\371\277\344\300\317")
+LOCVAL(LOCALE_SDAYNAME2,"\310\255\277\344\300\317")
+LOCVAL(LOCALE_SDAYNAME3,"\274\366\277\344\300\317")
+LOCVAL(LOCALE_SDAYNAME4,"\270\361\277\344\300\317")
+LOCVAL(LOCALE_SDAYNAME5,"\261\335\277\344\300\317")
+LOCVAL(LOCALE_SDAYNAME6,"\305\344\277\344\300\317")
+LOCVAL(LOCALE_SDAYNAME7,"\300\317\277\344\300\317")
+LOCVAL(LOCALE_SABBREVDAYNAME1,"\277\371")
+LOCVAL(LOCALE_SABBREVDAYNAME2,"\310\255")
+LOCVAL(LOCALE_SABBREVDAYNAME3,"\274\366")
+LOCVAL(LOCALE_SABBREVDAYNAME4,"\270\361")
+LOCVAL(LOCALE_SABBREVDAYNAME5,"\261\335")
+LOCVAL(LOCALE_SABBREVDAYNAME6,"\305\344")
+LOCVAL(LOCALE_SABBREVDAYNAME7,"\300\317")
+LOCVAL(LOCALE_SMONTHNAME1,"1\277\371")
+LOCVAL(LOCALE_SMONTHNAME2,"2\277\371")
+LOCVAL(LOCALE_SMONTHNAME3,"3\277\371")
+LOCVAL(LOCALE_SMONTHNAME4,"4\277\371")
+LOCVAL(LOCALE_SMONTHNAME5,"5\277\371")
+LOCVAL(LOCALE_SMONTHNAME6,"6\277\371")
+LOCVAL(LOCALE_SMONTHNAME7,"7\277\371")
+LOCVAL(LOCALE_SMONTHNAME8,"8\277\371")
+LOCVAL(LOCALE_SMONTHNAME9,"9\277\371")
+LOCVAL(LOCALE_SMONTHNAME10,"10\277\371")
+LOCVAL(LOCALE_SMONTHNAME11,"11\277\371")
+LOCVAL(LOCALE_SMONTHNAME12,"12\277\371")
+LOCVAL(LOCALE_SMONTHNAME13,"")
+LOCVAL(LOCALE_SABBREVMONTHNAME1,"1\277\371")
+LOCVAL(LOCALE_SABBREVMONTHNAME2,"2\277\371")
+LOCVAL(LOCALE_SABBREVMONTHNAME3,"3\277\371")
+LOCVAL(LOCALE_SABBREVMONTHNAME4,"4\277\371")
+LOCVAL(LOCALE_SABBREVMONTHNAME5,"5\277\371")
+LOCVAL(LOCALE_SABBREVMONTHNAME6,"6\277\371")
+LOCVAL(LOCALE_SABBREVMONTHNAME7,"7\277\371")
+LOCVAL(LOCALE_SABBREVMONTHNAME8,"8\277\371")
+LOCVAL(LOCALE_SABBREVMONTHNAME9,"9\277\371")
+LOCVAL(LOCALE_SABBREVMONTHNAME10,"10\277\371")
+LOCVAL(LOCALE_SABBREVMONTHNAME11,"11\277\371")
+LOCVAL(LOCALE_SABBREVMONTHNAME12,"12\277\371")
+LOCVAL(LOCALE_SABBREVMONTHNAME13,"")
+LOCVAL(LOCALE_SPOSITIVESIGN,"")
+LOCVAL(LOCALE_SNEGATIVESIGN,"-")
+LOCVAL(LOCALE_IPOSSIGNPOSN,"3")
+LOCVAL(LOCALE_INEGSIGNPOSN,"0")
+LOCVAL(LOCALE_IPOSSYMPRECEDES,"3")
+LOCVAL(LOCALE_IPOSSEPBYSPACE,"0")
+LOCVAL(LOCALE_INEGSYMPRECEDES,"3")
+LOCVAL(LOCALE_INEGSEPBYSPACE,"0")
+        default: found=0;break;
+        }
+    break;  /* LANG(Ko) */
+
 /*Insert other languages here*/
 
     default:
diff --git a/misc/registry.c b/misc/registry.c
index 9b7c209..48b577f 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -21,7 +21,6 @@
 #include "winerror.h"
 #include "file.h"
 #include "heap.h"
-#include "dos_fs.h"
 #include "string32.h"	
 #include "stddebug.h"
 #include "debug.h"
@@ -1228,8 +1227,8 @@
 	/* STEP 2: keydata & values */
 	if (!GetFileInformationByHandle(hfd,&hfdinfo))
 		return;
-	end		= hfdinfo.nFileSizeLow;
-	lastmodified	= DOSFS_FileTimeToUnixTime(&(hfdinfo.ftLastWriteTime));
+	end = hfdinfo.nFileSizeLow;
+	lastmodified = DOSFS_FileTimeToUnixTime(&hfdinfo.ftLastWriteTime,NULL);
 
 	if (-1==_llseek32(hfd,rgdbsection,SEEK_SET))
 		return;
@@ -1532,7 +1531,7 @@
 		_lclose32(hf);
 		return;
 	}
-	lastmodified	= DOSFS_FileTimeToUnixTime(&(hfinfo.ftLastWriteTime));
+	lastmodified = DOSFS_FileTimeToUnixTime(&hfinfo.ftLastWriteTime,NULL);
 
 	if (RegCreateKey16(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&hkey)!=ERROR_SUCCESS)
 		return;
diff --git a/misc/shell.c b/misc/shell.c
index 40a4534..506b13e 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -176,12 +176,8 @@
     }
 
     /* Make local copy & lowercase it for reg & 'programs=' lookup */
-    strncpy( tmpext, extension, 5 );
-    if (strlen(extension)<=4)
-	tmpext[strlen(extension)]='\0';
-    else
-	tmpext[4]='\0';
-    for (i=0;i<strlen(tmpext);i++) tmpext[i]=tolower(tmpext[i]);
+    lstrcpyn32A( tmpext, extension, 5 );
+    CharLower32A( tmpext );
     dprintf_exec(stddeb, "SHELL_FindExecutable: %s file\n", tmpext);
     
     /* Three places to check: */
diff --git a/misc/spy.c b/misc/spy.c
index 1b00d39..24906ab 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -136,15 +136,48 @@
     NULL, NULL, NULL, NULL, NULL, NULL,
 
     /* 0x00B0 - Win32 Edit controls */
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    "EM_GETSEL32",              /* 0x00b0 */
+    "EM_SETSEL32",              /* 0x00b1 */
+    "EM_GETRECT32",             /* 0x00b2 */
+    "EM_SETRECT32",             /* 0x00b3 */
+    "EM_SETRECTNP32",           /* 0x00b4 */
+    "EM_SCROLL32",              /* 0x00b5 */
+    "EM_LINESCROLL32",          /* 0x00b6 */
+    "EM_SCROLLCARET32",         /* 0x00b7 */
+    "EM_GETMODIFY32",           /* 0x00b8 */
+    "EM_SETMODIFY32",           /* 0x00b9 */
+    "EM_GETLINECOUNT32",        /* 0x00ba */
+    "EM_LINEINDEX32",           /* 0x00bb */
+    "EM_SETHANDLE32",           /* 0x00bc */
+    "EM_GETHANDLE32",           /* 0x00bd */
+    "EM_GETTHUMB32",            /* 0x00be */
+    NULL,                       /* 0x00bf */
 
-    /* 0x00C0 */
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL,                       /* 0x00c0 */
+    "EM_LINELENGTH32",          /* 0x00c1 */
+    "EM_REPLACESEL32",          /* 0x00c2 */
+    NULL,                       /* 0x00c3 */
+    "EM_GETLINE32",             /* 0x00c4 */
+    "EM_LIMITTEXT32",           /* 0x00c5 */
+    "EM_CANUNDO32",             /* 0x00c6 */
+    "EM_UNDO32",                /* 0x00c7 */
+    "EM_FMTLINES32",            /* 0x00c8 */
+    "EM_LINEFROMCHAR32",        /* 0x00c9 */
+    NULL,                       /* 0x00ca */
+    "EM_SETTABSTOPS32",         /* 0x00cb */
+    "EM_SETPASSWORDCHAR32",     /* 0x00cc */
+    "EM_EMPTYUNDOBUFFER32",     /* 0x00cd */
+    "EM_GETFIRSTVISIBLELINE32", /* 0x00ce */
+    "EM_SETREADONLY32",         /* 0x00cf */
 
-    /* 0x00D0 */
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    "EM_SETWORDBREAKPROC32",    /* 0x00d0 */
+    "EM_GETWORDBREAKPROC32",    /* 0x00d1 */
+    "EM_GETPASSWORDCHAR32",     /* 0x00d2 */
+    "EM_SETMARGINS32",          /* 0x00d3 */
+    "EM_GETMARGINS32",          /* 0x00d4 */
+    "EM_GETLIMITTEXT32",        /* 0x00d5 */
+    "EM_POSFROMCHAR32",         /* 0x00d6 */
+    "EM_CHARFROMPOS32",         /* 0x00d7 */
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
 
     /* 0x00E0 - Win32 Scrollbars */
diff --git a/misc/winsock.c b/misc/winsock.c
index e26e84f..5acadcd 100644
--- a/misc/winsock.c
+++ b/misc/winsock.c
@@ -14,6 +14,7 @@
 #if defined(__svr4__)
 #include <sys/filio.h>
 #include <sys/ioccom.h>
+#include <sys/sockio.h>
 #endif
 #include <sys/msg.h>
 #include <sys/wait.h>
diff --git a/misc/winsock_async.c b/misc/winsock_async.c
index 607b9cf..863f2ff 100644
--- a/misc/winsock_async.c
+++ b/misc/winsock_async.c
@@ -14,6 +14,10 @@
 #include <sys/msg.h>
 #include <sys/wait.h>
 #include <errno.h>
+#ifdef __svr4__
+#include <sys/file.h>
+#include <sys/filio.h>
+#endif
 
 extern int h_errno;
 
@@ -112,7 +116,7 @@
  ws_async_op*		p_aop;
 
  check_set = __async_io_fdset;
- bzero(&timeout,sizeof(timeout));
+ memset(&timeout, 0, sizeof(timeout));
 
  while( select(__async_io_max_fd + 1,
               &check_set, NULL, NULL, &timeout) > 0)
diff --git a/msdos/int21.c b/msdos/int21.c
index 609b908..79c0d87 100644
--- a/msdos/int21.c
+++ b/msdos/int21.c
@@ -16,9 +16,9 @@
 #include <utime.h>
 #include <ctype.h>
 #include "windows.h"
-#include "dos_fs.h"
 #include "drive.h"
 #include "file.h"
+#include "heap.h"
 #include "msdos.h"
 #include "ldt.h"
 #include "task.h"
@@ -291,32 +291,21 @@
 	}
 }
 
-static void GetSystemDate( CONTEXT *context )
+static void INT21_GetSystemDate( CONTEXT *context )
 {
-	struct tm *now;
-	time_t ltime;
-
-	ltime = time(NULL);
-	now = localtime(&ltime);
-
-	CX_reg(context) = now->tm_year + 1900;
-	DX_reg(context) = ((now->tm_mon + 1) << 8) | now->tm_mday;
-	AX_reg(context) = now->tm_wday;
+    SYSTEMTIME systime;
+    GetLocalTime( &systime );
+    CX_reg(context) = systime.wYear;
+    DX_reg(context) = (systime.wMonth << 8) | systime.wDay;
+    AX_reg(context) = systime.wDayOfWeek;
 }
 
 static void INT21_GetSystemTime( CONTEXT *context )
 {
-	struct tm *now;
-	struct timeval tv;
-	time_t seconds;
-
-	gettimeofday(&tv,NULL);		/* Note use of gettimeofday(), instead of time() */
-	seconds = tv.tv_sec;
-	now = localtime(&seconds);
-	 
-	CX_reg(context) = (now->tm_hour<<8) | now->tm_min;
-	DX_reg(context) = (now->tm_sec<<8) | tv.tv_usec/10000;
-					/* Note hundredths of seconds */
+    SYSTEMTIME systime;
+    GetLocalTime( &systime );
+    CX_reg(context) = (systime.wHour << 8) | systime.wMinute;
+    DX_reg(context) = (systime.wSecond << 8) | (systime.wMilliseconds / 10);
 }
 
 static void INT21_CreateFile( CONTEXT *context )
@@ -345,10 +334,6 @@
 	int mode;
 	int lock;
 	
-	dprintf_int (stddeb, "int21: open (%s, %d) = %d\n",
-		DOS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),
-                                             DX_reg(context))), mode, handle);
-
         switch (AX_reg(context) & 0x0070)
 	{
 	  case 0x00:    /* compatability mode */
@@ -424,8 +409,6 @@
 void ExtendedOpenCreateFile(CONTEXT *context )
 {
   BYTE action=DL_reg(context);
-  dprintf_int(stddeb, "int21: extended open/create: file= %s \n",
-	      DOSFS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),FALSE));
   /* Shuffle arguments to call OpenExistingFile */
   AL_reg(context) = BL_reg(context);
   DX_reg(context) = SI_reg(context);
@@ -433,8 +416,6 @@
   OpenExistingFile(context);
   if ((EFL_reg(context) & 0x0001)==0) 
     { /* It exists */
-      dprintf_int(stddeb, "int21: extended open/create %s exists \n",
-		  DOSFS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),TRUE));
       /* Now decide what do do */
       if ((action & 0x07)== 0)
 	{
@@ -487,9 +468,8 @@
   else /* file does not exist */
     {
       RESET_CFLAG(context); /* was set by OpenExistingFile(context) */
-     dprintf_int(stddeb, "int21: extended open/create %s dosen't exists \n",
-		  DOSFS_GetUnixFileName(PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context)),FALSE));
-      if ((action & 0xF0)== 0) {
+      if ((action & 0xF0)== 0)
+      {
 	CX_reg(context) = 0;
 	SET_CFLAG(context);
 	dprintf_int(stddeb, "int21: extended open/create: failed, file dosen't exist\n");
@@ -511,39 +491,6 @@
 }
 
 
-static int INT21_RenameFile( CONTEXT *context )
-{
-    const char *newname, *oldname;
-    char *buffer;
-
-    /* FIXME: should not rename over an existing file */
-    dprintf_int(stddeb,"int21: renaming %s to %s\n",
-                (char *)PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)),
-                (char *)PTR_SEG_OFF_TO_LIN(ES_reg(context),DI_reg(context)));
-	
-    oldname = DOSFS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),
-                                                DX_reg(context)), TRUE );
-    if (!oldname) return 0;
-    buffer = xstrdup( oldname );
-    newname = DOSFS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(ES_reg(context),
-                                                   DI_reg(context)), FALSE );
-    if (!newname)
-    {
-        free( buffer );
-        return 0;
-    }
-    
-    if (rename( buffer, newname) == -1)
-    {
-        FILE_SetDosError();
-        free( buffer );
-        return 0;
-    }
-    free( buffer );
-    return 1;
-}
-
-
 static void INT21_ChangeDir( CONTEXT *context )
 {
     int drive;
@@ -566,22 +513,27 @@
 
 static int INT21_FindFirst( CONTEXT *context )
 {
-    const char *path, *unixPath, *mask;
     char *p;
+    const char *path;
+    DOS_FULL_NAME full_name;
     FINDFILE_DTA *dta = (FINDFILE_DTA *)GetCurrentDTA();
 
     path = (const char *)PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
     dta->unixPath = NULL;
-    if (!(unixPath = DOSFS_GetUnixFileName( path, FALSE )))
+    if (!DOSFS_GetFullName( path, FALSE, &full_name ))
     {
         AX_reg(context) = DOS_ExtendedError;
         SET_CFLAG(context);
         return 0;
     }
-    dta->unixPath = xstrdup( unixPath );
+    dta->unixPath = xstrdup( full_name.long_name );
     p = strrchr( dta->unixPath, '/' );
     *p = '\0';
-    if (!(mask = DOSFS_ToDosFCBFormat( p + 1 )))
+
+    /* Note: terminating NULL in dta->mask overwrites dta->search_attr
+     *       (doesn't matter as it is set below anyway)
+     */
+    if (!DOSFS_ToDosFCBFormat( p + 1, dta->mask ))
     {
         free( dta->unixPath );
         dta->unixPath = NULL;
@@ -590,7 +542,6 @@
         SET_CFLAG(context);
         return 0;
     }
-    memcpy( dta->mask, mask, sizeof(dta->mask) );
     dta->drive = (path[0] && (path[1] == ':')) ? toupper(path[0]) - 'A'
                                                : DRIVE_GetCurrentDrive();
     dta->count = 0;
@@ -709,25 +660,19 @@
 {
     BYTE *fcb = (BYTE *)PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context));
     FINDFILE_FCB *pFCB;
-    BYTE attr;
-    char buffer[] = "A:.";
-    const char *unixPath;
+    LPCSTR root, cwd;
+    int drive;
 
-    if (*fcb == 0xff)
-    {
-        attr = fcb[6];
-        pFCB = (FINDFILE_FCB *)(fcb + 7);
-    }
-    else
-    {
-        attr = 0;
-        pFCB = (FINDFILE_FCB *)fcb;
-    }
-
-    buffer[0] += DOS_GET_DRIVE( pFCB->drive );
-    pFCB->unixPath = NULL;
-    if (!(unixPath = DOSFS_GetUnixFileName( buffer, TRUE ))) return 0;
-    pFCB->unixPath = xstrdup( unixPath );
+    if (*fcb == 0xff) pFCB = (FINDFILE_FCB *)(fcb + 7);
+    else pFCB = (FINDFILE_FCB *)fcb;
+    drive = DOS_GET_DRIVE( pFCB->drive );
+    root = DRIVE_GetRoot( drive );
+    cwd  = DRIVE_GetUnixCwd( drive );
+    pFCB->unixPath = HeapAlloc( SystemHeap, 0, strlen(root)+strlen(cwd)+2 );
+    if (!pFCB->unixPath) return 0;
+    strcpy( pFCB->unixPath, root );
+    strcat( pFCB->unixPath, "/" );
+    strcat( pFCB->unixPath, cwd );
     pFCB->count = 0;
     return 1;
 }
@@ -758,7 +703,7 @@
                                   DOS_GET_DRIVE( pFCB->drive ), attr,
                                   pFCB->count, &entry )))
     {
-        free( pFCB->unixPath );
+        HeapFree( SystemHeap, 0, pFCB->unixPath );
         pFCB->unixPath = NULL;
         return 0;
     }
@@ -933,21 +878,6 @@
 } 
 
 
-static int INT21_GetFileAttribute( CONTEXT * context )
-{
-    const char *unixName;
-    BY_HANDLE_FILE_INFORMATION info;
-
-    unixName = DOSFS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)), TRUE );
-    if (!unixName) return 0;
-    if (!FILE_Stat( unixName, &info )) return 0;
-    CX_reg(context) = info.dwFileAttributes;
-    dprintf_int( stddeb, "INT21_GetFileAttributes(%s) = 0x%x\n",
-                 unixName, CX_reg(context) );
-    return 1;
-}
-
-
 extern void LOCAL_PrintHeap (WORD ds);
 
 /***********************************************************************
@@ -1086,7 +1016,7 @@
         break;
 
     case 0x2a: /* GET SYSTEM DATE */
-        GetSystemDate(context);
+        INT21_GetSystemDate(context);
         break;
 
     case 0x2b: /* SET SYSTEM DATE */
@@ -1284,14 +1214,24 @@
         switch (AL_reg(context))
         {
         case 0x00:
-            if (!INT21_GetFileAttribute(context))
+            AX_reg(context) = (WORD)GetFileAttributes32A(
+                                          PTR_SEG_OFF_TO_LIN(DS_reg(context),
+                                                             DX_reg(context)));
+            if (AX_reg(context) == 0xffff)
             {
                 AX_reg(context) = DOS_ExtendedError;
                 SET_CFLAG(context);
             }
+            else CX_reg(context) = AX_reg(context);
             break;
         case 0x01:
-            RESET_CFLAG(context);
+            if (!SetFileAttributes32A( PTR_SEG_OFF_TO_LIN(DS_reg(context),
+                                                          DX_reg(context)),
+                                       CX_reg(context) ))
+            {
+                AX_reg(context) = DOS_ExtendedError;
+                SET_CFLAG(context);
+            }
             break;
         }
         break;
@@ -1466,7 +1406,8 @@
         break;
 
     case 0x56: /* "RENAME" - RENAME FILE */
-        if (!INT21_RenameFile(context))
+        if (!MoveFile32A( PTR_SEG_OFF_TO_LIN(DS_reg(context),DX_reg(context)),
+                          PTR_SEG_OFF_TO_LIN(ES_reg(context),DI_reg(context))))
         {
             AX_reg(context) = DOS_ExtendedError;
             SET_CFLAG(context);
@@ -1576,19 +1517,15 @@
 
     case 0x60: /* "TRUENAME" - CANONICALIZE FILENAME OR PATH */
         {
-            const char *truename = DOSFS_GetDosTrueName( PTR_SEG_OFF_TO_LIN(DS_reg(context),SI_reg(context) ), FALSE );
-            if (!truename)
+            if (!GetFullPathName32A( PTR_SEG_OFF_TO_LIN(DS_reg(context),
+                                                        SI_reg(context)), 128,
+                                     PTR_SEG_OFF_TO_LIN(ES_reg(context),
+                                                        DI_reg(context)),NULL))
             {
                 AX_reg(context) = DOS_ExtendedError;
                 SET_CFLAG(context);
             }
-            else
-            {
-                lstrcpyn32A( PTR_SEG_OFF_TO_LIN( ES_reg(context),
-                                                 DI_reg(context) ),
-                             truename, 128 );
-                AX_reg(context) = 0;
-            }
+            else AX_reg(context) = 0;
         }
         break;
 
diff --git a/multimedia/audio.c b/multimedia/audio.c
index b71b1d2..a822632 100644
--- a/multimedia/audio.c
+++ b/multimedia/audio.c
@@ -138,7 +138,7 @@
 						lpstrElementName);
 		if (strlen(lpstrElementName) > 0) {
 			strcpy(str, lpstrElementName);
-			AnsiUpper(str);
+			CharUpper32A(str);
 			MCIWavDev[wDevID].hFile = mmioOpen(str, NULL, 
 				MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_EXCLUSIVE);
 			if (MCIWavDev[wDevID].hFile == 0) {
diff --git a/multimedia/mcianim.c b/multimedia/mcianim.c
index ef0262d..ceef8bf 100644
--- a/multimedia/mcianim.c
+++ b/multimedia/mcianim.c
@@ -85,7 +85,7 @@
 						lpstrElementName);
 		if (strlen(lpstrElementName) > 0) {
 			strcpy(str, lpstrElementName);
-			AnsiUpper(str);
+			CharUpper32A(str);
 			}
 		}
 	memcpy(&AnimDev[wDevID].openParms, lpParms, sizeof(MCI_OPEN_PARMS));
diff --git a/multimedia/mcistring.c b/multimedia/mcistring.c
index 219c3f8..93fa060 100644
--- a/multimedia/mcistring.c
+++ b/multimedia/mcistring.c
@@ -2115,7 +2115,7 @@
 	*dev++='\0';
 	args=strchr(dev,' ');
 	if (args!=NULL) *args++='\0';
-	AnsiUpper(dev);
+	CharUpper32A(dev);
 	if (args!=NULL) {
 		char	*s;
 		i=1;/* nrofkeywords = nrofspaces+1 */
diff --git a/multimedia/midi.c b/multimedia/midi.c
index df4065f..addbf16 100644
--- a/multimedia/midi.c
+++ b/multimedia/midi.c
@@ -300,7 +300,7 @@
 		dprintf_midi(stddeb, "MIDI_mciOpen // MCI_OPEN_ELEMENT '%s' !\n", lpstrElementName);
 		if (strlen(lpstrElementName) > 0) {
 			strcpy(str, lpstrElementName);
-			AnsiUpper(str);
+			CharUpper32A(str);
 			MCIMidiDev[wDevID].hFile = mmioOpen(str, NULL, 
 				MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_EXCLUSIVE);
 			if (MCIMidiDev[wDevID].hFile == 0) {
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index a669a23..6cb620c 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -587,7 +587,7 @@
 		t=strrchr(s,'.');
 		if (t) {
 			GetProfileString32A("mci extensions",t+1,"*",str,sizeof(str));
-			AnsiUpper(str);
+			CharUpper32A(str);
 			if (strcmp(str, "CDAUDIO") == 0) {
 				uDevTyp = MCI_DEVTYPE_CD_AUDIO;
 			} else
@@ -636,7 +636,7 @@
 				(char*)PTR_SEG_TO_LIN(lpParms->lpstrDeviceType)
 			);
 			strcpy(str, PTR_SEG_TO_LIN(lpParms->lpstrDeviceType));
-			AnsiUpper(str);
+			CharUpper32A(str);
 			if (strcmp(str, "CDAUDIO") == 0) {
 				uDevTyp = MCI_DEVTYPE_CD_AUDIO;
 			} else
@@ -829,11 +829,8 @@
 {
 	char	str[128];
 	dprintf_mci(stddeb, "mciGetDeviceID(%s)\n", lpstrName);
-	if (lpstrName != NULL) {
-		strcpy(str, lpstrName);
-		AnsiUpper(str);
-		if (strcmp(str, "ALL") == 0) return MCI_ALL_DEVICE_ID;
-		}
+	if (lpstrName && !lstrcmpi32A(lpstrName, "ALL"))
+            return MCI_ALL_DEVICE_ID;
 	return 0;
 }
 
diff --git a/objects/font.c b/objects/font.c
index 945b380..07b95a6 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -280,7 +280,6 @@
     if (!*font->lfFaceName)
       ParseFontParms(*names, 2, font->lfFaceName , LF_FACESIZE-1);
     /* we need a font name for function GetTextFace() even if there isn't one ;-) */  
-    /*AnsiUpper(font->lfFaceName);*/
 
     fontStruct = XLoadQueryFont( display, *names );
     XFreeFontNames( names );
@@ -1372,7 +1371,6 @@
     dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
 
     ParseFontParms(names[i], 2, str, sizeof(str));
-/*    AnsiUpper(str);*/
     strcpy(lpNewFont->lfFaceName, str);
     ParseFontParms(names[i], 8, str, sizeof(str));
     lpNewFont->lfHeight = atoi(str) / 10;
@@ -1535,7 +1533,6 @@
   }
   lpOldName = NULL;
   strcpy(FaceName,lpLF->lfFaceName);
-/*  AnsiUpper(lpLF->lfFaceName);*/
 
   if (lpLogFontList[0] == NULL) InitFontsList();
   for(i = 0; lpLogFontList[i] != NULL; i++) {
@@ -1616,7 +1613,6 @@
   }
   lpOldName = NULL;
   strcpy(FaceName,lpLF->lfFaceName);
-/*  AnsiUpper(lpLF->lfFaceName);*/
 
   if (lpLogFontList[0] == NULL) InitFontsList();
   for(i = 0; lpLogFontList[i] != NULL; i++) {
@@ -1694,7 +1690,6 @@
   }
   lpOldName = NULL;
   lpszFamily = HEAP_strdupWtoA( GetProcessHeap(), 0, lpLF->lfFaceName );
-  AnsiUpper(lpszFamily);
   if (lpLogFontList[0] == NULL) InitFontsList();
   for(i = 0; lpLogFontList[i] != NULL; i++) {
     /* lfCharSet */
diff --git a/objects/metafile.c b/objects/metafile.c
index 9610dc6..c7ee25d 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -337,47 +337,6 @@
     return TRUE;
 }
 
-/*******************************************************************
- *   MF_GetDIBitsPointer    [internal helper for e.g. PlayMetaFileRecord]
- *
- * Returns offset to DIB bits or 0 if error
- * (perhaps should be moved to (objects/dib.c ?)
- */
-static LPSTR MF_GetDIBitsPointer(LPBITMAPINFO info)
-{
-      int offset;
-      if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
-	{
-        if (info->bmiHeader.biClrUsed)
-	  {
-	  if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
-	    offset = info->bmiHeader.biClrUsed * 4;
-          else
-	    offset = (1 << info->bmiHeader.biBitCount) * 4;
-          }
-        else
-	  offset = (1 << info->bmiHeader.biBitCount) * 4;
-	}
-      else if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
-	{
-	if (info->bmiHeader.biClrUsed)
-	  {
-	  if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
-	    offset = info->bmiHeader.biClrUsed * 3;
-          else
-	    offset = (1 << info->bmiHeader.biBitCount) * 3;
-          }
-        else
-	  offset = (1 << info->bmiHeader.biBitCount) * 3;
-	}
-      else
-	{
-	fprintf(stderr,"Unknown size for BITMAPHEADER in MetaFile!\n");
-	return NULL;
-	}
-      return (LPSTR)info + info->bmiHeader.biSize + offset; 
-}
-
 
 /******************************************************************
  *         PlayMetaFileRecord      GDI.176
@@ -431,7 +390,6 @@
     case META_SETSTRETCHBLTMODE:
 	SetStretchBltMode16(hdc, *(mr->rdParam));
 	break;
-
     case META_SETTEXTCOLOR:
 	SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1)));
 	break;
@@ -675,9 +633,8 @@
     case META_STRETCHDIB:
       {
        LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[11]);
-       LPSTR bits = MF_GetDIBitsPointer(info);
-       if (bits)
-        StretchDIBits16(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8],
+       LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[2] );
+       StretchDIBits16(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8],
                        mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
                        mr->rdParam[4],mr->rdParam[3],bits,info,
                        mr->rdParam[2],MAKELONG(mr->rdParam[0],mr->rdParam[1]));
@@ -687,9 +644,8 @@
     case META_DIBSTRETCHBLT:
       {
        LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[10]); 
-       LPSTR bits = MF_GetDIBitsPointer(info);
-       if (bits)
-         StretchDIBits16(hdc,mr->rdParam[9],mr->rdParam[8],mr->rdParam[7],
+       LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParam[2] );
+       StretchDIBits16(hdc,mr->rdParam[9],mr->rdParam[8],mr->rdParam[7],
                        mr->rdParam[6],mr->rdParam[5],mr->rdParam[4],
                        mr->rdParam[3],mr->rdParam[2],bits,info,
                        DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1]));
@@ -728,6 +684,32 @@
        DeleteDC32(hdcSrc);		    
       }
       break;
+#define META_UNIMP(x) case x: fprintf(stderr,"PlayMetaFileRecord:record type "#x" not implemented.\n");break;
+    META_UNIMP(META_SETTEXTCHAREXTRA)
+    META_UNIMP(META_SETTEXTJUSTIFICATION)
+    META_UNIMP(META_FILLREGION)
+    META_UNIMP(META_FRAMEREGION)
+    META_UNIMP(META_INVERTREGION)
+    META_UNIMP(META_PAINTREGION)
+    META_UNIMP(META_SELECTCLIPREGION)
+    META_UNIMP(META_DRAWTEXT)
+    META_UNIMP(META_SETDIBTODEV)
+    META_UNIMP(META_ANIMATEPALETTE)
+    META_UNIMP(META_SETPALENTRIES)
+    META_UNIMP(META_RESIZEPALETTE)
+    META_UNIMP(META_DIBBITBLT)
+    META_UNIMP(META_DIBCREATEPATTERNBRUSH)
+    META_UNIMP(META_EXTFLOODFILL)
+    META_UNIMP(META_RESETDC)
+    META_UNIMP(META_STARTDOC)
+    META_UNIMP(META_STARTPAGE)
+    META_UNIMP(META_ENDPAGE)
+    META_UNIMP(META_ABORTDOC)
+    META_UNIMP(META_ENDDOC)
+    META_UNIMP(META_CREATEBRUSH)
+    META_UNIMP(META_CREATEBITMAPINDIRECT)
+    META_UNIMP(META_CREATEBITMAP)
+#undef META_UNIMP
 
     default:
 	fprintf(stddeb,"PlayMetaFileRecord: Unknown record type %x\n",
@@ -1242,8 +1224,9 @@
     dprintf_metafile(stddeb,"MF_StretchBltViaDIB->len = %ld  rop=%lx  PixYPM=%ld Caps=%d\n",
                len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
     if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT)lpBMI->biHeight,
-              MF_GetDIBitsPointer((LPBITMAPINFO)lpBMI),    /* DIB bits */
-              (LPBITMAPINFO)lpBMI,DIB_RGB_COLORS))         /* DIB info structure */ 
+                  (LPSTR)lpBMI + DIB_BitmapInfoSize( (BITMAPINFO *)lpBMI,
+                                                     DIB_RGB_COLORS ),
+                  (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS))
 #else
     len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
diff --git a/objects/region.c b/objects/region.c
index 40dae541..18e808d 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -322,8 +322,46 @@
 HRGN16 CreatePolyPolygonRgn16( const POINT16 * points, const INT16 * count,
                                INT16 nbpolygons, INT16 mode )
 {
+    int		i,nrofpts;
+    LPINT32	count32;
+    LPPOINT32	points32;
+    HRGN32	ret;
+
+    nrofpts=0;
+    for (i=nbpolygons;i--;)
+	nrofpts+=count[i];
+    points32 = (LPPOINT32)HeapAlloc( GetProcessHeap(), 0,
+                                     nrofpts*sizeof(POINT32) );
+    for (i=nrofpts;i--;)
+    	CONV_POINT16TO32( &(points[i]), &(points32[i]) );
+    count32 = (LPINT32)HeapAlloc( GetProcessHeap(), 0, 
+                                  sizeof(INT32)*nbpolygons );
+    for (i=nbpolygons;i--;)
+    	count32[i]=count[i];
+    ret = CreatePolyPolygonRgn32(points32,count32,nbpolygons,mode);
+    HeapFree( GetProcessHeap(), 0, count32 );
+    HeapFree( GetProcessHeap(), 0, points32 );
+    return ret;
+}
+
+
+/***********************************************************************
+ *           CreatePolygonRgn32    (GDI32.58)
+ */
+HRGN32 CreatePolygonRgn32( const POINT32 *points, INT32 count, INT32 mode )
+{
+    return CreatePolyPolygonRgn32( points, &count, 1, mode );
+}
+
+
+/***********************************************************************
+ *           CreatePolyPolygonRgn32    (GDI32.57)
+ */
+HRGN32 CreatePolyPolygonRgn32( const POINT32 * points, const INT32 * count,
+                               INT32 nbpolygons, INT32 mode )
+{
     RGNOBJ * obj;
-    HRGN16 hrgn;
+    HRGN32 hrgn;
     int i, j, maxPoints;
     XPoint *xpoints, *pt;
     Region xrgn;
@@ -334,14 +372,15 @@
     for (i = maxPoints = 0; i < nbpolygons; i++)
 	if (maxPoints < count[i]) maxPoints = count[i];
     if (!maxPoints) return 0;
-    if (!(xpoints = (XPoint *) malloc( sizeof(XPoint) * maxPoints )))
-	return 0;
+    if (!(xpoints = (XPoint *)HeapAlloc( GetProcessHeap(), 0,
+                                         sizeof(XPoint) * maxPoints )))
+        return 0;
 
       /* Allocate region */
 
     if (!(hrgn = GDI_AllocObject( sizeof(RGNOBJ), REGION_MAGIC )))
     {
-	free( xpoints );
+	HeapFree( GetProcessHeap(), 0, xpoints );
 	return 0;
     }
     obj = (RGNOBJ *) GDI_HEAP_LIN_ADDR( hrgn );
@@ -363,7 +402,7 @@
 	if (!xrgn)
         {
             if (obj->xrgn) XDestroyRegion( obj->xrgn );
-            free( xpoints );
+            HeapFree( GetProcessHeap(), 0, xpoints );
             GDI_FreeObject( hrgn );
             return 0;
         }
@@ -378,7 +417,7 @@
 	else obj->xrgn = xrgn;
     }
 
-    free( xpoints );
+    HeapFree( GetProcessHeap(), 0, xpoints );
     return hrgn;
 }
 
diff --git a/objects/text.c b/objects/text.c
index e5977c4..d178a35 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -6,13 +6,10 @@
  */
 
 #include <stdlib.h>
-#include <X11/Xatom.h>
 #include "windows.h"
 #include "dc.h"
 #include "gdi.h"
-#include "callback.h"
 #include "heap.h"
-#include "metafile.h"
 #include "stddebug.h"
 /* #define DEBUG_TEXT */
 #include "debug.h"
@@ -31,9 +28,6 @@
 static int spacewidth;
 static int prefix_offset;
 
-extern int CLIPPING_IntersectClipRect( DC * dc, short left, short top,
-                                         short right, short bottom, UINT16 flags);
-
 static const char *TEXT_NextLine( HDC16 hdc, const char *str, int *count,
                                   char *dest, int *len, int width, WORD format)
 {
@@ -326,240 +320,18 @@
                      const RECT16 *lprect, LPCSTR str, UINT16 count,
                      const INT16 *lpDx )
 {
-    HRGN32	hRgnClip = 0;
-    int 	dir, ascent, descent, i;
-    XCharStruct info;
-    XFontStruct *font;
-    RECT16 	rect;
+    BOOL32	ret;
+    int		i;
+    RECT32	rect32;
+    LPINT32	lpdx32 = lpDx?(LPINT32)xmalloc(sizeof(INT32)*count):NULL;
 
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC );
-	if (!dc) return FALSE;
-	MF_ExtTextOut( dc, x, y, flags, lprect, str, count, lpDx );
-	return TRUE;
-    }
+    if (lprect)	CONV_RECT16TO32(lprect,&rect32);
+    if (lpdx32)	for (i=count;i--;) lpdx32[i]=lpDx[i];
+    ret = ExtTextOut32A(hdc,x,y,flags,lprect?&rect32:NULL,str,count,lpdx32);
+    if (lpdx32) free(lpdx32);
+    return ret;
 
-    if (!DC_SetupGCForText( dc )) return TRUE;
-    font = dc->u.x.font.fstruct;
 
-    dprintf_text(stddeb,"ExtTextOut: hdc=%04x %d,%d '%*.*s', %d  flags=%d\n",
-            hdc, x, y, count, count, str, count, flags);
-    if (lprect != NULL) dprintf_text(stddeb, "\trect=(%d,%d- %d,%d)\n",
-                                     lprect->left, lprect->top,
-                                     lprect->right, lprect->bottom );
-
-      /* Setup coordinates */
-
-    if (dc->w.textAlign & TA_UPDATECP)
-    {
-	x = dc->w.CursPosX;
-	y = dc->w.CursPosY;
-    }
-
-    if (flags & (ETO_OPAQUE | ETO_CLIPPED))  /* there's a rectangle */
-    {
-        if (!lprect)  /* not always */
-        {
-            SIZE16 sz;
-            if (flags & ETO_CLIPPED)  /* Can't clip with no rectangle */
-	      return FALSE;
-	    if (!GetTextExtentPoint16( hdc, str, count, &sz ))
-	      return FALSE;
-	    rect.left   = XLPTODP( dc, x );
-	    rect.right  = XLPTODP( dc, x+sz.cx );
-	    rect.top    = YLPTODP( dc, y );
-	    rect.bottom = YLPTODP( dc, y+sz.cy );
-	}
-	else
-	{
-	    rect.left   = XLPTODP( dc, lprect->left );
-	    rect.right  = XLPTODP( dc, lprect->right );
-	    rect.top    = YLPTODP( dc, lprect->top );
-	    rect.bottom = YLPTODP( dc, lprect->bottom );
-	}
-	if (rect.right < rect.left) SWAP_INT( rect.left, rect.right );
-	if (rect.bottom < rect.top) SWAP_INT( rect.top, rect.bottom );
-    }
-
-    x = XLPTODP( dc, x );
-    y = YLPTODP( dc, y );
-
-    dprintf_text(stddeb,"\treal coord: x=%i, y=%i, rect=(%d,%d-%d,%d)\n",
-			  x, y, rect.left, rect.top, rect.right, rect.bottom);
-
-      /* Draw the rectangle */
-
-    if (flags & ETO_OPAQUE)
-    {
-        XSetForeground( display, dc->u.x.gc, dc->w.backgroundPixel );
-        XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
-                        dc->w.DCOrgX + rect.left, dc->w.DCOrgY + rect.top,
-                        rect.right-rect.left, rect.bottom-rect.top );
-    }
-    if (!count) return TRUE;  /* Nothing more to do */
-
-      /* Compute text starting position */
-
-    XTextExtents( font, str, count, &dir, &ascent, &descent, &info );
-
-    if (lpDx) /* have explicit character cell x offsets */
-    {
-	/* sum lpDx array and add the width of last character */
-
-        info.width = XTextWidth( font, str + count - 1, 1) + dc->w.charExtra;
-        if (str[count-1] == (char)dc->u.x.font.metrics.tmBreakChar)
-            info.width += dc->w.breakExtra;
-
-        for (i = 0; i < count; i++) info.width += lpDx[i];
-    }
-    else
-       info.width += count*dc->w.charExtra + dc->w.breakExtra*dc->w.breakCount;
-
-    switch( dc->w.textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER) )
-    {
-      case TA_LEFT:
- 	  if (dc->w.textAlign & TA_UPDATECP)
-	      dc->w.CursPosX = XDPTOLP( dc, x + info.width );
-	  break;
-      case TA_RIGHT:
-	  x -= info.width;
-	  if (dc->w.textAlign & TA_UPDATECP) dc->w.CursPosX = XDPTOLP( dc, x );
-	  break;
-      case TA_CENTER:
-	  x -= info.width / 2;
-	  break;
-    }
-
-    switch( dc->w.textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
-    {
-      case TA_TOP:
-	  y += font->ascent;
-	  break;
-      case TA_BOTTOM:
-	  y -= font->descent;
-	  break;
-      case TA_BASELINE:
-	  break;
-    }
-
-      /* Set the clip region */
-
-    if (flags & ETO_CLIPPED)
-    {
-        hRgnClip = dc->w.hClipRgn;
-        CLIPPING_IntersectClipRect( dc, rect.left, rect.top, rect.right,
-                                    rect.bottom, CLIP_INTERSECT|CLIP_KEEPRGN );
-    }
-
-      /* Draw the text background if necessary */
-
-    if (dc->w.backgroundMode != TRANSPARENT)
-    {
-          /* If rectangle is opaque and clipped, do nothing */
-        if (!(flags & ETO_CLIPPED) || !(flags & ETO_OPAQUE))
-        {
-              /* Only draw if rectangle is not opaque or if some */
-              /* text is outside the rectangle */
-            if (!(flags & ETO_OPAQUE) ||
-                (x < rect.left) ||
-                (x + info.width >= rect.right) ||
-                (y-font->ascent < rect.top) ||
-                (y+font->descent >= rect.bottom))
-            {
-                XSetForeground( display, dc->u.x.gc, dc->w.backgroundPixel );
-                XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
-                                dc->w.DCOrgX + x,
-                                dc->w.DCOrgY + y - font->ascent,
-                                info.width,
-                                font->ascent + font->descent );
-            }
-        }
-    }
-    
-    /* Draw the text (count > 0 verified) */
-
-    XSetForeground( display, dc->u.x.gc, dc->w.textPixel );
-    if (!dc->w.charExtra && !dc->w.breakExtra && !lpDx)
-    {
-        XDrawString( display, dc->u.x.drawable, dc->u.x.gc, 
-                     dc->w.DCOrgX + x, dc->w.DCOrgY + y, str, count );
-    }
-    else  /* Now the fun begins... */
-    {
-        XTextItem *items, *pitem;
-	int delta;
-
-	/* allocate max items */
-
-        pitem = items = xmalloc( count * sizeof(XTextItem) );
-        delta = i = 0;
-        while (i < count)
-        {
-	    /* initialize text item with accumulated delta */
-
-            pitem->chars  = (char *)str + i;
-	    pitem->delta  = delta; 
-            pitem->nchars = 0;
-            pitem->font   = None;
-            delta = 0;
-
-	    /* stuff characters into the same XTextItem until new delta 
-	     * becomes  non-zero */
-
-	    do
-            {
-                if (lpDx) delta += lpDx[i] - XTextWidth( font, str + i, 1);
-                else
-                {
-                    delta += dc->w.charExtra;
-                    if (str[i] == (char)dc->u.x.font.metrics.tmBreakChar)
-                        delta += dc->w.breakExtra;
-                }
-                pitem->nchars++;
-            } 
-	    while ((++i < count) && !delta);
-            pitem++;
-        }
-
-        XDrawText( display, dc->u.x.drawable, dc->u.x.gc,
-                   dc->w.DCOrgX + x, dc->w.DCOrgY + y, items, pitem - items );
-        free( items );
-    }
-
-      /* Draw underline and strike-out if needed */
-
-    if (dc->u.x.font.metrics.tmUnderlined)
-    {
-	long linePos, lineWidth;       
-	if (!XGetFontProperty( font, XA_UNDERLINE_POSITION, &linePos ))
-	    linePos = font->descent-1;
-	if (!XGetFontProperty( font, XA_UNDERLINE_THICKNESS, &lineWidth ))
-	    lineWidth = 0;
-	else if (lineWidth == 1) lineWidth = 0;
-	XSetLineAttributes( display, dc->u.x.gc, lineWidth,
-			    LineSolid, CapRound, JoinBevel ); 
-        XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
-		   dc->w.DCOrgX + x, dc->w.DCOrgY + y + linePos,
-		   dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y + linePos );
-    }
-    if (dc->u.x.font.metrics.tmStruckOut)
-    {
-	long lineAscent, lineDescent;
-	if (!XGetFontProperty( font, XA_STRIKEOUT_ASCENT, &lineAscent ))
-	    lineAscent = font->ascent / 3;
-	if (!XGetFontProperty( font, XA_STRIKEOUT_DESCENT, &lineDescent ))
-	    lineDescent = -lineAscent;
-	XSetLineAttributes( display, dc->u.x.gc, lineAscent + lineDescent,
-			    LineSolid, CapRound, JoinBevel ); 
-	XDrawLine( display, dc->u.x.drawable, dc->u.x.gc,
-		   dc->w.DCOrgX + x, dc->w.DCOrgY + y - lineAscent,
-		   dc->w.DCOrgX + x + info.width, dc->w.DCOrgY + y - lineAscent );
-    }
-
-    if (flags & ETO_CLIPPED) SelectClipRgn32( hdc, hRgnClip );
-    return TRUE;
 }
 
 
@@ -570,15 +342,9 @@
                       const RECT32 *lprect, LPCSTR str, UINT32 count,
                       const INT32 *lpDx )
 {
-    RECT16 rect16;
-
-    if (lpDx) fprintf( stderr, "ExtTextOut32A: lpDx not implemented\n" );
-    if (!lprect)
-        return ExtTextOut16( (HDC16)hdc, (INT16)x, (INT16)y, (UINT16)flags,
-                             NULL, str, (UINT16)count, NULL );
-    CONV_RECT32TO16( lprect, &rect16 );
-    return ExtTextOut16( (HDC16)hdc, (INT16)x, (INT16)y, (UINT16)flags,
-                         &rect16, str, (UINT16)count, NULL );
+    DC * dc = DC_GetDCPtr( hdc );
+    return dc && dc->funcs->pExtTextOut && 
+    	   dc->funcs->pExtTextOut(dc,x,y,flags,lprect,str,count,lpDx);
 }
 
 
diff --git a/rc/Makefile.in b/rc/Makefile.in
index 7e19f99..36f04e2 100644
--- a/rc/Makefile.in
+++ b/rc/Makefile.in
@@ -3,7 +3,7 @@
 TOPOBJDIR = ..
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
-PROGRAMS  = winerc
+PROGRAMS  = winerc@PROGEXT@
 MODULE    = none
 
 C_SRCS     = winerc.c
@@ -14,7 +14,7 @@
 @MAKE_RULES@
 
 $(PROGRAMS): $(OBJS)
-	$(CC) $(CFLAGS) -o winerc $(OBJS) $(LEXLIB)
+	$(CC) $(CFLAGS) -o winerc@PROGEXT@ $(OBJS) $(LEXLIB)
 
 y.tab.c y.tab.h: parser.y
 	$(YACC) -d -t $(SRCDIR)/parser.y
diff --git a/scheduler/process.c b/scheduler/process.c
index c225531..a7e1991 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -5,7 +5,11 @@
  */
 
 #include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
 #include "process.h"
+#include "file.h"
 #include "heap.h"
 #include "task.h"
 #include "winerror.h"
@@ -234,10 +238,54 @@
 }
 
 
+static int pstr_cmp( const void *ps1, const void *ps2 )
+{
+    return lstrcmpi32A( *(LPSTR *)ps1, *(LPSTR *)ps2 );
+}
+
+/***********************************************************************
+ *           PROCESS_FillEnvDB
+ */
+static BOOL32 PROCESS_FillEnvDB( PDB32 *pdb, TDB *pTask )
+{
+    LPSTR p, env;
+    INT32 count = 0;
+    LPSTR *pp, *array = NULL;
+
+    /* Copy the Win16 environment, sorting it in the process */
+
+    env = p = GlobalLock16( pTask->pdb.environment );
+    for (p = env; *p; p += strlen(p) + 1) count++;
+    pdb->env_db->env_size = (p - env) + 1;
+    pdb->env_db->environ = HeapAlloc( pdb->heap, 0, pdb->env_db->env_size );
+    if (!pdb->env_db->environ) goto error;
+    if (!(array = HeapAlloc( pdb->heap, 0, count * sizeof(array[0]) )))
+        goto error;
+    for (p = env, pp = array; *p; p += strlen(p) + 1) *pp++ = p;
+    qsort( array, count, sizeof(LPSTR), pstr_cmp );
+    p = pdb->env_db->environ;
+    for (pp = array; count; count--, pp++)
+    {
+        strcpy( p, *pp );
+        p += strlen(p) + 1;
+    }
+    *p = '\0';
+    HeapFree( pdb->heap, 0, array );
+    array = NULL;
+
+    return TRUE;
+
+error:
+    if (array) HeapFree( pdb->heap, 0, array );
+    if (pdb->env_db->environ) HeapFree( pdb->heap, 0, pdb->env_db->environ );
+    return FALSE;
+}
+
+
 /***********************************************************************
  *           PROCESS_Create
  */
-PDB32 *PROCESS_Create(void)
+PDB32 *PROCESS_Create( TDB *pTask )
 {
     PDB32 *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB32) );
     if (!pdb) return NULL;
@@ -251,16 +299,17 @@
     pdb->parent          = pCurrentProcess;
     pdb->group           = pdb;
     pdb->priority        = 8;  /* Normal */
+    pdb->heap_list       = pdb->heap;
     InitializeCriticalSection( &pdb->crit_section );
     if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) goto error;
-    if (!(pdb->env_DB = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
+    if (!(pdb->env_db = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
         goto error;
     if (!(pdb->handle_table = PROCESS_AllocHandleTable( pdb ))) goto error;
-    pdb->heap_list       = pdb->heap;
+    if (!PROCESS_FillEnvDB( pdb, pTask )) goto error;
     return pdb;
 
 error:
-    if (pdb->env_DB) HeapFree( pdb->heap, 0, pdb->env_DB );
+    if (pdb->env_db) HeapFree( pdb->heap, 0, pdb->env_db );
     if (pdb->handle_table) HeapFree( pdb->system_heap, 0, pdb->handle_table );
     if (pdb->heap) HeapDestroy( pdb->heap );
     DeleteCriticalSection( &pdb->crit_section );
@@ -285,7 +334,7 @@
     /* Free everything */
 
     ptr->type = K32OBJ_UNKNOWN;
-    HeapFree( pdb->heap, 0, pdb->env_DB );
+    HeapFree( pdb->heap, 0, pdb->env_db );
     HeapFree( pdb->system_heap, 0, pdb->handle_table );
     HeapDestroy( pdb->heap );
     DeleteCriticalSection( &pdb->crit_section );
@@ -321,6 +370,178 @@
 
 
 /***********************************************************************
+ *      GetEnvironmentStrings32A   (KERNEL32.210) (KERNEL32.211)
+ */
+LPSTR GetEnvironmentStrings32A(void)
+{
+    assert( pCurrentProcess );
+    return pCurrentProcess->env_db->environ;
+}
+
+
+/***********************************************************************
+ *      GetEnvironmentStrings32W   (KERNEL32.212)
+ */
+LPWSTR GetEnvironmentStrings32W(void)
+{
+    INT32 size;
+    LPWSTR ret, pW;
+    LPSTR pA;
+
+    assert( pCurrentProcess );
+    size = HeapSize( GetProcessHeap(), 0, pCurrentProcess->env_db->environ );
+    if (!(ret = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) )))
+        return NULL;
+    pA = pCurrentProcess->env_db->environ;
+    pW = ret;
+    while (*pA)
+    {
+        lstrcpyAtoW( pW, pA );
+        size = strlen(pA);
+        pA += size + 1;
+        pW += size + 1;
+    }
+    *pW = 0;
+    return ret;
+}
+
+
+/***********************************************************************
+ *           FreeEnvironmentStrings32A   (KERNEL32.141)
+ */
+BOOL32 FreeEnvironmentStrings32A( LPSTR ptr )
+{
+    assert( pCurrentProcess );
+    if (ptr != pCurrentProcess->env_db->environ)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           FreeEnvironmentStrings32W   (KERNEL32.142)
+ */
+BOOL32 FreeEnvironmentStrings32W( LPWSTR ptr )
+{
+    assert( pCurrentProcess );
+    return HeapFree( GetProcessHeap(), 0, ptr );
+}
+
+
+/***********************************************************************
+ *          GetEnvironmentVariable32A   (KERNEL32.213)
+ */
+DWORD GetEnvironmentVariable32A( LPCSTR name, LPSTR value, DWORD size )
+{
+    LPSTR p;
+    INT32 len, res;
+
+    assert( pCurrentProcess );
+    p = pCurrentProcess->env_db->environ;
+    if (!name || !*name)
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return 0;
+    }
+    len = strlen(name);
+    while (*p)
+    {
+        res = lstrncmpi32A( name, p, len );
+        if (res < 0) goto not_found;
+        if (!res && (p[len] == '=')) break;
+        p += strlen(p) + 1;
+    }
+    if (!*p) goto not_found;
+    if (value) lstrcpyn32A( value, p + len + 1, size );
+    return strlen(p);
+not_found:
+    return 0;  /* FIXME: SetLastError */
+}
+
+
+/***********************************************************************
+ *           GetEnvironmentVariable32W   (KERNEL32.214)
+ */
+DWORD GetEnvironmentVariable32W( LPCWSTR nameW, LPWSTR valW, DWORD size )
+{
+    LPSTR name = HEAP_strdupWtoA( GetProcessHeap(), 0, nameW );
+    LPSTR val  = HeapAlloc( GetProcessHeap(), 0, size );
+    DWORD res  = GetEnvironmentVariable32A( name, val, size );
+    HeapFree( GetProcessHeap(), 0, name );
+    if (valW) lstrcpynAtoW( valW, val, size );
+    HeapFree( GetProcessHeap(), 0, val );
+    return res;
+}
+
+
+/***********************************************************************
+ *           SetEnvironmentVariable32A   (KERNEL32.484)
+ */
+BOOL32 SetEnvironmentVariable32A( LPCSTR name, LPCSTR value )
+{
+    INT32 size, len, res;
+    LPSTR p, env, new_env;
+
+    assert( pCurrentProcess );
+    env = p = pCurrentProcess->env_db->environ;
+
+    /* Find a place to insert the string */
+
+    res = -1;
+    len = strlen(name);
+    while (*p)
+    {
+        res = lstrncmpi32A( name, p, len );
+        if (res < 0) break;
+        if (!res && (p[len] == '=')) break;
+        res = 1;
+        p += strlen(p) + 1;
+    }
+    if (!value && res)  /* Value to remove doesn't exist already */
+        return FALSE;
+
+    /* Realloc the buffer */
+
+    len = value ? strlen(name) + strlen(value) + 2 : 0;
+    if (!res) len -= strlen(p) + 1;  /* The name already exists */
+    size = pCurrentProcess->env_db->env_size + len;
+    if (!(new_env = HeapReAlloc( GetProcessHeap(), 0, env, size )))
+        return FALSE;
+    p = new_env + (p - env);
+
+    /* Set the new string */
+
+    memmove( p + len, p, pCurrentProcess->env_db->env_size - (p-new_env) );
+    if (value)
+    {
+        strcpy( p, name );
+        strcat( p, "=" );
+        strcat( p, value );
+    }
+    pCurrentProcess->env_db->env_size = size;
+    pCurrentProcess->env_db->environ  = new_env;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           SetEnvironmentVariable32W   (KERNEL32.485)
+ */
+BOOL32 SetEnvironmentVariable32W( LPCWSTR name, LPCWSTR value )
+{
+    LPSTR nameA  = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
+    LPSTR valueA = HEAP_strdupWtoA( GetProcessHeap(), 0, value );
+    BOOL32 ret = SetEnvironmentVariable32A( nameA, valueA );
+    HeapFree( GetProcessHeap(), 0, nameA );
+    HeapFree( GetProcessHeap(), 0, valueA );
+    return ret;
+}
+
+
+/***********************************************************************
  *           GetProcessHeap    (KERNEL32.259)
  */
 HANDLE32 GetProcessHeap(void)
@@ -328,3 +549,141 @@
     if (!pCurrentProcess) return SystemHeap;  /* For the boot-up code */
     return pCurrentProcess->heap;
 }
+
+
+/***********************************************************************
+ *           GetThreadLocale    (KERNEL32.295)
+ */
+LCID GetThreadLocale(void)
+{
+    return pCurrentProcess->locale;
+}
+
+
+/***********************************************************************
+ *           SetPriorityClass   (KERNEL32.503)
+ */
+BOOL32 SetPriorityClass( HANDLE32 hprocess, DWORD priorityclass )
+{
+    PDB32	*pdb;
+
+    pdb = (PDB32*)PROCESS_GetObjPtr(hprocess,K32OBJ_PROCESS);
+    if (!pdb) return FALSE;
+    switch (priorityclass)
+    {
+    case NORMAL_PRIORITY_CLASS:
+    	pdb->priority = 0x00000008;
+	break;
+    case IDLE_PRIORITY_CLASS:
+    	pdb->priority = 0x00000004;
+	break;
+    case HIGH_PRIORITY_CLASS:
+    	pdb->priority = 0x0000000d;
+	break;
+    case REALTIME_PRIORITY_CLASS:
+    	pdb->priority = 0x00000018;
+    	break;
+    default:
+    	fprintf(stderr,"SetPriorityClass: unknown priority class %ld\n",priorityclass);
+	break;
+    }
+    K32OBJ_DecCount((K32OBJ*)pdb);
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           GetPriorityClass   (KERNEL32.250)
+ */
+DWORD GetPriorityClass(HANDLE32 hprocess)
+{
+    PDB32	*pdb;
+    DWORD	ret;
+
+    pdb = (PDB32*)PROCESS_GetObjPtr(hprocess,K32OBJ_PROCESS);
+    ret = 0;
+    if (pdb)
+    {
+    	switch (pdb->priority)
+        {
+	case 0x00000008:
+	    ret = NORMAL_PRIORITY_CLASS;
+	    break;
+	case 0x00000004:
+	    ret = IDLE_PRIORITY_CLASS;
+	    break;
+	case 0x0000000d:
+	    ret = HIGH_PRIORITY_CLASS;
+	    break;
+	case 0x00000018:
+	    ret = REALTIME_PRIORITY_CLASS;
+	    break;
+	default:
+	    fprintf(stderr,"GetPriorityClass: unknown priority %ld\n",pdb->priority);
+	}
+	K32OBJ_DecCount((K32OBJ*)pdb);
+    }
+    return ret;
+}
+
+
+/***********************************************************************
+ *           GetStdHandle    (KERNEL32.276)
+ *
+ * FIXME: These should be allocated when a console is created, or inherited
+ *        from the parent.
+ */
+HANDLE32 GetStdHandle( DWORD std_handle )
+{
+    HFILE32 hFile;
+    int fd;
+
+    assert( pCurrentProcess );
+    switch(std_handle)
+    {
+    case STD_INPUT_HANDLE:
+        if (pCurrentProcess->env_db->hStdin)
+            return pCurrentProcess->env_db->hStdin;
+        fd = 0;
+        break;
+    case STD_OUTPUT_HANDLE:
+        if (pCurrentProcess->env_db->hStdout)
+            return pCurrentProcess->env_db->hStdout;
+        fd = 1;
+        break;
+    case STD_ERROR_HANDLE:
+        if (pCurrentProcess->env_db->hStderr)
+            return pCurrentProcess->env_db->hStderr;
+        fd = 2;
+        break;
+    default:
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return INVALID_HANDLE_VALUE32;
+    }
+    hFile = FILE_DupUnixHandle( fd );
+    if (hFile != HFILE_ERROR32) FILE_SetFileType( hFile, FILE_TYPE_CHAR );
+    return hFile;
+}
+
+
+/***********************************************************************
+ *           SetStdHandle    (KERNEL32.506)
+ */
+BOOL32 SetStdHandle( DWORD std_handle, HANDLE32 handle )
+{
+    assert( pCurrentProcess );
+    switch(std_handle)
+    {
+    case STD_INPUT_HANDLE:
+        pCurrentProcess->env_db->hStdin = handle;
+        return TRUE;
+    case STD_OUTPUT_HANDLE:
+        pCurrentProcess->env_db->hStdout = handle;
+        return TRUE;
+    case STD_ERROR_HANDLE:
+        pCurrentProcess->env_db->hStderr = handle;
+        return TRUE;
+    }
+    SetLastError( ERROR_INVALID_PARAMETER );
+    return FALSE;
+}
diff --git a/scheduler/thread.c b/scheduler/thread.c
index 78b71f8..acc64a1 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -83,6 +83,7 @@
 
 /***********************************************************************
  *           GetCurrentThreadId   (KERNEL32.201)
+ * Returns crypted (xor'ed) pointer to THDB in Win95.
  */
 DWORD GetCurrentThreadId(void)
 {
@@ -229,3 +230,35 @@
 {
     EAX_reg(context) = GetSelectorBase( FS_reg(context) );
 }
+
+/**********************************************************************
+ *           GetThreadPriority   (KERNEL32.296)
+ */
+INT32
+GetThreadPriority(HANDLE32 hthread) {
+    THDB *thread;
+    INT32 ret;
+    
+    ret = 0;
+    thread = (THDB*)PROCESS_GetObjPtr(hthread,K32OBJ_THREAD);
+    if (thread) {
+    	ret = thread->delta_priority;
+	K32OBJ_DecCount((K32OBJ*)thread);
+    }
+    return ret;
+}
+
+/**********************************************************************
+ *           SetThreadPriority   (KERNEL32.514)
+ */
+BOOL32
+SetThreadPriority(HANDLE32 hthread,INT32 priority) {
+    THDB *thread;
+    
+    thread = (THDB*)PROCESS_GetObjPtr(hthread,K32OBJ_THREAD);
+    if (thread) {
+	thread->delta_priority = priority;
+	K32OBJ_DecCount((K32OBJ*)thread);
+    }
+    return TRUE;
+}
diff --git a/tools/Makefile.in b/tools/Makefile.in
index c1d3f14..0116c90 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -4,7 +4,7 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 
-PROGRAMS = build makedep fnt2bdf
+PROGRAMS = build@PROGEXT@ makedep@PROGEXT@ fnt2bdf@PROGEXT@
 MODULE   = none
 
 C_SRCS = build.c makedep.c fnt2bdf.c
@@ -13,13 +13,13 @@
 
 @MAKE_RULES@
 
-build: build.o
-	$(CC) $(CFLAGS) -o build build.o
+build@PROGEXT@: build.o
+	$(CC) $(CFLAGS) -o build@PROGEXT@ build.o
 
-makedep: makedep.o
-	$(CC) $(CFLAGS) -o makedep makedep.o
+makedep@PROGEXT@: makedep.o
+	$(CC) $(CFLAGS) -o makedep@PROGEXT@ makedep.o
 
-fnt2bdf: fnt2bdf.o
-	$(CC) $(CFLAGS) -o fnt2bdf fnt2bdf.o
+fnt2bdf@PROGEXT@: fnt2bdf.o
+	$(CC) $(CFLAGS) -o fnt2bdf@PROGEXT@ fnt2bdf.o
 
 ### Dependencies:
diff --git a/tools/build.c b/tools/build.c
index 95812d9..894b73c 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -2,6 +2,7 @@
  * Copyright 1993 Robert J. Amstadt
  * Copyright 1995 Martin von Loewis
  * Copyright 1995, 1996 Alexandre Julliard
+ * Copyright 1997 Eric Youngdale
  */
 
 #ifndef WINELIB
@@ -11,6 +12,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <unistd.h>
+
 #include "windows.h"
 #include "winnt.h"
 #include "winerror.h"  /* for ERROR_CALL_NOT_IMPLEMENTED */
@@ -105,6 +107,7 @@
 {
     ORD_TYPE    type;
     int         offset;
+    int		lineno;
     char        name[80];
     union
     {
@@ -519,6 +522,7 @@
         return -1;
     }
     strcpy( odp->name, token );
+    odp->lineno = Line;
 
     switch(odp->type)
     {
@@ -968,13 +972,25 @@
  *
  * Build a Win32 assembly file from a spec file.
  */
-static int BuildSpec32File( FILE *outfile )
+static int BuildSpec32File( char * specfile, FILE *outfile )
 {
     ORDDEF *odp;
     int i, module_size, len;
     char buffer[1024];
 
     fprintf( outfile, "/* File generated automatically; do not edit! */\n" );
+    fprintf( outfile, "\t.file\t\"%s\"\n", specfile );
+#ifdef __GNUC__
+    getcwd(buffer, sizeof(buffer));
+
+    /*
+     * The stabs help the internal debugger as they are an indication that it
+     * is sensible to step into a thunk/trampoline.
+     */
+    fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
+    fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", specfile);
+#endif
+
     fprintf( outfile, "\t.text\n" );
     fprintf( outfile, "\t.align 4\n" );
     fprintf( outfile, "Code_Start:\n\n" );
@@ -992,7 +1008,17 @@
         case TYPE_STUB:
         case TYPE_REGISTER:
             fprintf( outfile, "/* %s.%d (%s) */\n", DLLName, i, odp->name);
+#ifdef __GNUC__
+	    fprintf( outfile, ".stabs \"%s_%d:F1\",36,0,%d,%s_%d\n", 
+		     DLLName, i,
+		     odp->lineno, DLLName, i);
+#endif
+
             fprintf( outfile, "%s_%d:\n", DLLName, i );
+#ifdef __GNUC__
+	    fprintf( outfile, ".stabn 68,0,%d,0\n", odp->lineno);
+#endif
+
             fprintf( outfile, "\tpushl %%ebp\n" );
             fprintf( outfile, "\tpushl $" PREFIX "%s\n",odp->u.func.link_name);
             fprintf( outfile, "\tcall " PREFIX "CallFrom32_%s_%d\n",
@@ -1112,6 +1138,11 @@
     fprintf( outfile, "\t.long Code_Start\n" );       /* Code start */
     fprintf( outfile, "\t.long Functions\n" );        /* Functions */
     fprintf( outfile, "\t.long FuncNames\n" );        /* Function names */
+#ifdef __GNUC__
+    fprintf( outfile, "\t.text\n");
+    fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
+    fprintf( outfile, ".Letext:\n");
+#endif
     return 0;
 }
 
@@ -1121,7 +1152,7 @@
  *
  * Build a Win16 assembly file from a spec file.
  */
-static int BuildSpec16File( FILE *outfile )
+static int BuildSpec16File( char * specfile, FILE *outfile )
 {
     ORDDEF *odp;
     int i;
@@ -1259,9 +1290,9 @@
     switch(SpecType)
     {
     case SPEC_WIN16:
-        return BuildSpec16File( outfile );
+        return BuildSpec16File( specname, outfile );
     case SPEC_WIN32:
-        return BuildSpec32File( outfile );
+        return BuildSpec32File( specname, outfile );
     default:
         fprintf( stderr, "%s: Missing 'type' declaration\n", specname );
         return -1;
@@ -1293,6 +1324,9 @@
     /* Function header */
 
     fprintf( outfile, "\n\t.align 4\n" );
+#ifdef __GNUC__
+    fprintf( outfile, ".stabs \"CallTo32_LargeStack:F1\",36,0,0,CallTo32_LargeStack\n");
+#endif
     fprintf( outfile, "\t.globl " PREFIX "CallTo32_LargeStack\n" );
     fprintf( outfile, PREFIX "CallTo32_LargeStack:\n" );
     
@@ -1454,6 +1488,7 @@
              CONTEXTOFFSET(Esi) - sizeof(CONTEXT) );
     fprintf( outfile, "\tmovl %%edi,%d(%%ebx)\n",
              CONTEXTOFFSET(Edi) - sizeof(CONTEXT) );
+
     fprintf( outfile, "\tmovzwl -10(%%ebp),%%eax\n" ); /* Get %ds from stack*/
     fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
              CONTEXTOFFSET(SegDs) - sizeof(CONTEXT) );
@@ -1463,7 +1498,6 @@
     fprintf( outfile, "\tpushfl\n" );
     fprintf( outfile, "\tpopl %d(%%ebx)\n",
              CONTEXTOFFSET(EFlags) - sizeof(CONTEXT) );
-#if 0
     fprintf( outfile, "\tmovzwl 0(%%ebp),%%eax\n" ); /* Get %bp from stack */
     fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
              CONTEXTOFFSET(Ebp) - sizeof(CONTEXT) );
@@ -1473,12 +1507,16 @@
     fprintf( outfile, "\tmovzwl 4(%%ebp),%%eax\n" ); /* Get %cs from stack */
     fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
              CONTEXTOFFSET(SegCs) - sizeof(CONTEXT) );
-    fprintf( outfile, "\tmovl %%fs,%d(%%ebx)\n",
+    fprintf( outfile, "\tmovw %%fs,%%ax\n" );
+    fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
              CONTEXTOFFSET(SegFs) - sizeof(CONTEXT) );
-    fprintf( outfile, "\tmovl %%gs,%d(%%ebx)\n",
+    fprintf( outfile, "\tmovw %%gs,%%ax\n" );
+    fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
              CONTEXTOFFSET(SegGs) - sizeof(CONTEXT) );
-    fprintf( outfile, "\tmovl %%ss,%d(%%ebx)\n",
+    fprintf( outfile, "\tmovw %%ss,%%ax\n" );
+    fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
              CONTEXTOFFSET(SegSs) - sizeof(CONTEXT) );
+#if 0
     fprintf( outfile, "\tfsave %d(%%ebx)\n",
              CONTEXTOFFSET(FloatSave) - sizeof(CONTEXT) );
 #endif
@@ -1565,6 +1603,10 @@
     /* Function header */
 
     fprintf( outfile, "\n\t.align 4\n" );
+#ifdef __GNUC__
+    fprintf( outfile, ".stabs \"CallFrom16_%s:F1\",36,0,0,CallFrom16_%s\n", 
+	     profile, profile);
+#endif
     fprintf( outfile, "\t.globl " PREFIX "CallFrom16_%s\n", profile );
     fprintf( outfile, PREFIX "CallFrom16_%s:\n", profile );
 
@@ -1780,6 +1822,10 @@
     /* Function header */
 
     fprintf( outfile, "\n\t.align 4\n" );
+#ifdef __GNUC__
+    fprintf( outfile, ".stabs \"CallTo16_%s:F1\",36,0,0,CallTo16_%s\n", 
+	     profile, profile);
+#endif
     fprintf( outfile, "\t.globl " PREFIX "CallTo16_%s\n", profile );
     fprintf( outfile, PREFIX "CallTo16_%s:\n", profile );
 
@@ -1813,8 +1859,7 @@
     if (debugging)
     {
         /* Push the address of the first argument */
-        fprintf( outfile, "\tmovl %%ebx,%%eax\n" );
-        fprintf( outfile, "\taddl $12,%%eax\n" );
+        fprintf( outfile, "\tleal 12(%%ebx),%%eax\n" );
         fprintf( outfile, "\tpushl $%d\n", reg_func ? 8 : strlen(args) );
         fprintf( outfile, "\tpushl %%eax\n" );
         fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo16\n" );
@@ -1969,30 +2014,40 @@
 /*******************************************************************
  *         BuildContext32
  *
- * Build the context structure on the stack.
+ * Build the CONTEXT structure on the stack.
  */
 static void BuildContext32( FILE *outfile )
 {
     /* Build the context structure */
 
+    fprintf( outfile, "\tpushw $0\n" );
+    fprintf( outfile, "\tpushw %%ss\n" );
+    fprintf( outfile, "\tpushl %%eax\n" );  /* %esp */
     fprintf( outfile, "\tpushfl\n" );
-    fprintf( outfile, "\tsubl $%d,%%esp\n", sizeof(CONTEXT) );
-    fprintf( outfile, "\tmovl %%eax,%d(%%esp)\n", CONTEXTOFFSET(Eax) );
-    fprintf( outfile, "\tmovl %%ebx,%d(%%esp)\n", CONTEXTOFFSET(Ebx) );
-    fprintf( outfile, "\tmovl %%ecx,%d(%%esp)\n", CONTEXTOFFSET(Ecx) );
-    fprintf( outfile, "\tmovl %%edx,%d(%%esp)\n", CONTEXTOFFSET(Edx) );
-    fprintf( outfile, "\tmovl %%esi,%d(%%esp)\n", CONTEXTOFFSET(Esi) );
-    fprintf( outfile, "\tmovl %%edi,%d(%%esp)\n", CONTEXTOFFSET(Edi) );
+    fprintf( outfile, "\tpushw $0\n" );
+    fprintf( outfile, "\tpushw %%cs\n" );
+    fprintf( outfile, "\tsubl $8,%%esp\n" );  /* %eip + %ebp */
 
-    fprintf( outfile, "\tmovl %d(%%esp),%%eax\n", sizeof(CONTEXT) );
-    fprintf( outfile, "\tmovl %%eax,%d(%%esp)\n", CONTEXTOFFSET(EFlags) );
+    fprintf( outfile, "\tpushl %%eax\n" );
+    fprintf( outfile, "\tpushl %%ecx\n" );
+    fprintf( outfile, "\tpushl %%edx\n" );
+    fprintf( outfile, "\tpushl %%ebx\n" );
+    fprintf( outfile, "\tpushl %%esi\n" );
+    fprintf( outfile, "\tpushl %%edi\n" );
 
-    fprintf( outfile, "\tmovl %%cs,%d(%%esp)\n", CONTEXTOFFSET(SegCs) );
-    fprintf( outfile, "\tmovl %%ds,%d(%%esp)\n", CONTEXTOFFSET(SegDs) );
-    fprintf( outfile, "\tmovl %%es,%d(%%esp)\n", CONTEXTOFFSET(SegEs) );
-    fprintf( outfile, "\tmovl %%fs,%d(%%esp)\n", CONTEXTOFFSET(SegFs) );
-    fprintf( outfile, "\tmovl %%gs,%d(%%esp)\n", CONTEXTOFFSET(SegGs) );
-    fprintf( outfile, "\tmovl %%ss,%d(%%esp)\n", CONTEXTOFFSET(SegSs) );
+    fprintf( outfile, "\txorl %%eax,%%eax\n" );
+    fprintf( outfile, "\tmovw %%ds,%%ax\n" );
+    fprintf( outfile, "\tpushl %%eax\n" );
+    fprintf( outfile, "\tmovw %%es,%%ax\n" );
+    fprintf( outfile, "\tpushl %%eax\n" );
+    fprintf( outfile, "\tmovw %%fs,%%ax\n" );
+    fprintf( outfile, "\tpushl %%eax\n" );
+    fprintf( outfile, "\tmovw %%gs,%%ax\n" );
+    fprintf( outfile, "\tpushl %%eax\n" );
+
+    fprintf( outfile, "\tsubl $%d,%%esp\n",
+             sizeof(FLOATING_SAVE_AREA) + 6 * sizeof(DWORD) /* DR regs */ );
+    fprintf( outfile, "\tpushl $0x0001001f\n" );  /* ContextFlags */
 
     fprintf( outfile, "\tfsave %d(%%esp)\n", CONTEXTOFFSET(FloatSave) );
 
@@ -2021,32 +2076,33 @@
     fprintf( outfile, "\tleal %d(%%ebp),%%esp\n", -sizeof(CONTEXT)-12 );
     fprintf( outfile, "\tfrstor %d(%%esp)\n", CONTEXTOFFSET(FloatSave) );
 
-    fprintf( outfile, "\tmovl %d(%%esp),%%ebx\n", CONTEXTOFFSET(Ebx) );
-    fprintf( outfile, "\tmovl %d(%%esp),%%ecx\n", CONTEXTOFFSET(Ecx) );
-    fprintf( outfile, "\tmovl %d(%%esp),%%edx\n", CONTEXTOFFSET(Edx) );
-    fprintf( outfile, "\tmovl %d(%%esp),%%esi\n", CONTEXTOFFSET(Esi) );
-    fprintf( outfile, "\tmovl %d(%%esp),%%edi\n", CONTEXTOFFSET(Edi) );
-
-    fprintf( outfile, "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(EFlags) );
-    fprintf( outfile, "\tmovl %%eax,%d(%%esp)\n", sizeof(CONTEXT) );
-
-/*    fprintf( outfile, "\tmovl %d(%%esp),%%cs\n", CONTEXTOFFSET(SegCs) ); */
-    fprintf( outfile, "\tmovl %d(%%esp),%%ds\n", CONTEXTOFFSET(SegDs) );
-    fprintf( outfile, "\tmovl %d(%%esp),%%es\n", CONTEXTOFFSET(SegEs) );
-    fprintf( outfile, "\tmovl %d(%%esp),%%fs\n", CONTEXTOFFSET(SegFs) );
-    fprintf( outfile, "\tmovl %d(%%esp),%%gs\n", CONTEXTOFFSET(SegGs) );
-
     fprintf( outfile, "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(Eip) );
     fprintf( outfile, "\tmovl %%eax,4(%%ebp)\n" ); /* %eip at time of call */
     fprintf( outfile, "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(Ebp) );
     fprintf( outfile, "\tmovl %%eax,0(%%ebp)\n" ); /* %ebp at time of call */
+    fprintf( outfile, "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(EFlags) );
+    fprintf( outfile, "\tmovl %%eax,%d(%%esp)\n", sizeof(CONTEXT) );
 
-/*    fprintf( outfile, "\tmovl %d(%%esp),%%ss\n", CONTEXTOFFSET(SegSs) ); */
-/*    fprintf( outfile, "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(Esp) ); */
+    fprintf( outfile, "\taddl $%d,%%esp\n",
+             sizeof(FLOATING_SAVE_AREA) + 7 * sizeof(DWORD) );
+    fprintf( outfile, "\tpopl %%eax\n" );
+    fprintf( outfile, "\tmovw %%ax,%%gs\n" );
+    fprintf( outfile, "\tpopl %%eax\n" );
+    fprintf( outfile, "\tmovw %%ax,%%fs\n" );
+    fprintf( outfile, "\tpopl %%eax\n" );
+    fprintf( outfile, "\tmovw %%ax,%%es\n" );
+    fprintf( outfile, "\tpopl %%eax\n" );
+    fprintf( outfile, "\tmovw %%ax,%%ds\n" );
 
-    fprintf( outfile, "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(Eax) );
+    fprintf( outfile, "\tpopl %%edi\n" );
+    fprintf( outfile, "\tpopl %%esi\n" );
+    fprintf( outfile, "\tpopl %%ebx\n" );
+    fprintf( outfile, "\tpopl %%edx\n" );
+    fprintf( outfile, "\tpopl %%ecx\n" );
+    fprintf( outfile, "\tpopl %%eax\n" );
 
-    fprintf( outfile, "\taddl $%d,%%esp\n", sizeof(CONTEXT) );
+    fprintf( outfile, "\taddl $%d,%%esp\n",
+             6 * sizeof(DWORD) /* %ebp + %eip + %cs + %efl + %esp + %ss */ );
     fprintf( outfile, "\tpopfl\n" );
 }
 
@@ -2095,6 +2151,10 @@
     /* Function header */
 
     fprintf( outfile, "\n\t.align 4\n" );
+#ifdef __GNUC__
+    fprintf( outfile, ".stabs \"CallFrom32_%s:F1\",36,0,0,CallFrom32_%s\n", 
+	     profile, profile);
+#endif
     fprintf( outfile, "\t.globl " PREFIX "CallFrom32_%s\n", profile );
     fprintf( outfile, PREFIX "CallFrom32_%s:\n", profile );
 
@@ -2182,6 +2242,10 @@
     /* Function header */
 
     fprintf( outfile, "\n\t.align 4\n" );
+#ifdef __GNUC__
+    fprintf( outfile, ".stabs \"CallTo32_%d:F1\",36,0,0,CallTo32_%d\n", 
+	     args, args);
+#endif
     fprintf( outfile, "\t.globl " PREFIX "CallTo32_%d\n", args );
     fprintf( outfile, PREFIX "CallTo32_%d:\n", args );
 
@@ -2240,15 +2304,31 @@
  *
  * Build the 16-bit-to-Wine callbacks
  */
-static int BuildCallFrom16( FILE *outfile, int argc, char *argv[] )
+static int BuildCallFrom16( FILE *outfile, char * outname, int argc, char *argv[] )
 {
     int i;
+    char buffer[1024];
 
     /* File header */
 
     fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
     fprintf( outfile, "\t.text\n" );
 
+#ifdef __GNUC__
+    fprintf( outfile, "\t.file\t\"%s\"\n", outname );
+    getcwd(buffer, sizeof(buffer));
+
+    /*
+     * The stabs help the internal debugger as they are an indication that it
+     * is sensible to step into a thunk/trampoline.
+     */
+    fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
+    fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", outname);
+    fprintf( outfile, "\t.text\n" );
+    fprintf( outfile, "\t.align 4\n" );
+    fprintf( outfile, "Code_Start:\n\n" );
+#endif
+
     /* Build the 32-bit large stack callback */
 
     BuildCall32LargeStack( outfile );
@@ -2268,6 +2348,13 @@
             fprintf( outfile, "\t.ascii \"%s\\0\"\n", argv[i] + 5 );
         }
     }
+
+#ifdef __GNUC__
+    fprintf( outfile, "\t.text\n");
+    fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
+    fprintf( outfile, ".Letext:\n");
+#endif
+
     return 0;
 }
 
@@ -2277,14 +2364,31 @@
  *
  * Build the Wine-to-16-bit callbacks
  */
-static int BuildCallTo16( FILE *outfile, int argc, char *argv[] )
+static int BuildCallTo16( FILE *outfile, char * outname, int argc, char *argv[] )
 {
+    char buffer[1024];
     int i;
 
     /* File header */
 
     fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
     fprintf( outfile, "\t.text\n" );
+
+#ifdef __GNUC__
+    fprintf( outfile, "\t.file\t\"%s\"\n", outname );
+    getcwd(buffer, sizeof(buffer));
+
+    /*
+     * The stabs help the internal debugger as they are an indication that it
+     * is sensible to step into a thunk/trampoline.
+     */
+    fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
+    fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", outname);
+    fprintf( outfile, "\t.text\n" );
+    fprintf( outfile, "\t.align 4\n" );
+    fprintf( outfile, "Code_Start:\n\n" );
+#endif
+
     fprintf( outfile, "\t.globl " PREFIX "CALLTO16_Start\n" );
     fprintf( outfile, PREFIX "CALLTO16_Start:\n" );
 
@@ -2298,6 +2402,13 @@
 
     fprintf( outfile, "\t.globl " PREFIX "CALLTO16_End\n" );
     fprintf( outfile, PREFIX "CALLTO16_End:\n" );
+
+#ifdef __GNUC__
+    fprintf( outfile, "\t.text\n");
+    fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
+    fprintf( outfile, ".Letext:\n");
+#endif
+
     return 0;
 }
 
@@ -2307,8 +2418,9 @@
  *
  * Build the 32-bit-to-Wine callbacks
  */
-static int BuildCallFrom32( FILE *outfile, int argc, char *argv[] )
+static int BuildCallFrom32( FILE *outfile, char * outname, int argc, char *argv[] )
 {
+    char buffer[1024];
     int i;
 
     /* File header */
@@ -2316,9 +2428,31 @@
     fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
     fprintf( outfile, "\t.text\n" );
 
+#ifdef __GNUC__
+    fprintf( outfile, "\t.file\t\"%s\"\n", outname );
+    getcwd(buffer, sizeof(buffer));
+
+    /*
+     * The stabs help the internal debugger as they are an indication that it
+     * is sensible to step into a thunk/trampoline.
+     */
+    fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
+    fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", outname);
+    fprintf( outfile, "\t.text\n" );
+    fprintf( outfile, "\t.align 4\n" );
+    fprintf( outfile, "Code_Start:\n\n" );
+#endif
+
     /* Build the callback functions */
 
     for (i = 2; i < argc; i++) BuildCallFrom32Func( outfile, argv[i] );
+
+#ifdef __GNUC__
+    fprintf( outfile, "\t.text\n");
+    fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
+    fprintf( outfile, ".Letext:\n");
+#endif
+
     return 0;
 }
 
@@ -2328,8 +2462,10 @@
  *
  * Build the Wine-to-32-bit callbacks
  */
-static int BuildCallTo32( FILE *outfile, int argc, char *argv[] )
+static int BuildCallTo32( FILE *outfile, char * outname, 
+			  int argc, char *argv[] )
 {
+    char buffer[1024];
     int i;
 
     /* File header */
@@ -2337,9 +2473,37 @@
     fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
     fprintf( outfile, "\t.text\n" );
 
+    /*
+     * Throw in a couple of stabs.  The internal debugger doesn't really
+     * care about trying to step through this crap, but we use the file
+     * names as an indication that we should just step through it to whatever
+     * is on the other side.
+     */
+#ifdef __GNUC__
+    fprintf( outfile, "\t.file\t\"%s\"\n", outname );
+    getcwd(buffer, sizeof(buffer));
+
+    /*
+     * The stabs help the internal debugger as they are an indication that it
+     * is sensible to step into a thunk/trampoline.
+     */
+    fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
+    fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", outname);
+    fprintf( outfile, "\t.text\n" );
+    fprintf( outfile, "\t.align 4\n" );
+    fprintf( outfile, "Code_Start:\n\n" );
+#endif
+
     /* Build the callback functions */
 
     for (i = 2; i < argc; i++) BuildCallTo32Func( outfile, atoi(argv[i]) );
+
+#ifdef __GNUC__
+    fprintf( outfile, "\t.text\n");
+    fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
+    fprintf( outfile, ".Letext:\n");
+#endif
+
     return 0;
 }
 
@@ -2385,13 +2549,13 @@
     if (!strcmp( argv[1], "-spec" ))
         res = BuildSpec( outfile, argc, argv );
     else if (!strcmp( argv[1], "-callfrom16" ))
-        res = BuildCallFrom16( outfile, argc, argv );
+        res = BuildCallFrom16( outfile, outname, argc, argv );
     else if (!strcmp( argv[1], "-callto16" ))
-        res = BuildCallTo16( outfile, argc, argv );
+        res = BuildCallTo16( outfile, outname, argc, argv );
     else if (!strcmp( argv[1], "-callfrom32" ))
-        res = BuildCallFrom32( outfile, argc, argv );
+        res = BuildCallFrom32( outfile, outname, argc, argv );
     else if (!strcmp( argv[1], "-callto32" ))
-        res = BuildCallTo32( outfile, argc, argv );
+        res = BuildCallTo32( outfile, outname, argc, argv );
     else
     {
         fclose( outfile );
diff --git a/tools/fnt2bdf.c b/tools/fnt2bdf.c
index f391b79..8e889e6 100644
--- a/tools/fnt2bdf.c
+++ b/tools/fnt2bdf.c
@@ -121,7 +121,7 @@
   fnt_fontS	cpe_font_struct; 
   int     	ic=0, t;
 
-  bcopy(file_buffer, (char *) &cpe_font_struct.hdr, sizeof(fnt_hdrS));
+  memcpy((char *) &cpe_font_struct.hdr, file_buffer, sizeof(fnt_hdrS));
 
   /* check font header */
 
diff --git a/tools/make_os2.sh b/tools/make_os2.sh
new file mode 100644
index 0000000..7564c5e
--- /dev/null
+++ b/tools/make_os2.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+# GCCLOAD not needed, but recommended...
+#GCCLOAD=5
+CC=gcc
+YACC="bison -y"
+LEX="flex -olex.yy.c"
+RANLIB="ar -s"
+PROGEXT=".exe"
+export CC YACC LEX RANLIB PROGEXT
+./configure --x-includes=$X11ROOT/XFree86/include -x-libraries=$X11ROOT/XFree86/lib
diff --git a/win32/code_page.c b/win32/code_page.c
index 463505f..60673db 100644
--- a/win32/code_page.c
+++ b/win32/code_page.c
@@ -82,8 +82,10 @@
 	int dont_copy= (dstlen==0);
 	if(page!=GetACP() && page!=CP_OEMCP && page!=CP_ACP)
 		fprintf(stdnimp,"Conversion in CP %d not supported\n",page);
+#if 0
 	if(flags)
 		fprintf(stdnimp,"WideCharToMultiByte flags %lx not supported\n",flags);
+#endif
 	if(used)
 		*used=0;
 	while(srclen && (dont_copy || dstlen))
@@ -112,7 +114,10 @@
 }
 
 
-BOOL32 IsDBCSLeadByteEx(UINT32 codepage, BYTE testchar)
+/***********************************************************************
+ *           IsDBCSLeadByteEx   (KERNEL32.359)
+ */
+BOOL32 IsDBCSLeadByteEx( UINT32 codepage, BYTE testchar )
 {
     CPINFO cpinfo;
     int i;
@@ -128,7 +133,20 @@
     return FALSE;
 }
 
-BOOL32 IsDBCSLeadByte(BYTE testchar)
+
+/***********************************************************************
+ *           IsDBCSLeadByte16   (KERNEL.207)
+ */
+BOOL16 IsDBCSLeadByte16( BYTE testchar )
+{
+    return IsDBCSLeadByteEx(GetACP(), testchar);
+}
+
+
+/***********************************************************************
+ *           IsDBCSLeadByte32   (KERNEL32.358)
+ */
+BOOL32 IsDBCSLeadByte32( BYTE testchar )
 {
     return IsDBCSLeadByteEx(GetACP(), testchar);
 }
diff --git a/win32/file.c b/win32/file.c
index 165be9a..c059531 100644
--- a/win32/file.c
+++ b/win32/file.c
@@ -20,7 +20,6 @@
 #include "file.h"
 #include "heap.h"
 #include "handle32.h"
-#include "dos_fs.h"
 #include "xmalloc.h"
 #include "stddebug.h"
 #define DEBUG_WIN32
@@ -66,7 +65,8 @@
         SetLastError(ErrnoToLastError(errno));
         return INVALID_HANDLE_VALUE32;
     }
-    filemap_obj=(FILEMAP_OBJECT *)CreateKernelObject(sizeof(FILEMAP_OBJECT));
+    filemap_obj=(FILEMAP_OBJECT *)HeapAlloc( SystemHeap, 0,
+                                             sizeof(FILEMAP_OBJECT) );
     if(filemap_obj == NULL) {
         SetLastError(ERROR_UNKNOWN);
         return 0;
@@ -129,68 +129,6 @@
 }
 
 
-
-/***********************************************************************
- *           GetStdHandle             (KERNEL32.276)
- * FIXME: We should probably allocate filehandles for stdin/stdout/stderr
- *	  at task creation (with HFILE-handle 0,1,2 respectively) and
- *	  return them here. Or at least look, if we created them already.
- */
-HFILE32 GetStdHandle(DWORD nStdHandle)
-{
-    HFILE32 hfile;
-    int	unixfd;
-
-    switch(nStdHandle)
-    {
-        case STD_INPUT_HANDLE:
-	    unixfd = 0;
-            break;
-
-        case STD_OUTPUT_HANDLE:
-	    unixfd = 1;
-            break;
-
-        case STD_ERROR_HANDLE:
-	    unixfd = 2;
-            break;
-        default:
-            SetLastError(ERROR_INVALID_HANDLE);
-            return HFILE_ERROR32;
-    }
-    hfile = FILE_DupUnixHandle(unixfd);
-    if (hfile == HFILE_ERROR32)
-    	return HFILE_ERROR32;
-    FILE_SetFileType( hfile, FILE_TYPE_CHAR );
-    return hfile;
-}
-
-
-/***********************************************************************
- *              SetFilePointer          (KERNEL32.492)
- *
- * Luckily enough, this function maps almost directly into an lseek
- * call, the exception being the use of 64-bit offsets.
- */
-DWORD SetFilePointer(HFILE32 hFile, LONG distance, LONG *highword,
-                     DWORD method)
-{
-    LONG rc;
-    if(highword != NULL)
-    {
-        if(*highword != 0)
-        {
-            dprintf_file(stddeb, "SetFilePointer: 64-bit offsets not yet supported.\n");
-            return -1;
-        }
-    }
-
-    rc = _llseek32(hFile, distance, method);
-    if(rc == -1)
-        SetLastError(ErrnoToLastError(errno));
-    return rc;
-}
-
 /***********************************************************************
  *             WriteFile               (KERNEL32.578)
  */
@@ -354,26 +292,32 @@
  */
 BOOL32 SetFileAttributes32A(LPCSTR lpFileName, DWORD attributes)
 {
-	struct stat buf;
-	LPSTR	fn=(LPSTR)DOSFS_GetUnixFileName(lpFileName,FALSE);
+    struct stat buf;
+    DOS_FULL_NAME full_name;
 
-	dprintf_file(stddeb,"SetFileAttributes(%s,%lx)\n",lpFileName,attributes);
-	if(stat(fn,&buf)==-1) {
-		SetLastError(ErrnoToLastError(errno));
-		return FALSE;
-	}
-	if (attributes & FILE_ATTRIBUTE_READONLY) {
-		buf.st_mode &= ~0222; /* octal!, clear write permission bits */
-		attributes &= ~FILE_ATTRIBUTE_READONLY;
-	}
-	attributes &= ~(FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
-	if (attributes)
-		fprintf(stdnimp,"SetFileAttributesA(%s):%lx attribute(s) not implemented.\n",lpFileName,attributes);
-	if (-1==chmod(fn,buf.st_mode)) {
-		SetLastError(ErrnoToLastError(errno));
-		return FALSE;
-	}
-	return TRUE;
+    if (!DOSFS_GetFullName( lpFileName, TRUE, &full_name ))
+        return FALSE;
+
+    dprintf_file(stddeb,"SetFileAttributes(%s,%lx)\n",lpFileName,attributes);
+    if(stat(full_name.long_name,&buf)==-1)
+    {
+        SetLastError(ErrnoToLastError(errno));
+        return FALSE;
+    }
+    if (attributes & FILE_ATTRIBUTE_READONLY)
+    {
+        buf.st_mode &= ~0222; /* octal!, clear write permission bits */
+        attributes &= ~FILE_ATTRIBUTE_READONLY;
+    }
+    attributes &= ~(FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM);
+    if (attributes)
+        fprintf(stdnimp,"SetFileAttributesA(%s):%lx attribute(s) not implemented.\n",lpFileName,attributes);
+    if (-1==chmod(full_name.long_name,buf.st_mode))
+    {
+        SetLastError(ErrnoToLastError(errno));
+        return FALSE;
+    }
+    return TRUE;
 }
 
 /**************************************************************************
@@ -387,51 +331,6 @@
     return res;
 }
 
-/**************************************************************************
- *              MoveFileA		(KERNEL32.387)
- */
-BOOL32 MoveFile32A(LPCSTR fn1,LPCSTR fn2)
-{
-	LPSTR	ufn1;
-	LPSTR	ufn2;
-
-	dprintf_file(stddeb,"MoveFileA(%s,%s)\n",fn1,fn2);
-	ufn1 = (LPSTR)DOSFS_GetUnixFileName(fn1,FALSE);
-	if (!ufn1) {
-		SetLastError(ErrnoToLastError(ENOENT));
-		return FALSE;
-	}
-	ufn1 = xstrdup(ufn1);
-	ufn2 = (LPSTR)DOSFS_GetUnixFileName(fn2,FALSE);
-	if (!ufn2) {
-		SetLastError(ErrnoToLastError(ENOENT));
-		return FALSE;
-	}
-	ufn2 = xstrdup(ufn2);
-	if (-1==rename(ufn1,ufn2)) {
-		SetLastError(ErrnoToLastError(errno));
-		free(ufn1);
-		free(ufn2);
-		return FALSE;
-	}
-	free(ufn1);
-	free(ufn2);
-	return TRUE;
-}
-
-/**************************************************************************
- *              MoveFileW		(KERNEL32.390)
- */
-BOOL32 MoveFile32W(LPCWSTR fn1,LPCWSTR fn2)
-{
-    LPSTR afn1 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn1 );
-    LPSTR afn2 = HEAP_strdupWtoA( GetProcessHeap(), 0, fn2 );
-    BOOL32 res = MoveFile32A( afn1, afn2 );
-    HeapFree( GetProcessHeap(), 0, afn1 );
-    HeapFree( GetProcessHeap(), 0, afn2 );
-    return res;
-}
-
 VOID SetFileApisToOEM()
 {
     fprintf(stdnimp,"SetFileApisToOEM(),stub!\n");
@@ -449,38 +348,6 @@
 }
 
 
-BOOL32 CopyFile32A(LPCSTR sourcefn,LPCSTR destfn,BOOL32 failifexists)
-{
-	OFSTRUCT	of;
-	HFILE32		hf1,hf2;
-	char		buffer[2048];
-	int		lastread,curlen;
-
-	fprintf(stddeb,"CopyFile: %s -> %s\n",sourcefn,destfn);
-	hf1 = OpenFile32(sourcefn,&of,OF_READ);
-	if (hf1==HFILE_ERROR32) return TRUE;
-	if (failifexists)
-        {
-		hf2 = OpenFile32(sourcefn,&of,OF_WRITE);
-		if (hf2 != HFILE_ERROR32) return FALSE;
-		_lclose32(hf2);
-	}
-	hf2 = OpenFile32(sourcefn,&of,OF_WRITE);
-	if (hf2 == HFILE_ERROR32) return FALSE;
-	curlen = 0;
-	while ((lastread=_lread32(hf1,buffer,sizeof(buffer)))>0) {
-		curlen=0;
-		while (curlen<lastread) {
-			int res = _lwrite32(hf2,buffer+curlen,lastread-curlen);
-			if (res<=0) break;
-			curlen+=res;
-		}
-	}
-	_lclose32(hf1);
-	_lclose32(hf2);
-	return curlen > 0;
-}
-
 BOOL32
 LockFile(
 	HFILE32 hFile,DWORD dwFileOffsetLow,DWORD dwFileOffsetHigh,
diff --git a/win32/memory.c b/win32/memory.c
index e8d055c..9a22615 100644
--- a/win32/memory.c
+++ b/win32/memory.c
@@ -15,7 +15,7 @@
 #include "windows.h"
 #include "winerror.h"
 #include "winbase.h"
-#include "handle32.h"
+#include "heap.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -138,7 +138,7 @@
 
 VRANGE_OBJECT *MEMORY_AllocVrange(int start,int size)
 {
-	VRANGE_OBJECT *ret=CreateKernelObject(sizeof(VRANGE_OBJECT));
+	VRANGE_OBJECT *ret=HeapAlloc( SystemHeap, 0, sizeof(VRANGE_OBJECT));
 	MEMORY_InsertVrange(ret);
 	return ret;
 }
@@ -149,7 +149,7 @@
 	if(MEMORY_ranges==r)
 	{
 		MEMORY_ranges=r->next;
-		ReleaseKernelObject(r);
+		HeapFree( SystemHeap, 0, r );
 		return;
 	}
 	for(it=MEMORY_ranges;it;it=it->next)
@@ -160,7 +160,7 @@
 		return;
 	}
 	it->next=r->next;
-	ReleaseKernelObject(r);
+	HeapFree( SystemHeap, 0, r );
 }
 
 /***********************************************************************
diff --git a/win32/struct32.c b/win32/struct32.c
index 629a75a..7795c9e 100644
--- a/win32/struct32.c
+++ b/win32/struct32.c
@@ -11,25 +11,6 @@
 #include "stddebug.h"
 #include "debug.h"
 
-void STRUCT32_POINT32to16(const POINT32* p32, POINT16* p16)
-{
-	p16->x = p32->x;
-	p16->y = p32->y;
-}
-
-void STRUCT32_POINT16to32(const POINT16* p16, POINT32* p32)
-{
-	p32->x = p16->x;
-	p32->y = p16->y;
-}
-
-void STRUCT32_SIZE16to32(const SIZE16* p16, SIZE32* p32) 
-  
-{
-        p32->cx = p16->cx;
-        p32->cy = p16->cy;
-}
-
 void STRUCT32_MSG16to32(const MSG16 *msg16,MSG32 *msg32)
 {
 	msg32->hwnd=(DWORD)msg16->hwnd;
@@ -52,22 +33,6 @@
 	msg16->pt.y=msg32->pt.y;
 }
 
-void STRUCT32_RECT32to16(const RECT32* r32, RECT16 *r16)
-{
-	r16->left = r32->left;
-	r16->right = r32->right;
-	r16->top = r32->top;
-	r16->bottom = r32->bottom;
-}
-
-void STRUCT32_RECT16to32(const RECT16* r16, RECT32 *r32)
-{
-	r32->left = r16->left;
-	r32->right = r16->right;
-	r32->top = r16->top;
-	r32->bottom = r16->bottom;
-}
-
 void STRUCT32_MINMAXINFO32to16( const MINMAXINFO32 *from, MINMAXINFO16 *to )
 {
     CONV_POINT32TO16( &from->ptReserved,     &to->ptReserved );
diff --git a/windows/defdlg.c b/windows/defdlg.c
index 2c6e1e9..a4808e9 100644
--- a/windows/defdlg.c
+++ b/windows/defdlg.c
@@ -24,10 +24,10 @@
     if (IsChild( hwndDlg, hwndPrev ))
     {
         if (SendMessage16( hwndPrev, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
-            SendMessage16( hwndPrev, EM_SETSEL, TRUE, MAKELONG( -1, 0 ) );
+            SendMessage16( hwndPrev, EM_SETSEL16, TRUE, MAKELONG( -1, 0 ) );
     }
     if (SendMessage16( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
-        SendMessage16( hwndCtrl, EM_SETSEL, FALSE, MAKELONG( 0, -1 ) );
+        SendMessage16( hwndCtrl, EM_SETSEL16, FALSE, MAKELONG( 0, -1 ) );
     SetFocus32( hwndCtrl );
 }
 
@@ -142,7 +142,7 @@
 	      /* Delete menu */
 	    if (dlgInfo->hMenu)
 	    {		
-		DestroyMenu( dlgInfo->hMenu );
+		DestroyMenu32( dlgInfo->hMenu );
 		dlgInfo->hMenu = 0;
 	    }
 
diff --git a/windows/dialog.c b/windows/dialog.c
index 20437e1..bcd73ea 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -570,7 +570,7 @@
     if (!hwnd)
     {
 	if (hFont) DeleteObject32( hFont );
-	if (hMenu) DestroyMenu( hMenu );
+	if (hMenu) DestroyMenu32( hMenu );
 	return 0;
     }
     wndPtr = WIN_FindWndPtr( hwnd );
@@ -1193,9 +1193,9 @@
 
 
 /***********************************************************************
- *           GetDialogBaseUnits   (USER.243)
+ *           GetDialogBaseUnits   (USER.243) (USER32.232)
  */
-DWORD GetDialogBaseUnits()
+DWORD GetDialogBaseUnits(void)
 {
     return MAKELONG( xBaseUnit, yBaseUnit );
 }
@@ -1491,7 +1491,7 @@
         strcpy( temp, "A:\\" );
         temp[0] += drive;
         lstrcpyn32A( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 );
-        AnsiLower( temp );
+        CharLower32A( temp );
         /* Can't use PostMessage() here, because the string is on the stack */
         SetDlgItemText32A( hDlg, idStatic, temp );
     }
diff --git a/windows/event.c b/windows/event.c
index ac851e3..19480dd 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -33,7 +33,6 @@
 #include "queue.h"
 #include "winpos.h"
 #include "drive.h"
-#include "dos_fs.h"
 #include "shell.h"
 #include "xmalloc.h"
 #include "keyboard.h"
@@ -68,73 +67,6 @@
 static HWND32 captureWnd = 0;
 static BOOL32 InputEnabled = TRUE;
 
-/* Keyboard translation tables */
-static const int special_key[] =
-{
-    VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0,           /* FF08 */
-    0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0,                      /* FF10 */
-    0, 0, 0, VK_ESCAPE                                          /* FF18 */
-};
-
-static const int cursor_key[] =
-{
-    VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR, 
-                                       VK_NEXT, VK_END          /* FF50 */
-};
-
-static const int misc_key[] =
-{
-    VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0,  /* FF60 */
-    VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU                      /* FF68 */
-};
-
-static const int keypad_key[] =
-{
-    VK_MENU, VK_NUMLOCK,                                        /* FF7E */
-    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF80 */
-    0, 0, 0, 0, 0, VK_RETURN, 0, 0,                             /* FF88 */
-    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF90 */
-    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF98 */
-    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFA0 */
-    0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT, 
-                               VK_DECIMAL, VK_DIVIDE,           /* FFA8 */
-    VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
-                            VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
-    VK_NUMPAD8, VK_NUMPAD9                                      /* FFB8 */
-};
-    
-static const int function_key[] =
-{
-    VK_F1, VK_F2,                                               /* FFBE */
-    VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,    /* FFC0 */
-    VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16              /* FFC8 */
-};
-
-static const int modifier_key[] =
-{
-    VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL,
-                                                0, 0,           /* FFE1 */
-    0, VK_MENU, VK_MENU                                         /* FFE8 */
-};
-
-typedef union
-{
-    struct
-    {
-	unsigned long count : 16;
-	unsigned long code : 8;
-	unsigned long extended : 1;
-	unsigned long unused : 2;
-	unsigned long win_internal : 2;
-	unsigned long context : 1;
-	unsigned long previous : 1;
-	unsigned long transition : 1;
-    } lp1;
-    unsigned long lp2;
-} KEYLP;
-
-static BOOL KeyDown = FALSE;
-
 static Atom wmProtocols = None;
 static Atom wmDeleteWindow = None;
 static Atom dndProtocol = None;
@@ -517,18 +449,348 @@
  *
  * Handle a X key event
  */
+
+/* Keyboard translation tables */
+static const int special_key[] =
+{
+    VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0,           /* FF08 */
+    0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0,                      /* FF10 */
+    0, 0, 0, VK_ESCAPE                                          /* FF18 */
+};
+
+static const int cursor_key[] =
+{
+    VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, VK_DOWN, VK_PRIOR, 
+                                       VK_NEXT, VK_END          /* FF50 */
+};
+
+static const int misc_key[] =
+{
+    VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0,  /* FF60 */
+    VK_CANCEL, VK_HELP, VK_CANCEL, VK_MENU                      /* FF68 */
+};
+
+static const int keypad_key[] =
+{
+    0, VK_NUMLOCK,                                        	/* FF7E */
+    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF80 */
+    0, 0, 0, 0, 0, VK_RETURN, 0, 0,                             /* FF88 */
+    0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP,                     /* FF90 */
+    VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, VK_END, 0,
+				 VK_INSERT, VK_DELETE,          /* FF98 */
+    0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFA0 */
+    0, 0, VK_MULTIPLY, VK_ADD, VK_SEPARATOR, VK_SUBTRACT, 
+                               VK_DECIMAL, VK_DIVIDE,           /* FFA8 */
+    VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD4,
+                            VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, /* FFB0 */
+    VK_NUMPAD8, VK_NUMPAD9                                      /* FFB8 */
+};
+    
+static const int function_key[] =
+{
+    VK_F1, VK_F2,                                               /* FFBE */
+    VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,    /* FFC0 */
+    VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16              /* FFC8 */
+};
+
+static const int modifier_key[] =
+{
+    VK_SHIFT, VK_SHIFT, VK_CONTROL, VK_CONTROL, VK_CAPITAL, 0, /* FFE1 */
+    VK_MENU, VK_MENU, VK_MENU, VK_MENU                         /* FFE7 */
+};
+
+static int AltGrMask;
+static int min_keycode, max_keycode;
+static int keyc2vkey [256];
+/* For example : keyc2vkey[10] is the VK_* associated with keycode10 */
+
+static WORD EVENT_event_to_vkey( XKeyEvent *e)
+{
+  static int keysyms_per_keycode;
+  int i;
+  KeySym keysym;
+
+  if (!keysyms_per_keycode) /* First time : Initialization */
+    {
+      KeySym *ksp;
+      XModifierKeymap *mmp;
+      KeyCode *kcp;
+      XKeyEvent e2;
+      WORD vkey, OEMvkey;
+
+      XDisplayKeycodes(e->display, &min_keycode, &max_keycode);
+      ksp = XGetKeyboardMapping(e->display, min_keycode,
+				max_keycode + 1 - min_keycode, &keysyms_per_keycode);
+      /* We are only interested in keysyms_per_keycode.
+	 There is no need to hold a local copy of the keysyms table */
+      XFree(ksp);
+      mmp = XGetModifierMapping(e->display);
+      kcp = mmp->modifiermap;
+      for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
+	{
+	  int j;
+
+	  for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
+	    if (*kcp)
+	      {
+		int k;
+
+		for (k = 0; k < keysyms_per_keycode; k += 1)
+		  if (XKeycodeToKeysym(e->display, *kcp, k)
+		      == XK_Mode_switch)
+		    {
+		      AltGrMask = 1 << i;
+		      dprintf_key(stddeb, "AltGrMask is %x\n", AltGrMask);
+		    }
+	      }
+	}
+      XFreeModifiermap(mmp);
+	
+	/* Now build two conversion arrays :
+	 * keycode -> vkey + extended
+	 * vkey + extended -> keycode */
+
+      e2.display = e->display;
+      e2.state = 0;
+
+      OEMvkey = 0xb9; /* first OEM virtual key available is ba */
+      for (e2.keycode=min_keycode; e2.keycode<=max_keycode; e2.keycode++)
+	{
+	  XLookupString(&e2, NULL, 0, &keysym, NULL);
+	  vkey = 0;
+	  if (keysym)  /* otherwise, keycode not used */
+	    {
+	      if ((keysym >> 8) == 0xFF)         /* non-character key */
+		{
+		  int key = keysym & 0xff;
+		
+		  if (key >= 0x08 && key <= 0x1B)         /* special key */
+		    vkey = special_key[key - 0x08];
+		  else if (key >= 0x50 && key <= 0x57)    /* cursor key */
+		    vkey = cursor_key[key - 0x50];
+		  else if (key >= 0x60 && key <= 0x6B)    /* miscellaneous key */
+		    vkey = misc_key[key - 0x60];
+		  else if (key >= 0x7E && key <= 0xB9)    /* keypad key */
+		    vkey = keypad_key[key - 0x7E];
+		  else if (key >= 0xBE && key <= 0xCD)    /* function key */
+		    {
+		      vkey = function_key[key - 0xBE];
+		      vkey |= 0x100; /* set extended bit */
+		    }
+		  else if (key >= 0xE1 && key <= 0xEA)    /* modifier key */
+		    vkey = modifier_key[key - 0xE1];
+		  else if (key == 0xFF)                   /* DEL key */
+		    vkey = VK_DELETE;
+		  /* extended must also be set for ALT_R, CTRL_R,
+		     INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
+		     keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
+		  switch (keysym)
+		    {
+		    case XK_Control_R :
+		    case XK_Alt_R :
+		    case XK_Insert :
+		    case XK_Delete :
+		    case XK_Home :
+		    case XK_End :
+		    case XK_Prior :
+		    case XK_Next :
+		    case XK_Left :
+		    case XK_Up :
+		    case XK_Right :
+		    case XK_Down :
+		    case XK_KP_Divide :
+		    case XK_KP_Enter :
+		      vkey |= 0x100;
+		    }
+		}
+	      for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
+		{
+		  keysym = XLookupKeysym(&e2, i);
+		  if ((keysym >= VK_0 && keysym <= VK_9)
+		      || (keysym >= VK_A && keysym <= VK_Z)
+		      || keysym == VK_SPACE)
+		    vkey = keysym;
+		}
+
+	      if (!vkey)
+		{
+		  /* Others keys: let's assign OEM virtual key codes in the allowed range,
+		   * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
+		  switch (++OEMvkey)
+		    {
+		    case 0xc1 : OEMvkey=0xdb; break;
+		    case 0xe5 : OEMvkey=0xe9; break;
+		    case 0xf6 : OEMvkey=0xf5; fprintf(stderr,"No more OEM vkey available!\n");
+		    }
+		  
+		  vkey = OEMvkey;
+		  
+		  if (debugging_keyboard)
+		    {
+		      fprintf(stddeb,"OEM specific virtual key %X assigned to keycode %X :\n ("
+			      ,OEMvkey,e2.keycode);
+		      for (i = 0; i < keysyms_per_keycode; i += 1)
+			{
+			  char	*ksname;
+			  
+			  keysym = XLookupKeysym(&e2, i);
+			  ksname = XKeysymToString(keysym);
+			  if (!ksname)
+			    ksname = "NoSymbol";
+			  fprintf(stddeb, "%lX (%s) ", keysym, ksname);
+			}
+		      fprintf(stddeb, ")\n");
+		    }
+		}
+	    }
+	  keyc2vkey[e2.keycode] = vkey;
+	} /* for */
+    } /* Initialization */
+  
+  return keyc2vkey[e->keycode];
+  
+}
+
+int EVENT_ToAscii(WORD wVirtKey, WORD wScanCode, LPSTR lpKeyState, 
+	LPVOID lpChar, WORD wFlags) 
+{
+    XKeyEvent e;
+    KeySym keysym;
+    static XComposeStatus cs;
+    int ret;
+    WORD keyc;
+
+    e.display = display;
+    e.keycode = 0;
+    for (keyc=min_keycode; keyc<=max_keycode; keyc++)
+      { /* this could be speed up by making another table, an array of struct vkey,keycode
+	 * (vkey -> keycode) with vkeys sorted .... but it takes memory (512*3 bytes)!  DF */
+	if ((keyc2vkey[keyc] & 0xFF)== wVirtKey) /* no need to make a more precise test (with the extended bit correctly set above wVirtKey ... VK* are different enough... */
+	  {
+	    if ((e.keycode) && ((wVirtKey<0x10) || (wVirtKey>0x12))) 
+		/* it's normal to have 2 shift, control, and alt ! */
+		dprintf_keyboard(stddeb,"Strange ... the keycodes %X and %X are matching!\n",
+				 e.keycode,keyc);
+	    e.keycode = keyc;
+	  }
+      }
+    if (!e.keycode) 
+      {
+	fprintf(stderr,"Unknown virtual key %X !!! \n",wVirtKey);
+	return wVirtKey; /* whatever */
+      }
+    e.state = 0;
+    if (lpKeyState[VK_SHIFT] & 0x80)
+	e.state |= ShiftMask;
+    if (lpKeyState[VK_CAPITAL] & 0x80)
+	e.state |= LockMask;
+    if (lpKeyState[VK_CONTROL] & 0x80)
+	if (lpKeyState[VK_MENU] & 0x80)
+	    e.state |= AltGrMask;
+	else
+	    e.state |= ControlMask;
+    if (lpKeyState[VK_NUMLOCK] & 0x80)
+	e.state |= Mod2Mask;
+    dprintf_key(stddeb, "EVENT_ToAscii(%04X, %04X) : faked state = %X\n",
+		wVirtKey, wScanCode, e.state);
+    ret = XLookupString(&e, lpChar, 2, &keysym, &cs);
+    if (ret == 0)
+	{
+	BYTE dead_char = 0;
+
+	((char*)lpChar)[1] = '\0';
+	switch (keysym)
+	    {
+	    case XK_dead_tilde :
+	    case 0x1000FE7E : /* Xfree's XK_Dtilde */
+		dead_char = '~';
+		break;
+	    case XK_dead_acute :
+	    case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
+		dead_char = 0xb4;
+		break;
+	    case XK_dead_circumflex :
+	    case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
+		dead_char = '^';
+		break;
+	    case XK_dead_grave :
+	    case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
+		dead_char = '`';
+		break;
+	    case XK_dead_diaeresis :
+	    case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
+		dead_char = 0xa8;
+		break;
+	    }
+	if (dead_char)
+	    {
+	    *(char*)lpChar = dead_char;
+	    ret = -1;
+	    }
+	else
+	    {
+	    char	*ksname;
+
+	    ksname = XKeysymToString(keysym);
+	    if (!ksname)
+		ksname = "No Name";
+	    if ((keysym >> 8) != 0xff)
+		{
+		fprintf(stderr, "Please report : no char for keysym %04lX (%s) :\n",
+			keysym, ksname);
+		fprintf(stderr, "  wVirtKey = %X, wScanCode = %X, keycode = %X, state = %X\n",
+			wVirtKey, wScanCode, e.keycode, e.state);
+		}
+	    }
+	}
+    dprintf_key(stddeb, "EVENT_ToAscii about to return %d with char %x\n",
+		ret, *(char*)lpChar);
+    return ret;
+}
+
+typedef union
+{
+    struct
+    {
+	unsigned long count : 16;
+	unsigned long code : 8;
+	unsigned long extended : 1;
+	unsigned long unused : 2;
+	unsigned long win_internal : 2;
+	unsigned long context : 1;
+	unsigned long previous : 1;
+	unsigned long transition : 1;
+    } lp1;
+    unsigned long lp2;
+} KEYLP;
+
 static void EVENT_key( XKeyEvent *event )
 {
     char Str[24]; 
     XComposeStatus cs; 
     KeySym keysym;
     WORD vkey = 0;
-    WORD xkey, key_type, key;
     KEYLP keylp;
-    BOOL extended = FALSE;
+    WORD message;
+    static BOOL force_extended = FALSE; /* hack for AltGr translation */
 
     int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
 
+    dprintf_key(stddeb, "EVENT_key : state = %X\n", event->state);
+    if (keysym == XK_Mode_switch)
+	{
+	dprintf_key(stddeb, "Alt Gr key event received\n");
+	event->keycode = XKeysymToKeycode(event->display, XK_Control_L);
+	dprintf_key(stddeb, "Control_L is keycode 0x%x\n", event->keycode);
+	EVENT_key(event);
+	event->keycode = XKeysymToKeycode(event->display, XK_Alt_L);
+	dprintf_key(stddeb, "Alt_L is keycode 0x%x\n", event->keycode);
+	force_extended = TRUE;
+	EVENT_key(event);
+	force_extended = FALSE;
+	return;
+	}
+
     Str[ascii_chars] = '\0';
     if (debugging_key)
 	{
@@ -537,8 +799,9 @@
 	ksname = XKeysymToString(keysym);
 	if (!ksname)
 	    ksname = "No Name";
-	fprintf(stddeb, "WM_KEY??? : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n", 
-	   keysym, ksname, ascii_chars, Str[0], Str);
+	fprintf(stddeb, "%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n", 
+	    event_names[event->type], keysym, ksname,
+	    ascii_chars, Str[0] & 0xff, Str);
 	}
 
 #if 0
@@ -548,119 +811,51 @@
         DEBUG_EnterDebugger();
 #endif
 
-    xkey = LOWORD(keysym);
-    key_type = HIBYTE(xkey);
-    key = LOBYTE(xkey);
-    dprintf_key(stddeb,"            key_type=%X, key=%X\n", key_type, key);
+    vkey = EVENT_event_to_vkey(event);
+    if (force_extended) vkey |= 0x100;
 
-    if (key_type == 0xFF)                          /* non-character key */
-    {
-	if (key >= 0x08 && key <= 0x1B)            /* special key */
-	    vkey = special_key[key - 0x08];
-	else if (key >= 0x50 && key <= 0x57)       /* cursor key */
-	    vkey = cursor_key[key - 0x50];
-	else if (key >= 0x60 && key <= 0x6B)       /* miscellaneous key */
-	    vkey = misc_key[key - 0x60];
-	else if (key >= 0x7E && key <= 0xB9)       /* keypad key */
-	{
-	    vkey = keypad_key[key - 0x7E];
-	    extended = TRUE;
-	}
-	else if (key >= 0xBE && key <= 0xCD)       /* function key */
-	{
-	    vkey = function_key[key - 0xBE];
-	    extended = TRUE;
-	}
-	else if (key >= 0xE1 && key <= 0xEA)       /* modifier key */
-	    vkey = modifier_key[key - 0xE1];
-	else if (key == 0xFF)                      /* DEL key */
-	    vkey = VK_DELETE;
-	/* extended must also be set for ALT_R, CTRL_R,
-	INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
-	keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
-	switch (keysym)
-	    {
-	    case XK_Control_R :
-	    case XK_Alt_R :
-	    case XK_Insert :
-	    case XK_Delete :
-	    case XK_Home :
-	    case XK_End :
-	    case XK_Prior :
-	    case XK_Next :
-	    case XK_Left :
-	    case XK_Up :
-	    case XK_Right :
-	    case XK_Down :
-	    case XK_KP_Divide :
-	    case XK_KP_Enter :
-		extended = 1;
-	    }
-    }
-    else if (key_type == 0)                        /* character key */
-    {
-	if ( isalnum(key) )
-	     vkey = toupper(key);                  /* convert lc to uc */
-	else if ( isspace(key) )
-	  vkey = key;				   /* XXX approximately */
-        else  
-	  switch (key)				   /* the rest... */
-	  {
-#define vkcase(k,val) case k: vkey = val; break;
-#define vkcase2(k1,k2,val) case k1: case k2: vkey = val; break;
-	    WINE_VKEY_MAPPINGS
-#undef vkcase
-#undef vkcase2
-	    default:
-	      fprintf( stderr, "Unknown key! Please report!\n" );
-	      vkey = 0;				   /* whatever */
-	  }
-    }
+    dprintf_key(stddeb, "keycode 0x%x converted to vkey 0x%x\n",
+		    event->keycode, vkey);
 
+    keylp.lp1.count = 1;
+    keylp.lp1.code = LOBYTE(event->keycode) - 8;
+    keylp.lp1.extended = (vkey & 0x100 ? 1 : 0);
+    keylp.lp1.win_internal = 0; /* this has something to do with dialogs, 
+				* don't remember where I read it - AK */
+				/* it's '1' under windows, when a dialog box appears
+				 * and you press one of the underlined keys - DF*/
+    vkey &= 0xff;
     if (event->type == KeyPress)
     {
+	keylp.lp1.previous = (InputKeyStateTable[vkey] & 0x80) != 0;
         if (!(InputKeyStateTable[vkey] & 0x80))
             InputKeyStateTable[vkey] ^= 0x01;
 	InputKeyStateTable[vkey] |= 0x80;
-	keylp.lp1.count = 1;
-	keylp.lp1.code = LOBYTE(event->keycode) - 8;
-	keylp.lp1.extended = (extended ? 1 : 0);
-	keylp.lp1.win_internal = 0;			/* this has something to do with dialogs, 
-							 * don't remember where I read it - AK */
-	keylp.lp1.context = ( (event->state & Mod1Mask) || 
-			       (InputKeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
-	keylp.lp1.previous = (KeyDown ? 0 : 1);
 	keylp.lp1.transition = 0;
-	dprintf_key(stddeb,"            wParam=%X, lParam=%lX\n", 
-		    vkey, keylp.lp2 );
-	dprintf_key(stddeb,"            InputKeyState=%X\n", InputKeyStateTable[vkey]);
-	hardware_event( InputKeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN, 
-		        vkey, keylp.lp2,
-		        event->x_root - desktopX, event->y_root - desktopY,
-		        event->time - MSG_WineStartTicks, 0 );
-	KeyDown = TRUE;
+	message = (InputKeyStateTable[VK_MENU] & 0x80)
+		    && !(InputKeyStateTable[VK_CONTROL] & 0x80)
+			 ? WM_SYSKEYDOWN : WM_KEYDOWN;
     }
     else
     {
-	UINT sysKey = InputKeyStateTable[VK_MENU];
+	UINT sysKey = (InputKeyStateTable[VK_MENU] & 0x80)
+			&& !(InputKeyStateTable[VK_CONTROL] & 0x80)
+			&& (force_extended == FALSE); /* for Alt from AltGr */
 
 	InputKeyStateTable[vkey] &= ~0x80; 
-	keylp.lp1.count = 1;
-	keylp.lp1.code = LOBYTE(event->keycode) - 8;
-	keylp.lp1.extended = (extended ? 1 : 0);
-	keylp.lp1.win_internal = 0;
-	keylp.lp1.context = (event->state & Mod1Mask ? 1 : 0);
 	keylp.lp1.previous = 1;
 	keylp.lp1.transition = 1;
-	dprintf_key(stddeb,"            wParam=%X, lParam=%lX\n", 
-		    vkey, keylp.lp2 );
-	dprintf_key(stddeb,"            InputKeyState=%X\n", InputKeyStateTable[vkey]);
-	hardware_event( sysKey & 0x80 ? WM_SYSKEYUP : WM_KEYUP, 
-		        vkey, keylp.lp2,
-		        event->x_root - desktopX, event->y_root - desktopY,
-		        event->time - MSG_WineStartTicks, 0 );
-	KeyDown = FALSE;
+	message = sysKey ? WM_SYSKEYUP : WM_KEYUP;
     }
+    keylp.lp1.context = ( (event->state & Mod1Mask)  || 
+			  (InputKeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
+    dprintf_key(stddeb,"            wParam=%04X, lParam=%08lX\n", 
+		vkey, keylp.lp2 );
+    dprintf_key(stddeb,"            InputKeyState=%X\n",
+		InputKeyStateTable[vkey]);
+
+    hardware_event( message, vkey, keylp.lp2, event->x_root - desktopX,
+	    event->y_root - desktopY, event->time - MSG_WineStartTicks, 0 );
 }
 
 
@@ -952,10 +1147,10 @@
 	  union {
 		   Atom		atom_aux;
 		   POINT32	pt_aux;
-		   BOOL16	bAccept;
 		   int		i;
 		}		u;
 	  int			x, y;
+          BOOL16	        bAccept;
 	  HGLOBAL16		hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, sizeof(DRAGINFO));
 	  LPDRAGINFO            lpDragInfo = (LPDRAGINFO) GlobalLock16(hDragInfo);
 	  SEGPTR		spDragInfo = (SEGPTR) WIN16_GlobalLock16(hDragInfo);
@@ -974,16 +1169,16 @@
 	  if( x < 0 || y < 0 ||
 	      x > (pWnd->rectWindow.right - pWnd->rectWindow.left) ||
 	      y > (pWnd->rectWindow.bottom - pWnd->rectWindow.top) )
-	  {   u.bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
+	  {   bAccept = pWnd->dwExStyle & WS_EX_ACCEPTFILES; x = y = 0; }
 	  else
 	  {
-	      u.bAccept = DRAG_QueryUpdate( pWnd->hwndSelf, spDragInfo, TRUE );
+	      bAccept = DRAG_QueryUpdate( pWnd->hwndSelf, spDragInfo, TRUE );
 	      x = lpDragInfo->pt.x; y = lpDragInfo->pt.y;
 	  }
 	  pDropWnd = WIN_FindWndPtr( lpDragInfo->hScope );
 	  GlobalFree16( hDragInfo );
 
-	  if( u.bAccept )
+	  if( bAccept )
 	  {
 	      XGetWindowProperty( display, DefaultRootWindow(display),
 			      dndSelection, 0, 65535, FALSE,
@@ -992,20 +1187,20 @@
 
 	      if( !aux_long && p_data)	/* don't bother if > 64K */
 	      {
-		char*			p = (char*) p_data;
-		char*			p_filename,*p_drop;
+		char *p = (char*) p_data;
+		char *p_drop;
 
 		aux_long = 0; 
 		while( *p )	/* calculate buffer size */
 		{
 		  p_drop = p;
 		  if((u.i = *p) != -1 ) 
-		      u.i = DRIVE_FindDriveRoot( (const char**)&p_drop );
+		      u.i = DRIVE_FindDriveRoot( (const char **)&p_drop );
 		  if( u.i == -1 ) *p = -1;	/* mark as "bad" */
 		  else
 		  {
-		      p_filename = (char*) DOSFS_GetDosTrueName( (const char*)p, TRUE );
-		      if( p_filename ) aux_long += strlen(p_filename) + 1;
+                      INT32 len = GetShortPathName32A( p, NULL, 0 );
+                      if (len) aux_long += len + 1;
 		      else *p = -1;
 		  }
 		  p += strlen(p) + 1;
@@ -1035,9 +1230,8 @@
 		    {
 		      if( *p != -1 )	/* use only "good" entries */
 		      {
-			p_filename = (char*) DOSFS_GetDosTrueName( p, TRUE );
-			strcpy(p_drop, p_filename);
-			p_drop += strlen( p_filename ) + 1;
+                          GetShortPathName32A( p, p_drop, 65535 );
+                          p_drop += strlen( p_drop ) + 1;
 		      }
 		      p += strlen(p) + 1;
 		    }
diff --git a/windows/graphics.c b/windows/graphics.c
index caf865e..8dd1d65 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -14,6 +14,7 @@
 #define PI M_PI
 #endif
 #include "graphics.h"
+#include "gdi.h"
 #include "dc.h"
 #include "bitmap.h"
 #include "callback.h"
@@ -40,24 +41,10 @@
  */
 BOOL32 LineTo32( HDC32 hdc, INT32 x, INT32 y )
 {
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return FALSE;
-	MF_MetaParam2(dc, META_LINETO, x, y);
-	return TRUE;
-    }
+    DC * dc = DC_GetDCPtr( hdc );
 
-    if (DC_SetupGCForPen( dc ))
-	XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, 
-		  dc->w.DCOrgX + XLPTODP( dc, dc->w.CursPosX ),
-		  dc->w.DCOrgY + YLPTODP( dc, dc->w.CursPosY ),
-		  dc->w.DCOrgX + XLPTODP( dc, x ),
-		  dc->w.DCOrgY + YLPTODP( dc, y ) );
-    dc->w.CursPosX = x;
-    dc->w.CursPosY = y;
-    return TRUE;
+    return dc && dc->funcs->pLineTo &&
+    	   dc->funcs->pLineTo(dc,x,y);
 }
 
 
@@ -66,19 +53,11 @@
  */
 DWORD MoveTo( HDC16 hdc, INT16 x, INT16 y )
 {
-    DWORD ret;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return FALSE;
-	MF_MetaParam2(dc, META_MOVETO, x, y);
-	return 0;
-    }
-    ret = MAKELONG( dc->w.CursPosX, dc->w.CursPosY );
-    dc->w.CursPosX = x;
-    dc->w.CursPosY = y;
-    return ret;
+    POINT16	pt;
+
+    if (!MoveToEx16(hdc,x,y,&pt))
+    	return 0;
+    return MAKELONG(pt.x,pt.y);
 }
 
 
@@ -87,16 +66,12 @@
  */
 BOOL16 MoveToEx16( HDC16 hdc, INT16 x, INT16 y, LPPOINT16 pt )
 {
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return FALSE;
-    if (pt)
-    {
-	pt->x = dc->w.CursPosX;
-	pt->y = dc->w.CursPosY;
-    }
-    dc->w.CursPosX = x;
-    dc->w.CursPosY = y;
+    POINT32 pt32;
+
+    if (!MoveToEx32( (HDC32)hdc, (INT32)x, (INT32)y, &pt32 )) return FALSE;
+    if (pt) CONV_POINT32TO16( &pt32, pt );
     return TRUE;
+
 }
 
 
@@ -105,104 +80,10 @@
  */
 BOOL32 MoveToEx32( HDC32 hdc, INT32 x, INT32 y, LPPOINT32 pt )
 {
-    POINT16 pt16;
-    if (!MoveToEx16( (HDC16)hdc, (INT16)x, (INT16)y, &pt16 )) return FALSE;
-    if (pt) CONV_POINT16TO32( &pt16, pt );
-    return TRUE;
-}
-
-
-/***********************************************************************
- *           GRAPH_DrawArc
- *
- * Helper functions for Arc(), Chord() and Pie().
- * 'lines' is the number of lines to draw: 0 for Arc, 1 for Chord, 2 for Pie.
- */
-static BOOL32 GRAPH_DrawArc( HDC32 hdc, INT32 left, INT32 top, INT32 right,
-                             INT32 bottom, INT32 xstart, INT32 ystart,
-                             INT32 xend, INT32 yend, INT32 lines )
-{
-    INT32 xcenter, ycenter, istart_angle, idiff_angle, tmp;
-    double start_angle, end_angle;
-    XPoint points[3];
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return FALSE;
-	switch (lines)
-	{
-	case 0:
-	    MF_MetaParam8(dc, META_ARC, left, top, right, bottom,
-			  xstart, ystart, xend, yend);
-	    break;
-
-	case 1:
-	    MF_MetaParam8(dc, META_CHORD, left, top, right, bottom,
-			  xstart, ystart, xend, yend);
-	    break;
-
-	case 2:
-	    MF_MetaParam8(dc, META_PIE, left, top, right, bottom,
-			  xstart, ystart, xend, yend);
-	    break;
-	}
-	return 0;
-    }
-
-    left   = XLPTODP( dc, left );
-    top    = YLPTODP( dc, top );
-    right  = XLPTODP( dc, right );
-    bottom = YLPTODP( dc, bottom );
-    xstart = XLPTODP( dc, xstart );
-    ystart = YLPTODP( dc, ystart );
-    xend   = XLPTODP( dc, xend );
-    yend   = YLPTODP( dc, yend );
-    if ((left == right) || (top == bottom)) return FALSE;
-
-    xcenter = (right + left) / 2;
-    ycenter = (bottom + top) / 2;
-    start_angle = atan2( (double)(ycenter-ystart)*(right-left),
-			 (double)(xstart-xcenter)*(bottom-top) );
-    end_angle   = atan2( (double)(ycenter-yend)*(right-left),
-			 (double)(xend-xcenter)*(bottom-top) );
-    istart_angle = (INT32)(start_angle * 180 * 64 / PI);
-    idiff_angle  = (INT32)((end_angle - start_angle) * 180 * 64 / PI );
-    if (idiff_angle <= 0) idiff_angle += 360 * 64;
-    if (left > right) { tmp=left; left=right; right=tmp; }
-    if (top > bottom) { tmp=top; top=bottom; bottom=tmp; }
-
-      /* Fill arc with brush if Chord() or Pie() */
-
-    if ((lines > 0) && DC_SetupGCForBrush( dc ))
-    {
-        XSetArcMode( display, dc->u.x.gc, (lines==1) ? ArcChord : ArcPieSlice);
-        XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
-                 dc->w.DCOrgX + left, dc->w.DCOrgY + top,
-                 right-left-1, bottom-top-1, istart_angle, idiff_angle );
-    }
-
-      /* Draw arc and lines */
-
-    if (!DC_SetupGCForPen( dc )) return TRUE;
-    XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
-	      dc->w.DCOrgX + left, dc->w.DCOrgY + top,
-	      right-left-1, bottom-top-1, istart_angle, idiff_angle );
-    if (!lines) return TRUE;
-
-    points[0].x = dc->w.DCOrgX + xcenter + (int)(cos(start_angle) * (right-left) / 2);
-    points[0].y = dc->w.DCOrgY + ycenter - (int)(sin(start_angle) * (bottom-top) / 2);
-    points[1].x = dc->w.DCOrgX + xcenter + (int)(cos(end_angle) * (right-left) / 2);
-    points[1].y = dc->w.DCOrgY + ycenter - (int)(sin(end_angle) * (bottom-top) / 2);
-    if (lines == 2)
-    {
-	points[2] = points[1];
-	points[1].x = dc->w.DCOrgX + xcenter;
-	points[1].y = dc->w.DCOrgY + ycenter;
-    }
-    XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
-	        points, lines+1, CoordModeOrigin );
-    return TRUE;
+    DC * dc = DC_GetDCPtr( hdc );
+  
+    return dc && dc->funcs->pMoveToEx &&
+    	   dc->funcs->pMoveToEx(dc,x,y,pt);
 }
 
 
@@ -212,8 +93,9 @@
 BOOL16 Arc16( HDC16 hdc, INT16 left, INT16 top, INT16 right, INT16 bottom,
               INT16 xstart, INT16 ystart, INT16 xend, INT16 yend )
 {
-    return GRAPH_DrawArc( hdc, left, top, right, bottom,
-			  xstart, ystart, xend, yend, 0 );
+    return Arc32( (HDC32)hdc, (INT32)left, (INT32)top, (INT32)right,
+   		  (INT32)bottom, (INT32)xstart, (INT32)ystart, (INT32)xend,
+		  (INT32)yend );
 }
 
 
@@ -223,8 +105,10 @@
 BOOL32 Arc32( HDC32 hdc, INT32 left, INT32 top, INT32 right, INT32 bottom,
               INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
 {
-    return GRAPH_DrawArc( hdc, left, top, right, bottom,
-			  xstart, ystart, xend, yend, 0 );
+    DC * dc = DC_GetDCPtr( hdc );
+  
+    return dc && dc->funcs->pArc &&
+    	   dc->funcs->pArc(dc,left,top,right,bottom,xstart,ystart,xend,yend);
 }
 
 
@@ -234,8 +118,9 @@
 BOOL16 Pie16( HDC16 hdc, INT16 left, INT16 top, INT16 right, INT16 bottom,
               INT16 xstart, INT16 ystart, INT16 xend, INT16 yend )
 {
-    return GRAPH_DrawArc( hdc, left, top, right, bottom,
-			  xstart, ystart, xend, yend, 2 );
+    return Pie32( (HDC32)hdc, (INT32)left, (INT32)top, (INT32)right,
+   		  (INT32)bottom, (INT32)xstart, (INT32)ystart, (INT32)xend,
+		  (INT32)yend );
 }
 
 
@@ -245,8 +130,10 @@
 BOOL32 Pie32( HDC32 hdc, INT32 left, INT32 top, INT32 right, INT32 bottom,
               INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
 {
-    return GRAPH_DrawArc( hdc, left, top, right, bottom,
-			  xstart, ystart, xend, yend, 2 );
+    DC * dc = DC_GetDCPtr( hdc );
+  
+    return dc && dc->funcs->pPie &&
+    	   dc->funcs->pPie(dc,left,top,right,bottom,xstart,ystart,xend,yend);
 }
 
 
@@ -256,8 +143,7 @@
 BOOL16 Chord16( HDC16 hdc, INT16 left, INT16 top, INT16 right, INT16 bottom,
                 INT16 xstart, INT16 ystart, INT16 xend, INT16 yend )
 {
-    return GRAPH_DrawArc( hdc, left, top, right, bottom,
-			  xstart, ystart, xend, yend, 1 );
+    return Chord32( hdc, left, top, right, bottom, xstart, ystart, xend, yend );
 }
 
 
@@ -267,8 +153,10 @@
 BOOL32 Chord32( HDC32 hdc, INT32 left, INT32 top, INT32 right, INT32 bottom,
                 INT32 xstart, INT32 ystart, INT32 xend, INT32 yend )
 {
-    return GRAPH_DrawArc( hdc, left, top, right, bottom,
-			  xstart, ystart, xend, yend, 1 );
+    DC * dc = DC_GetDCPtr( hdc );
+  
+    return dc && dc->funcs->pChord &&
+    	   dc->funcs->pChord(dc,left,top,right,bottom,xstart,ystart,xend,yend);
 }
 
 
@@ -286,43 +174,10 @@
  */
 BOOL32 Ellipse32( HDC32 hdc, INT32 left, INT32 top, INT32 right, INT32 bottom )
 {
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return FALSE;
-	MF_MetaParam4(dc, META_ELLIPSE, left, top, right, bottom);
-	return 0;
-    }
-
-    left   = XLPTODP( dc, left );
-    top    = YLPTODP( dc, top );
-    right  = XLPTODP( dc, right );
-    bottom = YLPTODP( dc, bottom );
-    if ((left == right) || (top == bottom)) return FALSE;
-
-    if (right < left) { INT32 tmp = right; right = left; left = tmp; }
-    if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
-    
-    if ((dc->u.x.pen.style == PS_INSIDEFRAME) &&
-        (dc->u.x.pen.width < right-left-1) &&
-        (dc->u.x.pen.width < bottom-top-1))
-    {
-        left   += dc->u.x.pen.width / 2;
-        right  -= (dc->u.x.pen.width + 1) / 2;
-        top    += dc->u.x.pen.width / 2;
-        bottom -= (dc->u.x.pen.width + 1) / 2;
-    }
-
-    if (DC_SetupGCForBrush( dc ))
-	XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
-		  dc->w.DCOrgX + left, dc->w.DCOrgY + top,
-		  right-left-1, bottom-top-1, 0, 360*64 );
-    if (DC_SetupGCForPen( dc ))
-	XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
-		  dc->w.DCOrgX + left, dc->w.DCOrgY + top,
-		  right-left-1, bottom-top-1, 0, 360*64 );
-    return TRUE;
+    DC * dc = DC_GetDCPtr( hdc );
+  
+    return dc && dc->funcs->pEllipse &&
+    	   dc->funcs->pEllipse(dc,left,top,right,bottom);
 }
 
 
@@ -340,56 +195,10 @@
  */
 BOOL32 Rectangle32(HDC32 hdc, INT32 left, INT32 top, INT32 right, INT32 bottom)
 {
-    INT32 width;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return FALSE;
-	MF_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
-	return TRUE;
-    }
-    left   = XLPTODP( dc, left );
-    top    = YLPTODP( dc, top );
-    right  = XLPTODP( dc, right );
-    bottom = YLPTODP( dc, bottom );
-
-    if (right < left) { INT32 tmp = right; right = left; left = tmp; }
-    if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
-
-    if ((left == right) || (top == bottom))
-    {
-	if (DC_SetupGCForPen( dc ))
-	    XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, 
-		  dc->w.DCOrgX + left,
-		  dc->w.DCOrgY + top,
-		  dc->w.DCOrgX + right,
-		  dc->w.DCOrgY + bottom);
-	return TRUE;
-    }
-    width = dc->u.x.pen.width;
-    if (!width) width = 1;
-    if(dc->u.x.pen.style == PS_NULL) width = 0;
-
-    if ((dc->u.x.pen.style == PS_INSIDEFRAME) &&
-        (width < right-left) && (width < bottom-top))
-    {
-        left   += width / 2;
-        right  -= (width + 1) / 2;
-        top    += width / 2;
-        bottom -= (width + 1) / 2;
-    }
-
-    if (DC_SetupGCForBrush( dc ))
-	XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
-		        dc->w.DCOrgX + left + (width + 1) / 2,
-		        dc->w.DCOrgY + top + (width + 1) / 2,
-		        right-left-width-1, bottom-top-width-1);
-    if (DC_SetupGCForPen( dc ))
-	XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
-		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
-		        right-left-1, bottom-top-1 );
-    return TRUE;
+    DC * dc = DC_GetDCPtr( hdc );
+  
+    return dc && dc->funcs->pRectangle &&
+    	   dc->funcs->pRectangle(dc,left,top,right,bottom);
 }
 
 
@@ -409,115 +218,10 @@
 BOOL32 RoundRect32( HDC32 hdc, INT32 left, INT32 top, INT32 right,
                     INT32 bottom, INT32 ell_width, INT32 ell_height )
 {
-    DC * dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return FALSE;
-	MF_MetaParam6(dc, META_ROUNDRECT, left, top, right, bottom,
-		      ell_width, ell_height);
-	return TRUE;
-    }
-    dprintf_graphics(stddeb, "RoundRect(%d %d %d %d  %d %d\n", 
-    	left, top, right, bottom, ell_width, ell_height);
-
-    left   = XLPTODP( dc, left );
-    top    = YLPTODP( dc, top );
-    right  = XLPTODP( dc, right );
-    bottom = YLPTODP( dc, bottom );
-    ell_width  = abs( ell_width * dc->vportExtX / dc->wndExtX );
-    ell_height = abs( ell_height * dc->vportExtY / dc->wndExtY );
-
-    /* Fix the coordinates */
-
-    if (right < left) { INT32 tmp = right; right = left; left = tmp; }
-    if (bottom < top) { INT32 tmp = bottom; bottom = top; top = tmp; }
-    if (ell_width > right - left) ell_width = right - left;
-    if (ell_height > bottom - top) ell_height = bottom - top;
-
-    if (DC_SetupGCForBrush( dc ))
-    {
-        if (ell_width && ell_height)
-        {
-            XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
-                      dc->w.DCOrgX + left, dc->w.DCOrgY + top,
-                      ell_width, ell_height, 90 * 64, 90 * 64 );
-            XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
-                      dc->w.DCOrgX + left, dc->w.DCOrgY + bottom - ell_height,
-                      ell_width, ell_height, 180 * 64, 90 * 64 );
-            XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
-                      dc->w.DCOrgX + right - ell_width,
-                      dc->w.DCOrgY + bottom - ell_height,
-                      ell_width, ell_height, 270 * 64, 90 * 64 );
-            XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
-                      dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top,
-                      ell_width, ell_height, 0, 90 * 64 );
-        }
-        if (ell_width < right - left)
-        {
-            XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
-                            dc->w.DCOrgX + left + ell_width / 2,
-                            dc->w.DCOrgY + top,
-                            right - left - ell_width, ell_height / 2 );
-            XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
-                            dc->w.DCOrgX + left + ell_width / 2,
-                            dc->w.DCOrgY + bottom - (ell_height+1) / 2,
-                            right - left - ell_width, (ell_height+1) / 2 );
-        }
-        if  (ell_height < bottom - top)
-        {
-            XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
-                            dc->w.DCOrgX + left,
-                            dc->w.DCOrgY + top + ell_height / 2,
-                            right - left, bottom - top - ell_height );
-        }
-    }
-    if (DC_SetupGCForPen(dc))
-    {
-        if (ell_width && ell_height)
-        {
-            XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
-                      dc->w.DCOrgX + left, dc->w.DCOrgY + top,
-                      ell_width, ell_height, 90 * 64, 90 * 64 );
-            XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
-                      dc->w.DCOrgX + left, dc->w.DCOrgY + bottom - ell_height,
-                      ell_width, ell_height, 180 * 64, 90 * 64 );
-            XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
-                      dc->w.DCOrgX + right - ell_width,
-                      dc->w.DCOrgY + bottom - ell_height,
-                      ell_width, ell_height, 270 * 64, 90 * 64 );
-            XDrawArc( display, dc->u.x.drawable, dc->u.x.gc,
-                      dc->w.DCOrgX + right - ell_width, dc->w.DCOrgY + top,
-                      ell_width, ell_height, 0, 90 * 64 );
-	}
-        if (ell_width < right - left)
-        {
-            XDrawLine( display, dc->u.x.drawable, dc->u.x.gc, 
-                       dc->w.DCOrgX + left + ell_width / 2,
-                       dc->w.DCOrgY + top,
-                       dc->w.DCOrgX + right - ell_width / 2,
-                       dc->w.DCOrgY + top );
-            XDrawLine( display, dc->u.x.drawable, dc->u.x.gc, 
-                       dc->w.DCOrgX + left + ell_width / 2,
-                       dc->w.DCOrgY + bottom,
-                       dc->w.DCOrgX + right - ell_width / 2,
-                       dc->w.DCOrgY + bottom );
-        }
-        if (ell_height < bottom - top)
-        {
-            XDrawLine( display, dc->u.x.drawable, dc->u.x.gc, 
-                       dc->w.DCOrgX + right,
-                       dc->w.DCOrgY + top + ell_height / 2,
-                       dc->w.DCOrgX + right,
-                       dc->w.DCOrgY + bottom - ell_height / 2 );
-            XDrawLine( display, dc->u.x.drawable, dc->u.x.gc, 
-                       dc->w.DCOrgX + left,
-                       dc->w.DCOrgY + top + ell_height / 2,
-                       dc->w.DCOrgX + left,
-                       dc->w.DCOrgY + bottom - ell_height / 2 );
-        }
-    }
-    return TRUE;
+    DC * dc = DC_GetDCPtr( hdc );
+  
+    return dc && dc->funcs->pRoundRect &&
+    	   dc->funcs->pRoundRect(dc,left,top,right,bottom,ell_width,ell_height);
 }
 
 
@@ -635,28 +339,10 @@
  */
 COLORREF SetPixel32( HDC32 hdc, INT32 x, INT32 y, COLORREF color )
 {
-    Pixel pixel;
-    
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return 0;
-	MF_MetaParam4(dc, META_SETPIXEL, x, y, HIWORD(color), LOWORD(color)); 
-	return 1;
-    }
-
-    x = dc->w.DCOrgX + XLPTODP( dc, x );
-    y = dc->w.DCOrgY + YLPTODP( dc, y );
-    pixel = COLOR_ToPhysical( dc, color );
-    
-    XSetForeground( display, dc->u.x.gc, pixel );
-    XSetFunction( display, dc->u.x.gc, GXcopy );
-    XDrawPoint( display, dc->u.x.drawable, dc->u.x.gc, x, y );
-
-    /* inefficient but simple... */
-
-    return COLOR_ToLogical(pixel);
+    DC * dc = DC_GetDCPtr( hdc );
+  
+    if (!dc || !dc->funcs->pSetPixel) return 0;
+    return dc->funcs->pSetPixel(dc,x,y,color);
 }
 
 
@@ -674,40 +360,17 @@
  */
 COLORREF GetPixel32( HDC32 hdc, INT32 x, INT32 y )
 {
-    static Pixmap pixmap = 0;
-    XImage * image;
-    int pixel;
+    DC * dc = DC_GetDCPtr( hdc );
 
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
     if (!dc) return 0;
-
 #ifdef SOLITAIRE_SPEED_HACK
     return 0;
 #endif
 
+    /* FIXME: should this be in the graphics driver? */
     if (!PtVisible32( hdc, x, y )) return 0;
-
-    x = dc->w.DCOrgX + XLPTODP( dc, x );
-    y = dc->w.DCOrgY + YLPTODP( dc, y );
-    if (dc->w.flags & DC_MEMORY)
-    {
-        image = XGetImage( display, dc->u.x.drawable, x, y, 1, 1,
-                           AllPlanes, ZPixmap );
-    }
-    else
-    {
-        /* If we are reading from the screen, use a temporary copy */
-        /* to avoid a BadMatch error */
-        if (!pixmap) pixmap = XCreatePixmap( display, rootWindow,
-                                             1, 1, dc->w.bitsPerPixel );
-        XCopyArea( display, dc->u.x.drawable, pixmap, BITMAP_colorGC,
-                   x, y, 1, 1, 0, 0 );
-        image = XGetImage( display, pixmap, 0, 0, 1, 1, AllPlanes, ZPixmap );
-    }
-    pixel = XGetPixel( image, 0, 0 );
-    XDestroyImage( image );
-    
-    return COLOR_ToLogical(pixel);
+    if (!dc || !dc->funcs->pGetPixel) return 0;
+    return dc->funcs->pGetPixel(dc,x,y);
 }
 
 
@@ -725,35 +388,10 @@
  */
 BOOL32 PaintRgn32( HDC32 hdc, HRGN32 hrgn )
 {
-    RECT32 box;
-    HRGN32 tmpVisRgn, prevVisRgn;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return FALSE;
+    DC * dc = DC_GetDCPtr( hdc );
 
-      /* Modify visible region */
-
-    if (!(prevVisRgn = SaveVisRgn( hdc ))) return FALSE;
-    if (!(tmpVisRgn = CreateRectRgn32( 0, 0, 0, 0 )))
-    {
-        RestoreVisRgn( hdc );
-        return FALSE;
-    }
-    CombineRgn32( tmpVisRgn, prevVisRgn, hrgn, RGN_AND );
-    SelectVisRgn( hdc, tmpVisRgn );
-    DeleteObject32( tmpVisRgn );
-
-      /* Fill the region */
-
-    GetRgnBox32( dc->w.hGCClipRgn, &box );
-    if (DC_SetupGCForBrush( dc ))
-	XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
-		        dc->w.DCOrgX + box.left, dc->w.DCOrgY + box.top,
-		        box.right-box.left, box.bottom-box.top );
-
-      /* Restore the visible region */
-
-    RestoreVisRgn( hdc );
-    return TRUE;
+    return dc && dc->funcs->pPaintRgn &&
+	   dc->funcs->pPaintRgn(dc,hrgn);
 }
 
 
@@ -840,6 +478,8 @@
 
 /***********************************************************************
  *           DrawFocusRect32    (USER32.155)
+ *
+ * FIXME: should use Rectangle32!
  */
 void DrawFocusRect32( HDC32 hdc, const RECT32* rc )
 {
@@ -948,23 +588,13 @@
 BOOL16 Polyline16( HDC16 hdc, LPPOINT16 pt, INT16 count )
 {
     register int i;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return FALSE;
-	MF_MetaPoly(dc, META_POLYLINE, pt, count); 
-	return TRUE;
-    }
+    LPPOINT32 pt32 = (LPPOINT32)xmalloc(count*sizeof(POINT32));
+    BOOL16 ret;
 
-    if (DC_SetupGCForPen( dc ))
-	for (i = 0; i < count-1; i ++)
-	    XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,  
-		       dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
-		       dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
-		       dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
-		       dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
-    return TRUE;
+    for (i=count;i--;) CONV_POINT16TO32(&(pt[i]),&(pt32[i]));
+    ret = Polyline32(hdc,pt32,count);
+    free(pt32);
+    return ret;
 }
 
 
@@ -973,28 +603,10 @@
  */
 BOOL32 Polyline32( HDC32 hdc, const LPPOINT32 pt, INT32 count )
 {
-    register int i;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return FALSE;
-        fprintf( stderr, "Polyline32: Metafile Polyline not yet supported for Win32\n");
-/* win 16 code was:
-	MF_MetaPoly(dc, META_POLYLINE, pt, count); 
-	return TRUE;
-*/
-	return FALSE;
-    }
+    DC * dc = DC_GetDCPtr( hdc );
 
-    if (DC_SetupGCForPen( dc ))
-	for (i = 0; i < count-1; i ++)
-	    XDrawLine (display, dc->u.x.drawable, dc->u.x.gc,  
-		       dc->w.DCOrgX + XLPTODP(dc, pt [i].x),
-		       dc->w.DCOrgY + YLPTODP(dc, pt [i].y),
-		       dc->w.DCOrgX + XLPTODP(dc, pt [i+1].x),
-		       dc->w.DCOrgY + YLPTODP(dc, pt [i+1].y));
-    return TRUE;
+    return dc && dc->funcs->pPolyline &&
+    	   dc->funcs->pPolyline(dc,pt,count);
 }
 
 
@@ -1004,78 +616,26 @@
 BOOL16 Polygon16( HDC16 hdc, LPPOINT16 pt, INT16 count )
 {
     register int i;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    XPoint *points;
+    LPPOINT32 pt32 = (LPPOINT32)xmalloc(count*sizeof(POINT32));
+    BOOL32 ret;
 
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return FALSE;
-	MF_MetaPoly(dc, META_POLYGON, pt, count); 
-	return TRUE;
-    }
 
-    points = (XPoint *) xmalloc (sizeof (XPoint) * (count+1));
-    for (i = 0; i < count; i++)
-    {
-	points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
-	points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
-    }
-    points[count] = points[0];
-
-    if (DC_SetupGCForBrush( dc ))
-	XFillPolygon( display, dc->u.x.drawable, dc->u.x.gc,
-		     points, count+1, Complex, CoordModeOrigin);
-
-    if (DC_SetupGCForPen ( dc ))
-	XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
-		   points, count+1, CoordModeOrigin );
-
-    free( points );
-    return TRUE;
+    for (i=count;i--;) CONV_POINT16TO32(&(pt[i]),&(pt32[i]));
+    ret = Polygon32(hdc,pt32,count);
+    free(pt32);
+    return ret;
 }
 
 
 /**********************************************************************
  *          Polygon32  (GDI32.275)
- *
- * This a copy of Polygon16 so that conversion of array of
- * LPPOINT32 to LPPOINT16 is not necessary
- *
  */
 BOOL32 Polygon32( HDC32 hdc, LPPOINT32 pt, INT32 count )
 {
-    register int i;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    XPoint *points;
+    DC * dc = DC_GetDCPtr( hdc );
 
-    if (!dc)
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return FALSE;
-	/* FIXME: MF_MetaPoly expects LPPOINT16 not 32 */
-	/* MF_MetaPoly(dc, META_POLYGON, pt, count); */
-	return TRUE;
-    }
-
-    points = (XPoint *) xmalloc (sizeof (XPoint) * (count+1));
-    for (i = 0; i < count; i++)
-    {
-	points[i].x = dc->w.DCOrgX + XLPTODP( dc, pt[i].x );
-	points[i].y = dc->w.DCOrgY + YLPTODP( dc, pt[i].y );
-    }
-    points[count] = points[0];
-
-    if (DC_SetupGCForBrush( dc ))
-	XFillPolygon( display, dc->u.x.drawable, dc->u.x.gc,
-		     points, count+1, Complex, CoordModeOrigin);
-
-    if (DC_SetupGCForPen ( dc ))
-	XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
-		   points, count+1, CoordModeOrigin );
-
-    free( points );
-    return TRUE;
+    return dc && dc->funcs->pPolygon &&
+    	   dc->funcs->pPolygon(dc,pt,count);
 }
 
 
@@ -1084,155 +644,37 @@
  */
 BOOL16 PolyPolygon16( HDC16 hdc, LPPOINT16 pt, LPINT16 counts, UINT16 polygons)
 {
-    HRGN32 hrgn;
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    int		i,nrpts;
+    LPPOINT32	pt32;
+    LPINT32	counts32;
+    BOOL16	ret;
 
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return FALSE;
-	/* MF_MetaPoly(dc, META_POLYGON, pt, count); */
-	return TRUE;
-    }
-      /* FIXME: The points should be converted to device coords before */
-      /* creating the region. But as CreatePolyPolygonRgn is not */
-      /* really correct either, it doesn't matter much... */
-      /* At least the outline will be correct :-) */
-    hrgn = CreatePolyPolygonRgn16( pt, counts, polygons, dc->w.polyFillMode );
-    PaintRgn32( hdc, hrgn );
-    DeleteObject32( hrgn );
-
-      /* Draw the outline of the polygons */
-
-    if (DC_SetupGCForPen ( dc ))
-    {
-	int i, j, max = 0;
-	XPoint *points;
-
-	for (i = 0; i < polygons; i++) if (counts[i] > max) max = counts[i];
-	points = (XPoint *) xmalloc( sizeof(XPoint) * (max+1) );
-
-	for (i = 0; i < polygons; i++)
-	{
-	    for (j = 0; j < counts[i]; j++)
-	    {
-		points[j].x = dc->w.DCOrgX + XLPTODP( dc, pt->x );
-		points[j].y = dc->w.DCOrgY + YLPTODP( dc, pt->y );
-		pt++;
-	    }
-	    points[j] = points[0];
-	    XDrawLines( display, dc->u.x.drawable, dc->u.x.gc,
-		        points, j + 1, CoordModeOrigin );
-	}
-	free( points );
-    }
-    return TRUE;
+    nrpts=0;
+    for (i=polygons;i--;)
+    	nrpts+=counts[i];
+    pt32 = (LPPOINT32)xmalloc(sizeof(POINT32)*nrpts);
+    for (i=nrpts;i--;)
+    	CONV_POINT16TO32(&(pt[i]),&(pt32[i]));
+    counts32 = (LPINT32)xmalloc(polygons*sizeof(INT32));
+    for (i=polygons;i--;) counts32[i]=counts[i];
+   
+    ret = PolyPolygon32(hdc,pt32,counts32,polygons);
+    free(counts32);
+    free(pt32);
+    return ret;
 }
 
-
 /**********************************************************************
- *          GRAPH_InternalFloodFill
- *
- * Internal helper function for flood fill.
- * (xorg,yorg) is the origin of the X image relative to the drawable.
- * (x,y) is relative to the origin of the X image.
+ *          PolyPolygon32  (GDI.450)
  */
-static void GRAPH_InternalFloodFill( XImage *image, DC *dc,
-                                     int x, int y,
-                                     int xOrg, int yOrg,
-                                     Pixel pixel, WORD fillType )
+BOOL32 PolyPolygon32( HDC32 hdc, LPPOINT32 pt, LPINT32 counts, UINT32 polygons)
 {
-    int left, right;
+    DC * dc = DC_GetDCPtr( hdc );
 
-#define TO_FLOOD(x,y)  ((fillType == FLOODFILLBORDER) ? \
-                        (XGetPixel(image,x,y) != pixel) : \
-                        (XGetPixel(image,x,y) == pixel))
-
-    if (!TO_FLOOD(x,y)) return;
-
-      /* Find left and right boundaries */
-
-    left = right = x;
-    while ((left > 0) && TO_FLOOD( left-1, y )) left--;
-    while ((right < image->width) && TO_FLOOD( right, y )) right++;
-    XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
-                    xOrg + left, yOrg + y, right-left, 1 );
-
-      /* Set the pixels of this line so we don't fill it again */
-
-    for (x = left; x < right; x++)
-    {
-        if (fillType == FLOODFILLBORDER) XPutPixel( image, x, y, pixel );
-        else XPutPixel( image, x, y, ~pixel );
-    }
-
-      /* Fill the line above */
-
-    if (--y >= 0)
-    {
-        x = left;
-        while (x < right)
-        {
-            while ((x < right) && !TO_FLOOD(x,y)) x++;
-            if (x >= right) break;
-            while ((x < right) && TO_FLOOD(x,y)) x++;
-            GRAPH_InternalFloodFill( image, dc, x-1, y,
-                                     xOrg, yOrg, pixel, fillType );
-        }
-    }
-
-      /* Fill the line below */
-
-    if ((y += 2) < image->height)
-    {
-        x = left;
-        while (x < right)
-        {
-            while ((x < right) && !TO_FLOOD(x,y)) x++;
-            if (x >= right) break;
-            while ((x < right) && TO_FLOOD(x,y)) x++;
-            GRAPH_InternalFloodFill( image, dc, x-1, y,
-                                     xOrg, yOrg, pixel, fillType );
-        }
-    }
-#undef TO_FLOOD    
+    return dc && dc->funcs->pPolyPolygon &&
+    	   dc->funcs->pPolyPolygon(dc,pt,counts,polygons);
 }
 
-
-/**********************************************************************
- *          GRAPH_DoFloodFill
- *
- * Main flood-fill routine.
- */
-static BOOL32 GRAPH_DoFloodFill( DC *dc, RECT32 *rect, INT32 x, INT32 y,
-                                 COLORREF color, UINT32 fillType )
-{
-    XImage *image;
-
-    if (!(image = XGetImage( display, dc->u.x.drawable,
-                             dc->w.DCOrgX + rect->left,
-                             dc->w.DCOrgY + rect->top,
-                             rect->right - rect->left,
-                             rect->bottom - rect->top,
-                             AllPlanes, ZPixmap ))) return FALSE;
-
-    if (DC_SetupGCForBrush( dc ))
-    {
-          /* ROP mode is always GXcopy for flood-fill */
-        XSetFunction( display, dc->u.x.gc, GXcopy );
-        GRAPH_InternalFloodFill( image, dc,
-                                 XLPTODP(dc,x) - rect->left,
-                                 YLPTODP(dc,y) - rect->top,
-                                 dc->w.DCOrgX + rect->left,
-                                 dc->w.DCOrgY + rect->top,
-                                 COLOR_ToPhysical( dc, color ), fillType );
-    }
-
-    XDestroyImage( image );
-    return TRUE;
-}
-
-
 /**********************************************************************
  *          ExtFloodFill16   (GDI.372)
  */
@@ -1249,26 +691,10 @@
 BOOL32 ExtFloodFill32( HDC32 hdc, INT32 x, INT32 y, COLORREF color,
                        UINT32 fillType )
 {
-    RECT32 rect;
-    DC *dc;
+    DC *dc = DC_GetDCPtr( hdc );
 
-    dprintf_graphics( stddeb, "ExtFloodFill %04x %d,%d %06lx %d\n",
-                      hdc, x, y, color, fillType );
-    dc = (DC *) GDI_GetObjPtr(hdc, DC_MAGIC);
-    if (!dc) 
-    {
-	dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-	if (!dc) return FALSE;
-	MF_MetaParam4(dc, META_FLOODFILL, x, y, HIWORD(color), 
-		      LOWORD(color)); 
-	return TRUE;
-    }
-
-    if (!PtVisible32( hdc, x, y )) return FALSE;
-    if (GetRgnBox32( dc->w.hGCClipRgn, &rect ) == ERROR) return FALSE;
-
-    return CallTo32_LargeStack( (int(*)())GRAPH_DoFloodFill, 6,
-                                dc, &rect, x, y, color, fillType );
+    return dc && dc->funcs->pExtFloodFill &&
+	   dc->funcs->pExtFloodFill(dc,x,y,color,fillType);
 }
 
 
diff --git a/windows/hook.c b/windows/hook.c
index f5dd48a..e7a073d 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -109,7 +109,7 @@
                 LPMOUSEHOOKSTRUCT32 lpms32 = HeapAlloc( SystemHeap, 0,
                                                         sizeof(*lpms32) );
 
-                STRUCT32_POINT16to32( &lpms16->pt, &lpms32->pt );
+                CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
 
                 /* wHitTestCode may be negative, so convince compiler to do
                    correct sign extension. Yay. :| */
@@ -126,7 +126,7 @@
                 LPRECT32 lprect32 = HeapAlloc( SystemHeap, 0,
                                                sizeof(*lprect32) );
 
-                STRUCT32_RECT16to32( lprect16, lprect32 );
+                CONV_RECT16TO32( lprect16, lprect32 );
                 *plParam = (LPARAM)lprect32;
                 break;
             }
@@ -138,7 +138,7 @@
             LPMOUSEHOOKSTRUCT32 lpms32 = HeapAlloc( SystemHeap, 0,
                                                     sizeof(*lpms32) );
 
-            STRUCT32_POINT16to32( &lpms16->pt, &lpms32->pt );
+            CONV_POINT16TO32( &lpms16->pt, &lpms32->pt );
 
             /* wHitTestCode may be negative, so convince compiler to do
                correct sign extension. Yay. :| */
@@ -413,7 +413,7 @@
 	      LPMOUSEHOOKSTRUCT32 lpms32 = (LPMOUSEHOOKSTRUCT32)*plParam;
 	      LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
 
-	      STRUCT32_POINT32to16( &lpms32->pt, &lpms16->pt );
+	      CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
 
 	      lpms16->hwnd         = lpms32->hwnd;
 	      lpms16->wHitTestCode = lpms32->wHitTestCode;
@@ -428,7 +428,7 @@
 	      LPRECT32 lprect32 = (LPRECT32)*plParam;
 	      LPRECT16 lprect16 = SEGPTR_NEW( RECT16 );
 
-	      STRUCT32_RECT32to16( lprect32, lprect16 );
+	      CONV_RECT32TO16( lprect32, lprect16 );
 
 	      *plParam = (LPARAM)SEGPTR_GET( lprect16 );
 	      break;
@@ -441,7 +441,7 @@
 	  LPMOUSEHOOKSTRUCT32 lpms32 = (LPMOUSEHOOKSTRUCT32)*plParam;
 	  LPMOUSEHOOKSTRUCT16 lpms16 = SEGPTR_NEW( MOUSEHOOKSTRUCT16 );
 
-	  STRUCT32_POINT32to16( &lpms32->pt, &lpms16->pt );
+	  CONV_POINT32TO16( &lpms32->pt, &lpms16->pt );
 
 	  lpms16->hwnd = lpms32->hwnd;
 	  lpms16->wHitTestCode = lpms32->wHitTestCode;
diff --git a/windows/keyboard.c b/windows/keyboard.c
index d4dcc7f..1a418fd 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -10,6 +10,7 @@
 #include "win.h"
 #include "windows.h"
 #include "accel.h"
+#include "stddebug.h"
 #include "debug.h"
 
 extern BOOL MouseButtonsStates[3];
@@ -25,21 +26,28 @@
  * keyboard-input message.  This function retrieves the state of the key
  * at the time the input message was generated.  (SDK 3.1 Vol 2. p 390)
  */
-INT GetKeyState(INT keycode)
+INT GetKeyState(INT vkey)
 {
     INT retval;
 
-    if( keycode >= VK_LBUTTON && keycode <= VK_RBUTTON )
-	retval = MouseButtonsStates[keycode - VK_LBUTTON];
-    else
-    {
-	if (keycode >= 'a' && keycode <= 'z')
-	    keycode += 'A' - 'a';
-	retval = ( (INT)(QueueKeyStateTable[keycode] & 0x80) << 8 ) |
-		   (INT)(QueueKeyStateTable[keycode] & 0x01);
-    }
-
-    dprintf_key(stddeb, "GetKeyState(%x) -> %x\n", keycode, retval);
+    switch (vkey)
+	{
+	case VK_LBUTTON : /* VK_LBUTTON is 1 */
+	    retval = MouseButtonsStates[0];
+	    break;
+	case VK_MBUTTON : /* VK_MBUTTON is 4 */
+	    retval = MouseButtonsStates[1];
+	    break;
+	case VK_RBUTTON : /* VK_RBUTTON is 2 */
+	    retval = MouseButtonsStates[2];
+	    break;
+	default :
+	    if (vkey >= 'a' && vkey <= 'z')
+		vkey += 'A' - 'a';
+	    retval = ( (INT)(QueueKeyStateTable[vkey] & 0x80) << 8 ) |
+		       (INT)(QueueKeyStateTable[vkey] & 0x01);
+	}
+    dprintf_key(stddeb, "GetKeyState(0x%x) -> %x\n", vkey, retval);
     return retval;
 }
 
@@ -51,6 +59,7 @@
  */
 void GetKeyboardState(BYTE *lpKeyState)
 {
+    dprintf_key(stddeb, "GetKeyboardState()\n");
     if (lpKeyState != NULL) {
 	QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] >> 8;
 	QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] >> 8;
@@ -64,6 +73,7 @@
  */
 void SetKeyboardState(BYTE *lpKeyState)
 {
+    dprintf_key(stddeb, "SetKeyboardState()\n");
     if (lpKeyState != NULL) {
 	memcpy(QueueKeyStateTable, lpKeyState, 256);
 	MouseButtonsStates[0] = QueueKeyStateTable[VK_LBUTTON]? 0x8000: 0;
@@ -195,14 +205,14 @@
             mesg=3;
           else
           {
-            hMenu=GetMenu(hWnd);
-            hSysMenu=GetSystemMenu(hWnd,FALSE);
+            hMenu=GetMenu32(hWnd);
+            hSysMenu=GetSystemMenu32(hWnd,FALSE);
             if (hSysMenu)
-              iSysStat=GetMenuState(hSysMenu,lpAccelTbl->tbl[i].wIDval,MF_BYCOMMAND);
+              iSysStat=GetMenuState32(hSysMenu,lpAccelTbl->tbl[i].wIDval,MF_BYCOMMAND);
             else
               iSysStat=-1;
             if (hMenu)
-              iStat=GetMenuState(hMenu,lpAccelTbl->tbl[i].wIDval,MF_BYCOMMAND);
+              iStat=GetMenuState32(hMenu,lpAccelTbl->tbl[i].wIDval,MF_BYCOMMAND);
             else
               iStat=-1;
             if (iSysStat!=-1)
@@ -241,7 +251,7 @@
 	  {
 	   /*  some reasons for NOT sending the WM_{SYS}COMMAND message: 
 	    *   #0: unknown (please report!)
-	    *   #1: for WM_KEYUP,WM_SYKEYUP
+	    *   #1: for WM_KEYUP,WM_SYSKEYUP
 	    *   #2: mouse is captured
 	    *   #3: window is disabled 
 	    *   #4: it's a disabled system menu option
diff --git a/windows/mdi.c b/windows/mdi.c
index f780b72..f6e5bac 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -101,10 +101,10 @@
 
  if (wndPtr->text) lstrcpyn32A(buffer + n, wndPtr->text, sizeof(buffer) - n );
 
- n    = GetMenuState(clientInfo->hWindowMenu,wndPtr->wIDmenu ,MF_BYCOMMAND); 
+ n    = GetMenuState32(clientInfo->hWindowMenu,wndPtr->wIDmenu ,MF_BYCOMMAND); 
  bRet = ModifyMenu32A(clientInfo->hWindowMenu , wndPtr->wIDmenu, 
                       MF_BYCOMMAND | MF_STRING, wndPtr->wIDmenu, buffer );
- CheckMenuItem(clientInfo->hWindowMenu ,wndPtr->wIDmenu , n & MF_CHECKED);
+ CheckMenuItem32(clientInfo->hWindowMenu ,wndPtr->wIDmenu , n & MF_CHECKED);
  return bRet;
 }
 
@@ -122,7 +122,7 @@
      !clientInfo->hWindowMenu ) return 0;
 
  id = wndPtr->wIDmenu;
- DeleteMenu(clientInfo->hWindowMenu,id,MF_BYCOMMAND);
+ DeleteMenu32(clientInfo->hWindowMenu,id,MF_BYCOMMAND);
 
  /* walk the rest of MDI children to prevent gaps in the id 
   * sequence and in the menu child list */
@@ -226,7 +226,7 @@
     if (!fRefresh) 
        {
 	HWND hwndFrame = GetParent16(hwnd);
-	HMENU16 oldFrameMenu = GetMenu(hwndFrame);
+	HMENU32 oldFrameMenu = GetMenu32(hwndFrame);
         
 	if( ci->hwndChildMaximized && hmenuFrame && hmenuFrame!=oldFrameMenu )
 	    MDI_RestoreFrameMenu(w->parent, ci->hwndChildMaximized );
@@ -236,8 +236,8 @@
 	    /* delete menu items from ci->hWindowMenu 
 	     * and add them to hmenuWindow */
 
-            INT		i = GetMenuItemCount(ci->hWindowMenu) - 1;
-	    INT 	pos = GetMenuItemCount(hmenuWindow) + 1;
+            INT32 i = GetMenuItemCount32(ci->hWindowMenu) - 1;
+	    INT32 pos = GetMenuItemCount32(hmenuWindow) + 1;
 
             AppendMenu32A( hmenuWindow, MF_SEPARATOR, 0, NULL);
 
@@ -249,27 +249,27 @@
 
 		for( ; i >= j ; i-- )
 		   {
-		     id = GetMenuItemID(ci->hWindowMenu,i );
-		     state = GetMenuState(ci->hWindowMenu,i,MF_BYPOSITION); 
+		     id = GetMenuItemID32(ci->hWindowMenu,i );
+		     state = GetMenuState32(ci->hWindowMenu,i,MF_BYPOSITION); 
 
-		     GetMenuString(ci->hWindowMenu, i, buffer, 100, MF_BYPOSITION);
+		     GetMenuString32A(ci->hWindowMenu, i, buffer, 100, MF_BYPOSITION);
 
-		     DeleteMenu(ci->hWindowMenu, i , MF_BYPOSITION);
+		     DeleteMenu32(ci->hWindowMenu, i , MF_BYPOSITION);
 		     InsertMenu32A(hmenuWindow, pos, MF_BYPOSITION | MF_STRING,
 					     id, buffer);
-		     CheckMenuItem(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
+		     CheckMenuItem32(hmenuWindow ,pos , MF_BYPOSITION | (state & MF_CHECKED));
 		   }
 	      }
 
 	    /* remove separator */
-	    DeleteMenu(ci->hWindowMenu, i, MF_BYPOSITION); 
+	    DeleteMenu32(ci->hWindowMenu, i, MF_BYPOSITION); 
 
 	    ci->hWindowMenu = hmenuWindow;
 	  } 
 
 	if( hmenuFrame && hmenuFrame!=oldFrameMenu)
 	  {
-	    SetMenu(hwndFrame, hmenuFrame);
+	    SetMenu32(hwndFrame, hmenuFrame);
 	    if( ci->hwndChildMaximized )
 	        MDI_AugmentFrameMenu(ci, w->parent, ci->hwndChildMaximized );
 	    return oldFrameMenu;
@@ -386,7 +386,7 @@
     else
     {
 	ci->nActiveChildren--;
-	DeleteMenu(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND);
+	DeleteMenu32(ci->hWindowMenu,wIDmenu,MF_BYCOMMAND);
 	if( IsWindow(hwndMax) )
 	    ShowWindow(hwndMax, SW_SHOWMAXIMIZED);
     }
@@ -550,8 +550,8 @@
 #endif 
         /* uncheck menu item */
        	if( clientInfo->hWindowMenu )
-       	        CheckMenuItem( clientInfo->hWindowMenu,
-       	                       wndPrev->wIDmenu, 0);
+       	        CheckMenuItem32( clientInfo->hWindowMenu,
+                                 wndPrev->wIDmenu, 0);
       }
 
     /* set appearance */
@@ -578,8 +578,8 @@
 	
     /* check menu item */
     if( clientInfo->hWindowMenu )
-              CheckMenuItem( clientInfo->hWindowMenu,
-                             wndPtr->wIDmenu, MF_CHECKED);
+              CheckMenuItem32( clientInfo->hWindowMenu,
+                               wndPtr->wIDmenu, MF_CHECKED);
 
     /* bring active child to the top */
     SetWindowPos( hWndChild, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
@@ -853,21 +853,21 @@
  
  if( !InsertMenu32A(frame->wIDmenu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
                     hSysPopup, (LPSTR)(DWORD)hBmpClose ))
-   {  DestroyMenu(hSysPopup); return 0; }
+   {  DestroyMenu32(hSysPopup); return 0; }
 
  if( !AppendMenu32A(frame->wIDmenu,MF_HELP | MF_BITMAP,
                     SC_RESTORE, (LPSTR)(DWORD)hBmpRestore ))
    {
-      RemoveMenu(frame->wIDmenu,0,MF_BYPOSITION);
+      RemoveMenu32(frame->wIDmenu,0,MF_BYPOSITION);
       return 0;
    }
 
- EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
- EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem32(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem32(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem32(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
 
  /* redraw menu */
- DrawMenuBar(frame->hwndSelf);
+ DrawMenuBar32(frame->hwndSelf);
 
  return 1;
 }
@@ -877,18 +877,18 @@
  */
 BOOL MDI_RestoreFrameMenu( WND *frameWnd, HWND hChild)
 {
- INT	nItems   = GetMenuItemCount(frameWnd->wIDmenu) - 1;
+ INT32 nItems = GetMenuItemCount32(frameWnd->wIDmenu) - 1;
 
  dprintf_mdi(stddeb,"MDI_RestoreFrameMenu: for child %04x\n",hChild);
 
- if( GetMenuItemID(frameWnd->wIDmenu,nItems) != SC_RESTORE )
+ if( GetMenuItemID32(frameWnd->wIDmenu,nItems) != SC_RESTORE )
      return 0; 
 
 
- RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
- DeleteMenu(frameWnd->wIDmenu,nItems-1,MF_BYPOSITION);
+ RemoveMenu32(frameWnd->wIDmenu,0,MF_BYPOSITION);
+ DeleteMenu32(frameWnd->wIDmenu,nItems-1,MF_BYPOSITION);
 
- DrawMenuBar(frameWnd->hwndSelf);
+ DrawMenuBar32(frameWnd->hwndSelf);
 
  return 1;
 }
@@ -1019,11 +1019,11 @@
       
       case WM_DESTROY:
 	if( ci->hwndChildMaximized ) MDI_RestoreFrameMenu(w, frameWnd->hwndSelf);
-	if((nItems = GetMenuItemCount(ci->hWindowMenu)) > 0) {
+	if((nItems = GetMenuItemCount32(ci->hWindowMenu)) > 0) {
     	    ci->idFirstChild = nItems - 1;
 	    ci->nActiveChildren++; 		/* to delete a separator */
 	    while( ci->nActiveChildren-- )
-	        DeleteMenu(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--);
+	        DeleteMenu32(ci->hWindowMenu,MF_BYPOSITION,ci->idFirstChild--);
 	}
 	return 0;
 
@@ -1231,11 +1231,11 @@
 		if( wParam == VK_LEFT ) 
 		  { if( wndPtr->parent->wIDmenu != LOWORD(lParam) ) break; }
 		else if( wParam == VK_RIGHT )
-		  { if( GetSystemMenu( wndPtr->parent->hwndSelf, 0) 
-				       != LOWORD(lParam) ) break; }
+		  { if( GetSystemMenu16( wndPtr->parent->hwndSelf, 0) 
+                          != LOWORD(lParam) ) break; }
 		else break;
 		
-		return MAKELONG( GetSystemMenu(ci->hwndActiveChild, 0), 
+		return MAKELONG( GetSystemMenu16(ci->hwndActiveChild, 0), 
 				 ci->hwndActiveChild );
 	      }
 	    break;
@@ -1449,7 +1449,7 @@
       case WM_NEXTMENU:
 
 	if( wParam == VK_LEFT )		/* switch to frame system menu */
-	  return MAKELONG( GetSystemMenu(clientWnd->parent->hwndSelf, 0), 
+	  return MAKELONG( GetSystemMenu16(clientWnd->parent->hwndSelf, 0), 
 			   clientWnd->parent->hwndSelf );
 	if( wParam == VK_RIGHT )	/* to frame menu bar */
 	  return MAKELONG( clientWnd->parent->wIDmenu,
diff --git a/windows/message.c b/windows/message.c
index 70b3043..203d7e8 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -1166,6 +1166,48 @@
  * by the keyboard driver.
  */
 
+const struct accent_char
+	{
+	BYTE ac_accent;
+	BYTE ac_char;
+	BYTE ac_result;
+	} accent_chars[] =
+	{
+	{'`', 'A', '\300'},	{'`', 'a', '\340'},
+	{'\'', 'A', '\301'},	{'\'', 'a', '\341'},
+	{'^', 'A', '\302'},	{'^', 'a', '\342'},
+	{'~', 'A', '\303'},	{'~', 'a', '\343'},
+	{'"', 'A', '\304'},	{'"', 'a', '\344'},
+	{'O', 'A', '\305'},	{'o', 'a', '\345'},
+	{'0', 'A', '\305'},	{'0', 'a', '\345'},
+	{'A', 'A', '\305'},	{'a', 'a', '\345'},
+	{'A', 'E', '\306'},	{'a', 'e', '\346'},
+	{',', 'C', '\307'},	{',', 'c', '\347'},
+	{'`', 'E', '\310'},	{'`', 'e', '\350'},
+	{'\'', 'E', '\311'},	{'\'', 'e', '\351'},
+	{'^', 'E', '\312'},	{'^', 'e', '\352'},
+	{'"', 'E', '\313'},	{'"', 'e', '\353'},
+	{'`', 'I', '\314'},	{'`', 'i', '\354'},
+	{'\'', 'I', '\315'},	{'\'', 'i', '\355'},
+	{'^', 'I', '\316'},	{'^', 'i', '\356'},
+	{'"', 'I', '\317'},	{'"', 'i', '\357'},
+	{'-', 'D', '\320'},	{'-', 'd', '\360'},
+	{'~', 'N', '\321'},	{'~', 'n', '\361'},
+	{'`', 'O', '\322'},	{'`', 'o', '\362'},
+	{'\'', 'O', '\323'},	{'\'', 'o', '\363'},
+	{'^', 'O', '\324'},	{'^', 'o', '\364'},
+	{'~', 'O', '\325'},	{'~', 'o', '\365'},
+	{'"', 'O', '\326'},	{'"', 'o', '\366'},
+	{'/', 'O', '\330'},	{'/', 'o', '\370'},
+	{'`', 'U', '\331'},	{'`', 'u', '\371'},
+	{'\'', 'U', '\332'},	{'\'', 'u', '\372'},
+	{'^', 'U', '\333'},	{'^', 'u', '\373'},
+	{'"', 'U', '\334'},	{'"', 'u', '\374'},
+	{'\'', 'Y', '\335'},	{'\'', 'y', '\375'},
+	{'T', 'H', '\336'},	{'t', 'h', '\376'},
+	{'s', 's', '\337'},	{'"', 'y', '\377'},
+	{'s', 'z', '\337'},	{'i', 'j', '\377'},
+	};
 
 BOOL TranslateMessage( LPMSG16 msg )
 {
@@ -1176,25 +1218,54 @@
 	&& message != WM_MOUSEMOVE && message != WM_TIMER)
     || (debugging_key
 	&& message >= WM_KEYFIRST && message <= WM_KEYLAST))
-	    fprintf(stddeb, "TranslateMessage(%s, %04x, %08lx)\n",
+	    fprintf(stddeb, "TranslateMessage(%s, %04X, %08lX)\n",
 		SPY_GetMsgName(msg->message), msg->wParam, msg->lParam);
     if ((message == WM_KEYDOWN) || (message == WM_SYSKEYDOWN))
     {
+	static dead_char;
+
 	if (debugging_msg || debugging_key)
-	    fprintf(stddeb, "Translating key %04x, scancode %04x\n",
+	    fprintf(stddeb, "Translating key %04X, scancode %04X\n",
 		msg->wParam, HIWORD(msg->lParam) );
 
 	/* FIXME : should handle ToAscii yielding 2 */
-	if (ToAscii(msg->wParam, HIWORD(msg->lParam), (LPSTR)&QueueKeyStateTable,
-				      wparam, 0)) 
-	      {
-		/* Map WM_KEY* to WM_*CHAR */
-		message += 2 - (message & 0x0001); 
+	switch (ToAscii(msg->wParam, HIWORD(msg->lParam),
+		(LPSTR)&QueueKeyStateTable, wparam, 0)) 
+	    {
+	    case 1 :
+		message = message == WM_KEYDOWN ? WM_CHAR : WM_SYSCHAR;
+		/* Should dead chars handling go in ToAscii ? */
+		if (dead_char)
+		    {
+		    int i;
 
+		    if (wparam[0] == ' ')
+			wparam[0] =  dead_char;
+		    if (dead_char == 0xa8)
+			dead_char = '"';
+		    else if (dead_char == 0xb4)
+			dead_char = '\'';
+		    for (i = 0;
+			i < sizeof(accent_chars) / sizeof(accent_chars[0]);
+			i += 1)
+			if (accent_chars[i].ac_accent == dead_char
+			&& accent_chars[i].ac_char == wparam[0])
+			    {
+			    wparam[0] = accent_chars[i].ac_result;
+			    break;
+			    }
+		    dead_char = 0;
+		    }
+dprintf_key(stddeb, "1 -> PostMessage(%s)\n", SPY_GetMsgName(message));
 		PostMessage( msg->hwnd, message, wparam[0], msg->lParam );
-
 		return TRUE;
-	      }
+	    case -1 :
+		message = message == WM_KEYDOWN ? WM_DEADCHAR : WM_SYSDEADCHAR;
+		dead_char = wparam[0];
+dprintf_key(stddeb, "-1 -> PostMessage(%s)\n", SPY_GetMsgName(message));
+		PostMessage( msg->hwnd, message, wparam[0], msg->lParam );
+		return TRUE;
+	    }
     }
     return FALSE;
 }
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 20e2c6f..2f93a6a 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -268,7 +268,7 @@
  * but without the borders (if any).
  * The rectangle is in window coordinates (for drawing with GetWindowDC()).
  */
-static void NC_GetInsideRect( HWND hwnd, RECT16 *rect )
+static void NC_GetInsideRect( HWND hwnd, RECT32 *rect )
 {
     WND * wndPtr = WIN_FindWndPtr( hwnd );
 
@@ -282,16 +282,16 @@
       /* Remove frame from rectangle */
     if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
     {
-	InflateRect16( rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
+	InflateRect32( rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
 	if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
-            InflateRect16( rect, -1, 0 );
+            InflateRect32( rect, -1, 0 );
     }
     else
     {
 	if (HAS_THICKFRAME( wndPtr->dwStyle ))
-	    InflateRect16( rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
+	    InflateRect32( rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
 	if (wndPtr->dwStyle & WS_BORDER)
-	    InflateRect16( rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
+	    InflateRect32( rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
     }
 }
 
@@ -433,9 +433,9 @@
 /***********************************************************************
  *           NC_DrawSysButton
  */
-void NC_DrawSysButton( HWND hwnd, HDC16 hdc, BOOL32 down )
+void NC_DrawSysButton( HWND32 hwnd, HDC32 hdc, BOOL32 down )
 {
-    RECT16 rect;
+    RECT32 rect;
     HDC32 hdcMem;
     HBITMAP32 hbitmap;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
@@ -459,7 +459,7 @@
  */
 static void NC_DrawMaxButton( HWND hwnd, HDC16 hdc, BOOL down )
 {
-    RECT16 rect;
+    RECT32 rect;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
 
     if( !(wndPtr->flags & WIN_MANAGED) )
@@ -479,13 +479,13 @@
  */
 static void NC_DrawMinButton( HWND hwnd, HDC16 hdc, BOOL down )
 {
-    RECT16 rect;
+    RECT32 rect;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
 
     if( !(wndPtr->flags & WIN_MANAGED) )
     {
       NC_GetInsideRect( hwnd, &rect );
-      if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= SYSMETRICS_CXSIZE + 1;
+      if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= SYSMETRICS_CXSIZE+1;
       GRAPH_DrawBitmap( hdc, (down ? hbitmapMinimizeD : hbitmapMinimize),
 		        rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
 		        0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
@@ -723,7 +723,8 @@
 
     if (HAS_MENU(wndPtr))
     {
-	RECT16 r = rect;
+	RECT32 r;
+        CONV_RECT16TO32( &rect, &r );
 	r.bottom = rect.top + SYSMETRICS_CYMENU;  /* default height */
 	rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
     }
@@ -844,18 +845,18 @@
 /***********************************************************************
  *           NC_GetSysPopupPos
  */
-BOOL32 NC_GetSysPopupPos( WND* wndPtr, RECT16* rect )
+BOOL32 NC_GetSysPopupPos( WND* wndPtr, RECT32* rect )
 {
   if( wndPtr->hSysMenu )
   {
       if( wndPtr->dwStyle & WS_MINIMIZE )
-	  GetWindowRect16( wndPtr->hwndSelf, rect );
+	  GetWindowRect32( wndPtr->hwndSelf, rect );
       else
       {
   	  NC_GetInsideRect( wndPtr->hwndSelf, rect );
-  	  OffsetRect16( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top );
+  	  OffsetRect32( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
   	  if (wndPtr->dwStyle & WS_CHILD)
-     	      ClientToScreen16( wndPtr->parent->hwndSelf, (POINT16 *)rect );
+     	      ClientToScreen32( wndPtr->parent->hwndSelf, (POINT32 *)rect );
           rect->right = rect->left + SYSMETRICS_CXSIZE;
           rect->bottom = rect->top + SYSMETRICS_CYSIZE;
       }
@@ -882,12 +883,13 @@
 	if( !iconic ) 
 	{
 	     HDC16	hdc = GetWindowDC32(hwnd);
-	     RECT16	rect, rTrack;
+	     RECT32	rect;
+             RECT16     rTrack;
 	     BOOL32 	bNew, bTrack = TRUE;
 	     MSG16	msg;
 	    
 	     NC_GetSysPopupPos( wndPtr, &rect );
-	     rTrack = rect;
+             CONV_RECT32TO16( &rect, &rTrack );
 	     MapWindowPoints16( 0, hwnd, (LPPOINT16)&rTrack, 2 );
 
 	     /* track mouse while waiting for WM_LBUTTONUP */
@@ -936,7 +938,7 @@
     if ((wParam & 0xfff0) == SC_MOVE)
     {
 	  /* Move pointer at the center of the caption */
-	RECT16 rect;
+	RECT32 rect;
 	NC_GetInsideRect( hwnd, &rect );
 	if (wndPtr->dwStyle & WS_SYSMENU)
 	    rect.left += SYSMETRICS_CXSIZE + 1;
@@ -1450,7 +1452,8 @@
 	break;
 
     case SC_MOUSEMENU:
-        MENU_TrackMouseMenuBar( wndPtr, wParam & 0x000F, pt );
+        CONV_POINT16TO32( &pt, &pt32 );
+        MENU_TrackMouseMenuBar( wndPtr, wParam & 0x000F, pt32 );
 	break;
 
     case SC_KEYMENU:
diff --git a/windows/win.c b/windows/win.c
index aae3d6d..0966b49 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -360,8 +360,8 @@
     }
 
     if (!(wndPtr->dwStyle & WS_CHILD))
-       if (wndPtr->wIDmenu) DestroyMenu( (HMENU16)wndPtr->wIDmenu );
-    if (wndPtr->hSysMenu) DestroyMenu( wndPtr->hSysMenu );
+       if (wndPtr->wIDmenu) DestroyMenu32( (HMENU32)wndPtr->wIDmenu );
+    if (wndPtr->hSysMenu) DestroyMenu32( wndPtr->hSysMenu );
     if (wndPtr->window) EVENT_DestroyWindow( wndPtr );
     if (wndPtr->class->style & CS_OWNDC) DCE_FreeDCE( wndPtr->dce );
 
@@ -702,7 +702,7 @@
 
     if ((cs->style & WS_CAPTION) && !(cs->style & WS_CHILD))
     {
-        if (cs->hMenu) SetMenu(hwnd, cs->hMenu);
+        if (cs->hMenu) SetMenu32(hwnd, cs->hMenu);
         else
         {
 #if 0  /* FIXME: should check if classPtr->menuNameW can be used as is */
@@ -715,7 +715,7 @@
             if (menuName) cs->hMenu = LoadMenu16( cs->hInstance, menuName );
 #endif
         }
-        if (cs->hMenu) SetMenu( hwnd, cs->hMenu );
+        if (cs->hMenu) SetMenu32( hwnd, cs->hMenu );
     }
     else wndPtr->wIDmenu = (UINT)cs->hMenu;
 
diff --git a/windows/winpos.c b/windows/winpos.c
index 9061686..40516f3 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -1506,6 +1506,33 @@
 
 
 /***********************************************************************
+ *           WINPOS_FindDeskTopXWindow
+ *
+ * Find the actual X window which needs be restacked.
+ * Used by WINPOS_SetXWindowPos().
+ */
+static Window WINPOS_FindDeskTopXWindow( WND *wndPtr )
+{
+    if (!(wndPtr->flags & WIN_MANAGED))
+        return wndPtr->window;
+    else
+    {
+        Window window, root, parent, *children;
+        int nchildren;
+        window = wndPtr->window;
+        for (;;)
+        {
+            XQueryTree( display, window, &root, &parent,
+                        &children, &nchildren );
+            XFree( children );
+            if (parent == root)
+                return window;
+            window = parent;
+        }
+    }
+}
+
+/***********************************************************************
  *           WINPOS_SetXWindowPos
  *
  * SetWindowPos() for an X window. Used by the real SetWindowPos().
@@ -1560,8 +1587,8 @@
             WND*   insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
 	    Window stack[2];
 
-	    stack[0] = insertPtr->window;
-	    stack[1] = wndPtr->window;
+	    stack[0] = WINPOS_FindDeskTopXWindow( insertPtr );
+	    stack[1] = WINPOS_FindDeskTopXWindow( wndPtr );
 
 	    /* for stupid window managers (i.e. all of them) */
 
@@ -1644,7 +1671,8 @@
 	 if( wnd->parent != wndPtr->parent ) return FALSE;
 	 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
        }
-    else
+    else if (!(wndPtr->window))
+         /* FIXME: the following optimization is no good for "X-ed" windows */
        if (hwndInsertAfter == HWND_TOP)
 	   flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
        else /* HWND_BOTTOM */
diff --git a/wine.man b/wine.man
index 0247164..395b840 100644
--- a/wine.man
+++ b/wine.man
@@ -56,9 +56,6 @@
 .B configure.
 .SH OPTIONS
 .TP
-.I -allowreadonly
-Read only files may be opened in write mode
-.TP
 .I -backingstore
 Turn on backing store
 .TP
@@ -98,6 +95,11 @@
 GDI32, LZ32, MPR, NTDLL, OLE32, SHELL32, USER32, VER, VERSION, W32SYS, WINMM,
 WINSPOOL, WSOCK32
 .TP
+.I -failreadonly
+Read only files may not be opened in write mode (the default is to
+allow opening read-only files for writing, because most Windows
+programs always request read-write access, even on CD-ROM drives...).
+.TP
 .I -fixedmap
 Use a "standard" color map.
 .TP