Release 961201

Sat Nov 30 19:21:17 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [configure]
	Re-generated with autoconf 2.11. Let me know if you have
	problems.

	* [controls/listbox.c] [controls/oldlbox.c]
	Listboxes rewritten from scratch. Moved old code still used by
	comboboxes to oldlbox.c

	* [misc/registry.c]
	Use temporary file when saving registry.

	* [windows/dialog.c]
	Implemented Win32 version of DlgDirList() and DlgDirListComboBox().

	* [windows/winproc.c]
	Added translation for listbox Win32 messages.

Sat Nov 30 21:00:00 Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [controls/widgets.c] [controls/button.c]
	Fixed some incompatibilities with CTL3D DLL.

	* [windows/dialog.c]
	Made dialog windows fit into the desktop.

	* [misc/winsock.c] [misc/winsock_async.c]
	New Winsock engine.

	* [windows/message.c]
	GetMessage() fixes.

	* [windows/queue.c] [windows/hook.c] [windows/win.c]
	SetMessageQueue() fixes.

Fri Nov 29 10:25:12 1996  Slaven Rezic  <eserte@cs.tu-berlin.de>

	* [objects/text.c]
	DrawText16(): Fixed return value.

Tue Nov 26 14:47:09 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [files/profile.c] [*/*]
	Added Win32 profile functions, updated to new naming standard.

	* [objects/font.c] [if1632/thunk.c] [include/windows.h]
	Added EnumFonts32*, EnumFontFamiliesEx*, changed prototypes and
	structures.

	* [misc/ole2nls.c] [if1632/thunk.c]
	Added EnumSystemLocales() (winhelp.exe).

	* [misc/registry.c]
	Added Windows 3.1 registry loader supplied by Tor Sjxwall, tor@sn.no

	* [win32/file.c]
	Partially fixed CreateFileMapping(), added UnmapViewOfFile().

Sat Nov 23 23:36:05 1996  Ronan Waide  <waider@waider.ie>

	* [misc/shell.c]
	Fixed some FIXMEs relating to ShellExec() and FindExecutable().

	* [misc/main.c]
	Implemented a few more of the SystemParametersInfo() cases.

Tue Nov 19 01:24:34 1996  Philippe De Muyter  <phdm@info.ucl.ac.be>

	* [include/keyboard.h]
	New file, new macro WINE_VKEY_MAPPINGS (using code taken from event.c).

	* [include/windows.h]
	New [VK_A, VK_Z] and [VK_0, VK9] macros.

	* [misc/keyboard.c]
	Fixes in KeyTable and ToAscii.

	* [objects/font.c]
	FONT_init : Give default value for MSWIN "system" font.
	FONT_MatchFont : Do not try every size of a font family if the
	family does not exist.

	* [windows/event.c]
	lastEventChar hack removed.
	KeyStateTable replaced by InputKeyStateTable (maintained in event.c)
	and QueueKeyStateTable (maintained in message.c).
	EVENT_key : Corrections to the extended bit setting.

	* [windows/message.c] [windows/keyboard.c]
	Implementation of a new QueueKeyStateTable : table of key states
	valid when messages are retrieved by GetMessage or PeekMessage,
	and valid for TranslateMessage.
	TranslateMessage : Convert WM*KEY messages using QueueKeyStateTable
	and ToAscii.
	
Mon Nov 18 16:59:01 1996  Robert Pouliot <krynos@clic.net>

	* [graphics/Makefile.in] [graphics/wing.c]
	  [if1632/wing.spec]
	Some functions for WinG support, mostly empty stubs.

	* [misc/crtdll.c] [if1632/crtdll.spec]
	Many functions added to CRTDLL, mostly calls to Unix C library.
diff --git a/ANNOUNCE b/ANNOUNCE
index a999ecd..38e3e59 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,13 +1,15 @@
-This is release 961117 of Wine, the MS Windows emulator.  This is still a
+This is release 961201 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-961117: (see ChangeLog for details)
-	- More Win32 functions.
-	- OffiX-style drag and drop.
+WHAT'S NEW with Wine-961201: (see ChangeLog for details)
+	- Better Winsock.
+	- Rewritten listboxes.
+	- Windows 3.1 registry loader.
+	- Improved keyboard support.
 	- 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-961117.tar.gz
-  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-961117.tar.gz
-  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-961117.tar.gz
-  ftp://aris.com/pub/linux/ALPHA/Wine/development/Wine-961117.tar.gz
+  ftp://sunsite.unc.edu/pub/Linux/ALPHA/wine/development/Wine-961201.tar.gz
+  ftp://tsx-11.mit.edu/pub/linux/ALPHA/Wine/development/Wine-961201.tar.gz
+  ftp://ftp.infomagic.com/pub/mirrors/linux/wine/development/Wine-961201.tar.gz
+  ftp://aris.com/pub/linux/ALPHA/Wine/development/Wine-961201.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index d848a91..0ef8d33 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,110 @@
 ----------------------------------------------------------------------
+Sat Nov 30 19:21:17 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [configure]
+	Re-generated with autoconf 2.11. Let me know if you have
+	problems.
+
+	* [controls/listbox.c] [controls/oldlbox.c]
+	Listboxes rewritten from scratch. Moved old code still used by
+	comboboxes to oldlbox.c
+
+	* [misc/registry.c]
+	Use temporary file when saving registry.
+
+	* [windows/dialog.c]
+	Implemented Win32 version of DlgDirList() and DlgDirListComboBox().
+
+	* [windows/winproc.c]
+	Added translation for listbox Win32 messages.
+
+Sat Nov 30 21:00:00 Alex Korobka <alex@trantor.pharm.sunysb.edu>
+
+	* [controls/widgets.c] [controls/button.c]
+	Fixed some incompatibilities with CTL3D DLL.
+
+	* [windows/dialog.c]
+	Made dialog windows fit into the desktop.
+
+	* [misc/winsock.c] [misc/winsock_async.c]
+	New Winsock engine.
+
+	* [windows/message.c]
+	GetMessage() fixes.
+
+	* [windows/queue.c] [windows/hook.c] [windows/win.c]
+	SetMessageQueue() fixes.
+
+Fri Nov 29 10:25:12 1996  Slaven Rezic  <eserte@cs.tu-berlin.de>
+
+	* [objects/text.c]
+	DrawText16(): Fixed return value.
+
+Tue Nov 26 14:47:09 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
+
+	* [files/profile.c] [*/*]
+	Added Win32 profile functions, updated to new naming standard.
+
+	* [objects/font.c] [if1632/thunk.c] [include/windows.h]
+	Added EnumFonts32*, EnumFontFamiliesEx*, changed prototypes and
+	structures.
+
+	* [misc/ole2nls.c] [if1632/thunk.c]
+	Added EnumSystemLocales() (winhelp.exe).
+
+	* [misc/registry.c]
+	Added Windows 3.1 registry loader supplied by Tor Sjxwall, tor@sn.no
+
+	* [win32/file.c]
+	Partially fixed CreateFileMapping(), added UnmapViewOfFile().
+
+Sat Nov 23 23:36:05 1996  Ronan Waide  <waider@waider.ie>
+
+	* [misc/shell.c]
+	Fixed some FIXMEs relating to ShellExec() and FindExecutable().
+
+	* [misc/main.c]
+	Implemented a few more of the SystemParametersInfo() cases.
+
+Tue Nov 19 01:24:34 1996  Philippe De Muyter  <phdm@info.ucl.ac.be>
+
+	* [include/keyboard.h]
+	New file, new macro WINE_VKEY_MAPPINGS (using code taken from event.c).
+
+	* [include/windows.h]
+	New [VK_A, VK_Z] and [VK_0, VK9] macros.
+
+	* [misc/keyboard.c]
+	Fixes in KeyTable and ToAscii.
+
+	* [objects/font.c]
+	FONT_init : Give default value for MSWIN "system" font.
+	FONT_MatchFont : Do not try every size of a font family if the
+	family does not exist.
+
+	* [windows/event.c]
+	lastEventChar hack removed.
+	KeyStateTable replaced by InputKeyStateTable (maintained in event.c)
+	and QueueKeyStateTable (maintained in message.c).
+	EVENT_key : Corrections to the extended bit setting.
+
+	* [windows/message.c] [windows/keyboard.c]
+	Implementation of a new QueueKeyStateTable : table of key states
+	valid when messages are retrieved by GetMessage or PeekMessage,
+	and valid for TranslateMessage.
+	TranslateMessage : Convert WM*KEY messages using QueueKeyStateTable
+	and ToAscii.
+	
+Mon Nov 18 16:59:01 1996  Robert Pouliot <krynos@clic.net>
+
+	* [graphics/Makefile.in] [graphics/wing.c]
+	  [if1632/wing.spec]
+	Some functions for WinG support, mostly empty stubs.
+
+	* [misc/crtdll.c] [if1632/crtdll.spec]
+	Many functions added to CRTDLL, mostly calls to Unix C library.
+
+----------------------------------------------------------------------
 Sun Nov 17 15:01:45 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
 
 	* [graphics/bitblt.c] [graphics/x11drv/bitblt.c]
diff --git a/Make.rules.in b/Make.rules.in
index f8d1c90..2599eda 100644
--- a/Make.rules.in
+++ b/Make.rules.in
@@ -59,7 +59,7 @@
 	echo "#include \"windows.h\"" >winerctmp.c
 	echo WINDOWS_H_ENDS_HERE >>winerctmp.c
 	cat $< >>winerctmp.c
-	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P winerctmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) -c -o $* -p $*
+	$(CPP) $(DEFS) $(OPTIONS) $(DIVINCL) -DRC_INVOKED -P winerctmp.c | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | $(WINERC) $(RCFLAGS) -c -o $* -p $*
 	$(RM) winerctmp.c
 
 
diff --git a/configure b/configure
index 6d3c83d..e6d67cf 100755
--- a/configure
+++ b/configure
@@ -2,7 +2,7 @@
 
 # From configure.in configure.in 1.00
 # Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.10-patched 
+# Generated automatically using autoconf version 2.11 
 # Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
 #
 # This configure script is free software; the Free Software Foundation
@@ -58,6 +58,8 @@
 # Initialize some other variables.
 subdirs=
 MFLAGS= MAKEFLAGS=
+# Maximum number of lines to put in a shell here document.
+ac_max_here_lines=12
 
 ac_prev=
 for ac_option
@@ -339,7 +341,7 @@
     verbose=yes ;;
 
   -version | --version | --versio | --versi | --vers)
-    echo "configure generated by autoconf version 2.10-patched"
+    echo "configure generated by autoconf version 2.11"
     exit 0 ;;
 
   -with-* | --with-*)
@@ -543,8 +545,6 @@
 
 
 # We want these before the checks, so the checks can modify their values.
-test -z "$CFLAGS" && CFLAGS="-g -O2" 
-test -z "$LDFLAGS" && LDFLAGS=-g 
 test -z "$LDLIBS" && LDLIBS=-lm 
 
 
@@ -576,7 +576,8 @@
 
 
 echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-set dummy ${MAKE-make}; ac_make=$2
+echo "configure:580: 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
 else
@@ -604,6 +605,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:609: 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
@@ -632,6 +634,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:638: 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
@@ -678,7 +681,42 @@
   test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
 fi
 
+echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
+echo "configure:686: 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.
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
+
+cat > conftest.$ac_ext <<EOF
+#line 695 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:702: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  rm -rf conftest*
+  ac_cv_prog_cc_works=yes
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_cv_prog_cc_works=no
+fi
+rm -f conftest*
+
+
+echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
+if test $ac_cv_prog_cc_works = no; then
+  { echo "configure: error: Installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
+fi
+
 echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+echo "configure:720: 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
@@ -687,7 +725,7 @@
   yes;
 #endif
 EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:691: \"$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:729: \"$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
@@ -695,10 +733,14 @@
 fi
 
 echo "$ac_t""$ac_cv_prog_gcc" 1>&6
+
 if test $ac_cv_prog_gcc = yes; then
   GCC=yes
-  if test "${CFLAGS+set}" != set; then
-    echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+  ac_test_CFLAGS="${CFLAGS+set}"
+  ac_save_CFLAGS="$CFLAGS"
+  CFLAGS=
+  echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
+echo "configure:744: checking whether ${CC-cc} accepts -g" >&5
 if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
@@ -713,11 +755,12 @@
 fi
 
 echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6
-    if test $ac_cv_prog_gcc_g = yes; then
-      CFLAGS="-g -O"
-    else
-      CFLAGS="-O"
-    fi
+  if test "$ac_test_CFLAGS" = set; then
+    CFLAGS="$ac_save_CFLAGS"
+  elif test $ac_cv_prog_gcc_g = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-O2"
   fi
 else
   GCC=
@@ -725,6 +768,7 @@
 fi
 
 echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+echo "configure:772: checking how to run the C preprocessor" >&5
 # On Suns, sometimes $CPP names a directory.
 if test -n "$CPP" && test -d "$CPP"; then
   CPP=
@@ -739,33 +783,37 @@
   # On the NeXT, cc -E runs the code through the compiler's parser,
   # not just through cpp.
   cat > conftest.$ac_ext <<EOF
-#line 743 "configure"
+#line 787 "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:749: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:793: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   :
 else
   echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   CPP="${CC-cc} -E -traditional-cpp"
   cat > conftest.$ac_ext <<EOF
-#line 758 "configure"
+#line 804 "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:764: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:810: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   :
 else
   echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   CPP=/lib/cpp
 fi
@@ -780,31 +828,12 @@
 fi
 echo "$ac_t""$CPP" 1>&6
 
-echo $ac_n "checking for POSIXized ISC""... $ac_c" 1>&6
-if test -d /etc/conf/kconfig.d &&
-  grep _POSIX_VERSION /usr/include/sys/unistd.h >/dev/null 2>&1
-then
-  echo "$ac_t""yes" 1>&6
-  ISC=yes # If later tests want to check for ISC.
-  cat >> confdefs.h <<\EOF
-#define _POSIX_SOURCE 1
-EOF
-
-  if test "$GCC" = yes; then
-    CC="$CC -posix"
-  else
-    CC="$CC -Xp"
-  fi
-else
-  echo "$ac_t""no" 1>&6
-  ISC=
-fi
-
 # If we find X, set shell vars x_includes and x_libraries to the
 # paths, otherwise set no_x=yes.
 # 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:837: checking for X" >&5
 
 # Check whether --with-x or --without-x was given.
 if test "${with_x+set}" = set; then
@@ -844,7 +873,9 @@
         ac_im_usrlibdir=$ac_im_libdir; break
       fi
     done
-    # Screen out bogus values from the imake configuration.
+    # Screen out bogus values from the imake configuration.  They are
+    # bogus both because they are the default anyway, and because
+    # using them would break gcc on systems where it needs fixed includes.
     case "$ac_im_incroot" in
 	/usr/include) ;;
 	*) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;;
@@ -864,12 +895,12 @@
 
   # First, try using that file with no special directory specified.
 cat > conftest.$ac_ext <<EOF
-#line 868 "configure"
+#line 899 "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:873: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:904: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   rm -rf conftest*
@@ -877,30 +908,32 @@
 ac_x_includes=
 else
   echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   # Look for the header file in a standard set of common directories.
+# Check X11 before X11Rn because it is often a symlink to the current release.
   for ac_dir in               \
+    /usr/X11/include          \
     /usr/X11R6/include        \
     /usr/X11R5/include        \
     /usr/X11R4/include        \
                               \
+    /usr/include/X11          \
     /usr/include/X11R6        \
     /usr/include/X11R5        \
     /usr/include/X11R4        \
                               \
+    /usr/local/X11/include    \
     /usr/local/X11R6/include  \
     /usr/local/X11R5/include  \
     /usr/local/X11R4/include  \
                               \
+    /usr/local/include/X11    \
     /usr/local/include/X11R6  \
     /usr/local/include/X11R5  \
     /usr/local/include/X11R4  \
                               \
-    /usr/X11/include          \
-    /usr/include/X11          \
-    /usr/local/X11/include    \
-    /usr/local/include/X11    \
-                              \
     /usr/X386/include         \
     /usr/x386/include         \
     /usr/XFree86/include/X11  \
@@ -936,45 +969,46 @@
   ac_save_LIBS="$LIBS"
   LIBS="-l$x_direct_test_library $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 940 "configure"
+#line 973 "configure"
 #include "confdefs.h"
 
-int main() { return 0; }
-int t() {
+int main() {
 ${x_direct_test_function}()
 ; return 0; }
 EOF
-if { (eval echo configure:948: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:980: \"$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.
 ac_x_libraries=
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   LIBS="$ac_save_LIBS"
 # First see if replacing the include by lib works.
+# Check X11 before X11Rn because it is often a symlink to the current release.
 for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \
+    /usr/X11/lib          \
     /usr/X11R6/lib        \
     /usr/X11R5/lib        \
     /usr/X11R4/lib        \
                           \
+    /usr/lib/X11          \
     /usr/lib/X11R6        \
     /usr/lib/X11R5        \
     /usr/lib/X11R4        \
                           \
+    /usr/local/X11/lib    \
     /usr/local/X11R6/lib  \
     /usr/local/X11R5/lib  \
     /usr/local/X11R4/lib  \
                           \
+    /usr/local/lib/X11    \
     /usr/local/lib/X11R6  \
     /usr/local/lib/X11R5  \
     /usr/local/lib/X11R4  \
                           \
-    /usr/X11/lib          \
-    /usr/lib/X11          \
-    /usr/local/X11/lib    \
-    /usr/local/lib/X11    \
-                          \
     /usr/X386/lib         \
     /usr/x386/lib         \
     /usr/XFree86/lib/X11  \
@@ -985,6 +1019,7 @@
     /usr/athena/lib       \
     /usr/local/x11r5/lib  \
     /usr/lpp/Xamples/lib  \
+    /lib/usr/lib/X11	  \
                           \
     /usr/openwin/lib      \
     /usr/openwin/share/lib \
@@ -1030,74 +1065,83 @@
 
 if test "$no_x" = yes; then
   # Not all programs may use this symbol, but it does not hurt to define it.
-  X_CFLAGS="$X_CFLAGS -DX_DISPLAY_MISSING"
+  cat >> confdefs.h <<\EOF
+#define X_DISPLAY_MISSING 1
+EOF
+
+  X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS=
 else
   if test -n "$x_includes"; then
     X_CFLAGS="$X_CFLAGS -I$x_includes"
   fi
 
-  # It would be nice to have a more robust check for the -R ld option than
-  # just checking for Solaris.
   # It would also be nice to do this for all -L options, not just this one.
   if test -n "$x_libraries"; then
     X_LIBS="$X_LIBS -L$x_libraries"
-    if test "`(uname) 2>/dev/null`" = SunOS &&
-      uname -r | grep '^5' >/dev/null; then
-      X_LIBS="$X_LIBS -R $x_libraries"
-    fi
-  fi
-
-  # Check for libraries that X11R6 Xt/Xaw programs need.
-
-  ac_save_LDFLAGS="$LDFLAGS"
-  LDFLAGS="$LDFLAGS -L$x_libraries"
-  # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to
-  # check for ICE first), but we must link in the order -lSM -lICE or
-  # we get undefined symbols.  So assume we have SM if we have ICE.
-  # These have to be linked with before -lX11, unlike the other
-  # libraries we check for below, so use a different variable.
-  #  --interran@uluru.Stanford.EDU, kb@cs.umb.edu.
-  echo $ac_n "checking for -lICE""... $ac_c" 1>&6
-ac_lib_var=`echo ICE'_'IceConnectionNumber | tr './+\055' '__p_'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
-  echo $ac_n "(cached) $ac_c" 1>&6
-else
-  ac_save_LIBS="$LIBS"
-LIBS="-lICE  $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1069 "configure"
+    # For Solaris; some versions of Sun CC require a space after -R and
+    # others require no space.  Words are not sufficient . . . .
+    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:1087: 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 1090 "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
-    builtin and then its argument prototype would still apply.  */
-char IceConnectionNumber();
 
-int main() { return 0; }
-int t() {
-IceConnectionNumber()
+int main() {
+
 ; return 0; }
 EOF
-if { (eval echo configure:1081: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1097: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=yes"
+  ac_R_nospace=yes
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
-  eval "ac_cv_lib_$ac_lib_var=no"
+  ac_R_nospace=no
 fi
 rm -f conftest*
-LIBS="$ac_save_LIBS"
 
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
-  echo "$ac_t""yes" 1>&6
-  X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"
+      if test $ac_R_nospace = yes; then
+	echo "$ac_t""no" 1>&6
+	X_LIBS="$X_LIBS -R$x_libraries"
+      else
+	LIBS="$ac_xsave_LIBS -R $x_libraries"
+	cat > conftest.$ac_ext <<EOF
+#line 1114 "configure"
+#include "confdefs.h"
+
+int main() {
+
+; return 0; }
+EOF
+if { (eval echo configure:1121: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  rm -rf conftest*
+  ac_R_space=yes
 else
-  echo "$ac_t""no" 1>&6
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  ac_R_space=no
 fi
+rm -f conftest*
 
-  LDFLAGS="$ac_save_LDFLAGS"
+	if test $ac_R_space = yes; then
+	  echo "$ac_t""yes" 1>&6
+	  X_LIBS="$X_LIBS -R $x_libraries"
+	else
+	  echo "$ac_t""neither works" 1>&6
+	fi
+      fi
+      LIBS="$ac_xsave_LIBS"
+    esac
+  fi
 
   # Check for system-dependent libraries X programs must link with.
+  # Do this before checking for the system-independent R6 libraries
+  # (-lICE), since we may need -lsocket or whatever for X linking.
 
   if test "$ISC" = yes; then
     X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet"
@@ -1105,30 +1149,32 @@
     # Martyn.Johnson@cl.cam.ac.uk says this is needed for Ultrix, if the X
     # 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 -ldnet""... $ac_c" 1>&6
-ac_lib_var=`echo dnet'_'dnet_ntoa | tr './+\055' '__p_'`
+    echo $ac_n "checking for dnet_ntoa in -ldnet""... $ac_c" 1>&6
+echo "configure:1154: 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
 else
   ac_save_LIBS="$LIBS"
 LIBS="-ldnet  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1117 "configure"
+#line 1162 "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
     builtin and then its argument prototype would still apply.  */
 char dnet_ntoa();
 
-int main() { return 0; }
-int t() {
+int main() {
 dnet_ntoa()
 ; return 0; }
 EOF
-if { (eval echo configure:1129: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1173: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=no"
 fi
@@ -1144,30 +1190,32 @@
 fi
 
     if test $ac_cv_lib_dnet_dnet_ntoa = no; then
-      echo $ac_n "checking for -ldnet_stub""... $ac_c" 1>&6
-ac_lib_var=`echo dnet_stub'_'dnet_ntoa | tr './+\055' '__p_'`
+      echo $ac_n "checking for dnet_ntoa in -ldnet_stub""... $ac_c" 1>&6
+echo "configure:1195: 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
 else
   ac_save_LIBS="$LIBS"
 LIBS="-ldnet_stub  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1156 "configure"
+#line 1203 "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
     builtin and then its argument prototype would still apply.  */
 char dnet_ntoa();
 
-int main() { return 0; }
-int t() {
+int main() {
 dnet_ntoa()
 ; return 0; }
 EOF
-if { (eval echo configure:1168: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1214: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=no"
 fi
@@ -1186,32 +1234,85 @@
 
     # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT,
     # to get the SysV transport functions.
-    # Not sure which flavor of 386 UNIX this is, but it seems harmless to
-    # check for it.
-    echo $ac_n "checking for -lnsl""... $ac_c" 1>&6
-ac_lib_var=`echo nsl'_'t_accept | tr './+\055' '__p_'`
+    # chad@anasazi.com says the Pyramis MIS-ES running DC/OSx (SVR4)
+    # needs -lnsl.
+    # 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:1243: 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 1248 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char gethostbyname(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char gethostbyname();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_gethostbyname) || defined (__stub___gethostbyname)
+choke me
+#else
+gethostbyname();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1271: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  rm -rf conftest*
+  eval "ac_cv_func_gethostbyname=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_gethostbyname=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'gethostbyname`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  :
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+    if test $ac_cv_func_gethostbyname = no; then
+      echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6
+echo "configure:1292: 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
 else
   ac_save_LIBS="$LIBS"
 LIBS="-lnsl  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1200 "configure"
+#line 1300 "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
     builtin and then its argument prototype would still apply.  */
-char t_accept();
+char gethostbyname();
 
-int main() { return 0; }
-int t() {
-t_accept()
+int main() {
+gethostbyname()
 ; return 0; }
 EOF
-if { (eval echo configure:1212: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1311: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=no"
 fi
@@ -1226,36 +1327,90 @@
   echo "$ac_t""no" 1>&6
 fi
 
+    fi
 
     # lieder@skyler.mavd.honeywell.com says without -lsocket,
-    # socket/setsockopt and other routines are undefined under SCO ODT 2.0.
-    # But -lsocket is broken on IRIX, according to simon@lia.di.epfl.ch.
-    if test "`(uname) 2>/dev/null`" != IRIX; then
-      if test $ac_cv_lib_nsl_t_accept = no; then
-        echo $ac_n "checking for -lsocket""... $ac_c" 1>&6
-ac_lib_var=`echo socket'_'socket | tr './+\055' '__p_'`
+    # socket/setsockopt and other routines are undefined under SCO ODT
+    # 2.0.  But -lsocket is broken on IRIX 5.2 (and is not necessary
+    # on later versions), says simon@lia.di.epfl.ch: it contains
+    # gethostby* variants that don't use the nameserver (or something).
+    # -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:1341: 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 1346 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char connect(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char connect();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_connect) || defined (__stub___connect)
+choke me
+#else
+connect();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1369: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  rm -rf conftest*
+  eval "ac_cv_func_connect=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_connect=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'connect`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  :
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+    if test $ac_cv_func_connect = no; then
+      echo $ac_n "checking for connect in -lsocket""... $ac_c" 1>&6
+echo "configure:1390: 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
 else
   ac_save_LIBS="$LIBS"
-LIBS="-lsocket  $LIBS"
+LIBS="-lsocket $X_EXTRA_LIBS $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1244 "configure"
+#line 1398 "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
     builtin and then its argument prototype would still apply.  */
-char socket();
+char connect();
 
-int main() { return 0; }
-int t() {
-socket()
+int main() {
+connect()
 ; return 0; }
 EOF
-if { (eval echo configure:1256: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1409: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=no"
 fi
@@ -1265,37 +1420,89 @@
 fi
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
-  X_EXTRA_LIBS="$X_EXTRA_LIBS -lsocket"
+  X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS"
 else
   echo "$ac_t""no" 1>&6
 fi
 
-      else
-        # If we found -lnsl, use it to check for -lsocket. -- AJ
-        echo $ac_n "checking for -lsocket""... $ac_c" 1>&6
-ac_lib_var=`echo socket'_'socket | tr './+\055' '__p_'`
+    fi
+
+    # gomez@mi.uni-erlangen.de says -lposix is necessary on A/UX.
+    echo $ac_n "checking for remove""... $ac_c" 1>&6
+echo "configure:1433: 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 1438 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char remove(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char remove();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_remove) || defined (__stub___remove)
+choke me
+#else
+remove();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1461: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  rm -rf conftest*
+  eval "ac_cv_func_remove=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_remove=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'remove`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  :
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+    if test $ac_cv_func_remove = no; then
+      echo $ac_n "checking for remove in -lposix""... $ac_c" 1>&6
+echo "configure:1482: 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
 else
   ac_save_LIBS="$LIBS"
-LIBS="-lsocket -lnsl $LIBS"
+LIBS="-lposix  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1284 "configure"
+#line 1490 "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
     builtin and then its argument prototype would still apply.  */
-char socket();
+char remove();
 
-int main() { return 0; }
-int t() {
-socket()
+int main() {
+remove()
 ; return 0; }
 EOF
-if { (eval echo configure:1296: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1501: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=no"
 fi
@@ -1305,14 +1512,157 @@
 fi
 if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
   echo "$ac_t""yes" 1>&6
-  X_EXTRA_LIBS="$X_EXTRA_LIBS -lsocket"
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix"
 else
   echo "$ac_t""no" 1>&6
 fi
 
-      fi
+    fi
+
+    # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay.
+    echo $ac_n "checking for shmat""... $ac_c" 1>&6
+echo "configure:1525: 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 1530 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char shmat(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char shmat();
+
+int main() {
+
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined (__stub_shmat) || defined (__stub___shmat)
+choke me
+#else
+shmat();
+#endif
+
+; return 0; }
+EOF
+if { (eval echo configure:1553: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+  rm -rf conftest*
+  eval "ac_cv_func_shmat=yes"
+else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_func_shmat=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'shmat`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  :
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+    if test $ac_cv_func_shmat = no; then
+      echo $ac_n "checking for shmat in -lipc""... $ac_c" 1>&6
+echo "configure:1574: 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
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lipc  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1582 "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
+    builtin and then its argument prototype would still apply.  */
+char shmat();
+
+int main() {
+shmat()
+; return 0; }
+EOF
+if { (eval echo configure:1593: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
     fi
   fi
+
+  # Check for libraries that X11R6 Xt/Xaw programs need.
+  ac_save_LDFLAGS="$LDFLAGS"
+  test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries"
+  # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to
+  # check for ICE first), but we must link in the order -lSM -lICE or
+  # we get undefined symbols.  So assume we have SM if we have ICE.
+  # These have to be linked with before -lX11, unlike the other
+  # 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:1626: 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
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lICE  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1634 "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
+    builtin and then its argument prototype would still apply.  */
+char IceConnectionNumber();
+
+int main() {
+IceConnectionNumber()
+; return 0; }
+EOF
+if { (eval echo configure:1645: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib_var=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+  LDFLAGS="$ac_save_LDFLAGS"
+
 fi
 
 for ac_prog in 'bison -y' byacc
@@ -1320,6 +1670,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:1674: 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
@@ -1351,6 +1702,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:1706: 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
@@ -1382,30 +1734,32 @@
   flex*) ac_lib=fl ;;
   *) ac_lib=l ;;
   esac
-  echo $ac_n "checking for -l$ac_lib""... $ac_c" 1>&6
-ac_lib_var=`echo $ac_lib'_'yywrap | tr './+\055' '__p_'`
+  echo $ac_n "checking for yywrap in -l$ac_lib""... $ac_c" 1>&6
+echo "configure:1739: 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
 else
   ac_save_LIBS="$LIBS"
 LIBS="-l$ac_lib  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1394 "configure"
+#line 1747 "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
     builtin and then its argument prototype would still apply.  */
 char yywrap();
 
-int main() { return 0; }
-int t() {
+int main() {
 yywrap()
 ; return 0; }
 EOF
-if { (eval echo configure:1406: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1758: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=no"
 fi
@@ -1425,6 +1779,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:1783: 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
@@ -1461,6 +1816,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:1820: 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
@@ -1509,30 +1865,32 @@
 
 test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
 
-echo $ac_n "checking for -li386""... $ac_c" 1>&6
-ac_lib_var=`echo i386'_'i386_set_ldt | tr './+\055' '__p_'`
+echo $ac_n "checking for i386_set_ldt in -li386""... $ac_c" 1>&6
+echo "configure:1870: 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
 else
   ac_save_LIBS="$LIBS"
 LIBS="-li386  $LIBS"
 cat > conftest.$ac_ext <<EOF
-#line 1521 "configure"
+#line 1878 "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
     builtin and then its argument prototype would still apply.  */
 char i386_set_ldt();
 
-int main() { return 0; }
-int t() {
+int main() {
 i386_set_ldt()
 ; return 0; }
 EOF
-if { (eval echo configure:1533: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:1889: \"$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
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_lib_$ac_lib_var=no"
 fi
@@ -1552,41 +1910,47 @@
 if test "x${GCC}" = "xyes"
 then
   CFLAGS="$CFLAGS -Wall"
-  # If we cannot run a trivial program, we must be cross compiling.
-echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6
+  # If we cannot run a trivial program, we are probably using a cross compiler.
+echo $ac_n "checking whether using a cross-compiler""... $ac_c" 1>&6
+echo "configure:1916: checking whether using a cross-compiler" >&5
 if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then
   echo $ac_n "(cached) $ac_c" 1>&6
 else
   if test "$cross_compiling" = yes; then
   ac_cv_c_cross=yes
 else
-cat > conftest.$ac_ext <<EOF
-#line 1565 "configure"
+  cat > conftest.$ac_ext <<EOF
+#line 1924 "configure"
 #include "confdefs.h"
 main(){return(0);}
 EOF
-{ (eval echo configure:1569: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+{ (eval echo configure:1928: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
 if test -s conftest && (./conftest; exit) 2>/dev/null; then
   ac_cv_c_cross=no
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
   ac_cv_c_cross=yes
 fi
-fi
 rm -fr conftest*
 fi
 
+fi
+
 echo "$ac_t""$ac_cv_c_cross" 1>&6
 cross_compiling=$ac_cv_c_cross
 
   echo $ac_n "checking "for gcc strength-reduce bug"""... $ac_c" 1>&6
+echo "configure:1946: 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
   if test "$cross_compiling" = yes; then
   ac_cv_c_gcc_strength_bug="yes"
 else
-cat > conftest.$ac_ext <<EOF
-#line 1590 "configure"
+  cat > conftest.$ac_ext <<EOF
+#line 1954 "configure"
 #include "confdefs.h"
 
 int main(void) {
@@ -1597,14 +1961,18 @@
   exit( Array[1] != -2 );
 }
 EOF
-{ (eval echo configure:1601: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+{ (eval echo configure:1965: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
 if test -s conftest && (./conftest; exit) 2>/dev/null; then
   ac_cv_c_gcc_strength_bug="no"
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
   ac_cv_c_gcc_strength_bug="yes"
 fi
+rm -fr conftest*
 fi
-rm -fr conftest* 
+ 
 fi
 
 echo "$ac_t""$ac_cv_c_gcc_strength_bug" 1>&6
@@ -1616,6 +1984,7 @@
 
 
 echo $ac_n "checking "whether external symbols need an underscore prefix"""... $ac_c" 1>&6
+echo "configure:1988: 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
@@ -1627,18 +1996,19 @@
 	.long 0
 EOF
 cat > conftest.$ac_ext <<EOF
-#line 1631 "configure"
+#line 2000 "configure"
 #include "confdefs.h"
 extern int ac_test;
-int main() { return 0; }
-int t() {
+int main() {
 if (ac_test) return 1
 ; return 0; }
 EOF
-if { (eval echo configure:1639: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2007: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   ac_cv_c_extern_prefix="yes"
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_c_extern_prefix="no"
 fi
@@ -1660,11 +2030,12 @@
 for ac_func in memmove tcgetattr usleep
 do
 echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+echo "configure:2034: 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 1668 "configure"
+#line 2039 "configure"
 #include "confdefs.h"
 /* System header to define __stub macros and hopefully few prototypes,
     which can conflict with char $ac_func(); below.  */
@@ -1674,8 +2045,7 @@
     builtin and then its argument prototype would still apply.  */
 char $ac_func();
 
-int main() { return 0; }
-int t() {
+int main() {
 
 /* The GNU C library defines this for functions which it implements
     to always fail with ENOSYS.  Some functions are actually named
@@ -1688,10 +2058,12 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1692: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+if { (eval echo configure:2062: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=yes"
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   eval "ac_cv_func_$ac_func=no"
 fi
@@ -1711,11 +2083,12 @@
 done
 
 echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
+echo "configure:2087: 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 1719 "configure"
+#line 2092 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -1766,15 +2139,15 @@
 fi
 
 echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:2143: 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 1774 "configure"
+#line 2148 "configure"
 #include "confdefs.h"
 
-int main() { return 0; }
-int t() {
+int main() {
 
 /* Ultrix mips cc rejects this.  */
 typedef int charset[2]; const charset x;
@@ -1820,10 +2193,12 @@
 
 ; return 0; }
 EOF
-if { (eval echo configure:1824: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2197: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
   rm -rf conftest*
   ac_cv_c_const=yes
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_c_const=no
 fi
@@ -1840,11 +2215,12 @@
 fi
 
 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+echo "configure:2219: 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 1848 "configure"
+#line 2224 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 #include <stdarg.h>
@@ -1852,13 +2228,15 @@
 #include <float.h>
 EOF
 ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1856: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2232: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
 ac_err=`grep -v '^ *+' conftest.out`
 if test -z "$ac_err"; then
   rm -rf conftest*
   ac_cv_header_stdc=yes
 else
   echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
   rm -rf conftest*
   ac_cv_header_stdc=no
 fi
@@ -1867,7 +2245,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 1871 "configure"
+#line 2249 "configure"
 #include "confdefs.h"
 #include <string.h>
 EOF
@@ -1885,7 +2263,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 1889 "configure"
+#line 2267 "configure"
 #include "confdefs.h"
 #include <stdlib.h>
 EOF
@@ -1905,8 +2283,8 @@
 if test "$cross_compiling" = yes; then
   :
 else
-cat > conftest.$ac_ext <<EOF
-#line 1910 "configure"
+  cat > conftest.$ac_ext <<EOF
+#line 2288 "configure"
 #include "confdefs.h"
 #include <ctype.h>
 #define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1917,15 +2295,19 @@
 exit (0); }
 
 EOF
-{ (eval echo configure:1921: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
+{ (eval echo configure:2299: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }
 if test -s conftest && (./conftest; exit) 2>/dev/null; then
   :
 else
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -fr conftest*
   ac_cv_header_stdc=no
 fi
-fi
 rm -fr conftest*
 fi
+
+fi
 fi
 
 echo "$ac_t""$ac_cv_header_stdc" 1>&6
@@ -1937,19 +2319,21 @@
 fi
 
 echo $ac_n "checking for size_t""... $ac_c" 1>&6
+echo "configure:2323: 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 1945 "configure"
+#line 2328 "configure"
 #include "confdefs.h"
 #include <sys/types.h>
 #if STDC_HEADERS
 #include <stdlib.h>
+#include <stddef.h>
 #endif
 EOF
 if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
-  egrep "size_t" >/dev/null 2>&1; then
+  egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
   rm -rf conftest*
   ac_cv_type_size_t=yes
 else
@@ -1991,8 +2375,9 @@
 EOF
 # Ultrix sh set writes to stderr and can't be redirected directly,
 # and sets the high bit in the cache file unless we assign to the vars.
+# HP-UX 10.01 sh prints single quotes around any value that contains spaces.
 (set) 2>&1 |
-  sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \
+sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)='*\([^']*\)'*/\1=\${\1='\2'}/p"\
   >> confcache
 if cmp -s $cache_file confcache; then
   :
@@ -2048,7 +2433,7 @@
     echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
     exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
   -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
-    echo "$CONFIG_STATUS generated by autoconf version 2.10-patched"
+    echo "$CONFIG_STATUS generated by autoconf version 2.11"
     exit 0 ;;
   -help | --help | --hel | --he | --h)
     echo "\$ac_cs_usage"; exit 0 ;;
@@ -2137,6 +2522,42 @@
 
 CEOF
 EOF
+
+cat >> $CONFIG_STATUS <<\EOF
+
+# Split the substitutions into bite-sized pieces for seds with
+# small command number limits, like on Digital OSF/1 and HP-UX.
+ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
+ac_file=1 # Number of current file.
+ac_beg=1 # First line for current file.
+ac_end=$ac_max_sed_cmds # Line after last line for current file.
+ac_more_lines=:
+ac_sed_cmds=""
+while $ac_more_lines; do
+  if test $ac_beg -gt 1; then
+    sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
+  else
+    sed "${ac_end}q" conftest.subs > conftest.s$ac_file
+  fi
+  if test ! -s conftest.s$ac_file; then
+    ac_more_lines=false
+    rm -f conftest.s$ac_file
+  else
+    if test -z "$ac_sed_cmds"; then
+      ac_sed_cmds="sed -f conftest.s$ac_file"
+    else
+      ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
+    fi
+    ac_file=`expr $ac_file + 1`
+    ac_beg=$ac_end
+    ac_end=`expr $ac_end + $ac_max_sed_cmds`
+  fi
+done
+if test -z "$ac_sed_cmds"; then
+  ac_sed_cmds=cat
+fi
+EOF
+
 cat >> $CONFIG_STATUS <<EOF
 
 CONFIG_FILES=\${CONFIG_FILES-"Make.rules
@@ -2176,7 +2597,7 @@
   *) ac_file_in="${ac_file}.in" ;;
   esac
 
-  # Adjust relative srcdir, etc. for subdirectories.
+  # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
 
   # Remove last slash and all that follows it.  Not all systems have dirname.
   ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
@@ -2204,6 +2625,7 @@
   [/$]*) INSTALL="$ac_given_INSTALL" ;;
   *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
   esac
+
   echo creating "$ac_file"
   rm -f "$ac_file"
   configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
@@ -2217,9 +2639,9 @@
 s%@srcdir@%$srcdir%g
 s%@top_srcdir@%$top_srcdir%g
 s%@INSTALL@%$INSTALL%g
-" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
+" $ac_given_srcdir/$ac_file_in | eval "$ac_sed_cmds" > $ac_file
 fi; done
-rm -f conftest.subs
+rm -f conftest.s*
 
 # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
 # NAME is the cpp macro being defined and VALUE is the value it is being given.
@@ -2240,7 +2662,13 @@
 ac_eC=' '
 ac_eD='%g'
 
-CONFIG_HEADERS=${CONFIG_HEADERS-"include/config.h"}
+if test -z "$CONFIG_HEADERS"; then
+EOF
+cat >> $CONFIG_STATUS <<EOF
+  CONFIG_HEADERS="include/config.h"
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+fi
 for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then
   # Support "outfile[:infile]", defaulting infile="outfile.in".
   case "$ac_file" in
@@ -2280,8 +2708,6 @@
 
 # Break up conftest.vals because some shells have a limit on
 # the size of here documents, and old seds have small limits too.
-# Maximum number of lines to put in a single here document.
-ac_max_here_lines=12
 
 rm -f conftest.tail
 while :
diff --git a/configure.in b/configure.in
index e96abcc..8e49105 100644
--- a/configure.in
+++ b/configure.in
@@ -7,8 +7,6 @@
 AC_CONFIG_AUX_DIR(tools)
 
 # We want these before the checks, so the checks can modify their values.
-test -z "$CFLAGS" && CFLAGS="-g -O2" AC_SUBST(CFLAGS)
-test -z "$LDFLAGS" && LDFLAGS=-g AC_SUBST(LDFLAGS)
 test -z "$LDLIBS" && LDLIBS=-lm AC_SUBST(LDLIBS)
 
 dnl **** Command-line arguments ****
diff --git a/controls/Makefile.in b/controls/Makefile.in
index 09188b5..7f7dff9 100644
--- a/controls/Makefile.in
+++ b/controls/Makefile.in
@@ -12,6 +12,7 @@
 	edit.c \
 	listbox.c \
 	menu.c \
+	oldlbox.c \
 	scroll.c \
 	static.c \
 	status.c \
diff --git a/controls/button.c b/controls/button.c
index 3367a66..1c4df7e 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -187,7 +187,8 @@
 
     case WM_KILLFOCUS:
         infoPtr->state &= ~BUTTON_HASFOCUS;
-        PAINT_BUTTON( wndPtr, style, ODA_FOCUS );
+	PAINT_BUTTON( wndPtr, style, ODA_FOCUS );
+	InvalidateRect16( hWnd, NULL, TRUE );
         break;
 
     case WM_SYSCOLORCHANGE:
@@ -369,57 +370,70 @@
 
 static void CB_Paint( WND *wndPtr, HDC32 hDC, WORD action )
 {
-    RECT16 rc;
+    RECT16 rbox, rtext, client;
     HBRUSH16 hBrush;
-    int textlen, delta, x, y;
-    TEXTMETRIC16 tm;
+    int textlen, delta;
     BUTTONINFO *infoPtr = (BUTTONINFO *)wndPtr->wExtra;
 
-    GetClientRect16(wndPtr->hwndSelf, &rc);
+    textlen = 0;
+    GetClientRect16(wndPtr->hwndSelf, &client);
+    rbox = rtext = client;
 
     if (infoPtr->hFont) SelectObject32( hDC, infoPtr->hFont );
     hBrush = BUTTON_SEND_CTLCOLOR( wndPtr, hDC );
-    if (action == ODA_DRAWENTIRE) FillRect16( hDC, &rc, hBrush );
+    if (wndPtr->dwStyle & BS_LEFTTEXT) 
+    {
+	/* magic +4 is what CTL3D expects */
 
-    GetTextMetrics16(hDC, &tm);
-    delta = (rc.bottom - rc.top - tm.tmHeight) >> 1;
+        rtext.right -= checkBoxWidth + 4;
+        rbox.left = rbox.right - checkBoxWidth;
+    }
+    else 
+    {
+        rtext.left += checkBoxWidth + 4;
+        rbox.right = checkBoxWidth;
+    }
 
       /* Draw the check-box bitmap */
-    x = y = 0;
-    if (infoPtr->state & BUTTON_HIGHLIGHTED) x += 2 * checkBoxWidth;
-    if (infoPtr->state & (BUTTON_CHECKED | BUTTON_3STATE)) x += checkBoxWidth;
-    if (((wndPtr->dwStyle & 0x0f) == BS_RADIOBUTTON) ||
-        ((wndPtr->dwStyle & 0x0f) == BS_AUTORADIOBUTTON)) y += checkBoxHeight;
-    else if (infoPtr->state & BUTTON_3STATE) y += 2 * checkBoxHeight;
-    GRAPH_DrawBitmap( hDC, hbitmapCheckBoxes, rc.left, rc.top + delta,
-                      x, y, checkBoxWidth, checkBoxHeight );
-    rc.left += checkBoxWidth + tm.tmAveCharWidth / 2;
 
-    if (!wndPtr->text) return;
-    textlen = strlen( wndPtr->text );
+    if (wndPtr->text) textlen = strlen( wndPtr->text );
+    if (action == ODA_DRAWENTIRE || action == ODA_SELECT)
+    { 
+        int x = 0, y = 0;
+        delta = (rbox.bottom - rbox.top - checkBoxHeight) >> 1;
 
-    if (action == ODA_DRAWENTIRE)
-    {
-        if (wndPtr->dwStyle & WS_DISABLED)
-            SetTextColor( hDC, GetSysColor(COLOR_GRAYTEXT) );
-        DrawText16( hDC, wndPtr->text, textlen, &rc,
-                    DT_SINGLELINE | DT_VCENTER | DT_NOCLIP );
+        if (action == ODA_SELECT) FillRect16( hDC, &rbox, hBrush );
+        else FillRect16( hDC, &client, hBrush );
+
+        if (infoPtr->state & BUTTON_HIGHLIGHTED) x += 2 * checkBoxWidth;
+        if (infoPtr->state & (BUTTON_CHECKED | BUTTON_3STATE)) x += checkBoxWidth;
+        if (((wndPtr->dwStyle & 0x0f) == BS_RADIOBUTTON) ||
+            ((wndPtr->dwStyle & 0x0f) == BS_AUTORADIOBUTTON)) y += checkBoxHeight;
+        else if (infoPtr->state & BUTTON_3STATE) y += 2 * checkBoxHeight;
+
+        GRAPH_DrawBitmap( hDC, hbitmapCheckBoxes, rbox.left, rbox.top + delta,
+                          x, y, checkBoxWidth, checkBoxHeight );
+        if( textlen && action != ODA_SELECT )
+        {
+            if (wndPtr->dwStyle & WS_DISABLED)
+                SetTextColor( hDC, GetSysColor(COLOR_GRAYTEXT) );
+            DrawText16( hDC, wndPtr->text, textlen, &rtext,
+                        DT_SINGLELINE | DT_VCENTER );
+        }
     }
-    
+
     if ((action == ODA_FOCUS) ||
         ((action == ODA_DRAWENTIRE) && (infoPtr->state & BUTTON_HASFOCUS)))
     {
-        RECT16 rect = { 0, 0, 0, 0 };
-        DrawText16( hDC, wndPtr->text, textlen, &rect,
-                    DT_SINGLELINE | DT_CALCRECT );
-        if (delta > 1)
-        {
-            rc.top += delta - 1;
-            rc.bottom -= delta + 1;
-        }
-        rc.left--;
-        rc.right = rc.left + rect.right + 2;
-        DrawFocusRect16( hDC, &rc );
+	/* again, this is what CTL3D expects */
+
+        DWORD tm = (textlen) ? GetTextExtent( hDC, wndPtr->text, textlen) : 0x00020002;
+        delta = (rtext.bottom - rtext.top - HIWORD(tm) - 1)/2;
+
+        rbox.bottom = (rbox.top = rtext.top + delta - 1) + HIWORD(tm) + 2;
+        rbox.right = (rbox.left = --rtext.left) + LOWORD(tm) + 2;
+        IntersectRect16(&rbox, &rbox, &rtext);
+        DrawFocusRect16( hDC, &rbox );
     }
 }
 
diff --git a/controls/combo.c b/controls/combo.c
index 43a368b..4c231f4 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -1233,68 +1233,3 @@
     }
     return DefWindowProc16(hwnd, message, wParam, lParam);
 }
-
-
-static INT32 COMBO_DlgDirList( HWND32 hDlg, LPARAM path, INT32 idCBox,
-                               INT32 idStatic, UINT32 wType, BOOL32 unicode )
-{
-    LRESULT res = 0;
-
-    if (idCBox)
-    {
-        SendDlgItemMessage32A( hDlg, idCBox, CB_RESETCONTENT16, 0, 0 );
-        if (unicode)
-            res = SendDlgItemMessage32W( hDlg, idCBox, CB_DIR16, wType, path );
-        else
-            res = SendDlgItemMessage32A( hDlg, idCBox, CB_DIR16, wType, path );
-    }
-    if (idStatic)
-    {
-        char temp[512] = "A:\\";
-        int drive = DRIVE_GetCurrentDrive();
-        temp[0] += drive;
-        lstrcpyn32A( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 );
-        AnsiLower( temp );
-        SetDlgItemText32A( hDlg, idStatic, temp );
-    } 
-    return (res >= 0);
-}
-
-
-/***********************************************************************
- *           DlgDirListComboBox16   (USER.195)
- */
-INT16 DlgDirListComboBox16( HWND16 hDlg, SEGPTR path, INT16 idCBox,
-                            INT16 idStatic, UINT16 wType )
-{
-    dprintf_combo( stddeb,"DlgDirListComboBox16(%04x,%08x,%d,%d,%04x)\n",
-                   hDlg, (UINT32)path, idCBox, idStatic, wType );
-    return COMBO_DlgDirList( hDlg, (LPARAM)path, idCBox,
-                             idStatic, wType, FALSE );
-}
-
-
-/***********************************************************************
- *           DlgDirListComboBox32A   (USER32.143)
- */
-INT32 DlgDirListComboBox32A( HWND32 hDlg, LPCSTR path, INT32 idCBox,
-                             INT32 idStatic, UINT32 wType )
-{
-    dprintf_combo( stddeb,"DlgDirListComboBox32A(%08x,'%s',%d,%d,%08X)\n",
-                   hDlg, path, idCBox, idStatic, wType );
-    return COMBO_DlgDirList( hDlg, (LPARAM)path, idCBox,
-                             idStatic, wType, FALSE );
-}
-
-
-/***********************************************************************
- *           DlgDirListComboBox32W   (USER32.144)
- */
-INT32 DlgDirListComboBox32W( HWND32 hDlg, LPCWSTR path, INT32 idCBox,
-                             INT32 idStatic, UINT32 wType )
-{
-    dprintf_combo( stddeb,"DlgDirListComboBox32W(%08x,%p,%d,%d,%08X)\n",
-                   hDlg, path, idCBox, idStatic, wType );
-    return COMBO_DlgDirList( hDlg, (LPARAM)path, idCBox,
-                             idStatic, wType, TRUE );
-}
diff --git a/controls/desktop.c b/controls/desktop.c
index 87cde85..b7458b9 100644
--- a/controls/desktop.c
+++ b/controls/desktop.c
@@ -173,7 +173,7 @@
 BOOL16 SetDeskPattern(void)
 {
     char buffer[100];
-    GetProfileString( "desktop", "Pattern", "(None)", buffer, 100 );
+    GetProfileString32A( "desktop", "Pattern", "(None)", buffer, 100 );
     return DESKTOP_SetPattern( buffer );
 }
 
@@ -202,7 +202,7 @@
 
     if (filename == (LPSTR)-1)
     {
-	GetProfileString( "desktop", "WallPaper", "(None)", buffer, 256 );
+	GetProfileString32A( "desktop", "WallPaper", "(None)", buffer, 256 );
 	filename = buffer;
     }
     hdc = GetDC32( 0 );
@@ -210,7 +210,7 @@
     ReleaseDC32( 0, hdc );
     if (infoPtr->hbitmapWallPaper) DeleteObject32( infoPtr->hbitmapWallPaper );
     infoPtr->hbitmapWallPaper = hbitmap;
-    infoPtr->fTileWallPaper = GetProfileInt( "desktop", "TileWallPaper", 0 );
+    infoPtr->fTileWallPaper = GetProfileInt32A( "desktop", "TileWallPaper", 0 );
     if (hbitmap)
     {
 	BITMAP32 bmp;
diff --git a/controls/listbox.c b/controls/listbox.c
index a07645d..bad86a7 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -1,2269 +1,2393 @@
 /*
  * Listbox controls
- * 
- * Copyright  Martin Ayotte, 1993
- *            Constantine Sapuntzakis, 1995
- * 	      Alex Korobka, 1995, 1996 
- * 
+ *
+ * Copyright 1996 Alexandre Julliard
  */
 
- /*
-  * FIXME: 
-  * - proper scrolling for multicolumn style
-  * - anchor and caret for LBS_EXTENDEDSEL
-  * - proper selection with keyboard
-  * - how to handle (LBS_EXTENDEDSEL | LBS_MULTIPLESEL) style
-  * - support for LBS_NOINTEGRALHEIGHT and LBS_OWNERDRAWVARIABLE styles
-  */
-
-#include <stdio.h>
-#include <stdlib.h>
+#define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <string.h>
-#include <ctype.h>
+#include <stdio.h>
 #include "windows.h"
-#include "win.h"
-#include "gdi.h"
-#include "msdos.h"
-#include "listbox.h"
-#include "dos_fs.h"
 #include "drive.h"
-#include "file.h"
+#include "dos_fs.h"
+#include "msdos.h"
 #include "heap.h"
+#include "spy.h"
+#include "win.h"
 #include "stddebug.h"
 #include "debug.h"
-#include "xmalloc.h"
 
-#define LIST_HEAP_ALLOC(lphl,f,size) \
-    LOCAL_Alloc( lphl->HeapSel, LMEM_FIXED, (size) )
-#define LIST_HEAP_FREE(lphl,handle) \
-    LOCAL_Free( lphl->HeapSel, (handle) )
-#define LIST_HEAP_ADDR(lphl,handle)  \
-    ((handle) ? PTR_SEG_OFF_TO_LIN(lphl->HeapSel, (handle)) : NULL)
+/* Unimplemented yet:
+ * - LBS_NOSEL
+ * - LBS_USETABSTOPS
+ * - Unicode
+ * - Locale handling
+ * - COMBOLBOX
+ */
 
-#define LIST_HEAP_SIZE 0x10000
+/* Items array granularity */
+#define LB_ARRAY_GRANULARITY 16
 
-#define LBMM_EDGE   4    /* distance inside box which is same as moving mouse
-			    outside box, to trigger scrolling of LB */
+/* Scrolling timeout in ms */
+#define LB_SCROLL_TIMEOUT 50
 
-#define MATCH_SUBSTR            2
-#define MATCH_EXACT             1
-#define MATCH_NEAREST           0
+/* Listbox system timer id */
+#define LB_TIMER_ID  2
 
-static void ListBoxInitialize(LPHEADLIST lphl)
+/* Item structure */
+typedef struct
 {
-  lphl->lpFirst        = NULL;
-  lphl->ItemsCount     = 0;
-  lphl->ItemsVisible   = 0;
-  lphl->FirstVisible   = 0;
-  lphl->ColumnsVisible = 1;
-  lphl->ItemsPerColumn = 0;
-  lphl->ItemFocused    = -1;
-  lphl->PrevFocused    = -1;
-}
+    LPSTR     str;       /* Item text */
+    BOOL32    selected;  /* Is item selected? */
+    UINT32    height;    /* Item height (only for OWNERDRAWVARIABLE) */
+    DWORD     data;      /* User data */
+} LB_ITEMDATA;
 
-void CreateListBoxStruct(HWND hwnd, WORD CtlType, LONG styles, HWND parent)
+/* Listbox structure */
+typedef struct
 {
-  LPHEADLIST lphl;
-  HDC32         hdc;
+    HANDLE32      heap;           /* Heap for this listbox */
+    HWND32        owner;          /* Owner window */
+    UINT32        style;          /* Window style */
+    INT32         width;          /* Window width */
+    INT32         height;         /* Window height */
+    LB_ITEMDATA  *items;          /* Array of items */
+    INT32         nb_items;       /* Number of items */
+    INT32         top_item;       /* Top visible item */
+    INT32         selected_item;  /* Selected item */
+    INT32         focus_item;     /* Item that has the focus */
+    INT32         anchor_item;    /* Anchor item for extended selection */
+    INT32         item_height;    /* Default item height */
+    INT32         page_size;      /* Items per listbox page */
+    INT32         column_width;   /* Column width for multi-column listboxes */
+    INT32         horz_extent;    /* Horizontal extent (0 if no hscroll) */
+    INT32         horz_pos;       /* Horizontal position */
+    INT32         nb_tabs;        /* Number of tabs in array */
+    INT32        *tabs;           /* Array of tabs */
+    BOOL32        caret_on;       /* Is caret on? */
+    HFONT32       font;           /* Current font */
+    LCID          locale;         /* Current locale for string comparisons */
+} LB_DESCR;
 
-  lphl = (LPHEADLIST)xmalloc(sizeof(HEADLIST));
-  SetWindowLong32A(hwnd, 0, (LONG)lphl);
-  ListBoxInitialize(lphl);
-  lphl->DrawCtlType    = CtlType;
-  lphl->CtlID          = GetWindowWord(hwnd,GWW_ID);
-  lphl->bRedrawFlag    = TRUE;
-  lphl->iNumStops      = 0;
-  lphl->TabStops       = NULL;
-  lphl->hFont          = GetStockObject32(SYSTEM_FONT);
-  lphl->hSelf          = hwnd;  
-  if (CtlType==ODT_COMBOBOX)              /* use the "faked" style for COMBOLBOX */
-                                          /* LBS_SORT instead CBS_SORT e.g.      */
-    lphl->dwStyle   = MAKELONG(LOWORD(styles),HIWORD(GetWindowLong32A(hwnd,GWL_STYLE)));
-  else
-    lphl->dwStyle   = GetWindowLong32A(hwnd,GWL_STYLE); /* use original style dword */
-  lphl->hParent        = parent;
-  lphl->StdItemHeight  = 15; /* FIXME: should get the font height */
-  lphl->OwnerDrawn     = styles & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE);
-  lphl->HasStrings     = (styles & LBS_HASSTRINGS) || !lphl->OwnerDrawn;
 
-  /* create dummy hdc to set text height */
-  if ((hdc = GetDC32(0)))
-  {
-      TEXTMETRIC16 tm;
-      GetTextMetrics16( hdc, &tm );
-      lphl->StdItemHeight = tm.tmHeight;
-      dprintf_listbox(stddeb,"CreateListBoxStruct:  font height %d\n",
-                      lphl->StdItemHeight);
-      ReleaseDC32( 0, hdc );
-  }
+#define IS_OWNERDRAW(descr) \
+    ((descr)->style & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE))
 
-  if (lphl->OwnerDrawn)
-  {
-    LISTSTRUCT dummyls;
-    
-    lphl->needMeasure = TRUE;
-    dummyls.mis.CtlType    = lphl->DrawCtlType;
-    dummyls.mis.CtlID      = lphl->CtlID;
-    dummyls.mis.itemID     = -1;
-    dummyls.mis.itemWidth  = 0; /* ignored */
-    dummyls.mis.itemData   = 0;
+#define HAS_STRINGS(descr) \
+    (!IS_OWNERDRAW(descr) || ((descr)->style & LBS_HASSTRINGS))
 
-    ListBoxAskMeasure(lphl,&dummyls);
-  }
+#define SEND_NOTIFICATION(wnd,descr,code) \
+    (SendMessage32A( (descr)->owner, WM_COMMAND, \
+                     MAKEWPARAM( (wnd)->wIDmenu, (code) ), (wnd)->hwndSelf ))
 
-  lphl->HeapSel = GlobalAlloc16(GMEM_FIXED,LIST_HEAP_SIZE);
-  LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1);
-}
-
-void DestroyListBoxStruct(LPHEADLIST lphl)
+/* Current timer status */
+typedef enum
 {
-  /* XXX need to free lphl->Heap */
-  GlobalFree16(lphl->HeapSel);
-  free(lphl);
-}
+    LB_TIMER_NONE,
+    LB_TIMER_UP,
+    LB_TIMER_LEFT,
+    LB_TIMER_DOWN,
+    LB_TIMER_RIGHT
+} TIMER_DIRECTION;
 
-static LPHEADLIST ListBoxGetStorageHeader(HWND hwnd)
+static TIMER_DIRECTION LISTBOX_Timer = LB_TIMER_NONE;
+
+
+/***********************************************************************
+ *           LISTBOX_Dump
+ */
+void LISTBOX_Dump( WND *wnd )
 {
-    return (LPHEADLIST)GetWindowLong32A(hwnd,0);
-}
+    INT32 i;
+    LB_ITEMDATA *item;
+    LB_DESCR *descr = *(LB_DESCR **)wnd->wExtra;
 
-/* Send notification "code" as part of a WM_COMMAND-message if hwnd
-   has the LBS_NOTIFY style */
-void ListBoxSendNotification(LPHEADLIST lphl, WORD code)
-{
-  if (lphl->dwStyle & LBS_NOTIFY)
-      SendMessage32A( lphl->hParent, WM_COMMAND,
-                      MAKEWPARAM( lphl->CtlID, code), (LPARAM)lphl->hSelf );
-}
-
-
-/* get the maximum value of lphl->FirstVisible */
-int ListMaxFirstVisible(LPHEADLIST lphl)
-{
-    int m = lphl->ItemsCount-lphl->ItemsVisible;
-    return (m < 0) ? 0 : m;
-}
-
-
-void ListBoxUpdateWindow(HWND hwnd, LPHEADLIST lphl, BOOL repaint)
-{
-  if (lphl->dwStyle & WS_VSCROLL)
-    SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
-  if ((lphl->dwStyle & WS_HSCROLL) && (lphl->ItemsPerColumn != 0))
-    SetScrollRange32(hwnd, SB_HORZ, 1, lphl->ItemsVisible /
-		   lphl->ItemsPerColumn + 1, TRUE);
-
-  if (repaint && lphl->bRedrawFlag) InvalidateRect32( hwnd, NULL, TRUE );
-}
-
-/* Returns: 0 if nothing needs to be changed */
-/*          1 if FirstVisible changed */
-
-int ListBoxScrollToFocus(LPHEADLIST lphl)
-{
-  short       end;
-
-  if (lphl->ItemsCount == 0) return 0;
-  if (lphl->ItemFocused == -1) return 0;
-
-  end = lphl->FirstVisible + lphl->ItemsVisible - 1;
-
-  if (lphl->ItemFocused < lphl->FirstVisible ) {
-    lphl->FirstVisible = lphl->ItemFocused;
-    return 1;
-  } else {
-    if (lphl->ItemFocused > end) {
-      WORD maxFirstVisible = ListMaxFirstVisible(lphl);
-
-      lphl->FirstVisible = lphl->ItemFocused;
-      
-      if (lphl->FirstVisible > maxFirstVisible) {
-	lphl->FirstVisible = maxFirstVisible;
-      }
-      return 1;
+    printf( "Listbox:\n" );
+    printf( "hwnd=%04x descr=%08x heap=%08x items=%d top=%d\n",
+            wnd->hwndSelf, (UINT32)descr, descr->heap, descr->nb_items,
+            descr->top_item );
+    for (i = 0, item = descr->items; i < descr->nb_items; i++, item++)
+    {
+        printf( "%4d: %-40s %d %08lx %3d\n",
+                i, item->str, item->selected, item->data, item->height );
     }
-  } 
-  return 0;
 }
 
 
-LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex)
+/***********************************************************************
+ *           LISTBOX_GetCurrentPageSize
+ *
+ * Return the current page size
+ */
+static INT32 LISTBOX_GetCurrentPageSize( WND *wnd, LB_DESCR *descr )
 {
-  LPLISTSTRUCT lpls;
-  UINT         Count = 0;
-
-  if (uIndex >= lphl->ItemsCount) return NULL;
-
-  lpls = lphl->lpFirst;
-  while (Count++ < uIndex) lpls = lpls->lpNext;
-  return lpls;
+    INT32 i, height;
+    if (!(descr->style & LBS_OWNERDRAWVARIABLE)) return descr->page_size;
+    for (i = descr->top_item, height = 0; i < descr->nb_items; i++)
+    {
+        if ((height += descr->items[i].height) > descr->height) break;
+    }
+    if (i == descr->top_item) return 1;
+    else return i - descr->top_item;
 }
 
 
-void ListBoxDrawItem(HWND hwnd, LPHEADLIST lphl, HDC16 hdc, LPLISTSTRUCT lpls, 
-                     RECT16 *rect, WORD itemAction, WORD itemState)
+/***********************************************************************
+ *           LISTBOX_GetMaxTopIndex
+ *
+ * Return the maximum possible index for the top of the listbox.
+ */
+static INT32 LISTBOX_GetMaxTopIndex( WND *wnd, LB_DESCR *descr )
 {
-    if (lphl->OwnerDrawn)
+    INT32 max, page;
+
+    if (descr->style & LBS_OWNERDRAWVARIABLE)
+    {
+        page = descr->height;
+        for (max = descr->nb_items - 1; max >= 0; max--)
+            if ((page -= descr->items[max].height) < 0) break;
+        if (max < descr->nb_items - 1) max++;
+    }
+    else if (descr->style & LBS_MULTICOLUMN)
+    {
+        if ((page = descr->width / descr->column_width) < 1) page = 1;
+        max = (descr->nb_items + descr->page_size - 1) / descr->page_size;
+        max = (max - page) * descr->page_size;
+    }
+    else
+    {
+        max = descr->nb_items - descr->page_size;
+    }
+    if (max < 0) max = 0;
+    return max;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_UpdateScroll
+ *
+ * Update the scrollbars. Should be called whenever the content
+ * of the listbox changes.
+ */
+static void LISTBOX_UpdateScroll( WND *wnd, LB_DESCR *descr )
+{
+    SCROLLINFO info;
+
+    if (descr->style & LBS_NOREDRAW) return;
+    info.cbSize = sizeof(info);
+
+    if (descr->style & LBS_MULTICOLUMN)
+    {
+        info.nMin  = 0;
+        info.nMax  = (descr->nb_items - 1) / descr->page_size;
+        info.nPos  = descr->top_item / descr->page_size;
+        info.nPage = descr->width / descr->column_width;
+        if (info.nPage < 1) info.nPage = 1;
+        info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+        if (descr->style & LBS_DISABLENOSCROLL)
+            info.fMask |= SIF_DISABLENOSCROLL;
+        SetScrollInfo32( wnd->hwndSelf, SB_HORZ, &info, TRUE );
+        info.nMax = 0;
+        info.fMask = SIF_RANGE;
+        SetScrollInfo32( wnd->hwndSelf, SB_VERT, &info, TRUE );
+    }
+    else
+    {
+        info.nMin  = 0;
+        info.nMax  = descr->nb_items - 1;
+        info.nPos  = descr->top_item;
+        info.nPage = LISTBOX_GetCurrentPageSize( wnd, descr );
+        info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+        if (descr->style & LBS_DISABLENOSCROLL)
+            info.fMask |= SIF_DISABLENOSCROLL;
+        SetScrollInfo32( wnd->hwndSelf, SB_VERT, &info, TRUE );
+
+        if (descr->horz_extent)
+        {
+            info.nMin  = 0;
+            info.nMax  = descr->horz_extent - 1;
+            info.nPos  = descr->horz_pos;
+            info.nPage = descr->width;
+            info.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;
+            if (descr->style & LBS_DISABLENOSCROLL)
+                info.fMask |= SIF_DISABLENOSCROLL;
+            SetScrollInfo32( wnd->hwndSelf, SB_HORZ, &info, TRUE );
+        }
+    }
+}
+
+
+/***********************************************************************
+ *           LISTBOX_SetTopItem
+ *
+ * Set the top item of the listbox, scrolling up or down if necessary.
+ */
+static LRESULT LISTBOX_SetTopItem( WND *wnd, LB_DESCR *descr, INT32 index,
+                                   BOOL32 scroll )
+{
+    INT32 max = LISTBOX_GetMaxTopIndex( wnd, descr );
+    if (index > max) index = max;
+    if (index < 0) index = 0;
+    if (descr->style & LBS_MULTICOLUMN) index -= index % descr->page_size;
+    if (descr->top_item == index) return LB_OKAY;
+    if (descr->style & LBS_MULTICOLUMN)
+    {
+        INT32 diff = (descr->top_item - index) / descr->page_size * descr->column_width;
+        if (scroll && (abs(diff) < descr->width))
+            ScrollWindow32( wnd->hwndSelf, diff, 0, NULL, NULL );
+        else
+            scroll = FALSE;
+    }
+    else if (scroll)
+    {
+        INT32 diff;
+        if (descr->style & LBS_OWNERDRAWVARIABLE)
+        {
+            INT32 i;
+            diff = 0;
+            if (index > descr->top_item)
+            {
+                for (i = index - 1; i >= descr->top_item; i--)
+                    diff -= descr->items[i].height;
+            }
+            else
+            {
+                for (i = index; i < descr->top_item; i++)
+                    diff += descr->items[i].height;
+            }
+        }
+        else 
+            diff = (descr->top_item - index) * descr->item_height;
+
+        if (abs(diff) < descr->height)
+            ScrollWindow32( wnd->hwndSelf, 0, diff, NULL, NULL );
+        else
+            scroll = FALSE;
+    }
+    if (!scroll) InvalidateRect32( wnd->hwndSelf, NULL, TRUE );
+    descr->top_item = index;
+    LISTBOX_UpdateScroll( wnd, descr );
+    return LB_OKAY;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_UpdatePage
+ *
+ * Update the page size. Should be called when the size of
+ * the client area or the item height changes.
+ */
+static void LISTBOX_UpdatePage( WND *wnd, LB_DESCR *descr )
+{
+    INT32 page_size;
+
+    if ((page_size = descr->height / descr->item_height) < 1) page_size = 1;
+    if (page_size == descr->page_size) return;
+    descr->page_size = page_size;
+    if (descr->style & LBS_MULTICOLUMN)
+        InvalidateRect32( wnd->hwndSelf, NULL, TRUE );
+    LISTBOX_SetTopItem( wnd, descr, descr->top_item, FALSE );
+}
+
+
+/***********************************************************************
+ *           LISTBOX_UpdateSize
+ *
+ * Update the size of the listbox. Should be called when the size of
+ * the client area changes.
+ */
+static void LISTBOX_UpdateSize( WND *wnd, LB_DESCR *descr )
+{
+    RECT32 rect;
+
+    GetClientRect32( wnd->hwndSelf, &rect );
+    descr->width  = rect.right - rect.left;
+    descr->height = rect.bottom - rect.top;
+    if (!(descr->style & LBS_NOINTEGRALHEIGHT))
+    {
+        if ((descr->height > descr->item_height) &&
+            (descr->height % descr->item_height))
+        {
+            dprintf_listbox(stddeb, "Listbox %04x: changing height %d -> %d\n",
+                            wnd->hwndSelf, descr->height,
+                            descr->height - descr->height%descr->item_height );
+            SetWindowPos( wnd->hwndSelf, 0, 0, 0,
+                          wnd->rectWindow.right - wnd->rectWindow.left,
+                          wnd->rectWindow.bottom - wnd->rectWindow.top -
+                              (descr->height % descr->item_height),
+                          SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE );
+            return;
+        }
+    }
+    dprintf_listbox( stddeb, "Listbox %04x: new size = %d,%d\n",
+                     wnd->hwndSelf, descr->width, descr->height );
+    LISTBOX_UpdatePage( wnd, descr );
+    LISTBOX_UpdateScroll( wnd, descr );
+}
+
+
+/***********************************************************************
+ *           LISTBOX_GetItemRect
+ *
+ * Get the rectangle enclosing an item, in listbox client coordinates.
+ * Return 1 if the rectangle is (partially) visible, 0 if hidden, -1 on error.
+ */
+static LRESULT LISTBOX_GetItemRect( WND *wnd, LB_DESCR *descr, INT32 index,
+                                    RECT32 *rect )
+{
+    /* Index <= 0 is legal even on empty listboxes */
+    if (index && (index >= descr->nb_items)) return -1;
+    SetRect32( rect, 0, 0, descr->width, descr->height );
+    if (descr->style & LBS_MULTICOLUMN)
+    {
+        INT32 col = (index / descr->page_size) -
+                        (descr->top_item / descr->page_size);
+        rect->left += col * descr->column_width;
+        rect->right = rect->left + descr->column_width;
+        rect->top += (index % descr->page_size) * descr->item_height;
+        rect->bottom = rect->top + descr->item_height;
+    }
+    else if (descr->style & LBS_OWNERDRAWVARIABLE)
+    {
+        INT32 i;
+        if (index < descr->top_item)
+        {
+            for (i = descr->top_item-1; i >= index; i--)
+                rect->top -= descr->items[i].height;
+        }
+        else
+        {
+            for (i = descr->top_item; i < index; i++)
+                rect->top += descr->items[i].height;
+        }
+        rect->bottom = rect->top + descr->items[index].height;
+        rect->right += descr->horz_pos;
+    }
+    else
+    {
+        rect->top += (index - descr->top_item) * descr->item_height;
+        rect->bottom = rect->top + descr->item_height;
+        rect->right += descr->horz_pos;
+    }
+
+    return ((rect->left < descr->width) && (rect->right > 0) &&
+            (rect->top < descr->height) && (rect->bottom > 0));
+}
+
+
+/***********************************************************************
+ *           LISTBOX_GetItemFromPoint
+ *
+ * Return the item nearest from point (x,y) (in client coordinates).
+ */
+static INT32 LISTBOX_GetItemFromPoint( WND *wnd, LB_DESCR *descr,
+                                       INT32 x, INT32 y )
+{
+    INT32 index = descr->top_item;
+
+    if (!descr->nb_items) return -1;  /* No items */
+    if (descr->style & LBS_OWNERDRAWVARIABLE)
+    {
+        INT32 pos = 0;
+        if (y >= 0)
+        {
+            while (index < descr->nb_items)
+            {
+                if ((pos += descr->items[index].height) > y) break;
+                index++;
+            }
+        }
+        else
+        {
+            while (index > 0)
+            {
+                index--;
+                if ((pos -= descr->items[index].height) <= y) break;
+            }
+        }
+    }
+    else if (descr->style & LBS_MULTICOLUMN)
+    {
+        if (y >= descr->item_height * descr->page_size) return -1;
+        if (y >= 0) index += y / descr->item_height;
+        if (x >= 0) index += (x / descr->column_width) * descr->page_size;
+        else index -= (((x + 1) / descr->column_width) - 1) * descr->page_size;
+    }
+    else
+    {
+        index += (y / descr->item_height);
+    }
+    if (index < 0) return 0;
+    if (index >= descr->nb_items) return -1;
+    return index;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_PaintItem
+ *
+ * Paint an item.
+ */
+static void LISTBOX_PaintItem( WND *wnd, LB_DESCR *descr, HDC32 hdc,
+                               const RECT32 *rect, INT32 index, UINT32 action )
+{
+    LB_ITEMDATA *item = NULL;
+    if (index < descr->nb_items) item = &descr->items[index];
+
+    if (IS_OWNERDRAW(descr))
     {
         DRAWITEMSTRUCT32 dis;
-
-        dis.CtlID      = lpls->mis.CtlID;
-        dis.CtlType    = lpls->mis.CtlType;
-        dis.itemID     = lpls->mis.itemID;
-        dis.hDC        = hdc;
-        dis.hwndItem   = hwnd;
-        dis.itemData   = lpls->mis.itemData;
-        dis.itemAction = itemAction;
-        dis.itemState  = itemState;
-        CONV_RECT16TO32( rect, &dis.rcItem );
-        SendMessage32A( lphl->hParent, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis );
-        return;
-    }
-    if (itemAction == ODA_DRAWENTIRE || itemAction == ODA_SELECT) {
-      int 	OldBkMode;
-      DWORD 	dwOldTextColor = 0;
-
-      OldBkMode = SetBkMode(hdc, TRANSPARENT);
-
-      if (itemState != 0) {
-	dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
-	FillRect16(hdc, rect, GetStockObject32(BLACK_BRUSH));
-      }
-
-      if (lphl->dwStyle & LBS_USETABSTOPS) {
-	TabbedTextOut(hdc, rect->left + 5, rect->top + 2, 
-		      (char *)lpls->itemText, strlen((char *)lpls->itemText), 
-		      lphl->iNumStops, lphl->TabStops, 0);
-      } else {
-	TextOut16(hdc, rect->left + 5, rect->top + 2,
-                  (char *)lpls->itemText, strlen((char *)lpls->itemText));
-      }
-
-      if (itemState != 0) {
-	SetTextColor(hdc, dwOldTextColor);
-      }
-      
-      SetBkMode(hdc, OldBkMode);
-    }
-    else DrawFocusRect16(hdc, rect);
-}
-
-
-int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y)
-{
-  LPLISTSTRUCT lpls = lphl->lpFirst;
-  int          i, j;
-  POINT16      point;
-  
-  point.x = X; point.y = Y;
-  if (lphl->ItemsCount == 0) return LB_ERR;
-
-  for(i = 0; i < lphl->FirstVisible; i++) {
-    if (lpls == NULL) return LB_ERR;
-    lpls = lpls->lpNext;
-  }
-  for(j = 0; j < lphl->ItemsVisible; i++, j++) {
-    if (lpls == NULL) return LB_ERR;
-    if (PtInRect16(&lpls->itemRect,point)) {
-      return i;
-    }
-    lpls = lpls->lpNext;
-  }
-  dprintf_listbox(stddeb,"ListBoxFindMouse: not found\n");
-  return LB_ERR;
-}
-
-BOOL32 lbDeleteItemNotify(LPHEADLIST lphl, LPLISTSTRUCT lpls)
-{
-    /* called only for owner drawn listboxes */
-    BOOL32 ret;
-    DELETEITEMSTRUCT16 *delItem = SEGPTR_NEW(DELETEITEMSTRUCT16);
-    if (!delItem) return FALSE;
-
-    delItem->CtlType  = lphl->DrawCtlType;
-    delItem->CtlID    = lphl->CtlID;
-    delItem->itemID   = lpls->mis.itemID;
-    delItem->hwndItem = lphl->hSelf;
-    delItem->itemData = lpls->mis.itemData;
-
-    ret = SendMessage16( lphl->hParent, WM_DELETEITEM, (WPARAM16)lphl->CtlID,
-                         (LPARAM)SEGPTR_GET(delItem) );
-    SEGPTR_FREE(delItem);
-    return ret;
-}
-
-void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls)  
-{
-    MEASUREITEMSTRUCT16 *lpmeasure = SEGPTR_NEW(MEASUREITEMSTRUCT16);
-    if (!lpmeasure) return;
-    *lpmeasure = lpls->mis;
-    lpmeasure->itemHeight = lphl->StdItemHeight;
-    SendMessage16( lphl->hParent, WM_MEASUREITEM, lphl->CtlID,
-                   (LPARAM)SEGPTR_GET(lpmeasure) );
-
-    if (lphl->dwStyle & LBS_OWNERDRAWFIXED)
-    {
-        if (lpmeasure->itemHeight > lphl->StdItemHeight)
-            lphl->StdItemHeight = lpmeasure->itemHeight;
-        lpls->mis.itemHeight = lpmeasure->itemHeight;
-    }
-    SEGPTR_FREE(lpmeasure);
-}
-
-/* -------------------- strings and item data ---------------------- */
-
-LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id)
-{
-  LPLISTSTRUCT lplsnew = (LPLISTSTRUCT)malloc(sizeof(LISTSTRUCT));
-
-  if (lplsnew == NULL) return NULL;
-  
-  lplsnew->itemState      = 0;
-  lplsnew->mis.CtlType    = lphl->DrawCtlType;
-  lplsnew->mis.CtlID      = lphl->CtlID;
-  lplsnew->mis.itemID     = id;
-  lplsnew->mis.itemHeight = lphl->StdItemHeight;
-  lplsnew->mis.itemWidth  = 0; /* ignored */
-  lplsnew->mis.itemData   = 0;
-  SetRectEmpty16( &lplsnew->itemRect );
-
-  return lplsnew;
-}
-
-int ListBoxAskCompare(LPHEADLIST lphl, int startItem, SEGPTR matchData, BOOL exactMatch )
-{
- /*  Do binary search for sorted listboxes. Linked list item storage sort of 
-  *  defeats the purpose ( forces to traverse item list all the time ) but M$ does it this way...
-  *
-  *  MATCH_NEAREST (0) - return position for insertion - for all styles
-  *  MATCH_EXACT   (1) - search for an item, return index or LB_ERR 
-  *  MATCH_SUBSTR  (2) - same as exact match but with strncmp for string comparision
-  */
-
- COMPAREITEMSTRUCT16   *itemCmp;
- LPLISTSTRUCT		currentItem = NULL;
- LPCSTR			matchStr = (lphl->HasStrings)?(LPCSTR)PTR_SEG_TO_LIN(matchData):NULL;
- int                    head, pos = -1, tail, loop = 1;
- short                  b = 0, s_length = 0;
-
- /* check if empty */
-
- if( !lphl->ItemsCount )
-    return (exactMatch)? LB_ERR: 0;
-
- /* set up variables */
-
- if( exactMatch == MATCH_NEAREST )
-     startItem = 0;
- else if( ++startItem ) 
-   {
-     loop = 2;
-     if( startItem >= lphl->ItemsCount ) startItem = lphl->ItemsCount - 1;
-   }
-
- if( exactMatch == MATCH_SUBSTR && lphl->HasStrings )
-   {
-     s_length = strlen( matchStr );
-     if( !s_length ) return 0; 		        /* head of the list - empty string */
-   }
-
- head = startItem; tail = lphl->ItemsCount - 1;
-
- dprintf_listbox(stddeb,"AskCompare: head = %i, tail = %i, data = %08x\n", head, tail, (unsigned)matchData );
-
- if (!(itemCmp = SEGPTR_NEW(COMPAREITEMSTRUCT16))) return 0;
- itemCmp->CtlType        = lphl->DrawCtlType;
- itemCmp->CtlID          = lphl->CtlID;
- itemCmp->hwndItem       = lphl->hSelf;
-
- /* search from startItem */
-
- while ( loop-- )
-  {
-    while( head <= tail )
-     {
-       pos = (tail + head)/2;
-       currentItem = ListBoxGetItem( lphl, pos );
-
-       if( lphl->HasStrings )
-	 {
-           b = ( s_length )? lstrncmpi32A( currentItem->itemText, matchStr, s_length)
-                           : lstrcmpi32A( currentItem->itemText, matchStr);
-	 }
-       else
-         {
-           itemCmp->itemID1      = pos;
-           itemCmp->itemData1    = currentItem->mis.itemData;
-           itemCmp->itemID2      = -1;
-           itemCmp->itemData2    = matchData;
-
-           b = SendMessage16( lphl->hParent, WM_COMPAREITEM,
-                              (WPARAM16)lphl->CtlID,
-                              (LPARAM)SEGPTR_GET(itemCmp) );
-         }
-
-       if( b == 0 )
-       {
-           SEGPTR_FREE(itemCmp);
-           return pos;  /* found exact match */
-       }
-       else
-         if( b < 0 ) head = ++pos;
-         else
-           if( b > 0 ) tail = pos - 1;
-     }
-
-    /* reset to search from the first item */
-    head = 0; tail = startItem - 1;
-  }
-
- dprintf_listbox(stddeb,"\t-> pos = %i\n", pos );
- SEGPTR_FREE(itemCmp);
-
- /* if we got here match is not exact */
-
- if( pos < 0 ) pos = 0;
- else if( pos > lphl->ItemsCount ) pos = lphl->ItemsCount;
-
- return (exactMatch)? LB_ERR: pos;
-}
-
-int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr)
-{
-  LPLISTSTRUCT *lppls, lplsnew, lpls;
-  HANDLE16 hStr;
-  LPSTR	str;
-  UINT	Count;
-    
-  dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr);
-    
-  if (!newstr) return -1;
-
-  if (uIndex == (UINT)-1)
-    uIndex = lphl->ItemsCount;
-
-  lppls = &lphl->lpFirst;
-  for(Count = 0; Count < uIndex; Count++) {
-    if (*lppls == NULL) return LB_ERR;
-    lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
-  }
-    
-  lplsnew = ListBoxCreateItem(lphl, Count);
-  
-  if (lplsnew == NULL) {
-    fprintf(stdnimp,"ListBoxInsertString() out of memory !\n");
-    return LB_ERRSPACE;
-  }
-
-  lplsnew->lpNext = *lppls;
-  *lppls = lplsnew;
-  lphl->ItemsCount++;
-  
-  hStr = 0;
-  if (lphl->HasStrings) {
-    dprintf_listbox(stddeb,"  string: %s\n", newstr);
-    hStr = LIST_HEAP_ALLOC(lphl, LMEM_MOVEABLE, strlen(newstr) + 1);
-    str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
-    if (str == NULL) return LB_ERRSPACE;
-    strcpy(str, newstr); 
-    lplsnew->itemText = str;
-    /* I'm not so sure about the next one */
-    lplsnew->mis.itemData = 0;
-  } else {
-    lplsnew->itemText = NULL;
-    lplsnew->mis.itemData = (DWORD)newstr;
-  }
-
-  lplsnew->mis.itemID = uIndex;
-  lplsnew->hData = hStr;
-  
-  /* adjust the itemID field of the following entries */
-  for(lpls = lplsnew->lpNext; lpls != NULL; lpls = lpls->lpNext) {
-      lpls->mis.itemID++;
-  }
- 
-  if (lphl->needMeasure) {
-    ListBoxAskMeasure(lphl, lplsnew);
-  }
-
-  dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
-  return uIndex;
-}
-
-
-int ListBoxAddString(LPHEADLIST lphl, SEGPTR itemData)
-{
-    UINT 	pos = (UINT) -1;
-    LPCSTR	newstr = (lphl->HasStrings)?(LPCSTR)PTR_SEG_TO_LIN(itemData):(LPCSTR)itemData;
-
-    if ( lphl->dwStyle & LBS_SORT ) 
-	 pos = ListBoxAskCompare( lphl, -1, itemData, MATCH_NEAREST );
-
-    return ListBoxInsertString(lphl, pos, newstr);
-}
-
-
-int ListBoxGetText(LPHEADLIST lphl, UINT uIndex, LPSTR OutStr)
-{
-  LPLISTSTRUCT lpls;
-
-  if (!OutStr) {
-    dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
-    return 0;
-  }
-  *OutStr = '\0';
-  lpls = ListBoxGetItem (lphl, uIndex);
-  if (lpls == NULL) return LB_ERR;
-
-  if (!lphl->HasStrings) {
-    *((long *)OutStr) = lpls->mis.itemData;
-    return 4;
-  }
-	
-  strcpy(OutStr, lpls->itemText);
-  return strlen(OutStr);
-}
-
-
-DWORD ListBoxGetItemData(LPHEADLIST lphl, UINT uIndex)
-{
-  LPLISTSTRUCT lpls;
-
-  lpls = ListBoxGetItem (lphl, uIndex);
-  if (lpls == NULL) return LB_ERR;
-  return lpls->mis.itemData;
-}
-
-
-int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData)
-{
-  LPLISTSTRUCT lpls = ListBoxGetItem(lphl, uIndex);
-
-  if (lpls == NULL) return LB_ERR;
-  lpls->mis.itemData = ItemData;
-  return 1;
-}
-
-
-int ListBoxDeleteString(LPHEADLIST lphl, UINT uIndex)
-{
-  LPLISTSTRUCT lpls, lpls2;
-  UINT	Count;
-
-  if (uIndex >= lphl->ItemsCount) return LB_ERR;
-
-  lpls = lphl->lpFirst;
-  if (lpls == NULL) return LB_ERR;
-
-  if (uIndex == 0)
-  {
-    if( lphl->OwnerDrawn )
-        lbDeleteItemNotify( lphl, lpls);
-    lphl->lpFirst = lpls->lpNext;
-  }
-  else 
-  {
-    LPLISTSTRUCT lpls2 = NULL;
-    for(Count = 0; Count < uIndex; Count++) {
-      if (lpls->lpNext == NULL) return LB_ERR;
-
-      lpls2 = lpls;
-      lpls = (LPLISTSTRUCT)lpls->lpNext;
-    }
-    if( lphl->OwnerDrawn )
-	lbDeleteItemNotify( lphl, lpls);
-    lpls2->lpNext = lpls->lpNext;
-  }
-
-  /* adjust the itemID field of the following entries */
-  for(lpls2 = lpls->lpNext; lpls2 != NULL; lpls2 = lpls2->lpNext) {
-      lpls2->mis.itemID--;
-  }
- 
-  lphl->ItemsCount--;
-
-  if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
-  free(lpls);
-  
-  return lphl->ItemsCount;
-}
-
-int lbFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr, BOOL match)
-{
-  /*  match is either MATCH_SUBSTR or MATCH_EXACT */
-
-  LPLISTSTRUCT lpls;
-  UINT	       Count;
-  UINT         First      = nFirst + 1;
-  int	       s_length   = 0;
-  LPSTR        lpMatchStr = (LPSTR)MatchStr;
-
-  if (First > lphl->ItemsCount) return LB_ERR;
-
-  if (lphl->dwStyle & LBS_SORT )
-      return ListBoxAskCompare( lphl, nFirst, MatchStr, match );
-
-  if (lphl->HasStrings ) 
-  {
-    lpMatchStr = PTR_SEG_TO_LIN(MatchStr);
-
-    if( match == MATCH_SUBSTR )
-    {
-      s_length = strlen(lpMatchStr);
-      if( !s_length ) return (lphl->ItemsCount)?0:LB_ERR;
-    }
-  }
-
-  lpls = ListBoxGetItem(lphl, First);
-  Count = 0;
-  while(lpls != NULL) 
-  {
-    if (lphl->HasStrings) 
-    {
-      if ( ( s_length )? !lstrncmpi32A(lpls->itemText, lpMatchStr, s_length)
-                       : !lstrcmpi32A(lpls->itemText, lpMatchStr)  ) return Count;
+        dis.CtlType      = ODT_LISTBOX;
+        dis.CtlID        = wnd->wIDmenu;
+        dis.hwndItem     = wnd->hwndSelf;
+        dis.itemAction   = action;
+        dis.hDC          = hdc;
+        dis.itemID       = index;
+        dis.itemState    = 0;
+        if (item && item->selected) dis.itemState |= ODS_SELECTED;
+        if ((descr->focus_item == index) &&
+            (descr->caret_on) &&
+            (GetFocus32() == wnd->hwndSelf)) dis.itemState |= ODS_FOCUS;
+        if (wnd->dwStyle & WS_DISABLED) dis.itemState |= ODS_DISABLED;
+        dis.itemData     = item ? item->data : 0;
+        dis.rcItem       = *rect;
+        dprintf_listbox( stddeb, "Listbox %04x: drawitem %d (%s) action=%02x "
+                         "state=%02x rect=%d,%d-%d,%d\n",
+                         wnd->hwndSelf, index, item ? item->str : "", action,
+                         dis.itemState, rect->left, rect->top,
+                         rect->right, rect->bottom );
+        SendMessage32A(descr->owner, WM_DRAWITEM, wnd->wIDmenu, (LPARAM)&dis);
     }
     else
-      if ( lpls->mis.itemData == (DWORD)lpMatchStr ) return Count;
-
-    lpls = lpls->lpNext;
-    Count++;
-  }
-
-  /* Start over at top */
-  Count = 0;
-  lpls = lphl->lpFirst;
-
-  while (Count < First) 
-  {
-    if (lphl->HasStrings) 
     {
-      if ( ( s_length )? !lstrncmpi32A(lpls->itemText, lpMatchStr, s_length)
-                       : !lstrcmpi32A(lpls->itemText, lpMatchStr)  ) return Count;
+        if (action == ODA_FOCUS)
+        {
+            DrawFocusRect32( hdc, rect );
+            return;
+        }
+        if (item && item->selected)
+        {
+            SetBkColor( hdc, GetSysColor( COLOR_HIGHLIGHT ) );
+            SetTextColor( hdc, GetSysColor( COLOR_HIGHLIGHTTEXT ) );
+        }
+        else
+        {
+            SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) );
+            if (wnd->dwStyle & WS_DISABLED)
+                SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
+            else
+                SetTextColor( hdc, GetSysColor( COLOR_WINDOWTEXT ) );
+        }
+        dprintf_listbox( stddeb, "Listbox %04x: painting %d (%s) action=%02x"
+                         "rect=%d,%d-%d,%d\n",
+                         wnd->hwndSelf, index, item ? item->str : "", action,
+                         rect->left, rect->top, rect->right, rect->bottom );
+        /* FIXME: check LBS_USETABSTOPS style */
+        if (item)
+            ExtTextOut32A( hdc, rect->left + 1, rect->top + 1,
+                           ETO_OPAQUE | ETO_CLIPPED, rect, item->str,
+                           strlen(item->str), NULL );
+        else
+            ExtTextOut32A( hdc, rect->left + 1, rect->top + 1,
+                           ETO_OPAQUE | ETO_CLIPPED, rect, NULL, 0, NULL );
+        if ((descr->focus_item == index) &&
+            (descr->caret_on) &&
+            (GetFocus32() == wnd->hwndSelf)) DrawFocusRect32( hdc, rect );
     }
-    else
-      if ( lpls->mis.itemData == (DWORD)lpMatchStr ) return Count;
-    
-    lpls = lpls->lpNext;
-    Count++;
-  }
-
-  return LB_ERR;
 }
 
-int ListBoxFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
+
+/***********************************************************************
+ *           LISTBOX_SetRedraw
+ *
+ * Change the redraw flag.
+ */
+static void LISTBOX_SetRedraw( WND *wnd, LB_DESCR *descr, BOOL32 on )
 {
-  return lbFindString(lphl, nFirst, MatchStr, MATCH_SUBSTR );
-}
-
-int ListBoxFindStringExact(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
-{
-  return lbFindString(lphl, nFirst, MatchStr, MATCH_EXACT );
-}
-
-int ListBoxResetContent(LPHEADLIST lphl)
-{
-    LPLISTSTRUCT lpls;
-    int i;
-
-    if (lphl->ItemsCount == 0) return 0;
-
-    dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
-	lphl->ItemsCount);
-
-    for(i = 0; i < lphl->ItemsCount; i++) {
-      lpls = lphl->lpFirst;
-      if (lpls == NULL) return LB_ERR;
-
-      if (lphl->OwnerDrawn) lbDeleteItemNotify(lphl, lpls);
-
-      lphl->lpFirst = lpls->lpNext;
-      if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
-      free(lpls);
+    if (on)
+    {
+        if (!(descr->style & LBS_NOREDRAW)) return;
+        descr->style &= ~LBS_NOREDRAW;
+        LISTBOX_UpdateScroll( wnd, descr );
     }
-    ListBoxInitialize(lphl);
+    else descr->style |= LBS_NOREDRAW;
+}
 
+
+/***********************************************************************
+ *           LISTBOX_RepaintItem
+ *
+ * Repaint a single item synchronously.
+ */
+static void LISTBOX_RepaintItem( WND *wnd, LB_DESCR *descr, INT32 index,
+                                 UINT32 action )
+{
+    HDC32 hdc;
+    RECT32 rect;
+
+    if (descr->style & LBS_NOREDRAW) return;
+    if (LISTBOX_GetItemRect( wnd, descr, index, &rect ) != 1) return;
+    if ((hdc = GetDCEx32( wnd->hwndSelf, 0, DCX_CACHE )))
+    {
+        HFONT32 oldFont = 0;
+        if (descr->font) oldFont = SelectObject32( hdc, descr->font );
+        SetWindowOrgEx32( hdc, descr->horz_pos, 0, NULL );
+        LISTBOX_PaintItem( wnd, descr, hdc, &rect, index, action );
+        if (oldFont) SelectObject32( hdc, oldFont );
+        ReleaseDC32( wnd->hwndSelf, hdc );
+    }
+}
+
+
+/***********************************************************************
+ *           LISTBOX_InitStorage
+ */
+static LRESULT LISTBOX_InitStorage( WND *wnd, LB_DESCR *descr, INT32 nb_items,
+                                    DWORD bytes )
+{
+    LB_ITEMDATA *item;
+
+    nb_items += LB_ARRAY_GRANULARITY - 1;
+    nb_items -= (nb_items % LB_ARRAY_GRANULARITY);
+    if (descr->items)
+        nb_items += HeapSize( descr->heap, 0, descr->items ) / sizeof(*item);
+    if (!(item = HeapReAlloc( descr->heap, 0, descr->items,
+                              nb_items * sizeof(LB_ITEMDATA) )))
+    {
+        SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
+        return LB_ERRSPACE;
+    }
+    descr->items = item;
+    return LB_OKAY;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_SetTabStops
+ */
+static BOOL32 LISTBOX_SetTabStops( WND *wnd, LB_DESCR *descr, INT32 count,
+                                   LPINT32 tabs, BOOL32 short_ints )
+{
+    if (!(descr->style & LBS_USETABSTOPS)) return TRUE;
+    if (descr->tabs) HeapFree( descr->heap, 0, descr->tabs );
+    if (!(descr->nb_tabs = count))
+    {
+        descr->tabs = NULL;
+        return TRUE;
+    }
+    /* FIXME: count = 1 */
+    if (!(descr->tabs = (INT32 *)HeapAlloc( descr->heap, 0,
+                                            descr->nb_tabs * sizeof(INT32) )))
+        return FALSE;
+    if (short_ints)
+    {
+        INT32 i;
+        LPINT16 p = (LPINT16)tabs;
+        for (i = 0; i < descr->nb_tabs; i++) descr->tabs[i] = *p++;
+    }
+    else memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT32) );
+    /* FIXME: repaint the window? */
     return TRUE;
 }
 
-/* --------------------- selection ------------------------- */
 
-int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex)
+/***********************************************************************
+ *           LISTBOX_GetText
+ */
+static LRESULT LISTBOX_GetText( WND *wnd, LB_DESCR *descr, INT32 index,
+                                LPSTR buffer )
 {
-  LPLISTSTRUCT lpls;
-
-  /* use ListBoxSetSel instead */
-  if (lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) return 0;
-
-  /* unselect previous item */
-  if (lphl->ItemFocused != -1) {
-    lphl->PrevFocused = lphl->ItemFocused;
-    lpls = ListBoxGetItem(lphl, lphl->ItemFocused);
-    if (lpls == 0) return LB_ERR;
-    lpls->itemState = 0;
-  }
-
-  if ((wIndex != (UINT)-1) && (wIndex < lphl->ItemsCount))
-  {
-    lphl->ItemFocused = wIndex;
-    lpls = ListBoxGetItem(lphl, wIndex);
-    if (lpls == 0) return LB_ERR;
-    lpls->itemState = ODS_SELECTED | ODS_FOCUS;
-
-    return 0;
-  }
-
-  return LB_ERR;
-}
-
-
-int ListBoxSetSel(LPHEADLIST lphl, WORD wIndex, WORD state)
-{
-  LPLISTSTRUCT  lpls;
-  int           n = 0;
-
-  if (!(lphl->dwStyle &  (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)  )) 
-        return LB_ERR;
-
-  if (wIndex == (UINT)-1) {
-    for (lpls = lphl->lpFirst; lpls != NULL; lpls = lpls->lpNext) {
-      if( lpls->itemState & ODS_SELECTED) n++;
-      lpls->itemState = state? lpls->itemState |  ODS_SELECTED
-                             : lpls->itemState & ~ODS_SELECTED;
+    if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+    if (HAS_STRINGS(descr))
+    {
+        lstrcpy32A( buffer, descr->items[index].str );
+        return strlen(buffer);
     }
-    return n;
-  }
-
-  if (wIndex >= lphl->ItemsCount) return LB_ERR;
-
-  lpls = ListBoxGetItem(lphl, wIndex);
-  lpls->itemState = state? lpls->itemState |  ODS_SELECTED
-                         : lpls->itemState & ~ODS_SELECTED;
-
-  return 0;
+    else
+    {
+        memcpy( buffer, &descr->items[index].data, sizeof(DWORD) );
+        return sizeof(DWORD);
+    }
 }
 
 
-int ListBoxGetSel(LPHEADLIST lphl, WORD wIndex)
+/***********************************************************************
+ *           LISTBOX_FindStringPos
+ *
+ * Find the nearest string located before a given string in sort order.
+ * If 'exact' is TRUE, return an error if we don't get an exact match.
+ */
+static INT32 LISTBOX_FindStringPos( WND *wnd, LB_DESCR *descr, LPCSTR str,
+                                    BOOL32 exact )
 {
-  LPLISTSTRUCT lpls = ListBoxGetItem(lphl, wIndex);
+    INT32 index, min, max, res = -1;
 
-  if (lpls == NULL) return LB_ERR;
-  return lpls->itemState & ODS_SELECTED;
+    if (!(descr->style & LBS_SORT)) return -1;  /* Add it at the end */
+    min = 0;
+    max = descr->nb_items;
+    while (min != max)
+    {
+        index = (min + max) / 2;
+        if (HAS_STRINGS(descr))
+            res = lstrcmpi32A( descr->items[index].str, str );
+        else
+        {
+            COMPAREITEMSTRUCT32 cis;
+            cis.CtlType    = ODT_LISTBOX;
+            cis.CtlID      = wnd->wIDmenu;
+            cis.hwndItem   = wnd->hwndSelf;
+            cis.itemID1    = index;
+            cis.itemData1  = descr->items[index].data;
+            cis.itemID2    = -1;
+            cis.itemData2  = (DWORD)str;
+            cis.dwLocaleId = descr->locale;
+            res = SendMessage32A( descr->owner, WM_COMPAREITEM,
+                                  wnd->wIDmenu, (LPARAM)&cis );
+        }
+        if (!res) return index;
+        if (res > 0) max = index;
+        else min = index + 1;
+    }
+    return exact ? -1 : max;
 }
 
-/* ------------------------- dir listing ------------------------ */
 
-LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec)
+/***********************************************************************
+ *           LISTBOX_FindFileStrPos
+ *
+ * Find the nearest string located before a given string in directory
+ * sort order (i.e. first files, then directories, then drives).
+ */
+static INT32 LISTBOX_FindFileStrPos( WND *wnd, LB_DESCR *descr, LPCSTR str )
 {
-    char 	mask[13];
-    char*	temp = NULL;
-    const char*	ptr;
-    int 	skip, count;
-    LONG 	ret;
-    DOS_DIRENT 	entry;
+    INT32 min, max, res = -1;
+
+    if (!HAS_STRINGS(descr))
+        return LISTBOX_FindStringPos( wnd, descr, str, FALSE );
+    min = 0;
+    max = descr->nb_items;
+    while (min != max)
+    {
+        INT32 index = (min + max) / 2;
+        const char *p = descr->items[index].str;
+        if (*p == '[')  /* drive or directory */
+        {
+            if (*str != '[') res = -1;
+            else if (p[1] == '-')  /* drive */
+            {
+                if (str[1] == '-') res = str[2] - p[2];
+                else res = -1;
+            }
+            else  /* directory */
+            {
+                if (str[1] == '-') res = 1;
+                else res = lstrcmpi32A( str, p );
+            }
+        }
+        else  /* filename */
+        {
+            if (*str == '[') res = 1;
+            else res = lstrcmpi32A( str, p );
+        }
+        if (!res) return index;
+        if (res < 0) max = index;
+        else min = index + 1;
+    }
+    return max;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_FindString
+ *
+ * Find the item beginning with a given string.
+ */
+static INT32 LISTBOX_FindString( WND *wnd, LB_DESCR *descr, INT32 start,
+                                 LPCSTR str, BOOL32 exact )
+{
+    INT32 i;
+    LB_ITEMDATA *item;
+
+    if (start >= descr->nb_items) start = -1;
+    item = descr->items + start + 1;
+    if (HAS_STRINGS(descr))
+    {
+        if (exact)
+        {
+            for (i = start + 1; i < descr->nb_items; i++, item++)
+                if (!lstrcmpi32A( str, item->str )) return i;
+            for (i = 0, item = descr->items; i <= start; i++, item++)
+                if (!lstrcmpi32A( str, item->str )) return i;
+        }
+        else
+        {
+ /* Special case for drives and directories: ignore prefix */
+#define CHECK_DRIVE(item) \
+    if ((item)->str[0] == '[') \
+    { \
+        if (!lstrncmpi32A( str, (item)->str+1, len )) return i; \
+        if (((item)->str[1] == '-') && !lstrncmpi32A(str,(item)->str+2,len)) \
+        return i; \
+    }
+
+            INT32 len = strlen(str);
+            for (i = start + 1; i < descr->nb_items; i++, item++)
+            {
+               if (!lstrncmpi32A( str, item->str, len )) return i;
+               CHECK_DRIVE(item);
+            }
+            for (i = 0, item = descr->items; i <= start; i++, item++)
+            {
+               if (!lstrncmpi32A( str, item->str, len )) return i;
+               CHECK_DRIVE(item);
+            }
+#undef CHECK_DRIVE
+        }
+    }
+    else
+    {
+        if (exact && (descr->style & LBS_SORT))
+            /* If sorted, use a WM_COMPAREITEM binary search */
+            return LISTBOX_FindStringPos( wnd, descr, str, TRUE );
+
+        /* Otherwise use a linear search */
+        for (i = start + 1; i < descr->nb_items; i++, item++)
+            if (item->data == (DWORD)str) return i;
+        for (i = 0, item = descr->items; i <= start; i++, item++)
+            if (item->data == (DWORD)str) return i;
+    }
+    return LB_ERR;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_GetSelCount
+ */
+static LRESULT LISTBOX_GetSelCount( WND *wnd, LB_DESCR *descr )
+{
+    INT32 i, count;
+    LB_ITEMDATA *item = descr->items;
+
+    if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+    for (i = count = 0; i < descr->nb_items; i++, item++)
+        if (item->selected) count++;
+    return count;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_GetSelItems16
+ */
+static LRESULT LISTBOX_GetSelItems16( WND *wnd, LB_DESCR *descr, INT16 max,
+                                      LPINT16 array )
+{
+    INT32 i, count;
+    LB_ITEMDATA *item = descr->items;
+
+    if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+    for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
+        if (item->selected) array[count++] = (INT16)i;
+    return count;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_GetSelItems32
+ */
+static LRESULT LISTBOX_GetSelItems32( WND *wnd, LB_DESCR *descr, INT32 max,
+                                      LPINT32 array )
+{
+    INT32 i, count;
+    LB_ITEMDATA *item = descr->items;
+
+    if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+    for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
+        if (item->selected) array[count++] = i;
+    return count;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_Paint
+ */
+static LRESULT LISTBOX_Paint( WND *wnd, LB_DESCR *descr, HDC32 hdc )
+{
+    INT32 i, col_pos = descr->page_size - 1;
+    RECT32 rect;
+    HFONT32 oldFont = 0;
+
+    SetRect32( &rect, 0, 0, descr->width, descr->height );
+    if (descr->style & LBS_NOREDRAW) return 0;
+    if (descr->style & LBS_MULTICOLUMN)
+        rect.right = rect.left + descr->column_width;
+    else if (descr->horz_pos)
+    {
+        SetWindowOrgEx32( hdc, descr->horz_pos, 0, NULL );
+        rect.right += descr->horz_pos;
+    }
+
+    if (descr->font) oldFont = SelectObject32( hdc, descr->font );
+
+    if (!descr->nb_items && (descr->focus_item != -1) && descr->caret_on &&
+        (GetFocus32() == wnd->hwndSelf))
+    {
+        /* Special case for empty listbox: paint focus rect */
+        rect.bottom = rect.top + descr->item_height;
+        LISTBOX_PaintItem( wnd, descr, hdc, &rect, descr->focus_item,
+                           ODA_DRAWENTIRE );
+        rect.top = rect.bottom;
+    }
+
+    for (i = descr->top_item; i < descr->nb_items; i++)
+    {
+        if (!(descr->style & LBS_OWNERDRAWVARIABLE))
+            rect.bottom = rect.top + descr->item_height;
+        else
+            rect.bottom = rect.top + descr->items[i].height;
+
+        LISTBOX_PaintItem( wnd, descr, hdc, &rect, i, ODA_DRAWENTIRE );
+        rect.top = rect.bottom;
+
+        if ((descr->style & LBS_MULTICOLUMN) && !col_pos)
+        {
+            if (!IS_OWNERDRAW(descr))
+            {
+                /* Clear the bottom of the column */
+                SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) );
+                if (rect.top < descr->height)
+                {
+                    rect.bottom = descr->height;
+                    ExtTextOut32A( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
+                                   &rect, NULL, 0, NULL );
+                }
+            }
+
+            /* Go to the next column */
+            rect.left += descr->column_width;
+            rect.right += descr->column_width;
+            rect.top = 0;
+            col_pos = descr->page_size - 1;
+        }
+        else
+        {
+            col_pos--;
+            if (rect.top >= descr->height) break;
+        }
+    }
+
+    if (!IS_OWNERDRAW(descr))
+    {
+        /* Clear the remainder of the client area */
+        SetBkColor( hdc, GetSysColor( COLOR_WINDOW ) );
+        if (rect.top < descr->height)
+        {
+            rect.bottom = descr->height;
+            ExtTextOut32A( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
+                           &rect, NULL, 0, NULL );
+        }
+        if (rect.right < descr->width)
+        {
+            rect.left   = rect.right;
+            rect.right  = descr->width;
+            rect.top    = 0;
+            rect.bottom = descr->height;
+            ExtTextOut32A( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
+                           &rect, NULL, 0, NULL );
+        }
+    }
+    if (oldFont) SelectObject32( hdc, oldFont );
+    return 0;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_InvalidateItems
+ *
+ * Invalidate all items from a given item. If the specified item is not
+ * visible, nothing happens.
+ */
+static void LISTBOX_InvalidateItems( WND *wnd, LB_DESCR *descr, INT32 index )
+{
+    RECT32 rect;
+
+    if (LISTBOX_GetItemRect( wnd, descr, index, &rect ) == 1)
+    {
+        rect.bottom = descr->height;
+        InvalidateRect32( wnd->hwndSelf, &rect, TRUE );
+        if (descr->style & LBS_MULTICOLUMN)
+        {
+            /* Repaint the other columns */
+            rect.left  = rect.right;
+            rect.right = descr->width;
+            rect.top   = 0;
+            InvalidateRect32( wnd->hwndSelf, &rect, TRUE );
+        }
+    }
+}
+
+
+/***********************************************************************
+ *           LISTBOX_GetItemHeight
+ */
+static LRESULT LISTBOX_GetItemHeight( WND *wnd, LB_DESCR *descr, INT32 index )
+{
+    if (descr->style & LBS_OWNERDRAWVARIABLE)
+    {
+        if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+        return descr->items[index].height;
+    }
+    else return descr->item_height;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_SetItemHeight
+ */
+static LRESULT LISTBOX_SetItemHeight( WND *wnd, LB_DESCR *descr, INT32 index,
+                                      UINT32 height )
+{
+    if (!height) height = 1;
+
+    if (descr->style & LBS_OWNERDRAWVARIABLE)
+    {
+        if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+        dprintf_listbox( stddeb, "Listbox %04x: item %d height = %d\n",
+                         wnd->hwndSelf, index, height );
+        descr->items[index].height = height;
+        LISTBOX_UpdateScroll( wnd, descr );
+        LISTBOX_InvalidateItems( wnd, descr, index );
+    }
+    else if (height != descr->item_height)
+    {
+        dprintf_listbox( stddeb, "Listbox %04x: new height = %d\n",
+                         wnd->hwndSelf, height );
+        descr->item_height = height;
+        LISTBOX_UpdatePage( wnd, descr );
+        LISTBOX_UpdateScroll( wnd, descr );
+        InvalidateRect32( wnd->hwndSelf, 0, TRUE );
+    }
+    return LB_OKAY;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_SetHorizontalPos
+ */
+static void LISTBOX_SetHorizontalPos( WND *wnd, LB_DESCR *descr, INT32 pos )
+{
+    INT32 diff;
+
+    if (pos > descr->horz_extent - descr->width)
+        pos = descr->horz_extent - descr->width;
+    if (pos < 0) pos = 0;
+    if (!(diff = descr->horz_pos - pos)) return;
+    dprintf_listbox( stddeb, "Listbox %04x: new horz pos = %d\n",
+                     wnd->hwndSelf, pos );
+    descr->horz_pos = pos;
+    LISTBOX_UpdateScroll( wnd, descr );
+    if (abs(diff) < descr->width)
+        ScrollWindow32( wnd->hwndSelf, diff, 0, NULL, NULL );
+    else
+        InvalidateRect32( wnd->hwndSelf, NULL, TRUE );
+}
+
+
+/***********************************************************************
+ *           LISTBOX_SetHorizontalExtent
+ */
+static LRESULT LISTBOX_SetHorizontalExtent( WND *wnd, LB_DESCR *descr,
+                                            UINT32 extent )
+{
+    if (!descr->horz_extent || (descr->style & LBS_MULTICOLUMN))
+        return LB_OKAY;
+    if (extent <= 0) extent = 1;
+    if (extent == descr->horz_extent) return LB_OKAY;
+    dprintf_listbox( stddeb, "Listbox %04x: new horz extent = %d\n",
+                     wnd->hwndSelf, extent );
+    descr->horz_extent = extent;
+    if (descr->horz_pos > extent - descr->width)
+        LISTBOX_SetHorizontalPos( wnd, descr, extent - descr->width );
+    else
+        LISTBOX_UpdateScroll( wnd, descr );
+    return LB_OKAY;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_SetColumnWidth
+ */
+static LRESULT LISTBOX_SetColumnWidth( WND *wnd, LB_DESCR *descr, UINT32 width)
+{
+    width += 2;  /* For left and right margin */
+    if (width == descr->column_width) return LB_OKAY;
+    dprintf_listbox( stddeb, "Listbox %04x: new column width = %d\n",
+                     wnd->hwndSelf, width );
+    descr->column_width = width;
+    LISTBOX_UpdatePage( wnd, descr );
+    return LB_OKAY;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_SetFont
+ *
+ * Returns the item height.
+ */
+static INT32 LISTBOX_SetFont( WND *wnd, LB_DESCR *descr, HFONT32 font )
+{
+    HDC32 hdc;
+    HFONT32 oldFont = 0;
+    TEXTMETRIC32A tm;
+
+    descr->font = font;
+
+    if (!(hdc = GetDCEx32( wnd->hwndSelf, 0, DCX_CACHE )))
+    {
+        fprintf( stderr, "LISTBOX_SetFont: unable to get DC\n" );
+        return 16;
+    }
+    if (font) oldFont = SelectObject32( hdc, font );
+    GetTextMetrics32A( hdc, &tm );
+    if (oldFont) SelectObject32( hdc, oldFont );
+    ReleaseDC32( wnd->hwndSelf, hdc );
+    if (!IS_OWNERDRAW(descr))
+        LISTBOX_SetItemHeight( wnd, descr, 0, tm.tmHeight + 2 );
+    return tm.tmHeight + 2;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_MakeItemVisible
+ *
+ * Make sure that a given item is partially or fully visible.
+ */
+static void LISTBOX_MakeItemVisible( WND *wnd, LB_DESCR *descr, INT32 index,
+                                     BOOL32 fully )
+{
+    INT32 top;
+
+    if (index <= descr->top_item) top = index;
+    else if (descr->style & LBS_MULTICOLUMN)
+    {
+        INT32 cols = descr->width;
+        if (!fully) cols += descr->column_width - 1;
+        if (cols >= descr->column_width) cols /= descr->column_width;
+        else cols = 1;
+        if (index < descr->top_item + (descr->page_size * cols)) return;
+        top = index - descr->page_size * (cols - 1);
+    }
+    else if (descr->style & LBS_OWNERDRAWVARIABLE)
+    {
+        INT32 height = fully ? descr->items[index].height : 1;
+        for (top = index; top > descr->top_item; top--)
+            if ((height += descr->items[top-1].height) > descr->height) break;
+    }
+    else
+    {
+        if (index < descr->top_item + descr->page_size) return;
+        if (!fully && (index == descr->top_item + descr->page_size) &&
+            (descr->height > (descr->page_size * descr->item_height))) return;
+        top = index - descr->page_size + 1;
+    }
+    LISTBOX_SetTopItem( wnd, descr, top, TRUE );
+}
+
+
+/***********************************************************************
+ *           LISTBOX_SelectItemRange
+ *
+ * Select a range of items. Should only be used on a MULTIPLESEL listbox.
+ */
+static LRESULT LISTBOX_SelectItemRange( WND *wnd, LB_DESCR *descr, INT32 first,
+                                        INT32 last, BOOL32 on )
+{
+    INT32 i;
+
+    /* A few sanity checks */
+
+    if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+    if (last == -1) last = descr->nb_items - 1;
+    if ((first < 0) || (first >= descr->nb_items)) return LB_ERR;
+    if ((last < 0) || (last >= descr->nb_items)) return LB_ERR;
+    /* selected_item reflects last selected/unselected item on multiple sel */
+    descr->selected_item = last;
+
+    if (on)  /* Turn selection on */
+    {
+        for (i = first; i <= last; i++)
+        {
+            if (descr->items[i].selected) continue;
+            descr->items[i].selected = TRUE;
+            LISTBOX_RepaintItem( wnd, descr, i, ODA_SELECT );
+        }
+    }
+    else  /* Turn selection off */
+    {
+        for (i = first; i <= last; i++)
+        {
+            if (!descr->items[i].selected) continue;
+            descr->items[i].selected = FALSE;
+            LISTBOX_RepaintItem( wnd, descr, i, ODA_SELECT );
+        }
+    }
+    if (descr->style & LBS_NOTIFY)
+        SEND_NOTIFICATION( wnd, descr, LBN_SELCHANGE );
+    return LB_OKAY;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_SetCaretIndex
+ */
+static LRESULT LISTBOX_SetCaretIndex( WND *wnd, LB_DESCR *descr, INT32 index,
+                                      BOOL32 fully_visible )
+{
+    INT32 oldfocus = descr->focus_item;
+
+    if ((index < -1) || (index >= descr->nb_items)) return LB_ERR;
+    if (index == oldfocus) return LB_OKAY;
+    descr->focus_item = index;
+    if ((oldfocus != -1) && descr->caret_on && (GetFocus32() == wnd->hwndSelf))
+        LISTBOX_RepaintItem( wnd, descr, oldfocus, ODA_FOCUS );
+    if (index != -1)
+    {
+        LISTBOX_MakeItemVisible( wnd, descr, index, fully_visible );
+        if (descr->caret_on && (GetFocus32() == wnd->hwndSelf))
+            LISTBOX_RepaintItem( wnd, descr, index, ODA_FOCUS );
+    }
+    return LB_OKAY;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_SetSelection
+ */
+static LRESULT LISTBOX_SetSelection( WND *wnd, LB_DESCR *descr, INT32 index,
+                                     BOOL32 on, BOOL32 send_notify )
+{
+    if ((index < -1) || (index >= descr->nb_items)) return LB_ERR;
+    if (descr->style & LBS_MULTIPLESEL)
+    {
+        if (index == -1)  /* Select all items */
+            return LISTBOX_SelectItemRange( wnd, descr, 0, -1, on );
+        else  /* Only one item */
+            return LISTBOX_SelectItemRange( wnd, descr, index, index, on );
+    }
+    else
+    {
+        INT32 oldsel = descr->selected_item;
+        if (index == oldsel) return LB_OKAY;
+        if (oldsel != -1) descr->items[oldsel].selected = FALSE;
+        if (index != -1) descr->items[index].selected = TRUE;
+        descr->selected_item = index;
+/* FIXME    if (index != -1) LISTBOX_MakeItemVisible( wnd, descr, index );*/
+        if (oldsel != -1) LISTBOX_RepaintItem( wnd, descr, oldsel, ODA_SELECT);
+        if (index != -1) LISTBOX_RepaintItem( wnd, descr, index, ODA_SELECT );
+        if (send_notify) SEND_NOTIFICATION( wnd, descr,
+                               (index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL );
+    }
+    return LB_OKAY;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_MoveCaret
+ *
+ * Change the caret position and extend the selection to the new caret.
+ */
+static void LISTBOX_MoveCaret( WND *wnd, LB_DESCR *descr, INT32 index,
+                               BOOL32 fully_visible )
+{
+    LISTBOX_SetCaretIndex( wnd, descr, index, fully_visible );
+    if (descr->style & LBS_EXTENDEDSEL)
+    {
+        if (descr->anchor_item != -1)
+        {
+            INT32 first = MIN( descr->focus_item, descr->anchor_item );
+            INT32 last  = MAX( descr->focus_item, descr->anchor_item );
+            if (first > 0)
+                LISTBOX_SelectItemRange( wnd, descr, 0, first - 1, FALSE );
+            LISTBOX_SelectItemRange( wnd, descr, first, last, TRUE );
+            LISTBOX_SelectItemRange( wnd, descr, last + 1, -1, FALSE );
+        }
+    }
+    else if (!(descr->style & LBS_MULTIPLESEL) && (descr->selected_item != -1))
+    {
+        /* Set selection to new caret item */
+        LISTBOX_SetSelection( wnd, descr, index, TRUE,
+                              (descr->style & LBS_NOTIFY) != 0 );
+    }
+}
+
+
+/***********************************************************************
+ *           LISTBOX_InsertItem
+ */
+static LRESULT LISTBOX_InsertItem( WND *wnd, LB_DESCR *descr, INT32 index,
+                                   LPSTR str, DWORD data )
+{
+    LB_ITEMDATA *item;
+    INT32 max_items;
+
+    if (index == -1) index = descr->nb_items;
+    else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
+    if (!descr->items) max_items = 0;
+    else max_items = HeapSize( descr->heap, 0, descr->items ) / sizeof(*item);
+    if (descr->nb_items == max_items)
+    {
+        /* We need to grow the array */
+        max_items += LB_ARRAY_GRANULARITY;
+        if (!(item = HeapReAlloc( descr->heap, 0, descr->items,
+                                  max_items * sizeof(LB_ITEMDATA) )))
+        {
+            SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
+            return LB_ERRSPACE;
+        }
+        descr->items = item;
+    }
+
+    /* Insert the item structure */
+
+    item = &descr->items[index];
+    if (index < descr->nb_items)
+        RtlMoveMemory( item + 1, item,
+                       (descr->nb_items - index) * sizeof(LB_ITEMDATA) );
+    item->str      = str;
+    item->data     = data;
+    item->height   = 0;
+    item->selected = FALSE;
+    descr->nb_items++;
+
+    /* Get item height */
+
+    if (descr->style & LBS_OWNERDRAWVARIABLE)
+    {
+        MEASUREITEMSTRUCT32 mis;
+        mis.CtlType    = ODT_LISTBOX;
+        mis.CtlID      = wnd->wIDmenu;
+        mis.itemID     = index;
+        mis.itemData   = descr->items[index].data;
+        mis.itemHeight = descr->item_height;
+        SendMessage32A( descr->owner, WM_MEASUREITEM, wnd->wIDmenu,
+                        (LPARAM)&mis );
+        item->height = mis.itemHeight ? mis.itemHeight : 1;
+        dprintf_listbox( stddeb, "Listbox %04x: measure item %d (%s) = %d\n",
+                         wnd->hwndSelf, index, str ? str : "", item->height );
+    }
+
+    /* Repaint the items */
+
+    LISTBOX_UpdateScroll( wnd, descr );
+    LISTBOX_InvalidateItems( wnd, descr, index );
+
+    /* Move selection and focused item */
+
+    if (index <= descr->selected_item) descr->selected_item++;
+    if (index <= descr->focus_item)
+    {
+        descr->focus_item++;
+        LISTBOX_MoveCaret( wnd, descr, descr->focus_item - 1, FALSE );
+    }
+
+    /* If listbox was empty, set focus to the first item */
+
+    if (descr->nb_items == 1) LISTBOX_SetCaretIndex( wnd, descr, 0, FALSE );
+    return LB_OKAY;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_InsertString
+ */
+static LRESULT LISTBOX_InsertString( WND *wnd, LB_DESCR *descr, INT32 index,
+                                     LPCSTR str )
+{
+    LPSTR new_str = NULL;
+    DWORD data = 0;
+    LRESULT ret;
+
+    if (HAS_STRINGS(descr))
+    {
+        if (!(new_str = HEAP_strdupA( descr->heap, 0, str )))
+        {
+            SEND_NOTIFICATION( wnd, descr, LBN_ERRSPACE );
+            return LB_ERRSPACE;
+        }
+    }
+    else data = (DWORD)str;
+
+    if (index == -1) index = descr->nb_items;
+    if ((ret = LISTBOX_InsertItem( wnd, descr, index, new_str, data )) != 0)
+    {
+        if (new_str) HeapFree( descr->heap, 0, new_str );
+        return ret;
+    }
+
+    dprintf_listbox( stddeb, "Listbox %04x: added item %d '%s'\n",
+                     wnd->hwndSelf, index, HAS_STRINGS(descr) ? new_str : "" );
+    return index;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_DeleteItem
+ *
+ * Delete the content of an item. 'index' must be a valid index.
+ */
+static void LISTBOX_DeleteItem( WND *wnd, LB_DESCR *descr, INT32 index )
+{
+    /* Note: Win 3.1 only sends DELETEITEM on owner-draw items,
+     *       while Win95 sends it for all items with user data.
+     *       It's probably better to send it too often than not
+     *       often enough, so this is what we do here.
+     */
+    if (IS_OWNERDRAW(descr) || descr->items[index].data)
+    {
+        DELETEITEMSTRUCT32 dis;
+        dis.CtlType  = ODT_LISTBOX;
+        dis.CtlID    = wnd->wIDmenu;
+        dis.itemID   = index;
+        dis.hwndItem = wnd->hwndSelf;
+        dis.itemData = descr->items[index].data;
+        SendMessage32A( wnd->hwndSelf, WM_DELETEITEM, wnd->wIDmenu,
+                        (LPARAM)&dis );
+    }
+    if (HAS_STRINGS(descr) && descr->items[index].str)
+        HeapFree( descr->heap, 0, descr->items[index].str );
+}
+
+
+/***********************************************************************
+ *           LISTBOX_RemoveItem
+ *
+ * Remove an item from the listbox and delete its content.
+ */
+static LRESULT LISTBOX_RemoveItem( WND *wnd, LB_DESCR *descr, INT32 index )
+{
+    LB_ITEMDATA *item;
+    INT32 max_items;
+
+    if (index == -1) index = descr->nb_items - 1;
+    else if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+    LISTBOX_DeleteItem( wnd, descr, index );
+
+    /* Remove the item */
+
+    item = &descr->items[index];
+    if (index < descr->nb_items-1)
+        RtlMoveMemory( item, item + 1,
+                       (descr->nb_items - index - 1) * sizeof(LB_ITEMDATA) );
+    descr->nb_items--;
+    if (descr->anchor_item == descr->nb_items) descr->anchor_item--;
+
+    /* Shrink the item array if possible */
+
+    max_items = HeapSize( descr->heap, 0, descr->items ) / sizeof(LB_ITEMDATA);
+    if (descr->nb_items < max_items - 2*LB_ARRAY_GRANULARITY)
+    {
+        max_items -= LB_ARRAY_GRANULARITY;
+        item = HeapReAlloc( descr->heap, 0, descr->items,
+                            max_items * sizeof(LB_ITEMDATA) );
+        if (item) descr->items = item;
+    }
+
+    /* Repaint the items */
+
+    LISTBOX_UpdateScroll( wnd, descr );
+    LISTBOX_InvalidateItems( wnd, descr, index );
+
+    /* Move selection and focused item */
+
+    if (index <= descr->selected_item) descr->selected_item--;
+    if (index <= descr->focus_item)
+    {
+        descr->focus_item--;
+        LISTBOX_MoveCaret( wnd, descr, descr->focus_item + 1, FALSE );
+    }
+    return LB_OKAY;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_ResetContent
+ */
+static void LISTBOX_ResetContent( WND *wnd, LB_DESCR *descr )
+{
+    INT32 i;
+
+    for (i = 0; i < descr->nb_items; i++) LISTBOX_DeleteItem( wnd, descr, i );
+    if (descr->items) HeapFree( descr->heap, 0, descr->items );
+    descr->nb_items      = 0;
+    descr->top_item      = 0;
+    descr->selected_item = -1;
+    descr->focus_item    = 0;
+    descr->anchor_item   = -1;
+    descr->items         = NULL;
+    LISTBOX_UpdateScroll( wnd, descr );
+    InvalidateRect32( wnd->hwndSelf, NULL, TRUE );
+}
+
+
+/***********************************************************************
+ *           LISTBOX_SetCount
+ */
+static LRESULT LISTBOX_SetCount( WND *wnd, LB_DESCR *descr, INT32 count )
+{
+    LRESULT ret;
+
+    if (HAS_STRINGS(descr)) return LB_ERR;
+    /* FIXME: this is far from optimal... */
+    if (count > descr->nb_items)
+    {
+        while (count > descr->nb_items)
+            if ((ret = LISTBOX_InsertString( wnd, descr, -1, 0 )) < 0)
+                return ret;
+    }
+    else if (count < descr->nb_items)
+    {
+        while (count < descr->nb_items)
+            if ((ret = LISTBOX_RemoveItem( wnd, descr, -1 )) < 0)
+                return ret;
+    }
+    return LB_OKAY;
+}
+
+
+/***********************************************************************
+ *           LISTBOX_Directory
+ */
+LRESULT LISTBOX_Directory( WND *wnd, LB_DESCR *descr, UINT32 attrib,
+                           LPCSTR filespec, BOOL32 long_names )
+{
+    char mask[13];
+    const char *ptr;
     char *path, *p;
+    int count, skip, pos;
+    LRESULT ret;
+    DOS_DIRENT entry;
 
-    dprintf_listbox(stddeb, "ListBoxDirectory: '%s' %04x\n", filespec, attrib);
+    /* FIXME: should use FindFirstFile/FindNextFile */
+
     if (!filespec) return LB_ERR;
     if (!(ptr = DOSFS_GetUnixFileName( filespec, FALSE ))) return LB_ERR;
-    path = xstrdup(ptr);
+    path = HEAP_strdupA( SystemHeap, 0, ptr );
     p = strrchr( path, '/' );
     *p++ = '\0';
-    if (!(ptr = DOSFS_ToDosFCBFormat( p )) || 
-        !(temp = SEGPTR_ALLOC( sizeof(char) * 16 )) )
+    if (!(ptr = DOSFS_ToDosFCBFormat( p )))
     {
-        free( path );
+        HeapFree( SystemHeap, 0, path );
         return LB_ERR;
     }
-
     strcpy( mask, ptr );
 
-    dprintf_listbox(stddeb, "ListBoxDirectory: path=%s mask=%s\n", path, mask);
-
-    skip = ret = 0;
+    skip = 0;
+    ret = LB_OKAY;
     attrib &= ~FA_LABEL;
     while ((count = DOSFS_FindNext( path, mask, NULL, 0,
                                     attrib, skip, &entry )) > 0)
     {
+        char buffer[260];
         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;
-            }
+            if (!(attrib & DDL_DIRECTORY) || !strcmp(entry.name,".          "))
+                continue;
+            if (long_names) sprintf( buffer, "[%s]", entry.unixname );
+            else sprintf( buffer, "[%s]", DOSFS_ToDosDTAFormat( entry.name ) );
         }
         else  /* not a directory */
         {
-            if (!(attrib & DDL_EXCLUSIVE) ||
-                ((attrib & (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_ARCHIVE)) ==
+            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;
-            }
+                continue;
+            if (long_names) strcpy( buffer, entry.unixname );
+            else strcpy( buffer, DOSFS_ToDosDTAFormat( entry.name ) );
         }
-
-        dprintf_listbox(stddeb,"\tn - %i, file '%s'\n", count, temp); 
+        if (!long_names) AnsiLower( buffer );
+        pos = LISTBOX_FindFileStrPos( wnd, descr, buffer );
+        if ((ret = LISTBOX_InsertString( wnd, descr, pos, buffer )) < 0)
+            break;
     }
-    if (attrib & DDL_DRIVES)
+
+    if ((ret == LB_OKAY) && (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]++)
+        char buffer[] = "[-a-]";
+        int drive;
+        for (drive = 0; drive < MAX_DOS_DRIVES; drive++, buffer[2]++)
         {
-            if (DRIVE_IsValid(x))
-                if ((ret = ListBoxAddString(lphl, SEGPTR_GET(temp))) == LB_ERR) break;
+            if (!DRIVE_IsValid(drive)) continue;
+            if ((ret = LISTBOX_InsertString( wnd, descr, -1, buffer )) < 0)
+                break;
         }
-	lphl->dwStyle = oldstyle;
     }
 
-    free( path );
-    SEGPTR_FREE( temp );
-
+    HeapFree( SystemHeap, 0, path );
     return ret;
 }
 
-/* ------------------------- dimensions ------------------------- */
 
-int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT16 lprect)
+/***********************************************************************
+ *           LISTBOX_HandleVScroll
+ */
+static LRESULT LISTBOX_HandleVScroll( WND *wnd, LB_DESCR *descr,
+                                      WPARAM32 wParam, LPARAM lParam )
 {
-  LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wIndex);
+    SCROLLINFO info;
 
-  dprintf_listbox(stddeb,"ListBox LB_GETITEMRECT %i %p", wIndex,lpls);
-  if (lpls == NULL)
-  {
-    if (lphl->dwStyle & LBS_OWNERDRAWVARIABLE)
-      return LB_ERR;
-    else 
+    if (descr->style & LBS_MULTICOLUMN) return 0;
+    switch(LOWORD(wParam))
     {
-     GetClientRect16(lphl->hSelf,lprect);
-     lprect->bottom=lphl->StdItemHeight;
-     if (lprect->right<0) lprect->right=0;
+    case SB_LINEUP:
+        LISTBOX_SetTopItem( wnd, descr, descr->top_item - 1, TRUE );
+        break;
+    case SB_LINEDOWN:
+        LISTBOX_SetTopItem( wnd, descr, descr->top_item + 1, TRUE );
+        break;
+    case SB_PAGEUP:
+        LISTBOX_SetTopItem( wnd, descr, descr->top_item -
+                            LISTBOX_GetCurrentPageSize( wnd, descr ), TRUE );
+        break;
+    case SB_PAGEDOWN:
+        LISTBOX_SetTopItem( wnd, descr, descr->top_item +
+                            LISTBOX_GetCurrentPageSize( wnd, descr ), TRUE );
+        break;
+    case SB_THUMBPOSITION:
+        LISTBOX_SetTopItem( wnd, descr, HIWORD(wParam), TRUE );
+        break;
+    case SB_THUMBTRACK:
+        info.cbSize = sizeof(info);
+        info.fMask = SIF_TRACKPOS;
+        GetScrollInfo32( wnd->hwndSelf, SB_VERT, &info );
+        LISTBOX_SetTopItem( wnd, descr, info.nTrackPos, TRUE );
+        break;
+    case SB_TOP:
+        LISTBOX_SetTopItem( wnd, descr, 0, TRUE );
+        break;
+    case SB_BOTTOM:
+        LISTBOX_SetTopItem( wnd, descr, descr->nb_items, TRUE );
+        break;
     }
-  }
-  else
-   *lprect = lpls->itemRect;
-  dprintf_listbox(stddeb," = %d,%d  %d,%d\n", lprect->left,lprect->top,
-                                              lprect->right,lprect->bottom);
-  return 0;
-}
-
-
-int ListBoxSetItemHeight(LPHEADLIST lphl, WORD wIndex, long height)
-{
-  LPLISTSTRUCT lpls;
-
-  if (!(lphl->dwStyle & LBS_OWNERDRAWVARIABLE)) {
-    lphl->StdItemHeight = (short)height;
     return 0;
-  }
-  
-  lpls = ListBoxGetItem(lphl, wIndex);
-  if (lpls == NULL) return LB_ERR;
-  
-  lpls->mis.itemHeight = height;
-  return 0;
-}
-
-/* -------------------------- string search ------------------------ */  
-
-int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar)
-{
-  LPLISTSTRUCT lpls;
-  UINT	       count,first;
-
-  if ((char)wChar < ' ') return LB_ERR;
-  if (!lphl->HasStrings) return LB_ERR;
-
-  lpls = lphl->lpFirst;
-  
-  for (count = 0; lpls != NULL; lpls = lpls->lpNext, count++) {
-    if (tolower(*lpls->itemText) == tolower((char)wChar)) break;
-  }
-  if (lpls == NULL) return LB_ERR;
-  first = count;
-  for(; lpls != NULL; lpls = lpls->lpNext, count++) {
-    if (*lpls->itemText != (char)wChar) 
-      break;
-    if ((short) count > lphl->ItemFocused)
-      return count;
-  }
-  return first;
-}
-
-/***********************************************************************
- *           LBCreate
- */
-static LONG LBCreate(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST   lphl;
-  LONG	       dwStyle = GetWindowLong32A(hwnd,GWL_STYLE);
-  RECT16 rect;
-
-  CreateListBoxStruct(hwnd, ODT_LISTBOX, dwStyle, GetParent16(hwnd));
-  lphl = ListBoxGetStorageHeader(hwnd);
-  dprintf_listbox(stddeb,"ListBox created: lphl = %p dwStyle = %04x:%04x\n", 
-			  lphl, HIWORD(dwStyle), LOWORD(dwStyle));
-
-  GetClientRect16(hwnd,&rect);
-  lphl->ColumnsWidth = rect.right - rect.left;
-
-  if (dwStyle & WS_VSCROLL) 
-    SetScrollRange32(hwnd, SB_VERT, 0, ListMaxFirstVisible(lphl), TRUE);
-  if (dwStyle & WS_HSCROLL) 
-    SetScrollRange32(hwnd, SB_HORZ, 1, 1, TRUE);
-
-  return 0;
 }
 
 
 /***********************************************************************
- *           LBDestroy
+ *           LISTBOX_HandleHScroll
  */
-static LONG LBDestroy(HWND hwnd, WORD wParam, LONG lParam)
+static LRESULT LISTBOX_HandleHScroll( WND *wnd, LB_DESCR *descr,
+                                      WPARAM32 wParam, LPARAM lParam )
 {
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
+    SCROLLINFO info;
+    INT32 page;
 
-  ListBoxResetContent(lphl);
-
-  DestroyListBoxStruct(lphl);
-  dprintf_listbox(stddeb,"ListBox destroyed: lphl = %p\n",lphl);
-  return 0;
-}
-
-
-/***********************************************************************
- *           LBNCCalcSize
- */
-static LONG LBNCCalcSize(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LONG	     ret = DefWindowProc16(hwnd, WM_NCCALCSIZE, wParam, lParam);
-
-  return (GetWindowLong32A(hwnd,GWL_STYLE) & LBS_MULTICOLUMN)? WVR_VREDRAW : ret;
-}
-
-
-/***********************************************************************
- *           LBVScroll
- */
-static LONG LBVScroll(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  int  y;
-
-  dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
-		  wParam, lParam);
-  y = lphl->FirstVisible;
-
-  switch(wParam) {
-  case SB_LINEUP:
-    if (lphl->FirstVisible > 0)
-      lphl->FirstVisible--;
-    break;
-
-  case SB_LINEDOWN:
-    lphl->FirstVisible++;
-    break;
-
-  case SB_PAGEUP:
-    if (lphl->FirstVisible > lphl->ItemsVisible) {
-      lphl->FirstVisible -= lphl->ItemsVisible;
-    } else {
-      lphl->FirstVisible = 0;
+    if (descr->style & LBS_MULTICOLUMN)
+    {
+        switch(LOWORD(wParam))
+        {
+        case SB_LINELEFT:
+            LISTBOX_SetTopItem( wnd, descr, descr->top_item-descr->page_size,
+                                TRUE );
+            break;
+        case SB_LINERIGHT:
+            LISTBOX_SetTopItem( wnd, descr, descr->top_item+descr->page_size,
+                                TRUE );
+            break;
+        case SB_PAGELEFT:
+            page = descr->width / descr->column_width;
+            if (page < 1) page = 1;
+            LISTBOX_SetTopItem( wnd, descr,
+                             descr->top_item - page * descr->page_size, TRUE );
+            break;
+        case SB_PAGERIGHT:
+            page = descr->width / descr->column_width;
+            if (page < 1) page = 1;
+            LISTBOX_SetTopItem( wnd, descr,
+                             descr->top_item + page * descr->page_size, TRUE );
+            break;
+        case SB_THUMBPOSITION:
+            LISTBOX_SetTopItem( wnd, descr, HIWORD(wParam)*descr->page_size,
+                                TRUE );
+            break;
+        case SB_THUMBTRACK:
+            info.cbSize = sizeof(info);
+            info.fMask  = SIF_TRACKPOS;
+            GetScrollInfo32( wnd->hwndSelf, SB_VERT, &info );
+            LISTBOX_SetTopItem( wnd, descr, info.nTrackPos*descr->page_size,
+                                TRUE );
+            break;
+        case SB_LEFT:
+            LISTBOX_SetTopItem( wnd, descr, 0, TRUE );
+            break;
+        case SB_RIGHT:
+            LISTBOX_SetTopItem( wnd, descr, descr->nb_items, TRUE );
+            break;
+        }
     }
-    break;
-
-  case SB_PAGEDOWN:
-    lphl->FirstVisible += lphl->ItemsVisible;
-    break;
-
-  case SB_THUMBTRACK:
-    lphl->FirstVisible = LOWORD(lParam);
-    break;
-  }
-
-  if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
-    lphl->FirstVisible = ListMaxFirstVisible(lphl);
-
-  if (y != lphl->FirstVisible) {
-    SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-    InvalidateRect32( hwnd, NULL, TRUE );
-  }
-  return 0;
+    else if (descr->horz_extent)
+    {
+        switch(LOWORD(wParam))
+        {
+        case SB_LINELEFT:
+            LISTBOX_SetHorizontalPos( wnd, descr, descr->horz_pos - 1 );
+            break;
+        case SB_LINERIGHT:
+            LISTBOX_SetHorizontalPos( wnd, descr, descr->horz_pos + 1 );
+            break;
+        case SB_PAGELEFT:
+            LISTBOX_SetHorizontalPos( wnd, descr,
+                                      descr->horz_pos - descr->width );
+            break;
+        case SB_PAGERIGHT:
+            LISTBOX_SetHorizontalPos( wnd, descr,
+                                      descr->horz_pos + descr->width );
+            break;
+        case SB_THUMBPOSITION:
+            LISTBOX_SetHorizontalPos( wnd, descr, HIWORD(wParam) );
+            break;
+        case SB_THUMBTRACK:
+            info.cbSize = sizeof(info);
+            info.fMask = SIF_TRACKPOS;
+            GetScrollInfo32( wnd->hwndSelf, SB_HORZ, &info );
+            LISTBOX_SetHorizontalPos( wnd, descr, info.nTrackPos );
+            break;
+        case SB_LEFT:
+            LISTBOX_SetHorizontalPos( wnd, descr, 0 );
+            break;
+        case SB_RIGHT:
+            LISTBOX_SetHorizontalPos( wnd, descr,
+                                      descr->horz_extent - descr->width );
+            break;
+        }
+    }
+    return 0;
 }
 
+
 /***********************************************************************
- *           LBHScroll
+ *           LISTBOX_HandleLButtonDown
  */
-static LONG LBHScroll(HWND hwnd, WORD wParam, LONG lParam)
+static LRESULT LISTBOX_HandleLButtonDown( WND *wnd, LB_DESCR *descr,
+                                          WPARAM32 wParam, INT32 x, INT32 y )
 {
-  LPHEADLIST lphl;
-  int        y;
-
-  dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
-		  wParam, lParam);
-  lphl = ListBoxGetStorageHeader(hwnd);
-  y = lphl->FirstVisible;
-  switch(wParam) {
-  case SB_LINEUP:
-    if (lphl->FirstVisible > lphl->ItemsPerColumn) {
-      lphl->FirstVisible -= lphl->ItemsPerColumn;
-    } else {
-      lphl->FirstVisible = 0;
+    INT32 index = LISTBOX_GetItemFromPoint( wnd, descr, x, y );
+    dprintf_listbox( stddeb, "Listbox %04x: lbuttondown %d,%d item %d\n",
+                     wnd->hwndSelf, x, y, index );
+    if (!descr->caret_on && (GetFocus32() == wnd->hwndSelf)) return 0;
+    if (index != -1)
+    {
+        if (descr->style & LBS_EXTENDEDSEL)
+        {
+            if (!(wParam & MK_SHIFT)) descr->anchor_item = index;
+            if (wParam & MK_CONTROL)
+            {
+                LISTBOX_SetCaretIndex( wnd, descr, index, FALSE );
+                LISTBOX_SetSelection( wnd, descr, index,
+                                      !descr->items[index].selected,
+                                      (descr->style & LBS_NOTIFY) != 0 );
+            }
+            else LISTBOX_MoveCaret( wnd, descr, index, FALSE );
+        }
+        else
+        {
+            LISTBOX_MoveCaret( wnd, descr, index, FALSE );
+            LISTBOX_SetSelection( wnd, descr, index,
+                                  (!(descr->style & LBS_MULTIPLESEL) || 
+                                   !descr->items[index].selected),
+                                  (descr->style & LBS_NOTIFY) != 0 );
+        }
     }
-    break;
-  case SB_LINEDOWN:
-    lphl->FirstVisible += lphl->ItemsPerColumn;
-    break;
-  case SB_PAGEUP:
-    if (lphl->ItemsPerColumn != 0) {
-      int lbsub = lphl->ItemsVisible / lphl->ItemsPerColumn * lphl->ItemsPerColumn;
-      if (lphl->FirstVisible > lbsub) {
-	lphl->FirstVisible -= lbsub;
-      } else {
-	lphl->FirstVisible = 0;
-      }
+    SetFocus32( wnd->hwndSelf );
+    SetCapture32( wnd->hwndSelf );
+    if (index != -1)
+    {
+        if (descr->style & LBS_NOTIFY)
+            SendMessage32A( descr->owner, WM_LBTRACKPOINT, index,
+                            MAKELPARAM( x, y ) );
+        if (wnd->dwExStyle & WS_EX_DRAGDETECT)
+        {
+            POINT16 pt = { x, y };
+            if (DragDetect( wnd->hwndSelf, pt ))
+                SendMessage32A( descr->owner, WM_BEGINDRAG, 0, 0 );
+        }
     }
-    break;
-  case SB_PAGEDOWN:
-    if (lphl->ItemsPerColumn != 0)
-      lphl->FirstVisible += lphl->ItemsVisible /
-	lphl->ItemsPerColumn * lphl->ItemsPerColumn;
-    break;
-  case SB_THUMBTRACK:
-    lphl->FirstVisible = lphl->ItemsPerColumn * LOWORD(lParam);
-    break;
-  } 
-  if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
-    lphl->FirstVisible = ListMaxFirstVisible(lphl);
-
-  if (lphl->ItemsPerColumn != 0) {
-    lphl->FirstVisible = lphl->FirstVisible /
-      lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
-    if (y != lphl->FirstVisible) {
-      SetScrollPos32(hwnd, SB_HORZ, lphl->FirstVisible / 
-		   lphl->ItemsPerColumn + 1, TRUE);
-      InvalidateRect32( hwnd, NULL, TRUE );
-    }
-  }
-  return 0;
+    return 0;
 }
 
-/***********************************************************************
- *           LBLButtonDown
- */
-static LONG LBLButtonDown(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  WORD       wRet;
-  int        y,n;
-  RECT16     rectsel;
-
-  SetFocus32(hwnd);
-  SetCapture32(hwnd);
-
-  lphl->PrevFocused = lphl->ItemFocused;
-
-  y = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
-
-  if (y == -1) return 0;
-
-  if (lphl->dwStyle & LBS_NOTIFY && y!= LB_ERR )
-     if( SendMessage16(lphl->hParent, WM_LBTRACKPOINT, y, lParam) )
-         return 0;
-
-
-  switch( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
-   {
-        case LBS_MULTIPLESEL:
-                lphl->ItemFocused = y;
-                wRet = ListBoxGetSel(lphl, y);
-                ListBoxSetSel(lphl, y, !wRet);
-                break;
-        case LBS_EXTENDEDSEL:
-                /* should handle extended mode here and in kbd handler 
-                 */ 
-
-                if ( lphl->PrevFocused != y && y!= LB_ERR)
-                 {
-                   LPLISTSTRUCT lpls = ListBoxGetItem( lphl, lphl->ItemFocused = y );
-                   n = ListBoxSetSel(lphl,-1,FALSE);
-
-                   lpls->itemState = ODS_FOCUS | ODS_SELECTED;
-
-                   if( n > 1 && n != LB_ERR )
-                     InvalidateRect32( hwnd,NULL,TRUE );
-                 }
-                else
-                       return 0;
-
-                break;
-        case 0:
-                if( y!=lphl->ItemFocused )
-                  ListBoxSetCurSel(lphl, y);
-                else
-                  return 0;
-                break;
-        default:
-                fprintf(stdnimp,"Listbox: LBS_MULTIPLESEL and LBS_EXTENDEDSEL are on!\n");
-                return 0;
-   }
-
- /* invalidate changed items */
- if( lphl->dwStyle & LBS_MULTIPLESEL || y!=lphl->PrevFocused )
-   {
-     ListBoxGetItemRect(lphl, y, &rectsel);
-     InvalidateRect16( hwnd, &rectsel, TRUE );
-   }
- if( lphl->PrevFocused!=-1 && y!=lphl->PrevFocused ) 
-   {
-     ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
-     InvalidateRect16( hwnd, &rectsel, TRUE );
-   }
-
-  if (GetWindowLong32A(lphl->hSelf,GWL_EXSTYLE) & WS_EX_DRAGDETECT)
-     if( DragDetect(lphl->hSelf,MAKEPOINT16(lParam)) )
-         SendMessage16(lphl->hParent, WM_BEGINDRAG,0,0L);
-  return 0;
-}
 
 /***********************************************************************
- *           LBLButtonUp
- */
-static LONG LBLButtonUp(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
-  if (GetCapture32() == hwnd) ReleaseCapture();
-
-  if (lphl->PrevFocused != lphl->ItemFocused)
-    ListBoxSendNotification(lphl, LBN_SELCHANGE);
-
-  return 0;
-}
-
-/***********************************************************************
- *           LBRButtonUp
- */
-static LONG LBRButtonUp(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
-  SendMessage16(lphl->hParent, WM_COMMAND, GetWindowWord(hwnd,GWW_ID),
-		MAKELONG(hwnd, LBN_DBLCLK));
-  return 0;
-}
-
-/***********************************************************************
- *           LBMouseMove
- */
-static LONG LBMouseMove(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  int  y,redraw_prev = 0;
-  int  iRet;
-  RECT16 rect, rectsel;   /* XXX Broken */
-
-  dprintf_listbox(stddeb,"LBMouseMove %d %d\n",SLOWORD(lParam),SHIWORD(lParam));
-  if ((wParam & MK_LBUTTON) != 0) {
-    y = SHIWORD(lParam);
-    if (y < LBMM_EDGE) {
-      if (lphl->FirstVisible > 0) {
-	lphl->FirstVisible--;
-	SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-	InvalidateRect32( hwnd, NULL, TRUE );
-	return 0;
-      }
-    }
-    GetClientRect16(hwnd, &rect);
-    if (y >= (rect.bottom-LBMM_EDGE)) {
-      if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
-	lphl->FirstVisible++;
-	SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-	InvalidateRect32( hwnd, NULL, TRUE );
-	return 0;
-      }
-      }
-    if ((y > 0) && (y < (rect.bottom - LBMM_EDGE))) {
-      if ((y < rectsel.top) || (y > rectsel.bottom)) {
-        iRet = ListBoxFindMouse(lphl, LOWORD(lParam), HIWORD(lParam));
-        if (iRet == lphl->ItemFocused || iRet == -1)  {
-	  return 0;
-	}
-	if (lphl->dwStyle & LBS_MULTIPLESEL) {
-          lphl->ItemFocused = iRet;
-	  ListBoxSendNotification(lphl, LBN_SELCHANGE);
-        } else if ( lphl->dwStyle & LBS_EXTENDEDSEL )
-                  {
-                     /* Fixme: extended selection mode */
-                     ListBoxSetSel( lphl, lphl->ItemFocused, 0);
-                     lphl->PrevFocused = lphl->ItemFocused;
-                     lphl->ItemFocused = iRet;
-                     ListBoxSetSel( lphl, iRet, TRUE);
-                     redraw_prev = 1;
-                  }
-               else
-                  {
-                     ListBoxSetCurSel(lphl, (WORD)iRet);
-                     redraw_prev = 1; 
-                  }
-        if( lphl->PrevFocused!=-1 && redraw_prev )
-          {
-            ListBoxGetItemRect(lphl, lphl->PrevFocused, &rectsel);
-            InvalidateRect16( hwnd, &rectsel, TRUE );
-          }
-        ListBoxGetItemRect(lphl, iRet, &rectsel);
-	InvalidateRect16( hwnd, &rectsel, TRUE );
-      }
-    }
-  }
-
-  return 0;
-  }
-
-/***********************************************************************
- *           LBKeyDown
+ *           LISTBOX_HandleTimer
  *
- * Doesn't yet handle properly VK_SHIFT with LB_EXTENDEDSEL
+ * Handle scrolling upon a timer event.
+ * Return TRUE if scrolling should continue.
  */
-static LONG LBKeyDown(HWND hwnd, WORD wParam, LONG lParam)
+static LRESULT LISTBOX_HandleTimer( WND *wnd, LB_DESCR *descr,
+                                    INT32 index, TIMER_DIRECTION dir )
 {
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  WORD       newFocused = 0xFFFF;
-  RECT16     rect;
-
-  ListBoxGetItemRect(lphl,lphl->ItemFocused,&rect);
-  switch(wParam) 
+    switch(dir)
     {
-	case VK_HOME:
-	case VK_END:
-	case VK_LEFT:
-	case VK_RIGHT:
-	case VK_UP:
-	case VK_DOWN:
-	case VK_PRIOR:
-	case VK_NEXT:
-	     if ( lphl->dwStyle & LBS_WANTKEYBOARDINPUT )
-	        {
-		  newFocused = (WORD)(INT)SendMessage16(lphl->hParent,WM_VKEYTOITEM,
-                                                        wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
-	          if ( newFocused == 0xFFFE ) return 0L;
-                }
-	     if ( newFocused == 0xFFFF ) 
-		{
-		  newFocused = lphl->ItemFocused;
-
-		  /* nested switch */
-		  switch(wParam)
-		    {
-                        case VK_HOME:
-                          newFocused = 0;
-                          break;
-                        case VK_END:
-                          newFocused = lphl->ItemsCount - 1;
-                          break;
-                        case VK_LEFT:
-  			  if (lphl->dwStyle & LBS_MULTICOLUMN) {
-                            if (newFocused >= lphl->ItemsPerColumn) {
-                                newFocused -= lphl->ItemsPerColumn;
-                            } else {
-                                newFocused = 0;
-                            }
-                          }
-                          break;
-                        case VK_UP:
-                          if (newFocused > 0) newFocused--;
-                          break;
-                        case VK_RIGHT:
-                          if (lphl->dwStyle & LBS_MULTICOLUMN) 
-                             newFocused += lphl->ItemsPerColumn;
-                          break;
-                        case VK_DOWN:
-                          newFocused++;
-                          break;
-                        case VK_PRIOR:
-                          if (newFocused > lphl->ItemsVisible)
-                              newFocused -= lphl->ItemsVisible;
-			    else  newFocused = 0;
-                            break;
-                        case VK_NEXT:
-                          newFocused += lphl->ItemsVisible;
-                          break;
-                        default:
-                          return 0;
-                    }
-		  /* end of nested switch */
-		}
-	     break;   
-	case VK_SPACE:
-             if (lphl->dwStyle & LBS_MULTIPLESEL)
-                {
-                 WORD wRet = ListBoxGetSel(lphl, lphl->ItemFocused);
-                 ListBoxSetSel(lphl, lphl->ItemFocused, !wRet);
-                 }
-             return 0;
-
-        /* chars are handled in LBChar */
-	default:
-	     return 0;
+    case LB_TIMER_UP:
+        if (descr->top_item) index = descr->top_item - 1;
+        else index = 0;
+        break;
+    case LB_TIMER_LEFT:
+        if (descr->top_item) index -= descr->page_size;
+        break;
+    case LB_TIMER_DOWN:
+        index = descr->top_item + LISTBOX_GetCurrentPageSize( wnd, descr );
+        if (index >= descr->nb_items) index = descr->nb_items - 1;
+        break;
+    case LB_TIMER_RIGHT:
+        if (index + descr->page_size < descr->nb_items)
+            index += descr->page_size;
+        break;
+    case LB_TIMER_NONE:
+        break;
     }
+    if (index == descr->focus_item) return FALSE;
+    LISTBOX_MoveCaret( wnd, descr, index, FALSE );
+    return TRUE;
+}
 
-  /* at this point newFocused is set up */
 
-  if (newFocused >= lphl->ItemsCount)
-    newFocused = lphl->ItemsCount - 1;
-  
-  if (!(lphl->dwStyle & LBS_MULTIPLESEL)) 
-     {
-        ListBoxSetCurSel(lphl, newFocused);
-	ListBoxSendNotification(lphl, LBN_SELCHANGE);
-     }
-
-  lphl->ItemFocused = newFocused;
-
-  if( ListBoxScrollToFocus(lphl) || (lphl->dwStyle & 
-                          (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)) )
-  InvalidateRect32( hwnd, NULL, TRUE );
-  else
+/***********************************************************************
+ *           LISTBOX_HandleSystemTimer
+ *
+ * WM_SYSTIMER handler.
+ */
+static LRESULT LISTBOX_HandleSystemTimer( WND *wnd, LB_DESCR *descr )
+{
+    if (!LISTBOX_HandleTimer( wnd, descr, descr->focus_item, LISTBOX_Timer ))
     {
-	InvalidateRect16( hwnd, &rect, TRUE );
-	if( newFocused < 0x8000 )
-          {
-	   ListBoxGetItemRect(lphl, newFocused, &rect);
-	   InvalidateRect16( hwnd, &rect, TRUE );
-          }
+        KillSystemTimer32( wnd->hwndSelf, LB_TIMER_ID );
+        LISTBOX_Timer = LB_TIMER_NONE;
     }
-
-  SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-
-  return 0;
-}
-
-/***********************************************************************
- *           LBChar
- */
-static LONG LBChar(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  WORD       newFocused = 0xFFFF;
-
-  if ( (lphl->dwStyle & LBS_WANTKEYBOARDINPUT) && !(lphl->HasStrings))
-       {
-        newFocused = (WORD)(INT)SendMessage16(lphl->hParent,WM_CHARTOITEM,
-                                              wParam,MAKELPARAM(lphl->ItemFocused,hwnd));
-        if ( newFocused == 0xFFFE ) return 0L;
-       }
-
-  if (newFocused == 0xFFFF ) 
-  newFocused = ListBoxFindNextMatch(lphl, wParam);
-
-  if (newFocused == (WORD)LB_ERR) return 0;
-
-  if (newFocused >= lphl->ItemsCount)
-    newFocused = lphl->ItemsCount - 1;
-
-  if (!(lphl->dwStyle & LBS_MULTIPLESEL)) 
-     {
-    ListBoxSetCurSel(lphl, newFocused);
-	ListBoxSendNotification(lphl, LBN_SELCHANGE);
-  }
-
-  lphl->ItemFocused = newFocused;
-  ListBoxScrollToFocus(lphl);
-  SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-
-  InvalidateRect32( hwnd, NULL, TRUE );
-
-  return 0;
-}
-
-/***********************************************************************
- *           LBSetRedraw
- */
-static LONG LBSetRedraw(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST  lphl = ListBoxGetStorageHeader(hwnd);
-
-  dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04x w=%04x !\n",
-		  hwnd, wParam);
-  lphl->bRedrawFlag = wParam;
-
-  return 0;
-}
-
-/***********************************************************************
- *           LBSetFont
- */
-static LONG LBSetFont(HWND hwnd, WPARAM16 wParam, LPARAM lParam)
-{
-  LPHEADLIST  lphl = ListBoxGetStorageHeader(hwnd);
-  HDC32 hdc;
-
-  if (wParam == 0)
-    lphl->hFont = GetStockObject32(SYSTEM_FONT);
-  else
-    lphl->hFont = (HFONT16)wParam;
-
-  /* a new font means possible new text height */
-  /* does this mean the height of each entry must be separately changed? */
-  /* or are we guaranteed to get a LBSetFont before the first insert/add? */
-  if ((hdc = GetDC32(0)))
-  {
-      TEXTMETRIC16 tm;
-      GetTextMetrics16( hdc, &tm );
-      lphl->StdItemHeight = tm.tmHeight;
-      dprintf_listbox(stddeb,"LBSetFont:  new font %d with height %d\n",
-                      lphl->hFont, lphl->StdItemHeight);
-      ReleaseDC32( 0, hdc );
-  }
-
-  return 0;
-}
-
-/***********************************************************************
- *           LBPaint
- */
-static LONG LBPaint(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST   lphl = ListBoxGetStorageHeader(hwnd);
-  LPLISTSTRUCT lpls;
-  PAINTSTRUCT16 ps;
-  HBRUSH16 hBrush;
-  HFONT32 hOldFont;
-  HDC16 hdc    = BeginPaint16( hwnd, &ps );
-  DC    *dc    = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
-  RECT16  rect, paintRect, scratchRect;
-  int   i, top, height, maxwidth, ipc;
-
-  top = 0;
-
-  if (!IsWindowVisible(hwnd) || !lphl->bRedrawFlag) {
-    EndPaint16(hwnd, &ps);
     return 0;
-  }
-
-  GetRgnBox16(dc->w.hGCClipRgn,&paintRect);
-  GetClientRect16(hwnd, &rect);
-  IntersectRect16(&paintRect,&rect,&paintRect);
-
-  hOldFont = SelectObject32(hdc, lphl->hFont);
-
-  hBrush = (HBRUSH16)SendMessage32A( lphl->hParent, WM_CTLCOLORLISTBOX,
-                                     (WPARAM32)hdc, (LPARAM)hwnd);
-  if (hBrush == 0) hBrush = GetStockObject32(WHITE_BRUSH);
-
-  FillRect16(hdc, &rect, hBrush);
-
-  maxwidth = rect.right;
-  if (lphl->dwStyle & LBS_MULTICOLUMN) {
-    rect.right = lphl->ColumnsWidth;
-  }
-  lpls = lphl->lpFirst;
-
-  lphl->ItemsVisible = 0;
-  lphl->ItemsPerColumn = ipc = 0;
-
-  for(i = 0; i < lphl->ItemsCount; i++) {
-    if (lpls == NULL) break;
-
-    if (i >= lphl->FirstVisible) {
-      height = lpls->mis.itemHeight;
-
-      if (top > (rect.bottom-height+1)) {
-	if (lphl->dwStyle & LBS_MULTICOLUMN) {
-	  lphl->ItemsPerColumn = MAX(lphl->ItemsPerColumn, ipc);
-	  ipc = 0;
-	  top = 0;
-	  rect.left += lphl->ColumnsWidth;
-	  rect.right += lphl->ColumnsWidth;
-	  if (rect.left > maxwidth) break;
-	} else {
-	  break;
-	}
-      }
-
-      lpls->itemRect.top    = top;
-      lpls->itemRect.bottom = top + height;
-      lpls->itemRect.left   = rect.left;
-      lpls->itemRect.right  = rect.right;
-
-      if( IntersectRect16(&scratchRect,&paintRect,&lpls->itemRect) )
-       {
-        dprintf_listbox(stddeb,"LBPaint: drawing item: %d %d %d %d %d\n",
-                        rect.left,top,rect.right,top+height,lpls->itemState);
-
-        if (lphl->OwnerDrawn && (lphl->ItemFocused == i) && GetFocus32() == hwnd)
-           {
-             ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, 
-                                                      lpls->itemState & ~ODS_FOCUS);
-             ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE, 
-                                                      lpls->itemState & ~ODS_FOCUS);
-             ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_FOCUS, lpls->itemState);
-           }
-        else
-            ListBoxDrawItem (hwnd, lphl, hdc, lpls, &lpls->itemRect, ODA_DRAWENTIRE,
-                                                     lpls->itemState);
-       }
-
-      top += height;
-      lphl->ItemsVisible++;
-      ipc++;
-    }
-
-    lpls = lpls->lpNext;
-  }
-  ListBoxUpdateWindow(hwnd,lphl,FALSE);
-  SelectObject32(hdc,hOldFont);
-  EndPaint16( hwnd, &ps );
-  return 0;
 }
 
+
 /***********************************************************************
- *           LBSetFocus
+ *           LISTBOX_HandleMouseMove
+ *
+ * WM_MOUSEMOVE handler.
  */
-static LONG LBSetFocus(HWND hwnd, WORD wParam, LONG lParam)
+static void LISTBOX_HandleMouseMove( WND *wnd, LB_DESCR *descr,
+                                     INT32 x, INT32 y )
 {
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
+    INT32 index;
+    TIMER_DIRECTION dir;
 
-  dprintf_listbox(stddeb,"ListBox WM_SETFOCUS for %04x\n",hwnd);
-  if(!(lphl->dwStyle & LBS_MULTIPLESEL) )
-       if( lphl->ItemsCount && lphl->ItemFocused != -1)
-         {
-           HDC32        hDC = GetDC32(hwnd);
-           HFONT32 hOldFont = SelectObject32(hDC, lphl->hFont);
-           LPLISTSTRUCT lpls;
-
-           lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
-           lpls->itemState |= ODS_FOCUS;
-
-           ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
-           SelectObject32(hDC, hOldFont);
-           ReleaseDC32(hwnd,hDC);
-         }
-
-  ListBoxSendNotification(lphl, LBN_SETFOCUS);
-
-  return 0;
-}
-
-/***********************************************************************
- *           LBKillFocus
- */
-static LONG LBKillFocus(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
-  dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS for %04x\n",hwnd);
-  if (!(lphl->dwStyle & LBS_MULTIPLESEL))
-     {
-       if( lphl->ItemsCount )
-           if( lphl->ItemFocused != -1 )
-             {
-              HDC32        hDC = GetDC32(hwnd);
-              HFONT32 hOldFont = SelectObject32(hDC, lphl->hFont);
-              LPLISTSTRUCT lpls;
-
-              lpls = ListBoxGetItem(lphl,lphl->ItemFocused);
-              lpls->itemState &= ~ODS_FOCUS;
-
-              ListBoxDrawItem(hwnd,lphl,hDC,lpls,&lpls->itemRect, ODA_FOCUS, lpls->itemState);
-              SelectObject32(hDC, hOldFont);
-              ReleaseDC32(hwnd,hDC);
-             }
-           else
-             dprintf_listbox(stddeb,"LBKillFocus: no focused item!\n");
-     }
-  else
-     InvalidateRect32( hwnd, NULL, TRUE );
-
-  ListBoxSendNotification(lphl, LBN_KILLFOCUS);
-
-  return 0;
-}
-
-/***********************************************************************
- *           LBResetContent
- */
-static LONG LBResetContent(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
-  dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
-  ListBoxResetContent(lphl);
-  ListBoxUpdateWindow(hwnd, lphl, TRUE);
-  return 0;
-}
-
-/***********************************************************************
- *           LBDir
- */
-static LONG LBDir(HWND hwnd, WORD wParam, LONG lParam)
-{
-    LONG ret;
-    LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-    dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
-
-    ret = ListBoxDirectory(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
-    ListBoxUpdateWindow(hwnd, lphl, TRUE);
-    return ret;
-}
-
-/***********************************************************************
- *           LBAddString
- */
-static LONG LBAddString(HWND hwnd, WORD wParam, LONG lParam)
-{
-  WORD  wRet;
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
-  wRet = ListBoxAddString(lphl, (SEGPTR)lParam);
-
-  ListBoxUpdateWindow(hwnd,lphl,TRUE);
-  return wRet;
-}
-
-/***********************************************************************
- *           LBGetText
- */
-static LONG LBGetText(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LONG   wRet;
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
-  dprintf_listbox(stddeb, "LB_GETTEXT  wParam=%d\n",wParam);
-  wRet = ListBoxGetText(lphl, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
-
-  return wRet;
-}
-
-/***********************************************************************
- *           LBInsertString
- */
-static LONG LBInsertString(HWND hwnd, WORD wParam, LONG lParam)
-{
-  WORD  wRet;
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
-  if (lphl->HasStrings)
-    wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)PTR_SEG_TO_LIN(lParam));
-  else
-    wRet = ListBoxInsertString(lphl, wParam, (LPCSTR)lParam);
-
-  ListBoxUpdateWindow(hwnd,lphl,TRUE);
-  return wRet;
-}
-
-/***********************************************************************
- *           LBDeleteString
- */
-static LONG LBDeleteString(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  LONG lRet = ListBoxDeleteString(lphl,wParam);
-  
-  ListBoxUpdateWindow(hwnd,lphl,TRUE);
-  return lRet;
-}
-
-/***********************************************************************
- *           LBFindString
- */
-static LONG LBFindString(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  return lbFindString(lphl, wParam, (SEGPTR)lParam, MATCH_SUBSTR);
-}
-
-/***********************************************************************
- *           LBFindStringExact
- */
-static LONG LBFindStringExact(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  return lbFindString(lphl, wParam, (SEGPTR)lParam, MATCH_EXACT);
-}
-
-/***********************************************************************
- *           LBGetCaretIndex
- */
-static LONG LBGetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  return lphl->ItemFocused;
-}
-
-/***********************************************************************
- *           LBGetCount
- */
-static LONG LBGetCount(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST  lphl;
-
-  lphl = ListBoxGetStorageHeader(hwnd);
-  return lphl->ItemsCount;
-}
-
-/***********************************************************************
- *           LBGetCurSel
- */
-static LONG LBGetCurSel(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST  lphl;
-
-  lphl = ListBoxGetStorageHeader(hwnd);
-  dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %i !\n", 
-		  lphl->ItemFocused);
-  return lphl->ItemFocused;
-}
-
-/***********************************************************************
- *           LBGetHorizontalExtent
- */
-static LONG LBGetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
-{    
-  return 0;
-}
-
-/***********************************************************************
- *           LBGetItemHeight
- */
-static LONG LBGetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  LPLISTSTRUCT lpls = ListBoxGetItem (lphl, wParam);
-  
-  if (lpls == NULL) return LB_ERR;
-  return lpls->mis.itemHeight;
-}
-
-/***********************************************************************
- *           LBGetItemRect
- */
-static LONG LBGetItemRect(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  return ListBoxGetItemRect(lphl, wParam, PTR_SEG_TO_LIN(lParam));
-}
-
-/***********************************************************************
- *           LBGetSel
- */
-static LONG LBGetSel(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  int        iSel = ListBoxGetSel(lphl, wParam);
-
-  dprintf_listbox(stdnimp,"LBGetSel: item %u - %i\n",wParam,iSel);
-
-  return (iSel)? 1 : 0;
-}
-
-/***********************************************************************
- *           LBGetSelCount
- */
-static LONG LBGetSelCount(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  LPLISTSTRUCT lpls;
-  int          cnt = 0;
-  int          items = 0;
-
-  if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)  )) 
-	 return LB_ERR;
-
-  for( lpls = lphl->lpFirst;
-       lpls;
-       lpls = lpls->lpNext )
-	{
-	   items++;
-           if (lpls->itemState ) 
-               cnt++;
-  }
-
-  return cnt;
-}
-
-/***********************************************************************
- *           LBGetSelItems
- */
-static LONG LBGetSelItems(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST  lphl = ListBoxGetStorageHeader(hwnd);
-  LPLISTSTRUCT lpls;
-  int cnt, idx;
-  int *lpItems = PTR_SEG_TO_LIN(lParam);
-
-  if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)  )) 
-        return LB_ERR;
-
-  if (wParam == 0) return 0;
-
-  lpls = lphl->lpFirst;
-  cnt = 0; idx = 0;
-
-  while (lpls != NULL) {
-    if (lpls->itemState > 0) lpItems[cnt++] = idx;
-
-    if (cnt == wParam) break;
-    idx++;
-    lpls = lpls->lpNext;
-  }
-
-  return cnt;
-}
-
-/***********************************************************************
- *           LBGetTextLen
- */
-static LONG LBGetTextLen(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST   lphl = ListBoxGetStorageHeader(hwnd);
-  LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wParam);
-
-  if (lpls == NULL || !lphl->HasStrings) return LB_ERR;
-  return strlen(lpls->itemText);
-}
-
-/***********************************************************************
- *           LBGetDlgCode
- */
-static LONG LBGetDlgCode(HWND hwnd, WORD wParam, LONG lParam)
-{
-  return DLGC_WANTARROWS | DLGC_WANTCHARS;
-}
-
-/***********************************************************************
- *           LBGetTopIndex
- */
-static LONG LBGetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
-  return lphl->FirstVisible;
-}
-
-
-/***********************************************************************
- *           LBSelectString
- */
-static LONG LBSelectString(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  INT  iRet;
-
-  iRet = lbFindString(lphl, wParam, (SEGPTR)lParam, MATCH_SUBSTR);
-
-  if( iRet != LB_ERR)
+    if (descr->style & LBS_MULTICOLUMN)
     {
-      if( lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )
-         ListBoxSetSel(lphl,iRet,TRUE);
-      else
-         ListBoxSetCurSel(lphl,iRet);
+        if (y < 0) y = 0;
+        else if (y >= descr->item_height * descr->page_size)
+            y = descr->item_height * descr->page_size - 1;
 
-      lphl->ItemFocused = iRet;
-      InvalidateRect32( hwnd, 0, TRUE );
+        if (x < 0)
+        {
+            dir = LB_TIMER_LEFT;
+            x = 0;
+        }
+        else if (x >= descr->width)
+        {
+            dir = LB_TIMER_RIGHT;
+            x = descr->width - 1;
+        }
+        else dir = LB_TIMER_NONE;  /* inside */
     }
-  return iRet;
+    else
+    {
+        if (y < 0) dir = LB_TIMER_UP;  /* above */
+        else if (y >= descr->height) dir = LB_TIMER_DOWN;  /* below */
+        else dir = LB_TIMER_NONE;  /* inside */
+    }
+
+    index = LISTBOX_GetItemFromPoint( wnd, descr, x, y );
+    if (index == -1) index = descr->focus_item;
+    if (!LISTBOX_HandleTimer( wnd, descr, index, dir )) dir = LB_TIMER_NONE;
+
+    /* Start/stop the system timer */
+
+    if (dir != LB_TIMER_NONE)
+        SetSystemTimer32( wnd->hwndSelf, LB_TIMER_ID, LB_SCROLL_TIMEOUT, NULL);
+    else if (LISTBOX_Timer != LB_TIMER_NONE)
+        KillSystemTimer32( wnd->hwndSelf, LB_TIMER_ID );
+    LISTBOX_Timer = dir;
 }
 
+
 /***********************************************************************
- *           LBSelItemRange
+ *           LISTBOX_HandleKeyDown
  */
-static LONG LBSelItemRange(HWND hwnd, WORD wParam, LONG lParam)
+static LRESULT LISTBOX_HandleKeyDown( WND *wnd, LB_DESCR *descr,
+                                      WPARAM32 wParam )
 {
-  LPHEADLIST   lphl = ListBoxGetStorageHeader(hwnd);
-  LPLISTSTRUCT lpls;
-  WORD         cnt;
-  WORD         first = LOWORD(lParam);
-  WORD         last = HIWORD(lParam);
-  BOOL         select = wParam;
-
-  if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL)  )) 
-        return LB_ERR;
-
-  if (first >= lphl->ItemsCount ||
-      last >= lphl->ItemsCount) return LB_ERR;
-
-  lpls = lphl->lpFirst;
-  cnt = 0;
-
-  while (lpls != NULL) {
-    if (cnt++ >= first)
-      lpls->itemState = select ? lpls->itemState | ODS_SELECTED : 0;
-
-    if (cnt > last)
-      break;
-
-    lpls = lpls->lpNext;
-  }
-
-  return 0;
+    INT32 caret = -1;
+    if (descr->style & LBS_WANTKEYBOARDINPUT)
+    {
+        caret = SendMessage32A( descr->owner, WM_VKEYTOITEM,
+                                MAKEWPARAM(LOWORD(wParam), descr->focus_item),
+                                wnd->hwndSelf );
+        if (caret == -2) return 0;
+    }
+    if (caret == -1) switch(wParam)
+    {
+    case VK_LEFT:
+        if (descr->style & LBS_MULTICOLUMN)
+        {
+            if (descr->focus_item >= descr->page_size)
+                caret = descr->focus_item - descr->page_size;
+            break;
+        }
+        /* fall through */
+    case VK_UP:
+        caret = descr->focus_item - 1;
+        if (caret < 0) caret = 0;
+        break;
+    case VK_RIGHT:
+        if (descr->style & LBS_MULTICOLUMN)
+        {
+            if (descr->focus_item + descr->page_size < descr->nb_items)
+                caret = descr->focus_item + descr->page_size;
+            break;
+        }
+        /* fall through */
+    case VK_DOWN:
+        caret = descr->focus_item + 1;
+        if (caret >= descr->nb_items) caret = descr->nb_items - 1;
+        break;
+    case VK_PRIOR:
+        if (descr->style & LBS_MULTICOLUMN)
+        {
+            INT32 page = descr->width / descr->column_width;
+            if (page < 1) page = 1;
+            caret = descr->focus_item - (page * descr->page_size) + 1;
+        }
+        else caret = descr->focus_item-LISTBOX_GetCurrentPageSize(wnd,descr)+1;
+        if (caret < 0) caret = 0;
+        break;
+    case VK_NEXT:
+        if (descr->style & LBS_MULTICOLUMN)
+        {
+            INT32 page = descr->width / descr->column_width;
+            if (page < 1) page = 1;
+            caret = descr->focus_item + (page * descr->page_size) - 1;
+        }
+        else caret = descr->focus_item+LISTBOX_GetCurrentPageSize(wnd,descr)-1;
+        if (caret >= descr->nb_items) caret = descr->nb_items - 1;
+        break;
+    case VK_HOME:
+        caret = 0;
+        break;
+    case VK_END:
+        caret = descr->nb_items - 1;
+        break;
+    case VK_SPACE:
+        if (descr->style & LBS_EXTENDEDSEL)
+        {
+            if (!(GetKeyState(VK_SHIFT) & 0x8000))
+                descr->anchor_item = descr->focus_item;
+            LISTBOX_MoveCaret( wnd, descr, descr->focus_item, TRUE );
+        }
+        else if (descr->style & LBS_MULTIPLESEL)
+            LISTBOX_SetSelection( wnd, descr, descr->focus_item,
+                                  !descr->items[descr->focus_item].selected,
+                                  (descr->style & LBS_NOTIFY) != 0 );
+        break;
+    }
+    if (caret >= 0)
+    {
+        if ((descr->style & LBS_EXTENDEDSEL) &&
+            !(GetKeyState( VK_SHIFT ) & 0x8000))
+            descr->anchor_item = caret;
+        LISTBOX_MoveCaret( wnd, descr, caret, TRUE );
+    }
+    return 0;
 }
 
+
 /***********************************************************************
- *           LBSetCaretIndex
+ *           LISTBOX_HandleChar
  */
-static LONG LBSetCaretIndex(HWND hwnd, WORD wParam, LONG lParam)
+static LRESULT LISTBOX_HandleChar( WND *wnd, LB_DESCR *descr,
+                                   WPARAM32 wParam )
 {
-  LPHEADLIST   lphl = ListBoxGetStorageHeader(hwnd);
-  int          i;
+    INT32 index;
+    char str[2] = { wParam & 0xff, '\0' };
 
-  if (!(lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) )) return 0;
-
-  dprintf_listbox(stddeb,"LBSetCaretIndex: hwnd %04x n=%i\n",hwnd,wParam);  
-
-  if (wParam >= lphl->ItemsCount) return LB_ERR;
-
-  lphl->ItemFocused = wParam;
-  i = ListBoxScrollToFocus (lphl);
-
-  SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-  if(i)
-    InvalidateRect32( hwnd, NULL, TRUE );
- 
-  return 1;
+    index = LISTBOX_FindString( wnd, descr, descr->focus_item, str, FALSE );
+    if (index != LB_ERR) LISTBOX_MoveCaret( wnd, descr, index, TRUE );
+    return 0;
 }
 
-/***********************************************************************
- *           LBSetColumnWidth
- */
-static LONG LBSetColumnWidth(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  lphl->ColumnsWidth = wParam;
-  InvalidateRect32( hwnd, NULL, TRUE );
-  return 0;
-}
 
 /***********************************************************************
- *           LBSetHorizontalExtent
+ *           LISTBOX_Create
  */
-static LONG LBSetHorizontalExtent(HWND hwnd, WORD wParam, LONG lParam)
+static BOOL32 LISTBOX_Create( WND *wnd )
 {
-  return 0;
-}
+    LB_DESCR *descr;
+    MEASUREITEMSTRUCT32 mis;
+    RECT32 rect;
 
-/***********************************************************************
- *           LBGetItemData
- */
-static LONG LBGetItemData(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
-  return ListBoxGetItemData(lphl, wParam);
-}
+    if (!(descr = HeapAlloc( GetProcessHeap(), 0, sizeof(*descr) )))
+        return FALSE;
+    if (!(descr->heap = HeapCreate( 0, 0x10000, 0 )))
+    {
+        HeapFree( GetProcessHeap(), 0, descr );
+        return FALSE;
+    }
+    GetClientRect32( wnd->hwndSelf, &rect );
+    descr->owner         = GetParent32( wnd->hwndSelf );
+    descr->style         = wnd->dwStyle;
+    descr->width         = rect.right - rect.left;
+    descr->height        = rect.bottom - rect.top;
+    descr->items         = NULL;
+    descr->nb_items      = 0;
+    descr->top_item      = 0;
+    descr->selected_item = -1;
+    descr->focus_item    = 0;
+    descr->anchor_item   = -1;
+    descr->item_height   = 1;
+    descr->page_size     = 1;
+    descr->column_width  = 150;
+    descr->horz_extent   = (wnd->dwStyle & WS_HSCROLL) ? 1 : 0;
+    descr->horz_pos      = 0;
+    descr->nb_tabs       = 0;
+    descr->tabs          = NULL;
+    descr->caret_on      = TRUE;
+    descr->font          = 0;
+    descr->locale        = 0;  /* FIXME */
 
-/***********************************************************************
- *           LBSetItemData
- */
-static LONG LBSetItemData(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  dprintf_listbox(stddeb, "LB_SETITEMDATA  wParam=%x  lParam=%lx\n", wParam, lParam);
-  return ListBoxSetItemData(lphl, wParam, lParam);
-}
+    *(LB_DESCR **)wnd->wExtra = descr;
 
-/***********************************************************************
- *           LBSetTabStops
- */
-static LONG LBSetTabStops(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST  lphl;
+    if (descr->style & LBS_EXTENDEDSEL) descr->style |= LBS_MULTIPLESEL;
+    if (descr->style & LBS_MULTICOLUMN) descr->style &= ~LBS_OWNERDRAWVARIABLE;
+    if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT;
+    descr->item_height = LISTBOX_SetFont( wnd, descr, 0 );
 
-  lphl = ListBoxGetStorageHeader(hwnd);
+    if (descr->style & LBS_OWNERDRAWFIXED)
+    {
+        mis.CtlType    = ODT_LISTBOX;
+        mis.CtlID      = wnd->wIDmenu;
+        mis.itemID     = 0;
+        mis.itemWidth  = 0;
+        mis.itemData   = 0;
+        mis.itemHeight = descr->item_height;
+        SendMessage32A( descr->owner, WM_MEASUREITEM, wnd->wIDmenu,
+                        (LPARAM)&mis );
+        descr->item_height = mis.itemHeight ? mis.itemHeight : 1;
+    }
 
-  if (lphl->TabStops != NULL) {
-    lphl->iNumStops = 0;
-    free (lphl->TabStops);
-  }
-
-  lphl->TabStops = malloc (wParam * sizeof (short));
-  if (lphl->TabStops) {
-    lphl->iNumStops = wParam;
-    memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short));
     return TRUE;
-  }
-
-  return FALSE;
 }
 
+
 /***********************************************************************
- *           LBSetCurSel
+ *           LISTBOX_Destroy
  */
-static LONG LBSetCurSel(HWND hwnd, WORD wParam, LONG lParam)
+static BOOL32 LISTBOX_Destroy( WND *wnd, LB_DESCR *descr )
 {
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  WORD  wRet;
-
-  dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n", 
-		  wParam);
-
-  wRet = ListBoxSetCurSel(lphl, wParam);
-
-  SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-  InvalidateRect32( hwnd, NULL, TRUE );
-
-  return wRet;
-}
-
-/***********************************************************************
- *           LBSetSel
- */
-static LONG LBSetSel(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  RECT16 rect;
-  int iRet;
-
-  dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
-
-  iRet = ListBoxSetSel(lphl, LOWORD(lParam), wParam);
-
-  if( iRet > 1 ) InvalidateRect32( hwnd, NULL, TRUE );
-  else if( iRet != LB_ERR )
-      {
-        if( lphl->dwStyle & LBS_EXTENDEDSEL &&
-            lphl->ItemFocused != LOWORD(lParam) )
-          {
-            ListBoxGetItemRect(lphl, lphl->ItemFocused , &rect);
-            InvalidateRect16( hwnd, &rect, TRUE );
-            lphl->ItemFocused = LOWORD(lParam);
-          }
-        ListBoxGetItemRect(lphl,LOWORD(lParam),&rect);
-        InvalidateRect16( hwnd, &rect, TRUE );
-      }
-
-  return (iRet == (WORD)LB_ERR)? LB_ERR: 0;
-}
-
-/***********************************************************************
- *           LBSetTopIndex
- */
-static LONG LBSetTopIndex(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
-  dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
-		  wParam);
-  lphl->FirstVisible = wParam;
-  SetScrollPos32(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-
-  InvalidateRect32( hwnd, NULL, TRUE );
-
-  return 0;
-}
-
-/***********************************************************************
- *           LBSetItemHeight
- */
-static LONG LBSetItemHeight(HWND hwnd, WORD wParam, LONG lParam)
-{
-  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-  WORD wRet;
-  
-  dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
-  wRet = ListBoxSetItemHeight(lphl, wParam, lParam);
-  InvalidateRect32( hwnd, NULL, TRUE );
-  return wRet;
-}
-
-/***********************************************************************
- *	     LBPassToParent
- */
-static LRESULT LBPassToParent(HWND hwnd, UINT message, WPARAM16 wParam, LPARAM lParam)
-{
-  WND* ptrWnd = WIN_FindWndPtr(hwnd);  
-
-  if( ptrWnd )
-      if( /* !(ptrWnd->dwExStyle & WS_EX_NOPARENTNOTIFY) && */ 
-          ptrWnd->parent ) 
-          return SendMessage16(ptrWnd->parent->hwndSelf,message,wParam,lParam);
-  return 0;
-}
-
-/***********************************************************************
- *           ListBoxWndProc 
- */
-LRESULT ListBoxWndProc(HWND hwnd, UINT message, WPARAM16 wParam, LPARAM lParam)
-{ 
-    switch (message) {
-     case WM_CREATE: return LBCreate(hwnd, wParam, lParam);
-     case WM_DESTROY: return LBDestroy(hwnd, wParam, lParam);
-     case WM_GETDLGCODE: return LBGetDlgCode(hwnd, wParam, lParam);
-     case WM_VSCROLL: return LBVScroll(hwnd, wParam, lParam);
-     case WM_HSCROLL: return LBHScroll(hwnd, wParam, lParam);
-     case WM_LBUTTONDOWN: return LBLButtonDown(hwnd, wParam, lParam);
-     case WM_LBUTTONUP: return LBLButtonUp(hwnd, wParam, lParam);
-     case WM_RBUTTONUP: return LBRButtonUp(hwnd, wParam, lParam);
-     case WM_LBUTTONDBLCLK: return LBRButtonUp(hwnd, wParam, lParam);
-     case WM_MOUSEMOVE: return LBMouseMove(hwnd, wParam, lParam);
-     case WM_KEYDOWN: return LBKeyDown(hwnd, wParam, lParam);
-     case WM_CHAR: return LBChar(hwnd, wParam, lParam);
-     case WM_SETFONT: return LBSetFont(hwnd, wParam, lParam);
-     case WM_SETREDRAW: return LBSetRedraw(hwnd, wParam, lParam);
-     case WM_PAINT: return LBPaint(hwnd, wParam, lParam);
-     case WM_SETFOCUS: return LBSetFocus(hwnd, wParam, lParam);
-     case WM_KILLFOCUS: return LBKillFocus(hwnd, wParam, lParam);
-     case WM_NCCALCSIZE: return LBNCCalcSize(hwnd, wParam, lParam);
-     case LB_RESETCONTENT16: return LBResetContent(hwnd, wParam, lParam);
-     case LB_DIR16: return LBDir(hwnd, wParam, lParam);
-     case LB_ADDSTRING16: return LBAddString(hwnd, wParam, lParam);
-     case LB_INSERTSTRING16: return LBInsertString(hwnd, wParam, lParam);
-     case LB_DELETESTRING16: return LBDeleteString(hwnd, wParam, lParam);
-     case LB_FINDSTRING16: return LBFindString(hwnd, wParam, lParam);
-     case LB_FINDSTRINGEXACT16: return LBFindStringExact(hwnd, wParam, lParam);
-     case LB_GETCARETINDEX16: return LBGetCaretIndex(hwnd, wParam, lParam);
-     case LB_GETCOUNT16: return LBGetCount(hwnd, wParam, lParam);
-     case LB_GETCURSEL16: return LBGetCurSel(hwnd, wParam, lParam);
-     case LB_GETHORIZONTALEXTENT16: return LBGetHorizontalExtent(hwnd, wParam, lParam);
-     case LB_GETITEMDATA16: return LBGetItemData(hwnd, wParam, lParam);
-     case LB_GETITEMHEIGHT16: return LBGetItemHeight(hwnd, wParam, lParam);
-     case LB_GETITEMRECT16: return LBGetItemRect(hwnd, wParam, lParam);
-     case LB_GETSEL16: return LBGetSel(hwnd, wParam, lParam);
-     case LB_GETSELCOUNT16: return LBGetSelCount(hwnd, wParam, lParam);
-     case LB_GETSELITEMS16: return LBGetSelItems(hwnd, wParam, lParam);
-     case LB_GETTEXT16: return LBGetText(hwnd, wParam, lParam);
-     case LB_GETTEXTLEN16: return LBGetTextLen(hwnd, wParam, lParam);
-     case LB_GETTOPINDEX16: return LBGetTopIndex(hwnd, wParam, lParam);
-     case LB_SELECTSTRING16: return LBSelectString(hwnd, wParam, lParam);
-     case LB_SELITEMRANGE16: return LBSelItemRange(hwnd, wParam, lParam);
-     case LB_SETCARETINDEX16: return LBSetCaretIndex(hwnd, wParam, lParam);
-     case LB_SETCOLUMNWIDTH16: return LBSetColumnWidth(hwnd, wParam, lParam);
-     case LB_SETHORIZONTALEXTENT16: return LBSetHorizontalExtent(hwnd, wParam, lParam);
-     case LB_SETITEMDATA16: return LBSetItemData(hwnd, wParam, lParam);
-     case LB_SETTABSTOPS16: return LBSetTabStops(hwnd, wParam, lParam);
-     case LB_SETCURSEL16: return LBSetCurSel(hwnd, wParam, lParam);
-     case LB_SETSEL16: return LBSetSel(hwnd, wParam, lParam);
-     case LB_SETTOPINDEX16: return LBSetTopIndex(hwnd, wParam, lParam);
-     case LB_SETITEMHEIGHT16: return LBSetItemHeight(hwnd, wParam, lParam);
-
-     case WM_DROPFILES: return LBPassToParent(hwnd, message, wParam, lParam);
-
-     /* these will have to be implemented for proper LBS_EXTENDEDSEL -
-      *
-      * anchor item is an item that with caret (focused) item defines a 
-      * range of currently selected items when listbox is in the extended 
-      * selection mode.
-      */
-     case LB_SETANCHORINDEX16: return LB_SETANCHORINDEX16; /* that's what Windows returns */
-     case LB_GETANCHORINDEX16: return 0;
-
-	case WM_DROPOBJECT:
-	case WM_QUERYDROPOBJECT:
-	case WM_DRAGSELECT:
-	case WM_DRAGMOVE:
-	        {
-		 LPDRAGINFO lpDragInfo = (LPDRAGINFO) PTR_SEG_TO_LIN((SEGPTR)lParam);
-		 LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
-
-		 lpDragInfo->l = ListBoxFindMouse(lphl,lpDragInfo->pt.x,
-						       lpDragInfo->pt.y);
-	        
-		 return LBPassToParent(hwnd, message, wParam, lParam);
-		}
-    }
-    
-    return DefWindowProc16(hwnd, message, wParam, lParam);
-}
-
-
-/**********************************************************************
- *	    DlgDirList    (USER.100)
- */
-INT DlgDirList( HWND hDlg, SEGPTR spec, INT idLBox, INT idStatic, UINT attrib )
-{
-    char *filespec = (char *)PTR_SEG_TO_LIN( spec );
-    int drive;
-    HWND hwnd;
-
-#define SENDMSG(msg,wparam,lparam) \
-    ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
-                             : SendMessage16( hwnd, msg, wparam, lparam ))
-
-    dprintf_listbox( stddeb, "DlgDirList: %04x '%s' %d %d %04x\n",
-                     hDlg, filespec ? filespec : "NULL",
-                     idLBox, idStatic, attrib );
-
-    if (filespec && filespec[0] && (filespec[1] == ':'))
-    {
-        drive = toupper( filespec[0] ) - 'A';
-        filespec += 2;
-        if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
-    }
-    else drive = DRIVE_GetCurrentDrive();
-
-    if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
-    {
-        char mask[20];
-        
-        if (!filespec || !filespec[0]) strcpy( mask, "*.*" );
-        else
-        {
-            /* If the path exists and is a directory, chdir to it */
-            if (DRIVE_Chdir( drive, filespec )) strcpy( mask, "*.*" );
-            else
-            {
-                char *p, *p2;
-                p = filespec;
-                if ((p2 = strrchr( p, '\\' ))) p = p2 + 1;
-                if ((p2 = strrchr( p, '/' ))) p = p2 + 1;
-                lstrcpyn32A( mask, p, sizeof(mask) );
-                if (p != filespec)
-                {
-                    p[-1] = '\0';
-                    if (!DRIVE_Chdir( drive, filespec )) return FALSE;
-                }
-            }
-        }
-        
-        strcpy( (char *)PTR_SEG_TO_LIN(spec), mask );
-
-        dprintf_listbox(stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
-                        'A' + drive, DRIVE_GetDosCwd(drive), mask);
-        
-        SENDMSG( LB_RESETCONTENT16, 0, 0 );
-        if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE))
-        {
-            char *temp;
-            if (SENDMSG( LB_DIR16, attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
-                         (LPARAM)spec ) == LB_ERR) return FALSE;
-            if (!(temp = SEGPTR_ALLOC( 4*sizeof(char) ))) return FALSE;
-            strcpy( temp, "*.*" );
-            /* FIXME: this won't work with PostMessage(), as temp will */
-            /* have been freed by the time we do a DispatchMessage().  */
-            if (SENDMSG( LB_DIR16, (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
-                         (LPARAM)SEGPTR_GET(temp) ) == LB_ERR)
-            {
-                SEGPTR_FREE(temp);
-                return FALSE;
-            }
-            SEGPTR_FREE(temp);
-        }
-        else
-        {
-            if (SENDMSG( LB_DIR16, attrib, (LPARAM)spec) == LB_ERR) return FALSE;
-        }
-    }
-
-    if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
-    {
-        char temp[512];
-        int drive = DRIVE_GetCurrentDrive();
-        strcpy( temp, "A:\\" );
-        temp[0] += drive;
-        lstrcpyn32A( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 );
-        AnsiLower( temp );
-        /* Can't use PostMessage() here, because the string is on the stack */
-        SetDlgItemText32A( hDlg, idStatic, temp );
-    }
+    LISTBOX_ResetContent( wnd, descr );
+    HeapDestroy( descr->heap );
+    HeapFree( GetProcessHeap(), 0, descr );
+    *(LB_DESCR **)wnd->wExtra = NULL;
     return TRUE;
-#undef SENDMSG
+}
+
+
+/***********************************************************************
+ *           ListBoxWndProc
+ */
+LRESULT ListBoxWndProc(HWND32 hwnd, UINT32 msg, WPARAM32 wParam, LPARAM lParam)
+{
+    LRESULT ret;
+    LB_DESCR *descr;
+    WND *wnd = WIN_FindWndPtr( hwnd );
+
+    if (!wnd) return 0;
+    if (!(descr = *(LB_DESCR **)wnd->wExtra))
+    {
+        if (msg == WM_CREATE)
+        {
+            if (!LISTBOX_Create( wnd )) return -1;
+            dprintf_listbox( stddeb, "Listbox: creating wnd=%04x descr=%p\n",
+                             hwnd, *(LB_DESCR **)wnd->wExtra );
+            return 0;
+        }
+        /* Ignore all other messages before we get a WM_CREATE */
+        return DefWindowProc32A( hwnd, msg, wParam, lParam );
+    }
+
+    dprintf_listbox( stddeb, "Listbox %04x: msg %s wp %08x lp %08lx\n",
+                     wnd->hwndSelf, SPY_GetMsgName(msg), wParam, lParam );
+    switch(msg)
+    {
+    case LB_RESETCONTENT16:
+    case LB_RESETCONTENT32:
+        LISTBOX_ResetContent( wnd, descr );
+        return 0;
+
+    case LB_ADDSTRING16:
+        if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+        /* fall through */
+    case LB_ADDSTRING32:
+        wParam = LISTBOX_FindStringPos( wnd, descr, (LPCSTR)lParam, FALSE );
+        return LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam );
+
+    case LB_INSERTSTRING16:
+        if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+        wParam = (INT32)(INT16)wParam;
+        /* fall through */
+    case LB_INSERTSTRING32:
+        return LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam );
+
+    case LB_ADDFILE16:
+        if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+        /* fall through */
+    case LB_ADDFILE32:
+        wParam = LISTBOX_FindFileStrPos( wnd, descr, (LPCSTR)lParam );
+        return LISTBOX_InsertString( wnd, descr, wParam, (LPCSTR)lParam );
+
+    case LB_DELETESTRING16:
+    case LB_DELETESTRING32:
+        return LISTBOX_RemoveItem( wnd, descr, wParam );
+
+    case LB_GETITEMDATA16:
+    case LB_GETITEMDATA32:
+        if (((INT32)wParam < 0) || ((INT32)wParam >= descr->nb_items))
+            return LB_ERR;
+        return descr->items[wParam].data;
+
+    case LB_SETITEMDATA16:
+    case LB_SETITEMDATA32:
+        if (((INT32)wParam < 0) || ((INT32)wParam >= descr->nb_items))
+            return LB_ERR;
+        descr->items[wParam].data = (DWORD)lParam;
+        return LB_OKAY;
+
+    case LB_GETCOUNT16:
+    case LB_GETCOUNT32:
+        return descr->nb_items;
+
+    case LB_GETTEXT16:
+        lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+        /* fall through */
+    case LB_GETTEXT32:
+        return LISTBOX_GetText( wnd, descr, wParam, (LPSTR)lParam );
+
+    case LB_GETTEXTLEN16:
+        /* fall through */
+    case LB_GETTEXTLEN32:
+        if (wParam >= descr->nb_items) return LB_ERR;
+        return (HAS_STRINGS(descr) ? strlen(descr->items[wParam].str)
+                                   : sizeof(DWORD));
+
+    case LB_GETCURSEL16:
+    case LB_GETCURSEL32:
+        return descr->selected_item;
+
+    case LB_GETTOPINDEX16:
+    case LB_GETTOPINDEX32:
+        return descr->top_item;
+
+    case LB_GETITEMHEIGHT16:
+    case LB_GETITEMHEIGHT32:
+        return LISTBOX_GetItemHeight( wnd, descr, wParam );
+
+    case LB_SETITEMHEIGHT16:
+        lParam = LOWORD(lParam);
+        /* fall through */
+    case LB_SETITEMHEIGHT32:
+        return LISTBOX_SetItemHeight( wnd, descr, wParam, lParam );
+
+    case LB_ITEMFROMPOINT32:
+        {
+            POINT32 pt = { LOWORD(lParam), HIWORD(lParam) };
+            RECT32 rect = { 0, 0, descr->width, descr->height };
+            return MAKELONG( LISTBOX_GetItemFromPoint(wnd, descr, pt.x, pt.y),
+                             PtInRect32( &rect, pt ) );
+        }
+
+    case LB_SETCARETINDEX16:
+    case LB_SETCARETINDEX32:
+        return LISTBOX_SetCaretIndex( wnd, descr, wParam, !lParam );
+
+    case LB_GETCARETINDEX16:
+    case LB_GETCARETINDEX32:
+        return descr->focus_item;
+
+    case LB_SETTOPINDEX16:
+    case LB_SETTOPINDEX32:
+        return LISTBOX_SetTopItem( wnd, descr, wParam, TRUE );
+
+    case LB_SETCOLUMNWIDTH16:
+    case LB_SETCOLUMNWIDTH32:
+        return LISTBOX_SetColumnWidth( wnd, descr, wParam );
+
+    case LB_GETITEMRECT16:
+        {
+            RECT32 rect;
+            ret = LISTBOX_GetItemRect( wnd, descr, (INT16)wParam, &rect );
+            CONV_RECT32TO16( &rect, (RECT16 *)PTR_SEG_TO_LIN(lParam) );
+        }
+        return ret;
+
+    case LB_GETITEMRECT32:
+        return LISTBOX_GetItemRect( wnd, descr, wParam, (RECT32 *)lParam );
+
+    case LB_FINDSTRING16:
+        wParam = (INT32)(INT16)wParam;
+        if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+        /* fall through */
+    case LB_FINDSTRING32:
+        return LISTBOX_FindString( wnd, descr, wParam, (LPCSTR)lParam, FALSE );
+
+    case LB_FINDSTRINGEXACT16:
+        wParam = (INT32)(INT16)wParam;
+        if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+        /* fall through */
+    case LB_FINDSTRINGEXACT32:
+        return LISTBOX_FindString( wnd, descr, wParam, (LPCSTR)lParam, TRUE );
+
+    case LB_SELECTSTRING16:
+        wParam = (INT32)(INT16)wParam;
+        if (HAS_STRINGS(descr)) lParam = (LPARAM)PTR_SEG_TO_LIN(lParam);
+        /* fall through */
+    case LB_SELECTSTRING32:
+        {
+            INT32 index = LISTBOX_FindString( wnd, descr, wParam,
+                                              (LPCSTR)lParam, FALSE );
+            if (index == LB_ERR) return LB_ERR;
+            LISTBOX_SetSelection( wnd, descr, index, TRUE,
+                                  (descr->style & LBS_NOTIFY) != 0 );
+            return index;
+        }
+
+    case LB_GETSEL16:
+        wParam = (INT32)(INT16)wParam;
+        /* fall through */
+    case LB_GETSEL32:
+        if (((INT32)wParam < 0) || ((INT32)wParam >= descr->nb_items))
+            return LB_ERR;
+        return descr->items[wParam].selected;
+
+    case LB_SETSEL16:
+        lParam = (INT32)(INT16)lParam;
+        /* fall through */
+    case LB_SETSEL32:
+        return LISTBOX_SetSelection( wnd, descr, lParam, wParam,
+                                     (descr->style & LBS_NOTIFY) != 0 );
+
+    case LB_SETCURSEL16:
+        wParam = (INT32)(INT16)wParam;
+        /* fall through */
+    case LB_SETCURSEL32:
+        return LISTBOX_SetSelection( wnd, descr, wParam, TRUE, FALSE );
+
+    case LB_GETSELCOUNT16:
+    case LB_GETSELCOUNT32:
+        return LISTBOX_GetSelCount( wnd, descr );
+
+    case LB_GETSELITEMS16:
+        return LISTBOX_GetSelItems16( wnd, descr, wParam,
+                                      (LPINT16)PTR_SEG_TO_LIN(lParam) );
+
+    case LB_GETSELITEMS32:
+        return LISTBOX_GetSelItems32( wnd, descr, wParam, (LPINT32)lParam );
+
+    case LB_SELITEMRANGE16:
+    case LB_SELITEMRANGE32:
+        return LISTBOX_SelectItemRange( wnd, descr, LOWORD(lParam),
+                                        HIWORD(lParam), wParam );
+
+    case LB_SELITEMRANGEEX16:
+    case LB_SELITEMRANGEEX32:
+        if ((INT32)lParam >= (INT32)wParam)
+            return LISTBOX_SelectItemRange( wnd, descr, wParam, lParam, TRUE );
+        else
+            return LISTBOX_SelectItemRange( wnd, descr, lParam, wParam, FALSE);
+
+    case LB_GETHORIZONTALEXTENT16:
+    case LB_GETHORIZONTALEXTENT32:
+        return descr->horz_extent;
+
+    case LB_SETHORIZONTALEXTENT16:
+    case LB_SETHORIZONTALEXTENT32:
+        return LISTBOX_SetHorizontalExtent( wnd, descr, wParam );
+
+    case LB_GETANCHORINDEX16:
+    case LB_GETANCHORINDEX32:
+        return descr->anchor_item;
+
+    case LB_SETANCHORINDEX16:
+        wParam = (INT32)(INT16)wParam;
+        /* fall through */
+    case LB_SETANCHORINDEX32:
+        if (((INT32)wParam < -1) || ((INT32)wParam >= descr->nb_items))
+            return LB_ERR;
+        descr->anchor_item = (INT32)wParam;
+        return LB_OKAY;
+
+    case LB_DIR16:
+        return LISTBOX_Directory( wnd, descr, wParam,
+                                  (LPCSTR)PTR_SEG_TO_LIN(lParam), FALSE );
+
+    case LB_DIR32:
+        return LISTBOX_Directory( wnd, descr, wParam, (LPCSTR)lParam, TRUE );
+
+    case LB_GETLOCALE32:
+        return descr->locale;
+
+    case LB_SETLOCALE32:
+        descr->locale = (LCID)wParam;  /* FIXME: should check for valid lcid */
+        return LB_OKAY;
+
+    case LB_INITSTORAGE32:
+        return LISTBOX_InitStorage( wnd, descr, wParam, (DWORD)lParam );
+
+    case LB_SETCOUNT32:
+        return LISTBOX_SetCount( wnd, descr, (INT32)wParam );
+
+    case LB_SETTABSTOPS16:
+        return LISTBOX_SetTabStops( wnd, descr, (INT32)(INT16)wParam,
+                                    (LPINT32)PTR_SEG_TO_LIN(lParam), TRUE );
+
+    case LB_SETTABSTOPS32:
+        return LISTBOX_SetTabStops( wnd, descr, wParam,
+                                    (LPINT32)lParam, FALSE );
+
+    case LB_CARETON16:
+    case LB_CARETON32:
+        if (descr->caret_on) return LB_OKAY;
+        descr->caret_on = TRUE;
+        if ((descr->focus_item != -1) && (GetFocus32() == wnd->hwndSelf))
+            LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
+        return LB_OKAY;
+
+    case LB_CARETOFF16:
+    case LB_CARETOFF32:
+        if (!descr->caret_on) return LB_OKAY;
+        descr->caret_on = FALSE;
+        if ((descr->focus_item != -1) && (GetFocus32() == wnd->hwndSelf))
+            LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
+        return LB_OKAY;
+
+    case WM_DESTROY:
+        return LISTBOX_Destroy( wnd, descr );
+
+    case WM_ENABLE:
+        InvalidateRect32( hwnd, NULL, TRUE );
+        return 0;
+
+    case WM_SETREDRAW:
+        LISTBOX_SetRedraw( wnd, descr, wParam != 0 );
+        return 0;
+
+    case WM_GETDLGCODE:
+        return DLGC_WANTARROWS | DLGC_WANTCHARS;
+
+    case WM_PAINT:
+        {
+            PAINTSTRUCT32 ps;
+            HDC32 hdc = BeginPaint32( hwnd, &ps );
+            ret = LISTBOX_Paint( wnd, descr, hdc );
+            EndPaint32( hwnd, &ps );
+        }
+        return ret;
+
+    case WM_SIZE:
+        LISTBOX_UpdateSize( wnd, descr );
+        return 0;
+
+    case WM_GETFONT:
+        return descr->font;
+
+    case WM_SETFONT:
+        LISTBOX_SetFont( wnd, descr, (HFONT32)wParam );
+        if (lParam) InvalidateRect32( wnd->hwndSelf, 0, TRUE );
+        return 0;
+
+    case WM_SETFOCUS:
+        descr->caret_on = TRUE;
+        if (descr->focus_item != -1)
+            LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
+        SEND_NOTIFICATION( wnd, descr, LBN_SETFOCUS );
+        return 0;
+
+    case WM_KILLFOCUS:
+        if ((descr->focus_item != -1) && descr->caret_on)
+            LISTBOX_RepaintItem( wnd, descr, descr->focus_item, ODA_FOCUS );
+        SEND_NOTIFICATION( wnd, descr, LBN_KILLFOCUS );
+        return 0;
+
+    case WM_HSCROLL:
+        return LISTBOX_HandleHScroll( wnd, descr, wParam, lParam );
+
+    case WM_VSCROLL:
+        return LISTBOX_HandleVScroll( wnd, descr, wParam, lParam );
+
+    case WM_LBUTTONDOWN:
+        return LISTBOX_HandleLButtonDown( wnd, descr, wParam,
+                                          (INT16)LOWORD(lParam),
+                                          (INT16)HIWORD(lParam) );
+
+    case WM_LBUTTONDBLCLK:
+        if (descr->style & LBS_NOTIFY)
+            SEND_NOTIFICATION( wnd, descr, LBN_DBLCLK );
+        return 0;
+
+    case WM_MOUSEMOVE:
+        if (GetCapture32() == hwnd)
+            LISTBOX_HandleMouseMove( wnd, descr, (INT16)LOWORD(lParam),
+                                     (INT16)HIWORD(lParam) );
+        return 0;
+
+    case WM_LBUTTONUP:
+        if (LISTBOX_Timer != LB_TIMER_NONE)
+            KillSystemTimer32( hwnd, LB_TIMER_ID );
+        LISTBOX_Timer = LB_TIMER_NONE;
+        if (GetCapture32() == hwnd) ReleaseCapture();
+        return 0;
+
+    case WM_KEYDOWN:
+        return LISTBOX_HandleKeyDown( wnd, descr, wParam );
+
+    case WM_CHAR:
+        return LISTBOX_HandleChar( wnd, descr, wParam );
+
+    case WM_SYSTIMER:
+        return LISTBOX_HandleSystemTimer( wnd, descr );
+
+    case WM_ERASEBKGND:
+        if (IS_OWNERDRAW(descr))
+        {
+            RECT32 rect = { 0, 0, descr->width, descr->height };
+            HBRUSH32 hbrush = SendMessage32A( descr->owner, WM_CTLCOLORLISTBOX,
+                                              wParam, (LPARAM)wnd->hwndSelf );
+            if (hbrush) FillRect32( (HDC32)wParam, &rect, hbrush );
+        }
+        return 1;
+
+    case WM_DROPFILES:
+        return SendMessage32A( descr->owner, msg, wParam, lParam );
+
+    case WM_DROPOBJECT:
+    case WM_QUERYDROPOBJECT:
+    case WM_DRAGSELECT:
+    case WM_DRAGMOVE:
+    {
+        LPDRAGINFO dragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN( (SEGPTR)lParam );
+        dragInfo->l = LISTBOX_GetItemFromPoint( wnd, descr, dragInfo->pt.x,
+                                                dragInfo->pt.y );
+        return SendMessage32A( descr->owner, msg, wParam, lParam );
+    }
+
+    default:
+        if ((msg >= WM_USER) && (msg < 0xc000))
+            fprintf(stderr,"Listbox %04x: unknown msg %04x wp %08x lp %08lx\n",
+                    hwnd, msg, wParam, lParam );
+        return DefWindowProc32A( hwnd, msg, wParam, lParam );
+    }
+    return 0;
 }
diff --git a/controls/menu.c b/controls/menu.c
index 59cee28..fd5bb8a 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -84,8 +84,8 @@
 #define NO_SELECTED_ITEM  0xffff
 #define SYSMENU_SELECTED  0xfffe  /* Only valid on menu-bars */
 
-#define IS_STRING_ITEM(flags) (!((flags) & (MF_BITMAP | MF_OWNERDRAW | \
-			     MF_MENUBARBREAK | MF_MENUBREAK | MF_SEPARATOR)))
+#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);
@@ -1923,8 +1923,9 @@
                          INT32 nReserved, HWND32 hWnd, const RECT32 *lpRect )
 {
     RECT16 r;
-    CONV_RECT32TO16( lpRect, &r );
-    return TrackPopupMenu16( hMenu, wFlags, x, y, nReserved, hWnd, &r );
+    if (lpRect)
+   	 CONV_RECT32TO16( lpRect, &r );
+    return TrackPopupMenu16(hMenu,wFlags,x,y,nReserved,hWnd,lpRect?&r:NULL);
 }
 
 
diff --git a/controls/oldlbox.c b/controls/oldlbox.c
new file mode 100644
index 0000000..d7a7547
--- /dev/null
+++ b/controls/oldlbox.c
@@ -0,0 +1,843 @@
+/*
+ * Listbox controls
+ * 
+ * Copyright  Martin Ayotte, 1993
+ *            Constantine Sapuntzakis, 1995
+ * 	      Alex Korobka, 1995, 1996 
+ * 
+ */
+
+ /*
+  * FIXME: 
+  * - proper scrolling for multicolumn style
+  * - anchor and caret for LBS_EXTENDEDSEL
+  * - proper selection with keyboard
+  * - how to handle (LBS_EXTENDEDSEL | LBS_MULTIPLESEL) style
+  * - support for LBS_NOINTEGRALHEIGHT and LBS_OWNERDRAWVARIABLE styles
+  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "windows.h"
+#include "win.h"
+#include "gdi.h"
+#include "msdos.h"
+#include "listbox.h"
+#include "dos_fs.h"
+#include "drive.h"
+#include "file.h"
+#include "heap.h"
+#include "stddebug.h"
+#include "debug.h"
+#include "xmalloc.h"
+
+#define LIST_HEAP_ALLOC(lphl,f,size) \
+    LOCAL_Alloc( lphl->HeapSel, LMEM_FIXED, (size) )
+#define LIST_HEAP_FREE(lphl,handle) \
+    LOCAL_Free( lphl->HeapSel, (handle) )
+#define LIST_HEAP_ADDR(lphl,handle)  \
+    ((handle) ? PTR_SEG_OFF_TO_LIN(lphl->HeapSel, (handle)) : NULL)
+
+#define LIST_HEAP_SIZE 0x10000
+
+#define LBMM_EDGE   4    /* distance inside box which is same as moving mouse
+			    outside box, to trigger scrolling of LB */
+
+#define MATCH_SUBSTR            2
+#define MATCH_EXACT             1
+#define MATCH_NEAREST           0
+
+static void ListBoxInitialize(LPHEADLIST lphl)
+{
+  lphl->lpFirst        = NULL;
+  lphl->ItemsCount     = 0;
+  lphl->ItemsVisible   = 0;
+  lphl->FirstVisible   = 0;
+  lphl->ColumnsVisible = 1;
+  lphl->ItemsPerColumn = 0;
+  lphl->ItemFocused    = -1;
+  lphl->PrevFocused    = -1;
+}
+
+void CreateListBoxStruct(HWND hwnd, WORD CtlType, LONG styles, HWND parent)
+{
+  LPHEADLIST lphl;
+  HDC32         hdc;
+
+  lphl = (LPHEADLIST)xmalloc(sizeof(HEADLIST));
+  SetWindowLong32A(hwnd, 0, (LONG)lphl);
+  ListBoxInitialize(lphl);
+  lphl->DrawCtlType    = CtlType;
+  lphl->CtlID          = GetWindowWord(hwnd,GWW_ID);
+  lphl->bRedrawFlag    = TRUE;
+  lphl->iNumStops      = 0;
+  lphl->TabStops       = NULL;
+  lphl->hFont          = GetStockObject32(SYSTEM_FONT);
+  lphl->hSelf          = hwnd;  
+  if (CtlType==ODT_COMBOBOX)              /* use the "faked" style for COMBOLBOX */
+                                          /* LBS_SORT instead CBS_SORT e.g.      */
+    lphl->dwStyle   = MAKELONG(LOWORD(styles),HIWORD(GetWindowLong32A(hwnd,GWL_STYLE)));
+  else
+    lphl->dwStyle   = GetWindowLong32A(hwnd,GWL_STYLE); /* use original style dword */
+  lphl->hParent        = parent;
+  lphl->StdItemHeight  = 15; /* FIXME: should get the font height */
+  lphl->OwnerDrawn     = styles & (LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE);
+  lphl->HasStrings     = (styles & LBS_HASSTRINGS) || !lphl->OwnerDrawn;
+
+  /* create dummy hdc to set text height */
+  if ((hdc = GetDC32(0)))
+  {
+      TEXTMETRIC16 tm;
+      GetTextMetrics16( hdc, &tm );
+      lphl->StdItemHeight = tm.tmHeight;
+      dprintf_listbox(stddeb,"CreateListBoxStruct:  font height %d\n",
+                      lphl->StdItemHeight);
+      ReleaseDC32( 0, hdc );
+  }
+
+  if (lphl->OwnerDrawn)
+  {
+    LISTSTRUCT dummyls;
+    
+    lphl->needMeasure = TRUE;
+    dummyls.mis.CtlType    = lphl->DrawCtlType;
+    dummyls.mis.CtlID      = lphl->CtlID;
+    dummyls.mis.itemID     = -1;
+    dummyls.mis.itemWidth  = 0; /* ignored */
+    dummyls.mis.itemData   = 0;
+
+    ListBoxAskMeasure(lphl,&dummyls);
+  }
+
+  lphl->HeapSel = GlobalAlloc16(GMEM_FIXED,LIST_HEAP_SIZE);
+  LocalInit( lphl->HeapSel, 0, LIST_HEAP_SIZE-1);
+}
+
+/* Send notification "code" as part of a WM_COMMAND-message if hwnd
+   has the LBS_NOTIFY style */
+void ListBoxSendNotification(LPHEADLIST lphl, WORD code)
+{
+  if (lphl->dwStyle & LBS_NOTIFY)
+      SendMessage32A( lphl->hParent, WM_COMMAND,
+                      MAKEWPARAM( lphl->CtlID, code), (LPARAM)lphl->hSelf );
+}
+
+
+/* get the maximum value of lphl->FirstVisible */
+int ListMaxFirstVisible(LPHEADLIST lphl)
+{
+    int m = lphl->ItemsCount-lphl->ItemsVisible;
+    return (m < 0) ? 0 : m;
+}
+
+
+/* Returns: 0 if nothing needs to be changed */
+/*          1 if FirstVisible changed */
+
+int ListBoxScrollToFocus(LPHEADLIST lphl)
+{
+  short       end;
+
+  if (lphl->ItemsCount == 0) return 0;
+  if (lphl->ItemFocused == -1) return 0;
+
+  end = lphl->FirstVisible + lphl->ItemsVisible - 1;
+
+  if (lphl->ItemFocused < lphl->FirstVisible ) {
+    lphl->FirstVisible = lphl->ItemFocused;
+    return 1;
+  } else {
+    if (lphl->ItemFocused > end) {
+      WORD maxFirstVisible = ListMaxFirstVisible(lphl);
+
+      lphl->FirstVisible = lphl->ItemFocused;
+      
+      if (lphl->FirstVisible > maxFirstVisible) {
+	lphl->FirstVisible = maxFirstVisible;
+      }
+      return 1;
+    }
+  } 
+  return 0;
+}
+
+
+LPLISTSTRUCT ListBoxGetItem(LPHEADLIST lphl, UINT uIndex)
+{
+  LPLISTSTRUCT lpls;
+  UINT         Count = 0;
+
+  if (uIndex >= lphl->ItemsCount) return NULL;
+
+  lpls = lphl->lpFirst;
+  while (Count++ < uIndex) lpls = lpls->lpNext;
+  return lpls;
+}
+
+
+void ListBoxDrawItem(HWND hwnd, LPHEADLIST lphl, HDC16 hdc, LPLISTSTRUCT lpls, 
+                     RECT16 *rect, WORD itemAction, WORD itemState)
+{
+    if (lphl->OwnerDrawn)
+    {
+        DRAWITEMSTRUCT32 dis;
+
+        dis.CtlID      = lpls->mis.CtlID;
+        dis.CtlType    = lpls->mis.CtlType;
+        dis.itemID     = lpls->mis.itemID;
+        dis.hDC        = hdc;
+        dis.hwndItem   = hwnd;
+        dis.itemData   = lpls->mis.itemData;
+        dis.itemAction = itemAction;
+        dis.itemState  = itemState;
+        CONV_RECT16TO32( rect, &dis.rcItem );
+        SendMessage32A( lphl->hParent, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis );
+        return;
+    }
+    if (itemAction == ODA_DRAWENTIRE || itemAction == ODA_SELECT) {
+      int 	OldBkMode;
+      DWORD 	dwOldTextColor = 0;
+
+      OldBkMode = SetBkMode(hdc, TRANSPARENT);
+
+      if (itemState != 0) {
+	dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
+	FillRect16(hdc, rect, GetStockObject32(BLACK_BRUSH));
+      }
+
+      if (lphl->dwStyle & LBS_USETABSTOPS) {
+	TabbedTextOut(hdc, rect->left + 5, rect->top + 2, 
+		      (char *)lpls->itemText, strlen((char *)lpls->itemText), 
+		      lphl->iNumStops, lphl->TabStops, 0);
+      } else {
+	TextOut16(hdc, rect->left + 5, rect->top + 2,
+                  (char *)lpls->itemText, strlen((char *)lpls->itemText));
+      }
+
+      if (itemState != 0) {
+	SetTextColor(hdc, dwOldTextColor);
+      }
+      
+      SetBkMode(hdc, OldBkMode);
+    }
+    else DrawFocusRect16(hdc, rect);
+}
+
+
+int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y)
+{
+  LPLISTSTRUCT lpls = lphl->lpFirst;
+  int          i, j;
+  POINT16      point;
+  
+  point.x = X; point.y = Y;
+  if (lphl->ItemsCount == 0) return LB_ERR;
+
+  for(i = 0; i < lphl->FirstVisible; i++) {
+    if (lpls == NULL) return LB_ERR;
+    lpls = lpls->lpNext;
+  }
+  for(j = 0; j < lphl->ItemsVisible; i++, j++) {
+    if (lpls == NULL) return LB_ERR;
+    if (PtInRect16(&lpls->itemRect,point)) {
+      return i;
+    }
+    lpls = lpls->lpNext;
+  }
+  dprintf_listbox(stddeb,"ListBoxFindMouse: not found\n");
+  return LB_ERR;
+}
+
+BOOL32 lbDeleteItemNotify(LPHEADLIST lphl, LPLISTSTRUCT lpls)
+{
+    /* called only for owner drawn listboxes */
+    BOOL32 ret;
+    DELETEITEMSTRUCT16 *delItem = SEGPTR_NEW(DELETEITEMSTRUCT16);
+    if (!delItem) return FALSE;
+
+    delItem->CtlType  = lphl->DrawCtlType;
+    delItem->CtlID    = lphl->CtlID;
+    delItem->itemID   = lpls->mis.itemID;
+    delItem->hwndItem = lphl->hSelf;
+    delItem->itemData = lpls->mis.itemData;
+
+    ret = SendMessage16( lphl->hParent, WM_DELETEITEM, (WPARAM16)lphl->CtlID,
+                         (LPARAM)SEGPTR_GET(delItem) );
+    SEGPTR_FREE(delItem);
+    return ret;
+}
+
+/* -------------------- strings and item data ---------------------- */
+
+void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls)  
+{
+    MEASUREITEMSTRUCT16 *lpmeasure = SEGPTR_NEW(MEASUREITEMSTRUCT16);
+    if (!lpmeasure) return;
+    *lpmeasure = lpls->mis;
+    lpmeasure->itemHeight = lphl->StdItemHeight;
+    SendMessage16( lphl->hParent, WM_MEASUREITEM, lphl->CtlID,
+                   (LPARAM)SEGPTR_GET(lpmeasure) );
+
+    if (lphl->dwStyle & LBS_OWNERDRAWFIXED)
+    {
+        if (lpmeasure->itemHeight > lphl->StdItemHeight)
+            lphl->StdItemHeight = lpmeasure->itemHeight;
+        lpls->mis.itemHeight = lpmeasure->itemHeight;
+    }
+    SEGPTR_FREE(lpmeasure);
+}
+
+static LPLISTSTRUCT ListBoxCreateItem(LPHEADLIST lphl, int id)
+{
+  LPLISTSTRUCT lplsnew = (LPLISTSTRUCT)malloc(sizeof(LISTSTRUCT));
+
+  if (lplsnew == NULL) return NULL;
+  
+  lplsnew->itemState      = 0;
+  lplsnew->mis.CtlType    = lphl->DrawCtlType;
+  lplsnew->mis.CtlID      = lphl->CtlID;
+  lplsnew->mis.itemID     = id;
+  lplsnew->mis.itemHeight = lphl->StdItemHeight;
+  lplsnew->mis.itemWidth  = 0; /* ignored */
+  lplsnew->mis.itemData   = 0;
+  SetRectEmpty16( &lplsnew->itemRect );
+
+  return lplsnew;
+}
+
+static int ListBoxAskCompare(LPHEADLIST lphl, int startItem, SEGPTR matchData, BOOL exactMatch )
+{
+ /*  Do binary search for sorted listboxes. Linked list item storage sort of 
+  *  defeats the purpose ( forces to traverse item list all the time ) but M$ does it this way...
+  *
+  *  MATCH_NEAREST (0) - return position for insertion - for all styles
+  *  MATCH_EXACT   (1) - search for an item, return index or LB_ERR 
+  *  MATCH_SUBSTR  (2) - same as exact match but with strncmp for string comparision
+  */
+
+ COMPAREITEMSTRUCT16   *itemCmp;
+ LPLISTSTRUCT		currentItem = NULL;
+ LPCSTR			matchStr = (lphl->HasStrings)?(LPCSTR)PTR_SEG_TO_LIN(matchData):NULL;
+ int                    head, pos = -1, tail, loop = 1;
+ short                  b = 0, s_length = 0;
+
+ /* check if empty */
+
+ if( !lphl->ItemsCount )
+    return (exactMatch)? LB_ERR: 0;
+
+ /* set up variables */
+
+ if( exactMatch == MATCH_NEAREST )
+     startItem = 0;
+ else if( ++startItem ) 
+   {
+     loop = 2;
+     if( startItem >= lphl->ItemsCount ) startItem = lphl->ItemsCount - 1;
+   }
+
+ if( exactMatch == MATCH_SUBSTR && lphl->HasStrings )
+   {
+     s_length = strlen( matchStr );
+     if( !s_length ) return 0; 		        /* head of the list - empty string */
+   }
+
+ head = startItem; tail = lphl->ItemsCount - 1;
+
+ dprintf_listbox(stddeb,"AskCompare: head = %i, tail = %i, data = %08x\n", head, tail, (unsigned)matchData );
+
+ if (!(itemCmp = SEGPTR_NEW(COMPAREITEMSTRUCT16))) return 0;
+ itemCmp->CtlType        = lphl->DrawCtlType;
+ itemCmp->CtlID          = lphl->CtlID;
+ itemCmp->hwndItem       = lphl->hSelf;
+
+ /* search from startItem */
+
+ while ( loop-- )
+  {
+    while( head <= tail )
+     {
+       pos = (tail + head)/2;
+       currentItem = ListBoxGetItem( lphl, pos );
+
+       if( lphl->HasStrings )
+	 {
+           b = ( s_length )? lstrncmpi32A( currentItem->itemText, matchStr, s_length)
+                           : lstrcmpi32A( currentItem->itemText, matchStr);
+	 }
+       else
+         {
+           itemCmp->itemID1      = pos;
+           itemCmp->itemData1    = currentItem->mis.itemData;
+           itemCmp->itemID2      = -1;
+           itemCmp->itemData2    = matchData;
+
+           b = SendMessage16( lphl->hParent, WM_COMPAREITEM,
+                              (WPARAM16)lphl->CtlID,
+                              (LPARAM)SEGPTR_GET(itemCmp) );
+         }
+
+       if( b == 0 )
+       {
+           SEGPTR_FREE(itemCmp);
+           return pos;  /* found exact match */
+       }
+       else
+         if( b < 0 ) head = ++pos;
+         else
+           if( b > 0 ) tail = pos - 1;
+     }
+
+    /* reset to search from the first item */
+    head = 0; tail = startItem - 1;
+  }
+
+ dprintf_listbox(stddeb,"\t-> pos = %i\n", pos );
+ SEGPTR_FREE(itemCmp);
+
+ /* if we got here match is not exact */
+
+ if( pos < 0 ) pos = 0;
+ else if( pos > lphl->ItemsCount ) pos = lphl->ItemsCount;
+
+ return (exactMatch)? LB_ERR: pos;
+}
+
+int ListBoxInsertString(LPHEADLIST lphl, UINT uIndex, LPCSTR newstr)
+{
+  LPLISTSTRUCT *lppls, lplsnew, lpls;
+  HANDLE16 hStr;
+  LPSTR	str;
+  UINT	Count;
+    
+  dprintf_listbox(stddeb,"ListBoxInsertString(%d, %p);\n", uIndex, newstr);
+    
+  if (!newstr) return -1;
+
+  if (uIndex == (UINT)-1)
+    uIndex = lphl->ItemsCount;
+
+  lppls = &lphl->lpFirst;
+  for(Count = 0; Count < uIndex; Count++) {
+    if (*lppls == NULL) return LB_ERR;
+    lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
+  }
+    
+  lplsnew = ListBoxCreateItem(lphl, Count);
+  
+  if (lplsnew == NULL) {
+    fprintf(stdnimp,"ListBoxInsertString() out of memory !\n");
+    return LB_ERRSPACE;
+  }
+
+  lplsnew->lpNext = *lppls;
+  *lppls = lplsnew;
+  lphl->ItemsCount++;
+  
+  hStr = 0;
+  if (lphl->HasStrings) {
+    dprintf_listbox(stddeb,"  string: %s\n", newstr);
+    hStr = LIST_HEAP_ALLOC(lphl, LMEM_MOVEABLE, strlen(newstr) + 1);
+    str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
+    if (str == NULL) return LB_ERRSPACE;
+    strcpy(str, newstr); 
+    lplsnew->itemText = str;
+    /* I'm not so sure about the next one */
+    lplsnew->mis.itemData = 0;
+  } else {
+    lplsnew->itemText = NULL;
+    lplsnew->mis.itemData = (DWORD)newstr;
+  }
+
+  lplsnew->mis.itemID = uIndex;
+  lplsnew->hData = hStr;
+  
+  /* adjust the itemID field of the following entries */
+  for(lpls = lplsnew->lpNext; lpls != NULL; lpls = lpls->lpNext) {
+      lpls->mis.itemID++;
+  }
+ 
+  if (lphl->needMeasure) {
+    ListBoxAskMeasure(lphl, lplsnew);
+  }
+
+  dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
+  return uIndex;
+}
+
+
+int ListBoxAddString(LPHEADLIST lphl, SEGPTR itemData)
+{
+    UINT 	pos = (UINT) -1;
+    LPCSTR	newstr = (lphl->HasStrings)?(LPCSTR)PTR_SEG_TO_LIN(itemData):(LPCSTR)itemData;
+
+    if ( lphl->dwStyle & LBS_SORT ) 
+	 pos = ListBoxAskCompare( lphl, -1, itemData, MATCH_NEAREST );
+
+    return ListBoxInsertString(lphl, pos, newstr);
+}
+
+
+int ListBoxGetText(LPHEADLIST lphl, UINT uIndex, LPSTR OutStr)
+{
+  LPLISTSTRUCT lpls;
+
+  if (!OutStr) {
+    dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
+    return 0;
+  }
+  *OutStr = '\0';
+  lpls = ListBoxGetItem (lphl, uIndex);
+  if (lpls == NULL) return LB_ERR;
+
+  if (!lphl->HasStrings) {
+    *((long *)OutStr) = lpls->mis.itemData;
+    return 4;
+  }
+	
+  strcpy(OutStr, lpls->itemText);
+  return strlen(OutStr);
+}
+
+
+DWORD ListBoxGetItemData(LPHEADLIST lphl, UINT uIndex)
+{
+  LPLISTSTRUCT lpls;
+
+  lpls = ListBoxGetItem (lphl, uIndex);
+  if (lpls == NULL) return LB_ERR;
+  return lpls->mis.itemData;
+}
+
+
+int ListBoxSetItemData(LPHEADLIST lphl, UINT uIndex, DWORD ItemData)
+{
+  LPLISTSTRUCT lpls = ListBoxGetItem(lphl, uIndex);
+
+  if (lpls == NULL) return LB_ERR;
+  lpls->mis.itemData = ItemData;
+  return 1;
+}
+
+
+int ListBoxDeleteString(LPHEADLIST lphl, UINT uIndex)
+{
+  LPLISTSTRUCT lpls, lpls2;
+  UINT	Count;
+
+  if (uIndex >= lphl->ItemsCount) return LB_ERR;
+
+  lpls = lphl->lpFirst;
+  if (lpls == NULL) return LB_ERR;
+
+  if (uIndex == 0)
+  {
+    if( lphl->OwnerDrawn )
+        lbDeleteItemNotify( lphl, lpls);
+    lphl->lpFirst = lpls->lpNext;
+  }
+  else 
+  {
+    LPLISTSTRUCT lpls2 = NULL;
+    for(Count = 0; Count < uIndex; Count++) {
+      if (lpls->lpNext == NULL) return LB_ERR;
+
+      lpls2 = lpls;
+      lpls = (LPLISTSTRUCT)lpls->lpNext;
+    }
+    if( lphl->OwnerDrawn )
+	lbDeleteItemNotify( lphl, lpls);
+    lpls2->lpNext = lpls->lpNext;
+  }
+
+  /* adjust the itemID field of the following entries */
+  for(lpls2 = lpls->lpNext; lpls2 != NULL; lpls2 = lpls2->lpNext) {
+      lpls2->mis.itemID--;
+  }
+ 
+  lphl->ItemsCount--;
+
+  if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
+  free(lpls);
+  
+  return lphl->ItemsCount;
+}
+
+static int lbFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr, BOOL match)
+{
+  /*  match is either MATCH_SUBSTR or MATCH_EXACT */
+
+  LPLISTSTRUCT lpls;
+  UINT	       Count;
+  UINT         First      = nFirst + 1;
+  int	       s_length   = 0;
+  LPSTR        lpMatchStr = (LPSTR)MatchStr;
+
+  if (First > lphl->ItemsCount) return LB_ERR;
+
+  if (lphl->dwStyle & LBS_SORT )
+      return ListBoxAskCompare( lphl, nFirst, MatchStr, match );
+
+  if (lphl->HasStrings ) 
+  {
+    lpMatchStr = PTR_SEG_TO_LIN(MatchStr);
+
+    if( match == MATCH_SUBSTR )
+    {
+      s_length = strlen(lpMatchStr);
+      if( !s_length ) return (lphl->ItemsCount)?0:LB_ERR;
+    }
+  }
+
+  lpls = ListBoxGetItem(lphl, First);
+  Count = 0;
+  while(lpls != NULL) 
+  {
+    if (lphl->HasStrings) 
+    {
+      if ( ( s_length )? !lstrncmpi32A(lpls->itemText, lpMatchStr, s_length)
+                       : !lstrcmpi32A(lpls->itemText, lpMatchStr)  ) return Count;
+    }
+    else
+      if ( lpls->mis.itemData == (DWORD)lpMatchStr ) return Count;
+
+    lpls = lpls->lpNext;
+    Count++;
+  }
+
+  /* Start over at top */
+  Count = 0;
+  lpls = lphl->lpFirst;
+
+  while (Count < First) 
+  {
+    if (lphl->HasStrings) 
+    {
+      if ( ( s_length )? !lstrncmpi32A(lpls->itemText, lpMatchStr, s_length)
+                       : !lstrcmpi32A(lpls->itemText, lpMatchStr)  ) return Count;
+    }
+    else
+      if ( lpls->mis.itemData == (DWORD)lpMatchStr ) return Count;
+    
+    lpls = lpls->lpNext;
+    Count++;
+  }
+
+  return LB_ERR;
+}
+
+int ListBoxFindString(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
+{
+  return lbFindString(lphl, nFirst, MatchStr, MATCH_SUBSTR );
+}
+
+int ListBoxFindStringExact(LPHEADLIST lphl, UINT nFirst, SEGPTR MatchStr)
+{
+  return lbFindString(lphl, nFirst, MatchStr, MATCH_EXACT );
+}
+
+int ListBoxResetContent(LPHEADLIST lphl)
+{
+    LPLISTSTRUCT lpls;
+    int i;
+
+    if (lphl->ItemsCount == 0) return 0;
+
+    dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
+	lphl->ItemsCount);
+
+    for(i = 0; i < lphl->ItemsCount; i++) {
+      lpls = lphl->lpFirst;
+      if (lpls == NULL) return LB_ERR;
+
+      if (lphl->OwnerDrawn) lbDeleteItemNotify(lphl, lpls);
+
+      lphl->lpFirst = lpls->lpNext;
+      if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
+      free(lpls);
+    }
+    ListBoxInitialize(lphl);
+
+    return TRUE;
+}
+
+/* --------------------- selection ------------------------- */
+
+int ListBoxSetCurSel(LPHEADLIST lphl, WORD wIndex)
+{
+  LPLISTSTRUCT lpls;
+
+  /* use ListBoxSetSel instead */
+  if (lphl->dwStyle & (LBS_MULTIPLESEL | LBS_EXTENDEDSEL) ) return 0;
+
+  /* unselect previous item */
+  if (lphl->ItemFocused != -1) {
+    lphl->PrevFocused = lphl->ItemFocused;
+    lpls = ListBoxGetItem(lphl, lphl->ItemFocused);
+    if (lpls == 0) return LB_ERR;
+    lpls->itemState = 0;
+  }
+
+  if ((wIndex != (UINT)-1) && (wIndex < lphl->ItemsCount))
+  {
+    lphl->ItemFocused = wIndex;
+    lpls = ListBoxGetItem(lphl, wIndex);
+    if (lpls == 0) return LB_ERR;
+    lpls->itemState = ODS_SELECTED | ODS_FOCUS;
+
+    return 0;
+  }
+
+  return LB_ERR;
+}
+
+
+
+/* ------------------------- dir listing ------------------------ */
+
+LONG ListBoxDirectory(LPHEADLIST lphl, UINT attrib, LPCSTR filespec)
+{
+    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;
+}
+
+/* ------------------------- dimensions ------------------------- */
+
+int ListBoxGetItemRect(LPHEADLIST lphl, WORD wIndex, LPRECT16 lprect)
+{
+  LPLISTSTRUCT lpls = ListBoxGetItem(lphl,wIndex);
+
+  dprintf_listbox(stddeb,"ListBox LB_GETITEMRECT %i %p", wIndex,lpls);
+  if (lpls == NULL)
+  {
+    if (lphl->dwStyle & LBS_OWNERDRAWVARIABLE)
+      return LB_ERR;
+    else 
+    {
+     GetClientRect16(lphl->hSelf,lprect);
+     lprect->bottom=lphl->StdItemHeight;
+     if (lprect->right<0) lprect->right=0;
+    }
+  }
+  else
+   *lprect = lpls->itemRect;
+  dprintf_listbox(stddeb," = %d,%d  %d,%d\n", lprect->left,lprect->top,
+                                              lprect->right,lprect->bottom);
+  return 0;
+}
+
+
+int ListBoxSetItemHeight(LPHEADLIST lphl, WORD wIndex, long height)
+{
+  LPLISTSTRUCT lpls;
+
+  if (!(lphl->dwStyle & LBS_OWNERDRAWVARIABLE)) {
+    lphl->StdItemHeight = (short)height;
+    return 0;
+  }
+  
+  lpls = ListBoxGetItem(lphl, wIndex);
+  if (lpls == NULL) return LB_ERR;
+  
+  lpls->mis.itemHeight = height;
+  return 0;
+}
+
+/* -------------------------- string search ------------------------ */  
+
+int ListBoxFindNextMatch(LPHEADLIST lphl, WORD wChar)
+{
+  LPLISTSTRUCT lpls;
+  UINT	       count,first;
+
+  if ((char)wChar < ' ') return LB_ERR;
+  if (!lphl->HasStrings) return LB_ERR;
+
+  lpls = lphl->lpFirst;
+  
+  for (count = 0; lpls != NULL; lpls = lpls->lpNext, count++) {
+    if (tolower(*lpls->itemText) == tolower((char)wChar)) break;
+  }
+  if (lpls == NULL) return LB_ERR;
+  first = count;
+  for(; lpls != NULL; lpls = lpls->lpNext, count++) {
+    if (*lpls->itemText != (char)wChar) 
+      break;
+    if ((short) count > lphl->ItemFocused)
+      return count;
+  }
+  return first;
+}
diff --git a/controls/scroll.c b/controls/scroll.c
index 21316a0..0ffa3b4 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -54,7 +54,7 @@
 #define SCROLL_FIRST_DELAY   200
 
   /* Delay (in ms) between scroll repetitions */
-#define SCROLL_REPEAT_DELAY  100
+#define SCROLL_REPEAT_DELAY  50
 
   /* Scroll timer id */
 #define SCROLL_TIMER   0
diff --git a/controls/widgets.c b/controls/widgets.c
index 88d01a4..a884757 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -16,7 +16,12 @@
 #include "module.h"
 #include "heap.h"
 
-#define OLD_LISTBOX
+/* Window procedures */
+
+extern LRESULT ListBoxWndProc( HWND32 hwnd, UINT32 msg, WPARAM32 wParam,
+                               LPARAM lParam );
+
+/* Win16 class info */
 
 typedef struct
 {
@@ -27,42 +32,39 @@
     LPCSTR     className;
 } BUILTIN_CLASS_INFO16;
 
+/* Win16 built-in classes */
+
 static const BUILTIN_CLASS_INFO16 WIDGETS_BuiltinClasses16[] =
 {
     { CS_GLOBALCLASS | CS_PARENTDC,
-       sizeof(STATICINFO), 0, "StaticWndProc", "STATIC" },
-#ifdef OLD_LISTBOX
+       sizeof(STATICINFO), 0, "StaticWndProc", "Static" },
     { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
-      8, 0, "ListBoxWndProc", "LISTBOX" },
-#endif
-    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
-      8, 0, "ComboBoxWndProc", "COMBOBOX" },
+      8, 0, "ComboBoxWndProc", "ComboBox" },
     { CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS,
-      8, 0, "ComboLBoxWndProc", "COMBOLBOX" },
+      8, 0, "ComboLBoxWndProc", "ComboLBox" },
     { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS,
-      sizeof(DWORD), 0, "EditWndProc", "EDIT" },
+      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" }
+      STOCK_LTGRAY_BRUSH, "MDIClientWndProc", "MDIClient" }
 };
 
 #define NB_BUILTIN_CLASSES16 \
          (sizeof(WIDGETS_BuiltinClasses16)/sizeof(WIDGETS_BuiltinClasses16[0]))
 
+/* Win32 built-in classes */
 
 static WNDCLASS32A WIDGETS_BuiltinClasses32[] =
 {
     { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
-      ButtonWndProc, 0, sizeof(BUTTONINFO), 0, 0, 0, 0, 0, "BUTTON" },
-#ifndef OLD_LISTBOX
+      ButtonWndProc, 0, sizeof(BUTTONINFO), 0, 0, 0, 0, 0, "Button" },
     { CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,
-      ListBoxWndProc32, 0, sizeof(void *), 0, 0, 0, 0, 0, "LISTBOX" },
-#endif
+      ListBoxWndProc, 0, sizeof(void *), 0, 0, 0, 0, 0, "ListBox" },
     { CS_GLOBALCLASS | CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_PARENTDC,
-      ScrollBarWndProc, 0, sizeof(SCROLLBAR_INFO), 0, 0, 0, 0, 0, "SCROLLBAR"},
+      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 }
 };
@@ -71,6 +73,8 @@
          (sizeof(WIDGETS_BuiltinClasses32)/sizeof(WIDGETS_BuiltinClasses32[0]))
 
 
+/* Win32 common controls */
+
 static WNDCLASS32A WIDGETS_CommonControls32[] =
 {
     { CS_GLOBALCLASS | CS_VREDRAW | CS_HREDRAW, StatusWindowProc, 0,
diff --git a/files/profile.c b/files/profile.c
index ddb21ed..d1a8426 100644
--- a/files/profile.c
+++ b/files/profile.c
@@ -5,6 +5,7 @@
  * Copyright 1996 Alexandre Julliard
  */
 
+#define NO_TRANSITION_TYPES  /* This file is Win32-clean */
 #include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -13,6 +14,7 @@
 #include "windows.h"
 #include "dos_fs.h"
 #include "xmalloc.h"
+#include "string32.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -33,7 +35,7 @@
 
 typedef struct
 {
-    int              changed;
+    BOOL32           changed;
     PROFILESECTION  *section;
     char            *dos_name;
 } PROFILE;
@@ -55,6 +57,8 @@
 
 #define WINE_INI_GLOBAL ETCDIR "/wine.conf"
 
+static LPCWSTR wininiW = NULL;
+
 /***********************************************************************
  *           PROFILE_CopyEntry
  *
@@ -227,7 +231,7 @@
  *
  * Delete a section from a profile tree.
  */
-static BOOL PROFILE_DeleteSection( PROFILESECTION **section, const char *name )
+static BOOL32 PROFILE_DeleteSection( PROFILESECTION **section, LPCSTR name )
 {
     while (*section)
     {
@@ -250,8 +254,8 @@
  *
  * Delete a key from a profile tree.
  */
-static BOOL PROFILE_DeleteKey( PROFILESECTION **section,
-                               const char *section_name, const char *key_name )
+static BOOL32 PROFILE_DeleteKey( PROFILESECTION **section,
+                                 LPCSTR section_name, LPCSTR key_name )
 {
     while (*section)
     {
@@ -323,7 +327,7 @@
  *
  * Flush the current profile to disk if changed.
  */
-static BOOL PROFILE_FlushFile(void)
+static BOOL32 PROFILE_FlushFile(void)
 {
     char *p, buffer[MAX_PATHNAME_LEN];
     const char *unix_name;
@@ -368,7 +372,7 @@
  *
  * Open a profile file, checking the cached file first.
  */
-static BOOL PROFILE_Open( const char *filename )
+static BOOL32 PROFILE_Open( LPCSTR filename )
 {
     char buffer[MAX_PATHNAME_LEN];
     const char *dos_name, *unix_name;
@@ -443,16 +447,15 @@
  *
  * Enumerate all the keys of a section.
  */
-static INT PROFILE_GetSection( PROFILESECTION *section,
-                               const char *section_name,
-                               char *buffer, INT len, int handle_env )
+static INT32 PROFILE_GetSection( PROFILESECTION *section, LPCSTR section_name,
+                                 LPSTR buffer, INT32 len, BOOL32 handle_env )
 {
     PROFILEKEY *key;
     while (section)
     {
         if (section->name && !lstrcmpi32A( section->name, section_name ))
         {
-            INT oldlen = len;
+            INT32 oldlen = len;
             for (key = section->key; key; key = key->next)
             {
                 if (len <= 2) break;
@@ -476,8 +479,8 @@
  *
  * Get a profile string.
  */
-static INT PROFILE_GetString( const char *section, const char *key_name,
-                              const char *def_val, char *buffer, INT len )
+static INT32 PROFILE_GetString( LPCSTR section, LPCSTR key_name,
+                                LPCSTR def_val, LPSTR buffer, INT32 len )
 {
     PROFILEKEY *key = NULL;
 
@@ -500,10 +503,10 @@
  *
  * Set a profile string.
  */
-static BOOL PROFILE_SetString( const char *section_name, const char *key_name,
-                               const char *value )
+static BOOL32 PROFILE_SetString( LPCSTR section_name, LPCSTR key_name,
+                                 LPCSTR value )
 {
-    BOOL ret;
+    BOOL32 ret;
 
     if (!key_name)  /* Delete a whole section */
     {
@@ -623,66 +626,156 @@
 }
 
 
+/********************* API functions **********************************/
+
 /***********************************************************************
- *           GetProfileInt   (KERNEL.57)
+ *           GetProfileInt16   (KERNEL.57)
  */
-UINT GetProfileInt( LPCSTR section, LPCSTR entry, INT def_val )
+UINT16 GetProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val )
 {
-    return GetPrivateProfileInt( section, entry, def_val, "win.ini" );
+    return GetPrivateProfileInt16( section, entry, def_val, "win.ini" );
 }
 
 
 /***********************************************************************
- *           GetProfileString   (KERNEL.58)
+ *           GetProfileInt32A   (KERNEL32.264)
  */
-INT GetProfileString( LPCSTR section, LPCSTR entry, LPCSTR def_val,
-                      LPSTR buffer, INT len )
+UINT32 GetProfileInt32A( LPCSTR section, LPCSTR entry, INT32 def_val )
 {
-    return GetPrivateProfileString( section, entry, def_val,
-                                    buffer, len, "win.ini" );
+    return GetPrivateProfileInt32A( section, entry, def_val, "win.ini" );
+}
+
+/***********************************************************************
+ *           GetProfileInt32W   (KERNEL32.264)
+ */
+UINT32 GetProfileInt32W( LPCWSTR section, LPCWSTR entry, INT32 def_val )
+{
+    if (!wininiW) wininiW = STRING32_DupAnsiToUni("win.ini");
+    return GetPrivateProfileInt32W( section, entry, def_val, wininiW );
+}
+
+/***********************************************************************
+ *           GetProfileString16   (KERNEL.58)
+ */
+INT16 GetProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
+                          LPSTR buffer, INT16 len )
+{
+    return GetPrivateProfileString16( section, entry, def_val,
+                                      buffer, len, "win.ini" );
+}
+
+/***********************************************************************
+ *           GetProfileString32A   (KERNEL32.268)
+ */
+INT32 GetProfileString32A( LPCSTR section, LPCSTR entry, LPCSTR def_val,
+                           LPSTR buffer, INT32 len )
+{
+    return GetPrivateProfileString32A( section, entry, def_val,
+                                       buffer, len, "win.ini" );
+}
+
+/***********************************************************************
+ *           GetProfileString32W   (KERNEL32.269)
+ */
+INT32 GetProfileString32W( LPCWSTR section,LPCWSTR entry,LPCWSTR def_val,
+                           LPWSTR buffer, INT32 len )
+{
+    if (!wininiW) wininiW = STRING32_DupAnsiToUni("win.ini");
+    return GetPrivateProfileString32W( section, entry, def_val,
+                                       buffer, len, wininiW );
 }
 
 
 /***********************************************************************
- *           WriteProfileString   (KERNEL.59)
+ *           WriteProfileString16   (KERNEL.59)
  */
-BOOL WriteProfileString( LPCSTR section, LPCSTR entry, LPCSTR string )
+BOOL16 WriteProfileString16( LPCSTR section, LPCSTR entry, LPCSTR string )
 {
-    return WritePrivateProfileString( section, entry, string, "win.ini" );
+    return WritePrivateProfileString16( section, entry, string, "win.ini" );
+}
+
+/***********************************************************************
+ *           WriteProfileString32A   (KERNEL32.587)
+ */
+BOOL32 WriteProfileString32A( LPCSTR section, LPCSTR entry, LPCSTR string )
+{
+    return WritePrivateProfileString32A( section, entry, string, "win.ini" );
+}
+
+/***********************************************************************
+ *           WriteProfileString32W   (KERNEL32.588)
+ */
+BOOL32 WriteProfileString32W( LPCWSTR section, LPCWSTR entry, LPCWSTR string )
+{
+    if (!wininiW) wininiW = STRING32_DupAnsiToUni("win.ini");
+    return WritePrivateProfileString32W( section, entry, string, wininiW );
 }
 
 
 /***********************************************************************
- *           GetPrivateProfileInt   (KERNEL.127)
+ *           GetPrivateProfileInt16   (KERNEL.127)
  */
-UINT GetPrivateProfileInt( LPCSTR section, LPCSTR entry, INT def_val,
-                           LPCSTR filename )
+UINT16 GetPrivateProfileInt16( LPCSTR section, LPCSTR entry, INT16 def_val,
+                               LPCSTR filename )
+{
+    long result=(long)GetPrivateProfileInt32A(section,entry,def_val,filename);
+
+    if (result > 65535) return 65535;
+    if (result >= 0) return (UINT16)result;
+    if (result < -32768) return -32768;
+    return (UINT16)(INT16)result;
+}
+
+/***********************************************************************
+ *           GetPrivateProfileInt32A   (KERNEL32.251)
+ */
+UINT32 GetPrivateProfileInt32A( LPCSTR section, LPCSTR entry, INT32 def_val,
+                                LPCSTR filename )
 {
     char buffer[20];
     char *p;
     long result;
 
-    GetPrivateProfileString( section, entry, "",
-                             buffer, sizeof(buffer), filename );
-    if (!buffer[0]) return (UINT)def_val;
+    GetPrivateProfileString32A( section, entry, "",
+                                buffer, sizeof(buffer), filename );
+    if (!buffer[0]) return (UINT32)def_val;
     result = strtol( buffer, &p, 0 );
     if (p == buffer) return 0;  /* No digits at all */
-#ifdef WINELIB32
-    return (UINT)result;
-#else
-    if (result > 65535) return 65535;
-    if (result >= 0) return (UINT)result;
-    if (result < -32768) return -32768;
-    return (UINT)(INT)result;
-#endif
+    return (UINT32)result;
 }
 
+/***********************************************************************
+ *           GetPrivateProfileInt32W   (KERNEL32.252)
+ */
+UINT32 GetPrivateProfileInt32W( LPCWSTR section, LPCWSTR entry, INT32 def_val,
+                                LPCWSTR filename )
+{
+    LPSTR sectionA=section?STRING32_DupUniToAnsi(section):NULL;
+    LPSTR entryA=entry?STRING32_DupUniToAnsi(entry):NULL;
+    LPSTR filenameA=filename?STRING32_DupUniToAnsi(filename):NULL;
+    UINT32 res;
+
+    res=GetPrivateProfileInt32A(sectionA,entryA,def_val,filenameA);
+    if (sectionA) free(sectionA);
+    if (filenameA) free(filenameA);
+    if (entryA) free(entryA);
+    return res;
+}
 
 /***********************************************************************
- *           GetPrivateProfileString   (KERNEL.128)
+ *           GetPrivateProfileString16   (KERNEL.128)
  */
-INT GetPrivateProfileString( LPCSTR section, LPCSTR entry, LPCSTR def_val,
-                             LPSTR buffer, INT len, LPCSTR filename )
+INT16 GetPrivateProfileString16( LPCSTR section, LPCSTR entry, LPCSTR def_val,
+                                 LPSTR buffer, INT16 len, LPCSTR filename )
+{
+    return GetPrivateProfileString32A(section,entry,def_val,buffer,len,filename);
+}
+
+/***********************************************************************
+ *           GetPrivateProfileString32A   (KERNEL32.255)
+ */
+INT32 GetPrivateProfileString32A( LPCSTR section, LPCSTR entry, LPCSTR def_val,
+                                  LPSTR buffer, INT32 len, LPCSTR filename )
 {
     if (PROFILE_Open( filename ))
         return PROFILE_GetString( section, entry, def_val, buffer, len );
@@ -690,18 +783,73 @@
     return strlen( buffer );
 }
 
+/***********************************************************************
+ *           GetPrivateProfileString32W   (KERNEL32.256)
+ */
+INT32 GetPrivateProfileString32W( LPCWSTR section,LPCWSTR entry,LPCWSTR def_val,
+                                  LPWSTR buffer,INT32 len,LPCWSTR filename )
+{
+    LPSTR	sectionA = section?STRING32_DupUniToAnsi(section):NULL;
+    LPSTR	entryA = entry?STRING32_DupUniToAnsi(entry):NULL;
+    LPSTR	filenameA = filename?STRING32_DupUniToAnsi(filename):NULL;
+    LPSTR	def_valA = def_val?STRING32_DupUniToAnsi(def_val):NULL;
+    LPSTR	bufferA = xmalloc(len);
+    INT32	ret;
+
+    ret=GetPrivateProfileString32A(sectionA,entryA,def_valA,bufferA,len,filenameA);
+    if (sectionA) free(sectionA);
+    if (entryA) free(entryA);
+    if (filenameA) free(filenameA);
+    if (def_valA) free(def_valA);
+
+    lstrcpynAtoW( buffer, bufferA, len );
+    free(bufferA);
+    return ret;
+}
+
+
 
 /***********************************************************************
- *           WritePrivateProfileString   (KERNEL.129)
+ *           WritePrivateProfileString16   (KERNEL.129)
  */
-BOOL WritePrivateProfileString( LPCSTR section, LPCSTR entry, LPCSTR string,
-                                LPCSTR filename )
+BOOL16 WritePrivateProfileString16(LPCSTR section,LPCSTR entry,LPCSTR string,
+                                   LPCSTR filename)
+{
+    return WritePrivateProfileString32A(section,entry,string,filename);
+}
+
+/***********************************************************************
+ *           WritePrivateProfileString32A   (KERNEL32.582)
+ */
+BOOL32 WritePrivateProfileString32A(LPCSTR section,LPCSTR entry,LPCSTR string,
+                                    LPCSTR filename )
 {
     if (!PROFILE_Open( filename )) return FALSE;
     if (!section) return PROFILE_FlushFile();
     return PROFILE_SetString( section, entry, string );
 }
 
+/***********************************************************************
+ *           WritePrivateProfileString32W   (KERNEL32.583)
+ */
+BOOL32 WritePrivateProfileString32W(LPCWSTR section,LPCWSTR entry,LPCWSTR string,
+                                    LPCWSTR filename )
+{
+    LPSTR sectionA = section?STRING32_DupUniToAnsi(section):NULL;
+    LPSTR entryA = entry?STRING32_DupUniToAnsi(entry):NULL;
+    LPSTR stringA = string?STRING32_DupUniToAnsi(string):NULL;
+    LPSTR filenameA = filename?STRING32_DupUniToAnsi(filename):NULL;
+    BOOL32 res;
+
+    res = WritePrivateProfileString32A(sectionA,entryA,stringA,filenameA);
+
+    if (sectionA) free(sectionA);
+    if (entryA) free(entryA);
+    if (stringA) free(stringA);
+    if (filenameA) free(filenameA);
+    return res;
+}
+
 
 /***********************************************************************
  *           WriteOutProfiles   (KERNEL.315)
diff --git a/graphics/Makefile.in b/graphics/Makefile.in
index 9bb9535..cc14f5f 100644
--- a/graphics/Makefile.in
+++ b/graphics/Makefile.in
@@ -6,6 +6,7 @@
 MODULE    = graphics
 
 C_SRCS = \
+	wing.c \
 	bitblt.c \
 	driver.c
 
diff --git a/graphics/wing.c b/graphics/wing.c
new file mode 100644
index 0000000..4f3b29d
--- /dev/null
+++ b/graphics/wing.c
@@ -0,0 +1,67 @@
+/*
+ * WingG support
+ *
+ * Started by Robert Pouliot <krynos@clic.net>
+ */
+
+#include "gdi.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/* I dunno if this structure can be put here... Maybe copyright, I'm no lawyer... */
+typedef enum WING_DITHER_TYPE
+{
+    WING_DISPERSED_4x4,
+    WING_DISPERSED_8x8,
+
+    WING_CLUSTERED_4x4
+
+} WING_DITHER_TYPE;
+
+/***********************************************************************
+ *          WingCreateDC16	(WING.1001)
+ */
+HDC16 WinGCreateDC16(void)
+{
+	/* FIXME: Probably wrong... */
+	return CreateDC("DISPLAY", NULL, NULL, NULL);
+}
+
+
+/***********************************************************************
+ *  WinGRecommendDIBFormat16    (WING.1002)
+ */
+BOOL16 WinGRecommendDIBFormat16(BITMAPINFO *fmt)
+{
+        fprintf(stdnimp,"WinGRecommendDIBFormat: empty stub!\n");
+	return 0;
+}
+
+/***********************************************************************
+ *        WinGCreateBitmap16    (WING.1003)
+ */
+HBITMAP16 WinGCreateBitmap16(HDC16 winDC, BITMAPINFO *header, void **bits)
+{
+        fprintf(stdnimp,"WinGCreateBitmap: empty stub! (expect failure)\n");
+	*bits=0;
+	return 0;
+}
+
+/***********************************************************************
+ *  WinGCreateHalfTonePalette16   (WING.1007)
+ */
+HPALETTE16 WinGCreateHalfTonePalette16(void)
+{
+        fprintf(stdnimp,"WinGCreateHalfTonePalette: empty stub!\n");
+	return 0;
+}
+
+/***********************************************************************
+ *  WinGCreateHalfToneBrush16   (WING.1008)
+ */
+HPALETTE16 WinGCreateHalfToneBrush16(HDC16 winDC, COLORREF col, WING_DITHER_TYPE type)
+{
+        fprintf(stdnimp,"WinGCreateHalfToneBrush: empty stub!\n");
+	return 0;
+}
+
diff --git a/if1632/crtdll.spec b/if1632/crtdll.spec
index 6e15693..bf709fb 100644
--- a/if1632/crtdll.spec
+++ b/if1632/crtdll.spec
@@ -343,7 +343,7 @@
 338 stub abort
 339 cdecl abs(long) CRTDLL_abs
 340 cdecl acos(long) CRTDLL_acos
-341 stub asctime
+341 cdecl asctime(ptr) asctime
 342 cdecl asin(long) CRTDLL_asin
 343 cdecl atan(long) CRTDLL_atan
 344 cdecl atan2(long long) CRTDLL_atan2
@@ -352,15 +352,15 @@
 347 cdecl atoi(ptr) CRTDLL_atoi
 348 cdecl atol(ptr) CRTDLL_atol
 349 stub bsearch
-350 stub calloc
+350 cdecl calloc(long long) CRTDLL_calloc
 351 stub ceil
 352 stub clearerr
-353 stub clock
+353 cdecl clock() clock
 354 cdecl cos(long) CRTDLL_cos
 355 cdecl cosh(long) CRTDLL_cosh
-356 stub ctime
+356 cdecl ctime(ptr) ctime
 357 stub difftime
-358 stub div
+358 cdecl div(long long) div
 359 cdecl exit(long) CRTDLL_exit
 360 cdecl exp(long) CRTDLL_exp
 361 cdecl fabs(long) CRTDLL_fabs
@@ -394,7 +394,7 @@
 389 stub getchar
 390 stub getenv
 391 cdecl gets(ptr) CRTDLL_gets
-392 stub gmtime
+392 cdecl gmtime(ptr) gmtime
 393 stub is_wctype
 394 cdecl isalnum(long) CRTDLL_isalnum
 395 cdecl isalpha(long) CRTDLL_isalpha
@@ -423,9 +423,9 @@
 418 cdecl isxdigit(long) CRTDLL_isxdigit
 419 cdecl labs(long) CRTDLL_labs
 420 stub ldexp
-421 stub ldiv
+421 cdecl ldiv(long long) ldiv
 422 stub localeconv
-423 stub localtime
+423 cdecl localtime(ptr) localtime
 424 cdecl log(long) CRTDLL_log
 425 cdecl log10(long) CRTDLL_log10
 426 stub longjmp
@@ -438,7 +438,7 @@
 433 cdecl memcpy(ptr ptr long) memcpy
 434 cdecl memmove(ptr ptr long) memmove
 435 cdecl memset(ptr long long) memset 
-436 stub mktime
+436 cdecl mktime(ptr) mktime
 437 stub modf
 438 stub perror
 439 cdecl pow(long long) CRTDLL_pow
@@ -449,7 +449,7 @@
 444 stub qsort
 445 stub raise
 446 cdecl rand() CRTDLL_rand
-447 stub realloc
+447 cdecl realloc(ptr long) CRTDLL_realloc
 448 stub remove
 449 stub rename
 450 stub rewind
@@ -464,27 +464,27 @@
 459 cdecl sqrt(long) CRTDLL_sqrt
 460 cdecl srand(long) CRTDLL_srand
 461 stub sscanf
-462 cdecl strcat(ptr ptr) lstrcat32A
+462 cdecl strcat(ptr ptr) strcat
 463 cdecl strchr(ptr long) strchr
-464 cdecl strcmp(ptr ptr) lstrcmp32A
-465 stub strcoll
-466 cdecl strcpy(ptr ptr) lstrcpy32A
+464 cdecl strcmp(ptr ptr) strcmp
+465 cdecl strcoll(ptr ptr) strcoll
+466 cdecl strcpy(ptr ptr) strcpy
 467 cdecl strcspn(ptr ptr) strcspn
 468 stub strerror
-469 stub strftime
-470 cdecl strlen(ptr) lstrlen32A
-471 cdecl strncat(ptr ptr long) lstrcatn32A
-472 cdecl strncmp(ptr ptr long) lstrncmp32A
-473 cdecl strncpy(ptr ptr long) lstrcpyn32A
-474 stub strpbrk
-475 stub strrchr
+469 cdecl strftime(ptr long ptr ptr) strftime
+470 cdecl strlen(ptr) strlen
+471 cdecl strncat(ptr ptr long) strncat
+472 cdecl strncmp(ptr ptr long) strncmp
+473 cdecl strncpy(ptr ptr long) strncpy
+474 cdecl strpbrk(ptr ptr) strpbrk
+475 cdecl strrchr(ptr long) strrchr
 476 cdecl strspn(ptr ptr) strspn
 477 cdecl strstr(ptr ptr) strstr
 478 stub strtod
 479 cdecl strtok(ptr ptr) strtok
 480 cdecl strtol(ptr ptr long) strtol
 481 cdecl strtoul(ptr ptr long) strtoul
-482 stub strxfrm
+482 cdecl strxfrm(ptr ptr long) strxfrm
 483 stub swprintf
 484 stub swscanf
 485 stub system
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index 4a8e1b5..3fd6b1e 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -149,7 +149,7 @@
 169 stub IsDCDirty
 170 stub SetDCStatus
 172 pascal16 SetRectRgn(word s_word s_word s_word s_word) SetRectRgn
-173 pascal16 GetClipRgn(word) GetClipRgn
+173 pascal16 GetClipRgn(word) GetClipRgn16
 175 pascal16 EnumMetaFile(word word segptr long) THUNK_EnumMetaFile16
 176 pascal16 PlayMetaFileRecord(word ptr ptr word) PlayMetaFileRecord
 179 pascal16 GetDCState(word) GetDCState
@@ -382,7 +382,7 @@
 610 stub GDISignalProc32
 611 stub GetRandomRgn
 612 stub GetTextCharSet
-613 stub EnumFontFamiliesEx
+613 pascal16 EnumFontFamiliesEx(word ptr segptr long long) THUNK_EnumFontFamiliesEx16
 614 stub AddLpkToGDI
 615 stub GetCharacterPlacement
 616 stub GetFontLanguageInfo
diff --git a/if1632/gdi32.spec b/if1632/gdi32.spec
index 6c6853e..c84bf4a 100644
--- a/if1632/gdi32.spec
+++ b/if1632/gdi32.spec
@@ -86,11 +86,11 @@
 0078 stub EndPath
 0079 stub EnumEnhMetaFile
 0080 stdcall EnumFontFamiliesA(long ptr ptr long) THUNK_EnumFontFamilies32A
-0081 stub EnumFontFamiliesExA
-0082 stub EnumFontFamiliesExW
+0081 stdcall EnumFontFamiliesExA(long ptr ptr long long) THUNK_EnumFontFamiliesEx32A
+0082 stdcall EnumFontFamiliesExW(long ptr ptr long long) THUNK_EnumFontFamiliesEx32W
 0083 stdcall EnumFontFamiliesW(long ptr ptr long) THUNK_EnumFontFamilies32W
-0084 stub EnumFontsA
-0085 stub EnumFontsW
+0084 stdcall EnumFontsA(long ptr ptr long) THUNK_EnumFonts32A
+0085 stdcall EnumFontsW(long ptr ptr long) THUNK_EnumFonts32W
 0086 stub EnumICMProfilesA
 0087 stub EnumICMProfilesW
 0088 stub EnumMetaFile
@@ -153,7 +153,7 @@
 0145 stdcall GetBkColor(long) GetBkColor
 0146 stub GetBkMode
 0147 stub GetBoundsRect
-0148 stub GetBrushOrgEx
+0148 stdcall GetBrushOrgEx(long ptr) GetBrushOrgEx32
 0149 stub GetCharABCWidthsA
 0150 stub GetCharABCWidthsFloatA
 0151 stub GetCharABCWidthsFloatW
@@ -168,12 +168,12 @@
 0160 stub GetCharacterPlacementA
 0161 stub GetCharacterPlacementW
 0162 stdcall GetClipBox(long ptr) GetClipBox32
-0163 stub GetClipRgn
+0163 stdcall GetClipRgn(long long) GetClipRgn32
 0164 stub GetColorAdjustment
 0165 stub GetColorSpace
 0166 stub GetCurrentObject
-0167 stub GetCurrentPositionEx
-0168 stub GetDCOrgEx
+0167 stdcall GetCurrentPositionEx(long ptr) GetCurrentPositionEx32
+0168 stdcall GetDCOrgEx(long ptr) GetDCOrgEx
 0169 stub GetDIBColorTable
 0170 stub GetDIBits
 0171 stdcall GetDeviceCaps(long long) GetDeviceCaps
@@ -239,16 +239,16 @@
 0231 stub GetTextExtentPoint32W
 0232 stdcall GetTextExtentPointA(long ptr long ptr) GetTextExtentPoint32A
 0233 stdcall GetTextExtentPointW(long ptr long ptr) GetTextExtentPoint32W
-0234 stub GetTextFaceA
+0234 stdcall GetTextFaceA(long long ptr) GetTextFace
 0235 stub GetTextFaceW
 0236 stdcall GetTextMetricsA(long ptr) GetTextMetrics32A
 0237 stdcall GetTextMetricsW(long ptr) GetTextMetrics32W
 0238 stub GetTransform
-0239 stub GetViewportExtEx
-0240 stub GetViewportOrgEx
+0239 stdcall GetViewportExtEx(long ptr) GetViewportExtEx32
+0240 stdcall GetViewportOrgEx(long ptr) GetViewportOrgEx32
 0241 stub GetWinMetaFileBits
-0242 stub GetWindowExtEx
-0243 stub GetWindowOrgEx
+0242 stdcall GetWindowExtEx(long ptr) GetWindowExtEx32
+0243 stdcall GetWindowOrgEx(long ptr) GetWindowOrgEx32
 0244 stub GetWorldTransform
 0245 stdcall IntersectClipRect(long long long long long) IntersectClipRect32
 0246 stdcall InvertRgn(long long) InvertRgn32
@@ -328,7 +328,7 @@
 0319 stub SetICMProfileA
 0320 stub SetICMProfileW
 0321 stdcall SetMapMode(long long) SetMapMode
-0322 stub SetMapperFlags
+0322 stdcall SetMapperFlags(long long) SetMapperFlags
 0323 stub SetMetaFileBitsEx
 0324 stub SetMetaRgn
 0325 stub SetMiterLimit
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 9b2c4c9..eb3fd29 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -53,9 +53,9 @@
 54  pascal16 GetInstanceData(word word word) GetInstanceData
 55  pascal16 Catch(ptr) Catch 
 56  pascal16 Throw(ptr word) Throw
-57  pascal16 GetProfileInt(ptr ptr s_word) GetProfileInt
-58  pascal16 GetProfileString(ptr ptr ptr ptr word) GetProfileString
-59  pascal16 WriteProfileString(ptr ptr ptr) WriteProfileString
+57  pascal16 GetProfileInt(ptr ptr s_word) GetProfileInt16
+58  pascal16 GetProfileString(ptr ptr ptr ptr word) GetProfileString16
+59  pascal16 WriteProfileString(ptr ptr ptr) WriteProfileString16
 60  pascal16 FindResource(word segptr segptr) FindResource16
 61  pascal16 LoadResource(word word) LoadResource16
 62  pascal LockResource(word) WIN16_LockResource16
@@ -123,11 +123,11 @@
 124 return EnableKernel 0 0
 125 return DisableKernel 0 0
 126 stub MemoryFreed
-127 pascal16 GetPrivateProfileInt(ptr ptr s_word ptr) GetPrivateProfileInt
+127 pascal16 GetPrivateProfileInt(ptr ptr s_word ptr) GetPrivateProfileInt16
 128 pascal16 GetPrivateProfileString(ptr ptr ptr ptr word ptr)
-             GetPrivateProfileString
+             GetPrivateProfileString16
 129 pascal16 WritePrivateProfileString(ptr ptr ptr ptr)
-             WritePrivateProfileString
+             WritePrivateProfileString16
 130 pascal FileCDR(ptr) FileCDR
 131 pascal GetDOSEnvironment() GetDOSEnvironment
 132 pascal GetWinFlags() GetWinFlags
diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec
index ecf6020..9c7501e 100644
--- a/if1632/kernel32.spec
+++ b/if1632/kernel32.spec
@@ -96,8 +96,8 @@
 0091 stub EnumResourceTypesW
 0092 stdcall EnumSystemCodePagesA(ptr long) THUNK_EnumSystemCodePages32A
 0093 stdcall EnumSystemCodePagesW(ptr long) THUNK_EnumSystemCodePages32W
-0094 stub EnumSystemLocalesA
-0095 stub EnumSystemLocalesW
+0094 stdcall EnumSystemLocalesA(ptr long) THUNK_EnumSystemLocales32A
+0095 stdcall EnumSystemLocalesW(ptr long) THUNK_EnumSystemLocales32W
 0096 stub EnumTimeFormatsA
 0097 stub EnumTimeFormatsW
 0098 stub EraseTape
@@ -253,12 +253,12 @@
 0248    stdcall GetOEMCP() GetOEMCP
 0249 stub GetOverlappedResult
 0250 stub GetPriorityClass
-0251 stdcall GetPrivateProfileIntA(ptr ptr long ptr) GetPrivateProfileInt
-0252 stub GetPrivateProfileIntW
+0251 stdcall GetPrivateProfileIntA(ptr ptr long ptr) GetPrivateProfileInt32A
+0252 stdcall GetPrivateProfileIntW(ptr ptr long ptr) GetPrivateProfileInt32W
 0253 stub GetPrivateProfileSectionA
 0254 stub GetPrivateProfileSectionW
-0255 stdcall GetPrivateProfileStringA(ptr ptr ptr ptr long ptr) GetPrivateProfileString
-0256 stub GetPrivateProfileStringW
+0255 stdcall GetPrivateProfileStringA(ptr ptr ptr ptr long ptr) GetPrivateProfileString32A
+0256 stdcall GetPrivateProfileStringW(ptr ptr ptr ptr long ptr) GetPrivateProfileString32W
 0257 stdcall GetProcAddress(long ptr) GetProcAddress32
 0258 stdcall GetProcessAffinityMask(long ptr ptr)	GetProcessAffinityMask
 0259 stdcall GetProcessHeap() GetProcessHeap
@@ -266,12 +266,12 @@
 0261 stub GetProcessShutdownParameters
 0262 stub GetProcessTimes
 0263 stub GetProcessWorkingSetSize
-0264 	stdcall GetProfileIntA(ptr ptr long) GetProfileInt
-0265 stub GetProfileIntW
+0264 stdcall GetProfileIntA(ptr ptr long) GetProfileInt32A
+0265 stdcall GetProfileIntW(ptr ptr long) GetProfileInt32W
 0266 stub GetProfileSectionA
 0267 stub GetProfileSectionW
-0268 stdcall GetProfileStringA(ptr ptr ptr ptr long) GetProfileString
-0269 stub GetProfileStringW
+0268 stdcall GetProfileStringA(ptr ptr ptr ptr long) GetProfileString32A
+0269 stdcall GetProfileStringW(ptr ptr ptr ptr long) GetProfileString32W
 0270 stub GetQueuedCompletionStatus
 0271 stdcall GetShortPathNameA(ptr ptr long) GetShortPathName32A
 0272 stdcall GetShortPathNameW(ptr ptr long) GetShortPathName32W
@@ -542,7 +542,7 @@
 0537    stdcall UnhandledExceptionFilter(ptr) UnhandledExceptionFilter
 0538 stub UnlockFile
 0539 stub UnlockFileEx
-0540 stub UnmapViewOfFile
+0540 stdcall UnmapViewOfFile(ptr) UnmapViewOfFile
 0541 stub UpdateResourceA
 0542 stub UpdateResourceW
 0543 stub VDMConsoleOperation
@@ -584,13 +584,13 @@
 0579 stub WriteFileEx
 0580 stub WritePrivateProfileSectionA
 0581 stub WritePrivateProfileSectionW
-0582 stdcall WritePrivateProfileStringA(ptr ptr ptr ptr)	WritePrivateProfileString
-0583 stub WritePrivateProfileStringW
+0582 stdcall WritePrivateProfileStringA(ptr ptr ptr ptr) WritePrivateProfileString32A
+0583 stdcall WritePrivateProfileStringW(ptr ptr ptr ptr) WritePrivateProfileString32W
 0584 stub WriteProcessMemory
 0585 stub WriteProfileSectionA
 0586 stub WriteProfileSectionW
-0587 stdcall WriteProfileStringA(ptr ptr ptr)	WriteProfileString
-0588 stub WriteProfileStringW
+0587 stdcall WriteProfileStringA(ptr ptr ptr) WriteProfileString32A
+0588 stdcall WriteProfileStringW(ptr ptr ptr) WriteProfileString32W
 0589 stub WriteTapemark
 0590 stdcall _hread(long ptr long) _hread
 0591 stdcall _hwrite(long ptr long) _hwrite
diff --git a/if1632/thunk.c b/if1632/thunk.c
index 348606f..5da3982 100644
--- a/if1632/thunk.c
+++ b/if1632/thunk.c
@@ -117,9 +117,28 @@
                          FONTENUMPROC16 func, LPARAM lParam )
 {
     DECL_THUNK( thunk, func, CallTo16_word_llwl );
-    return EnumFonts( hdc, lpFaceName, (FONTENUMPROC16)&thunk, lParam );
+    return EnumFonts16( hdc, lpFaceName, (FONTENUMPROC16)&thunk, lParam );
 }
 
+/*************************************************************************
+ *           THUNK_EnumFonts32A   (GDI32.84)
+ */
+INT32 THUNK_EnumFonts32A( HDC32 hdc, LPCSTR lpFaceName,
+                          FONTENUMPROC32A func, LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo32_4 );
+    return EnumFonts32A( hdc, lpFaceName, (FONTENUMPROC32A)&thunk, lParam );
+}
+
+/*************************************************************************
+ *           THUNK_EnumFonts32W   (GDI32.85)
+ */
+INT32 THUNK_EnumFonts32W( HDC32 hdc, LPCWSTR lpFaceName,
+                          FONTENUMPROC32W func, LPARAM lParam )
+{
+    DECL_THUNK( thunk, func, CallTo32_4 );
+    return EnumFonts32W( hdc, lpFaceName, (FONTENUMPROC32W)&thunk, lParam );
+}
 
 /******************************************************************
  *           THUNK_EnumMetaFile16   (GDI.175)
@@ -164,6 +183,44 @@
     return EnumFontFamilies32W(hdc,lpszFamily,(FONTENUMPROC32W)&thunk,lParam);
 }
 
+/*************************************************************************
+ *           THUNK_EnumFontFamiliesEx16   (GDI.613)
+ */
+INT16 THUNK_EnumFontFamiliesEx16( HDC16 hdc, LPLOGFONT16 lpLF,
+                                  FONTENUMPROCEX16 func, LPARAM lParam,
+                                  DWORD reserved )
+{
+    DECL_THUNK( thunk, func, CallTo16_word_llwl );
+    return EnumFontFamiliesEx16( hdc, lpLF, (FONTENUMPROCEX16)&thunk,
+                                 lParam, reserved );
+}
+
+
+/*************************************************************************
+ *           THUNK_EnumFontFamiliesEx32A   (GDI32.81)
+ */
+INT32 THUNK_EnumFontFamiliesEx32A( HDC32 hdc, LPLOGFONT32A lpLF,
+                                   FONTENUMPROCEX32A func, LPARAM lParam,
+                                   DWORD reserved)
+{
+    DECL_THUNK( thunk, func, CallTo32_4 );
+    return EnumFontFamiliesEx32A( hdc, lpLF, (FONTENUMPROCEX32A)&thunk,
+                                  lParam, reserved );
+}
+
+
+/*************************************************************************
+ *           THUNK_EnumFontFamiliesEx32W   (GDI32.82)
+ */
+INT32 THUNK_EnumFontFamiliesEx32W( HDC32 hdc, LPLOGFONT32W lpLF,
+                                   FONTENUMPROCEX32W func, LPARAM lParam,
+                                   DWORD reserved )
+{
+    DECL_THUNK( thunk, func, CallTo32_4 );
+    return EnumFontFamiliesEx32W( hdc, lpLF, (FONTENUMPROCEX32W)&thunk,
+                                  lParam, reserved );
+}
+
 
 /**********************************************************************
  *           THUNK_LineDDA16   (GDI.100)
@@ -320,6 +377,25 @@
     return EnumSystemCodePages32W( (CODEPAGE_ENUMPROC32W)&thunk, flags );
 }
 
+/***********************************************************************
+ *           THUNK_EnumSystemLocales32A   (KERNEL32.92)
+ */
+BOOL32 THUNK_EnumSystemLocales32A( LOCALE_ENUMPROC32A func, DWORD flags )
+{
+    DECL_THUNK( thunk, func, CallTo32_1 );
+    return EnumSystemLocales32A( (LOCALE_ENUMPROC32A)&thunk, flags );
+}
+
+
+/***********************************************************************
+ *           THUNK_EnumSystemLocales32W   (KERNEL32.93)
+ */
+BOOL32 THUNK_EnumSystemLocales32W( LOCALE_ENUMPROC32W func, DWORD flags )
+{
+    DECL_THUNK( thunk, func, CallTo32_1 );
+    return EnumSystemLocales32W( (LOCALE_ENUMPROC32W)&thunk, flags );
+}
+
 
 /***********************************************************************
  *           THUNK_GrayString16   (USER.185)
diff --git a/if1632/user.spec b/if1632/user.spec
index 2ca9abf..20ab847 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -99,7 +99,7 @@
 97  pascal16 CheckDlgButton(word word word) CheckDlgButton
 98  pascal16 IsDlgButtonChecked(word word) IsDlgButtonChecked
 99  pascal16 DlgDirSelect(word ptr word) DlgDirSelect
-100 pascal16 DlgDirList(word segptr word word word) DlgDirList
+100 pascal16 DlgDirList(word ptr word word word) DlgDirList16
 101 pascal   SendDlgItemMessage(word word word word long) SendDlgItemMessage16
 102 pascal16 AdjustWindowRect(ptr long word) AdjustWindowRect16
 103 pascal16 MapDialogRect(word ptr) MapDialogRect16
@@ -194,7 +194,7 @@
 192 pascal16 InSendMessage() InSendMessage
 193 pascal16 IsClipboardFormatAvailable(word) IsClipboardFormatAvailable
 194 pascal16 DlgDirSelectComboBox(word ptr word) DlgDirSelectComboBox
-195 pascal16 DlgDirListComboBox(word segptr word word word) DlgDirListComboBox16
+195 pascal16 DlgDirListComboBox(word ptr word word word) DlgDirListComboBox16
 196 pascal   TabbedTextOut(word s_word s_word ptr s_word s_word ptr s_word)
              TabbedTextOut
 197 pascal   GetTabbedTextExtent(word ptr word word ptr) GetTabbedTextExtent
diff --git a/if1632/user32.spec b/if1632/user32.spec
index 7a484ba..e4c871d 100644
--- a/if1632/user32.spec
+++ b/if1632/user32.spec
@@ -82,7 +82,7 @@
 0077 stub CreateIconIndirect
 0078 stub CreateMDIWindowA
 0079 stub CreateMDIWindowW
-0080 stub CreateMenu
+0080 stdcall CreateMenu() CreateMenu
 0081 stdcall CreatePopupMenu() CreatePopupMenu
 0082 stdcall CreateWindowExA(long ptr ptr long long long long long 
 				long long long ptr) CreateWindowEx32A
@@ -146,10 +146,10 @@
 0139 stdcall DialogBoxParamW(long ptr long ptr long) DialogBoxParam32W
 0140 stdcall DispatchMessageA(ptr) USER32_DispatchMessageA
 0141 stdcall DispatchMessageW(ptr) USER32_DispatchMessageA
-0142 stub DlgDirListA
+0142 stdcall DlgDirListA(long ptr long long long) DlgDirList32A
 0143 stdcall DlgDirListComboBoxA(long ptr long long long) DlgDirListComboBox32A
 0144 stdcall DlgDirListComboBoxW(long ptr long long long) DlgDirListComboBox32W
-0145 stub DlgDirListW
+0145 stdcall DlgDirListW(long ptr long long long) DlgDirList32W
 0146 stdcall DlgDirSelectComboBoxExA(long ptr long long) DlgDirSelectComboBoxEx32A
 0147 stdcall DlgDirSelectComboBoxExW(long ptr long long) DlgDirSelectComboBoxEx32W
 0148 stdcall DlgDirSelectExA(long ptr long long) DlgDirSelectEx32A
@@ -466,7 +466,7 @@
 0459 stub SendNotifyMessageA
 0460 stub SendNotifyMessageW
 0461 stub ServerSetFunctionPointers
-0462 stub SetActiveWindow
+0462 stdcall SetActiveWindow(long) SetActiveWindow
 0463 stdcall SetCapture(long) SetCapture32
 0464 stdcall SetCaretBlinkTime(long) SetCaretBlinkTime
 0465 stdcall SetCaretPos(long long) SetCaretPos
diff --git a/if1632/wing.spec b/if1632/wing.spec
index ec1ab43..f22122e 100644
--- a/if1632/wing.spec
+++ b/if1632/wing.spec
@@ -1,15 +1,16 @@
 name    wing
 type    win16
 
-1001 stub WINGCREATEDC
-1002 stub WINGRECOMMENDDIBFORMAT
-1003 stub WINGCREATEBITMAP
+1001 pascal16 WinGCreateDC() WinGCreateDC16
+1002 pascal16 WinGRecommendDIBFormat(ptr) WinGRecommendDIBFormat16
+1003 pascal16 WinGCreateBitmap(word ptr ptr) WinGCreateBitmap16
 1004 stub WINGGETDIBPOINTER
 1005 stub WINGGETDIBCOLORTABLE
 1006 stub WINGSETDIBCOLORTABLE
-1007 stub WINGCREATEHALFTONEPALETTE
-1008 stub WINGCREATEHALFTONEBRUSH
+1007 pascal16 WinGCreateHalfTonePalette() WinGCreateHalfTonePalette16
+1008 pascal16 WinGCreateHalfToneBrush(word long word) WinGCreateHalfToneBrush16
 1009 stub WINGSTRETCHBLT
+# Probably much like BitBlt16... but, without the last field (what value?)
 1010 stub WINGBITBLT
 
 # Seem that 1299 is the limit... weird...
diff --git a/if1632/winmm.spec b/if1632/winmm.spec
index 5707803..44a0691 100644
--- a/if1632/winmm.spec
+++ b/if1632/winmm.spec
@@ -139,7 +139,7 @@
 0138 stub timeEndPeriod
 0139 stub timeGetDevCaps
 0140 stub timeGetSystemTime
-0141 stub timeGetTime
+0141 stdcall timeGetTime() timeGetTime
 0142 stub timeKillEvent
 0143 stub timeSetEvent
 0144 stub waveInAddBuffer
diff --git a/if1632/winsock.spec b/if1632/winsock.spec
index 5048f83..24d2fc0 100644
--- a/if1632/winsock.spec
+++ b/if1632/winsock.spec
@@ -37,17 +37,17 @@
 56  pascal   getservbyport(word ptr) WINSOCK_getservbyport
 57  pascal   gethostname(ptr word) WINSOCK_gethostname
 101 pascal16 WSAAsyncSelect(word word word long) WSAAsyncSelect
-102 pascal16 WSAAsyncGetHostByAddr(word word ptr word word ptr word)
+102 pascal16 WSAAsyncGetHostByAddr(word word ptr word word segptr word)
              WSAAsyncGetHostByAddr
-103 pascal16 WSAAsyncGetHostByName(word word ptr ptr word)
+103 pascal16 WSAAsyncGetHostByName(word word ptr segptr word)
              WSAAsyncGetHostByName
-104 pascal16 WSAAsyncGetProtoByNumber(word word word ptr word)
+104 pascal16 WSAAsyncGetProtoByNumber(word word word segptr word)
              WSAAsyncGetProtoByNumber
-105 pascal16 WSAAsyncGetProtoByName(word word ptr ptr word)
+105 pascal16 WSAAsyncGetProtoByName(word word ptr segptr word)
              WSAAsyncGetProtoByName
-106 pascal16 WSAAsyncGetServByPort(word word word ptr ptr word)
+106 pascal16 WSAAsyncGetServByPort(word word word ptr segptr word)
              WSAAsyncGetServByPort
-107 pascal16 WSAAsyncGetServByName(word word ptr ptr ptr word)
+107 pascal16 WSAAsyncGetServByName(word word ptr ptr segptr word)
              WSAAsyncGetServByName
 108 pascal16 WSACancelAsyncRequest(word) WSACancelAsyncRequest
 109 pascal16 WSASetBlockingHook() WSASetBlockingHook
@@ -58,4 +58,4 @@
 114 pascal16 WSAIsBlocking() WSAIsBlocking
 115 pascal   WSAStartup(word ptr) WSAStartup
 116 pascal   WSACleanup() WSACleanup
-151 pascal16 __WSAFDIsSet(word ptr) WSAFDIsSet
+151 pascal16 __WSAFDIsSet(word ptr) __WSAFDIsSet
diff --git a/if1632/wprocs.spec b/if1632/wprocs.spec
index 07d63e7..3522fec 100644
--- a/if1632/wprocs.spec
+++ b/if1632/wprocs.spec
@@ -4,7 +4,6 @@
 1  pascal WINPROC_CallProc16To32A(word word word long long) WINPROC_CallProc16To32A
 2  pascal StaticWndProc(word word word long) StaticWndProc
 3  pascal ScrollBarWndProc(word word word long) ScrollBarWndProc
-4  pascal ListBoxWndProc(word word word long) ListBoxWndProc
 5  pascal ComboBoxWndProc(word word word long) ComboBoxWndProc
 6  pascal EditWndProc(word word word long) EditWndProc
 7  pascal PopupMenuWndProc(word word word long) PopupMenuWndProc
diff --git a/include/config.h.in b/include/config.h.in
index 638652a..cf00d28 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -3,9 +3,6 @@
 /* Define to empty if the keyword does not work.  */
 #undef const
 
-/* Define if you need to in order for stat and other things to work.  */
-#undef _POSIX_SOURCE
-
 /* Define to `unsigned' if <sys/types.h> doesn't define.  */
 #undef size_t
 
@@ -15,6 +12,9 @@
 /* Define if you have the ANSI C header files.  */
 #undef STDC_HEADERS
 
+/* Define if the X Window System is missing or not being used.  */
+#undef X_DISPLAY_MISSING
+
 /* Define if symbols declared in assembly code need an underscore prefix */
 #undef NEED_UNDERSCORE_PREFIX
 
diff --git a/include/dce.h b/include/dce.h
index 06ff062..b21ec2a 100644
--- a/include/dce.h
+++ b/include/dce.h
@@ -8,6 +8,7 @@
 #define DCE_H
 
 #include "windows.h"
+#include "win.h"
 
 /* additional DCX flags 
  */
@@ -44,8 +45,9 @@
 } DCE;
 
 
-extern void DCE_Init(void);
-extern DCE *DCE_AllocDCE( HWND32 hWnd, DCE_TYPE type );
-extern void DCE_FreeDCE( DCE *dce );
+extern void  DCE_Init(void);
+extern DCE*  DCE_AllocDCE( HWND32 hWnd, DCE_TYPE type );
+extern void  DCE_FreeDCE( DCE *dce );
+extern INT16 DCE_ExcludeRgn( HDC32, WND*, HRGN32 );
 
 #endif  /* DCE_H */
diff --git a/include/hook.h b/include/hook.h
index 535afc2..2a9857b 100644
--- a/include/hook.h
+++ b/include/hook.h
@@ -13,6 +13,7 @@
 extern LRESULT HOOK_CallHooks( INT16 id, INT16 code,
                                WPARAM16 wParam, LPARAM lParam );
 extern HOOKPROC16 HOOK_GetProc16( HHOOK hook );
+extern void HOOK_ResetQueueHooks( HQUEUE16 hQueue );
 extern void HOOK_FreeModuleHooks( HMODULE16 hModule );
 extern void HOOK_FreeQueueHooks( HQUEUE16 hQueue );
 
diff --git a/include/keyboard.h b/include/keyboard.h
new file mode 100644
index 0000000..95f681c
--- /dev/null
+++ b/include/keyboard.h
@@ -0,0 +1,32 @@
+/*
+ * Keyboard definitions
+ *
+ */
+
+#ifndef __WINE_KEYBOARD_H
+#define __WINE_KEYBOARD_H
+
+#define WINE_VKEY_MAPPINGS\
+		vkcase('!', '1')\
+		vkcase('@', '2')\
+		vkcase('#', '3')\
+		vkcase('$', '4')\
+		vkcase('%', '5')\
+		vkcase('^', '6')\
+		vkcase('&', '7')\
+		vkcase('*', '8')\
+		vkcase('(', '9')\
+		vkcase(')', '0')\
+		vkcase2('`', '~', 0xc0)\
+		vkcase2('-', '_', 0xbd)\
+		vkcase2('=', '+', 0xbb)\
+		vkcase2('[', '{', 0xdb)\
+		vkcase2(']', '}', 0xdd)\
+		vkcase2(';', ':', 0xba)\
+		vkcase2('\'', '"', 0xde)\
+		vkcase2(',', '<', 0xbc)\
+		vkcase2('.', '>', 0xbe)\
+		vkcase2('/', '?', 0xbf)\
+		vkcase2('\\', '|', 0xdc)
+
+#endif  /* __WINE_KEYBOARD_H */
diff --git a/include/listbox.h b/include/listbox.h
index 3cfe426..ebee813 100644
--- a/include/listbox.h
+++ b/include/listbox.h
@@ -69,5 +69,3 @@
 			     WORD itemState);
 extern int ListBoxFindMouse(LPHEADLIST lphl, int X, int Y);
 extern void ListBoxAskMeasure(LPHEADLIST lphl, LPLISTSTRUCT lpls);
-
-extern LRESULT ListBoxWndProc(HWND hwnd,UINT message,WPARAM16 wParam,LPARAM lParam);
diff --git a/include/win.h b/include/win.h
index 18c3321..445ee3b 100644
--- a/include/win.h
+++ b/include/win.h
@@ -92,7 +92,7 @@
 extern HWND32 WIN_FindWinToRepaint( HWND32 hwnd, HQUEUE16 hQueue );
 extern void WIN_SendParentNotify( HWND32 hwnd, WORD event,
                                   WORD idChild, LPARAM lValue );
-extern void WIN_DestroyQueueWindows( WND* wnd, HQUEUE16 hQueue );
+extern void WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew );
 extern BOOL32 WIN_CreateDesktopWindow(void);
 extern HWND32 WIN_GetTopParent( HWND32 hwnd );
 extern BOOL32 WIN_IsWindowDrawable(WND*, BOOL32 );
diff --git a/include/windows.h b/include/windows.h
index 8e03f49..2cf3596 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -920,8 +920,40 @@
   WCHAR      elfStyle[LF_FACESIZE] WINE_PACKED;
 } ENUMLOGFONT32W, *LPENUMLOGFONT32W;
 
+typedef struct
+{
+  LOGFONT16  elfLogFont;
+  BYTE       elfFullName[LF_FULLFACESIZE] WINE_PACKED;
+  BYTE       elfStyle[LF_FACESIZE] WINE_PACKED;
+  BYTE       elfScript[LF_FACESIZE] WINE_PACKED;
+} ENUMLOGFONTEX16, *LPENUMLOGFONTEX16;
+
+typedef struct
+{
+  LOGFONT32A elfLogFont;
+  BYTE       elfFullName[LF_FULLFACESIZE] WINE_PACKED;
+  BYTE       elfStyle[LF_FACESIZE] WINE_PACKED;
+  BYTE       elfScript[LF_FACESIZE] WINE_PACKED;
+} ENUMLOGFONTEX32A,*LPENUMLOGFONTEX32A;
+
+typedef struct
+{
+  LOGFONT32W elfLogFont;
+  WCHAR      elfFullName[LF_FULLFACESIZE] WINE_PACKED;
+  WCHAR      elfStyle[LF_FACESIZE] WINE_PACKED;
+  WCHAR      elfScript[LF_FACESIZE] WINE_PACKED;
+} ENUMLOGFONTEX32W,*LPENUMLOGFONTEX32W;
+
 DECL_WINELIB_TYPE_AW(ENUMLOGFONT);
 DECL_WINELIB_TYPE_AW(LPENUMLOGFONT);
+DECL_WINELIB_TYPE_AW(LPENUMLOGFONTEX);
+
+typedef struct
+{
+  DWORD fsUsb[4];
+  DWORD fsCsb[2];
+} FONTSIGNATURE,*LPFONTSIGNATURE;
+
 
   /* lfWeight values */
 #define FW_DONTCARE	    0
@@ -1057,11 +1089,130 @@
 DECL_WINELIB_TYPE_AW(TEXTMETRIC);
 DECL_WINELIB_TYPE_AW(LPTEXTMETRIC);
 
+/* ntmFlags field flags */
+#define NTM_REGULAR     0x00000040L
+#define NTM_BOLD        0x00000020L
+#define NTM_ITALIC      0x00000001L
+
+typedef struct
+{
+    INT16     tmHeight;
+    INT16     tmAscent;
+    INT16     tmDescent;
+    INT16     tmInternalLeading;
+    INT16     tmExternalLeading;
+    INT16     tmAveCharWidth;
+    INT16     tmMaxCharWidth;
+    INT16     tmWeight;
+    BYTE      tmItalic;
+    BYTE      tmUnderlined;
+    BYTE      tmStruckOut;
+    BYTE      tmFirstChar;
+    BYTE      tmLastChar;
+    BYTE      tmDefaultChar;
+    BYTE      tmBreakChar;
+    BYTE      tmPitchAndFamily;
+    BYTE      tmCharSet;
+    INT16     tmOverhang WINE_PACKED;
+    INT16     tmDigitizedAspectX WINE_PACKED;
+    INT16     tmDigitizedAspectY WINE_PACKED;
+    DWORD     ntmFlags;
+    UINT16    ntmSizeEM;
+    UINT16    ntmCellHeight;
+    UINT16    ntmAvgWidth;
+} NEWTEXTMETRIC16,*LPNEWTEXTMETRIC16;
+
+typedef struct
+{
+    INT32     tmHeight;
+    INT32     tmAscent;
+    INT32     tmDescent;
+    INT32     tmInternalLeading;
+    INT32     tmExternalLeading;
+    INT32     tmAveCharWidth;
+    INT32     tmMaxCharWidth;
+    INT32     tmWeight;
+    INT32     tmOverhang;
+    INT32     tmDigitizedAspectX;
+    INT32     tmDigitizedAspectY;
+    BYTE      tmFirstChar;
+    BYTE      tmLastChar;
+    BYTE      tmDefaultChar;
+    BYTE      tmBreakChar;
+    BYTE      tmItalic;
+    BYTE      tmUnderlined;
+    BYTE      tmStruckOut;
+    BYTE      tmPitchAndFamily;
+    BYTE      tmCharSet;
+    DWORD     ntmFlags;
+    UINT32    ntmSizeEM;
+    UINT32    ntmCellHeight;
+    UINT32    ntmAvgWidth;
+} NEWTEXTMETRIC32A, *LPNEWTEXTMETRIC32A;
+
+typedef struct
+{
+    INT32     tmHeight;
+    INT32     tmAscent;
+    INT32     tmDescent;
+    INT32     tmInternalLeading;
+    INT32     tmExternalLeading;
+    INT32     tmAveCharWidth;
+    INT32     tmMaxCharWidth;
+    INT32     tmWeight;
+    INT32     tmOverhang;
+    INT32     tmDigitizedAspectX;
+    INT32     tmDigitizedAspectY;
+    WCHAR     tmFirstChar;
+    WCHAR     tmLastChar;
+    WCHAR     tmDefaultChar;
+    WCHAR     tmBreakChar;
+    BYTE      tmItalic;
+    BYTE      tmUnderlined;
+    BYTE      tmStruckOut;
+    BYTE      tmPitchAndFamily;
+    BYTE      tmCharSet;
+    DWORD     ntmFlags;
+    UINT32    ntmSizeEM;
+    UINT32    ntmCellHeight;
+    UINT32    ntmAvgWidth;
+} NEWTEXTMETRIC32W, *LPNEWTEXTMETRIC32W;
+
+DECL_WINELIB_TYPE_AW(NEWTEXTMETRIC);
+DECL_WINELIB_TYPE_AW(LPNEWTEXTMETRIC);
+
+typedef struct
+{
+    NEWTEXTMETRIC16	ntmetm;
+    FONTSIGNATURE       ntmeFontSignature;
+} NEWTEXTMETRICEX16,*LPNEWTEXTMETRICEX16;
+
+typedef struct
+{
+    NEWTEXTMETRIC32A	ntmetm;
+    FONTSIGNATURE       ntmeFontSignature;
+} NEWTEXTMETRICEX32A,*LPNEWTEXTMETRICEX32A;
+
+typedef struct
+{
+    NEWTEXTMETRIC32W	ntmetm;
+    FONTSIGNATURE       ntmeFontSignature;
+} NEWTEXTMETRICEX32W,*LPNEWTEXTMETRICEX32W;
+
+DECL_WINELIB_TYPE_AW(NEWTEXTMETRICEX);
+DECL_WINELIB_TYPE_AW(LPNEWTEXTMETRICEX);
+
+
 typedef INT16 (*FONTENUMPROC16)(SEGPTR,SEGPTR,UINT16,LPARAM);
-typedef INT32 (*FONTENUMPROC32A)(const LOGFONT32A*,const TEXTMETRIC32A*,UINT32,LPARAM);
-typedef INT32 (*FONTENUMPROC32W)(const LOGFONT32W*,const TEXTMETRIC32W*,UINT32,LPARAM);
+typedef INT32 (*FONTENUMPROC32A)(LPENUMLOGFONT32A,LPNEWTEXTMETRIC32A,UINT32,LPARAM);
+typedef INT32 (*FONTENUMPROC32W)(LPENUMLOGFONT32W,LPNEWTEXTMETRIC32W,UINT32,LPARAM);
 DECL_WINELIB_TYPE_AW(FONTENUMPROC);
 
+typedef INT16 (*FONTENUMPROCEX16)(SEGPTR,SEGPTR,UINT16,LPARAM);
+typedef INT32 (*FONTENUMPROCEX32A)(LPENUMLOGFONTEX32A,LPNEWTEXTMETRICEX32A,UINT32,LPARAM);
+typedef INT32 (*FONTENUMPROCEX32W)(LPENUMLOGFONTEX32W,LPNEWTEXTMETRICEX32W,UINT32,LPARAM);
+DECL_WINELIB_TYPE_AW(FONTENUMPROCEX);
+
   /* tmPitchAndFamily values */
 #define TMPF_FIXED_PITCH    1
 #define TMPF_VECTOR	    2
@@ -2724,7 +2875,12 @@
 #define LB_FINDSTRINGEXACT16     (WM_USER+35)
 #define LB_FINDSTRINGEXACT32     0x01a2
 #define LB_FINDSTRINGEXACT       WINELIB_NAME(LB_FINDSTRINGEXACT)
-/* Here are 2 undocumented messages used by ComboLBoxes */
+#define LB_CARETON16             (WM_USER+36)
+#define LB_CARETON32             0x01a3
+#define LB_CARETON               WINELIB_NAME(LB_CARETON)
+#define LB_CARETOFF16            (WM_USER+37)
+#define LB_CARETOFF32            0x01a4
+#define LB_CARETOFF              WINELIB_NAME(LB_CARETOFF)
 #define LB_SETLOCALE16           WM_NULL  /* Not in Win16 */
 #define LB_SETLOCALE32           0x01a5
 #define LB_SETLOCALE             WINELIB_NAME(LB_SETLOCALE)
@@ -3088,16 +3244,22 @@
 #define VK_RBUTTON          0x02
 #define VK_CANCEL           0x03
 #define VK_MBUTTON          0x04
+/*                          0x05-0x07  Undefined */
 #define VK_BACK             0x08
 #define VK_TAB              0x09
+/*                          0x0A-0x0B  Undefined */
 #define VK_CLEAR            0x0C
 #define VK_RETURN           0x0D
+/*                          0x0E-0x0F  Undefined */
 #define VK_SHIFT            0x10
 #define VK_CONTROL          0x11
 #define VK_MENU             0x12
 #define VK_PAUSE            0x13
 #define VK_CAPITAL          0x14
+/*                          0x15-0x19  Reserved for Kanji systems */
+/*                          0x1A       Undefined */
 #define VK_ESCAPE           0x1B
+/*                          0x1C-0x1F  Reserved for Kanji systems */
 #define VK_SPACE            0x20
 #define VK_PRIOR            0x21
 #define VK_NEXT             0x22
@@ -3108,12 +3270,50 @@
 #define VK_RIGHT            0x27
 #define VK_DOWN             0x28
 #define VK_SELECT           0x29
-#define VK_PRINT            0x2A
+#define VK_PRINT            0x2A /* OEM specific in Windows 3.1 SDK */
 #define VK_EXECUTE          0x2B
 #define VK_SNAPSHOT         0x2C
 #define VK_INSERT           0x2D
 #define VK_DELETE           0x2E
 #define VK_HELP             0x2F
+#define VK_0                0x30
+#define VK_1                0x31
+#define VK_2                0x32
+#define VK_3                0x33
+#define VK_4                0x34
+#define VK_5                0x35
+#define VK_6                0x36
+#define VK_7                0x37
+#define VK_8                0x38
+#define VK_9                0x39
+/*                          0x3A-0x40  Undefined */
+#define VK_A                0x41
+#define VK_B                0x42
+#define VK_C                0x43
+#define VK_D                0x44
+#define VK_E                0x45
+#define VK_F                0x46
+#define VK_G                0x47
+#define VK_H                0x48
+#define VK_I                0x49
+#define VK_J                0x4A
+#define VK_K                0x4B
+#define VK_L                0x4C
+#define VK_M                0x4D
+#define VK_N                0x4E
+#define VK_O                0x4F
+#define VK_P                0x50
+#define VK_Q                0x51
+#define VK_R                0x52
+#define VK_S                0x53
+#define VK_T                0x54
+#define VK_U                0x55
+#define VK_V                0x56
+#define VK_W                0x57
+#define VK_X                0x58
+#define VK_Y                0x59
+#define VK_Z                0x5A
+/*                          0x5B-0x5F  Undefined */
 #define VK_NUMPAD0          0x60
 #define VK_NUMPAD1          0x61
 #define VK_NUMPAD2          0x62
@@ -3154,8 +3354,18 @@
 #define VK_F22              0x85
 #define VK_F23              0x86
 #define VK_F24              0x87
+/*                          0x88-0x8F  Unassigned */
 #define VK_NUMLOCK          0x90
 #define VK_SCROLL           0x91
+/*                          0x92-0xB9  Unassigned */
+/*                          0xBA-0xC0  OEM specific */
+/*                          0xC1-0xDA  Unassigned */
+/*                          0xDB-0xE4  OEM specific */
+/*                          0xE5       Unassigned */
+/*                          0xE6       OEM specific */
+/*                          0xE7-0xE8  Unassigned */
+/*                          0xE9-0xF5  OEM specific */
+/*                          0xF6-0xFE  Unassigned */
 
   
 #define LMEM_FIXED          0   
@@ -3705,6 +3915,10 @@
 typedef BOOL32 (*CODEPAGE_ENUMPROC32W)(LPWSTR);
 DECL_WINELIB_TYPE_AW(CODEPAGE_ENUMPROC);
 
+typedef BOOL32 (*LOCALE_ENUMPROC32A)(LPSTR);
+typedef BOOL32 (*LOCALE_ENUMPROC32W)(LPWSTR);
+DECL_WINELIB_TYPE_AW(LOCALE_ENUMPROC);
+
 typedef struct tagSYSTEM_INFO
 {
     DWORD   dwOemId;
@@ -3742,10 +3956,6 @@
 VOID       FillWindow(HWND16,HWND16,HDC16,HBRUSH16);
 INT16      FlushComm(INT16,INT16);
 WORD       FreeSelector(WORD);
-void       GlobalFreeAll(HGLOBAL16);
-HGLOBAL16  GlobalLRUNewest(HGLOBAL16);
-HGLOBAL16  GlobalLRUOldest(HGLOBAL16);
-VOID       GlobalNotify(FARPROC16);
 HANDLE16   GetAtomHandle(ATOM);
 DWORD      GetBitmapDimension(HBITMAP16);
 HANDLE16   GetCodeHandle(FARPROC16);
@@ -3755,6 +3965,7 @@
 HANDLE16   GetCurrentPDB(void);
 HTASK16    GetCurrentTask(void);
 DWORD      GetDCHook(HDC16,FARPROC16*);
+DWORD      GetDCOrg(HDC16);
 HWND16     GetDesktopHwnd(void);
 HMODULE16  GetExePtr(HANDLE16);
 WORD       GetExeVersion(void);
@@ -3768,6 +3979,10 @@
 HQUEUE16   GetTaskQueue(HTASK16);
 DWORD      GlobalDOSAlloc(DWORD);
 WORD       GlobalDOSFree(WORD);
+void       GlobalFreeAll(HGLOBAL16);
+HGLOBAL16  GlobalLRUNewest(HGLOBAL16);
+HGLOBAL16  GlobalLRUOldest(HGLOBAL16);
+VOID       GlobalNotify(FARPROC16);
 WORD       GlobalPageLock(HGLOBAL16);
 WORD       GlobalPageUnlock(HGLOBAL16);
 INT16      InitApp(HINSTANCE16);
@@ -3815,6 +4030,7 @@
 VOID       UserYield(void);
 BOOL16     WaitEvent(HTASK16);
 INT16      WriteComm(INT16,LPSTR,INT16);
+VOID       WriteOutProfiles(VOID);
 VOID       hmemcpy(LPVOID,LPCVOID,LONG);
 VOID       Yield(void);
 
@@ -3835,6 +4051,9 @@
 BOOL32     EnumSystemCodePages32A(CODEPAGE_ENUMPROC32A,DWORD);
 BOOL32     EnumSystemCodePages32W(CODEPAGE_ENUMPROC32W,DWORD);
 #define    EnumSystemCodePages WINELIB_NAME_AW(EnumSystemCodePages)
+BOOL32     EnumSystemLocales32A(LOCALE_ENUMPROC32A,DWORD);
+BOOL32     EnumSystemLocales32W(LOCALE_ENUMPROC32W,DWORD);
+#define    EnumSystemLocales WINELIB_NAME_AW(EnumSystemLocales)
 BOOL32     EnumThreadWindows(DWORD,WNDENUMPROC32,LPARAM);
 void       ExitProcess(DWORD);
 BOOL32     FileTimeToDosDateTime(LPFILETIME,LPWORD,LPWORD);
@@ -3848,6 +4067,7 @@
 LPCWSTR    GetCommandLine32W();
 #define    GetCommandLine WINELIB_NAME_AW(GetCommandLine)
 BOOL32     GetCommTimeouts(INT32,LPCOMMTIMEOUTS);
+BOOL32     GetDCOrgEx(HDC32,LPPOINT32);
 DWORD      GetFileInformationByHandle(HFILE,BY_HANDLE_FILE_INFORMATION*);
 DWORD      GetFileSize(HFILE,LPDWORD);
 DWORD      GetFileType(HFILE);
@@ -3873,6 +4093,7 @@
 BOOL32     HeapUnlock(HANDLE32);
 BOOL32     HeapValidate(HANDLE32,DWORD,LPVOID);
 BOOL32     IsWindowUnicode(HWND32);
+BOOL32     IsValidLocale(DWORD,DWORD);
 BOOL32     LocalFileTimeToFileTime(LPFILETIME,LPFILETIME);
 LPVOID     MapViewOfFileEx(HANDLE32,DWORD,DWORD,DWORD,DWORD,DWORD);
 BOOL32     MoveFile32A(LPCSTR,LPCSTR);
@@ -4220,7 +4441,11 @@
 INT32      DialogBoxParam32A(HINSTANCE32,LPCSTR,HWND32,DLGPROC32,LPARAM);
 INT32      DialogBoxParam32W(HINSTANCE32,LPCWSTR,HWND32,DLGPROC32,LPARAM);
 #define    DialogBoxParam WINELIB_NAME_AW(DialogBoxParam)
-INT16      DlgDirListComboBox16(HWND16,SEGPTR,INT16,INT16,UINT16);
+INT16      DlgDirList16(HWND16,LPCSTR,INT16,INT16,UINT16);
+INT32      DlgDirList32A(HWND32,LPCSTR,INT32,INT32,UINT32);
+INT32      DlgDirList32W(HWND32,LPCWSTR,INT32,INT32,UINT32);
+#define    DlgDirList WINELIB_NAME_AW(DlgDirList)
+INT16      DlgDirListComboBox16(HWND16,LPCSTR,INT16,INT16,UINT16);
 INT32      DlgDirListComboBox32A(HWND32,LPCSTR,INT32,INT32,UINT32);
 INT32      DlgDirListComboBox32W(HWND32,LPCWSTR,INT32,INT32,UINT32);
 #define    DlgDirListComboBox WINELIB_NAME_AW(DlgDirListComboBox)
@@ -4264,6 +4489,14 @@
 INT32      EnumFontFamilies32A(HDC32,LPCSTR,FONTENUMPROC32A,LPARAM);
 INT32      EnumFontFamilies32W(HDC32,LPCWSTR,FONTENUMPROC32W,LPARAM);
 #define    EnumFontFamilies WINELIB_NAME_AW(EnumFontFamilies)
+INT16      EnumFontFamiliesEx16(HDC16,LPLOGFONT16,FONTENUMPROCEX16,LPARAM,DWORD);
+INT32      EnumFontFamiliesEx32A(HDC32,LPLOGFONT32A,FONTENUMPROCEX32A,LPARAM,DWORD);
+INT32      EnumFontFamiliesEx32W(HDC32,LPLOGFONT32W,FONTENUMPROCEX32W,LPARAM,DWORD);
+#define    EnumFontFamiliesEx WINELIB_NAME_AW(EnumFontFamiliesEx)
+INT16      EnumFonts16(HDC16,LPCSTR,FONTENUMPROC16,LPARAM);
+INT32      EnumFonts32A(HDC32,LPCSTR,FONTENUMPROC32A,LPARAM);
+INT32      EnumFonts32W(HDC32,LPCWSTR,FONTENUMPROC32W,LPARAM);
+#define    EnumFonts WINELIB_NAME_AW(EnumFonts)
 INT16      EnumObjects16(HDC16,INT16,GOBJENUMPROC16,LPARAM);
 INT32      EnumObjects32(HDC32,INT32,GOBJENUMPROC32,LPARAM);
 #define    EnumObjects WINELIB_NAME(EnumObjects)
@@ -4384,6 +4617,9 @@
 void       GetClipCursor16(LPRECT16);
 void       GetClipCursor32(LPRECT32);
 #define    GetClipCursor WINELIB_NAME(GetClipCursor)
+HRGN16     GetClipRgn16(HDC16);
+INT32      GetClipRgn32(HDC32,HRGN32);
+#define    GetClipRgn WINELIB_NAME(GetClipRgn)
 INT16      GetCommState16(INT16,LPDCB16);
 BOOL32     GetCommState32(INT32,LPDCB32);
 #define    GetCommState WINELIB_NAME(GetCommState)
@@ -4459,9 +4695,25 @@
 COLORREF   GetPixel16(HDC16,INT16,INT16);
 COLORREF   GetPixel32(HDC32,INT32,INT32);
 #define    GetPixel WINELIB_NAME(GetPixel)
+UINT16     GetPrivateProfileInt16(LPCSTR,LPCSTR,INT16,LPCSTR);
+UINT32     GetPrivateProfileInt32A(LPCSTR,LPCSTR,INT32,LPCSTR);
+UINT32     GetPrivateProfileInt32W(LPCWSTR,LPCWSTR,INT32,LPCWSTR);
+#define    GetPrivateProfileInt WINELIB_NAME_AW(GetPrivateProfileInt)
+INT16      GetPrivateProfileString16(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT16,LPCSTR);
+INT32      GetPrivateProfileString32A(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT32,LPCSTR);
+INT32      GetPrivateProfileString32W(LPCWSTR,LPCWSTR,LPCWSTR,LPWSTR,INT32,LPCWSTR);
+#define    GetPrivateProfileString WINELIB_NAME_AW(GetPrivateProfileString)
 FARPROC16  GetProcAddress16(HMODULE16,SEGPTR);
 FARPROC32  GetProcAddress32(HMODULE32,LPCSTR);
 #define    GetProcAddress WINELIB_NAME(GetProcAddress)
+UINT16     GetProfileInt16(LPCSTR,LPCSTR,INT16);
+UINT32     GetProfileInt32A(LPCSTR,LPCSTR,INT32);
+UINT32     GetProfileInt32W(LPCWSTR,LPCWSTR,INT32);
+#define    GetProfileInt WINELIB_NAME_AW(GetProfileInt)
+INT16      GetProfileString16(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT16);
+INT32      GetProfileString32A(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT32);
+INT32      GetProfileString32W(LPCWSTR,LPCWSTR,LPCWSTR,LPWSTR,INT32);
+#define    GetProfileString WINELIB_NAME_AW(GetProfileString)
 HANDLE16   GetProp16(HWND16,LPCSTR);
 HANDLE32   GetProp32A(HWND32,LPCSTR);
 HANDLE32   GetProp32W(HWND32,LPCWSTR);
@@ -5099,6 +5351,14 @@
 HWND16     WindowFromPoint16(POINT16);
 HWND32     WindowFromPoint32(POINT32);
 #define    WindowFromPoint WINELIB_NAME(WindowFromPoint)
+BOOL16     WritePrivateProfileString16(LPCSTR,LPCSTR,LPCSTR,LPCSTR);
+BOOL32     WritePrivateProfileString32A(LPCSTR,LPCSTR,LPCSTR,LPCSTR);
+BOOL32     WritePrivateProfileString32W(LPCWSTR,LPCWSTR,LPCWSTR,LPCWSTR);
+#define    WritePrivateProfileString WINELIB_NAME_AW(WritePrivateProfileString)
+BOOL16     WriteProfileString16(LPCSTR,LPCSTR,LPCSTR);
+BOOL32     WriteProfileString32A(LPCSTR,LPCSTR,LPCSTR);
+BOOL32     WriteProfileString32W(LPCWSTR,LPCWSTR,LPCWSTR);
+#define    WriteProfileString WINELIB_NAME_AW(WriteProfileString)
 SEGPTR     lstrcat16(SEGPTR,SEGPTR);
 LPSTR      lstrcat32A(LPSTR,LPCSTR);
 LPWSTR     lstrcat32W(LPWSTR,LPCWSTR);
@@ -5238,7 +5498,6 @@
 BOOL       DestroyMenu(HMENU16);
 BOOL       DestroyWindow(HWND);
 LONG       DispatchMessage(const MSG16*);
-INT        DlgDirList(HWND,SEGPTR,INT,INT,UINT);
 BOOL16     DragDetect(HWND16,POINT16);
 DWORD      DragObject(HWND, HWND, WORD, HANDLE16, WORD, HCURSOR16);
 BOOL       DrawIcon(HDC16,INT,INT,HICON16);
@@ -5249,7 +5508,6 @@
 BOOL       EnableWindow(HWND,BOOL);
 BOOL       EndDeferWindowPos(HDWP16);
 UINT16     EnumClipboardFormats(UINT16);
-INT        EnumFonts(HDC16,LPCSTR,FONTENUMPROC16,LPARAM);
 BOOL       EnumMetaFile(HDC16,HMETAFILE16,MFENUMPROC16,LPARAM);
 INT        Escape(HDC16,INT,INT,SEGPTR,SEGPTR);
 BOOL       ExitWindows(DWORD,WORD);
@@ -5271,7 +5529,6 @@
 DWORD      GetBrushOrg(HDC16);
 BOOL       GetCharABCWidths(HDC16,UINT,UINT,LPABC16);
 BOOL       GetCharWidth(HDC16,WORD,WORD,LPINT16);
-HRGN32     GetClipRgn(HDC16);
 HANDLE16   GetClipboardData(WORD);
 int        GetClipboardFormatName(WORD,LPSTR,short);
 HWND       GetClipboardOwner(void);
@@ -5280,7 +5537,6 @@
 DWORD      GetCurrentPosition(HDC16);
 DWORD      GetCurrentTime(void);
 HCURSOR16  GetCursor(void);
-DWORD      GetDCOrg(HDC16);
 HDC16      GetDCState(HDC16);
 int        GetDIBits(HDC16,HBITMAP16,WORD,WORD,LPSTR,LPBITMAPINFO,WORD);
 SEGPTR     GetDOSEnvironment(void);
@@ -5323,10 +5579,6 @@
 WORD       GetPaletteEntries(HPALETTE16,WORD,WORD,LPPALETTEENTRY);
 WORD       GetPolyFillMode(HDC16);
 int        GetPriorityClipboardFormat(WORD*,short);
-UINT       GetPrivateProfileInt(LPCSTR,LPCSTR,INT,LPCSTR);
-INT        GetPrivateProfileString(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT,LPCSTR);
-UINT       GetProfileInt(LPCSTR,LPCSTR,INT);
-INT        GetProfileString(LPCSTR,LPCSTR,LPCSTR,LPSTR,INT);
 DWORD      GetQueueStatus(UINT);
 BOOL       GetRasterizerCaps(LPRASTERIZER_STATUS,UINT);
 WORD       GetROP2(HDC16);
@@ -5484,9 +5736,6 @@
 int        WaitSoundState(int);
 HINSTANCE16 WinExec(LPSTR,WORD);
 BOOL       WinHelp(HWND,LPSTR,WORD,DWORD);
-void       WriteOutProfiles(void);
-BOOL       WritePrivateProfileString(LPCSTR,LPCSTR,LPCSTR,LPCSTR);
-BOOL       WriteProfileString(LPCSTR,LPCSTR,LPCSTR);
 
 #endif  /* NO_TRANSITION_TYPES */
 
diff --git a/include/winnls.h b/include/winnls.h
index 6791fd3..04c92d4 100644
--- a/include/winnls.h
+++ b/include/winnls.h
@@ -1,6 +1,9 @@
 #ifndef __WINE_WINNLS_H
 #define __WINE_WINNLS_H
 
+/* When adding new defines, don't forget to add an entry to the
+ * locale2id map in misc/ole2nls.c
+ */
 #define LOCALE_ILANGUAGE            0x00000001   
 #define LOCALE_SLANGUAGE            0x00000002   
 #define LOCALE_SENGLANGUAGE         0x00001001   
diff --git a/include/winproc.h b/include/winproc.h
index f5ce4f5..1a5ba11 100644
--- a/include/winproc.h
+++ b/include/winproc.h
@@ -50,9 +50,9 @@
                                      LPARAM lParam );
 extern void WINPROC_UnmapMsg16To32W( UINT32 msg, WPARAM32 wParam,
                                      LPARAM lParam );
-extern void WINPROC_UnmapMsg32ATo16( UINT16 msg, WPARAM16 wParam,
+extern void WINPROC_UnmapMsg32ATo16( UINT32 msg, WPARAM16 wParam,
                                      LPARAM lParam );
-extern void WINPROC_UnmapMsg32WTo16( UINT16 msg, WPARAM16 wParam,
+extern void WINPROC_UnmapMsg32WTo16( UINT32 msg, WPARAM16 wParam,
                                      LPARAM lParam );
 
 #endif  /* __WINE_WINPROC_H */
diff --git a/include/winsock.h b/include/winsock.h
index 9548229..9119c01 100644
--- a/include/winsock.h
+++ b/include/winsock.h
@@ -16,26 +16,112 @@
 #include <sys/socket.h>
 #include "windows.h"
 
-/*
- * The new type to be used in all
- * instances which refer to sockets.
- */
-typedef u_int	SOCKET;
-
-extern int __WSAFDIsSet(SOCKET, fd_set *);
-
-/*
- * Internet address (old style... should be updated)
- */
-#ifdef WS_USE_OLD_STYLE
-#define s_addr  S_un.S_addr	/* can be used for most tcp & ip code */
-#define s_host  S_un.S_un_b.s_b2	/* host on imp */
-#define s_net   S_un.S_un_b.s_b1	/* network */
-#define s_imp   S_un.S_un_w.s_w2	/* imp */
-#define s_impno S_un.S_un_b.s_b4	/* imp # */
-#define s_lh    S_un.S_un_b.s_b3	/* logical host */
+#ifndef WINELIB
+#pragma pack(1)                 /* tight alignment for the emulator */
 #endif
 
+/* Win16 socket-related types */
+
+typedef UINT16		SOCKET16;
+
+typedef struct ws_hostent
+{
+        SEGPTR  h_name;         /* official name of host */
+        SEGPTR  h_aliases;      /* alias list */
+        INT16   h_addrtype;     /* host address type */
+        INT16   h_length;       /* length of address */
+        SEGPTR  h_addr_list;    /* list of addresses from name server */
+} _ws_hostent;
+
+typedef struct ws_protoent
+{
+        SEGPTR  p_name;         /* official protocol name */
+        SEGPTR  p_aliases;      /* alias list */
+        INT16   p_proto;        /* protocol # */
+} _ws_protoent;
+
+typedef struct ws_servent 
+{
+        SEGPTR  s_name;         /* official service name */
+        SEGPTR  s_aliases;      /* alias list */
+        INT16   s_port;         /* port # */
+        SEGPTR  s_proto;        /* protocol to use */
+} _ws_servent;
+
+typedef struct ws_netent
+{
+        SEGPTR  n_name;         /* official name of net */
+        SEGPTR  n_aliases;      /* alias list */
+        INT16   n_addrtype;     /* net address type */
+        INT32   n_net;          /* network # */
+} _ws_netent;
+
+typedef struct sockaddr		ws_sockaddr;
+
+typedef struct
+{
+        UINT16    fd_count;               /* how many are SET? */
+        SOCKET16  fd_array[FD_SETSIZE];   /* an array of SOCKETs */
+} ws_fd_set;
+
+/* ws_fd_set operations */
+
+INT16   __WSAFDIsSet( SOCKET16, ws_fd_set * );
+
+#define WS_FD_CLR(fd, set) do { \
+    UINT16 __i; \
+    for (__i = 0; __i < ((ws_fd_set*)(set))->fd_count ; __i++) \
+    { \
+        if (((ws_fd_set*)(set))->fd_array[__i] == fd) \
+	{ \
+            while (__i < ((ws_fd_set*)(set))->fd_count-1) \
+	    { \
+                ((ws_fd_set*)(set))->fd_array[__i] = \
+                    ((ws_fd_set*)(set))->fd_array[__i+1]; \
+                __i++; \
+            } \
+            ((ws_fd_set*)(set))->fd_count--; \
+            break; \
+        } \
+    } \
+} while(0)
+
+#define WS_FD_SET(fd, set) do { \
+    if (((ws_fd_set*)(set))->fd_count < FD_SETSIZE) \
+        ((ws_fd_set*)(set))->fd_array[((ws_fd_set*)(set))->fd_count++]=(fd);\
+} while(0)
+
+#define WS_FD_ZERO(set) (((ws_fd_set*)(set))->fd_count=0)
+
+#define WS_FD_ISSET(fd, set) __WSAFDIsSet((SOCKET16)(fd), (ws_fd_set*)(set))
+
+/* 
+ * Internet address (old style... should be updated) 
+ */
+
+typedef struct ws_addr_in
+{
+        union {
+                struct { BYTE   s_b1,s_b2,s_b3,s_b4; } S_un_b;
+                struct { UINT16 s_w1,s_w2; } S_un_w;
+                UINT32 S_addr;
+        } S_un;
+#define ws_addr  S_un.S_addr		/* can be used for most tcp & ip code */
+#define ws_host  S_un.S_un_b.s_b2	/* host on imp */
+#define ws_net   S_un.S_un_b.s_b1	/* network */
+#define ws_imp   S_un.S_un_w.s_w2	/* imp */
+#define ws_impno S_un.S_un_b.s_b4	/* imp # */
+#define ws_lh    S_un.S_un_b.s_b3	/* logical host */
+} _ws_in_addr;
+
+typedef struct ws_sockaddr_in
+{
+        INT16		sin_family;
+        UINT16 		sin_port;
+        _ws_in_addr 	sin_addr;
+        char    	sin_zero[8];
+} _ws_sockaddr_in;
+
 #define WSADESCRIPTION_LEN      256
 #define WSASYS_STATUS_LEN       128
 
@@ -44,24 +130,79 @@
         WORD                    wHighVersion;
         char                    szDescription[WSADESCRIPTION_LEN+1];
         char                    szSystemStatus[WSASYS_STATUS_LEN+1];
-        unsigned short          iMaxSockets;
-        unsigned short          iMaxUdpDg;
-        char                   *lpVendorInfo;
+        UINT16			iMaxSockets;
+        UINT16			iMaxUdpDg;
+        SEGPTR			lpVendorInfo;
 } WSADATA, *LPWSADATA;
 
+#ifndef WINELIB
+#pragma pack(4)
+#endif
+
+/* ----------------------------------- no Win16 structure defs beyond this line! */
+
 /*
  * This is used instead of -1, since the
  * SOCKET type is unsigned.
  */
-#define INVALID_SOCKET  (SOCKET)(~0)
-#define SOCKET_ERROR            (-1)
+#define INVALID_SOCKET  (SOCKET16)(~0)
+#define SOCKET_ERROR              (-1)
+
+/*
+ * Types
+ */
+#define WS_SOCK_STREAM     1               /* stream socket */
+#define WS_SOCK_DGRAM      2               /* datagram socket */
+#define WS_SOCK_RAW        3               /* raw-protocol interface */
+#define WS_SOCK_RDM        4               /* reliably-delivered message */
+#define WS_SOCK_SEQPACKET  5               /* sequenced packet stream */
+
+#define WS_SOL_SOCKET		(-1)
+#define WS_IPPROTO_TCP		6
 
 /*
  * Option flags per-socket.
  */
-#ifndef SO_DONTLINGER
-#define SO_DONTLINGER   (u_int)(~SO_LINGER)
-#endif
+#define WS_SO_DEBUG        0x0001          /* turn on debugging info recording */
+#define WS_SO_ACCEPTCONN   0x0002          /* socket has had listen() */
+#define WS_SO_REUSEADDR    0x0004          /* allow local address reuse */
+#define WS_SO_KEEPALIVE    0x0008          /* keep connections alive */
+#define WS_SO_DONTROUTE    0x0010          /* just use interface addresses */
+#define WS_SO_BROADCAST    0x0020          /* permit sending of broadcast msgs */
+#define WS_SO_USELOOPBACK  0x0040          /* bypass hardware when possible */
+#define WS_SO_LINGER       0x0080          /* linger on close if data present */
+#define WS_SO_OOBINLINE    0x0100          /* leave received OOB data in line */
+
+#define WS_SO_DONTLINGER   (UINT16)(~WS_SO_LINGER)
+
+/*
+ * Additional options.
+ */
+#define WS_SO_SNDBUF       0x1001          /* send buffer size */
+#define WS_SO_RCVBUF       0x1002          /* receive buffer size */
+#define WS_SO_SNDLOWAT     0x1003          /* send low-water mark */
+#define WS_SO_RCVLOWAT     0x1004          /* receive low-water mark */
+#define WS_SO_SNDTIMEO     0x1005          /* send timeout */
+#define WS_SO_RCVTIMEO     0x1006          /* receive timeout */
+#define WS_SO_ERROR        0x1007          /* get error status and clear */
+#define WS_SO_TYPE         0x1008          /* get socket type */
+
+#define WS_IOCPARM_MASK    0x7f            /* parameters must be < 128 bytes */
+#define WS_IOC_VOID        0x20000000      /* no parameters */
+#define WS_IOC_OUT         0x40000000      /* copy out parameters */
+#define WS_IOC_IN          0x80000000      /* copy in parameters */
+#define WS_IOC_INOUT       (WS_IOC_IN|WS_IOC_OUT)
+#define WS_IOR(x,y,t)      (WS_IOC_OUT|(((UINT32)sizeof(t)&WS_IOCPARM_MASK)<<16)|((x)<<8)|(y))
+#define WS_IOW(x,y,t)      (WS_IOC_IN|(((UINT32)sizeof(t)&WS_IOCPARM_MASK)<<16)|((x)<<8)|(y))
+
+/*
+ * Socket I/O flags (supported by spec 1.1)
+ */
+
+#define WS_FIONREAD    WS_IOR('f', 127, u_long)
+#define WS_FIONBIO     WS_IOW('f', 126, u_long)
+
+#define WS_SIOCATMARK  WS_IOR('s',  7, u_long)
 
 /*
  * Maximum queue length specifiable by listen.
@@ -84,12 +225,17 @@
 /*
  * Define flags to be used with the WSAAsyncSelect() call.
  */
-#define FD_READ         0x01
-#define FD_WRITE        0x02
-#define FD_OOB          0x04
-#define FD_ACCEPT       0x08
-#define FD_CONNECT      0x10
-#define FD_CLOSE        0x20
+#define WS_FD_READ         0x01
+#define WS_FD_WRITE        0x02
+#define WS_FD_OOB          0x04
+#define WS_FD_ACCEPT       0x08
+#define WS_FD_CONNECT      0x10
+#define WS_FD_CLOSE        0x20
+
+#define WS_FD_NONBLOCK	   0x10000000	/* internal per-socket flags */
+#define WS_FD_INACTIVE	   0x20000000
+#define WS_FD_CONNECTED	   0x40000000
+#define WS_FD_INTERNAL	   0xFFFF0000
 
 /*
  * All Windows Sockets error constants are biased by WSABASEERR from
@@ -190,29 +336,35 @@
 
 /* Microsoft Windows Extension function prototypes */
 
-INT WSAStartup(WORD wVersionRequired, LPWSADATA lpWSAData);
-INT WSACleanup(void);
-void WSASetLastError(INT iError);
-INT WSAGetLastError(void);
-BOOL WSAIsBlocking(void);
-INT WSAUnhookBlockingHook(void);
+INT16 	  WSAStartup(UINT16 wVersionRequired, LPWSADATA lpWSAData);
+INT16 	  WSACleanup(void);
+void 	  WSASetLastError(INT16 iError);
+INT16 	  WSAGetLastError(void);
+BOOL16 	  WSAIsBlocking(void);
+INT16 	  WSAUnhookBlockingHook(void);
 FARPROC16 WSASetBlockingHook(FARPROC16 lpBlockFunc);
-INT WSACancelBlockingCall(void);
-HANDLE16 WSAAsyncGetServByName(HWND hWnd, u_int wMsg,
-                               LPCSTR name, LPCSTR proto,
-                               LPSTR buf, INT buflen);
-HANDLE16 WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port,
-                               LPCSTR proto, LPSTR buf, INT buflen);
-HANDLE16 WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg,
-                                LPCSTR name, LPSTR buf, INT buflen);
-HANDLE16 WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg,
-                                  INT number, LPSTR buf, INT buflen);
-HANDLE16 WSAAsyncGetHostByName(HWND hWnd, u_int wMsg,
-                               LPCSTR name, LPSTR buf, INT buflen);
-HANDLE16 WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, LPCSTR addr, INT len,
-                               INT type, LPSTR buf, INT buflen);
-INT WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle);
-INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent);
+INT16 	  WSACancelBlockingCall(void);
+HANDLE16  WSAAsyncGetServByName(HWND16 hWnd, UINT16 wMsg,
+                                LPCSTR name, LPCSTR proto,
+                                SEGPTR buf, INT16 buflen);
+
+HANDLE16  WSAAsyncGetServByPort(HWND16 hWnd, UINT16 wMsg, INT16 port,
+                                LPCSTR proto, SEGPTR buf, INT16 buflen);
+
+HANDLE16  WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 wMsg,
+                                 LPCSTR name, SEGPTR buf, INT16 buflen);
+
+HANDLE16  WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 wMsg,
+                                   INT16 number, SEGPTR buf, INT16 buflen);
+
+HANDLE16  WSAAsyncGetHostByName(HWND16 hWnd, UINT16 wMsg,
+                                LPCSTR name, SEGPTR buf, INT16 buflen);
+
+HANDLE16  WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 wMsg, LPCSTR addr, INT16 len,
+                                INT16 type, SEGPTR buf, INT16 buflen);
+
+INT16 	  WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle);
+INT16     WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 wMsg, UINT32 lEvent);
 
 #ifdef __cplusplus
 }
@@ -267,4 +419,121 @@
  */
 #define WSAGETSELECTERROR(lParam)           HIWORD(lParam)
 
+/* ----------------------------------- internal structures */
+
+#define WS_DUP_NATIVE           0x0
+#define WS_DUP_OFFSET           0x2
+#define WS_DUP_SEGPTR           0x4
+
+#define AOP_IO                  0x0000001	/* aop_control paramaters */
+
+#define AOP_CONTROL_REMOVE      0x0000000	/* aop_control return values */
+#define AOP_CONTROL_KEEP        0x0000001
+
+typedef struct  __aop
+{
+  /* AOp header */
+
+  struct __aop *next, *prev;
+  int           fd[2];				/* pipe */
+  int   (*aop_control)(struct __aop*, int);	/* SIGIO handler */
+  pid_t         pid;			/* child process pid */
+
+  /* custom data */
+
+  HWND16        hWnd;
+  UINT16        uMsg;
+
+  unsigned	flags;
+  SEGPTR	buffer_base;
+  int           buflen;
+  char*         init;			/* parameter data - length is in the async_ctl */
+} ws_async_op;
+
+#define WSMSG_ASYNC_SELECT      0x0000001
+#define WSMSG_ASYNC_HOSTBYNAME  0x0000010
+#define WSMSG_ASYNC_HOSTBYADDR  0x0000020
+#define WSMSG_ASYNC_PROTOBYNAME 0x0000100
+#define WSMSG_ASYNC_PROTOBYNUM  0x0000200
+#define WSMSG_ASYNC_SERVBYNAME  0x0001000
+#define WSMSG_ASYNC_SERVBYPORT  0x0002000
+
+#define MTYPE_PARENT            0x50505357
+#define MTYPE_CLIENT            0x50435357
+
+#pragma pack(1)
+typedef struct
+{
+  long          mtype;          /* WSMSG_... */
+
+  UINT32        lParam;
+  UINT16        wParam;         /* socket handle */
+} ipc_packet;
+
+#define MTYPE_PARENT_SIZE \
+        (sizeof(UINT32))
+#define MTYPE_CLIENT_SIZE \
+        (sizeof(ipc_packet) - sizeof(long))
+#pragma pack(4)
+
+typedef struct
+{
+  int                   fd;
+  unsigned              flags;
+  ws_async_op*          p_aop;
+} ws_socket;
+
+typedef struct
+{
+  ws_async_op*  ws_aop;         /* init'ed for getXbyY */
+  ws_socket*    ws_sock;        /* init'ed for AsyncSelect */
+  int           lEvent;
+  int           lLength;
+  char*		buffer;
+  ipc_packet    ip;
+} ws_async_ctl;
+
+#define WS_MAX_SOCKETS_PER_THREAD       16
+#define WS_MAX_UDP_DATAGRAM             1024
+
+#define WSI_BLOCKINGCALL	0x00000001	/* per-thread info flags */
+
+typedef struct __WSINFO
+{
+  struct __WSINFO*      prev,*next;
+
+  unsigned		flags;
+  int			errno;
+  int			num_startup;
+  int                   num_async_rq;
+  int                   last_free;
+  ws_socket             sock[WS_MAX_SOCKETS_PER_THREAD];
+  int			buflen;
+  char*			buffer;
+  FARPROC16		blocking_hook;
+  HTASK16               tid;    /* owning thread id - better switch
+                                 * to TLS when it gets fixed */
+} WSINFO, *LPWSINFO;
+
+int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag);
+int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag);
+int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag);
+
+void WS_do_async_gethost(LPWSINFO, unsigned);
+void WS_do_async_getproto(LPWSINFO, unsigned);
+void WS_do_async_getserv(LPWSINFO, unsigned);
+
+int WINSOCK_async_io(int fd, int async);
+int WINSOCK_unblock_io(int fd, int noblock);
+
+int  WINSOCK_check_async_op(ws_async_op* p_aop);
+void WINSOCK_link_async_op(ws_async_op* p_aop);
+void WINSOCK_unlink_async_op(ws_async_op* p_aop);
+void WINSOCK_cancel_async_op(HTASK16 tid);
+void WINSOCK_do_async_select(void);
+
+UINT16 wsaErrno(void);
+UINT16 wsaHerrno(void);
+
 #endif  /* _WINSOCKAPI_ */
+
diff --git a/library/miscstubs.c b/library/miscstubs.c
index 45f8bd7..6a7cda1 100644
--- a/library/miscstubs.c
+++ b/library/miscstubs.c
@@ -13,6 +13,11 @@
 #include "debug.h"
 #include "xmalloc.h"
 
+void SIGNAL_MaskAsyncEvents( BOOL32 mask )
+{
+    /* FIXME: signals don't work in the library */
+}
+
 int CallTo32_LargeStack( int (*func)(), int nbargs, ...)
 {
   va_list arglist;
@@ -49,7 +54,6 @@
 extern LRESULT FileOpenDlgProc(HWND,UINT,WPARAM16,LPARAM);
 extern LRESULT FileSaveDlgProc(HWND,UINT,WPARAM16,LPARAM);
 extern LRESULT FindTextDlgProc(HWND,UINT,WPARAM16,LPARAM);
-extern LRESULT ListBoxWndProc(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);
@@ -77,7 +81,6 @@
   MAP_STR_TO_PROC("FileOpenDlgProc",FileOpenDlgProc);
   MAP_STR_TO_PROC("FileSaveDlgProc",FileSaveDlgProc);
   MAP_STR_TO_PROC("FindTextDlgProc",FindTextDlgProc);
-  MAP_STR_TO_PROC("ListBoxWndProc",ListBoxWndProc);
   MAP_STR_TO_PROC("MDIClientWndProc",MDIClientWndProc);
   MAP_STR_TO_PROC("PopupMenuWndProc",PopupMenuWndProc);
   MAP_STR_TO_PROC("PrintDlgProc",PrintDlgProc);
diff --git a/loader/main.c b/loader/main.c
index ada2934..8cac976 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -149,11 +149,11 @@
     if (!KERN32_Init()) return 0;
 
       /* Create system message queue */
-    queueSize = GetProfileInt( "windows", "TypeAhead", 120 );
+    queueSize = GetProfileInt32A( "windows", "TypeAhead", 120 );
     if (!QUEUE_CreateSysMsgQueue( queueSize )) return 0;
 
     /* Set double click time */
-    SetDoubleClickTime( GetProfileInt( "windows", "DoubleClickSpeed", 452 ) );
+    SetDoubleClickTime( GetProfileInt32A("windows","DoubleClickSpeed",452) );
 
     return 1;
 }
diff --git a/loader/module.c b/loader/module.c
index 5707003..3866137 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -1290,6 +1290,7 @@
 {
     NE_MODULE *pModule;
 
+    if (!hModule) hModule = GetCurrentTask();
     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
     if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     lstrcpyn32A( lpFileName, NE_MODULE_NAME(pModule), nSize );
@@ -1407,7 +1408,8 @@
 	{
 	    /* Check that the original file name did not have a suffix */
 	    p = strrchr(filename, '.');
-	    if (!p || (strchr(p, '/') && strchr(p, '\\')))
+	    /* if there is a '.', check if either \ OR / follow */
+	    if (!p || strchr(p, '/') || strchr(p, '\\'))
             {
                 p = filename + strlen(filename);
                 strcpy( p, ".exe" );
diff --git a/loader/signal.c b/loader/signal.c
index 8474223..d9238e3 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -124,14 +124,14 @@
 /**********************************************************************
  *		SIGNAL_SetHandler
  */
-static void SIGNAL_SetHandler( int sig, void (*func)() )
+static void SIGNAL_SetHandler( int sig, void (*func)(), int flags )
 {
     int ret;
     struct sigaction sig_act;
 
 #ifdef linux
     sig_act.sa_handler = func;
-    sig_act.sa_flags = SA_RESTART | SA_NOMASK;
+    sig_act.sa_flags = SA_RESTART | (flags) ? SA_NOMASK : 0;
     /* Point to the top of the stack, minus 4 just in case, and make
        it aligned  */
     sig_act.sa_restorer = 
@@ -165,6 +165,7 @@
 }
 
 extern void stop_wait(int a);
+extern void WINSOCK_sigio(int a);
 
 
 /**********************************************************************
@@ -204,18 +205,19 @@
     }
 #endif  /* __svr4__ || _SCO_DS */
     
-    SIGNAL_SetHandler( SIGALRM, (void (*)())wine_timer );
-    SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault );
-    SIGNAL_SetHandler( SIGILL,  (void (*)())SIGNAL_fault );
-    SIGNAL_SetHandler( SIGFPE,  (void (*)())SIGNAL_fault );
-    SIGNAL_SetHandler( SIGTRAP, (void (*)())SIGNAL_trap ); /* debugger */
-    SIGNAL_SetHandler( SIGHUP,  (void (*)())SIGNAL_trap ); /* forced break */
+    SIGNAL_SetHandler( SIGALRM, (void (*)())wine_timer, 1);
+    SIGNAL_SetHandler( SIGSEGV, (void (*)())SIGNAL_fault, 1);
+    SIGNAL_SetHandler( SIGILL,  (void (*)())SIGNAL_fault, 1);
+    SIGNAL_SetHandler( SIGFPE,  (void (*)())SIGNAL_fault, 1);
+    SIGNAL_SetHandler( SIGTRAP, (void (*)())SIGNAL_trap, 1); 	/* debugger */
+    SIGNAL_SetHandler( SIGHUP,  (void (*)())SIGNAL_trap, 1); 	/* forced break */
 #ifdef SIGBUS
-    SIGNAL_SetHandler( SIGBUS,  (void (*)())SIGNAL_fault );
+    SIGNAL_SetHandler( SIGBUS,  (void (*)())SIGNAL_fault, 1);
 #endif
 #ifdef CONFIG_IPC
-    SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait ); /* For IPC */
+    SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait, 1); 	/* For IPC */
 #endif
+    SIGNAL_SetHandler( SIGIO,   (void (*)())WINSOCK_sigio, 0); 
     return TRUE;
 }
 
@@ -239,4 +241,19 @@
     setitimer(ITIMER_REAL, &vt_timer, NULL);
 }
 
+/**********************************************************************
+ *              SIGNAL_MaskAsyncEvents
+ */
+void SIGNAL_MaskAsyncEvents( BOOL32 flag )
+{
+  sigset_t 	set;
+  sigemptyset(&set);
+  sigaddset(&set, SIGIO);
+  sigaddset(&set, SIGUSR1);
+#ifdef CONFIG_IPC
+  sigaddset(&set, SIGUSR2);
+#endif
+  sigprocmask( (flag) ? SIG_BLOCK : SIG_UNBLOCK , &set, NULL);
+}
+
 #endif /* ifndef WINELIB */
diff --git a/loader/task.c b/loader/task.c
index 97b2ac3..d55e252 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -67,6 +67,7 @@
 #endif
 
 static HGLOBAL16 TASK_CreateDOSEnvironment(void);
+static void	 TASK_YieldToSystem(TDB*);
 
 /***********************************************************************
  *           TASK_Init
@@ -514,7 +515,7 @@
 
       /* Get the compatibility flags */
 
-    pTask->compat_flags = GetProfileInt( "Compatibility", name, 0 );
+    pTask->compat_flags = GetProfileInt32A( "Compatibility", name, 0 );
 
       /* Allocate a code segment alias for the TDB */
 
@@ -685,11 +686,22 @@
 
     /* Remove the task from the list to be sure we never switch back to it */
     TASK_UnlinkTask( hCurrentTask );
-    
+    if( nTaskCount )
+    {
+        TDB* p = (TDB *)GlobalLock16( hFirstTask );
+        while( p )
+        {
+            if( p->hYieldTo == hCurrentTask ) p->hYieldTo = 0;
+            p = (TDB *)GlobalLock16( p->hNext );
+        }
+    }
+
     hTaskToKill = hCurrentTask;
     hLockedTask = 0;
 
-    Yield();
+    pTask->nEvents = 0;
+    TASK_YieldToSystem(pTask);
+
     /* We should never return from this Yield() */
 
     fprintf(stderr,"Return of the living dead %04x!!!\n", hCurrentTask);
@@ -753,8 +765,9 @@
         /* check for DirectedYield() */
 
         hTask = pOldTask->hYieldTo;
-        if (!(pNewTask = (TDB *)GlobalLock16( hTask )) || !pNewTask->nEvents)
-            hTask = 0;
+        pNewTask = (TDB *)GlobalLock16( hTask );
+        if( !pNewTask || !pNewTask->nEvents) hTask = 0;
+        pOldTask->hYieldTo = 0;
     }
 
     /* extract hardware events only! */
diff --git a/misc/Makefile.in b/misc/Makefile.in
index 32b5cc2..e21b133 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -38,7 +38,8 @@
 	user.c \
 	ver.c \
 	w32sys.c \
-	winsocket.c \
+	winsock.c \
+	winsock_async.c \
 	wsprintf.c \
 	xmalloc.c
 
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 80aa834..fddf5a9 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -166,22 +166,14 @@
  */
 static BOOL FILEDLG_ScanDir(HWND hWnd, LPSTR newPath)
 {
-    BOOL32 ret = FALSE;
     int len;
-    char *str = SEGPTR_ALLOC(512);
-    if (!str) return TRUE;
+    char str[512];
 
     lstrcpyn32A( str, newPath, 512 );
     len = strlen(str);
-    GetDlgItemText32A( hWnd, edt1, str + len, 512 - len );
-    if (DlgDirList(hWnd, SEGPTR_GET(str), lst1, 0, 0x0000))
-    {
-        strcpy( str, "*.*" );
-        DlgDirList(hWnd, SEGPTR_GET(str), lst2, stc1, 0x8010 );
-        ret = TRUE;
-    }
-    SEGPTR_FREE(str);
-    return ret;
+    GetDlgItemText32A( hWnd, edt1, str + len, sizeof(str) - len );
+    if (!DlgDirList32A( hWnd, str, lst1, 0, 0x0000 )) return FALSE;
+    return DlgDirList32A( hWnd, "*.*", lst2, stc1, 0x8010 );
 }
 
 /***********************************************************************
@@ -388,10 +380,7 @@
   			lpofn->nFilterIndex, tmpstr);
   SetDlgItemText32A( hWnd, edt1, tmpstr );
   /* get drive list */
-  pstr = SEGPTR_ALLOC(1);
-  *pstr = 0;
-  DlgDirListComboBox16(hWnd, SEGPTR_GET(pstr), cmb2, 0, 0xC000);
-  SEGPTR_FREE(pstr);
+  DlgDirListComboBox32A(hWnd, "", cmb2, 0, 0xC000);
   /* read initial directory */
   if (PTR_SEG_TO_LIN(lpofn->lpstrInitialDir) != NULL) 
     {
diff --git a/misc/crtdll.c b/misc/crtdll.c
index e7a8be6..66b0549 100644
--- a/misc/crtdll.c
+++ b/misc/crtdll.c
@@ -616,6 +616,22 @@
 }
 
 /*********************************************************************
+ *                  calloc        (CRTDLL.350)
+ */
+VOID* CRTDLL_calloc(DWORD size, DWORD count)
+{
+    return HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size * count );
+}
+
+/*********************************************************************
+ *                  realloc        (CRTDLL.447)
+ */
+VOID* CRTDLL_realloc( VOID *ptr, DWORD size )
+{
+    return HeapReAlloc( GetProcessHeap(), 0, ptr, size );
+}
+
+/*********************************************************************
  *                  free          (CRTDLL.427)
  */
 VOID CRTDLL_free(LPVOID ptr)
diff --git a/misc/driver.c b/misc/driver.c
index e09113b..c0a23b0 100644
--- a/misc/driver.c
+++ b/misc/driver.c
@@ -21,7 +21,7 @@
     char  str[256];
     LPSTR ptr;
 
-    if (GetPrivateProfileString( "drivers", NULL, "", str, sizeof(str),
+    if (GetPrivateProfileString32A( "drivers", NULL, "", str, sizeof(str),
 				 "SYSTEM.INI" ) < 2)
     {
     	fprintf( stderr,
@@ -84,7 +84,7 @@
 		    lpDriverName, lpSectionName, lParam );
 
     if (lpSectionName == NULL) lpSectionName = "drivers";
-    GetPrivateProfileString( lpSectionName, lpDriverName, "", DrvName,
+    GetPrivateProfileString32A( lpSectionName, lpDriverName, "", DrvName,
 			     sizeof(DrvName), "SYSTEM.INI" );
     dprintf_driver( stddeb,"OpenDriver // DrvName='%s'\n", DrvName );
     if (lstrlen32A(DrvName) < 1) return 0;
diff --git a/misc/keyboard.c b/misc/keyboard.c
index 750a645..cf0cbbe 100644
--- a/misc/keyboard.c
+++ b/misc/keyboard.c
@@ -8,6 +8,7 @@
 #include <string.h>
 #include <ctype.h>
 #include "windows.h"
+#include "keyboard.h"
 #include "stddebug.h"
 /* #define DEBUG_KEYBOARD */
 #include "debug.h"
@@ -22,105 +23,110 @@
 
 static const struct KeyTableEntry KeyTable[] =
 {
-	{ 0x3, 0x3, 0x0, "" },
-	{ 0x8, 0x8, 0xe, "Backspace" },
-	{ 0x9, 0x9, 0xf, "Tab" },
-	{ 0xc, 0x0, 0x4c, "Num 5" },
-	{ 0xd, 0xd, 0x1c, "Enter" },
-	{ 0x10, 0x0, 0x2a, "Shift" },
-	{ 0x11, 0x0, 0x1d, "Ctrl" },
-	{ 0x12, 0x0, 0x38, "Alt" },
-	{ 0x14, 0x0, 0x3a, "Caps Lock" },
-	{ 0x1b, 0x1b, 0x1, "Esc" },
-	{ 0x20, 0x20, 0x39, "Space" },
-	{ 0x21, 0x0, 0x49, "Num 9" },
-	{ 0x22, 0x0, 0x51, "Num 3" },
-	{ 0x23, 0x0, 0x4f, "Num 1" },
-	{ 0x24, 0x0, 0x47, "Num 7" },
-	{ 0x25, 0x0, 0x4b, "Num 4" },
-	{ 0x26, 0x0, 0x48, "Num 8" },
-	{ 0x27, 0x0, 0x4d, "Num 6" },
-	{ 0x28, 0x0, 0x50, "Num 2" },
-	{ 0x2d, 0x0, 0x52, "Num 0" },
-	{ 0x2e, 0x0, 0x53, "Num Del" },
-	{ 0x30, 0x30, 0xb, "0" },
-	{ 0x31, 0x31, 0x2, "1" },
-	{ 0x32, 0x32, 0x3, "2" },
-	{ 0x33, 0x33, 0x4, "3" },
-	{ 0x34, 0x34, 0x5, "4" },
-	{ 0x35, 0x35, 0x6, "5" },
-	{ 0x36, 0x36, 0x7, "6" },
-	{ 0x37, 0x37, 0x8, "7" },
-	{ 0x38, 0x38, 0x9, "8" },
-	{ 0x39, 0x39, 0xa, "9" },
-	{ 0x41, 0x41, 0x1e, "A" },
-	{ 0x42, 0x42, 0x30, "B" },
-	{ 0x43, 0x43, 0x2e, "C" },
-	{ 0x44, 0x44, 0x20, "D" },
-	{ 0x45, 0x45, 0x12, "E" },
-	{ 0x46, 0x46, 0x21, "F" },
-	{ 0x47, 0x47, 0x22, "G" },
-	{ 0x48, 0x48, 0x23, "H" },
-	{ 0x49, 0x49, 0x17, "I" },
-	{ 0x4a, 0x4a, 0x24, "J" },
-	{ 0x4b, 0x4b, 0x25, "K" },
-	{ 0x4c, 0x4c, 0x26, "L" },
-	{ 0x4d, 0x4d, 0x32, "M" },
-	{ 0x4e, 0x4e, 0x31, "N" },
-	{ 0x4f, 0x4f, 0x18, "O" },
-	{ 0x50, 0x50, 0x19, "P" },
-	{ 0x51, 0x51, 0x10, "Q" },
-	{ 0x52, 0x52, 0x13, "R" },
-	{ 0x53, 0x53, 0x1f, "S" },
-	{ 0x54, 0x54, 0x14, "T" },
-	{ 0x55, 0x55, 0x16, "U" },
-	{ 0x56, 0x56, 0x2f, "V" },
-	{ 0x57, 0x57, 0x11, "W" },
-	{ 0x58, 0x58, 0x2d, "X" },
-	{ 0x59, 0x59, 0x15, "Y" },
-	{ 0x5a, 0x5a, 0x2c, "Z" },
-	{ 0x60, 0x0, 0x52, "Num 0" },
-	{ 0x61, 0x0, 0x4f, "Num 1" },
-	{ 0x62, 0x0, 0x50, "Num 2" },
-	{ 0x63, 0x0, 0x51, "Num 3" },
-	{ 0x64, 0x0, 0x4b, "Num 4" },
-	{ 0x65, 0x0, 0x4c, "Num 5" },
-	{ 0x66, 0x0, 0x4d, "Num 6" },
-	{ 0x67, 0x0, 0x47, "Num 7" },
-	{ 0x68, 0x0, 0x48, "Num 8" },
-	{ 0x69, 0x0, 0x49, "Num 9" },
-	{ 0x6a, 0x2a, 0x37, "Num *" },
-	{ 0x6b, 0x2b, 0x4e, "Num +" },
-	{ 0x6c, 0x0, 0x0, "" },
-	{ 0x6d, 0x2d, 0x4a, "Num -" },
-	{ 0x6e, 0x2e, 0x53, "Num Del" },
-	{ 0x6f, 0x2f, 0x0, "" },
-	{ 0x70, 0x0, 0x3b, "F1" },
-	{ 0x71, 0x0, 0x3c, "F2" },
-	{ 0x72, 0x0, 0x3d, "F3" },
-	{ 0x73, 0x0, 0x3e, "F4" },
-	{ 0x74, 0x0, 0x3f, "F5" },
-	{ 0x75, 0x0, 0x40, "F6" },
-	{ 0x76, 0x0, 0x41, "F7" },
-	{ 0x77, 0x0, 0x42, "F8" },
-	{ 0x78, 0x0, 0x43, "F9" },
-	{ 0x79, 0x0, 0x44, "F10" },
-	{ 0x7a, 0x0, 0x57, "F11" },
-	{ 0x7b, 0x0, 0x58, "F12" },
-	{ 0x90, 0x0, 0x45, "Pause" },
-	{ 0x91, 0x0, 0x46, "Scroll Lock" },
-	{ 0xba, 0x3b, 0x27, ";" },
-	{ 0xbb, 0x3d, 0xd, "=" },
-	{ 0xbc, 0x2c, 0x33, "," },
-	{ 0xbd, 0x2d, 0xc, "-" },
-	{ 0xbe, 0x2e, 0x34, "." },
-	{ 0xbf, 0x2f, 0x35, "/" },
-	{ 0xc0, 0x60, 0x29, "`" },
-	{ 0xdb, 0x5b, 0x1a, "[" },
-	{ 0xdc, 0x5c, 0x2b, "\\" },
-	{ 0xdd, 0x5d, 0x1b, "]" },
-	{ 0xde, 0x27, 0x28, "\'" },
-	{ 0xe2, 0x5c, 0x56, "\\" },
+	{ VK_CANCEL,	0x3,	0,	"" },
+	{ VK_BACK,	0x8,	0xe,	"Backspace" },
+	{ VK_TAB,	0x9,	0xf,	"Tab" },
+	{ VK_CLEAR,	0,	0x4c,	"Clear" },
+	{ VK_RETURN,	0xd,	0x1c,	"Enter" },
+	{ VK_SHIFT,	0,	0x2a,	"Shift" },
+	{ VK_CONTROL,	0,	0x1d,	"Ctrl" },
+	{ VK_MENU,	0,	0x38,	"Alt" },
+	{ VK_CAPITAL,	0,	0x3a,	"Caps Lock" },
+	{ VK_ESCAPE,	0x1b,	0x1,	"Esc" },
+	{ VK_SPACE,	0x20,	0x39,	"Space" },
+	{ VK_PRIOR,	0,	0x49,	"Page Up" },
+	{ VK_NEXT,	0,	0x51,	"Page Down" },
+	{ VK_END,	0,	0x4f,	"End" },
+	{ VK_HOME,	0,	0x47,	"Home" },
+	{ VK_LEFT,	0,	0x4b,	"Left Arrow" },
+	{ VK_UP,	0,	0x48,	"Up Arrow" },
+	{ VK_RIGHT,	0,	0x4d,	"Right Arrow" },
+	{ VK_DOWN,	0,	0x50,	"Down Arrow" },
+	{ VK_INSERT,	0,	0x52,	"Ins" },
+	{ VK_DELETE,	0,	0x53,	"Del" },
+	{ VK_0,		0x30,	0xb,	"0" },
+	{ VK_1,		0x31,	0x2,	"1" },
+	{ VK_2,		0x32,	0x3,	"2" },
+	{ VK_3,		0x33,	0x4,	"3" },
+	{ VK_4,		0x34,	0x5,	"4" },
+	{ VK_5,		0x35,	0x6,	"5" },
+	{ VK_6,		0x36,	0x7,	"6" },
+	{ VK_7,		0x37,	0x8,	"7" },
+	{ VK_8,		0x38,	0x9,	"8" },
+	{ VK_9,		0x39,	0xa,	"9" },
+	{ VK_A,		0x41,	0x1e,	"A" },
+	{ VK_B,		0x42,	0x30,	"B" },
+	{ VK_C,		0x43,	0x2e,	"C" },
+	{ VK_D,		0x44,	0x20,	"D" },
+	{ VK_E,		0x45,	0x12,	"E" },
+	{ VK_F,		0x46,	0x21,	"F" },
+	{ VK_G,		0x47,	0x22,	"G" },
+	{ VK_H,		0x48,	0x23,	"H" },
+	{ VK_I,		0x49,	0x17,	"I" },
+	{ VK_J,		0x4a,	0x24,	"J" },
+	{ VK_K,		0x4b,	0x25,	"K" },
+	{ VK_L,		0x4c,	0x26,	"L" },
+	{ VK_M,		0x4d,	0x32,	"M" },
+	{ VK_N,		0x4e,	0x31,	"N" },
+	{ VK_O,		0x4f,	0x18,	"O" },
+	{ VK_P,		0x50,	0x19,	"P" },
+	{ VK_Q,		0x51,	0x10,	"Q" },
+	{ VK_R,		0x52,	0x13,	"R" },
+	{ VK_S,		0x53,	0x1f,	"S" },
+	{ VK_T,		0x54,	0x14,	"T" },
+	{ VK_U,		0x55,	0x16,	"U" },
+	{ VK_V,		0x56,	0x2f,	"V" },
+	{ VK_W,		0x57,	0x11,	"W" },
+	{ VK_X,		0x58,	0x2d,	"X" },
+	{ VK_Y,		0x59,	0x15,	"Y" },
+	{ VK_Z,		0x5a,	0x2c,	"Z" },
+	{ VK_NUMPAD0,	0,	0x52,	"Num 0" },
+	{ VK_NUMPAD1,	0,	0x4f,	"Num 1" },
+	{ VK_NUMPAD2,	0,	0x50,	"Num 2" },
+	{ VK_NUMPAD3,	0,	0x51,	"Num 3" },
+	{ VK_NUMPAD4,	0,	0x4b,	"Num 4" },
+	{ VK_NUMPAD5,	0,	0x4c,	"Num 5" },
+	{ VK_NUMPAD6,	0,	0x4d,	"Num 6" },
+	{ VK_NUMPAD7,	0,	0x47,	"Num 7" },
+	{ VK_NUMPAD8,	0,	0x48,	"Num 8" },
+	{ VK_NUMPAD9,	0,	0x49,	"Num 9" },
+	{ VK_MULTIPLY,	0x2a,	0x37,	"Num *" },
+	{ VK_ADD,	0x2b,	0x4e,	"Num +" },
+	{ VK_SEPARATOR,	0,	0,	"" },
+	{ VK_SUBTRACT,	0x2d,	0x4a,	"Num -" },
+	{ VK_DECIMAL,	0x2e,	0x53,	"Num Del" },
+	{ VK_DIVIDE,	0x2f,	0,	"Num /" },
+	{ VK_F1,	0,	0x3b,	"F1" },
+	{ VK_F2,	0,	0x3c,	"F2" },
+	{ VK_F3,	0,	0x3d,	"F3" },
+	{ VK_F4,	0,	0x3e,	"F4" },
+	{ VK_F5,	0,	0x3f,	"F5" },
+	{ VK_F6,	0,	0x40,	"F6" },
+	{ VK_F7,	0,	0x41,	"F7" },
+	{ VK_F8,	0,	0x42,	"F8" },
+	{ VK_F9,	0,	0x43,	"F9" },
+	{ VK_F10,	0,	0x44,	"F10" },
+	{ VK_F11,	0,	0x57,	"F11" },
+	{ VK_F12,	0,	0x58,	"F12" },
+	{ VK_NUMLOCK,	0,	0x45,	"Num Lock" },
+	{ VK_SCROLL,	0,	0x46,	"Scroll Lock" },
+	/* Allowable ranges for OEM-specific virtual-key codes */
+/*	-		    0xBA-0xC0		OEM specific */
+	{ 0xba,		0x3b,	0x27,	";" },
+	{ 0xbb,		0x3d,	0xd,	"=" },
+	{ 0xbc,		0x2c,	0x33,	"," },
+	{ 0xbd,		0x2d,	0xc,	"-" },
+	{ 0xbe,		0x2e,	0x34,	"." },
+	{ 0xbf,		0x2f,	0x35,	"/" },
+	{ 0xc0,		0x60,	0x29,	"`" },
+/*	-		    0xDB-0xE4		OEM specific */
+	{ 0xdb,		0x5b,	0x1a,	"[" },
+	{ 0xdc,		0x5c,	0x2b,	"\\" },
+	{ 0xdd,		0x5d,	0x1b,	"]" },
+	{ 0xde,		0x27,	0x28,	"'" },
+	{ 0xe2,		0x5c,	0x56,	"\\" },
+/*	-		    0xE6		OEM specific */
+/*	-		    0xE9-0xF5		OEM specific */
 };
 
 #define KeyTableSize	sizeof(KeyTable) / sizeof(struct KeyTableEntry)
@@ -128,34 +134,55 @@
 int ToAscii(WORD wVirtKey, WORD wScanCode, LPSTR lpKeyState, 
 	LPVOID lpChar, WORD wFlags) 
 {
+	char shift = lpKeyState[VK_SHIFT] < 0;
 	int i;
 
-    	dprintf_keyboard(stddeb,"ToAscii (%d,%d)\n",wVirtKey, wScanCode);
+    	dprintf_keyboard(stddeb, "ToAscii (%x,%x) -> ", wVirtKey, wScanCode);
 
 	/* FIXME: codepage is broken */
 
-	for (i = 0 ; i != KeyTableSize ; i++) 
-		if (KeyTable[i].virtualkey == wVirtKey)  
-		 {
-		   dprintf_keyboard(stddeb,"\t\tchar = %s\n", KeyTable[i].name);
-		   if( isprint(KeyTable[i].ASCII) || isspace(KeyTable[i].ASCII) )
-		     {
-			*(BYTE*)lpChar = KeyTable[i].ASCII;
-			*(((BYTE*)lpChar) + 1) = 0;
-
-			if( isalpha( *(BYTE*)lpChar ) )
-			  if( (lpKeyState[VK_CAPITAL]<0 && !lpKeyState[VK_SHIFT]) ||
-			      (!lpKeyState[VK_CAPITAL] && lpKeyState[VK_SHIFT]<0) )
-			      *(BYTE*)lpChar = toupper( *(BYTE*)lpChar );
-			  else
-			      *(BYTE*)lpChar = tolower( *(BYTE*)lpChar );
-
-			return 1;
-		     }
-		 }
-
 	*(BYTE*)lpChar = 0;
-	return 0;
+	switch (wVirtKey)
+	  {
+#define vkcase2(k1,k2,val) case val : *(BYTE*)lpChar = shift ? k2 : k1; break;
+#define vkcase(k, val) vkcase2(val, k, val)
+	  WINE_VKEY_MAPPINGS
+#undef vkcase
+#undef vkcase2
+	  default :
+	    for (i = 0 ; ; i++) 
+	      {
+	      if (i == KeyTableSize)
+		{
+		  dprintf_keyboard(stddeb, "0\n");
+		  return 0;
+		}
+	      if (KeyTable[i].virtualkey == wVirtKey)  
+	        {
+		  if (!isprint(KeyTable[i].ASCII) && !isspace(KeyTable[i].ASCII))
+		    {
+		      dprintf_keyboard(stddeb, "0\n");
+		      return 0;
+		    }
+		  dprintf_keyboard(stddeb,"\"%s\" ", KeyTable[i].name);
+
+		  *(BYTE*)lpChar = KeyTable[i].ASCII;
+		  *(((BYTE*)lpChar) + 1) = 0;
+
+		  if (isalpha(*(BYTE*)lpChar))
+		    if( (lpKeyState[VK_CAPITAL]<0 && !lpKeyState[VK_SHIFT]) ||
+			(!lpKeyState[VK_CAPITAL] && lpKeyState[VK_SHIFT]<0) )
+			*(BYTE*)lpChar = toupper( *(BYTE*)lpChar );
+		    else
+			*(BYTE*)lpChar = tolower( *(BYTE*)lpChar );
+		  break;
+	        }
+	     }
+	  }
+	if (lpKeyState[VK_CONTROL] < 0)
+	  *(BYTE*)lpChar = *(BYTE*)lpChar & 0x1f;
+	dprintf_keyboard(stddeb, "1 (%x)\n", *(BYTE*)lpChar);
+	return 1;
 }
 
 DWORD OemKeyScan(WORD wOemChar)
@@ -166,7 +193,16 @@
 }
 
 /* VkKeyScan translates an ANSI character to a virtual-key and shift code
- * for the current keyboard. */
+ * for the current keyboard.
+ * FIXME high-order byte should yield :
+ *	0	Unshifted
+ *	1	Shift
+ *	2	Ctrl
+ *	3-5	Shift-key combinations that are not used for characters
+ *	6	Ctrl-Alt
+ *	7	Ctrl-Alt-Shift
+ *	I.e. :	Shift = 1, Ctrl = 2, Alt = 4.
+ */
 
 WORD VkKeyScan(WORD cChar)
 {
@@ -208,26 +244,28 @@
 	int i;
 	
 	switch(wMapType) {
-		case 0:
+		case 0:	/* vkey-code to scan-code */
 			for (i = 0 ; i != KeyTableSize ; i++) 
 				if (KeyTable[i].virtualkey == wCode) 
 					return KeyTable[i].scancode;
 			return 0;
 
-		case 1:
+		case 1: /* scan-code to vkey-code */
 			for (i = 0 ; i != KeyTableSize ; i++) 
 				if (KeyTable[i].scancode == wCode) 
 					return KeyTable[i].virtualkey;
 			return 0;
 
-		case 2:
+		case 2: /* vkey-code to unshifted ANSI code */
+			/* FIXME : what does unshifted mean ? 'a' or 'A' ? */
 			for (i = 0 ; i != KeyTableSize ; i++) 
 				if (KeyTable[i].virtualkey == wCode) 
 					return KeyTable[i].ASCII;
 			return 0;
 
-		default: 
-			fprintf(stderr, "MapVirtualKey: unknown wMapType!\n");
+		default: /* reserved */
+			fprintf(stderr, "MapVirtualKey: unknown wMapType %d !\n",
+				wMapType);
 			return 0;	
 	}
 	return 0;
diff --git a/misc/main.c b/misc/main.c
index b9113a7..f8597ec 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -804,7 +804,8 @@
     fprintf(stderr, "Unknown mode set? This shouldn't happen. Check GetWinFlags()!\n");
     break;
   }
-
+  if( getVersionEx.dwPlatformId == VER_PLATFORM_WIN32_NT )
+      result |= 0x4000; /* undocumented WF_WINNT */
   return result;
 }
 
@@ -1076,18 +1077,21 @@
 			break;
 
 		case SPI_GETFASTTASKSWITCH:
-			*(BOOL *) lpvParam = FALSE;
-			/* FIXME GetProfileInt( "windows", "CoolSwitch", 1 ) */
+		    if ( GetProfileInt32A( "windows", "CoolSwitch", 1 ) == 1 )
+			  *(BOOL *) lpvParam = TRUE;
+			else
+			  *(BOOL *) lpvParam = FALSE;
 			break;
 
 		case SPI_GETGRIDGRANULARITY:
-			*(INT *) lpvParam = 1;
-		/* FIXME GetProfileInt( "desktop", "GridGranularity", 1 ) */
-			break;
+                    *(INT *) lpvParam = GetProfileInt32A( "desktop", 
+                                                          "GridGranularity",
+                                                          1 );
+                    break;
 
 		case SPI_GETICONTITLEWRAP:
 			*(BOOL *) lpvParam = FALSE;
-			/* FIXME GetProfileInt( "desktop", "?", True ) */
+			/* FIXME GetProfileInt32A( "desktop", "?", True ) */
 			break;
 
 		case SPI_GETKEYBOARDDELAY:
@@ -1105,9 +1109,11 @@
 			break;
 
 		case SPI_GETSCREENSAVEACTIVE:
-			/* FIXME GetProfileInt( "windows", "ScreenSaveActive", 1 ); */
-			*(BOOL *) lpvParam = FALSE;
-			break;
+                    if ( GetProfileInt32A( "windows", "ScreenSaveActive", 1 ) == 1 )
+                        *(BOOL *) lpvParam = TRUE;
+                    else
+                        *(BOOL *) lpvParam = FALSE;
+                    break;
 
 		case SPI_GETSCREENSAVETIMEOUT:
 			/* FIXME GetProfileInt( "windows", "ScreenSaveTimeout", 300 ); */
@@ -1116,18 +1122,20 @@
 			break;
 
 		case SPI_ICONHORIZONTALSPACING:
+                    /* FIXME Get/SetProfileInt */
 			if (lpvParam == NULL)
-				fprintf(stderr, "SystemParametersInfo: Horizontal icon spacing set to %d\n.", uParam);
-			else
-				*(INT *) lpvParam = GetSystemMetrics( SM_CXICONSPACING );
+                            /*SetSystemMetrics( SM_CXICONSPACING, uParam )*/ ;
+                        else
+                            *(INT *) lpvParam = GetSystemMetrics( SM_CXICONSPACING );
 			break;
 
 		case SPI_ICONVERTICALSPACING:
-			if (lpvParam == NULL)
-				fprintf(stderr, "SystemParametersInfo: Vertical icon spacing set to %d\n.", uParam);
-			else
-				*(INT *) lpvParam = GetSystemMetrics( SM_CYICONSPACING );
-			break;
+                    /* FIXME Get/SetProfileInt */
+                    if (lpvParam == NULL)
+                        /*SetSystemMetrics( SM_CYICONSPACING, uParam )*/ ;
+		    else
+                        *(INT *) lpvParam = GetSystemMetrics(SM_CYICONSPACING);
+                    break;
 
 		case SPI_SETBEEP:
 			if (uParam == TRUE)
@@ -1147,7 +1155,7 @@
 
 		case SPI_SETSCREENSAVETIMEOUT:
 			XSetScreenSaver(display, uParam, 60, DefaultBlanking, 
-						DefaultExposures);
+							DefaultExposures);
 			break;
 
 		case SPI_SETDESKWALLPAPER:
@@ -1156,7 +1164,7 @@
 
 		case SPI_SETDESKPATTERN:
 			if ((INT) uParam == -1) {
-				GetProfileString("Desktop", "Pattern", 
+				GetProfileString32A("Desktop", "Pattern", 
 						"170 85 170 85 170 85 170 85", 
 						buffer, sizeof(buffer) );
 				return (DESKTOP_SetPattern((LPSTR) buffer));
@@ -1166,19 +1174,20 @@
 
 	        case SPI_GETICONTITLELOGFONT: 
 	        {
-		    /* FIXME GetProfileString( "?", "?", "?" ) */
-		  LPLOGFONT16 lpLogFont = (LPLOGFONT16)lpvParam;
-		  lpLogFont->lfHeight = 10;
-		  lpLogFont->lfWidth = 0;
-		  lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
-		  lpLogFont->lfWeight = FW_NORMAL;
-		  lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE;
-		  lpLogFont->lfCharSet = ANSI_CHARSET;
-		  lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
-		  lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
-		  lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
-		  break;
-		}
+			  /* FIXME GetProfileString32A( "?", "?", "?" ) */
+			  LPLOGFONT16 lpLogFont = (LPLOGFONT16)lpvParam;
+			  lpLogFont->lfHeight = 10;
+			  lpLogFont->lfWidth = 0;
+			  lpLogFont->lfEscapement = lpLogFont->lfOrientation = 0;
+			  lpLogFont->lfWeight = FW_NORMAL;
+			  lpLogFont->lfItalic = lpLogFont->lfStrikeOut = lpLogFont->lfUnderline = FALSE;
+			  lpLogFont->lfCharSet = ANSI_CHARSET;
+			  lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
+			  lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
+			  lpLogFont->lfPitchAndFamily = DEFAULT_PITCH | FF_SWISS;
+			  break;
+			}
+
 		case SPI_LANGDRIVER:
 		case SPI_SETBORDER:
 		case SPI_SETDOUBLECLKHEIGHT:
diff --git a/misc/ole2nls.c b/misc/ole2nls.c
index 66a7a74..8669f50 100644
--- a/misc/ole2nls.c
+++ b/misc/ole2nls.c
@@ -4,16 +4,126 @@
  *	Copyright 1995	Martin von Loewis
  */
 
-/*	At the moment, these are only empty stubs.
- */
-
 #include <string.h>
+#include <malloc.h>
 #include "windows.h"
 #include "ole.h"
 #include "options.h"
 #include "winnls.h"
 #include "stddebug.h"
 #include "debug.h"
+#include "string32.h"
+
+/* Locale name to id map. used by EnumSystemLocales, GetLocalInfoA 
+ * MUST contain all #defines from winnls.h
+ * last entry has NULL name, 0 id.
+ */ 
+#define LOCALE_ENTRY(x)	{#x,LOCALE_##x}
+static struct tagLOCALE_NAME2ID {
+	char	*name;
+	DWORD	id;
+} locale_name2id[]= {
+	LOCALE_ENTRY(ILANGUAGE),
+	LOCALE_ENTRY(SLANGUAGE),
+	LOCALE_ENTRY(SENGLANGUAGE),
+	LOCALE_ENTRY(SABBREVLANGNAME),
+	LOCALE_ENTRY(SNATIVELANGNAME),
+	LOCALE_ENTRY(ICOUNTRY),
+	LOCALE_ENTRY(SCOUNTRY),
+	LOCALE_ENTRY(SENGCOUNTRY),
+	LOCALE_ENTRY(SABBREVCTRYNAME),
+	LOCALE_ENTRY(SNATIVECTRYNAME),
+	LOCALE_ENTRY(IDEFAULTLANGUAGE),
+	LOCALE_ENTRY(IDEFAULTCOUNTRY),
+	LOCALE_ENTRY(IDEFAULTCODEPAGE),
+	LOCALE_ENTRY(IDEFAULTANSICODEPAGE),
+	LOCALE_ENTRY(SLIST),
+	LOCALE_ENTRY(IMEASURE),
+	LOCALE_ENTRY(SDECIMAL),
+	LOCALE_ENTRY(STHOUSAND),
+	LOCALE_ENTRY(SGROUPING),
+	LOCALE_ENTRY(IDIGITS),
+	LOCALE_ENTRY(ILZERO),
+	LOCALE_ENTRY(INEGNUMBER),
+	LOCALE_ENTRY(SNATIVEDIGITS),
+	LOCALE_ENTRY(SCURRENCY),
+	LOCALE_ENTRY(SINTLSYMBOL),
+	LOCALE_ENTRY(SMONDECIMALSEP),
+	LOCALE_ENTRY(SMONTHOUSANDSEP),
+	LOCALE_ENTRY(SMONGROUPING),
+	LOCALE_ENTRY(ICURRDIGITS),
+	LOCALE_ENTRY(IINTLCURRDIGITS),
+	LOCALE_ENTRY(ICURRENCY),
+	LOCALE_ENTRY(INEGCURR),
+	LOCALE_ENTRY(SDATE),
+	LOCALE_ENTRY(STIME),
+	LOCALE_ENTRY(SSHORTDATE),
+	LOCALE_ENTRY(SLONGDATE),
+	LOCALE_ENTRY(STIMEFORMAT),
+	LOCALE_ENTRY(IDATE),
+	LOCALE_ENTRY(ILDATE),
+	LOCALE_ENTRY(ITIME),
+	LOCALE_ENTRY(ITIMEMARKPOSN),
+	LOCALE_ENTRY(ICENTURY),
+	LOCALE_ENTRY(ITLZERO),
+	LOCALE_ENTRY(IDAYLZERO),
+	LOCALE_ENTRY(IMONLZERO),
+	LOCALE_ENTRY(S1159),
+	LOCALE_ENTRY(S2359),
+	LOCALE_ENTRY(ICALENDARTYPE),
+	LOCALE_ENTRY(IOPTIONALCALENDAR),
+	LOCALE_ENTRY(IFIRSTDAYOFWEEK),
+	LOCALE_ENTRY(IFIRSTWEEKOFYEAR),
+	LOCALE_ENTRY(SDAYNAME1),
+	LOCALE_ENTRY(SDAYNAME2),
+	LOCALE_ENTRY(SDAYNAME3),
+	LOCALE_ENTRY(SDAYNAME4),
+	LOCALE_ENTRY(SDAYNAME5),
+	LOCALE_ENTRY(SDAYNAME6),
+	LOCALE_ENTRY(SDAYNAME7),
+	LOCALE_ENTRY(SABBREVDAYNAME1),
+	LOCALE_ENTRY(SABBREVDAYNAME2),
+	LOCALE_ENTRY(SABBREVDAYNAME3),
+	LOCALE_ENTRY(SABBREVDAYNAME4),
+	LOCALE_ENTRY(SABBREVDAYNAME5),
+	LOCALE_ENTRY(SABBREVDAYNAME6),
+	LOCALE_ENTRY(SABBREVDAYNAME7),
+	LOCALE_ENTRY(SMONTHNAME1),
+	LOCALE_ENTRY(SMONTHNAME2),
+	LOCALE_ENTRY(SMONTHNAME3),
+	LOCALE_ENTRY(SMONTHNAME4),
+	LOCALE_ENTRY(SMONTHNAME5),
+	LOCALE_ENTRY(SMONTHNAME6),
+	LOCALE_ENTRY(SMONTHNAME7),
+	LOCALE_ENTRY(SMONTHNAME8),
+	LOCALE_ENTRY(SMONTHNAME9),
+	LOCALE_ENTRY(SMONTHNAME10),
+	LOCALE_ENTRY(SMONTHNAME11),
+	LOCALE_ENTRY(SMONTHNAME12),
+	LOCALE_ENTRY(SMONTHNAME13),
+	LOCALE_ENTRY(SABBREVMONTHNAME1),
+	LOCALE_ENTRY(SABBREVMONTHNAME2),
+	LOCALE_ENTRY(SABBREVMONTHNAME3),
+	LOCALE_ENTRY(SABBREVMONTHNAME4),
+	LOCALE_ENTRY(SABBREVMONTHNAME5),
+	LOCALE_ENTRY(SABBREVMONTHNAME6),
+	LOCALE_ENTRY(SABBREVMONTHNAME7),
+	LOCALE_ENTRY(SABBREVMONTHNAME8),
+	LOCALE_ENTRY(SABBREVMONTHNAME9),
+	LOCALE_ENTRY(SABBREVMONTHNAME10),
+	LOCALE_ENTRY(SABBREVMONTHNAME11),
+	LOCALE_ENTRY(SABBREVMONTHNAME12),
+	LOCALE_ENTRY(SABBREVMONTHNAME13),
+	LOCALE_ENTRY(SPOSITIVESIGN),
+	LOCALE_ENTRY(SNEGATIVESIGN),
+	LOCALE_ENTRY(IPOSSIGNPOSN),
+	LOCALE_ENTRY(INEGSIGNPOSN),
+	LOCALE_ENTRY(IPOSSYMPRECEDES),
+	LOCALE_ENTRY(IPOSSEPBYSPACE),
+	LOCALE_ENTRY(INEGSYMPRECEDES),
+	LOCALE_ENTRY(INEGSEPBYSPACE),
+	{NULL,0},
+};
 
 /***********************************************************************
  *           GetUserDefaultLCID       (OLE2NLS.1)
@@ -86,137 +196,39 @@
  */
 int GetLocaleInfoA(DWORD lcid,DWORD LCType,LPSTR buf,WORD len)
 {
-	char *retString;
-    int retLen;
-    dprintf_ole(stddeb,"GetLocaleInfoA(%8lX,%8lX,%p,%4X)\n",
+	char	*retString;
+	int	found,i;
+
+	dprintf_ole(stddeb,"GetLocaleInfoA(%8lX,%8lX,%p,%4X)\n",
 			lcid,LCType,buf,len);
-#if 0
-	/* Wine is supporting only the default locale */
-	if(lcid!=GetUserDefaultLCID())
-	{
-		dprintf_ole(stdnimp,"GetLocaleInfoA: Unknown locale\n");
-		return 0;
-	}
-#endif
 	/* As an option, we could obtain the value from win.ini.
 	   This would not match the Wine compile-time option.
 	   Also, not all identifiers are available from win.ini */
 	retString=0;
-	retLen=0;
 	/* If we are through all of this, retLen should not be zero anymore.
 	   If it is, the value is not supported */
-#define LOCVAL(type,value)	if(type==LCType)			\
-								{retLen=strlen(value)+1;\
-								 retString=value;       \
-								}
-#define UNSUPPORTED(type)   if(type==lcid)retString=#type;
+	i=0;
+	while (locale_name2id[i].name!=NULL) {
+		if (LCType == locale_name2id[i].id) {
+			retString = locale_name2id[i].name;
+			break;
+		}
+		i++;
+	}
+	if (!retString) {
+		fprintf(stderr,"Unkown LC type %lX\n",LCType);
+		return 0;
+	}
 
-/* I really wish I would know a better way to do this */
-UNSUPPORTED(LOCALE_ILANGUAGE)
-UNSUPPORTED(LOCALE_SLANGUAGE)
-UNSUPPORTED(LOCALE_SENGLANGUAGE)
-UNSUPPORTED(LOCALE_SABBREVLANGNAME)
-UNSUPPORTED(LOCALE_SNATIVELANGNAME)
-UNSUPPORTED(LOCALE_ICOUNTRY)
-UNSUPPORTED(LOCALE_SCOUNTRY)
-UNSUPPORTED(LOCALE_SENGCOUNTRY)
-UNSUPPORTED(LOCALE_SABBREVCTRYNAME)
-UNSUPPORTED(LOCALE_SNATIVECTRYNAME)
-UNSUPPORTED(LOCALE_IDEFAULTLANGUAGE)
-UNSUPPORTED(LOCALE_IDEFAULTCOUNTRY)
-UNSUPPORTED(LOCALE_IDEFAULTCODEPAGE)
-UNSUPPORTED(LOCALE_IDEFAULTANSICODEPAGE)
-UNSUPPORTED(LOCALE_SLIST)
-UNSUPPORTED(LOCALE_IMEASURE)
-UNSUPPORTED(LOCALE_SDECIMAL)
-UNSUPPORTED(LOCALE_STHOUSAND)
-UNSUPPORTED(LOCALE_SGROUPING)
-UNSUPPORTED(LOCALE_IDIGITS)
-UNSUPPORTED(LOCALE_ILZERO)
-UNSUPPORTED(LOCALE_INEGNUMBER)
-UNSUPPORTED(LOCALE_SNATIVEDIGITS)
-UNSUPPORTED(LOCALE_SCURRENCY)
-UNSUPPORTED(LOCALE_SINTLSYMBOL)
-UNSUPPORTED(LOCALE_SMONDECIMALSEP)
-UNSUPPORTED(LOCALE_SMONTHOUSANDSEP)
-UNSUPPORTED(LOCALE_SMONGROUPING)
-UNSUPPORTED(LOCALE_ICURRDIGITS)
-UNSUPPORTED(LOCALE_IINTLCURRDIGITS)
-UNSUPPORTED(LOCALE_ICURRENCY)
-UNSUPPORTED(LOCALE_INEGCURR)
-UNSUPPORTED(LOCALE_SDATE)
-UNSUPPORTED(LOCALE_STIME)
-UNSUPPORTED(LOCALE_SSHORTDATE)
-UNSUPPORTED(LOCALE_SLONGDATE)
-UNSUPPORTED(LOCALE_STIMEFORMAT)
-UNSUPPORTED(LOCALE_IDATE)
-UNSUPPORTED(LOCALE_ILDATE)
-UNSUPPORTED(LOCALE_ITIME)
-UNSUPPORTED(LOCALE_ITIMEMARKPOSN)
-UNSUPPORTED(LOCALE_ICENTURY)
-UNSUPPORTED(LOCALE_ITLZERO)
-UNSUPPORTED(LOCALE_IDAYLZERO)
-UNSUPPORTED(LOCALE_IMONLZERO)
-UNSUPPORTED(LOCALE_S1159)
-UNSUPPORTED(LOCALE_S2359)
-UNSUPPORTED(LOCALE_ICALENDARTYPE)
-UNSUPPORTED(LOCALE_IOPTIONALCALENDAR)
-UNSUPPORTED(LOCALE_IFIRSTDAYOFWEEK)
-UNSUPPORTED(LOCALE_IFIRSTWEEKOFYEAR)
-UNSUPPORTED(LOCALE_SDAYNAME1)
-UNSUPPORTED(LOCALE_SDAYNAME2)
-UNSUPPORTED(LOCALE_SDAYNAME3)
-UNSUPPORTED(LOCALE_SDAYNAME4)
-UNSUPPORTED(LOCALE_SDAYNAME5)
-UNSUPPORTED(LOCALE_SDAYNAME6)
-UNSUPPORTED(LOCALE_SDAYNAME7)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME1)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME2)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME3)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME4)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME5)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME6)
-UNSUPPORTED(LOCALE_SABBREVDAYNAME7)
-UNSUPPORTED(LOCALE_SMONTHNAME1)
-UNSUPPORTED(LOCALE_SMONTHNAME2)
-UNSUPPORTED(LOCALE_SMONTHNAME3)
-UNSUPPORTED(LOCALE_SMONTHNAME4)
-UNSUPPORTED(LOCALE_SMONTHNAME5)
-UNSUPPORTED(LOCALE_SMONTHNAME6)
-UNSUPPORTED(LOCALE_SMONTHNAME7)
-UNSUPPORTED(LOCALE_SMONTHNAME8)
-UNSUPPORTED(LOCALE_SMONTHNAME9)
-UNSUPPORTED(LOCALE_SMONTHNAME10)
-UNSUPPORTED(LOCALE_SMONTHNAME11)
-UNSUPPORTED(LOCALE_SMONTHNAME12)
-UNSUPPORTED(LOCALE_SMONTHNAME13)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME1)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME2)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME3)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME4)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME5)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME6)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME7)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME8)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME9)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME10)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME11)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME12)
-UNSUPPORTED(LOCALE_SABBREVMONTHNAME13)
-UNSUPPORTED(LOCALE_SPOSITIVESIGN)
-UNSUPPORTED(LOCALE_SNEGATIVESIGN)
-UNSUPPORTED(LOCALE_IPOSSIGNPOSN)
-UNSUPPORTED(LOCALE_INEGSIGNPOSN)
-UNSUPPORTED(LOCALE_IPOSSYMPRECEDES)
-UNSUPPORTED(LOCALE_IPOSSEPBYSPACE)
-UNSUPPORTED(LOCALE_INEGSYMPRECEDES)
-UNSUPPORTED(LOCALE_INEGSEPBYSPACE)
+#define LOCVAL(type,value) case type:retString=value;break;
 
 /* Now, the language specific definitions. They don't have to be
    complete */
+    found=1;
     switch(Options.language)
     {
     case LANG_De:
+    	switch (LCType) {
 /* This definitions apply to Germany only. Users in Austria 
    or Switzerland might want to modify them */
 LOCVAL(LOCALE_ILANGUAGE,"9")
@@ -339,9 +351,12 @@
 LOCVAL(LOCALE_INEGSYMPRECEDES)
 LOCVAL(LOCALE_INEGSEPBYSPACE)
 */
+	default: found=0;break;
+	}
     break;  /* LANG(De) */
 
     case LANG_Da:
+    	switch (LCType) {
 /* LOCVAL(LOCALE_ILANGUAGE,"9") */
 LOCVAL(LOCALE_SLANGUAGE,"Dansk")
 LOCVAL(LOCALE_SENGLANGUAGE,"Danish")
@@ -441,9 +456,12 @@
 /* LOCVAL(LOCALE_IPOSSEPBYSPACE) */
 /* LOCVAL(LOCALE_INEGSYMPRECEDES) */
 /* LOCVAL(LOCALE_INEGSEPBYSPACE) */
+	default: found=0;break;
+	}
     break; /* LANG(Da) */
 
     case LANG_En:
+    	switch (LCType) {
 /* This definitions apply to Germany only. Users in Austria 
    or Switzerland might want to modify them */
 LOCVAL(LOCALE_ILANGUAGE,"9")
@@ -566,9 +584,12 @@
 LOCVAL(LOCALE_INEGSYMPRECEDES)
 LOCVAL(LOCALE_INEGSEPBYSPACE)
 */
+	default: found=0;break;
+	}
     break;  /* LANG(En) */
 
     case LANG_Eo:
+    	switch (LCType) {
 /* LOCVAL(LOCALE_ILANGUAGE,"9") ISO numerical ID for language TODO */
 LOCVAL(LOCALE_SLANGUAGE,"Esperanto")
 LOCVAL(LOCALE_SENGLANGUAGE,"Esperanto")
@@ -668,9 +689,12 @@
 /* LOCVAL(LOCALE_IPOSSEPBYSPACE) */
 /* LOCVAL(LOCALE_INEGSYMPRECEDES) */
 /* LOCVAL(LOCALE_INEGSEPBYSPACE) */
+	default: found=0;break;
+	}
     break;  /* LANG(Eo) */
 
     case LANG_Fi:
+    	switch (LCType) {
 LOCVAL(LOCALE_ILANGUAGE,"11")
 LOCVAL(LOCALE_SLANGUAGE,"Suomi")
 LOCVAL(LOCALE_SENGLANGUAGE,"Finnish")
@@ -791,9 +815,12 @@
 LOCVAL(LOCALE_INEGSYMPRECEDES)
 LOCVAL(LOCALE_INEGSEPBYSPACE)
 */
+	default: found=0;break;
+	}
     break;  /* LANG(Fi) */
 
     case LANG_It:
+    	switch (LCType) {
 LOCVAL(LOCALE_ILANGUAGE,"9")
 LOCVAL(LOCALE_SLANGUAGE,"Italiano")
 LOCVAL(LOCALE_SENGLANGUAGE,"Italian")
@@ -914,9 +941,12 @@
 LOCVAL(LOCALE_INEGSYMPRECEDES)
 LOCVAL(LOCALE_INEGSEPBYSPACE)
 */
+	default: found=0;break;
+	}
     break;  /* LANG(It) */
 
     case 0x0409:
+    	switch (LCType) {
 LOCVAL(LOCALE_ILANGUAGE, "0409")
 LOCVAL(LOCALE_SLANGUAGE, "English (United States)")
 LOCVAL(LOCALE_SENGLANGUAGE, "English")
@@ -1016,9 +1046,12 @@
 LOCVAL(LOCALE_IPOSSEPBYSPACE, "0")
 LOCVAL(LOCALE_INEGSYMPRECEDES, "1")
 LOCVAL(LOCALE_INEGSEPBYSPACE, "0")
+	default: found=0;break;
+	}
     break; /* LANG(0x0409) (U.S. English) */
 
     case 0x0809:
+    	switch (LCType) {
 LOCVAL(LOCALE_ILANGUAGE, "0809")
 LOCVAL(LOCALE_SLANGUAGE, "English (United Kingdom)")
 LOCVAL(LOCALE_SENGLANGUAGE, "English")
@@ -1118,25 +1151,24 @@
 LOCVAL(LOCALE_IPOSSEPBYSPACE, "0")
 LOCVAL(LOCALE_INEGSYMPRECEDES, "1")
 LOCVAL(LOCALE_INEGSEPBYSPACE, "0")
+	default: found=0;break;
+	}
     break; /* LANG(0x0809) (U.K. English) */
 
 /*Insert other languages here*/
 
     default:
+    	found=0;
 	break;
     }  /* switch */
 
-	if(!retLen)
-	{
-		if(!retString)fprintf(stderr,"Unkown LC type %lX\n",LCType);
-		else fprintf(stderr,"'%s' not supported for your language.\n",
+	if(!found) {
+		fprintf(stderr,"'%s' not supported for your language.\n",
 			retString);
 		return 0;
 	}
-
-	if(retLen>len)retLen=len;
 	lstrcpyn32A(buf,retString,len);
-	return retLen;
+	return strlen(retString)+1;
 }
 
 /***********************************************************************
@@ -1230,7 +1262,57 @@
 	return TRUE;
 }
 
-BOOL IsValidLocale(DWORD lcid,DWORD flags) {
-	fprintf(stdnimp,"IsValidLocale(%ld,%ld)\n",lcid,flags);
+/***********************************************************************
+ *           IsValidLocale       (KERNEL32.361)
+ */
+BOOL32 IsValidLocale(DWORD lcid,DWORD flags) {
+	int	i;
+
+	i=0;
+	while (locale_name2id[i].name!=NULL)
+		if (locale_name2id[i].id == lcid)
+			return TRUE;
+	return FALSE;
+}
+
+/***********************************************************************
+ *              EnumSystemLocales32W                (KERNEL32.93)
+ */
+BOOL32
+EnumSystemLocales32W(LOCALE_ENUMPROC32W lpfnLocaleEnum,DWORD flags) {
+	WCHAR	*cp;
+	int	i;
+	BOOL32	ret;
+
+	dprintf_win32(stddeb,"EnumSystemLocales32W(%p,%08lx)\n",
+		lpfnLocaleEnum,flags
+	);
+	i=0;
+	while (locale_name2id[i].name!=NULL) {
+		cp=(LPWSTR)STRING32_DupAnsiToUni(locale_name2id[i].name);
+		ret=lpfnLocaleEnum(cp);
+		free(cp);
+		if (!ret) break;
+		i++;
+	}
+	return TRUE;
+}
+
+/***********************************************************************
+ *              EnumSystemLocales32A                (KERNEL32.92)
+ */
+BOOL32
+EnumSystemLocales32A(LOCALE_ENUMPROC32A lpfnLocaleEnum,DWORD flags) {
+	int	i;
+
+	dprintf_win32(stddeb,"EnumSystemLocales32A(%p,%08lx)\n",
+		lpfnLocaleEnum,flags
+	);
+	i=0;
+	while (locale_name2id[i].name!=NULL) {
+		if (!lpfnLocaleEnum(locale_name2id[i].name))
+			break;
+		i++;
+	}
 	return TRUE;
 }
diff --git a/misc/registry.c b/misc/registry.c
index cdd6751..90c001a 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -450,7 +450,7 @@
 	return _savesubkey(F,lpkey->nextsub,0,all);
 }
 
-static void
+static BOOL32
 _savereg(LPKEYSTRUCT lpkey,char *fn,int all) {
 	FILE	*F;
 
@@ -459,15 +459,16 @@
 		fprintf(stddeb,__FILE__":_savereg:Couldn't open %s for writing: %s\n",
 			fn,strerror(errno)
 		);
-		return;
+		return FALSE;
 	}
 	if (!_savesubreg(F,lpkey,all)) {
 		fclose(F);
 		unlink(fn);
 		fprintf(stddeb,__FILE__":_savereg:Failed to save keys, perhaps no more diskspace for %s?\n",fn);
-		return;
+		return FALSE;
 	}
 	fclose(F);
+        return TRUE;
 }
 
 void
@@ -500,19 +501,22 @@
 	if (lstrcmpi32A(buf,"yes"))
 		all=1;
 	pwd=getpwuid(getuid());
-	if (pwd!=NULL && pwd->pw_dir!=NULL) {
-		fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_USERS_DEFAULT)+2);
+	if (pwd!=NULL && pwd->pw_dir!=NULL)
+        {
+                char *tmp = tmpnam(NULL);
+		fn=(char*)xmalloc( strlen(pwd->pw_dir) + strlen(WINE_PREFIX) +
+                                   strlen(SAVE_CURRENT_USER) + 2 );
 		strcpy(fn,pwd->pw_dir);
 		strcat(fn,WINE_PREFIX);
 		/* create the directory. don't care about errorcodes. */
 		mkdir(fn,0755); /* drwxr-xr-x */
 		strcat(fn,"/"SAVE_CURRENT_USER);
-		_savereg(key_current_user,fn,all);
+		if (_savereg(key_current_user,tmp,all)) rename(tmp,fn);
 		free(fn);
 		fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+2);
 		strcpy(fn,pwd->pw_dir);
 		strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
-		_savereg(key_local_machine,fn,all);
+		if (_savereg(key_local_machine,tmp,all)) rename(tmp,fn);
 		free(fn);
 	} else
 		fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
@@ -1315,6 +1319,216 @@
 	free(keys);
 }
 
+/* WINDOWS 31 REGISTRY LOADER, supplied by Tor Sjøwall, tor@sn.no */
+
+/*
+    reghack - windows 3.11 registry data format demo program.
+
+    The reg.dat file has 3 parts, a header, a table of 8-byte entries that is
+    a combined hash table and tree description, and finally a text table.
+
+    The header is obvious from the struct header. The taboff1 and taboff2
+    fields are always 0x20, and their usage is unknown.
+
+    The 8-byte entry table has various entry types.
+
+    tabent[0] is a root index. The second word has the index of the root of
+            the directory.
+    tabent[1..hashsize] is a hash table. The first word in the hash entry is
+            the index of the key/value that has that hash. Data with the same
+            hash value are on a circular list. The other three words in the
+            hash entry are always zero.
+    tabent[hashsize..tabcnt] is the tree structure. There are two kinds of
+            entry: dirent and keyent/valent. They are identified by context.
+    tabent[freeidx] is the first free entry. The first word in a free entry
+            is the index of the next free entry. The last has 0 as a link.
+            The other three words in the free list are probably irrelevant.
+
+    Entries in text table are preceeded by a word at offset-2. This word
+    has the value (2*index)+1, where index is the referring keyent/valent
+    entry in the table. I have no suggestion for the 2* and the +1.
+    Following the word, there are N bytes of data, as per the keyent/valent
+    entry length. The offset of the keyent/valent entry is from the start
+    of the text table to the first data byte.
+
+    This information is not available from Microsoft. The data format is
+    deduced from the reg.dat file by me. Mistakes may
+    have been made. I claim no rights and give no guarantees for this program.
+
+    Tor Sjøwall, tor@sn.no
+*/
+
+/* reg.dat header format */
+struct _w31_header {
+	char		cookie[8];	/* 'SHCC3.10' */
+	unsigned long	taboff1;	/* offset of hash table (??) = 0x20 */
+	unsigned long	taboff2;	/* offset of index table (??) = 0x20 */
+	unsigned long	tabcnt;		/* number of entries in index table */
+	unsigned long	textoff;	/* offset of text part */
+	unsigned long	textsize;	/* byte size of text part */
+	unsigned short	hashsize;	/* hash size */
+	unsigned short	freeidx;	/* free index */
+};
+
+/* generic format of table entries */
+struct _w31_tabent {
+	unsigned short w0, w1, w2, w3;
+};
+
+/* directory tabent: */
+struct _w31_dirent {
+	unsigned short	sibling_idx;	/* table index of sibling dirent */
+	unsigned short	child_idx;	/* table index of child dirent */
+	unsigned short	key_idx;	/* table index of key keyent */
+	unsigned short	value_idx;	/* table index of value valent */
+};
+
+/* key tabent: */
+struct _w31_keyent {
+	unsigned short	hash_idx;	/* hash chain index for string */
+	unsigned short	refcnt;		/* reference count */
+	unsigned short	length;		/* length of string */
+	unsigned short	string_off;	/* offset of string in text table */
+};
+
+/* value tabent: */
+struct _w31_valent {
+	unsigned short	hash_idx;	/* hash chain index for string */
+	unsigned short	refcnt;		/* reference count */
+	unsigned short	length;		/* length of string */
+	unsigned short	string_off;	/* offset of string in text table */
+};
+
+/* recursive helper function to display a directory tree */
+void
+__w31_dumptree(	unsigned short idx,
+		unsigned char *txt,
+		struct _w31_tabent *tab,
+		struct _w31_header *head,
+		LPKEYSTRUCT	lpkey,
+		time_t		lastmodified,
+		int		level
+) {
+	struct _w31_dirent	*dir;
+	struct _w31_keyent	*key;
+	struct _w31_valent	*val;
+	LPKEYSTRUCT		xlpkey;
+	LPWSTR			name,value;
+	static char		tail[400];
+
+	while (idx!=0) {
+		dir=(struct _w31_dirent*)&tab[idx];
+
+		if (dir->key_idx) {
+			key = (struct _w31_keyent*)&tab[dir->key_idx];
+
+			memcpy(tail,&txt[key->string_off],key->length);
+			tail[key->length]='\0';
+			/* all toplevel entries AND the entries in the 
+			 * toplevel subdirectory belong to \SOFTWARE\Classes
+			 */
+			if (!level && !lstrcmp32A(tail,".classes")) {
+				__w31_dumptree(dir->child_idx,txt,tab,head,lpkey,lastmodified,level+1);
+				idx=dir->sibling_idx;
+				continue;
+			}
+			name=STRING32_DupAnsiToUni(tail);
+
+			xlpkey=_find_or_add_key(lpkey,name);
+
+			/* only add if leaf node or valued node */
+			if (dir->value_idx!=0||dir->child_idx==0) {
+				if (dir->value_idx) {
+					val=(struct _w31_valent*)&tab[dir->value_idx];
+					memcpy(tail,&txt[val->string_off],val->length);
+					tail[val->length]='\0';
+					value=STRING32_DupAnsiToUni(tail);
+					_find_or_add_value(xlpkey,NULL,REG_SZ,(LPBYTE)value,lstrlen32W(value)*2+2,lastmodified);
+				}
+			}
+		} else {
+			dprintf_reg(stddeb,"__w31_dumptree:strange: no directory key name, idx=%04x\n", idx);
+		}
+		__w31_dumptree(dir->child_idx,txt,tab,head,xlpkey,lastmodified,level+1);
+		idx=dir->sibling_idx;
+	}
+}
+
+void
+_w31_loadreg() {
+	HFILE			hf;
+	struct _w31_header	head;
+	struct _w31_tabent	*tab;
+	unsigned char		*txt;
+	int			len;
+	OFSTRUCT		ofs;
+	BY_HANDLE_FILE_INFORMATION hfinfo;
+	time_t			lastmodified;
+	HKEY			hkey;
+	LPKEYSTRUCT		lpkey;
+
+	hf = OpenFile("reg.dat",&ofs,OF_READ);
+	if (hf==HFILE_ERROR)
+		return;
+
+	/* read & dump header */
+	if (sizeof(head)!=_lread32(hf,&head,sizeof(head))) {
+		dprintf_reg(stddeb,"_w31_loadreg:reg.dat is too short.\n");
+		_lclose(hf);
+		return;
+	}
+	if (memcmp(head.cookie, "SHCC3.10", sizeof(head.cookie))!=0) {
+		dprintf_reg(stddeb,"_w31_loadreg:reg.dat has bad signature.\n");
+		_lclose(hf);
+		return;
+	}
+
+	len = head.tabcnt * sizeof(struct _w31_tabent);
+	/* read and dump index table */
+	tab = xmalloc(len);
+	if (len!=_lread32(hf,tab,len)) {
+		dprintf_reg(stderr,"_w31_loadreg:couldn't read %d bytes.\n",len); 
+		free(tab);
+		_lclose(hf);
+		return;
+	}
+
+	/* read text */
+	txt = xmalloc(head.textsize);
+	if (-1==_llseek(hf,head.textoff,SEEK_SET)) {
+		dprintf_reg(stderr,"_w31_loadreg:couldn't seek to textblock.\n"); 
+		free(tab);
+		free(txt);
+		_lclose(hf);
+		return;
+	}
+	if (head.textsize!=_lread32(hf,txt,head.textsize)) {
+		dprintf_reg(stderr,"_w31_loadreg:textblock too short (%d instead of %ld).\n",len,head.textsize); 
+		free(tab);
+		free(txt);
+		_lclose(hf);
+		return;
+	}
+
+	if (!GetFileInformationByHandle(hf,&hfinfo)) {
+		dprintf_reg(stderr,"_w31_loadreg:GetFileInformationByHandle failed?.\n"); 
+		free(tab);
+		free(txt);
+		_lclose(hf);
+		return;
+	}
+	lastmodified	= DOSFS_FileTimeToUnixTime(&(hfinfo.ftLastWriteTime));
+
+	if (RegCreateKey16(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&hkey)!=ERROR_SUCCESS)
+		return;
+	lpkey = lookup_hkey(hkey);
+	__w31_dumptree(tab[0].w1,txt,tab,&head,lpkey,lastmodified,0);
+	free(tab);
+	free(txt);
+	_lclose(hf);
+	return;
+}
+
 void
 SHELL_LoadRegistry() {
 	char	*fn;
@@ -1326,13 +1540,13 @@
 	if (key_classes_root==NULL)
 		SHELL_Init();
 
+	/* Load windows 3.1 entries */
+	_w31_loadreg();
 	/* Load windows 95 entries */
 	_w95_loadreg("C:\\system.1st",	key_local_machine);
 	_w95_loadreg("system.dat",	key_local_machine);
 	_w95_loadreg("user.dat",	key_users);
 
-	/* FIXME: win3.1 reg.dat loader still missing */
-
 	/* the global user default is loaded under HKEY_USERS\\.Default */
 	RegCreateKey16(HKEY_USERS,".Default",&hkey);
 	lpkey = lookup_hkey(hkey);
diff --git a/misc/shell.c b/misc/shell.c
index 3a96897..2f9cc8b 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -195,29 +195,34 @@
     /* extensions; however, it'd make sense to check the programs */
     /* section first, so that's what happens here. */
 
-    /* See if it's a program */
-    GetProfileString("windows", "programs", "exe pif bat com",
-		      buffer, sizeof(buffer)); /* FIXME check return code! */
+    /* See if it's a program - if GetProfileString fails, we skip this
+     * section. Actually, if GetProfileString fails, we've probably
+     * got a lot more to worry about than running a program... */
+    if ( GetProfileString32A("windows", "programs", "exe pif bat com",
+						  buffer, sizeof(buffer)) > 0 )
+	  {
+		for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
 
-    for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
+		tok = strtok(buffer, " \t"); /* ? */
+		while( tok!= NULL)
+		  {
+			if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
+			  {
+				strcpy(lpResult, xlpFile);
+				/* Need to perhaps check that the file has a path
+				 * attached */
+				dprintf_exec(stddeb, "SHELL_FindExecutable: found %s\n",
+							 lpResult);
+	    return 33;
 
-    tok = strtok(buffer, " \t"); /* ? */
-    while( tok!= NULL)
-    {
-	if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
-	{
-	    strcpy(lpResult, xlpFile); /* Need to perhaps check that */
-				      /* the file has a path attached */
-	    dprintf_exec(stddeb, "SHELL_FindExecutable: found %s\n",
-			 lpResult);
-	    return 33; /* Greater than 32 to indicate success FIXME */
-		       /* According to the docs, I should be returning */
-		       /* a handle for the executable. Does this mean */
-		       /* I'm supposed to open the executable file or */
-		       /* something? More RTFM, I guess... */
-	}
-	tok=strtok(NULL, " \t");
-    }
+		/* Greater than 32 to indicate success FIXME According to the
+		 * docs, I should be returning a handle for the
+		 * executable. Does this mean I'm supposed to open the
+		 * executable file or something? More RTFM, I guess... */
+			  }
+			tok=strtok(NULL, " \t");
+		  }
+	  }
 
     /* Check registry */
     if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, tmpext, filetype,
@@ -249,32 +254,34 @@
 		    strcat( lpResult, &tok[2] );
 		}
 	    }
-	    retval=33;
+	    retval=33; /* FIXME see above */
 	}
     }
     else /* Check win.ini */
     {
 	/* Toss the leading dot */
 	extension++;
-	GetProfileString( "extensions", extension, "", command,
-			 sizeof(command));
-	if (strlen(command)!=0)
-	{
-	    strcpy( lpResult, command );
-	    tok=strstr( lpResult, "^" ); /* should be ^.extension? */
-	    if (tok != NULL)
-	    {
-		tok[0]='\0';
-		strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
-		tok=strstr( command, "^" ); /* see above */
-		if ((tok != NULL) && (strlen(tok)>5))
-		{
-		    strcat( lpResult, &tok[5]);
-		}
-	    }
-	    retval=33;
+	if ( GetProfileString32A( "extensions", extension, "", command,
+                                  sizeof(command)) > 0)
+	  {
+		if (strlen(command)!=0)
+		  {
+			strcpy( lpResult, command );
+			tok=strstr( lpResult, "^" ); /* should be ^.extension? */
+			if (tok != NULL)
+			  {
+				tok[0]='\0';
+				strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
+				tok=strstr( command, "^" ); /* see above */
+				if ((tok != NULL) && (strlen(tok)>5))
+				  {
+					strcat( lpResult, &tok[5]);
+				  }
+			  }
+			retval=33; /* FIXME - see above */
+		  }
+	  }
 	}
-    }
 
     dprintf_exec(stddeb, "SHELL_FindExecutable: returning %s\n", lpResult);
     return retval;
@@ -804,7 +811,7 @@
  */
 int RegisterShellHook(void *ptr) 
 {
-	fprintf(stdnimp, "RegisterShellHook : Empty Stub !!!\n");
+	fprintf(stdnimp, "RegisterShellHook( %p ) : Empty Stub !!!\n", ptr);
 	return 0;
 }
 
diff --git a/misc/spy.c b/misc/spy.c
index 57ce9d9..1b00d39 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -296,7 +296,8 @@
     "LB_SETITEMHEIGHT32",       /* 0x01a0 */
     "LB_GETITEMHEIGHT32",       /* 0x01a1 */
     "LB_FINDSTRINGEXACT32",     /* 0x01a2 */
-    NULL, NULL,
+    "LB_CARETON32",             /* 0x01a3 */
+    "LB_CARETOFF32",            /* 0x01a4 */
     "LB_SETLOCALE32",           /* 0x01a5 */
     "LB_GETLOCALE32",           /* 0x01a6 */
     "LB_SETCOUNT32",            /* 0x01a7 */
diff --git a/misc/user.c b/misc/user.c
index 3516a78..68a91a5 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -101,7 +101,7 @@
     int queueSize;
 
       /* Create task message queue */
-    queueSize = GetProfileInt( "windows", "DefaultQueueSize", 8 );
+    queueSize = GetProfileInt32A( "windows", "DefaultQueueSize", 8 );
     if (!SetMessageQueue( queueSize )) return 0;
 
     return 1;
@@ -112,8 +112,7 @@
  */
 void USER_AppExit( HTASK16 hTask, HINSTANCE16 hInstance, HQUEUE16 hQueue )
 {
-    /* FIXME: flush send messages (which are not implemented yet),
-     *        empty clipboard if needed, maybe destroy menus (Windows
+    /* FIXME: empty clipboard if needed, maybe destroy menus (Windows
      *	      only complains about them but does nothing);
      */
 
@@ -126,18 +125,13 @@
     /* Patch resident popup menu window */
     MENU_SwitchTPWndTo(0);
 
-    /* Nuke timers */
-
     TIMER_RemoveQueueTimers( hQueue );
 
+    QUEUE_FlushMessages( hQueue );
     HOOK_FreeQueueHooks( hQueue );
 
     QUEUE_SetDoomedQueue( hQueue );
-
-    /* Nuke orphaned windows */
-
-    WIN_DestroyQueueWindows( desktop->child, hQueue );
-
+    WIN_ResetQueueWindows( desktop->child, hQueue, (HQUEUE16)0);
     QUEUE_SetDoomedQueue( 0 );
 
     /* Free the message queue */
diff --git a/misc/winsock.c b/misc/winsock.c
new file mode 100644
index 0000000..cb22484
--- /dev/null
+++ b/misc/winsock.c
@@ -0,0 +1,1713 @@
+/*
+ * based on Windows Sockets 1.1 specs
+ * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
+ * 
+ * (C) 1993,1994,1996 John Brezak, Erik Bos, Alex Korobka.
+ */
+ 
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/ioctl.h>
+#if defined(__svr4__)
+#include <sys/filio.h>
+#include <sys/ioccom.h>
+#endif
+#include <sys/msg.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#include "windows.h"
+#include "winnt.h"
+#include "heap.h"
+#include "ldt.h"
+#include "winsock.h"
+#include "stddebug.h"
+#include "debug.h"
+
+#define dump_sockaddr(a) \
+        fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
+                        ((struct sockaddr_in *)a)->sin_family, \
+                        inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
+                        ntohs(((struct sockaddr_in *)a)->sin_port))
+
+extern void SIGNAL_MaskAsyncEvents( BOOL32 );
+
+#pragma pack(4)
+
+/* ----------------------------------- internal data */
+
+extern int h_errno;
+extern void __sigio(int);
+
+ws_async_ctl            async_ctl;
+int                     async_qid = -1;
+
+static HANDLE32 	_WSHeap = 0;
+static unsigned char*	_ws_stub = NULL;
+static LPWSINFO         _wsi_list = NULL;
+
+#define WS_ALLOC(size) \
+	HeapAlloc(_WSHeap, HEAP_ZERO_MEMORY, (size) )
+#define WS_FREE(ptr) \
+	HeapFree(_WSHeap, 0, (ptr) )
+
+#define WS_PTR2HANDLE(ptr) \
+        ((short)((int)(ptr) - (int)_ws_stub))
+#define WS_HANDLE2PTR(handle) \
+        ((unsigned)((int)_ws_stub + (int)handle))
+
+#define WSI_CHECK_RANGE(pwsi, pws) \
+	( ((unsigned)(pws) > (unsigned)(pwsi)) && \
+	  ((unsigned)(pws) < ((unsigned)(pwsi) + sizeof(WSINFO))) )
+
+static INT16         _ws_sock_ops[] =
+       { WS_SO_DEBUG, WS_SO_REUSEADDR, WS_SO_KEEPALIVE, WS_SO_DONTROUTE,
+         WS_SO_BROADCAST, WS_SO_LINGER, WS_SO_OOBINLINE, WS_SO_SNDBUF,
+         WS_SO_RCVBUF, WS_SO_ERROR, WS_SO_TYPE, WS_SO_DONTLINGER, 0 };
+static int           _px_sock_ops[] =
+       { SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
+         SO_LINGER, SO_OOBINLINE, SO_SNDBUF, SO_RCVBUF, SO_ERROR, SO_TYPE,
+	 SO_LINGER };
+
+static INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent);
+static int notify_client(ws_socket* pws, unsigned flag);
+
+static int _check_ws(LPWSINFO pwsi, ws_socket* pws);
+static int _check_buffer(LPWSINFO pwsi, int size);
+
+static void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base);
+static void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base);
+static void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base);
+
+static int delete_async_op(ws_socket*);
+
+static void convert_sockopt(INT16 *level, INT16 *optname)
+{
+  int           i;
+  switch (*level)
+  {
+     case WS_SOL_SOCKET:
+        *level = SOL_SOCKET;
+        for(i=0; _ws_sock_ops[i]; i++)
+            if( _ws_sock_ops[i] == *optname ) break;
+        if( _ws_sock_ops[i] ) *optname = (INT16)_px_sock_ops[i];
+        else fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
+        break;
+     case WS_IPPROTO_TCP:
+        *optname = IPPROTO_TCP;
+  }
+}
+
+static void _ws_global_init()
+{
+   if( !_ws_stub )
+   {
+     _WSHeap = HeapCreate(HEAP_ZERO_MEMORY, 8120, 32768);
+     if( !(_ws_stub = WS_ALLOC(0x10)) )
+       fprintf(stderr,"Fatal: failed to create WinSock heap\n");
+   }
+   if( async_qid == -1 ) 
+     if( (async_qid = msgget(IPC_PRIVATE, IPC_CREAT | 0x1FF)) == -1 )
+       fprintf(stderr,"Fatal: failed to create WinSock resource\n");
+}
+
+/* ----------------------------------- Per-thread info */
+
+static void wsi_link(LPWSINFO pwsi)
+{ if( _wsi_list ) _wsi_list->prev = pwsi;
+  pwsi->next = _wsi_list; _wsi_list = pwsi; 
+}
+
+static void wsi_unlink(LPWSINFO pwsi)
+{
+  if( pwsi == _wsi_list ) _wsi_list = pwsi->next;
+  else 
+  { pwsi->prev->next = pwsi->next;
+    if( pwsi->next ) pwsi->next->prev = pwsi->prev; } 
+}
+
+static LPWSINFO wsi_find(HTASK16 hTask)
+{ LPWSINFO pwsi = _wsi_list;
+  while( pwsi && pwsi->tid != hTask ) pwsi = pwsi->next;
+  return pwsi; 
+}
+
+static ws_socket* wsi_alloc_socket(LPWSINFO pwsi, int fd)
+{
+  if( pwsi->last_free >= 0 )
+  {
+    int i = pwsi->last_free;
+
+    pwsi->last_free = pwsi->sock[i].flags;
+    pwsi->sock[i].fd = fd;
+    pwsi->sock[i].flags = 0;
+    return &pwsi->sock[i];
+  }
+  return NULL;
+}
+
+static void fd_set_normalize(fd_set* fds, LPWSINFO pwsi, ws_fd_set* ws, int* highfd)
+{
+  FD_ZERO(fds);
+  if(ws) 
+  { 
+    int 	i;
+    ws_socket*  pws;
+    for(i=0;i<(ws->fd_count);i++) 
+    {
+      pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
+      if( _check_ws(pwsi, pws) ) 
+      { 
+        if( pws->fd > *highfd ) *highfd = pws->fd; 
+        FD_SET(pws->fd, fds); 
+      }
+    }
+  }
+}
+
+static void fd_set_update(LPWSINFO pwsi, fd_set* fds, ws_fd_set* ws)
+{
+  if( ws )
+  {
+    int	        i, j, count = ws->fd_count;
+    ws_socket*  pws;
+    for( i = 0, j = 0; i < count; i++ )
+    {
+      pws = (ws_socket*)WS_HANDLE2PTR(ws->fd_array[i]);
+      if( _check_ws(pwsi, pws) ) 
+        if( FD_ISSET(pws->fd, fds) )
+        { 
+	  ws->fd_array[j++] = ws->fd_array[i];
+          continue; 
+        }
+      ws->fd_count--;
+    }
+  }
+}
+
+/* ----------------------------------- API ----- 
+ *
+ * Init / cleanup / error checking.
+ */
+
+INT16 WSAStartup(UINT16 wVersionRequested, LPWSADATA lpWSAData)
+{
+  WSADATA WINSOCK_data = { 0x0101, 0x0101,
+                          "WINE Sockets 1.1",
+                        #ifdef linux
+                                "Linux/i386",
+                        #elif defined(__NetBSD__)
+                                "NetBSD/i386",
+                        #elif defined(sunos)
+                                "SunOS",
+                        #elif defined(__FreeBSD__)
+                                "FreeBSD",
+                        #else
+                                "Unknown",
+                        #endif
+			   WS_MAX_SOCKETS_PER_THREAD,
+			   WS_MAX_UDP_DATAGRAM, NULL };
+  HTASK16               tid = GetCurrentTask();
+  LPWSINFO              pwsi;
+
+  dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
+
+  if (LOBYTE(wVersionRequested) < 1 || (LOBYTE(wVersionRequested) == 1 &&
+      HIBYTE(wVersionRequested) < 1)) return WSAVERNOTSUPPORTED;
+
+  if (!lpWSAData) return WSAEINVAL;
+
+  _ws_global_init();
+  if( _WSHeap == 0 ) return WSASYSNOTREADY;
+  
+  pwsi = wsi_find(GetCurrentTask());
+  if( pwsi == NULL )
+  {
+    if( (pwsi = (LPWSINFO)WS_ALLOC( sizeof(WSINFO))) )
+    {
+      int i = 0;
+      pwsi->tid = tid;
+      for( i = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++ )
+      { 
+	pwsi->sock[i].fd = -1; 
+	pwsi->sock[i].flags = i + 1; 
+      }
+      pwsi->sock[WS_MAX_SOCKETS_PER_THREAD - 1].flags = -1;
+    } 
+    else return WSASYSNOTREADY;
+    wsi_link(pwsi);
+  } else pwsi->num_startup++;
+
+  /* return winsock information */
+  memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data));
+
+  dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
+  return(0);
+}
+
+INT16 WSACleanup(void)
+{
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  /* FIXME: do global cleanup if no current task */
+
+  dprintf_winsock(stddeb, "WSACleanup(%08x)\n", (unsigned)pwsi);
+  if( pwsi )
+  {
+      int	i, j, n;
+
+      if( pwsi->num_startup-- ) return 0;
+
+      SIGNAL_MaskAsyncEvents( TRUE );
+      WINSOCK_cancel_async_op(GetCurrentTask());
+      SIGNAL_MaskAsyncEvents( FALSE );
+
+      wsi_unlink(pwsi);
+      if( _wsi_list == NULL && async_qid != -1 )
+        if( msgctl(async_qid, IPC_RMID, NULL) == -1 )
+        { 
+          fprintf(stderr,"failed to delete WS message queue.\n");
+        } else async_qid = -1;
+
+      if( pwsi->flags & WSI_BLOCKINGCALL )
+	  dprintf_winsock(stddeb,"\tinside blocking call!\n");
+      if( pwsi->num_async_rq )
+	  dprintf_winsock(stddeb,"\thave %i outstanding async ops!\n", pwsi->num_async_rq );
+
+      for(i = 0, j = 0, n = 0; i < WS_MAX_SOCKETS_PER_THREAD; i++)
+	if( pwsi->sock[i].fd != -1 )
+	{ 
+	  n += delete_async_op(&pwsi->sock[i]);
+          close(pwsi->sock[i].fd); j++; 
+        }
+      if( j ) 
+	  dprintf_winsock(stddeb,"\tclosed %i sockets, killed %i async selects!\n", j, n);
+
+      if( pwsi->buffer ) SEGPTR_FREE(pwsi->buffer);
+      WS_FREE(pwsi);
+      return 0;
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WSAGetLastError(void)
+{
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+  INT16		ret;
+
+  dprintf_winsock(stddeb, "WSAGetLastError(%08x)", (unsigned)pwsi);
+
+  ret = (pwsi) ? pwsi->errno : WSANOTINITIALISED;
+
+  dprintf_winsock(stddeb, " = %i\n", (int)ret);
+  return ret;
+}
+
+void WSASetLastError(INT16 iError)
+{
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WSASetLastError(%08x): %d\n", (unsigned)pwsi, (int)iError);
+
+  if( pwsi ) pwsi->errno = iError;
+}
+
+int _check_ws(LPWSINFO pwsi, ws_socket* pws)
+{
+  if( pwsi )
+    if( pwsi->flags & WSI_BLOCKINGCALL ) pwsi->errno = WSAEINPROGRESS;
+    else if( WSI_CHECK_RANGE(pwsi, pws) ) return 1;
+    else pwsi->errno = WSAENOTSOCK;
+  return 0;
+}
+
+int _check_buffer(LPWSINFO pwsi, int size)
+{
+  if( pwsi->buffer && pwsi->buflen >= size ) return 1;
+  else SEGPTR_FREE(pwsi->buffer);
+  pwsi->buffer = (char*)SEGPTR_ALLOC((pwsi->buflen = size)); 
+  return (pwsi->buffer != NULL);
+}
+
+/* ----- socket operations */
+
+SOCKET16 WINSOCK_accept(SOCKET16 s, struct sockaddr *addr, INT16 *addrlen16)
+{
+  ws_socket*	pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO	pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_ACCEPT(%08x): socket %04x\n", 
+				   (unsigned)pwsi, (UINT16)s); 
+  if( _check_ws(pwsi, pws) )
+  {
+     int 	sock, fd_flags, addrlen32 = *addrlen16;
+
+     /* this is how block info is supposed to be used -
+      * WSAIsBlocking() would then check WSI_BLOCKINGCALL bit.
+      */
+
+     fd_flags = fcntl(pws->fd, F_GETFL, 0);
+     if( !(fd_flags & O_NONBLOCK) ) pwsi->flags |= WSI_BLOCKINGCALL; 
+
+     if( (sock = accept(pws->fd, addr, &addrlen32)) >= 0 )
+     {
+        ws_socket*	pnew = wsi_alloc_socket(pwsi, sock); 
+	notify_client(pws, WS_FD_ACCEPT);
+        if( pnew )
+        {
+	  if( pws->p_aop )
+	      init_async_select(pnew, pws->p_aop->hWnd,
+				      pws->p_aop->uMsg,
+				      pws->p_aop->flags & ~WS_FD_ACCEPT );
+
+	  pwsi->flags &= ~WSI_BLOCKINGCALL; 
+	  return (SOCKET16)WS_PTR2HANDLE(pnew);
+        } 
+	else pwsi->errno = WSAENOBUFS;
+     } 
+     else pwsi->errno = wsaErrno();
+
+     pwsi->flags &= ~WSI_BLOCKINGCALL;
+  }
+  return INVALID_SOCKET;
+}
+
+INT16 WINSOCK_bind(SOCKET16 s, struct sockaddr *name, INT16 namelen)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_BIND(%08x): socket %04x, ptr %8x, length %d\n", 
+			   (unsigned)pwsi, s, (int) name, namelen);
+#if 0
+  dump_sockaddr(name);
+#endif
+
+  if ( _check_ws(pwsi, pws) )
+    if (namelen >= sizeof(*name)) 
+       if ( ((struct sockaddr_in *)name)->sin_family == AF_INET )
+	  if ( bind(pws->fd, name, namelen) < 0 ) 
+	  {
+	     int	loc_errno = errno;
+	     dprintf_winsock(stddeb,"\tfailure - errno = %i\n", errno);
+	     errno = loc_errno;
+	     switch(errno)
+	     {
+		case EBADF: pwsi->errno = WSAENOTSOCK; break;
+		case EADDRNOTAVAIL: pwsi->errno = WSAEINVAL; break;
+		default: pwsi->errno = wsaErrno();
+	     }
+	  }
+	  else return 0;
+       else pwsi->errno = WSAEAFNOSUPPORT;
+    else pwsi->errno = WSAEFAULT;
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_closesocket(SOCKET16 s)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_CLOSE(%08x): socket %08x\n", (unsigned)pwsi, s);
+
+  if( _check_ws(pwsi, pws) )
+  { 
+    int		fd = pws->fd;
+
+    delete_async_op(pws);
+    pws->p_aop = NULL; pws->fd = -1;
+    pws->flags = (unsigned)pwsi->last_free;
+    pwsi->last_free = pws - &pwsi->sock[0];
+    if (close(fd) < 0) pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
+    else return 0;
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_connect(SOCKET16 s, struct sockaddr *name, INT16 namelen)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_CONNECT(%08x): socket %04x, ptr %8x, length %d\n", 
+			   (unsigned)pwsi, s, (int) name, namelen);
+#if 0
+  dump_sockaddr(name);
+#endif
+
+  if( _check_ws(pwsi, pws) )
+  {
+    if (connect(pws->fd, name, namelen) == 0) 
+    { 
+	if( pws->p_aop )
+	    /* we need to notify handler process if
+	     * connect() succeeded NOT in response to winsock message
+	     */
+	    notify_client(pws, WS_FD_CONNECTED);
+
+        pws->flags &= ~(WS_FD_INACTIVE | WS_FD_CONNECT); 
+        return 0; 
+    }
+    pwsi->errno = (errno == EINPROGRESS) ? WSAEWOULDBLOCK : wsaErrno();
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_getpeername(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_GETPEERNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
+			   (unsigned)pwsi, s, (int) name, *namelen);
+  if( _check_ws(pwsi, pws) )
+  {
+    int	namelen32 = *namelen;
+    if (getpeername(pws->fd, name, &namelen32) == 0) 
+    { 
+#if 0
+	dump_sockaddr(name);
+#endif
+       *namelen = (INT16)namelen32; 
+        return 0; 
+    }
+    pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_getsockname(SOCKET16 s, struct sockaddr *name, INT16 *namelen)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_GETSOCKNAME(%08x): socket: %04x, ptr %8x, ptr %8x\n", 
+			  (unsigned)pwsi, s, (int) name, (int) *namelen);
+  if( _check_ws(pwsi, pws) )
+  {
+    int namelen32 = *namelen;
+    if (getsockname(pws->fd, name, &namelen32) == 0)
+    { 
+	*namelen = (INT16)namelen32; 
+	 return 0; 
+    }
+    pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_getsockopt(SOCKET16 s, INT16 level, 
+			 INT16 optname, char *optval, INT16 *optlen)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WSA_GETSOCKOPT(%08x): socket: %04x, opt %d, ptr %8x, ptr %8x\n", 
+			   (unsigned)pwsi, s, level, (int) optval, (int) *optlen);
+
+  if( _check_ws(pwsi, pws) )
+  {
+     int	optlen32 = *optlen;
+
+     convert_sockopt(&level, &optname);
+     if (getsockopt(pws->fd, (int) level, optname, optval, &optlen32) == 0 )
+     { *optlen = (INT16)optlen32; return 0; }
+     pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno();
+  }
+  return SOCKET_ERROR;
+}
+
+u_long  WINSOCK_htonl(u_long hostlong)   { return( htonl(hostlong) ); }         
+u_short WINSOCK_htons(u_short hostshort) { return( htons(hostshort) ); }
+u_long  WINSOCK_inet_addr(char *cp)      { return( inet_addr(cp) ); }
+u_long  WINSOCK_ntohl(u_long netlong)    { return( ntohl(netlong) ); }
+u_short WINSOCK_ntohs(u_short netshort)  { return( ntohs(netshort) ); }
+
+SEGPTR WINSOCK_inet_ntoa(struct in_addr in)
+{
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+  char*		s = inet_ntoa(in);
+
+  if( pwsi )
+  {
+    if( s == NULL ) { pwsi->errno = wsaErrno(); return NULL; }
+    if( _check_buffer( pwsi, 32 ) )
+    { 
+      strncpy(pwsi->buffer, s, 32 );
+      return SEGPTR_GET(pwsi->buffer); 
+    }
+    pwsi->errno = WSAENOBUFS;
+  }
+  return (SEGPTR)NULL;
+}
+
+INT16 WINSOCK_ioctlsocket(SOCKET16 s, UINT32 cmd, UINT32 *argp)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_IOCTL(%08x): socket %04x, cmd %08x, ptr %8x\n", 
+			  (unsigned)pwsi, s, cmd, (unsigned) argp);
+  if( _check_ws(pwsi, pws) )
+  {
+    long 	newcmd  = cmd;
+
+    switch( cmd )
+    {
+	case WS_FIONREAD:   newcmd=FIONREAD; break;
+	case WS_FIONBIO:    newcmd=FIONBIO;  
+			    if( pws->p_aop && *argp == 0 ) 
+			    { 
+				pwsi->errno = WSAEINVAL; 
+				return SOCKET_ERROR; 
+			    }
+			    break;
+	case WS_SIOCATMARK: newcmd=SIOCATMARK; break;
+	case WS_IOW('f',125,u_long): 
+			  fprintf(stderr,"Warning: WS1.1 shouldn't be using async I/O\n");
+			  pwsi->errno = WSAEINVAL; return SOCKET_ERROR;
+	default:	  fprintf(stderr,"Warning: Unknown WS_IOCTL cmd (%08x)\n", cmd);
+    }
+    if( ioctl(pws->fd, newcmd, (char*)argp ) == 0 ) return 0;
+    pwsi->errno = (errno == EBADF) ? WSAENOTSOCK : wsaErrno(); 
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_listen(SOCKET16 s, INT16 backlog)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_LISTEN(%08x): socket %04x, backlog %d\n", 
+			  (unsigned)pwsi, s, backlog);
+  if( _check_ws(pwsi, pws) )
+  {
+    if( !pws->p_aop )
+    {
+      int  fd_flags = fcntl(pws->fd, F_GETFL, 0);
+      if( !(fd_flags & O_NONBLOCK) ) pws->flags |= WS_FD_ACCEPT;
+    }
+    else notify_client(pws, WS_FD_ACCEPT);
+
+    if (listen(pws->fd, backlog) == 0) return 0;
+    pwsi->errno = wsaErrno();
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_recv(SOCKET16 s, char *buf, INT16 len, INT16 flags)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_RECV(%08x): socket %04x, buf %8x, len %d, flags %d",
+                          (unsigned)pwsi, s, (unsigned)buf, len, flags);
+  if( _check_ws(pwsi, pws) )
+  {
+    int length;
+    if ((length = recv(pws->fd, buf, len, flags)) >= 0) 
+    { 
+	dprintf_winsock(stddeb, " -> %i bytes\n", length);
+	notify_client(pws, WS_FD_READ);
+	return (INT16)length;
+    }
+    pwsi->errno = wsaErrno();
+  }
+  dprintf_winsock(stddeb, " -> ERROR\n");
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_recvfrom(SOCKET16 s, char *buf, INT16 len, INT16 flags, 
+		struct sockaddr *from, INT16 *fromlen16)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_RECVFROM(%08x): socket %04x, ptr %08x, len %d, flags %d\n",
+                          (unsigned)pwsi, s, (unsigned)buf, len, flags);
+  if( _check_ws(pwsi, pws) )
+  {
+    int length, fromlen32 = *fromlen16;
+    if ((length = recvfrom(pws->fd, buf, len, flags, from, &fromlen32)) >= 0) 
+    {   
+      *fromlen16 = fromlen32; 
+       notify_client(pws, WS_FD_READ);
+       return (INT16)length;
+    }
+    pwsi->errno = wsaErrno();
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_select(INT16 nfds, ws_fd_set *ws_readfds,
+				 ws_fd_set *ws_writefds,
+				 ws_fd_set *ws_exceptfds, struct timeval *timeout)
+{
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+	
+  dprintf_winsock(stddeb, "WS_SELECT(%08x): nfds %d (ignored), read %8x, write %8x, excp %8x\n", 
+	  (unsigned) pwsi, nfds, (unsigned) ws_readfds, (unsigned) ws_writefds, (unsigned) ws_exceptfds);
+
+  if( pwsi )
+  {
+     int         highfd = 0;
+     fd_set      readfds, writefds, exceptfds;
+
+     fd_set_normalize(&readfds, pwsi, ws_readfds, &highfd);
+     fd_set_normalize(&writefds, pwsi, ws_writefds, &highfd);
+     fd_set_normalize(&exceptfds, pwsi, ws_exceptfds, &highfd);
+
+     if( (highfd = select(highfd + 1, &readfds, &writefds, &exceptfds, timeout)) >= 0 )
+     {
+	  if( highfd )
+	  {
+	    fd_set_update(pwsi, &readfds, ws_readfds);
+	    fd_set_update(pwsi, &writefds, ws_writefds);
+ 	    fd_set_update(pwsi, &exceptfds, ws_exceptfds);
+	  }
+	  return highfd; 
+     }
+     pwsi->errno = wsaErrno();
+  } 
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_send(SOCKET16 s, char *buf, INT16 len, INT16 flags)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_SEND(%08x): socket %04x, ptr %08x, length %d, flags %d\n", 
+			  (unsigned)pwsi, s, (unsigned) buf, len, flags);
+  if( _check_ws(pwsi, pws) )
+  {
+    int		length;
+    if ((length = send(pws->fd, buf, len, flags)) < 0 ) 
+    {  
+	length = SOCKET_ERROR;
+	pwsi->errno = wsaErrno();
+    }
+    notify_client(pws, WS_FD_WRITE);
+    return (INT16)length;
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_sendto(SOCKET16 s, char *buf, INT16 len, INT16 flags,
+		     struct sockaddr *to, INT16 tolen)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_SENDTO(%08x): socket %04x, ptr %08x, length %d, flags %d\n",
+                          (unsigned)pwsi, s, (unsigned) buf, len, flags);
+  if( _check_ws(pwsi, pws) )
+  {
+    int		length;
+
+    if ((length = sendto(pws->fd, buf, len, flags, to, tolen)) < 0 )
+    {
+	length = SOCKET_ERROR;
+        pwsi->errno = wsaErrno();
+    }
+    notify_client(pws, WS_FD_WRITE);
+    return (INT16)length;
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_setsockopt(SOCKET16 s, INT16 level, INT16 optname, 
+			 char *optval, INT16 optlen)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_SETSOCKOPT(%08x): socket %04x, level %d, opt %d, ptr %08x, len %d\n",
+			  (unsigned)pwsi, s, level, optname, (int) optval, optlen);
+  if( _check_ws(pwsi, pws) )
+  {
+    int		linger32[2];
+    convert_sockopt(&level, &optname);
+    if( optname == SO_LINGER )
+    {
+	INT16*	   ptr = (INT16*)optval;
+        linger32[0] = ptr[0];
+	linger32[1] = ptr[1]; 
+	optval = (char*)&linger32;
+	optlen = sizeof(linger32);
+    }
+    if (setsockopt(pws->fd, level, optname, optval, optlen) == 0) return 0;
+    pwsi->errno = wsaErrno();
+  }
+  return SOCKET_ERROR;
+}
+
+INT16 WINSOCK_shutdown(SOCKET16 s, INT16 how)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_SHUTDOWN(%08x): socket %04x, how %i\n",
+			   (unsigned)pwsi, s, how );
+  if( _check_ws(pwsi, pws) )
+  {
+    pws->flags  = WS_FD_INACTIVE;
+    delete_async_op(pws);
+
+    if (shutdown(pws->fd, how) == 0) return 0;
+    pwsi->errno = wsaErrno();
+  }
+  return SOCKET_ERROR;
+}
+
+SOCKET16 WINSOCK_socket(INT16 af, INT16 type, INT16 protocol)
+{
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_SOCKET(%08x): af=%d type=%d protocol=%d\n", 
+			  (unsigned)pwsi, af, type, protocol);
+
+  if( pwsi )
+  {
+    int		sock;
+
+    /* check the socket family */
+    switch(af) 
+    {
+	case AF_INET:
+	case AF_UNSPEC: break;
+	default:        pwsi->errno = WSAEAFNOSUPPORT; return INVALID_SOCKET;
+    }
+
+    /* check the socket type */
+    switch(type) 
+    {
+	case SOCK_STREAM:
+	case SOCK_DGRAM:
+	case SOCK_RAW: break;
+	default:       pwsi->errno = WSAESOCKTNOSUPPORT; return INVALID_SOCKET;
+    }
+
+    /* check the protocol type */
+    if ( protocol < 0 )  /* don't support negative values */
+    { pwsi->errno = WSAEPROTONOSUPPORT; return INVALID_SOCKET; }
+
+    if ( af == AF_UNSPEC)  /* did they not specify the address family? */
+        switch(protocol) 
+	{
+          case IPPROTO_TCP:
+             if (type == SOCK_STREAM) { af = AF_INET; break; }
+          case IPPROTO_UDP:
+             if (type == SOCK_DGRAM)  { af = AF_INET; break; }
+          default: pwsi->errno = WSAEPROTOTYPE; return INVALID_SOCKET;
+        }
+
+    if ((sock = socket(af, type, protocol)) >= 0) 
+    {
+        ws_socket*      pnew = wsi_alloc_socket(pwsi, sock);
+
+/*	printf("created %04x (%i)\n", sock, (UINT16)WS_PTR2HANDLE(pnew));
+ */
+        if( pnew ) return (SOCKET16)WS_PTR2HANDLE(pnew);
+        else pwsi->errno = WSAENOBUFS;
+    }
+
+    if (errno == EPERM) /* raw socket denied */
+    {
+        fprintf(stderr, "WS_SOCKET: not enough privileges\n");
+        pwsi->errno = WSAESOCKTNOSUPPORT;
+    } pwsi->errno = wsaErrno();
+  }
+ 
+  dprintf_winsock(stddeb, "\t\tfailed!\n");
+  return INVALID_SOCKET;
+}
+    
+
+/* ----- database functions 
+ *
+ * Note that ws_...ent structures we return have SEGPTR pointers inside them.
+ */
+
+static char*	NULL_STRING = "NULL";
+
+/*
+struct WIN_hostent *
+*/
+SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT16 len, INT16 type)
+{
+  LPWSINFO      	pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_GetHostByAddr(%08x): ptr %8x, len %d, type %d\n", 
+			  (unsigned)pwsi, (unsigned) addr, len, type);
+  if( pwsi )
+  {
+    struct hostent* 	host;
+    if( (host = gethostbyaddr(addr, len, type)) != NULL )
+      if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
+          return SEGPTR_GET(pwsi->buffer);
+      else pwsi->errno = WSAENOBUFS;
+    else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+  } 
+  return NULL;
+}
+
+/*
+struct WIN_hostent *
+*/
+SEGPTR WINSOCK_gethostbyname(const char *name)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_GetHostByName(%08x): %s\n",
+                          (unsigned)pwsi, (name)?name:"NULL");
+  if( pwsi )
+  {
+    struct hostent*     host;
+    if( (host = gethostbyname(name)) != NULL )
+      if( WS_dup_he(pwsi, host, WS_DUP_SEGPTR) )
+          return SEGPTR_GET(pwsi->buffer);
+      else pwsi->errno = WSAENOBUFS;
+    else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+  }
+  return NULL;
+}
+
+INT16 WINSOCK_gethostname(char *name, INT16 namelen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_GetHostName(%08x): name %s, len %d\n", 
+			  (unsigned)pwsi, (name)?name:NULL_STRING, namelen);
+  if( pwsi )
+  {
+    if (gethostname(name, namelen) == 0) return 0;
+    pwsi->errno = (errno == EINVAL) ? WSAEFAULT : wsaErrno();
+  }
+  return SOCKET_ERROR;
+}
+
+/*
+struct WIN_protoent *
+*/
+SEGPTR WINSOCK_getprotobyname(char *name)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_GetProtoByName(%08x): %s\n",
+                          (unsigned)pwsi, (name)?name:NULL_STRING);
+  if( pwsi )
+  {
+    struct protoent*     proto;
+    if( (proto = getprotobyname(name)) != NULL )
+      if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
+          return SEGPTR_GET(pwsi->buffer);
+      else pwsi->errno = WSAENOBUFS;
+    else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+  }
+  return NULL;
+}
+
+/*
+struct WIN_protoent *
+*/
+SEGPTR WINSOCK_getprotobynumber(INT16 number)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_GetProtoByNumber(%08x): %i\n", (unsigned)pwsi, number);
+
+  if( pwsi )
+  {
+    struct protoent*     proto;
+    if( (proto = getprotobynumber(number)) != NULL )
+      if( WS_dup_pe(pwsi, proto, WS_DUP_SEGPTR) )
+          return SEGPTR_GET(pwsi->buffer);
+      else pwsi->errno = WSAENOBUFS;
+    else pwsi->errno = WSANO_DATA;
+  }
+  return NULL;
+}
+
+/*
+struct WIN_servent *
+*/
+SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_GetServByName(%08x): '%s', '%s'\n", 
+			  (unsigned)pwsi, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING);
+
+  if( pwsi )
+  {
+    struct servent*     serv;
+    if( (serv = getservbyname(name, proto)) != NULL )
+      if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
+          return SEGPTR_GET(pwsi->buffer);
+      else pwsi->errno = WSAENOBUFS;
+    else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+  }
+  return NULL;
+}
+
+/*
+struct WIN_servent *
+*/
+SEGPTR WINSOCK_getservbyport(INT16 port, const char *proto)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_GetServByPort(%08x): %i, '%s'\n",
+                          (unsigned)pwsi, (int)port, (proto)?proto:NULL_STRING);
+  if( pwsi )
+  {
+    struct servent*     serv;
+    if( (serv = getservbyport(port, proto)) != NULL )
+      if( WS_dup_se(pwsi, serv, WS_DUP_SEGPTR) )
+          return SEGPTR_GET(pwsi->buffer);
+      else pwsi->errno = WSAENOBUFS;
+    else pwsi->errno = (h_errno < 0) ? wsaErrno() : wsaHerrno();
+  }
+  return NULL;
+}
+
+
+/* ----------------------------------- Windows sockets extensions -- *
+ *								     *
+ * ----------------------------------------------------------------- */
+
+static int aop_control(ws_async_op* p_aop, int flag )
+{
+  unsigned	lLength;
+
+  read(p_aop->fd[0], &lLength, sizeof(unsigned));
+  if( LOWORD(lLength) )
+    if( LOWORD(lLength) <= p_aop->buflen )
+    {
+      char* buffer = (char*)PTR_SEG_TO_LIN(p_aop->buffer_base);
+      read(p_aop->fd[0], buffer, LOWORD(lLength));
+      switch( p_aop->flags )
+      {
+	case WSMSG_ASYNC_HOSTBYNAME:
+	case WSMSG_ASYNC_HOSTBYADDR: 
+	     fixup_wshe((struct ws_hostent*)buffer, p_aop->buffer_base); break;
+	case WSMSG_ASYNC_PROTOBYNAME:
+	case WSMSG_ASYNC_PROTOBYNUM:
+	     fixup_wspe((struct ws_protoent*)buffer, p_aop->buffer_base); break;
+	case WSMSG_ASYNC_SERVBYNAME:
+	case WSMSG_ASYNC_SERVBYPORT:
+	     fixup_wsse((struct ws_servent*)buffer, p_aop->buffer_base); break;
+	default:
+	     if( p_aop->flags ) fprintf(stderr,"Received unknown async request!\n"); 
+	     return AOP_CONTROL_REMOVE;
+      }
+    }
+    else lLength =  ((UINT32)LOWORD(lLength)) | ((unsigned)WSAENOBUFS << 16);
+
+#if 0
+  printf("async op completed: hWnd [%04x], uMsg [%04x], aop [%04x], event [%08x]\n",
+	 p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
+#endif
+
+  PostMessage(p_aop->hWnd, p_aop->uMsg, (HANDLE16)WS_PTR2HANDLE(p_aop), (LPARAM)lLength);
+  return AOP_CONTROL_REMOVE;
+}
+
+
+static HANDLE16 __WSAsyncDBQuery(LPWSINFO pwsi, HWND16 hWnd, UINT16 uMsg, LPCSTR init,
+				 INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen, UINT32 flag)
+{
+  /* queue 'flag' request and fork off its handler */
+
+  async_ctl.ws_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op));
+
+  if( async_ctl.ws_aop )
+  {
+      HANDLE16        handle = (HANDLE16)WS_PTR2HANDLE(async_ctl.ws_aop);
+
+      if( pipe(async_ctl.ws_aop->fd) == 0 )
+      {
+	async_ctl.ws_aop->init = (char*)init;
+	async_ctl.lLength = len;
+	async_ctl.lEvent = type;
+
+        async_ctl.ws_aop->hWnd = hWnd;
+        async_ctl.ws_aop->uMsg = uMsg;
+
+	async_ctl.ws_aop->buffer_base = sbuf; async_ctl.ws_aop->buflen = buflen;
+	async_ctl.ws_aop->flags = flag;
+	async_ctl.ws_aop->aop_control = &aop_control;
+	WINSOCK_link_async_op( async_ctl.ws_aop );
+
+        async_ctl.ws_aop->pid = fork();
+        if( async_ctl.ws_aop->pid )
+        {
+            close(async_ctl.ws_aop->fd[1]);        /* write endpoint */
+
+           /* Damn, BSD'ish SIGIO doesn't work on pipes/streams
+            *
+            * async_io(async_ctl.ws_aop->fd[0], 1);
+            */
+
+            dprintf_winsock(stddeb, "\tasync_op = %04x (child %i)\n",
+                                    handle, async_ctl.ws_aop->pid);
+            return handle;
+        } else
+                /* child process */
+                 {
+                   close(async_ctl.ws_aop->fd[0]); /* read endpoint */
+		   switch(flag)
+		   {
+		     case WSMSG_ASYNC_HOSTBYADDR:
+		     case WSMSG_ASYNC_HOSTBYNAME:
+ 			WS_do_async_gethost(pwsi,flag);
+		     case WSMSG_ASYNC_PROTOBYNUM:
+		     case WSMSG_ASYNC_PROTOBYNAME:
+			WS_do_async_getproto(pwsi,flag);
+		     case WSMSG_ASYNC_SERVBYPORT:
+		     case WSMSG_ASYNC_SERVBYNAME:
+			WS_do_async_getserv(pwsi,flag);
+		   }
+                 }
+      }
+      WS_FREE(async_ctl.ws_aop);
+      pwsi->errno = wsaErrno();
+  } else pwsi->errno = WSAEWOULDBLOCK;
+  return 0;
+}
+
+HANDLE16 WSAAsyncGetHostByAddr(HWND16 hWnd, UINT16 uMsg, LPCSTR addr,
+                               INT16 len, INT16 type, SEGPTR sbuf, INT16 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetHostByAddr(%08x): hwnd %04x, msg %04x, addr %08x[%i]\n",
+                          (unsigned)pwsi, hWnd, uMsg, (unsigned)addr , len );
+
+  if( pwsi ) 
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, addr, len,
+			    type, sbuf, buflen, WSMSG_ASYNC_HOSTBYADDR );
+  return 0;
+}
+
+
+HANDLE16 WSAAsyncGetHostByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
+                               SEGPTR sbuf, INT16 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetHostByName(%08x): hwnd %04x, msg %04x, host %s, buffer %i\n",
+                          (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (int)buflen );
+
+  if( pwsi )
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
+                            0, sbuf, buflen, WSMSG_ASYNC_HOSTBYNAME );
+  return 0;
+}                     
+
+
+HANDLE16 WSAAsyncGetProtoByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
+                                SEGPTR sbuf, INT16 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetProtoByName(%08x): hwnd %04x, msg %04x, protocol %s\n",
+                          (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING );
+
+  if( pwsi )
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
+                            0, sbuf, buflen, WSMSG_ASYNC_PROTOBYNAME );
+  return 0;
+}
+
+
+HANDLE16 WSAAsyncGetProtoByNumber(HWND16 hWnd, UINT16 uMsg, INT16 number, 
+                                  SEGPTR sbuf, INT16 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetProtoByNumber(%08x): hwnd %04x, msg %04x, num %i\n",
+                          (unsigned)pwsi, hWnd, uMsg, number );
+
+  if( pwsi )
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, NULL, 0,
+                            number, sbuf, buflen, WSMSG_ASYNC_PROTOBYNUM );
+  return 0;
+}
+
+
+HANDLE16 WSAAsyncGetServByName(HWND16 hWnd, UINT16 uMsg, LPCSTR name, 
+                               LPCSTR proto, SEGPTR sbuf, INT16 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetServByName(%08x): hwnd %04x, msg %04x, name %s, proto %s\n",
+                   (unsigned)pwsi, hWnd, uMsg, (name)?name:NULL_STRING, (proto)?proto:NULL_STRING );
+
+  if( pwsi )
+  { 
+    async_ctl.buffer = (char*)proto;
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, name, 0,
+                            0, sbuf, buflen, WSMSG_ASYNC_SERVBYNAME );
+  }
+  return 0;
+}
+
+
+HANDLE16 WSAAsyncGetServByPort(HWND16 hWnd, UINT16 uMsg, INT16 port, 
+			       LPCSTR proto, SEGPTR sbuf, INT16 buflen)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncGetServByPort(%08x): hwnd %04x, msg %04x, port %i, proto %s\n",
+                           (unsigned)pwsi, hWnd, uMsg, port, (proto)?proto:NULL_STRING );
+
+  if( pwsi )
+    return __WSAsyncDBQuery(pwsi, hWnd, uMsg, proto, 0,
+                            port, sbuf, buflen, WSMSG_ASYNC_SERVBYPORT );
+  return 0;
+}
+
+INT16 WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+  ws_async_op*		p_aop = (ws_async_op*)WS_HANDLE2PTR(hAsyncTaskHandle);
+
+  dprintf_winsock(stddeb, "WS_CancelAsyncRequest(%08x): handle %04x\n", 
+			   (unsigned)pwsi, hAsyncTaskHandle);
+  if( pwsi )
+    if( WINSOCK_check_async_op(p_aop) )
+    {
+  	kill(p_aop->pid, SIGKILL); 
+	waitpid(p_aop->pid, NULL, 0);
+	close(p_aop->fd[0]);
+	WINSOCK_unlink_async_op(p_aop);
+	WS_FREE(p_aop);
+	return 0;
+    }
+    else pwsi->errno = WSAEINVAL;
+  return SOCKET_ERROR;
+}
+
+/* ----- asynchronous select() */
+
+int delete_async_op(ws_socket* pws)
+{
+  if( pws->p_aop )
+  {
+    kill(pws->p_aop->pid, SIGKILL);
+    waitpid(pws->p_aop->pid, NULL, 0);
+    WS_FREE(pws->p_aop); return 1;
+    pws->flags &= WS_FD_INTERNAL;
+  }
+  return 0;
+}
+
+void _sigusr1_handler_parent(int sig)
+{
+  /* child process puts MTYPE_CLIENT data packet into the
+   * 'async_qid' message queue and signals us with SIGUSR1.
+   * This handler reads the queue and posts 'uMsg' notification
+   * message.
+   */
+
+  ipc_packet		ipack;
+
+  signal( SIGUSR1, _sigusr1_handler_parent);
+  while( msgrcv(async_qid, (struct msgbuf*)&ipack,
+          MTYPE_CLIENT_SIZE, MTYPE_CLIENT, IPC_NOWAIT) != -1 )
+  {
+    if( ipack.wParam && abs((short)ipack.wParam) < 32768 )
+    {
+      ws_socket*        pws = (ws_socket*)WS_HANDLE2PTR(ipack.wParam);
+      if( pws->p_aop && abs((char*)_ws_stub - (char*)pws->p_aop) < 32768 )
+      {
+	  pws->flags &= ~(ipack.lParam);
+#if 0
+          printf("async event - hWnd %04x, uMsg %04x [%08x]\n",
+                  pws->p_aop->hWnd, pws->p_aop->uMsg, ipack.lParam );
+#endif
+	  PostMessage(pws->p_aop->hWnd, pws->p_aop->uMsg, 
+		     (WPARAM16)ipack.wParam, (LPARAM)ipack.lParam );
+      }
+      else fprintf(stderr,"AsyncSelect:stray async_op in socket %04x!\n", ipack.wParam);
+    }
+    else fprintf(stderr,"AsyncSelect:stray socket at %04x!\n", ipack.wParam);
+  }
+}
+
+int notify_client( ws_socket* pws, unsigned flag )
+{
+  if( pws->p_aop && ((pws->p_aop->flags & flag) ||
+		     (flag == WS_FD_CONNECTED && pws->flags & WS_FD_CONNECT)) )
+  {
+     async_ctl.ip.mtype = MTYPE_PARENT;
+     async_ctl.ip.lParam = flag;
+     while( msgsnd(async_qid, (struct msgbuf*)&(async_ctl.ip),
+                               MTYPE_PARENT_SIZE, 0) == -1 )
+     { 
+	if( errno == EINTR ) continue;
+	else
+	{
+	    perror("AsyncSelect(parent)"); 
+	    delete_async_op(pws);
+	    pws->flags &= WS_FD_INTERNAL;
+	    return 0;
+	}
+     }
+     kill(pws->p_aop->pid, SIGUSR1);
+     return 1;
+  }
+  return 0;
+}
+
+INT16 init_async_select(ws_socket* pws, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
+{
+    ws_async_op*        p_aop;
+
+    if( delete_async_op(pws) )  /* delete old async handler if any */
+    {
+      pws->p_aop = NULL;
+      pws->flags &= WS_FD_INTERNAL;
+    }
+    if( lEvent == 0 ) return 0;
+
+    /* setup async handler - some data may be redundant */
+
+    WINSOCK_unblock_io(pws->fd, 1);
+    if( (p_aop = (ws_async_op*)WS_ALLOC(sizeof(ws_async_op))) )
+    {
+      p_aop->hWnd = hWnd;
+      p_aop->uMsg = uMsg;
+      pws->p_aop = p_aop;
+
+      async_ctl.lEvent = p_aop->flags = lEvent;
+      async_ctl.ws_sock = pws;
+      async_ctl.ip.wParam = (UINT16)WS_PTR2HANDLE(pws);
+      async_ctl.ip.lParam = 0;
+
+      p_aop->pid = fork();
+      if( p_aop->pid != -1 )
+        if( p_aop->pid == 0 ) WINSOCK_do_async_select(); /* child process */
+	else pws->flags |= lEvent;
+
+      signal( SIGUSR1, _sigusr1_handler_parent );
+      return 0;                                  /* Wine process */
+    }
+    return SOCKET_ERROR;
+}
+
+INT16 WSAAsyncSelect(SOCKET16 s, HWND16 hWnd, UINT16 uMsg, UINT32 lEvent)
+{
+  ws_socket*    pws  = (ws_socket*)WS_HANDLE2PTR(s);
+  LPWSINFO      pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_AsyncSelect(%08x): %04x, hWnd %04x, uMsg %04x, event %08x\n",
+			  (unsigned)pwsi, s, hWnd, uMsg, (unsigned)lEvent );
+  if( _check_ws(pwsi, pws) )
+    if( init_async_select(pws, hWnd, uMsg, lEvent) == 0 ) return 0;
+    else pwsi->errno = WSAENOBUFS;
+  return SOCKET_ERROR; 
+}
+
+/* ----- miscellaneous */
+
+INT16 __WSAFDIsSet(SOCKET16 fd, ws_fd_set *set)
+{
+  int i = set->fd_count;
+  
+  dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n",fd,(unsigned long)set);
+    
+  while (i--)
+      if (set->fd_array[i] == fd) return 1;
+  return 0;
+}                                                            
+
+BOOL16 WSAIsBlocking(void)
+{
+  /* By default WinSock should set all its sockets to non-blocking mode
+   * and poll in PeekMessage loop when processing "blocking" ones. This 
+   * function * is supposed to tell if program is in this loop. Our 
+   * blocking calls are truly blocking so we always return FALSE.
+   *
+   * Note: It is allowed to call this function without prior WSAStartup().
+   */
+
+  dprintf_winsock(stddeb, "WS_IsBlocking()\n");
+  return FALSE;
+}
+
+INT16 WSACancelBlockingCall(void)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_CancelBlockingCall(%08x)\n", (unsigned)pwsi);
+
+  if( pwsi ) return 0;
+  return SOCKET_ERROR;
+}
+
+FARPROC16 WSASetBlockingHook(FARPROC16 lpBlockFunc)
+{
+  FARPROC16		prev;
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_SetBlockingHook(%08x): hook %08x\n", 
+			  (unsigned)pwsi, (unsigned) lpBlockFunc);
+
+  if( pwsi ) { 
+      prev = pwsi->blocking_hook; 
+      pwsi->blocking_hook = lpBlockFunc; 
+      return prev; 
+  }
+  return 0;
+}
+
+INT16 WSAUnhookBlockingHook(void)
+{
+  LPWSINFO              pwsi = wsi_find(GetCurrentTask());
+
+  dprintf_winsock(stddeb, "WS_UnhookBlockingHook(%08x)\n", (unsigned)pwsi);
+  if( pwsi ) return (INT16)(INT32)(pwsi->blocking_hook = (FARPROC16)NULL);
+  return SOCKET_ERROR;
+}
+
+VOID
+WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,LPDWORD x5,LPDWORD x6) 
+{
+	fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n",
+		x1,x2,x3,x4,x5,x6
+	);
+	fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n",
+		x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0
+	);
+	return;
+}
+/* ----------------------------------- end of API stuff */
+
+
+
+/* ----------------------------------- helper functions */
+
+static int list_size(char** l, int item_size)
+{
+  int i,j = 0;
+  if(l)
+  { for(i=0;l[i];i++) 
+	j += (item_size) ? item_size : strlen(l[i]) + 1;
+    j += (i + 1) * sizeof(char*); }
+  return j;
+}
+
+static int list_dup(char** l_src, char* ref, char* base, int item_size)
+{ 
+   /* base is either either equal to ref or 0 or SEGPTR */
+
+   char*		p = ref;
+   char**		l_to = (char**)ref;
+   int			i,j,k;
+
+   for(j=0;l_src[j];j++) ;
+   p += (j + 1) * sizeof(char*);
+   for(i=0;i<j;i++)
+   { l_to[i] = base + (p - ref);
+     k = ( item_size ) ? item_size : strlen(l_src[i]) + 1;
+     memcpy(p, l_src[i], k); p += k; }
+   l_to[i] = NULL;
+   return (p - ref);
+}
+
+/* ----- hostent */
+
+static int hostent_size(struct hostent* p_he)
+{
+  int size = 0;
+  if( p_he )
+  { size  = sizeof(struct hostent); 
+    size += strlen(p_he->h_name) + 1;
+    size += list_size(p_he->h_aliases, 0);  
+    size += list_size(p_he->h_addr_list, p_he->h_length ); }
+  return size;
+}
+
+int WS_dup_he(LPWSINFO pwsi, struct hostent* p_he, int flag)
+{
+   /* Duplicate hostent structure and flatten data (with its pointers)
+    * into pwsi->buffer. Internal pointers can be linear, SEGPTR, or 
+    * relative to 0 depending on "flag" value. Return data size (also 
+    * in the pwsi->buflen).
+    */
+
+   int size = hostent_size(p_he);
+   if( size )
+   {
+     char*           p_name,*p_aliases,*p_addr,*p_base,*p;
+
+     _check_buffer(pwsi, size);
+     p = pwsi->buffer;
+     p_base = (flag & WS_DUP_OFFSET) ? NULL
+				     : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
+     p += (flag & WS_DUP_SEGPTR) ? sizeof(struct ws_hostent) : sizeof(struct hostent);
+     p_name = p;
+     strcpy(p, p_he->h_name); p += strlen(p) + 1;
+     p_aliases = p;
+     p += list_dup(p_he->h_aliases, p, p_base + (p - pwsi->buffer), 0);
+     p_addr = p;
+     list_dup(p_he->h_addr_list, p, p_base + (p - pwsi->buffer), p_he->h_length);
+     if( !(flag & WS_DUP_SEGPTR) )
+     { struct hostent* p_to = (struct hostent*)pwsi->buffer;
+       p_to->h_addrtype = p_he->h_addrtype; p_to->h_length = p_he->h_length;
+       p_to->h_name = p_base + (p_name - pwsi->buffer);
+       p_to->h_aliases = (char**)(p_base + (p_aliases - pwsi->buffer));
+       p_to->h_addr_list = (char**)(p_base + (p_addr - pwsi->buffer)); }
+     else
+     { struct ws_hostent* p_to = (struct ws_hostent*)pwsi->buffer;
+       p_to->h_addrtype = (INT16)p_he->h_addrtype; 
+       p_to->h_length = (INT16)p_he->h_length;
+       p_to->h_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
+       p_to->h_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer));
+       p_to->h_addr_list = (SEGPTR)(p_base + (p_addr - pwsi->buffer));
+       return (size + sizeof(struct ws_hostent) - sizeof(struct hostent)); }
+   }
+   return size;
+}
+
+void fixup_wshe(struct ws_hostent* p_wshe, SEGPTR base)
+{
+   /* add 'base' to ws_hostent pointers to convert them from offsets */ 
+
+   int i;
+   unsigned*	p_aliases,*p_addr;
+
+   p_aliases = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_aliases); 
+   p_addr = (unsigned*)((char*)p_wshe + (unsigned)p_wshe->h_addr_list);
+   ((unsigned)(p_wshe->h_name)) += (unsigned)base;
+   ((unsigned)(p_wshe->h_aliases)) += (unsigned)base;
+   ((unsigned)(p_wshe->h_addr_list)) += (unsigned)base;
+   for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
+   for(i=0;p_addr[i];i++) p_addr[i] += (unsigned)base;
+}
+
+/* ----- protoent */
+
+static int protoent_size(struct protoent* p_pe)
+{
+  int size = 0;
+  if( p_pe )
+  { size  = sizeof(struct protoent);
+    size += strlen(p_pe->p_name) + 1;
+    size += list_size(p_pe->p_aliases, 0); }
+  return size;
+}
+
+int WS_dup_pe(LPWSINFO pwsi, struct protoent* p_pe, int flag)
+{
+   int size = protoent_size(p_pe);
+   if( size )
+   {
+     char*            p_name,*p_aliases,*p_base,*p;
+
+     _check_buffer(pwsi, size);
+     p = pwsi->buffer; 
+     p_base = (flag & WS_DUP_OFFSET) ? NULL
+				     : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
+     p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_protoent) : sizeof(struct protoent);
+     p_name = p;
+     strcpy(p, p_pe->p_name); p += strlen(p) + 1;
+     p_aliases = p;
+     list_dup(p_pe->p_aliases, p, p_base + (p - pwsi->buffer), 0);
+     if( !(flag & WS_DUP_NATIVE) )
+     { struct protoent* p_to = (struct protoent*)pwsi->buffer;
+       p_to->p_proto = p_pe->p_proto;
+       p_to->p_name = p_base + (p_name - pwsi->buffer); 
+       p_to->p_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
+     else
+     { struct ws_protoent* p_to = (struct ws_protoent*)pwsi->buffer;
+       p_to->p_proto = (INT16)p_pe->p_proto;
+       p_to->p_name = (SEGPTR)(p_base) + (p_name - pwsi->buffer);
+       p_to->p_aliases = (SEGPTR)((p_base) + (p_aliases - pwsi->buffer)); 
+       return (size + sizeof(struct ws_protoent) - sizeof(struct protoent)); }
+   }
+   return size;
+}
+
+void fixup_wspe(struct ws_protoent* p_wspe, SEGPTR base)
+{
+   int i;
+   unsigned*       p_aliases = (unsigned*)((char*)p_wspe + (unsigned)p_wspe->p_aliases); 
+   ((unsigned)(p_wspe->p_name)) += (unsigned)base;
+   ((unsigned)(p_wspe->p_aliases)) += (unsigned)base;
+   for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
+}
+
+/* ----- servent */
+
+static int servent_size(struct servent* p_se)
+{
+  int size = 0;
+  if( p_se )
+  { size += sizeof(struct servent);
+    size += strlen(p_se->s_proto) + strlen(p_se->s_name) + 2;
+    size += list_size(p_se->s_aliases, 0); }
+  return size;
+}
+
+int WS_dup_se(LPWSINFO pwsi, struct servent* p_se, int flag)
+{
+   int size = servent_size(p_se);
+   if( size )
+   {
+     char*           p_name,*p_aliases,*p_proto,*p_base,*p;
+
+     _check_buffer(pwsi, size);
+     p = pwsi->buffer;
+     p_base = (flag & WS_DUP_OFFSET) ? NULL 
+				     : ((flag & WS_DUP_SEGPTR) ? (char*)SEGPTR_GET(p) : p);
+     p += (flag & WS_DUP_SEGPTR)? sizeof(struct ws_servent) : sizeof(struct servent);
+     p_name = p;
+     strcpy(p, p_se->s_name); p += strlen(p) + 1;
+     p_proto = p;
+     strcpy(p, p_se->s_proto); p += strlen(p) + 1;
+     p_aliases = p;
+     list_dup(p_se->s_aliases, p, p_base + (p - pwsi->buffer), 0);
+
+     if( !(flag & WS_DUP_SEGPTR) )
+     { struct servent* p_to = (struct servent*)pwsi->buffer;
+       p_to->s_port = p_se->s_port;
+       p_to->s_name = p_base + (p_name - pwsi->buffer); 
+       p_to->s_proto = p_base + (p_proto - pwsi->buffer);
+       p_to->s_aliases = (char**)(p_base + (p_aliases - pwsi->buffer)); }
+     else
+     { struct ws_servent* p_to = (struct ws_servent*)pwsi->buffer;
+       p_to->s_port = (INT16)p_se->s_port;
+       p_to->s_name = (SEGPTR)(p_base + (p_name - pwsi->buffer));
+       p_to->s_proto = (SEGPTR)(p_base + (p_proto - pwsi->buffer));
+       p_to->s_aliases = (SEGPTR)(p_base + (p_aliases - pwsi->buffer)); 
+       return (size + sizeof(struct ws_servent) - sizeof(struct servent)); }
+   }
+   return size;
+}
+
+void fixup_wsse(struct ws_servent* p_wsse, SEGPTR base)
+{
+   int i;
+   unsigned*       p_aliases = (unsigned*)((char*)p_wsse + (unsigned)p_wsse->s_aliases);
+   ((unsigned)(p_wsse->s_name)) += (unsigned)base;
+   ((p_wsse->s_proto)) += (unsigned)base;
+   ((p_wsse->s_aliases)) += (unsigned)base;
+   for(i=0;p_aliases[i];i++) p_aliases[i] += (unsigned)base;
+}
+
+/* ----------------------------------- error handling */
+
+UINT16 wsaErrno(void)
+{
+    int	loc_errno = errno; 
+#if defined(__FreeBSD__)
+       dprintf_winsock(stderr, "winsock: errno %d, (%s).\n", 
+                			 errno, sys_errlist[errno]);
+#else
+       dprintf_winsock(stderr, "winsock: errno %d\n", errno);
+#endif
+
+    switch(loc_errno)
+    {
+	case EINTR:		return WSAEINTR;
+	case EBADF:		return WSAEBADF;
+	case EACCES:		return WSAEACCES;
+	case EFAULT:		return WSAEFAULT;
+	case EINVAL:		return WSAEINVAL;
+	case EMFILE:		return WSAEMFILE;
+	case EWOULDBLOCK:	return WSAEWOULDBLOCK;
+	case EINPROGRESS:	return WSAEINPROGRESS;
+	case EALREADY:		return WSAEALREADY;
+	case ENOTSOCK:		return WSAENOTSOCK;
+	case EDESTADDRREQ:	return WSAEDESTADDRREQ;
+	case EMSGSIZE:		return WSAEMSGSIZE;
+	case EPROTOTYPE:	return WSAEPROTOTYPE;
+	case ENOPROTOOPT:	return WSAENOPROTOOPT;
+	case EPROTONOSUPPORT:	return WSAEPROTONOSUPPORT;
+	case ESOCKTNOSUPPORT:	return WSAESOCKTNOSUPPORT;
+	case EOPNOTSUPP:	return WSAEOPNOTSUPP;
+	case EPFNOSUPPORT:	return WSAEPFNOSUPPORT;
+	case EAFNOSUPPORT:	return WSAEAFNOSUPPORT;
+	case EADDRINUSE:	return WSAEADDRINUSE;
+	case EADDRNOTAVAIL:	return WSAEADDRNOTAVAIL;
+	case ENETDOWN:		return WSAENETDOWN;
+	case ENETUNREACH:	return WSAENETUNREACH;
+	case ENETRESET:		return WSAENETRESET;
+	case ECONNABORTED:	return WSAECONNABORTED;
+	case ECONNRESET:	return WSAECONNRESET;
+	case ENOBUFS:		return WSAENOBUFS;
+	case EISCONN:		return WSAEISCONN;
+	case ENOTCONN:		return WSAENOTCONN;
+	case ESHUTDOWN:		return WSAESHUTDOWN;
+	case ETOOMANYREFS:	return WSAETOOMANYREFS;
+	case ETIMEDOUT:		return WSAETIMEDOUT;
+	case ECONNREFUSED:	return WSAECONNREFUSED;
+	case ELOOP:		return WSAELOOP;
+	case ENAMETOOLONG:	return WSAENAMETOOLONG;
+	case EHOSTDOWN:		return WSAEHOSTDOWN;
+	case EHOSTUNREACH:	return WSAEHOSTUNREACH;
+	case ENOTEMPTY:		return WSAENOTEMPTY;
+#ifdef EPROCLIM
+	case EPROCLIM:		return WSAEPROCLIM;
+#endif
+#ifdef EUSERS
+	case EUSERS:		return WSAEUSERS;
+#endif
+#ifdef EDQUOT
+	case EDQUOT:		return WSAEDQUOT;
+#endif
+	case ESTALE:		return WSAESTALE;
+	case EREMOTE:		return WSAEREMOTE;
+
+       /* just in case we ever get here and there are no problems */
+	case 0:			return 0;
+        default:
+		fprintf(stderr, "winsock: unknown errno %d!\n", errno);
+		return WSAEOPNOTSUPP;
+    }
+}
+
+UINT16 wsaHerrno(void)
+{
+    int		loc_errno = h_errno;
+
+#if defined(__FreeBSD__)
+    dprintf_winsock(stderr, "winsock: h_errno %d, (%s).\n", 
+               	    h_errno, sys_errlist[h_errno]);
+#else
+    dprintf_winsock(stderr, "winsock: h_errno %d.\n", h_errno);
+#ifndef sun
+    if( debugging_winsock )  herror("wine: winsock: wsaherrno");
+#endif
+#endif
+
+    switch(loc_errno)
+    {
+	case HOST_NOT_FOUND:	return WSAHOST_NOT_FOUND;
+	case TRY_AGAIN:		return WSATRY_AGAIN;
+	case NO_RECOVERY:	return WSANO_RECOVERY;
+	case NO_DATA:		return WSANO_DATA; 
+
+	case 0:			return 0;
+        default:
+		fprintf(stderr, "winsock: unknown h_errno %d!\n", h_errno);
+		return WSAEOPNOTSUPP;
+    }
+}
+
+
diff --git a/misc/winsock_async.c b/misc/winsock_async.c
new file mode 100644
index 0000000..6596b5f
--- /dev/null
+++ b/misc/winsock_async.c
@@ -0,0 +1,486 @@
+/*
+ * asynchronous winsock services
+ * 
+ * (C) 1996 Alex Korobka.
+ *
+ * FIXME: telftp16 (ftp part) stalls on AsyncSelect with FD_ACCEPT.
+ */
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <sys/wait.h>
+#include <errno.h>
+
+#include "windows.h"
+#include "winsock.h"
+#include "debug.h"
+
+#define __WS_ASYNC_DEBUG	0
+
+static int		_async_io_max_fd = 0;
+static fd_set		__async_io_fdset;
+static ws_async_op*	__async_op_list = NULL;
+
+extern ws_async_ctl	async_ctl;
+extern int		async_qid;
+
+fd_set		 fd_read, fd_write, fd_excp;
+
+/* ----------------------------------- async/non-blocking I/O */
+
+int WINSOCK_async_io(int fd, int async)
+{
+    int fd_flags;
+
+    fcntl(fd, F_SETOWN, getpid());
+
+    fd_flags = fcntl(fd, F_GETFL, 0);
+    if (fcntl(fd, F_SETFL, (async)? fd_flags | FASYNC
+                                  : fd_flags & ~FASYNC ) != -1) return 0;
+    return -1;
+}
+
+int WINSOCK_unblock_io(int fd, int noblock)
+{
+    int fd_flags;
+
+    fd_flags = fcntl(fd, F_GETFL, 0);
+    if (fcntl(fd, F_SETFL, (noblock)? fd_flags |  O_NONBLOCK
+                                    : fd_flags & ~O_NONBLOCK ) != -1) return 0;
+    return -1;
+}
+
+int WINSOCK_check_async_op(ws_async_op* p_aop)
+{
+  ws_async_op*   p = __async_op_list;
+  while( p ) if( p == p_aop ) return 1;
+	     else p = p->next;
+  return 0;
+}
+
+void WINSOCK_cancel_async_op(HTASK16 hTask)
+{
+  ws_async_op*   p = __async_op_list;
+  while( p ) 
+     if(hTask == GetWindowTask16(p->hWnd)) 
+        p->flags = 0;
+}
+
+void WINSOCK_link_async_op(ws_async_op* p_aop)
+{
+  if( __async_op_list ) __async_op_list->prev = p_aop;
+  else FD_ZERO(&__async_io_fdset);
+
+  p_aop->next = __async_op_list; 
+  p_aop->prev = NULL;
+  __async_op_list = p_aop;
+
+  FD_SET(p_aop->fd[0], &__async_io_fdset);
+  if( p_aop->fd[0] > _async_io_max_fd ) 
+		     _async_io_max_fd = p_aop->fd[0];
+}
+
+void WINSOCK_unlink_async_op(ws_async_op* p_aop)
+{
+  if( p_aop == __async_op_list ) __async_op_list = p_aop->next;
+  else
+  { p_aop->prev->next = p_aop->next;
+    if( p_aop->next ) p_aop->next->prev = p_aop->prev; }
+  FD_CLR(p_aop->fd[0], &__async_io_fdset); 
+  if( p_aop->fd[0] == _async_io_max_fd )
+		      _async_io_max_fd--;
+}
+
+/* ----------------------------------- SIGIO handler -
+ *
+ * link_async_op/unlink_async_op allow to install generic
+ * async IO handlers (provided that aop_control function is defined).
+ *
+ * Note: AsyncGetXbyY expilicitly raise it.
+ */
+
+void WINSOCK_sigio(int signal)
+{
+ struct timeval         timeout;
+ fd_set                 check_set;
+ ws_async_op*		p_aop;
+
+ check_set = __async_io_fdset;
+ bzero(&timeout,sizeof(timeout));
+
+ while( select(_async_io_max_fd + 1,
+              &check_set, NULL, NULL, &timeout) > 0)
+ {
+   for( p_aop = __async_op_list;
+	p_aop ; p_aop = p_aop->next )
+      if( FD_ISSET(p_aop->fd[0], &check_set) )
+          if( p_aop->aop_control(p_aop, AOP_IO) == AOP_CONTROL_REMOVE )
+	  {
+	      if( p_aop->pid ) 
+	      { 
+		kill(p_aop->pid, SIGKILL);
+		waitpid(p_aop->pid, NULL, 0);  
+	      }
+	      WINSOCK_unlink_async_op( p_aop );
+	  }
+   check_set = __async_io_fdset;
+  }
+}
+
+/* ----------------------------------- child process IPC */
+
+static void _sigusr1_handler_child(int sig)
+{
+   /* read message queue to decide which
+    * async_ctl parameters to update 
+    *
+    * Note: we don't want to have SA_RESTART on this signal
+    * handler, otherwise select() won't notice changed fd sets.
+    */
+
+   signal( SIGUSR1, _sigusr1_handler_child );
+   while( msgrcv(async_qid, (struct msgbuf*)&async_ctl.ip,
+          MTYPE_PARENT_SIZE, MTYPE_PARENT, IPC_NOWAIT) != -1 )
+   {
+       /* only ip.lParam is updated */
+#if __WS_ASYNC_DEBUG
+       printf("handler - event %08x\n", async_ctl.ip.lParam );
+#endif
+
+       switch( async_ctl.ip.lParam )
+       {
+	  /* These are events we are notified of.
+	   */
+
+          case   WS_FD_CONNECTED: async_ctl.lEvent &= ~WS_FD_CONNECT;
+				  FD_SET(async_ctl.ws_sock->fd, &fd_read);
+				  FD_SET(async_ctl.ws_sock->fd, &fd_write);
+			  	  break;
+
+          case   WS_FD_ACCEPT:  async_ctl.ws_sock->flags |= WS_FD_ACCEPT;
+				FD_SET(async_ctl.ws_sock->fd, &fd_read);
+                                FD_SET(async_ctl.ws_sock->fd, &fd_write);
+                                break;
+          case   WS_FD_OOB:     async_ctl.lEvent |= WS_FD_OOB;
+				FD_SET(async_ctl.ws_sock->fd, &fd_excp);
+                                break;
+          case   WS_FD_READ:    async_ctl.lEvent |= WS_FD_READ;
+				FD_SET(async_ctl.ws_sock->fd, &fd_read);
+                                break;
+          case   WS_FD_WRITE:   async_ctl.lEvent |= WS_FD_WRITE;
+				FD_SET(async_ctl.ws_sock->fd, &fd_write);
+                                break;
+          default:
+       }
+   }
+}
+
+static int notify_parent( unsigned flag )
+{
+  if( flag & WSMSG_ASYNC_SELECT )
+  {
+     async_ctl.ip.mtype = MTYPE_CLIENT;
+     while( msgsnd(async_qid, (struct msgbuf*)&(async_ctl.ip),
+                               MTYPE_CLIENT_SIZE, 0) == -1 )
+     {
+       if( errno == EINTR ) continue;
+       else if( errno == EIDRM ) _exit(0);
+       else 
+       { 
+	 perror("AsyncSelect(child)"); 
+	 return 0; 
+       }
+     }
+     kill(getppid(), SIGUSR1); 
+
+#if __WS_ASYNC_DEBUG
+  printf("handler - notify [%08x]\n", async_ctl.ip.lParam);
+#endif
+  }
+  else /* use half-duplex pipe to handle variable length packets */
+  {
+     write(async_ctl.ws_aop->fd[1], &async_ctl.lLength, sizeof(unsigned) );
+     write(async_ctl.ws_aop->fd[1], async_ctl.buffer, async_ctl.lLength );
+     kill(getppid(), SIGIO);    /* simulate async I/O */
+#if __WS_ASYNC_DEBUG
+  printf("handler - notify aop [%d, buf %d]\n", async_ctl.lLength, async_ctl.ws_aop->buflen);
+#endif
+     pause();
+  }
+  return 1;
+}
+
+/* ----------------------------------- async select */
+
+static void setup_fd_sets()
+{
+   FD_ZERO(&fd_read); FD_ZERO(&fd_write); FD_ZERO(&fd_excp);
+
+   if( async_ctl.lEvent & WS_FD_OOB) 
+       FD_SET(async_ctl.ws_sock->fd, &fd_excp);
+   if( async_ctl.lEvent & (WS_FD_ACCEPT | WS_FD_READ |
+			   WS_FD_CONNECT | WS_FD_CLOSE) ) 
+       FD_SET(async_ctl.ws_sock->fd, &fd_read);
+   if( async_ctl.lEvent & (WS_FD_WRITE | WS_FD_CONNECT) ) 
+       FD_SET(async_ctl.ws_sock->fd, &fd_write);
+}
+
+static void setup_sig_sets(sigset_t* sig_block)
+{
+   sigemptyset(sig_block);
+   sigaddset(sig_block, SIGUSR1);
+   sigprocmask( SIG_BLOCK, sig_block, NULL);
+   signal( SIGUSR1, _sigusr1_handler_child );
+}
+
+void WINSOCK_do_async_select()
+{
+  sigset_t    sig_block;
+  int	      bytes;
+
+  setup_sig_sets(&sig_block);
+  setup_fd_sets();
+
+  while(1)
+  {
+    int		val;
+
+    sigprocmask( SIG_UNBLOCK, &sig_block, NULL); 
+
+#if __WS_ASYNC_DEBUG
+    printf("select(2)[%i,%i,%i]... ", 
+	     FD_ISSET(async_ctl.ws_sock->fd, &fd_read),
+	     FD_ISSET(async_ctl.ws_sock->fd, &fd_write),
+	     FD_ISSET(async_ctl.ws_sock->fd, &fd_excp));
+#endif
+    if( (val = select(async_ctl.ws_sock->fd + 1, 
+		     &fd_read, &fd_write, &fd_excp, NULL)) == -1 )
+      if( errno == EINTR ) continue;
+#if __WS_ASYNC_DEBUG
+    printf("got %i events\n", val);
+#endif
+
+#if __WS_ASYNC_DEBUG
+    if( FD_ISSET(async_ctl.ws_sock->fd, &fd_read) )
+	printf("handler - read is READY! [%08x]\n", async_ctl.lEvent & (WS_FD_READ | WS_FD_CLOSE));
+#endif
+
+    sigprocmask( SIG_BLOCK, &sig_block, NULL);
+    async_ctl.ip.lParam = 0;
+    if( async_ctl.ws_sock->flags & WS_FD_ACCEPT )
+    {
+	/* listening socket */
+	
+	FD_CLR(async_ctl.ws_sock->fd, &fd_read);
+	FD_CLR(async_ctl.ws_sock->fd, &fd_write);
+
+	async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_ACCEPT, 0 );
+        notify_parent( WSMSG_ASYNC_SELECT );
+	continue;
+    }
+    else /* I/O socket */
+    {
+	if( async_ctl.lEvent & WS_FD_CONNECT )
+	{
+	  if( FD_ISSET(async_ctl.ws_sock->fd, &fd_write) ) 
+	  {
+	      /* success - reinit fd sets to start I/O */
+
+	      if( async_ctl.lEvent & (WS_FD_READ | WS_FD_CLOSE))
+		   FD_SET(async_ctl.ws_sock->fd, &fd_read);
+	      else FD_CLR(async_ctl.ws_sock->fd, &fd_read);
+	      if( async_ctl.lEvent & WS_FD_WRITE )
+		   FD_SET(async_ctl.ws_sock->fd, &fd_write);
+	      else FD_CLR(async_ctl.ws_sock->fd, &fd_write);
+
+	      async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_CONNECT, 0 );
+	      async_ctl.lEvent &= ~WS_FD_CONNECT; /* one-shot */
+	  }
+	  else if( FD_ISSET(async_ctl.ws_sock->fd, &fd_read) )
+	  {
+              /* failure - do read() to get correct errno */
+
+              if( read(async_ctl.ws_sock->fd, &bytes, 4) == -1 )
+                  async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_CONNECT, wsaErrno() );
+              else continue;
+	  } else continue; /* OOB?? */
+
+          notify_parent( WSMSG_ASYNC_SELECT );
+	}
+	else /* connected socket */
+	{
+
+	  if( async_ctl.lEvent & WS_FD_OOB )
+	    if( FD_ISSET(async_ctl.ws_sock->fd, &fd_excp) )
+	    {
+	      async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_OOB, 0 );
+	      async_ctl.lEvent &= ~WS_FD_OOB;
+	      FD_CLR(async_ctl.ws_sock->fd, &fd_excp);
+	      notify_parent( WSMSG_ASYNC_SELECT );
+	    }
+	    else FD_SET(async_ctl.ws_sock->fd, &fd_excp);
+
+          if( async_ctl.lEvent & WS_FD_WRITE )
+            if( FD_ISSET( async_ctl.ws_sock->fd, &fd_write ) )
+            {
+              async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_WRITE, 0 );
+              async_ctl.lEvent &= ~WS_FD_WRITE;
+              FD_CLR(async_ctl.ws_sock->fd, &fd_write);
+              notify_parent( WSMSG_ASYNC_SELECT );
+            }
+            else FD_SET(async_ctl.ws_sock->fd, &fd_write);
+
+	  if( async_ctl.lEvent & (WS_FD_READ | WS_FD_CLOSE) )
+	    if( FD_ISSET(async_ctl.ws_sock->fd, &fd_read) )
+	    {
+	      if( ioctl( async_ctl.ws_sock->fd, FIONREAD, (char*)&bytes) != -1 )
+	      {
+	        if( bytes )	/* got data */
+	        {
+#if __WS_ASYNC_DEBUG
+		  printf("\t%i bytes pending\n", bytes );
+#endif
+		  if( async_ctl.lEvent & WS_FD_READ )
+		  {
+		     async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_READ, 0 );
+		     async_ctl.lEvent &= ~WS_FD_READ;
+		     if( !(async_ctl.lEvent & WS_FD_CLOSE) ) 
+			   FD_CLR( async_ctl.ws_sock->fd, &fd_read );
+		  }
+		  else if( !(async_ctl.lEvent & (WS_FD_WRITE | WS_FD_OOB)) ) 
+		       {
+			  sigprocmask( SIG_UNBLOCK, &sig_block, NULL);
+			  pause();
+			  sigprocmask( SIG_BLOCK, &sig_block, NULL);
+		       }
+		       else continue;
+	        }
+	        else		/* 0 bytes to read */
+	        {
+		  val = read( async_ctl.ws_sock->fd, (char*)&bytes, 4);
+	          if( errno == EWOULDBLOCK || errno == EINTR ) 
+		  { 
+#if __WS_ASYNC_DEBUG
+		    printf("\twould block..\n");
+#endif
+		    continue;
+		  }
+		  switch( val )
+		  {
+		    case  0: errno = ENETDOWN;	/* ENETDOWN */
+		    case -1: 			/* ECONNRESET */
+			     async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_CLOSE, wsaErrno() );
+			     break;
+		    default: continue;
+		  }
+		  async_ctl.lEvent &= ~(WS_FD_CLOSE | WS_FD_READ); /* one-shot */
+		  FD_ZERO(&fd_read); FD_ZERO(&fd_write); 
+	        }
+	      }
+	      else async_ctl.ip.lParam = WSAMAKESELECTREPLY( WS_FD_READ, wsaErrno() );
+
+	      notify_parent( WSMSG_ASYNC_SELECT );
+	  }
+	  else FD_SET(async_ctl.ws_sock->fd, &fd_read);
+
+	} /* connected socket */
+    } /* I/O socket */
+  } /* while */
+}
+
+
+/* ----------------------------------- getXbyY requests */
+
+static void _async_fail()
+{
+     async_ctl.lLength =
+        (h_errno < 0) ? (unsigned)WSAMAKEASYNCREPLY( 0, wsaErrno() )
+                      : (unsigned)WSAMAKEASYNCREPLY( 0, wsaHerrno() );
+     write(async_ctl.ws_aop->fd[1], &async_ctl.lLength, sizeof(unsigned) );
+     kill(getppid(), SIGIO);    /* simulate async I/O */
+     pause();
+}
+
+void dump_ws_hostent_offset(struct ws_hostent* wshe)
+{
+  int		i;
+  char*		base = (char*)wshe;
+  unsigned*	ptr;
+
+  printf("h_name = %08x\t[%s]\n", (unsigned)wshe->h_name, base + (unsigned)wshe->h_name);
+  printf("h_aliases = %08x\t[%08x]\n", (unsigned)wshe->h_aliases, 
+				       (unsigned)(base + (unsigned)wshe->h_aliases));
+  ptr = (unsigned*)(base + (unsigned)wshe->h_aliases);
+  for(i = 0; ptr[i]; i++ )
+  {
+	printf("%i - %08x ", i + 1, ptr[i]);
+	printf(" [%s]\n", ((char*)base) + ptr[i]);
+  }
+  printf("h_length = %i\n", wshe->h_length);
+}
+
+void WS_do_async_gethost(LPWSINFO pwsi, unsigned flag )
+{  
+  int			size = 0;
+  struct hostent* 	p_he;
+
+  close(async_ctl.ws_aop->fd[0]);
+  p_he = (flag & WSMSG_ASYNC_HOSTBYNAME)
+	 ? gethostbyname(async_ctl.ws_aop->init)
+	 : gethostbyaddr(async_ctl.ws_aop->init,
+		 	 async_ctl.lLength, async_ctl.lEvent);
+  if( p_he ) size = WS_dup_he(pwsi, p_he, WS_DUP_SEGPTR | WS_DUP_OFFSET );
+  if( size )
+  {
+     async_ctl.buffer = pwsi->buffer;
+     async_ctl.lLength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
+     notify_parent( flag );
+  }
+  else _async_fail();
+  _exit(0);
+}
+
+void WS_do_async_getproto(LPWSINFO pwsi, unsigned flag )
+{
+  int			size = 0;
+  struct protoent*	p_pe;
+
+  close(async_ctl.ws_aop->fd[0]);
+  p_pe = (flag & WSMSG_ASYNC_PROTOBYNAME)
+	 ? getprotobyname(async_ctl.ws_aop->init)
+	 : getprotobynumber(async_ctl.lEvent);
+  if( p_pe ) size = WS_dup_pe(pwsi, p_pe, WS_DUP_SEGPTR | WS_DUP_OFFSET );
+  if( size )
+  {
+     async_ctl.buffer = pwsi->buffer;
+     async_ctl.lLength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
+     notify_parent( flag );
+  } 
+  else _async_fail();
+  _exit(0);
+}
+
+void WS_do_async_getserv(LPWSINFO pwsi, unsigned flag )
+{
+  int			size = 0;
+  struct servent* 	p_se;
+
+  close(async_ctl.ws_aop->fd[0]);
+  p_se = (flag & WSMSG_ASYNC_SERVBYNAME)
+	 ? getservbyname(async_ctl.ws_aop->init, async_ctl.buffer)
+	 : getservbyport(async_ctl.lEvent, async_ctl.ws_aop->init);
+  if( p_se ) size = WS_dup_se(pwsi, p_se, WS_DUP_SEGPTR | WS_DUP_OFFSET );
+  if( size )
+  {
+     async_ctl.buffer = pwsi->buffer;
+     async_ctl.lLength = (unsigned)WSAMAKEASYNCREPLY( (UINT16)size, 0 );
+     notify_parent( flag );
+  }
+  else _async_fail();
+  _exit(0);
+}
+
diff --git a/misc/winsocket.c b/misc/winsocket.c
deleted file mode 100644
index 1507a5e..0000000
--- a/misc/winsocket.c
+++ /dev/null
@@ -1,1697 +0,0 @@
-/*
- * based on Windows Sockets 1.1 specs
- * (ftp.microsoft.com:/Advsys/winsock/spec11/WINSOCK.TXT)
- * 
- * (C) 1993,1994 John Brezak, Erik Bos.
- */
- 
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/ioctl.h>
-#if defined(__svr4__)
-#include <sys/filio.h>
-#include <sys/ioccom.h>
-#endif
-#include <sys/msg.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <netdb.h>
-#include <unistd.h>
-
-#include "winsock.h"
-#include "global.h"
-#include "stddebug.h"
-#include "debug.h"
-
-#ifdef _SCO_DS
-#define _IOR _IOSR
-#define _IOW _IOSW
-#endif
-
-static WORD wsa_errno;
-static int wsa_initted;
-static key_t wine_key = 0;
-static FARPROC16 BlockFunction;
-static fd_set fd_in_use;
-
-extern int h_errno;
-
-struct ipc_packet {
-	long	mtype;
-	HANDLE16 handle;
-	HWND	hWnd;
-	WORD	wMsg;
-	LONG	lParam;
-};
-
-#ifndef WINELIB
-#pragma pack(1)
-#endif
-
-#define WINSOCK_MAX_SOCKETS	256
-#define WINSOCK_MAX_UDPDG	1024
-
-/* we are out by two with the following, is it due to byte alignment?
- * #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long)) 
- */
-#define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long) - 2)
-/*#define MTYPE 0xb0b0eb05*/
-#define MTYPE 0x30b0eb05
-
-/* These structures are Win16 only */
-
-struct WIN_hostent  {
-	SEGPTR	h_name WINE_PACKED;		/* official name of host */
-	SEGPTR	h_aliases WINE_PACKED;	/* alias list */
-	INT	h_addrtype WINE_PACKED;		/* host address type */
-	INT	h_length WINE_PACKED;		/* length of address */
-	char	**h_addr_list WINE_PACKED;	/* list of addresses from name server */
-	char	*names[2];
-	char    hostname[200];
-};
-
-struct	WIN_protoent {
-	SEGPTR	p_name WINE_PACKED;		/* official protocol name */
-	SEGPTR	p_aliases WINE_PACKED;	/* alias list */
-	INT	p_proto WINE_PACKED;		/* protocol # */
-};
-
-struct	WIN_servent {
-	SEGPTR	s_name WINE_PACKED;		/* official service name */
-	SEGPTR	s_aliases WINE_PACKED;	/* alias list */
-	INT	s_port WINE_PACKED;		/* port # */
-	SEGPTR	s_proto WINE_PACKED;		/* protocol to use */
-};
-
-typedef struct WinSock_fd_set {
-	u_short fd_count;               /* how many are SET? */
-	SOCKET  fd_array[FD_SETSIZE];   /* an array of SOCKETs */
-} WinSock_fd_set;
-                
-struct WinSockHeap {
-	char	ntoa_buffer[32];
-
-	struct	WIN_hostent hostent_addr;
-	struct	WIN_hostent hostent_name;
-	struct	WIN_protoent protoent_name;
-	struct	WIN_protoent protoent_number;
-	struct	WIN_servent servent_name;
-	struct	WIN_servent servent_port;
-
-	struct	WIN_hostent WSAhostent_addr;
-	struct	WIN_hostent WSAhostent_name;
-	struct	WIN_protoent WSAprotoent_name;
-	struct	WIN_protoent WSAprotoent_number;	
-	struct	WIN_servent WSAservent_name;
-	struct	WIN_servent WSAservent_port;
-	/* 8K scratch buffer for aliases and friends are hopefully enough */
-	char scratch[8192];
-};
-static struct WinSockHeap *Heap;
-static HGLOBAL16 HeapHandle;
-#ifndef WINELIB32
-static int ScratchPtr;
-#endif
-
-#ifndef WINELIB
-#define GET_SEG_PTR(x)	MAKELONG((int)((char*)(x)-(char*)Heap),	\
-							GlobalHandleToSel(HeapHandle))
-#else
-#define GET_SEG_PTR(x)	((SEGPTR)x)
-#endif
-
-#ifndef WINELIB
-#pragma pack(4)
-#endif
-
-#define dump_sockaddr(a) \
-	fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
-			((struct sockaddr_in *)a)->sin_family, \
-			inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
-			ntohs(((struct sockaddr_in *)a)->sin_port))
-
-#ifndef WINELIB32
-static void ResetScratch()
-{
-	ScratchPtr=0;
-}
-
-static void *scratch_alloc(int size)
-{
-	char *ret;
-	if(ScratchPtr+size > sizeof(Heap->scratch))
-		return 0;
-	ret = Heap->scratch + ScratchPtr;
-	ScratchPtr += size;
-	return ret;
-}
-
-static SEGPTR scratch_strdup(char * s)
-{
-	char *ret=scratch_alloc(strlen(s)+1);
-	strcpy(ret,s);
-	return GET_SEG_PTR(ret);
-}
-#endif
-
-static WORD wsaerrno(void)
-{
-#ifdef DEBUG_WINSOCK
-#ifndef sun
-#if defined(__FreeBSD__)
-                fprintf(stderr, "winsock: errno %d, (%s).\n", 
-                			errno, sys_errlist[errno]);
-#else
-                fprintf(stderr, "winsock: errno %d\n", errno);
-#endif
-#else
-                fprintf(stderr, "winsock: errno %d\n", errno);
-#endif
-#endif
-
-        switch(errno)
-        {
-	case EINTR:		return WSAEINTR;
-	case EBADF:		return WSAEBADF;
-	case EACCES:		return WSAEACCES;
-	case EFAULT:		return WSAEFAULT;
-	case EINVAL:		return WSAEINVAL;
-	case EMFILE:		return WSAEMFILE;
-	case EWOULDBLOCK:	return WSAEWOULDBLOCK;
-	case EINPROGRESS:	return WSAEINPROGRESS;
-	case EALREADY:		return WSAEALREADY;
-	case ENOTSOCK:		return WSAENOTSOCK;
-	case EDESTADDRREQ:	return WSAEDESTADDRREQ;
-	case EMSGSIZE:		return WSAEMSGSIZE;
-	case EPROTOTYPE:	return WSAEPROTOTYPE;
-	case ENOPROTOOPT:	return WSAENOPROTOOPT;
-	case EPROTONOSUPPORT:	return WSAEPROTONOSUPPORT;
-	case ESOCKTNOSUPPORT:	return WSAESOCKTNOSUPPORT;
-	case EOPNOTSUPP:	return WSAEOPNOTSUPP;
-	case EPFNOSUPPORT:	return WSAEPFNOSUPPORT;
-	case EAFNOSUPPORT:	return WSAEAFNOSUPPORT;
-	case EADDRINUSE:	return WSAEADDRINUSE;
-	case EADDRNOTAVAIL:	return WSAEADDRNOTAVAIL;
-	case ENETDOWN:		return WSAENETDOWN;
-	case ENETUNREACH:	return WSAENETUNREACH;
-	case ENETRESET:		return WSAENETRESET;
-	case ECONNABORTED:	return WSAECONNABORTED;
-	case ECONNRESET:	return WSAECONNRESET;
-	case ENOBUFS:		return WSAENOBUFS;
-	case EISCONN:		return WSAEISCONN;
-	case ENOTCONN:		return WSAENOTCONN;
-	case ESHUTDOWN:		return WSAESHUTDOWN;
-	case ETOOMANYREFS:	return WSAETOOMANYREFS;
-	case ETIMEDOUT:		return WSAETIMEDOUT;
-	case ECONNREFUSED:	return WSAECONNREFUSED;
-	case ELOOP:		return WSAELOOP;
-	case ENAMETOOLONG:	return WSAENAMETOOLONG;
-	case EHOSTDOWN:		return WSAEHOSTDOWN;
-	case EHOSTUNREACH:	return WSAEHOSTUNREACH;
-	case ENOTEMPTY:		return WSAENOTEMPTY;
-#ifdef EPROCLIM
-	case EPROCLIM:		return WSAEPROCLIM;
-#endif
-#ifdef EUSERS
-	case EUSERS:		return WSAEUSERS;
-#endif
-#ifdef EDQUOT
-	case EDQUOT:		return WSAEDQUOT;
-#endif
-	case ESTALE:		return WSAESTALE;
-	case EREMOTE:		return WSAEREMOTE;
-/* just in case we ever get here and there are no problems */
-	case 0:			return 0;
-
-        default:
-		fprintf(stderr, "winsock: unknown errorno %d!\n", errno);
-		return WSAEOPNOTSUPP;
-	}
-}
-
-static void errno_to_wsaerrno(void)
-{
-	wsa_errno = wsaerrno();
-}
-
-
-static WORD wsaherrno(void)
-{
-#if DEBUG_WINSOCK
-#ifndef sun
-#if defined(__FreeBSD__)
-                fprintf(stderr, "winsock: h_errno %d, (%s).\n", 
-                			h_errno, sys_errlist[h_errno]);
-#else
-                fprintf(stderr, "winsock: h_errno %d.\n", h_errno);
-		herror("wine: winsock: wsaherrno");
-#endif
-#else
-                fprintf(stderr, "winsock: h_errno %d\n", h_errno);
-#endif
-#endif
-
-        switch(h_errno)
-        {
-	case HOST_NOT_FOUND:	return WSAHOST_NOT_FOUND;
-	case TRY_AGAIN:		return WSATRY_AGAIN;
-	case NO_RECOVERY:	return WSANO_RECOVERY;
-	case NO_DATA:		return WSANO_DATA; 
-/* just in case we ever get here and there are no problems */
-	case 0:			return 0;
-
-
-        default:
-		fprintf(stderr, "winsock: unknown h_errorno %d!\n", h_errno);
-		return WSAEOPNOTSUPP;
-	}
-}
-
-
-static void herrno_to_wsaerrno(void)
-{
-	wsa_errno = wsaherrno();
-}
-
-
-static void convert_sockopt(INT *level, INT *optname)
-{
-/* $%#%!#! why couldn't they use the same values for both winsock and unix ? */
-
-	switch (*level) {
-		case -1: 
-			*level = SOL_SOCKET;
-			switch (*optname) {
-			case 0x01:	*optname = SO_DEBUG;
-					break;
-			case 0x04:	*optname = SO_REUSEADDR;
-					break;
-			case 0x08:	*optname = SO_KEEPALIVE;
-					break;
-			case 0x10:	*optname = SO_DONTROUTE;
-					break;
-			case 0x20:	*optname = SO_BROADCAST;
-					break;
-			case 0x80:	*optname = SO_LINGER;
-					break;
-			case 0x100:	*optname = SO_OOBINLINE;
-					break;
-			case 0x1001:	*optname = SO_SNDBUF;
-					break;
-			case 0x1002:	*optname = SO_RCVBUF;
-					break;
-			case 0x1007:	*optname = SO_ERROR;
-					break;
-			case 0x1008:	*optname = SO_TYPE;
-					break;
-			default: 
-					fprintf(stderr, "convert_sockopt() unknown optname %d\n", *optname);
-					break;
-			}
-			break;
-		case 6:	*optname = IPPROTO_TCP;
-	}
-}
-
-#ifndef WINELIB
-static SEGPTR copy_stringlist(char **list)
-{
-	SEGPTR *s_list;
-	int i;
-	for(i=0;list[i];i++)
-		;
-	s_list = scratch_alloc(sizeof(SEGPTR)*(i+1));
-	for(i=0;list[i];i++)
-	{
-		void *copy = scratch_alloc(strlen(list[i])+1);
-		strcpy(copy,list[i]);
-		s_list[i]=GET_SEG_PTR(copy);
-	}
-	s_list[i]=0;
-	return GET_SEG_PTR(s_list);
-}
-	
-
-static void CONVERT_HOSTENT(struct WIN_hostent *heapent, struct hostent *host)
-{
-	SEGPTR *addr_list;
-	int i;
-	ResetScratch();
-	strcpy(heapent->hostname,host->h_name);
-	heapent->h_name = GET_SEG_PTR(heapent->hostname);
-	/* Convert aliases. Have to create array with FAR pointers */
-	if(!host->h_aliases)
-		heapent->h_aliases = 0;
-	else
-		heapent->h_aliases = copy_stringlist(host->h_aliases);
-
-	heapent->h_addrtype = host->h_addrtype;
-	heapent->h_length = host->h_length;
-	for(i=0;host->h_addr_list[i];i++)
-		;
-	addr_list=scratch_alloc(sizeof(SEGPTR)*(i+1));
-	heapent->h_addr_list = (char**)GET_SEG_PTR(addr_list);
-	for(i=0;host->h_addr_list[i];i++)
-	{
-		void *addr=scratch_alloc(host->h_length);
-		memcpy(addr,host->h_addr_list[i],host->h_length);
-		addr_list[i]=GET_SEG_PTR(addr);
-	}
-	addr_list[i]=0;
-}
-
-static void CONVERT_PROTOENT(struct WIN_protoent *heapent, 
-	struct protoent *proto)
-{
-	ResetScratch();
-	heapent->p_name= scratch_strdup(proto->p_name);
-	heapent->p_aliases=proto->p_aliases ? 
-			copy_stringlist(proto->p_aliases) : 0;
-	heapent->p_proto = proto->p_proto;
-}
-
-static void CONVERT_SERVENT(struct WIN_servent *heapent, struct servent *serv)
-{
-	ResetScratch();
-	heapent->s_name = scratch_strdup(serv->s_name);
-	heapent->s_aliases = serv->s_aliases ?
-			copy_stringlist(serv->s_aliases) : 0;
-	heapent->s_port = serv->s_port;
-	heapent->s_proto = scratch_strdup(serv->s_proto);
-}
-#else
-#define CONVERT_HOSTENT(a,b)	memcpy(a, &b, sizeof(a))
-#define CONVERT_PROTOENT(a,b)	memcpy(a, &b, sizeof(a))
-#define CONVERT_SERVENT(a,b)	memcpy(a, &b, sizeof(a))
-#endif
-
-SOCKET WINSOCK_accept(SOCKET s, struct sockaddr *addr, INT *addrlen)
-{
-	int sock;
-
-	dprintf_winsock(stddeb, "WSA_accept: socket %d, ptr %8x, length %d\n", s, (int) addr, *addrlen);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return INVALID_SOCKET;
-	}
-
-	if ((sock = accept(s, addr, (int *) addrlen)) < 0) {
-        	errno_to_wsaerrno();
-        	return INVALID_SOCKET;
-	}
-	return sock;
-}
-
-INT WINSOCK_bind(SOCKET s, struct sockaddr *name, INT namelen)
-{
-
-	dprintf_winsock(stddeb, "WSA_bind: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
-	dump_sockaddr(name);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (namelen < sizeof(*name)) {
-		WSASetLastError(WSAEFAULT);
-		return SOCKET_ERROR;
-	}
-
-	/* check the socket family */
-	if ( ((struct sockaddr_in *)name)->sin_family != AF_INET ) {
-		WSASetLastError(WSAEAFNOSUPPORT);
-		return SOCKET_ERROR;
-	}
-
-	if (bind(s, name, namelen) < 0) {
-		switch(errno) {
-		case EBADF:
-			WSASetLastError(WSAENOTSOCK);
-			break;
-		case EADDRNOTAVAIL:
-			WSASetLastError(WSAEINVAL);
-			break;
-		default:
-			errno_to_wsaerrno();
-			break;
-		}
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-INT WINSOCK_closesocket(SOCKET s)
-{
-	dprintf_winsock(stddeb, "WSA_closesocket: socket %d\n", s);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	FD_CLR(s, &fd_in_use);
-
-	if (close(s) < 0) {
-		if (errno == EBADF)
-			WSASetLastError(WSAENOTSOCK);
-		else
-        		errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-INT WINSOCK_connect(SOCKET s, struct sockaddr *name, INT namelen)
-{
-	dprintf_winsock(stddeb, "WSA_connect: socket %d, ptr %8x, length %d\n", s, (int) name, namelen);
-	dump_sockaddr(name);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (connect(s, name, namelen) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-INT WINSOCK_getpeername(SOCKET s, struct sockaddr *name, INT *namelen)
-{
-	dprintf_winsock(stddeb, "WSA_getpeername: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, *namelen);
-	dump_sockaddr(name);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (getpeername(s, name, (int *) namelen) < 0) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-INT WINSOCK_getsockname(SOCKET s, struct sockaddr *name, INT *namelen)
-{
-	dprintf_winsock(stddeb, "WSA_getsockname: socket: %d, ptr %8x, ptr %8x\n", s, (int) name, (int) *namelen);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (getsockname(s, name, (int *) namelen) < 0) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-INT
-WINSOCK_getsockopt(SOCKET s, INT level, INT optname, char *optval, INT *optlen)
-{
-	dprintf_winsock(stddeb, "WSA_getsockopt: socket: %d, opt %d, ptr %8x, ptr %8x\n", s, level, (int) optval, (int) *optlen);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	convert_sockopt(&level, &optname);
-
-	if (getsockopt(s, (int) level, optname, optval, (int *) optlen) < 0) {
-		if (errno == EBADF)
-			WSASetLastError(WSAENOTSOCK);
-		else
-        		errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-u_long WINSOCK_htonl(u_long hostlong)
-{
-	return( htonl(hostlong) );
-}         
-
-u_short WINSOCK_htons(u_short hostshort)
-{
-	return( htons(hostshort) );
-}
-
-u_long WINSOCK_inet_addr(char *cp)
-{
-	return( inet_addr(cp) );
-}
-
-char *WINSOCK_inet_ntoa(struct in_addr in)
-{
-	char *s;
-
-/*	dprintf_winsock(stddeb, "WSA_inet_ntoa: %8lx\n", (int) in);*/
-
-	if ((s = inet_ntoa(in)) == NULL) {
-        	errno_to_wsaerrno();
-        	return NULL;
-	}
-
-	strncpy(Heap->ntoa_buffer, s, sizeof(Heap->ntoa_buffer) );
-
-	return (char *) GET_SEG_PTR(&Heap->ntoa_buffer);
-}
-
-INT WINSOCK_ioctlsocket(SOCKET s, u_long cmd, u_long *argp)
-{
-	long newcmd;
-	u_long *newargp;
-	char *ctlname;
-	dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %lX, ptr %8x\n", s, cmd, (int) argp);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	/* Why can't they all use the same ioctl numbers */
-	newcmd=cmd;
-	newargp=argp;
-	ctlname=0;
-	if(cmd == _IOR('f',127,u_long))
-	{
-		ctlname="FIONREAD";
-		newcmd=FIONREAD;
-	}else 
-	if(cmd == _IOW('f',126,u_long) || cmd == _IOR('f',126,u_long))
-	{
-		ctlname="FIONBIO";
-		newcmd=FIONBIO;
-	}else
-	if(cmd == _IOW('f',125,u_long))
-	{
-		ctlname="FIOASYNC";
-		newcmd=FIOASYNC;
-	}
-
-	if(!ctlname)
-		fprintf(stderr,"Unknown winsock ioctl. Trying anyway\n");
-	else
-		dprintf_winsock(stddeb,"Recognized as %s\n", ctlname);
-	
-
-	if (ioctl(s, newcmd, newargp) < 0) {
-		if (errno == EBADF)
-			WSASetLastError(WSAENOTSOCK);
-		else
-        		errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-INT WINSOCK_listen(SOCKET s, INT backlog)
-{
-	dprintf_winsock(stddeb, "WSA_listen: socket %d, backlog %d\n", s, backlog);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (listen(s, backlog) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-u_long WINSOCK_ntohl(u_long netlong)
-{
-	return( ntohl(netlong) );
-}
-
-u_short WINSOCK_ntohs(u_short netshort)
-{
-	return( ntohs(netshort) );
-}
-
-INT WINSOCK_recv(SOCKET s, char *buf, INT len, INT flags)
-{
-	int length;
-
-	dprintf_winsock(stddeb, "WSA_recv: socket %d, ptr %8x, length %d, flags %d\n", s, (int) buf, len, flags);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if ((length = recv(s, buf, len, flags)) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return length;
-}
-
-INT WINSOCK_recvfrom(SOCKET s, char *buf, INT len, INT flags, 
-		struct sockaddr *from, int *fromlen)
-{
-	int length;
-
-	dprintf_winsock(stddeb, "WSA_recvfrom: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long)buf, len, flags);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if ((length = recvfrom(s, buf, len, flags, from, fromlen)) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return length;
-}
-
-INT WINSOCK_select(INT nfds, WinSock_fd_set *ws_readfds,
-	WinSock_fd_set *ws_writefds, WinSock_fd_set *ws_exceptfds,
-	struct timeval *timeout)
-{
-	int ret;
-	int i;
-	int count;
-	int highfd;
-	fd_set readfds,writefds,exceptfds;
-	FD_ZERO(&readfds);
-	FD_ZERO(&writefds);
-	FD_ZERO(&exceptfds);
-	
-	dprintf_winsock(stddeb, "WSA_select called: nfds %d (ignored), ptr %8lx, ptr %8lx, ptr %8lx\n", nfds, (unsigned long) ws_readfds, (unsigned long) ws_writefds, (unsigned long) ws_exceptfds);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		dprintf_winsock(stddeb, "WSA_select: returning error WSANOTINITIALISED\n");
-		return SOCKET_ERROR;
-	}
-	
-/* In some sort of attempt to be BSD-compatible, MS-Winsock accepts and
-   discards the nfds parameter.  However, the format of windoze's fd_sets
-   is totally different from the BSD standard.  So much for compatibility.
-   Hence, we must convert the winsock array-of-ints fd_set to the UNIX
-   bitmapped format. */
-
-	if(ws_readfds!=NULL) {
-		dprintf_winsock(stddeb, "readfds: (%d) ",ws_readfds->fd_count);
-		for(i=0;i<(ws_readfds->fd_count);i++) {
-			dprintf_winsock(stddeb, " %d",( (SOCKET *)&(((char *)ws_readfds)[2]) )[i]);
-			/*FD_SET(((SOCKET *)&(((char *)ws_readfds)[2]))[i], &readfds);*/
-			FD_SET(ws_readfds->fd_array[i], &readfds);
-		}
-		dprintf_winsock(stddeb, "\n");
-	} else {
-		dprintf_winsock(stddeb, "readfds: (null)\n");
-	}
-	if(ws_writefds!=NULL) {
-		dprintf_winsock(stddeb, "writefds: (%d) ",ws_writefds->fd_count);
-		for(i=0;i<(ws_writefds->fd_count);i++) {
-			dprintf_winsock(stddeb, " %d",( (SOCKET *)&(((char *)ws_writefds)[2]) )[i]);
-			/*FD_SET(((SOCKET *)&(((char *)ws_writefds)[2]))[i], &writefds);*/
-			FD_SET(ws_writefds->fd_array[i], &writefds);
-		}
-		dprintf_winsock(stddeb, "\n");
-	} else {
-		dprintf_winsock(stddeb, "writefds: (null)\n");
-	}
-	if(ws_exceptfds!=NULL) {
-		dprintf_winsock(stddeb, "exceptfds: (%d) ",ws_exceptfds->fd_count);
-		for(i=0;i<(ws_exceptfds->fd_count);i++) {
-			dprintf_winsock(stddeb, " %d",( (SOCKET *)&(((char *)ws_exceptfds)[2]) )[i]);
-			/*FD_SET(((SOCKET *)&(((char *)ws_exceptfds)[2]))[i], &exceptfds);*/
-			FD_SET(ws_exceptfds->fd_array[i], &exceptfds);
-		}
-		dprintf_winsock(stddeb, "\n");
-	} else {
-		dprintf_winsock(stddeb, "exceptfds: (null)\n");
-	}
-	
-	/* Make the select() call */
-	dprintf_winsock(stddeb, "WSA_select: calling select()\n");
-	highfd=256; /* We should count them, but this works */
-	ret=select(highfd, &readfds, &writefds, &exceptfds, timeout);
-	dprintf_winsock(stddeb, "WSA_select: select() returned %d\n",ret);
-	if(ret<0) {
-		errno_to_wsaerrno();
-		dprintf_winsock(stddeb, "WSA_select returning: Error %d\n",SOCKET_ERROR);
-		return SOCKET_ERROR;
-	}
-	
-	/* update the winsock fd sets */
-	if(ws_readfds!=NULL) {
-		dprintf_winsock(stddeb, "readfds: ");
-		count=0;
-		for(i=0;i<highfd;i++) {
-			if(FD_ISSET(i,&readfds)) {
-				dprintf_winsock(stddeb, " %d",i);
-				ws_readfds->fd_array[count++]=i;
-			}
-		}
-		dprintf_winsock(stddeb, "  (%d)\n",count);
-		ws_readfds->fd_count=count;
-	} else {
-		dprintf_winsock(stddeb, "readfds: (null)\n");
-	}
-	if(ws_writefds!=NULL) {
-		dprintf_winsock(stddeb, "writefds: ");
-		count=0;
-		for(i=0;i<highfd;i++) {
-			if(FD_ISSET(i,&writefds)) {
-				dprintf_winsock(stddeb, " %d",i);
-				ws_writefds->fd_array[count++]=i;
-			}
-		}
-		dprintf_winsock(stddeb, "  (%d)\n",count);
-		ws_writefds->fd_count=count;
-	} else {
-		dprintf_winsock(stddeb, "writefds: (null)\n");
-	}
-	if(ws_exceptfds!=NULL) {
-		dprintf_winsock(stddeb, "exceptfds: ");
-		count=0;
-		for(i=0;i<highfd;i++) {
-			if(FD_ISSET(i,&exceptfds)) {
-				dprintf_winsock(stddeb, " %d",i);
-				ws_exceptfds->fd_array[count++]=i;
-			}
-		}
-		dprintf_winsock(stddeb, "  (%d)\n",count);
-		ws_exceptfds->fd_count=count;
-	} else {
-		dprintf_winsock(stddeb, "exceptfds: (null)\n");
-	}
-	
-	dprintf_winsock(stddeb, "WSA_select returning: %d\n",ret);
-	return(ret);	
-}
-
-INT WINSOCK_send(SOCKET s, char *buf, INT len, INT flags)
-{
-	int length;
-
-	dprintf_winsock(stddeb, "WSA_send: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if ((length = send(s, buf, len, flags)) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return length;
-}
-
-INT WINSOCK_sendto(SOCKET s, char *buf, INT len, INT flags,
-		struct sockaddr *to, INT tolen)
-{
-	int length;
-
-	dprintf_winsock(stddeb, "WSA_sendto: socket %d, ptr %8lx, length %d, flags %d\n", s, (unsigned long) buf, len, flags);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if ((length = sendto(s, buf, len, flags, to, tolen)) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return length;
-}
-
-INT WINSOCK_setsockopt(SOCKET s, INT level, INT optname, const char *optval, 
-			INT optlen)
-{
-	dprintf_winsock(stddeb, "WSA_setsockopt: socket %d, level %d, opt %d, ptr %8x, len %d\n", s, level, optname, (int) optval, optlen);
-	convert_sockopt(&level, &optname);
-	
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (setsockopt(s, level, optname, optval, optlen) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}                                         
-
-INT WINSOCK_shutdown(SOCKET s, INT how)
-{
-	dprintf_winsock(stddeb, "WSA_shutdown: socket s %d, how %d\n", s, how);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	if (shutdown(s, how) < 0) {
-        	errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}
-
-SOCKET WINSOCK_socket(INT af, INT type, INT protocol)
-{
-    int sock;
-
-    dprintf_winsock(stddeb, "WSA_socket: af=%d type=%d protocol=%d\n", af, type, protocol);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return INVALID_SOCKET;
-	}
-
-    /* check the socket family */
-    switch(af) {
-    case AF_INET:
-    case AF_UNSPEC:
-        break;
-    default:
-        WSASetLastError(WSAEAFNOSUPPORT);
-        return INVALID_SOCKET;
-        break;
-    }
-
-    /* check the socket type */
-    switch(type) {
-    case SOCK_STREAM:
-    case SOCK_DGRAM:
-    case SOCK_RAW:
-        break;
-    default:
-        WSASetLastError(WSAESOCKTNOSUPPORT);
-        return INVALID_SOCKET;
-        break;
-    }
-
-    /* check the protocol type */
-    if ( protocol < 0 ) { /* don't support negative values */
-        WSASetLastError(WSAEPROTONOSUPPORT);
-        return INVALID_SOCKET;
-    }
-
-    if ( af == AF_UNSPEC) { /* did they not specify the address family? */
-        switch(protocol) {
-        case IPPROTO_TCP:
-             if (type == SOCK_STREAM) {
-                 af = AF_INET;
-                 break;
-             }
-        case IPPROTO_UDP:
-             if (type == SOCK_DGRAM) {
-                 af = AF_INET;
-                 break;
-             }
-        default:
-             WSASetLastError(WSAEPROTOTYPE);
-             return INVALID_SOCKET;
-             break;
-        }
-    }
-
-    if ((sock = socket(af, type, protocol)) < 0) {
-        if (errno == EPERM) {
-            /* non super-user wants a raw socket */
-            fprintf(stderr, "WSA_socket: not enough privileges\n");
-            WSASetLastError(WSAESOCKTNOSUPPORT);
-        } else
-            errno_to_wsaerrno();
-        dprintf_winsock(stddeb, "WSA_socket: failed !\n");
-        return INVALID_SOCKET;
-    }
-    
-    if (sock > WINSOCK_MAX_SOCKETS) {
-	/* we only support socket numbers up to WINSOCK_MAX_SOCKETS.
-	 * The return value indicates no more descriptors are available
-	 */
-        WSASetLastError(WSAEMFILE);
-	return INVALID_SOCKET;
-    }
-
-    FD_SET(sock, &fd_in_use);
-
-    dprintf_winsock(stddeb, "WSA_socket: fd %d\n", sock);
-    return sock;
-}
-
-/*
-struct WIN_hostent *
-*/
-SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
-{
-	struct hostent *host;
-
-	dprintf_winsock(stddeb, "WSA_gethostbyaddr: ptr %8x, len %d, type %d\n", (int) addr, len, type);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return NULL;
-	}
-
-	if ((host = gethostbyaddr(addr, len, type)) == NULL) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return NULL;
-	}
-	CONVERT_HOSTENT(&Heap->hostent_addr, host);
-
-	return GET_SEG_PTR(&Heap->hostent_addr);
-}
-
-/*
-struct WIN_hostent *
-*/
-SEGPTR WINSOCK_gethostbyname(const char *name)
-{
-	struct hostent *host;
-
-	dprintf_winsock(stddeb, "WSA_gethostbyname: %s\n", name);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return NULL;
-	}
-
-	if ((host = gethostbyname(name)) == NULL) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return NULL;
-	}
-	CONVERT_HOSTENT(&Heap->hostent_name, host);
-
-	return GET_SEG_PTR(&Heap->hostent_name);
-}
-
-INT WINSOCK_gethostname(char *name, INT namelen)
-{
-	dprintf_winsock(stddeb, "WSA_gethostname: name %s, len %d\n", name, namelen);
-
-	if (!wsa_initted) {
-		WSASetLastError(WSANOTINITIALISED);
-        	return SOCKET_ERROR;
-	}
-
-	if (gethostname(name, namelen) < 0) {
-		if (errno == EINVAL)
-			WSASetLastError(WSAEFAULT);
-		else
-			errno_to_wsaerrno();
-        	return SOCKET_ERROR;
-	}
-	return 0;
-}          
-
-/*
-struct WIN_protoent *
-*/
-SEGPTR WINSOCK_getprotobyname(char *name)
-{
-	struct protoent *proto;
-
-	dprintf_winsock(stddeb, "WSA_getprotobyname: name %s\n", name);
-
-	if (!wsa_initted) {
-		WSASetLastError(WSANOTINITIALISED);
-        	return NULL;
-	}
-
-	if ((proto = getprotobyname(name)) == NULL) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return NULL;
-	}
-	CONVERT_PROTOENT(&Heap->protoent_name, proto);
-
-	return GET_SEG_PTR(&Heap->protoent_name);
-}
-
-/*
-struct WIN_protoent *
-*/
-SEGPTR WINSOCK_getprotobynumber(INT number)
-{
-	struct protoent *proto;
-
-	dprintf_winsock(stddeb, "WSA_getprotobynumber: num %d\n", number);
-
-	if (!wsa_initted) {
-		WSASetLastError(WSANOTINITIALISED);
-        	return NULL;
-	}
-
-	if ((proto = getprotobynumber(number)) == NULL) {
-#if 0
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-#endif
-		WSASetLastError(WSANO_DATA);
-        	return NULL;
-	}
-	CONVERT_PROTOENT(&Heap->protoent_number, proto);
-
-	return GET_SEG_PTR(&Heap->protoent_number);
-}
-
-/*
-struct WIN_servent *
-*/
-SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
-{
-	struct servent *service;
-
-	if (proto == NULL)
-		proto = "tcp";
-
-	dprintf_winsock(stddeb, "WSA_getservbyname: name %s, proto %s\n", name, proto);
-
-	if (!wsa_initted) {
-		WSASetLastError(WSANOTINITIALISED);
-        	return NULL;
-	}
-
-	if ((service = getservbyname(name, proto)) == NULL) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return NULL;
-	}
-	CONVERT_SERVENT(&Heap->servent_name, service);
-
-	return GET_SEG_PTR(&Heap->servent_name);
-}
-
-/*
-struct WIN_servent *
-*/
-SEGPTR WINSOCK_getservbyport(INT port, const char *proto)
-{
-	struct servent *service;
-
-	dprintf_winsock(stddeb, "WSA_getservbyport: port %d, name %s\n", port, proto);
-
-	if (!wsa_initted) {
-		WSASetLastError(WSANOTINITIALISED);
-        	return NULL;
-	}
-
-	if ((service = getservbyport(port, proto)) == NULL) {
-		if (h_errno < 0) {
-        		errno_to_wsaerrno();
-		} else {
-			herrno_to_wsaerrno();
-		}
-        	return NULL;
-	}
-	CONVERT_SERVENT(&Heap->servent_port, service);
-
-	return GET_SEG_PTR(&Heap->servent_port);
-}
-
-/******************** winsock specific functions ************************
- *
- */
-static HANDLE16 new_handle = 1;
-
-static HANDLE16 AllocWSAHandle(void)
-{
-	return new_handle++;
-}
-
-static void recv_message(int sig)
-{
-	static struct ipc_packet message;
-	int message_is_valid = 0;
-	BOOL result;
-
-	message.mtype = MTYPE;
-
-	signal(SIGUSR1, recv_message);
-	while (1) {
-
-		if (!message_is_valid) {
-			if (msgrcv(wine_key, (struct msgbuf*)&(message), 
-				   IPC_PACKET_SIZE, 0 /*MTYPE*/, IPC_NOWAIT) == -1) {
-				perror("wine: winsock: msgrcv");
-				break;
-			}
-		}
-
-		result = PostMessage(message.hWnd, message.wMsg,
-				     (WPARAM16)message.handle, message.lParam);
-		if (result != FALSE) {
-			message_is_valid = 1;
-			break;
-		}
-		else
-			message_is_valid = 0;
-		
-	}
-		
-    if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
-	perror("wine: winsock: msgget"); 
-}
-
-
-static void send_message( HWND hWnd, u_int wMsg, HANDLE16 handle, long lParam)
-{
-	struct ipc_packet message;
-	
-	message.mtype = MTYPE;
-	message.handle = handle;
-	message.hWnd = hWnd;
-	message.wMsg = wMsg;
-	message.lParam = lParam;
-
-	if (msgsnd(wine_key, (struct msgbuf*)&(message),  
-		   IPC_PACKET_SIZE, 0/*IPC_NOWAIT*/) == -1)
-		perror("wine: winsock: msgsnd");
-
-	kill(getppid(), SIGUSR1);
-}
-
-
-HANDLE16 WSAAsyncGetHostByAddr(HWND hWnd, u_int wMsg, LPCSTR addr,
-                             INT len, INT type, LPSTR buf, INT buflen)
-{
-	HANDLE16 handle;
-	struct hostent *host;
-	int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return 0;
-	}
-
-	handle = AllocWSAHandle();
-
-	newpid = fork();
-	if (newpid) {
-		dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-		return handle;
-	} else {
-		if ((host = gethostbyaddr(addr, len, type)) == NULL) {
-			if (h_errno < 0) {
-        			errno_to_wsaerrno();
-			} else {
-				herrno_to_wsaerrno();
-			}
-			send_message(hWnd, wMsg, handle, wsaerrno() << 16);
-			exit(0);
-		}
-		memcpy(buf, host, buflen);
-		send_message(hWnd, wMsg, handle, 0);
-		exit(0);
-	}
-}
-
-
-HANDLE16 WSAAsyncGetHostByName(HWND hWnd, u_int wMsg, LPCSTR name, 
-                             LPSTR buf, INT buflen)
-{
-	HANDLE16 handle;
-	struct hostent *host;
-	int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return 0;
-	}
-
-	handle = AllocWSAHandle();
-
-	newpid = fork();
-	if (newpid) {
-		dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-		return handle;
-	} else {
-		if ((host = gethostbyname(name)) == NULL) {
-			if (h_errno < 0) {
-        			errno_to_wsaerrno();
-			} else {
-				herrno_to_wsaerrno();
-			}
-			send_message(hWnd, wMsg, handle, wsaerrno() << 16);
-			exit(0);
-		}
-		memcpy(buf, host, buflen);
-		send_message(hWnd, wMsg, handle, 0);
-		exit(0);
-	}
-}                     
-
-
-HANDLE16 WSAAsyncGetProtoByName(HWND hWnd, u_int wMsg, LPCSTR name, 
-                              LPSTR buf, INT buflen)
-{
-	HANDLE16 handle;
-	struct protoent *proto;
-	int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return 0;
-	}
-
-	handle = AllocWSAHandle();
-
-	newpid = fork();
-	if (newpid) {
-		dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-		return handle;
-	} else {
-		if ((proto = getprotobyname(name)) == NULL) {
-			if (h_errno < 0) {
-        			errno_to_wsaerrno();
-			} else {
-				herrno_to_wsaerrno();
-			}
-			send_message(hWnd, wMsg, handle, wsaerrno() << 16);
-			exit(0);
-		}
-		memcpy(buf, proto, buflen);
-		send_message(hWnd, wMsg, handle, 0);
-		exit(0);
-	}
-}
-
-
-HANDLE16 WSAAsyncGetProtoByNumber(HWND hWnd, u_int wMsg, INT number, 
-                                LPSTR buf, INT buflen)
-{
-	HANDLE16 handle;
-	struct protoent *proto;
-	int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return 0;
-	}
-
-	handle = AllocWSAHandle();
-
-	newpid = fork();
-	if (newpid) {
-		dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-		return handle;
-	} else {
-		if ((proto = getprotobynumber(number)) == NULL) {
-			if (h_errno < 0) {
-        			errno_to_wsaerrno();
-			} else {
-				herrno_to_wsaerrno();
-			}
-			send_message(hWnd, wMsg, handle, wsaerrno() << 16);
-			exit(0);
-		}
-		memcpy(buf, proto, buflen);
-		send_message(hWnd, wMsg, handle, 0);
-		exit(0);
-	}
-}
-
-
-HANDLE16 WSAAsyncGetServByName(HWND hWnd, u_int wMsg, LPCSTR name, 
-                             LPCSTR proto, LPSTR buf, INT buflen)
-{
-	HANDLE16 handle;
-	struct servent *service;
-	int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return 0;
-	}
-
-	handle = AllocWSAHandle();
-
-	newpid = fork();
-	if (newpid) {
-		dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-		return handle;
-	} else {
-		if ((service = getservbyname(name, proto)) == NULL) {
-			if (h_errno < 0) {
-        			errno_to_wsaerrno();
-			} else {
-				herrno_to_wsaerrno();
-			}
-			send_message(hWnd, wMsg, handle, wsaerrno() << 16);
-			exit(0);
-		}
-		memcpy(buf, service, buflen);
-		send_message(hWnd, wMsg, handle, 0);
-		exit(0);
-	}
-}
-
-
-HANDLE16 WSAAsyncGetServByPort(HWND hWnd, u_int wMsg, INT port, LPCSTR proto,
-                             LPSTR buf, INT buflen)
-{
-	HANDLE16 handle;
-	struct servent *service;
-	int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return 0;
-	}
-
-	handle = AllocWSAHandle();
-
-	newpid = fork();
-	if (newpid) {
-		dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-		return handle;
-	} else {
-		if ((service = getservbyport(port, proto)) == NULL) {
-			if (h_errno < 0) {
-        			errno_to_wsaerrno();
-			} else {
-				herrno_to_wsaerrno();
-			}
-			send_message(hWnd, wMsg, handle, wsaerrno() << 16);
-			exit(0);
-		}
-		memcpy(buf, service, buflen);
-		send_message(hWnd, wMsg, handle, 0);
-		exit(0);
-	}
-}
-
-INT WSAAsyncSelect(SOCKET s, HWND hWnd, u_int wMsg, long lEvent)
-{
-    long event;
-    fd_set read_fds, write_fds, except_fds;
-    int errors = 0;
-    int newpid;
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-    dprintf_winsock(stddeb, "WSA_AsyncSelect: socket %d, HWND %04x, wMsg %d, event %ld\n", s, hWnd, wMsg, lEvent);
-
-    /* remove outstanding asyncselect() processes */
-    /* kill */
-
-    if (wMsg == 0 && lEvent == 0) 
-        return 0;
-
-    newpid = fork();
-    if (newpid) {
-        dprintf_winsock(stddeb, "forked, child is (%d)\n",newpid);
-        return 0;
-    } else {
-        while (1) {
-            FD_ZERO(&read_fds);
-            FD_ZERO(&write_fds);
-            FD_ZERO(&except_fds);
-
-            if (lEvent & FD_READ)
-                FD_SET(s, &read_fds);
-            if (lEvent & FD_WRITE)
-                FD_SET(s, &write_fds);
-
-            fcntl(s, F_SETFL, O_NONBLOCK);
-            if (select(s + 1, &read_fds, &write_fds, &except_fds, NULL)<0) {
-                errors = wsaerrno();
-            }
-
-            event = 0;
-            if (FD_ISSET(s, &read_fds))
-                event |= FD_READ;
-            if (FD_ISSET(s, &write_fds))
-                event |= FD_WRITE;
-            send_message(hWnd, wMsg, s, WSAMAKESELECTREPLY(event,errors));
-        }
-    }
-}
-
-INT WSAFDIsSet(SOCKET fd, WinSock_fd_set *set)
-{
-  int i = set->fd_count;
-  
-  dprintf_winsock(stddeb, "__WSAFDIsSet(%d,%8lx)\n",fd,(unsigned long)set);
-    
-  while (i--)
-    {
-      if (set->fd_array[i] == fd)
-        {
-          dprintf_winsock(stddeb, "__WSAFDIsSet returning 1\n");
-          return 1;
-        }
-    }
-  dprintf_winsock(stddeb, "__WSAFDIsSet returning 0\n");
-  return 0;
-}                                                            
-
-INT WSACancelAsyncRequest(HANDLE16 hAsyncTaskHandle)
-{
-	dprintf_winsock(stddeb, "WSA_AsyncRequest: handle %04x\n", hAsyncTaskHandle);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	return 0;
-}
-
-INT WSACancelBlockingCall(void)
-{
-	dprintf_winsock(stddeb, "WSA_CancelBlockCall\n");
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	return 0;
-}
-          
-INT WSAGetLastError(void)
-{
-	dprintf_winsock(stddeb, "WSA_GetLastError = %x\n", wsa_errno);
-
-	return wsa_errno;
-}
-
-void WSASetLastError(INT iError)
-{
-	dprintf_winsock(stddeb, "WSA_SetLastErorr %d\n", iError);
-
-	/* technically, we should make sure that WINESockets 
-	* has been started up correctly. But since this function
-	* is also used internally, it makes no sense.
-	*
-	*if (!wsa_initted) { 
-	*	WSASetLastError(WSANOTINITIALISED);
-	*	return SOCKET_ERROR;
-	*}
-	*/
-
-	wsa_errno = iError;
-}
-
-BOOL WSAIsBlocking(void)
-{
-	dprintf_winsock(stddeb, "WSA_IsBlocking\n");
-
-	return 0;
-}
-
-FARPROC16 WSASetBlockingHook(FARPROC16 lpBlockFunc)
-{
-	dprintf_winsock(stddeb, "WSA_SetBlockHook %8lx, STUB!\n", (unsigned long) lpBlockFunc);
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return NULL;
-	}
-
-	BlockFunction = lpBlockFunc;
-
-	return (FARPROC16) lpBlockFunc;
-}
-
-INT WSAUnhookBlockingHook(void)
-{
-	dprintf_winsock(stddeb, "WSA_UnhookBlockingHook\n");
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return NULL;
-	}
-
-	BlockFunction = NULL;
-
-	return 0;
-}
-
-#ifdef 0
-WSADATA WINSOCK_data = {
-        0x0101,
-        0x0101,
-        "WINE Sockets",
-#ifdef linux
-        "LINUX/i386",
-#elif defined(__NetBSD__)
-        "NetBSD/i386",
-#elif defined(sunos)
-	"SunOS",
-#elif defined(__FreeBSD__)
-	"FreeBSD",
-#else
-	"Unknown",
-#endif
-        WINSOCK_MAX_SOCKETS,
-	WINSOCK_MAX_UDPDG,
-        NULL
-};
-#endif
-
-INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
-{
-
-	WSADATA WINSOCK_data = {
-        			0x0101,
-        			0x0101,
-        			"WINE Sockets",
-			#ifdef linux
-        			"Linux/i386",
-			#elif defined(__NetBSD__)
-        			"NetBSD/i386",
-			#elif defined(sunos)
-				"SunOS",
-			#elif defined(__FreeBSD__)
-				"FreeBSD",
-			#else
-				"Unknown",
-			#endif
-        			WINSOCK_MAX_SOCKETS,
-				WINSOCK_MAX_UDPDG,
-				NULL
-				};
-
-    dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
-
-    if (LOBYTE(wVersionRequested) < 1 ||
-        (LOBYTE(wVersionRequested) == 1 &&
-         HIBYTE(wVersionRequested) < 1))
-	return WSAVERNOTSUPPORTED;
-
-    if (!lpWSAData)
-        return WSAEINVAL;
-
-	/* alloc winsock heap */
-
-    if ((HeapHandle = GlobalAlloc16(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0)
-	return WSASYSNOTREADY;
-
-    Heap = (struct WinSockHeap *) GlobalLock16(HeapHandle);
-
-    /* return winsock information */
-    memcpy(lpWSAData, &WINSOCK_data, sizeof(WINSOCK_data)); 
-
-    /* ipc stuff */
-
-    if ((wine_key = msgget(IPC_PRIVATE, 0600)) == -1)
-	perror("wine: winsock: msgget"); 
-
-    signal(SIGUSR1, recv_message);
-
-    /* clear */
-    
-    FD_ZERO(&fd_in_use);
-
-    /* increment our usage count */
-    wsa_initted++;
-    dprintf_winsock(stddeb, "WSAStartup: succeeded\n");
-    return(0);
-}
-
-INT WSACleanup(void)
-{
-	int fd;
-
-	dprintf_winsock(stddeb, "WSACleanup (%d)\n",getpid());
-
-	if (!wsa_initted) { 
-		WSASetLastError(WSANOTINITIALISED);
-		return SOCKET_ERROR;
-	}
-
-	/* decrement usage count */
-	wsa_initted--;
-
-	if (wsa_initted == 0) {
-		if (wine_key)
-			if (msgctl(wine_key, IPC_RMID, NULL) == -1)
-				perror("wine: winsock: msgctl");
-
-		for (fd = 0; fd != FD_SETSIZE; fd++)
-			if (FD_ISSET(fd, &fd_in_use))
-				close(fd);
-
-	}
-	return 0;
-}
-
-VOID
-WsControl(DWORD x1,DWORD x2,LPDWORD x3,LPDWORD x4,LPDWORD x5,LPDWORD x6) {
-	fprintf(stdnimp,"WsControl(%lx,%lx,%p,%p,%p,%p)\n",
-		x1,x2,x3,x4,x5,x6
-	);
-	fprintf(stdnimp,"WsControl(x,x,%lx,%lx,%lx,%lx)\n",
-		x3?*x3:0,x4?*x4:0,x5?*x5:0,x6?*x6:0
-	);
-	return;
-}
diff --git a/miscemu/int21.c b/miscemu/int21.c
index 1a4cc96..d2a5fb5 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -649,7 +649,6 @@
     }
 
     lstrcpyn32A( ptr, DRIVE_GetDosCwd(drive), 64 );
-    if (!ptr[0]) strcpy( ptr, "\\" );
     return 1;
 }
 
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index c8a066a1..44c4bb4 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -91,7 +91,7 @@
 		MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
 	if (hmmio == 0) {
 		dprintf_mmsys(stddeb, "sndPlaySound // searching in SystemSound List !\n");
-		GetProfileString("Sounds", (LPSTR)lpszSoundName, "", str, sizeof(str));
+		GetProfileString32A("Sounds", (LPSTR)lpszSoundName, "", str, sizeof(str));
 		if (strlen(str) == 0) return FALSE;
 		if ( (ptr = (LPSTR)strchr(str, ',')) != NULL) *ptr = '\0';
 		hmmio = mmioOpen(str, NULL, MMIO_ALLOCBUF | MMIO_READ | MMIO_DENYWRITE);
@@ -586,7 +586,7 @@
 		s=(char*)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
 		t=strrchr(s,'.');
 		if (t) {
-			GetProfileString("mci extensions",t+1,"*",str,sizeof(str));
+			GetProfileString32A("mci extensions",t+1,"*",str,sizeof(str));
 			AnsiUpper(str);
 			if (strcmp(str, "CDAUDIO") == 0) {
 				uDevTyp = MCI_DEVTYPE_CD_AUDIO;
@@ -745,7 +745,7 @@
 				InstalledCount = 0;
 				InstalledListLen = 0;
 				ptr = lpInstallNames = xmalloc(2048);
-				GetPrivateProfileString("mci", NULL, "", lpInstallNames, 2000, SysFile);
+				GetPrivateProfileString32A("mci", NULL, "", lpInstallNames, 2000, SysFile);
 				while(strlen(ptr) > 0) {
 					dprintf_mci(stddeb, "---> '%s' \n", ptr);
 					len = strlen(ptr) + 1;
diff --git a/objects/clipping.c b/objects/clipping.c
index c7f55fc..787991b 100644
--- a/objects/clipping.c
+++ b/objects/clipping.c
@@ -418,6 +418,24 @@
     return ret;
 }
 
+/***********************************************************************
+ *           GetClipRgn32  (GDI32.163)
+ */
+INT32 GetClipRgn32( HDC32 hdc, HRGN32 hRgn )
+{
+    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
+    if( dc && hRgn )
+      if( dc->w.hClipRgn )
+      { 
+	/* this assumes that dc->w.hClipRgn is in coordinates
+	   relative to the DC origin (not device) */
+
+	if( CombineRgn32(hRgn, dc->w.hClipRgn, 0, RGN_COPY) != ERROR )
+	    return 1;
+      }
+      else return 0;
+    return -1;
+}
 
 /***********************************************************************
  *           SaveVisRgn    (GDI.129)
diff --git a/objects/dc.c b/objects/dc.c
index 834e0f8..70c0355 100644
--- a/objects/dc.c
+++ b/objects/dc.c
@@ -719,19 +719,36 @@
 
 
 /***********************************************************************
+ *           GetDCOrgEx  (GDI32.168)
+ */
+BOOL32 GetDCOrgEx(HDC32 hDC, LPPOINT32 lpp)
+{
+    DC * dc = (DC *) GDI_GetObjPtr( hDC, DC_MAGIC );
+    if (!dc || !lpp) return FALSE;
+
+    if (!(dc->w.flags & DC_MEMORY))
+    {
+       Window root;
+       int w, h, border, depth;
+
+       XGetGeometry( display, dc->u.x.drawable, &root,
+                    &lpp->x, &lpp->y, &w, &h, &border, &depth );
+    }
+    else lpp->x = lpp->y = 0;
+    lpp->x += dc->w.DCOrgX; lpp->y += dc->w.DCOrgY;
+    return TRUE;
+}
+
+
+/***********************************************************************
  *           GetDCOrg    (GDI.79)
  */
 DWORD GetDCOrg( HDC16 hdc )
 {
-    Window root;
-    int x, y, w, h, border, depth;
-
-    DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
-    if (!dc) return 0;
-    if (dc->w.flags & DC_MEMORY) return 0;
-    XGetGeometry( display, dc->u.x.drawable, &root,
-		  &x, &y, &w, &h, &border, &depth );
-    return MAKELONG( dc->w.DCOrgX + (WORD)x, dc->w.DCOrgY + (WORD)y );
+    POINT32	pt;
+    if( GetDCOrgEx( hdc, &pt) )
+  	return MAKELONG( (WORD)pt.x, (WORD)pt.y );    
+    return 0;
 }
 
 
diff --git a/objects/dcvalues.c b/objects/dcvalues.c
index e32996a..b497558 100644
--- a/objects/dcvalues.c
+++ b/objects/dcvalues.c
@@ -86,7 +86,6 @@
 DC_GET_X_Y( DWORD, GetWindowOrg, WndOrgX, WndOrgY )               /* GDI.97 */
 DC_GET_VAL( HRGN32, InquireVisRgn, hVisRgn )                      /* GDI.131 */
 DC_GET_X_Y( DWORD, GetBrushOrg, brushOrgX, brushOrgY )            /* GDI.149 */
-DC_GET_VAL( HRGN32, GetClipRgn, hClipRgn )                        /* GDI.173 */
 DC_GET_VAL( WORD, GetTextAlign, textAlign )                       /* GDI.345 */
 DC_GET_VAL( HFONT16, GetCurLogFont, hFont )                       /* GDI.411 */
 DC_GET_VAL_EX( GetBrushOrgEx, brushOrgX, brushOrgY )              /* GDI.469 */
@@ -95,3 +94,9 @@
 DC_GET_VAL_EX( GetViewportOrgEx, VportOrgX, VportOrgY )           /* GDI.473 */
 DC_GET_VAL_EX( GetWindowExtEx, WndExtX, WndExtY )                 /* GDI.474 */
 DC_GET_VAL_EX( GetWindowOrgEx, WndOrgX, WndOrgY )                 /* GDI.475 */
+
+/* this one is wrong - Windows returns region that
+   is relative to the device and not to the DC origin */
+
+DC_GET_VAL( HRGN16, GetClipRgn16, hClipRgn )                      /* GDI.173 */
+
diff --git a/objects/font.c b/objects/font.c
index df3b109..061e5cc 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -94,7 +94,8 @@
     FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
     FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
     FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
-    FontSize = 7;
+    FontNames[7].window = "system"; FontNames[7].x11 = "*-helvetica";
+    FontSize = 8;
   }
   return TRUE;
 }
@@ -220,6 +221,20 @@
       family = "*-*";
       break;
     }
+    sprintf( pattern, "-%s-%s-*-normal-*-*-*-*-*-*-*-%s",
+	    family, weight, charset);
+    dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
+    names = XListFonts( display, pattern, 1, &count );
+    if (names) XFreeFontNames( names );
+    else
+    {
+        if (strcmp(family, "*-*") == 0)
+        {
+            fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
+            return NULL;
+        }
+        else family = "*-*";
+    }
     oldheight = height;
     oldspacing = spacing;
     while (TRUE) {
@@ -1197,133 +1212,145 @@
   XFreeFontNames(names);
 }
 
-
 /*************************************************************************
  *				EnumFonts			[GDI.70]
+ * We reuse EnumFontFamilies* for the callback function get the same
+ * structs (+ extra stuff at the end which will be ignored by the enum funcs)
  */
-INT EnumFonts(HDC16 hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
+INT16 EnumFonts16(HDC16 hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
 {
-  HLOCAL16     hLog;
-  HLOCAL16     hMet;
-  HFONT16 hFont;
-  HFONT16 hOldFont;
-  LPLOGFONT16  lpLogFont;
-  LPTEXTMETRIC16 lptm;
-  LPSTR	       lpOldName;
-  char	       FaceName[LF_FACESIZE];
-  int          nRet = 0;
-  int          i;
-
-  dprintf_font(stddeb,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n", 
-	       hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
-  if (lpEnumFunc == 0) return 0;
-  hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT16) + LF_FACESIZE );
-  lpLogFont = (LPLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
-  if (lpLogFont == NULL) {
-    fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
-    return 0;
-  }
-  hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
-  lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
-  if (lptm == NULL) {
-    GDI_HEAP_FREE(hLog);
-    fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
-    return 0;
-  }
-  if (lpFaceName != NULL) {
-    strcpy(FaceName, lpFaceName);
-    AnsiUpper(FaceName);
-  } 
-  lpOldName = NULL;
-  
-  if (lpLogFontList[0] == NULL) InitFontsList();
-  for(i = 0; lpLogFontList[i] != NULL; i++) {
-    if (lpFaceName == NULL) {
-      if (lpOldName != NULL) {
-	if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
-      }
-      lpOldName = lpLogFontList[i]->lfFaceName;
-    } else {
-      if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
-    }
-    dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
-    dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
-    memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT16) + LF_FACESIZE);
-    hFont = CreateFontIndirect16(lpLogFont);
-    hOldFont = SelectObject32(hDC, hFont);
-    GetTextMetrics16(hDC, lptm);
-    SelectObject32(hDC, hOldFont);
-    DeleteObject32(hFont);
-    dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
-    nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
-                       0, (LONG)lpData );
-    if (nRet == 0) {
-      dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
-      break;
-    }
-  }
-  GDI_HEAP_FREE(hMet);
-  GDI_HEAP_FREE(hLog);
-  return nRet;
+  return EnumFontFamilies16(hDC,lpFaceName,lpEnumFunc,lpData);
 }
 
+/*************************************************************************
+ *				EnumFontsA			[GDI32.84]
+ */
+INT32 EnumFonts32A(HDC32 hDC, LPCSTR lpFaceName, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
+{
+  return EnumFontFamilies32A(hDC,lpFaceName,lpEnumFunc,lpData);
+}
+
+/*************************************************************************
+ *				EnumFontsA			[GDI32.84]
+ */
+INT32 EnumFonts32W(HDC32 hDC, LPCWSTR lpFaceName, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
+{
+  return EnumFontFamilies32W(hDC,lpFaceName,lpEnumFunc,lpData);
+}
 
 /*************************************************************************
  *				EnumFontFamilies	[GDI.330]
  */
 INT16 EnumFontFamilies16(HDC16 hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
 {
+  LOGFONT16	LF;
+
+  if (lpszFamily)
+     strcpy(LF.lfFaceName,lpszFamily);
+  else
+     LF.lfFaceName[0]='\0';
+  LF.lfCharSet = DEFAULT_CHARSET;
+
+  return EnumFontFamiliesEx16(hDC,&LF,(FONTENUMPROCEX16)lpEnumFunc,lpData,0);
+}
+
+/*************************************************************************
+ *				EnumFontFamiliesA	[GDI32.80]
+ */
+INT32 EnumFontFamilies32A(HDC32 hDC, LPCSTR lpszFamily, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
+{
+  LOGFONT32A	LF;
+
+  if (lpszFamily)
+     strcpy(LF.lfFaceName,lpszFamily);
+  else
+     LF.lfFaceName[0]='\0';
+  LF.lfCharSet = DEFAULT_CHARSET;
+
+  return EnumFontFamiliesEx32A(hDC,&LF,(FONTENUMPROCEX32A)lpEnumFunc,lpData,0);
+}
+
+/*************************************************************************
+ *				EnumFontFamiliesW	[GDI32.83]
+ */
+INT32 EnumFontFamilies32W(HDC32 hDC, LPCWSTR lpszFamilyW, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
+{
+  LOGFONT32W	LF;
+
+  if (lpszFamilyW)
+  	lstrcpy32W(LF.lfFaceName,lpszFamilyW);
+  else
+  	LF.lfFaceName[0]=0;
+  LF.lfCharSet = DEFAULT_CHARSET;
+  return EnumFontFamiliesEx32W(hDC,&LF,(FONTENUMPROCEX32W)lpEnumFunc,lpData,0);
+}
+
+/*************************************************************************
+ *				EnumFontFamiliesEx	[GDI.618]
+ * FIXME: fill the rest of the NEWTEXTMETRICEX and ENUMLOGFONTEX structures.
+ *        (applies to all EnumFontFamiliesEx*)
+ *        winelib/16 support.
+ */
+INT16 EnumFontFamiliesEx16(HDC16 hDC, LPLOGFONT16 lpLF, FONTENUMPROCEX16 lpEnumFunc, LPARAM lpData,DWORD reserved)
+{
   HLOCAL16     	hLog;
   HLOCAL16     	hMet;
   HFONT16 hFont;
   HFONT16 hOldFont;
-  LPENUMLOGFONT16 lpEnumLogFont;
-  LPTEXTMETRIC16 lptm;
+  LPENUMLOGFONTEX16 lpEnumLogFont;
+  LPNEWTEXTMETRICEX16 lptm;
   LPSTR	       	lpOldName;
   char	       	FaceName[LF_FACESIZE];
   int	       	nRet = 0;
   int	       	i;
   
-  dprintf_font(stddeb,"EnumFontFamilies(%04x, %p, %08lx, %08lx)\n",
-	       hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
+  dprintf_font(stddeb,"EnumFontFamiliesEx(%04x, '%s', %08lx, %08lx, %08lx)\n",
+	       hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData, reserved);
   if (lpEnumFunc == 0) return 0;
-  hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT16) );
-  lpEnumLogFont = (LPENUMLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
+  hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX16) );
+  lpEnumLogFont = (LPENUMLOGFONTEX16) GDI_HEAP_LIN_ADDR(hLog);
   if (lpEnumLogFont == NULL) {
-    fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
+    fprintf(stderr,"EnumFontFamiliesEx // can't alloc LOGFONT struct !\n");
     return 0;
   }
-  hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
-  lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
+  hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX16) );
+  lptm = (LPNEWTEXTMETRICEX16) GDI_HEAP_LIN_ADDR(hMet);
   if (lptm == NULL) {
     GDI_HEAP_FREE(hLog);
-    fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
+    fprintf(stderr,"EnumFontFamiliesEx // can't alloc TEXTMETRIC struct !\n");
     return 0;
   }
   lpOldName = NULL;
-  if (lpszFamily != NULL) {
-    strcpy(FaceName, lpszFamily);
-    AnsiUpper(FaceName);
-  }
+  strcpy(FaceName,lpLF->lfFaceName);
+  AnsiUpper(lpLF->lfFaceName);
+
   if (lpLogFontList[0] == NULL) InitFontsList();
   for(i = 0; lpLogFontList[i] != NULL; i++) {
-    if (lpszFamily == NULL) {
-      if (lpOldName != NULL) {
-	if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
-      }
-      lpOldName = lpLogFontList[i]->lfFaceName;
+    /* lfCharSet */
+    if (lpLF->lfCharSet!=DEFAULT_CHARSET)
+    	if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
+	   continue;
+
+    /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
+    /* lfFaceName */
+    if (FaceName[0]) {
+    	if (strcmp(FaceName,lpLogFontList[i]->lfFaceName))
+	   continue;
     } else {
-      if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
+    	if ((lpOldName!=NULL)&&!strcmp(lpOldName,lpLogFontList[i]->lfFaceName))
+	   continue;
+	lpOldName=lpLogFontList[i]->lfFaceName;
     }
+
     memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16));
     strcpy(lpEnumLogFont->elfFullName,"");
     strcpy(lpEnumLogFont->elfStyle,"");
     hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont);
     hOldFont = SelectObject32(hDC, hFont);
-    GetTextMetrics16(hDC, lptm);
+    GetTextMetrics16(hDC, (LPTEXTMETRIC16)lptm);
     SelectObject32(hDC, hOldFont);
     DeleteObject32(hFont);
-    dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
+    dprintf_font(stddeb, "EnumFontFamiliesEx // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
     
     nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
                        0, lpData );
@@ -1338,66 +1365,74 @@
 }
 
 /*************************************************************************
- *				EnumFontFamiliesA	[GDI32.80]
+ *				EnumFontFamiliesExA	[GDI32.81]
+ * FIXME: Don't use 16 bit GDI heap functions (applies to EnumFontFamiliesEx32*)
  */
-INT32 EnumFontFamilies32A(HDC32 hDC, LPCSTR lpszFamily, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
+INT32 EnumFontFamiliesEx32A(HDC32 hDC, LPLOGFONT32A lpLF,FONTENUMPROCEX32A lpEnumFunc, LPARAM lpData,DWORD reserved)
 {
   HLOCAL16     	hLog;
   HLOCAL16     	hMet;
   HFONT32	hFont;
   HFONT32	hOldFont;
-  LPENUMLOGFONT32A	lpEnumLogFont;
-  LPTEXTMETRIC32A	lptm;
+  LPENUMLOGFONTEX32A	lpEnumLogFont;
+  LPNEWTEXTMETRICEX32A	lptm;
   LPSTR	       	lpOldName;
   char	       	FaceName[LF_FACESIZE];
   int	       	nRet = 0;
   int	       	i;
   
-  dprintf_font(stddeb,"EnumFontFamilies32A(%04x, %p, %08lx, %08lx)\n",
-	       hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
+  dprintf_font(stddeb,"EnumFontFamilies32A(%04x, %p, %08lx, %08lx, %08lx)\n",
+	       hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData,reserved);
   if (lpEnumFunc == 0) return 0;
-  hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT32A) );
-  lpEnumLogFont = (LPENUMLOGFONT32A) GDI_HEAP_LIN_ADDR(hLog);
+  hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32A) );
+  lpEnumLogFont = (LPENUMLOGFONTEX32A) GDI_HEAP_LIN_ADDR(hLog);
   if (lpEnumLogFont == NULL) {
     fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
     return 0;
   }
-  hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC32A) );
-  lptm = (LPTEXTMETRIC32A) GDI_HEAP_LIN_ADDR(hMet);
+  hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32A) );
+  lptm = (LPNEWTEXTMETRICEX32A) GDI_HEAP_LIN_ADDR(hMet);
   if (lptm == NULL) {
     GDI_HEAP_FREE(hLog);
     fprintf(stderr,"EnumFontFamilies32A // can't alloc TEXTMETRIC struct !\n");
     return 0;
   }
   lpOldName = NULL;
-  if (lpszFamily != NULL) {
-    strcpy(FaceName, lpszFamily);
-    AnsiUpper(FaceName);
-  }
+  strcpy(FaceName,lpLF->lfFaceName);
+  AnsiUpper(lpLF->lfFaceName);
+
   if (lpLogFontList[0] == NULL) InitFontsList();
   for(i = 0; lpLogFontList[i] != NULL; i++) {
-    if (lpszFamily == NULL) {
-      if (lpOldName != NULL) {
-	if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
-      }
-      lpOldName = lpLogFontList[i]->lfFaceName;
+    /* lfCharSet */
+    if (lpLF->lfCharSet!=DEFAULT_CHARSET)
+    	if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
+	   continue;
+
+    /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
+    /* lfFaceName */
+    if (FaceName[0]) {
+    	if (strcmp(FaceName,lpLogFontList[i]->lfFaceName))
+	   continue;
     } else {
-      if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
+    	if ((lpOldName!=NULL)&&!strcmp(lpOldName,lpLogFontList[i]->lfFaceName))
+	   continue;
+	lpOldName=lpLogFontList[i]->lfFaceName;
     }
+
     FONT_LOGFONT16ToLOGFONT32A(lpLogFontList[i],&(lpEnumLogFont->elfLogFont));
     strcpy(lpEnumLogFont->elfFullName,"");
     strcpy(lpEnumLogFont->elfStyle,"");
+    strcpy(lpEnumLogFont->elfScript,"");
     hFont = CreateFontIndirect32A((LPLOGFONT32A)lpEnumLogFont);
     hOldFont = SelectObject32(hDC, hFont);
-    GetTextMetrics32A(hDC, lptm);
+    GetTextMetrics32A(hDC, (LPTEXTMETRIC32A)lptm);
     SelectObject32(hDC, hOldFont);
     DeleteObject32(hFont);
-    dprintf_font(stddeb, "EnumFontFamilies32A // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
+    dprintf_font(stddeb, "EnumFontFamiliesEx32A // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
     
-    nRet = lpEnumFunc( GDI_HEAP_LIN_ADDR(hLog), GDI_HEAP_LIN_ADDR(hMet),
-                       0, lpData );
+    nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData);
     if (nRet == 0) {
-      dprintf_font(stddeb,"EnumFontFamilies32A // EnumEnd requested by application !\n");
+      dprintf_font(stddeb,"EnumFontFamiliesEx32A // EnumEnd requested by application !\n");
       break;
     }
   }
@@ -1406,66 +1441,76 @@
   return nRet;
 }
 
+
 /*************************************************************************
- *				EnumFontFamiliesW	[GDI32.83]
+ *				EnumFontFamiliesW	[GDI32.82]
  */
-INT32 EnumFontFamilies32W(HDC32 hDC, LPCWSTR lpszFamilyW, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
+INT32 EnumFontFamiliesEx32W(HDC32 hDC, LPLOGFONT32W lpLF, FONTENUMPROCEX32W lpEnumFunc, LPARAM lpData, DWORD reserved)
 {
   HLOCAL16     	hLog;
   HLOCAL16     	hMet;
   HFONT32	hFont;
   HFONT32	hOldFont;
-  LPENUMLOGFONT32W	lpEnumLogFont;
-  LPTEXTMETRIC32W	lptm;
+  LPENUMLOGFONTEX32W	lpEnumLogFont;
+  LPNEWTEXTMETRICEX32W	lptm;
   LPSTR	       	lpOldName;
-  char	       	FaceName[LF_FACESIZE];
   int	       	nRet = 0;
   int	       	i;
-  LPCSTR	lpszFamily=lpszFamilyW?STRING32_DupUniToAnsi(lpszFamilyW):NULL;
+  LPSTR	lpszFamily=STRING32_DupUniToAnsi(lpLF->lfFaceName);
   
-  dprintf_font(stddeb,"EnumFontFamilies32W(%04x, %p, %08lx, %08lx)\n",
-	       hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
-  if (lpEnumFunc == 0) return 0;
-  hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT32W) );
-  lpEnumLogFont = (LPENUMLOGFONT32W) GDI_HEAP_LIN_ADDR(hLog);
-  if (lpEnumLogFont == NULL) {
-    fprintf(stderr,"EnumFontFamilies32W // can't alloc LOGFONT struct !\n");
+  dprintf_font(stddeb,"EnumFontFamiliesEx32W(%04x, %p, %08lx, %08lx, %08lx)\n",
+	       hDC, lpLF, (DWORD)lpEnumFunc, lpData,reserved);
+  if (lpEnumFunc == 0) {
+    free(lpszFamily);
     return 0;
   }
-  hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC32W) );
-  lptm = (LPTEXTMETRIC32W) GDI_HEAP_LIN_ADDR(hMet);
+  hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32W) );
+  lpEnumLogFont = (LPENUMLOGFONTEX32W) GDI_HEAP_LIN_ADDR(hLog);
+  if (lpEnumLogFont == NULL) {
+    fprintf(stderr,"EnumFontFamilies32W // can't alloc LOGFONT struct !\n");
+    free(lpszFamily);
+    return 0;
+  }
+  hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32W) );
+  lptm = (LPNEWTEXTMETRICEX32W) GDI_HEAP_LIN_ADDR(hMet);
   if (lptm == NULL) {
     GDI_HEAP_FREE(hLog);
     fprintf(stderr,"EnumFontFamilies32W // can't alloc TEXTMETRIC struct !\n");
+    free(lpszFamily);
     return 0;
   }
   lpOldName = NULL;
-  if (lpszFamily != NULL) {
-    strcpy(FaceName, lpszFamily);
-    AnsiUpper(FaceName);
-  }
+  AnsiUpper(lpszFamily);
   if (lpLogFontList[0] == NULL) InitFontsList();
   for(i = 0; lpLogFontList[i] != NULL; i++) {
-    if (lpszFamily == NULL) {
-      if (lpOldName != NULL) {
-	if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
-      }
-      lpOldName = lpLogFontList[i]->lfFaceName;
+    /* lfCharSet */
+    if (lpLF->lfCharSet!=DEFAULT_CHARSET)
+    	if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
+	   continue;
+
+    /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
+    /* lfFaceName */
+    if (lpszFamily[0]) {
+    	if (strcmp(lpszFamily,lpLogFontList[i]->lfFaceName))
+	   continue;
     } else {
-      if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
+    	if ((lpOldName!=NULL)&&!strcmp(lpOldName,lpLogFontList[i]->lfFaceName))
+	   continue;
+	lpOldName=lpLogFontList[i]->lfFaceName;
     }
+
     FONT_LOGFONT16ToLOGFONT32W(lpLogFontList[i],&(lpEnumLogFont->elfLogFont));
     lstrcpynAtoW(lpEnumLogFont->elfFullName,"",1);
     lstrcpynAtoW(lpEnumLogFont->elfStyle,"",1);
+    lstrcpynAtoW(lpEnumLogFont->elfScript,"",1);
     hFont = CreateFontIndirect32W((LPLOGFONT32W)lpEnumLogFont);
     hOldFont = SelectObject32(hDC, hFont);
-    GetTextMetrics32W(hDC, lptm);
+    GetTextMetrics32W(hDC, (LPTEXTMETRIC32W)lptm);
     SelectObject32(hDC, hOldFont);
     DeleteObject32(hFont);
     dprintf_font(stddeb, "EnumFontFamilies32W // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
     
-    nRet = lpEnumFunc( GDI_HEAP_LIN_ADDR(hLog), GDI_HEAP_LIN_ADDR(hMet),
-                       0, lpData );
+    nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData);
     if (nRet == 0) {
       dprintf_font(stddeb,"EnumFontFamilies32W // EnumEnd requested by application !\n");
       break;
@@ -1473,6 +1518,7 @@
   }
   GDI_HEAP_FREE(hMet);
   GDI_HEAP_FREE(hLog);
+  free(lpszFamily);
   return nRet;
 }
 
diff --git a/objects/pen.c b/objects/pen.c
index bb14791..83f70c7 100644
--- a/objects/pen.c
+++ b/objects/pen.c
@@ -13,7 +13,7 @@
 
 
 static const char PEN_dash[]       = { 5,3 };      /* -----   -----   -----  */
-static const char PEN_dot[]        = { 2,2 };      /* --  --  --  --  --  -- */
+static const char PEN_dot[]        = { 1,1 };      /* --  --  --  --  --  -- */
 static const char PEN_dashdot[]    = { 4,3,2,3 };  /* ----   --   ----   --  */
 static const char PEN_dashdotdot[] = { 4,2,2,2,2,2 }; /* ----  --  --  ----  */
 
diff --git a/objects/text.c b/objects/text.c
index 782fe70..fd2450f 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -283,7 +283,7 @@
 	rect->right = rect->left + max_width;
 	rect->bottom = y;
     }
-    return 1;
+    return y - rect->top;
 }
 
 
diff --git a/programs/winhelp/winhelp.c b/programs/winhelp/winhelp.c
index aefda90..54e0a8d 100644
--- a/programs/winhelp/winhelp.c
+++ b/programs/winhelp/winhelp.c
@@ -592,7 +592,7 @@
       {
 	BOOL  update = TRUE;
 	RECT  rect;
-	INT16 Min, Max;
+	INT   Min, Max;
 	INT   CurPos = GetScrollPos(hWnd, SB_VERT);
 	GetScrollRange(hWnd, SB_VERT, &Min, &Max);
 	GetClientRect(hWnd, &rect);
diff --git a/win32/file.c b/win32/file.c
index 925de51..e60bc61 100644
--- a/win32/file.c
+++ b/win32/file.c
@@ -60,20 +60,16 @@
         SetLastError(ErrnoToLastError(errno));
         return INVALID_HANDLE_VALUE;
     }
-    hfile = _lcreat(lpName,1);
-    if(hfile == HFILE_ERROR) {
-        SetLastError(ErrnoToLastError(errno));
-        return INVALID_HANDLE_VALUE;
-    }
     filemap_obj=(FILEMAP_OBJECT *)CreateKernelObject(sizeof(FILEMAP_OBJECT));
     if(filemap_obj == NULL) {
-    	_lclose(hfile);
         SetLastError(ERROR_UNKNOWN);
         return 0;
     }
+    if (h==INVALID_HANDLE_VALUE)
+    	h=_lcreat(lpName,1);/*FIXME*/
 
     filemap_obj->common.magic = KERNEL_OBJECT_FILEMAP;
-    filemap_obj->hfile = hfile;
+    filemap_obj->hfile = h;
     filemap_obj->prot = TranslateProtectionFlags(pot);
     filemap_obj->size = hlow;
     return (HANDLE32)filemap_obj;;
@@ -97,7 +93,6 @@
 
 /***********************************************************************
  *           MapViewOfFile                  (KERNEL32.385)
- *
  */
 LPVOID MapViewOfFile(HANDLE32 handle, DWORD access, DWORD offhi,
                       DWORD offlo, DWORD size)
@@ -112,13 +107,25 @@
 LPVOID MapViewOfFileEx(HANDLE32 handle, DWORD access, DWORD offhi,
                       DWORD offlo, DWORD size, DWORD st)
 {
-    if (!size) size = ((FILEMAP_OBJECT *)handle)->size;
-    return mmap ((caddr_t)st, size, ((FILEMAP_OBJECT *)handle)->prot, 
+    FILEMAP_OBJECT *fmap = (FILEMAP_OBJECT*)handle;
+
+    if (!size) size = fmap->size;
+    if (!size) size = 1;
+    return mmap ((caddr_t)st, size, fmap->prot, 
                  MAP_ANON|MAP_PRIVATE, 
-		 FILE_GetUnixHandle(((FILEMAP_OBJECT *)handle)->hfile),
+		 FILE_GetUnixHandle(fmap->hfile),
 		 offlo);
 }
 
+/***********************************************************************
+ *           UnmapViewOfFile                  (KERNEL32.385)
+ */
+BOOL32 UnmapViewOfFile(LPVOID address) {
+    munmap(address,/*hmm*/1); /* FIXME: size? */
+    return TRUE;
+}
+
+
 
 /***********************************************************************
  *           GetFileInformationByHandle       (KERNEL32.219)
diff --git a/windows/caret.c b/windows/caret.c
index 99c955f..055bb1b 100644
--- a/windows/caret.c
+++ b/windows/caret.c
@@ -150,7 +150,7 @@
     Caret.x = 0;
     Caret.y = 0;
 
-    Caret.timeout = GetProfileInt( "windows", "CursorBlinkRate", 750 );
+    Caret.timeout = GetProfileInt32A( "windows", "CursorBlinkRate", 750 );
     return TRUE;
 }
    
diff --git a/windows/dce.c b/windows/dce.c
index 5a7c9e0..1f03832 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -282,7 +282,8 @@
 
       /* Get visible rectangle and create a region with it. 
        * do we really need to calculate vis rgns for X windows? 
-       * - yes, to clip child windows.
+       * - yes, to clip child windows but we should skip 
+       *   siblings in this case.
        */
 
     if (!wndPtr || !DCE_GetVisRect( wndPtr, !(flags & DCX_WINDOW), &rect ))
@@ -377,7 +378,41 @@
         dc->u.x.drawable = wndPtr->window;
     }
 }
+/***********************************************************************
+ *           DCE_ExcludeRgn
+ * 
+ *  Translate given region from the wnd client to the DC coordinates
+ *  and add it to the clipping region.
+ */
+INT16 DCE_ExcludeRgn( HDC32 hDC, WND* wnd, HRGN32 hRgn )
+{
+  INT16	   ret;
+  POINT32  pt = {0, 0};
+  HRGN32   hRgnClip = GetClipRgn16( hDC );
+  DCE     *dce = firstDCE;
 
+  while (dce && (dce->hDC != hDC)) dce = dce->next;
+  if( dce )
+  {
+      MapWindowPoints32( wnd->hwndSelf, dce->hwndCurrent, &pt, 1);
+      if( dce->DCXflags & DCX_WINDOW )
+      { 
+	  wnd = WIN_FindWndPtr(dce->hwndCurrent);
+	  pt.x += wnd->rectClient.left - wnd->rectWindow.left;
+	  pt.y += wnd->rectClient.top - wnd->rectWindow.top;
+      }
+  }
+  else return ERROR;
+  OffsetRgn32(hRgn, pt.x, pt.y);
+  if( hRgnClip ) ret = CombineRgn32( hRgnClip, hRgnClip, hRgn, RGN_DIFF );
+  else 
+  {
+      hRgnClip = InquireVisRgn( hDC );
+      ret = CombineRgn32( hRgn, hRgnClip, hRgn, RGN_DIFF );
+      SelectClipRgn32( hDC, hRgn );
+  }
+  return ret;
+}
 
 /***********************************************************************
  *           GetDCEx16    (USER.359)
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 03b82c3..b201881 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -376,7 +376,7 @@
         if (wParam && wndPtr->text)
         {
             lstrcpyn32A( (LPSTR)PTR_SEG_TO_LIN(lParam), wndPtr->text, wParam );
-            result = (LRESULT)strlen( (LPSTR)PTR_SEG_TO_LIN(lParam) ) + 1;
+            result = (LRESULT)strlen( (LPSTR)PTR_SEG_TO_LIN(lParam) );
         }
         break;
 
@@ -442,7 +442,7 @@
         if (wParam && wndPtr->text)
         {
             lstrcpyn32A( (LPSTR)lParam, wndPtr->text, wParam );
-            result = (LRESULT)strlen( (LPSTR)lParam ) + 1;
+            result = (LRESULT)strlen( (LPSTR)lParam );
         }
         break;
 
diff --git a/windows/dialog.c b/windows/dialog.c
index 03a0ddf..7f51666 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -4,11 +4,13 @@
  * Copyright 1993, 1994, 1996 Alexandre Julliard
  */
 
+#include <ctype.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include "windows.h"
 #include "dialog.h"
+#include "drive.h"
 #include "heap.h"
 #include "win.h"
 #include "ldt.h"
@@ -16,6 +18,7 @@
 #include "user.h"
 #include "winproc.h"
 #include "message.h"
+#include "sysmetrics.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -534,8 +537,22 @@
     {
         rect.left += template.x * xUnit / 4;
         rect.top += template.y * yUnit / 8;
-        if ( !(template.style & DS_ABSALIGN) && !(template.style & WS_CHILD) )
-            ClientToScreen16( owner, (POINT16 *)&rect );
+        if ( !(template.style & WS_CHILD) )
+	{
+            INT16 dX, dY;
+
+            if( !(template.style & DS_ABSALIGN) )
+                ClientToScreen16( owner, (POINT16 *)&rect );
+	    
+            /* try to fit it into the desktop */
+
+            if( (dX = rect.left + rect.right + SYSMETRICS_CXDLGFRAME 
+                 - SYSMETRICS_CXSCREEN) > 0 ) rect.left -= dX;
+            if( (dY = rect.top + rect.bottom + SYSMETRICS_CYDLGFRAME
+                 - SYSMETRICS_CYSCREEN) > 0 ) rect.top -= dY;
+            if( rect.left < 0 ) rect.left = 0;
+            if( rect.top < 0 ) rect.top = 0;
+        }
     }
 
     if (procType != WIN_PROC_16)
@@ -569,6 +586,9 @@
     dlgInfo->msgResult = 0;  /* This is used to store the default button id */
     dlgInfo->hDialogHeap = 0;
 
+    if (dlgInfo->hUserFont)
+        SendMessage32A( hwnd, WM_SETFONT, (WPARAM32)dlgInfo->hUserFont, 0 );
+
     /* Create controls */
 
     if (!DIALOG_CreateControls( wndPtr, dlgTemplate, template.nbItems,
@@ -581,8 +601,6 @@
     /* Send initialisation messages and set focus */
 
     dlgInfo->hwndFocus = GetNextDlgTabItem32( hwnd, 0, FALSE );
-    if (dlgInfo->hUserFont)
-	SendMessage32A( hwnd, WM_SETFONT, (WPARAM32)dlgInfo->hUserFont, 0 );
     if (SendMessage32A( hwnd, WM_INITDIALOG,
                         (WPARAM32)dlgInfo->hwndFocus, param ))
 	SetFocus32( dlgInfo->hwndFocus );
@@ -1391,6 +1409,96 @@
 
 
 /**********************************************************************
+ *	    DIALOG_DlgDirList
+ *
+ * Helper function for DlgDirList*
+ */
+static INT32 DIALOG_DlgDirList( HWND32 hDlg, LPCSTR spec, INT32 idLBox,
+                                INT32 idStatic, UINT32 attrib, BOOL32 combo )
+{
+    int drive;
+    HWND32 hwnd;
+
+#define SENDMSG(msg,wparam,lparam) \
+    ((attrib & DDL_POSTMSGS) ? PostMessage( hwnd, msg, wparam, lparam ) \
+                             : SendMessage32A( hwnd, msg, wparam, lparam ))
+
+    dprintf_dialog( stddeb, "DlgDirList: %04x '%s' %d %d %04x\n",
+                    hDlg, spec ? spec : "NULL", idLBox, idStatic, attrib );
+
+    if (spec && spec[0] && (spec[1] == ':'))
+    {
+        drive = toupper( spec[0] ) - 'A';
+        spec += 2;
+        if (!DRIVE_SetCurrentDrive( drive )) return FALSE;
+    }
+    else drive = DRIVE_GetCurrentDrive();
+
+    if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
+    {
+        /* If the path exists and is a directory, chdir to it */
+        if (!spec || !spec[0] || DRIVE_Chdir( drive, spec )) spec = "*.*";
+        else
+        {
+            const char *p, *p2;
+            p = spec;
+            if ((p2 = strrchr( p, '\\' ))) p = p2 + 1;
+            if ((p2 = strrchr( p, '/' ))) p = p2 + 1;
+            if (p != spec)
+            {
+                BOOL32 ret = FALSE;
+                char *dir = HeapAlloc( SystemHeap, 0, p - spec );
+                if (dir)
+                {
+                    lstrcpyn32A( dir, spec, p - spec );
+                    ret = DRIVE_Chdir( drive, dir );
+                    HeapFree( SystemHeap, 0, dir );
+                }
+                if (!ret) return FALSE;
+                spec = p;
+            }
+        }
+        
+        dprintf_dialog( stddeb, "ListBoxDirectory: path=%c:\\%s mask=%s\n",
+                        'A' + drive, DRIVE_GetDosCwd(drive), spec );
+        
+        SENDMSG( combo ? CB_RESETCONTENT32 : LB_RESETCONTENT32, 0, 0 );
+        if ((attrib & DDL_DIRECTORY) && !(attrib & DDL_EXCLUSIVE))
+        {
+            if (SENDMSG( combo ? CB_DIR32 : LB_DIR32,
+                         attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
+                         (LPARAM)spec ) == LB_ERR)
+                return FALSE;
+            if (SENDMSG( combo ? CB_DIR32 : LB_DIR32,
+                       (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
+                         (LPARAM)"*.*" ) == LB_ERR)
+                return FALSE;
+        }
+        else
+        {
+            if (SENDMSG( combo ? CB_DIR32 : LB_DIR32, attrib,
+                         (LPARAM)spec ) == LB_ERR)
+                return FALSE;
+        }
+    }
+
+    if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
+    {
+        char temp[512];
+        int drive = DRIVE_GetCurrentDrive();
+        strcpy( temp, "A:\\" );
+        temp[0] += drive;
+        lstrcpyn32A( temp + 3, DRIVE_GetDosCwd(drive), sizeof(temp)-3 );
+        AnsiLower( temp );
+        /* Can't use PostMessage() here, because the string is on the stack */
+        SetDlgItemText32A( hDlg, idStatic, temp );
+    }
+    return TRUE;
+#undef SENDMSG
+}
+
+
+/**********************************************************************
  *	    DlgDirSelect    (USER.99)
  */
 BOOL16 DlgDirSelect( HWND16 hwnd, LPSTR str, INT16 id )
@@ -1460,3 +1568,73 @@
 {
     return DIALOG_DlgDirSelect( hwnd, (LPSTR)str, len, id, TRUE, TRUE, TRUE );
 }
+
+
+/**********************************************************************
+ *	    DlgDirList16    (USER.100)
+ */
+INT16 DlgDirList16( HWND16 hDlg, LPCSTR spec, INT16 idLBox, INT16 idStatic,
+                    UINT16 attrib )
+{
+    return DIALOG_DlgDirList( hDlg, spec, idLBox, idStatic, attrib, FALSE );
+}
+
+
+/**********************************************************************
+ *	    DlgDirList32A    (USER32.142)
+ */
+INT32 DlgDirList32A( HWND32 hDlg, LPCSTR spec, INT32 idLBox, INT32 idStatic,
+                     UINT32 attrib )
+{
+    return DIALOG_DlgDirList( hDlg, spec, idLBox, idStatic, attrib, FALSE );
+}
+
+
+/**********************************************************************
+ *	    DlgDirList32W    (USER32.145)
+ */
+INT32 DlgDirList32W( HWND32 hDlg, LPCWSTR spec, INT32 idLBox, INT32 idStatic,
+                     UINT32 attrib )
+{
+    INT32 ret;
+    LPSTR specA = NULL;
+    if (spec) specA = STRING32_DupUniToAnsi(spec);
+    ret = DIALOG_DlgDirList( hDlg, specA, idLBox, idStatic, attrib, FALSE );
+    if (specA) free( specA );
+    return ret;
+}
+
+
+/**********************************************************************
+ *	    DlgDirListComboBox16    (USER.195)
+ */
+INT16 DlgDirListComboBox16( HWND16 hDlg, LPCSTR spec, INT16 idCBox,
+                            INT16 idStatic, UINT16 attrib )
+{
+    return DIALOG_DlgDirList( hDlg, spec, idCBox, idStatic, attrib, TRUE );
+}
+
+
+/**********************************************************************
+ *	    DlgDirListComboBox32A    (USER32.143)
+ */
+INT32 DlgDirListComboBox32A( HWND32 hDlg, LPCSTR spec, INT32 idCBox,
+                             INT32 idStatic, UINT32 attrib )
+{
+    return DIALOG_DlgDirList( hDlg, spec, idCBox, idStatic, attrib, TRUE );
+}
+
+
+/**********************************************************************
+ *	    DlgDirListComboBox32W    (USER32.144)
+ */
+INT32 DlgDirListComboBox32W( HWND32 hDlg, LPCWSTR spec, INT32 idCBox,
+                             INT32 idStatic, UINT32 attrib )
+{
+    INT32 ret;
+    LPSTR specA = NULL;
+    if (spec) specA = STRING32_DupUniToAnsi(spec);
+    ret = DIALOG_DlgDirList( hDlg, specA, idCBox, idStatic, attrib, FALSE );
+    if (specA) free( specA );
+    return ret;
+}
diff --git a/windows/event.c b/windows/event.c
index 2010052..49d325a 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -37,6 +37,7 @@
 #include "shell.h"
 #include "registers.h"
 #include "xmalloc.h"
+#include "keyboard.h"
 #include "stddebug.h"
 #include "debug.h"
 #include "dde_proc.h"
@@ -62,13 +63,9 @@
   /* State variables */
 BOOL MouseButtonsStates[NB_BUTTONS];
 BOOL AsyncMouseButtonsStates[NB_BUTTONS];
-BYTE KeyStateTable[256];
-BYTE AsyncKeyStateTable[256];
+BYTE InputKeyStateTable[256];
 
 
-WPARAM16 lastEventChar = 0; /* this will have to be changed once
-                             * ToAscii starts working */
-
 static HWND32 captureWnd = 0;
 static BOOL32 InputEnabled = TRUE;
 
@@ -128,8 +125,8 @@
 	unsigned long count : 16;
 	unsigned long code : 8;
 	unsigned long extended : 1;
-	unsigned long : 2;
-	unsigned long reserved : 2;
+	unsigned long unused : 2;
+	unsigned long win_internal : 2;
 	unsigned long context : 1;
 	unsigned long previous : 1;
 	unsigned long transition : 1;
@@ -188,7 +185,7 @@
 {
     WND *pWnd;
     
-    if (XFindContext( display, ((XAnyEvent *)event)->window, winContext,
+    if (XFindContext( display, event->xany.window, winContext,
                       (char **)&pWnd ) != 0)
         return;  /* Not for a registered window */
 
@@ -521,8 +518,16 @@
     int ascii_chars = XLookupString(event, Str, 1, &keysym, &cs);
 
     Str[ascii_chars] = '\0';
-    dprintf_key(stddeb,"WM_KEY??? : keysym=%lX, ascii chars=%u / %X / '%s'\n", 
-	   keysym, ascii_chars, Str[0], Str);
+    if (debugging_key)
+	{
+	char	*ksname;
+
+	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);
+	}
 
     /* Ctrl-Alt-Return enters the debugger */
     if ((keysym == XK_Return) && (event->type == KeyPress) &&
@@ -556,6 +561,27 @@
 	    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_Page_Up :
+	    case XK_Page_Down :
+	    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 */
     {
@@ -568,24 +594,7 @@
 	  {
 #define vkcase(k,val) case k: vkey = val; break;
 #define vkcase2(k1,k2,val) case k1: case k2: vkey = val; break;
-
-	      /* I wish I had a bit-paired keyboard! */
-	      vkcase('!','1'); vkcase('@','2'); vkcase('#','3');
-	      vkcase('$','4'); vkcase('%','5'); vkcase('^','6');
-	      vkcase('&','7'); vkcase('*','8'); vkcase('(','9');
-	      vkcase(')','0');
-
-	      vkcase2('`','~',0xc0);
-	      vkcase2('-','_',0xbd);
-	      vkcase2('=','+',0xbb);
-	      vkcase2('[','{',0xdb);
-	      vkcase2(']','}',0xdd);
-	      vkcase2(';',':',0xba);
-	      vkcase2('\'','\"',0xde);
-	      vkcase2(',','<',0xbc);
-	      vkcase2('.','>',0xbe);
-	      vkcase2('/','?',0xbf);
-	      vkcase2('\\','|',0xdc);
+	    WINE_VKEY_MAPPINGS
 #undef vkcase
 #undef vkcase2
 	    default:
@@ -596,50 +605,41 @@
 
     if (event->type == KeyPress)
     {
-        if (!(KeyStateTable[vkey] & 0x80))
-            KeyStateTable[vkey] ^= 0x01;
-	KeyStateTable[vkey] |= 0x80;
+        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.reserved = (ascii_chars ? 1 : 0);
+	keylp.lp1.win_internal = 0;
 	keylp.lp1.context = ( (event->state & Mod1Mask) || 
-			       (KeyStateTable[VK_MENU] & 0x80)) ? 1 : 0;
+			       (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,"            KeyState=%X\n", KeyStateTable[vkey]);
-	hardware_event( KeyStateTable[VK_MENU] & 0x80 ? WM_SYSKEYDOWN : WM_KEYDOWN, 
+	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;
-
-	/* Currently we use reserved field in the scan-code byte to
-	 * make it possible for TranslateMessage to recognize character keys
-	 * and get them from lastEventChar global variable.
-	 *
-	 * ToAscii should handle it.
-	 */
-
-	if( ascii_chars ) lastEventChar = Str[0];
     }
     else
     {
-	UINT sysKey = KeyStateTable[VK_MENU];
+	UINT sysKey = InputKeyStateTable[VK_MENU];
 
-	KeyStateTable[vkey] &= ~0x80; 
+	InputKeyStateTable[vkey] &= ~0x80; 
 	keylp.lp1.count = 1;
 	keylp.lp1.code = LOBYTE(event->keycode) - 8;
 	keylp.lp1.extended = (extended ? 1 : 0);
-	keylp.lp1.reserved = 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,"            KeyState=%X\n", KeyStateTable[vkey]);
+	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,
diff --git a/windows/graphics.c b/windows/graphics.c
index 40d1c30..5003f17 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -834,7 +834,7 @@
 {
     RECT32 rect32;
     CONV_RECT16TO32( rc, &rect32 );
-    return DrawFocusRect32( hdc, &rect32 );
+    DrawFocusRect32( hdc, &rect32 );
 }
 
 
diff --git a/windows/hook.c b/windows/hook.c
index dcc5fdf..ef81d3a 100644
--- a/windows/hook.c
+++ b/windows/hook.c
@@ -133,7 +133,6 @@
     data->ownerQueue  = hQueue;
     data->ownerModule = hInst;
     data->inHookProc  = 0;
-    dprintf_hook( stddeb, "Setting hook %d: ret=%04x\n", id, handle );
 
     /* Insert it in the correct linked list */
 
@@ -148,6 +147,8 @@
         data->next = HOOK_systemHooks[id - WH_MINHOOK];
         HOOK_systemHooks[id - WH_MINHOOK] = handle;
     }
+    dprintf_hook( stddeb, "Setting hook %d: ret=%04x [next=%04x]\n", 
+			   id, handle, data->next );
     return handle;
 }
 
@@ -188,7 +189,7 @@
     while (*prevHook && *prevHook != hook)
         prevHook = &((HOOKDATA *)USER_HEAP_LIN_ADDR(*prevHook))->next;
 
-     if (!*prevHook) return FALSE;
+    if (!*prevHook) return FALSE;
     *prevHook = data->next;
     USER_HEAP_FREE( hook );
     return TRUE;
@@ -251,6 +252,33 @@
 
 
 /***********************************************************************
+ *           HOOK_ResetQueueHooks
+ */
+void HOOK_ResetQueueHooks( HQUEUE16 hQueue )
+{
+    MESSAGEQUEUE *queue;
+
+    if ((queue = (MESSAGEQUEUE *)GlobalLock16( hQueue )) != NULL)
+    {
+	HOOKDATA*	data;
+	HHOOK		hook;
+	int		id;
+	for( id = WH_MINHOOK; id <= WH_MAXHOOK; id++ )
+	{
+	    hook = queue->hooks[id - WH_MINHOOK];
+	    while( hook )
+	    {
+	        if( (data = (HOOKDATA *)USER_HEAP_LIN_ADDR(hook)) )
+	        {
+		  data->ownerQueue = hQueue;
+		  hook = data->next;
+		} else break;
+	    }
+	}
+    }
+}
+
+/***********************************************************************
  *	     HOOK_FreeModuleHooks
  */
 void HOOK_FreeModuleHooks( HMODULE16 hModule )
diff --git a/windows/keyboard.c b/windows/keyboard.c
index ccc815b..10e3ed0 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -3,47 +3,60 @@
  *
  * Copyright 1993 Bob Amstadt
  */
+#include <stdio.h>
 #include <string.h>
 #include "win.h"
 #include "windows.h"
+#include "debug.h"
 
 extern BOOL MouseButtonsStates[3];
 extern BOOL AsyncMouseButtonsStates[3];
-extern BYTE KeyStateTable[256];
-extern BYTE AsyncKeyStateTable[256];
+extern BYTE InputKeyStateTable[256];
+BYTE AsyncKeyStateTable[256];
+
+extern BYTE QueueKeyStateTable[256];
 
 /**********************************************************************
  *		GetKeyState			[USER.106]
+ * An application calls the GetKeyState function in response to a
+ * 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 retval;
 
+    if (keycode >= 'a' && keycode <= 'z')
+        keycode += 'A' - 'a';
     switch(keycode) {
      case VK_LBUTTON:
-	return MouseButtonsStates[0];
+	retval = MouseButtonsStates[0];
      case VK_MBUTTON:
-	return MouseButtonsStates[1];
+	retval = MouseButtonsStates[1];
      case VK_RBUTTON:
-	return MouseButtonsStates[2];
+	retval = MouseButtonsStates[2];
      default:
-	retval = ( (INT)(KeyStateTable[keycode] & 0x80) << 8 ) |
-		   (INT)(KeyStateTable[keycode] & 0x01);
+	retval = ( (INT)(QueueKeyStateTable[keycode] & 0x80) << 8 ) |
+		   (INT)(QueueKeyStateTable[keycode] & 0x01);
     }
 
+    dprintf_key(stddeb, "GetKeyState(%x) -> %x\n", keycode, retval);
     return retval;
 }
 
 /**********************************************************************
  *		GetKeyboardState			[USER.222]
+ * An application calls the GetKeyboardState function in response to a
+ * keyboard-input message.  This function retrieves the state of the keyboard
+ * at the time the input message was generated.  (SDK 3.1 Vol 2. p 387)
  */
 void GetKeyboardState(BYTE *lpKeyState)
 {
     if (lpKeyState != NULL) {
-	KeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] >> 8;
-	KeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] >> 8;
-	KeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] >> 8;
-	memcpy(lpKeyState, KeyStateTable, 256);
+	QueueKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] >> 8;
+	QueueKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] >> 8;
+	QueueKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] >> 8;
+	memcpy(lpKeyState, QueueKeyStateTable, 256);
     }
 }
 
@@ -53,10 +66,10 @@
 void SetKeyboardState(BYTE *lpKeyState)
 {
     if (lpKeyState != NULL) {
-	memcpy(KeyStateTable, lpKeyState, 256);
-	MouseButtonsStates[0] = KeyStateTable[VK_LBUTTON]? 0x8000: 0;
-	MouseButtonsStates[1] = KeyStateTable[VK_MBUTTON]? 0x8000: 0;
-	MouseButtonsStates[2] = KeyStateTable[VK_RBUTTON]? 0x8000: 0;
+	memcpy(QueueKeyStateTable, lpKeyState, 256);
+	MouseButtonsStates[0] = QueueKeyStateTable[VK_LBUTTON]? 0x8000: 0;
+	MouseButtonsStates[1] = QueueKeyStateTable[VK_MBUTTON]? 0x8000: 0;
+	MouseButtonsStates[2] = QueueKeyStateTable[VK_RBUTTON]? 0x8000: 0;
     }
 }
 
@@ -92,13 +105,13 @@
 	break;
      default:
 	retval = AsyncKeyStateTable[nKey] | 
-	(KeyStateTable[nKey] ? 0x8000 : 0);
+	(InputKeyStateTable[nKey] ? 0x8000 : 0);
 	break;
     }
 
     memset( AsyncMouseButtonsStates, 0, 3 );  /* all states to false */
     memset( AsyncKeyStateTable, 0, 256 );
 
+    dprintf_key(stddeb, "GetAsyncKeyState(%x) -> %x\n", nKey, retval);
     return retval;
 }
-
diff --git a/windows/message.c b/windows/message.c
index 4ac32f3..77ee2f9 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -32,16 +32,15 @@
 #define HWND_BROADCAST16  ((HWND16)0xffff)
 #define HWND_BROADCAST32  ((HWND32)0xffffffff)
 
-#define ASCII_CHAR_HACK 0x0800 
-
 typedef enum { SYSQ_MSG_ABANDON, SYSQ_MSG_SKIP, SYSQ_MSG_ACCEPT } SYSQ_STATUS;
 
-extern WPARAM16 lastEventChar;				 /* event.c */
 extern BOOL MouseButtonsStates[3];
 extern BOOL AsyncMouseButtonsStates[3];
-extern BYTE KeyStateTable[256];
+extern BYTE InputKeyStateTable[256];
 extern BYTE AsyncKeyStateTable[256];
 
+BYTE QueueKeyStateTable[256];
+
 extern MESSAGEQUEUE *pCursorQueue;			 /* queue.c */
 extern MESSAGEQUEUE *pActiveQueue;
 
@@ -292,24 +291,10 @@
     SEGPTR_FREE(event);
 }
 
-/*****************************************************************
- *              MSG_JournalPlayBackIsAscii
- */
-static BOOL MSG_JournalPlayBackIsAscii(WPARAM16 wParam)
-{
- return ((wParam>VK_HELP && wParam<VK_F1) || 
-          wParam == VK_SPACE  ||
-          wParam == VK_ESCAPE ||
-          wParam == VK_RETURN ||
-          wParam == VK_TAB    ||
-          wParam == VK_BACK);   
-}
-
-
 /***********************************************************************
  *          MSG_JournalPlayBackMsg
  *
- * Get an EVENTMSG struct via call JOURNALPAYBACK hook function 
+ * Get an EVENTMSG struct via call JOURNALPLAYBACK hook function 
  */
 static int MSG_JournalPlayBackMsg(void)
 {
@@ -332,29 +317,18 @@
      if (tmpMsg->message == WM_KEYDOWN || tmpMsg->message == WM_SYSKEYDOWN)
      {
        for (keyDown=i=0; i<256 && !keyDown; i++)
-          if (KeyStateTable[i] & 0x80)
+          if (InputKeyStateTable[i] & 0x80)
             keyDown++;
        if (!keyDown)
          lParam |= 0x40000000;       
-       AsyncKeyStateTable[wParam]=KeyStateTable[wParam] |= 0x80;
-       if (MSG_JournalPlayBackIsAscii(wParam))
-       {
-         lastEventChar= wParam;         /* control TranslateMessage() */
-         lParam |= (LONG)((LONG)ASCII_CHAR_HACK*0x10000L);
-
-         if (!(KeyStateTable[VK_SHIFT] & 0x80) &&
-             !(KeyStateTable[VK_CAPITAL] & 0x80))
-           lastEventChar= tolower(lastEventChar);
-         if (KeyStateTable[VK_CONTROL] & 0x80)
-           lastEventChar&=0x1f;
-       }  
+       AsyncKeyStateTable[wParam]=InputKeyStateTable[wParam] |= 0x80;
      }  
      else                                       /* WM_KEYUP, WM_SYSKEYUP */
      {
        lParam |= 0xC0000000;      
-       AsyncKeyStateTable[wParam]=KeyStateTable[wParam] &= ~0x80;
+       AsyncKeyStateTable[wParam]=InputKeyStateTable[wParam] &= ~0x80;
      }
-     if (KeyStateTable[VK_MENU] & 0x80)
+     if (InputKeyStateTable[VK_MENU] & 0x80)
        lParam |= 0x20000000;     
      if (tmpMsg->paramH & 0x8000)              /*special_key bit*/
        lParam |= 0x01000000;
@@ -373,9 +347,9 @@
       case WM_RBUTTONDOWN:MouseButtonsStates[2]=AsyncMouseButtonsStates[2]=1;break;
       case WM_RBUTTONUP:  MouseButtonsStates[2]=AsyncMouseButtonsStates[2]=0;break;      
      }
-     AsyncKeyStateTable[VK_LBUTTON]= KeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] << 8;
-     AsyncKeyStateTable[VK_MBUTTON]= KeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] << 8;
-     AsyncKeyStateTable[VK_RBUTTON]= KeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] << 8;
+     AsyncKeyStateTable[VK_LBUTTON]= InputKeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] << 8;
+     AsyncKeyStateTable[VK_MBUTTON]= InputKeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] << 8;
+     AsyncKeyStateTable[VK_RBUTTON]= InputKeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] << 8;
      SetCursorPos(tmpMsg->paramL,tmpMsg->paramH);
      lParam=MAKELONG(tmpMsg->paramL,tmpMsg->paramH);
      wParam=0;             
@@ -644,7 +618,7 @@
 
         /* First handle a message put by SendMessage() */
 
-	if (msgQueue->wakeBits & QS_SENDMESSAGE)
+	while (msgQueue->wakeBits & QS_SENDMESSAGE)
             QUEUE_ReceiveMessage( msgQueue );
 
         /* Now handle a WM_QUIT message 
@@ -661,6 +635,7 @@
             msg->message = WM_QUIT;
             msg->wParam  = msgQueue->wExitCode;
             msg->lParam  = 0;
+            if( !peek ) msgQueue->wPostQMsg = 0;
             break;
         }
     
@@ -695,7 +670,7 @@
 
         /* Check again for SendMessage */
 
- 	if (msgQueue->wakeBits & QS_SENDMESSAGE)
+ 	while (msgQueue->wakeBits & QS_SENDMESSAGE)
             QUEUE_ReceiveMessage( msgQueue );
 
         /* Now find a WM_PAINT message */
@@ -734,7 +709,7 @@
         if (!(flags & PM_NOYIELD))
         {
             UserYield();
-            if (msgQueue->wakeBits & QS_SENDMESSAGE)
+            while (msgQueue->wakeBits & QS_SENDMESSAGE)
                 QUEUE_ReceiveMessage( msgQueue );
         }
 	if ((msgQueue->wakeBits & mask) & QS_TIMER)
@@ -752,6 +727,21 @@
     }
 
       /* We got a message */
+    if (flags & PM_REMOVE)
+    {
+	WORD message = msg->message;
+
+	if (message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
+	{
+	    BYTE *p = &QueueKeyStateTable[msg->wParam & 0xff];
+
+	    if (!(*p & 0x80))
+		*p ^= 0x01;
+	    *p |= 0x80;
+	}
+	else if (message == WM_KEYUP || message == WM_SYSKEYUP)
+	    QueueKeyStateTable[msg->wParam & 0xff] &= ~0x80;
+    }
     if (peek) return TRUE;
     else return (msg->message != WM_QUIT);
 }
@@ -1013,7 +1003,7 @@
         if (WINPROC_MapMsg32ATo16( msg, wParam, &msg16, &wParam16, &lParam ) == -1)
             return 0;
         ret = SendMessage16( hwnd, msg16, wParam16, lParam );
-        WINPROC_UnmapMsg32ATo16( msg16, wParam16, lParam );
+        WINPROC_UnmapMsg32ATo16( msg, wParam16, lParam );
         return ret;
     }
 
@@ -1088,32 +1078,42 @@
 /***********************************************************************
  *           TranslateMessage   (USER.113)
  *
- * This should call ToAscii but it is currently broken
+ * TranlateMessage translate virtual-key messages into character-messages,
+ * as follows :
+ * WM_KEYDOWN/WM_KEYUP combinations produce a WM_CHAR or WM_DEADCHAR message.
+ * ditto replacing WM_* with WM_SYS*
+ * This produces WM_CHAR messages only for keys mapped to ASCII characters
+ * by the keyboard driver.
  */
 
 
 BOOL TranslateMessage( LPMSG16 msg )
 {
     UINT message = msg->message;
-    /* BYTE wparam[2]; */
+    BYTE wparam[2];
     
-    if ((message == WM_KEYDOWN) || (message == WM_KEYUP) ||
-	(message == WM_SYSKEYDOWN) || (message == WM_SYSKEYUP))
+    if ((debugging_msg
+	&& message != WM_MOUSEMOVE && message != WM_TIMER)
+    || (debugging_key
+	&& message >= WM_KEYFIRST && message <= WM_KEYLAST))
+	    fprintf(stddeb, "TranslateMessage(%s, %04x, %08lx)\n",
+		SPY_GetMsgName(msg->message), msg->wParam, msg->lParam);
+    if ((message == WM_KEYDOWN) || (message == WM_SYSKEYDOWN))
     {
-	dprintf_msg(stddeb, "Translating key %04x, scancode %04x\n", msg->wParam, 
-							      HIWORD(msg->lParam) );
+	if (debugging_msg || debugging_key)
+	    fprintf(stddeb, "Translating key %04x, scancode %04x\n",
+		msg->wParam, HIWORD(msg->lParam) );
 
-	if( HIWORD(msg->lParam) & ASCII_CHAR_HACK )
-
-	/*  if( ToAscii( msg->wParam, HIWORD(msg->lParam), (LPSTR)&KeyStateTable,
-				      wparam, 0 ) ) 
-         */
+	/* FIXME : should handle ToAscii yielding 2 */
+	if (ToAscii(msg->wParam, HIWORD(msg->lParam), (LPSTR)&QueueKeyStateTable,
+				      wparam, 0)) 
 	      {
-     		message += 2 - (message & 0x0001); 
+		/* Map WM_KEY* to WM_*CHAR */
+		message += 2 - (message & 0x0001); 
 
-	        PostMessage( msg->hwnd, message, lastEventChar, msg->lParam );
+		PostMessage( msg->hwnd, message, wparam[0], msg->lParam );
 
-	        return TRUE;
+		return TRUE;
 	      }
     }
     return FALSE;
diff --git a/windows/painting.c b/windows/painting.c
index b41a6e9..43af442 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -590,20 +590,28 @@
  */
 INT16 ExcludeUpdateRgn( HDC32 hdc, HWND32 hwnd )
 {
-    INT32 retval = ERROR;
-    HRGN32 hrgn;
+    RECT16 rect;
     WND * wndPtr;
 
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
-    if ((hrgn = CreateRectRgn32( 0, 0, 0, 0 )) != 0)
+
+    if (wndPtr->hrgnUpdate)
     {
-	retval = CombineRgn32( hrgn, InquireVisRgn(hdc),
-			       (wndPtr->hrgnUpdate>1) ? wndPtr->hrgnUpdate : 0,
-			       (wndPtr->hrgnUpdate>1) ? RGN_DIFF : RGN_COPY );
-	if (retval) SelectVisRgn( hdc, hrgn );
+	INT16  ret;
+	HRGN32 hrgn = CreateRectRgn32(wndPtr->rectWindow.left - wndPtr->rectClient.left,
+				      wndPtr->rectWindow.top - wndPtr->rectClient.top,
+				      wndPtr->rectClient.right - wndPtr->rectClient.left,
+				      wndPtr->rectClient.bottom - wndPtr->rectClient.top);
+	if( wndPtr->hrgnUpdate > 1 )
+	    CombineRgn32(hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY);
+
+	/* do ugly coordinate translations in dce.c */
+
+	ret = DCE_ExcludeRgn( hdc, wndPtr, hrgn );
 	DeleteObject32( hrgn );
-    }
-    return retval;
+	return ret;
+    } 
+    return GetClipBox16(hdc, &rect);
 }
 
 
diff --git a/windows/queue.c b/windows/queue.c
index aeff35c..83a8c7d 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -5,10 +5,12 @@
  */
 
 #include <stdlib.h>
+#include <signal.h>
 #include "module.h"
 #include "queue.h"
 #include "task.h"
 #include "win.h"
+#include "hook.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -22,6 +24,8 @@
 static MESSAGEQUEUE *pMouseQueue = NULL;  /* Queue for last mouse message */
 static MESSAGEQUEUE *pKbdQueue = NULL;    /* Queue for last kbd message */
 
+extern void SIGNAL_MaskAsyncEvents(BOOL32);
+
 MESSAGEQUEUE *pCursorQueue = NULL; 
 MESSAGEQUEUE *pActiveQueue = NULL;
 
@@ -137,6 +141,9 @@
  *	     QUEUE_DeleteMsgQueue
  *
  * Unlinks and deletes a message queue.
+ *
+ * Note: We need to mask asynchronous events to make sure PostMessage works
+ * even in the signal handler.
  */
 BOOL32 QUEUE_DeleteMsgQueue( HQUEUE16 hQueue )
 {
@@ -165,6 +172,8 @@
       senderQ = sq->hPrevSendingTask;
     }
 
+    SIGNAL_MaskAsyncEvents( TRUE );
+
     pPrev = &hFirstQueue;
     while (*pPrev && (*pPrev != hQueue))
     {
@@ -173,6 +182,9 @@
     }
     if (*pPrev) *pPrev = msgQueue->next;
     msgQueue->self = 0;
+
+    SIGNAL_MaskAsyncEvents( FALSE );
+
     GlobalFree16( hQueue );
     return 1;
 }
@@ -333,6 +345,39 @@
     dprintf_msg(stddeb,"ReceiveMessage: done!\n");
 }
 
+/***********************************************************************
+ *           QUEUE_FlushMessage
+ * 
+ * Try to reply to all pending sent messages on exit.
+ */
+void QUEUE_FlushMessages( HQUEUE16 hQueue )
+{
+  MESSAGEQUEUE *queue = (MESSAGEQUEUE*)GlobalLock16( hQueue );
+
+  if( queue )
+  {
+    MESSAGEQUEUE *senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask);
+    QSMCTRL*      CtrlPtr = queue->smResultCurrent;
+
+    while( senderQ )
+    {
+      if( !(queue->hSendingTask = senderQ->hPrevSendingTask) )
+            queue->wakeBits &= ~QS_SENDMESSAGE;
+      QUEUE_SetWakeBit( senderQ, QS_SMPARAMSFREE );
+      
+      queue->smResultCurrent = CtrlPtr;
+      while( senderQ->wakeBits & QS_SMRESULT ) OldYield();
+
+      senderQ->SendMessageReturn = 0;
+      senderQ->smResult = queue->smResultCurrent;
+      QUEUE_SetWakeBit( senderQ, QS_SMRESULT);
+
+      if( (senderQ = (MESSAGEQUEUE*)GlobalLock16( queue->hSendingTask)) )
+	   CtrlPtr = senderQ->smResultInit;
+    }
+    queue->InSendMessageHandle = 0;
+  }  
+}
 
 /***********************************************************************
  *           QUEUE_AddMsg
@@ -344,12 +389,15 @@
     int pos;
     MESSAGEQUEUE *msgQueue;
 
+    SIGNAL_MaskAsyncEvents( TRUE );
+
     if (!(msgQueue = (MESSAGEQUEUE *)GlobalLock16( hQueue ))) return FALSE;
     pos = msgQueue->nextFreeMessage;
 
       /* Check if queue is full */
     if ((pos == msgQueue->nextMessage) && (msgQueue->msgCount > 0))
     {
+	SIGNAL_MaskAsyncEvents( FALSE );
         fprintf(stderr,"MSG_AddMsg // queue is full !\n");
         return FALSE;
     }
@@ -361,6 +409,9 @@
     else pos = 0;
     msgQueue->nextFreeMessage = pos;
     msgQueue->msgCount++;
+
+    SIGNAL_MaskAsyncEvents( FALSE );
+
     QUEUE_SetWakeBit( msgQueue, QS_POSTMESSAGE );
     return TRUE;
 }
@@ -403,6 +454,8 @@
  */
 void QUEUE_RemoveMsg( MESSAGEQUEUE * msgQueue, int pos )
 {
+    SIGNAL_MaskAsyncEvents( TRUE );
+
     if (pos >= msgQueue->nextMessage)
     {
 	for ( ; pos > msgQueue->nextMessage; pos--)
@@ -420,6 +473,8 @@
     }
     msgQueue->msgCount--;
     if (!msgQueue->msgCount) msgQueue->wakeBits &= ~QS_POSTMESSAGE;
+
+    SIGNAL_MaskAsyncEvents( FALSE );
 }
 
 
@@ -633,12 +688,18 @@
     }
     queuePtr = (MESSAGEQUEUE *)GlobalLock16( hNewQueue );
 
+    SIGNAL_MaskAsyncEvents( TRUE );
+
     /* Copy data and free the old message queue */
     if ((hQueue = GetTaskQueue(0)) != 0) 
     {
        MESSAGEQUEUE *oldQ = (MESSAGEQUEUE *)GlobalLock16( hQueue );
        memcpy( &queuePtr->reserved2, &oldQ->reserved2, 
 			(int)oldQ->messages - (int)(&oldQ->reserved2) );
+       HOOK_ResetQueueHooks( hNewQueue );
+       if( WIN_GetDesktop()->hmemTaskQ == hQueue )
+	   WIN_GetDesktop()->hmemTaskQ = hNewQueue;
+       WIN_ResetQueueWindows( WIN_GetDesktop()->child, hQueue, hNewQueue );
        QUEUE_DeleteMsgQueue( hQueue );
     }
 
@@ -648,8 +709,9 @@
     hFirstQueue = hNewQueue;
     
     if( !queuePtr->next ) pCursorQueue = queuePtr;
-
     SetTaskQueue( 0, hNewQueue );
+    
+    SIGNAL_MaskAsyncEvents( FALSE );
     return TRUE;
 }
 
diff --git a/windows/scroll.c b/windows/scroll.c
index 71ecc98..b416537 100644
--- a/windows/scroll.c
+++ b/windows/scroll.c
@@ -162,7 +162,7 @@
     if( rectClip.left >= rectClip.right || rectClip.top >= rectClip.bottom )
 	return FALSE;
     
-    hrgnClip = GetClipRgn(hdc);
+    hrgnClip = GetClipRgn16(hdc);
     hrgnScrollClip = CreateRectRgnIndirect32(&rectClip);
 
     if( hrgnClip )
diff --git a/windows/syscolor.c b/windows/syscolor.c
index 7441be1..596eceb 100644
--- a/windows/syscolor.c
+++ b/windows/syscolor.c
@@ -137,7 +137,7 @@
 
     for (i = 0, p = DefSysColors; i < NUM_SYS_COLORS; i++, p += 2)
     {
-	GetProfileString( "colors", p[0], p[1], buffer, 100 );
+	GetProfileString32A( "colors", p[0], p[1], buffer, 100 );
 	if (!sscanf( buffer, " %d %d %d", &r, &g, &b )) r = g = b = 0;
 	SYSCOLOR_SetColor( i, RGB(r,g,b) );
     }
diff --git a/windows/sysmetrics.c b/windows/sysmetrics.c
index 64b80dc..5325a86 100644
--- a/windows/sysmetrics.c
+++ b/windows/sysmetrics.c
@@ -51,15 +51,15 @@
     sysMetrics[SM_CYMIN] = SYSMETRICS_CYMIN;
     sysMetrics[SM_CXSIZE] = SYSMETRICS_CXSIZE;
     sysMetrics[SM_CYSIZE] = SYSMETRICS_CYSIZE;
-    sysMetrics[SM_CXFRAME] = GetProfileInt( "windows", "BorderWidth", 4 );
+    sysMetrics[SM_CXFRAME] = GetProfileInt32A( "windows", "BorderWidth", 4 );
     sysMetrics[SM_CYFRAME] = sysMetrics[SM_CXFRAME];
     sysMetrics[SM_CXMINTRACK] = SYSMETRICS_CXMINTRACK;
     sysMetrics[SM_CYMINTRACK] = SYSMETRICS_CYMINTRACK;
-    sysMetrics[SM_CXDOUBLECLK] = (GetProfileInt( "windows","DoubleClickWidth", 4) + 1) & ~1;
-    sysMetrics[SM_CYDOUBLECLK] = (GetProfileInt( "windows","DoubleClickHeight", 4) + 1) & ~1;
-    sysMetrics[SM_CXICONSPACING] = GetProfileInt( "desktop","IconSpacing", 75);
-    sysMetrics[SM_CYICONSPACING] = GetProfileInt( "desktop","IconVerticalSpacing", 72);
-    sysMetrics[SM_MENUDROPALIGNMENT] = GetProfileInt( "windows","MenuDropAlignment", 0 );
+    sysMetrics[SM_CXDOUBLECLK] = (GetProfileInt32A( "windows","DoubleClickWidth", 4) + 1) & ~1;
+    sysMetrics[SM_CYDOUBLECLK] = (GetProfileInt32A( "windows","DoubleClickHeight", 4) + 1) & ~1;
+    sysMetrics[SM_CXICONSPACING] = GetProfileInt32A( "desktop","IconSpacing", 75);
+    sysMetrics[SM_CYICONSPACING] = GetProfileInt32A( "desktop","IconVerticalSpacing", 72);
+    sysMetrics[SM_MENUDROPALIGNMENT] = GetProfileInt32A( "windows","MenuDropAlignment", 0 );
     sysMetrics[SM_PENWINDOWS] = 0;
     sysMetrics[SM_DBCSENABLED] = 0;
     sysMetrics[SM_CMETRICS] = SM_CMETRICS;
diff --git a/windows/win.c b/windows/win.c
index f9b70ee..2b48de3 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -374,24 +374,24 @@
     USER_HEAP_FREE( hwnd );
 }
 
-
 /***********************************************************************
- *	     WIN_DestroyQueueWindows
+ *           WIN_ResetQueueWindows
  */
-void WIN_DestroyQueueWindows( WND* wnd, HQUEUE16 hQueue )
+void WIN_ResetQueueWindows( WND* wnd, HQUEUE16 hQueue, HQUEUE16 hNew )
 {
     WND* next;
 
     while (wnd)
     {
         next = wnd->next;
-        if (wnd->hmemTaskQ == hQueue) DestroyWindow( wnd->hwndSelf );
-        else WIN_DestroyQueueWindows( wnd->child, hQueue );
+        if (wnd->hmemTaskQ == hQueue)
+	   if( hNew ) wnd->hmemTaskQ = hNew;
+	   else DestroyWindow( wnd->hwndSelf );
+        else WIN_ResetQueueWindows( wnd->child, hQueue, hNew );
         wnd = next;
     }
 }
 
-
 /***********************************************************************
  *           WIN_CreateDesktopWindow
  *
@@ -736,8 +736,12 @@
     }
     else wndPtr->wIDmenu = (UINT)cs->hMenu;
 
-    /* Send the WM_CREATE message */
+    /* Send the WM_CREATE message 
+     * Perhaps we shouldn't allow width/height changes as well. 
+     * See p327 in "Internals". 
+     */
 
+    maxPos.x = wndPtr->rectWindow.left; maxPos.y = wndPtr->rectWindow.top;
     if (unicode)
     {
         if (!SendMessage32W( hwnd, WM_NCCREATE, 0, (LPARAM)cs)) wmcreate = -1;
@@ -745,6 +749,8 @@
         {
             WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
                                    NULL, NULL, 0, &wndPtr->rectClient );
+	    OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
+					    maxPos.y - wndPtr->rectWindow.top);
             wmcreate = SendMessage32W( hwnd, WM_CREATE, 0, (LPARAM)cs );
         }
     }
@@ -755,6 +761,8 @@
         {
             WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
                                    NULL, NULL, 0, &wndPtr->rectClient );
+            OffsetRect16(&wndPtr->rectWindow, maxPos.x - wndPtr->rectWindow.left,
+                                            maxPos.y - wndPtr->rectWindow.top);
             wmcreate = SendMessage32A( hwnd, WM_CREATE, 0, (LPARAM)cs );
         }
     }
@@ -799,7 +807,6 @@
     {
 	/* MinMaximize(hwnd, SW_SHOWMAXIMIZED, 1) */
 
-        POINT16 maxSize, maxPos, minTrack, maxTrack;
         NC_GetMinMaxInfo( wndPtr, &maxSize, &maxPos, &minTrack, &maxTrack );
         SetWindowPos( hwnd, 0, maxPos.x, maxPos.y, maxSize.x, maxSize.y,
             ((GetActiveWindow())? SWP_NOACTIVATE : 0) | SWP_FRAMECHANGED );
diff --git a/windows/winproc.c b/windows/winproc.c
index aa212e7..2fa5f5d 100644
--- a/windows/winproc.c
+++ b/windows/winproc.c
@@ -964,6 +964,82 @@
     case BM_SETSTYLE32:
         *pmsg16 = (UINT16)msg32 + (BM_GETCHECK16 - BM_GETCHECK32);
         return 0;
+    case LB_CARETOFF32:
+    case LB_CARETON32:
+    case LB_DELETESTRING32:
+    case LB_GETANCHORINDEX32:
+    case LB_GETCARETINDEX32:
+    case LB_GETCOUNT32:
+    case LB_GETCURSEL32:
+    case LB_GETHORIZONTALEXTENT32:
+    case LB_GETITEMDATA32:
+    case LB_GETITEMHEIGHT32:
+    case LB_GETSEL32:
+    case LB_GETSELCOUNT32:
+    case LB_GETTEXTLEN32:
+    case LB_GETTOPINDEX32:
+    case LB_RESETCONTENT32:
+    case LB_SELITEMRANGE32:
+    case LB_SELITEMRANGEEX32:
+    case LB_SETANCHORINDEX32:
+    case LB_SETCARETINDEX32:
+    case LB_SETCOLUMNWIDTH32:
+    case LB_SETCURSEL32:
+    case LB_SETHORIZONTALEXTENT32:
+    case LB_SETITEMDATA32:
+    case LB_SETITEMHEIGHT32:
+    case LB_SETSEL32:
+    case LB_SETTOPINDEX32:
+        *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
+        return 0;
+    case LB_ADDSTRING32:
+    case LB_FINDSTRING32:
+    case LB_FINDSTRINGEXACT32:
+    case LB_INSERTSTRING32:
+    case LB_SELECTSTRING32:
+    case LB_DIR32:
+    case LB_ADDFILE32:
+/*    case LB_GETTEXT32: FIXME */
+        {
+            LPSTR str = SEGPTR_STRDUP( (LPSTR)*plparam );
+            if (!str) return -1;
+            *plparam = (LPARAM)SEGPTR_GET(str);
+        }
+        *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
+        return 1;
+    case LB_GETITEMRECT32:
+        {
+            RECT16 *rect;
+            rect = (RECT16 *)SEGPTR_ALLOC( sizeof(RECT16) + sizeof(LPARAM) );
+            if (!rect) return -1;
+            *(LPARAM *)(rect + 1) = *plparam;  /* Store the previous lParam */
+            *plparam = (LPARAM)SEGPTR_GET(rect);
+        }
+        return 1;
+    case LB_GETSELITEMS32:
+        {
+            LPINT16 items;
+            *pwparam16 = (WPARAM16)MIN( wParam32, 0x7f80 ); /* Must be < 64K */
+            if (!(items = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
+                                        + sizeof(LPARAM)))) return -1;
+            *((LPARAM *)items)++ = *plparam;  /* Store the previous lParam */
+            *plparam = (LPARAM)SEGPTR_GET(items);
+        }
+        return 1;
+    case LB_SETTABSTOPS32:
+        if (wParam32)
+        {
+            INT32 i;
+            LPINT16 stops;
+            *pwparam16 = (WPARAM16)MIN( wParam32, 0x7f80 ); /* Must be < 64K */
+            if (!(stops = SEGPTR_ALLOC( *pwparam16 * sizeof(INT16)
+                                        + sizeof(LPARAM)))) return -1;
+            for (i = 0; i < *pwparam16; i++) stops[i] = *((LPINT32)*plparam+i);
+            *plparam = (LPARAM)SEGPTR_GET(stops);
+            return 1;
+        }
+        *pmsg16 = LB_SETTABSTOPS16;
+        return 0;
     case WM_ACTIVATE:
     case WM_CHARTOITEM:
     case WM_COMMAND:
@@ -1173,15 +1249,41 @@
  *
  * Unmap a message that was mapped from 32-bit Ansi to 16-bit.
  */
-void WINPROC_UnmapMsg32ATo16( UINT16 msg, WPARAM16 wParam, LPARAM lParam )
+void WINPROC_UnmapMsg32ATo16( UINT32 msg, WPARAM16 wParam, LPARAM lParam )
 {
     switch(msg)
     {
+    case LB_ADDFILE32:
+    case LB_ADDSTRING32:
+    case LB_DIR32:
+    case LB_FINDSTRING32:
+    case LB_FINDSTRINGEXACT32:
+    case LB_INSERTSTRING32:
+    case LB_SELECTSTRING32:
+    case LB_SETTABSTOPS32:
     case WM_COMPAREITEM:
     case WM_DELETEITEM:
     case WM_DRAWITEM:
+    case WM_SETTEXT:
         SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
         break;
+    case LB_GETITEMRECT32:
+        {
+            RECT16 *rect = (RECT16 *)PTR_SEG_TO_LIN(lParam);
+            lParam = *(LPARAM *)(rect + 1);
+            CONV_RECT16TO32( rect, (RECT32 *)lParam );
+            SEGPTR_FREE( rect );
+        }
+        break;
+    case LB_GETSELITEMS32:
+        {
+            INT32 i;
+            LPINT16 items = (LPINT16)PTR_SEG_TO_LIN(lParam);
+            lParam = *((LPARAM *)items - 1);
+            for (i = 0; i < wParam; i++) *((LPINT32)lParam + i) = items[i];
+            SEGPTR_FREE( (LPARAM *)items - 1 );
+        }
+        break;
     case WM_MEASUREITEM:
         {
             MEASUREITEMSTRUCT16 *mis = (MEASUREITEMSTRUCT16 *)PTR_SEG_TO_LIN(lParam);
@@ -1242,9 +1344,6 @@
             SEGPTR_FREE( cs );
         }
         break;
-    case WM_SETTEXT:
-        SEGPTR_FREE( PTR_SEG_TO_LIN(lParam) );
-        break;
     case WM_WINDOWPOSCHANGING:
     case WM_WINDOWPOSCHANGED:
         {
@@ -1269,6 +1368,22 @@
 {
     switch(msg32)
     {
+    case LB_ADDSTRING32:
+    case LB_FINDSTRING32:
+    case LB_FINDSTRINGEXACT32:
+    case LB_INSERTSTRING32:
+    case LB_SELECTSTRING32:
+    case LB_DIR32:
+    case LB_ADDFILE32:
+        {
+            LPSTR str = SEGPTR_ALLOC( lstrlen32W((LPWSTR)*plparam) + 1 );
+            if (!str) return -1;
+            STRING32_UniToAnsi( str, (LPWSTR)*plparam );
+            *pmsg16 = (UINT16)msg32 + (LB_ADDSTRING16 - LB_ADDSTRING32);
+            *pwparam16 = (WPARAM16)LOWORD(wParam32);
+            *plparam   = (LPARAM)SEGPTR_GET(str);
+        }
+        return 1;
     case WM_NCCREATE:
     case WM_CREATE:
         {
@@ -1344,7 +1459,7 @@
  *
  * Unmap a message that was mapped from 32-bit Unicode to 16-bit.
  */
-void WINPROC_UnmapMsg32WTo16( UINT16 msg, WPARAM16 wParam, LPARAM lParam )
+void WINPROC_UnmapMsg32WTo16( UINT32 msg, WPARAM16 wParam, LPARAM lParam )
 {
     switch(msg)
     {
@@ -1461,7 +1576,7 @@
     if (wndPtr) CURRENT_DS = wndPtr->hInstance;
     result = CallWndProc16( func, hwnd, msg16, wParam16, lParam );
     CURRENT_DS = ds;
-    WINPROC_UnmapMsg32ATo16( msg16, wParam16, lParam );
+    WINPROC_UnmapMsg32ATo16( msg, wParam16, lParam );
     return result;
 }
 
@@ -1486,7 +1601,7 @@
     if (wndPtr) CURRENT_DS = wndPtr->hInstance;
     result = CallWndProc16( func, hwnd, msg16, wParam16, lParam );
     CURRENT_DS = ds;
-    WINPROC_UnmapMsg32WTo16( msg16, wParam16, lParam );
+    WINPROC_UnmapMsg32WTo16( msg, wParam16, lParam );
     return result;
 }
 
diff --git a/wine.man b/wine.man
index 3e71c1a..0247164 100644
--- a/wine.man
+++ b/wine.man
@@ -9,7 +9,7 @@
 ]
 .I program_name
 [
-.I arguments
+.I program_name...
 ]
 .SH DESCRIPTION
 .B wine