Release 950727

Sat Jul 22 22:39:09 IDT 1995 Michael Veksler <e1678223@tochnapc2.technion.ac.il>

	* [ipc/*]
	New directory. This directory contains the new inter-wine
 	communications support. It enables DDE protocols between two wine
 	instances.  Currently it is limited to DDE, but can be enhanced to
 	support OLE between 2 different wine instances.  This is very
 	important for libwine.a DDE/OLE support.

	* [tools/ipcl]
    	A script to delete garbage IPC handles (shared memory, semaphores
 	and message queues).  The current inter-wine communication is not
 	perfect, and sometimes leaves garbage behind.

	* [if1632/relay.c] [include/atom.h] [include/global.h]
 	[loader/selector.c] [loader/task.c] [loader/module.c]
 	[loader/signal.c] [memory/global.c] [misc/atom.c]
 	[windows/class.c] [windows/message.c] [windows/win.c]
	[Imakefile]
    	Hooks for inter-wine DDE support, current Global.*Atom functions
 	renamed to Local.*Atom since Global.*Atom are used for Inter-Wine
 	DDE communication. (The first call to these functions sets up the
 	IPC structures - which otherwise cause unneeded overhead.

Mon Jul 17 19:55:21 1995  Alexandre Julliard  <julliard@sunsite.unc.edu>

	* [controls/menu.c]
	Don't crash if a NULL string is passed to menu functions.

	* [memory/selector.c]
	We now use a bit in ldt_flags_copy to indicate free LDT entries.
	Fixed a bug in SELECTOR_ReallocBlock that could cause it to
	overwrite valid LDT entries when growing a block.

	* [miscemu/instr.c]
	Emulate int xx instruction by storing the interrupt vector in
	CS:IP and returning directly. This allows a program to install an
	interrupt vector.

	* [windows/win.c]
	Added function WIN_GetTopParent to get the top-level parent of a
	window.

Sun Jul  16 18:17:17 1995  Gregory Trubetskoy <grisha@mira.com>

        * [loader/resource.c]
        Added LoadIconHandler. It doesn't do anything yet, but now you
        can use borland help files with winhelp.exe.

Sun Jul 16 11:58:45 1995 Anand Kumria <akumria@ozemail.com.au>

	* [misc/main.c]
	Fixed to return 386 Enhanced mode correctly. Also return the same
 	type of CPU, for both Enhanced and Standard mode, namely a 386.

Sun Jul 16 00:02:04 1995    Martin von Loewis <loewis@informatik.hu-berlin.de>

	* [Configure] [include/options.h] [include/wineopts.h]
	  [misc/main.c][misc/spy.c]
	  Removed support of spy file. Redirected spy messages to stddeb.
	  Removed -spy option. Added -debugmsg +spy option.

	* [debugger/dbg.y][debugger/debug.l]
	Enabled segmented addresses (seg:offs) for break and x commands.

	* [if1632/gdi.spec] [objects/region.c] [windows/graphics.c]
	  [include/region.h]
	FrameRgn, REGION_FrameRgn: New functions

	* [if1632/kernel.spec]
	IsWinOldApTask: Return false

	* [if1632/mouse.spec]
	CplApplet: Removed

	* [if1632/user.spec] [windows/win.c]
	ShowOwnedPopups: New function

	* [if1632/winsock.spec] [misc/winsocket.c]
	inet_addr, select: New prototypes in relay code
	Fixed memory layout for netdb functions (getXbyY).
	WINSOCK_ioctlsocket: Translated FIONREAD, FIONBIO, and FIOASYNC

	* [objects/clipping.c]
	RectVisible: Fixed call to LPToDP

	* [rc/winerc.c]
	main: Removed extra argument to getopt for Linux.

Tue Jul 11 00:14:41 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

        * [controls/listbox.c]
	Yet another fix for ListBoxDirectory().
	
	* [loader/module.c] [if1632/kernel.spec]
	Make GetModuleHandle() accept instance handles as parameter.

        * [if1632/relay.c] [loader/task.c]
	Put a magic cookie at the bottom of the 32 bit stack, and check on
	each return from a 32 bit function whether it's still there. Complain
	if it's not.

        * [if1632/user.spec]
	Wrong entry for CloseDriver().

	* [misc/dos_fs.c] [loader/task.c] [include/dos_fs.h] [misc/file.c]
	[miscemu/int21.c]
	Large parts of dos_fs.c simplified. Changed it to use one
	current drive/directory per task, which is set to the module path on
	task creation.
	Prevent CorelPaint from closing stdin.
	open() with O_CREAT set must be passed three parameters.
	DOS FindFirst()/FindNext() could crash when FA_LABEL was set. Fixed,
	it's in DOS_readdir() now.

	* [misc/profile.c]
	Some badly written software (Lotus Freelance Graphics) passes a bogus
	size parameter that caused Wine to write off the end of a segment.
	Fixed. (It's probably too paranoid now.)
	
	* [multimedia/mmsystem.c] [multimedia/time.c] [multimedia/joystick.c]
	[multimedia/Imakefile] [if1632/winprocs.spec]
	16 bit entry point for MMSysTimeCallback.
	Split off time.c and joystick.c from mmsystem.c.
	
	* [objects/dib.c]
	GetDIBits(): call XGetImage() via CallTo32_LargeStack.

        * [windows/cursor.c]
	DestroyCursor(): do nothing for builtin cursors.
	
	* [windows/mdi.c]
	Half of WM_MDISETMENU implemented.
	
	* [windows/win.c]
	EnumWindows() and EnumTaskWindows() never enumerated any windows.
	Fixed.

	* [windows/*.c]
	Fixed GetParent() to return correct values for owned windows.

	* [windows/message.c]
	Don't try to activate disabled top-level windows.

        * [windows/nonclient.c]
	Work around a bug in gcc-2.7.0.
	
	* [tools/build.c] [include/stackframe.h] [memory/global.c] 
	[loader/task.c] [memory/selector.c]
	Some Visual Basic programs (and possibly others, too) expect ES to be 
	preserved by a call to an API function, so we have to save it.
	In GlobalFree() and FreeSelector(), we must clear CURRENT_STACK16->es 
	to prevent segfaults if ES contained the selector to be freed.

Sun Jul  9 20:21:20 1995  Jon Tombs  <jon@gtex02.us.es>

	* [*/*]
	Added missing prototypes to header files and relevant includes
	to reduce compile time warnings.

Sun Jul  9 18:32:56 1995  Michael Patra  <micky@marie.physik.tu-berlin.de>

	* [configure.in] [include/config.h] [*/Makefile.in]
	New configuration scheme based on autoconf.

Sat Jul  8 14:12:45 1995  Morten Welinder  <terra+@cs.cmu.edu>

	* [miscemu/ioports.c]
	Revamp to have only one in- and one out- variant, both really
 	implemented.

	* [miscemu/instr.c]
	INSTR_EmulateInstruction: Use new ioport interface.  Implement
 	string io.  Correct instruction pointer for 32-bit code.

	* [include/miscemu.h]
	Update port function prototypes.

	* [include/registers.h]
	Defined FS and GS.

Sat Jul  8 13:38:54 1995  Hans de Graaff  <graaff@twi72.twi.tudelft.nl>

	* [misc/dos_fs.c]
	ChopOffSlash(): A path consisting off a single slash is left
 	intact, and multiple slashes are all removed.
diff --git a/ANNOUNCE b/ANNOUNCE
index 35713f1..a8b38b9 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,14 +1,15 @@
-This is release 950706 of Wine the MS Windows emulator.  This is still a
+This is release 950727 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.
 
 Patches should be submitted to "wine-new@amscons.com".  Please don't forget
 to include a ChangeLog entry.  I'll make a new release every other Sunday.
 
-WHAT'S NEW with Wine-950706: (see ChangeLog for details)
-	- Built-in debugger supports single-stepping (please test it on *BSD).
-	- Winelib should compile again.
-	- More OLE2 functions.
+WHAT'S NEW with Wine-950727: (see ChangeLog for details)
+	- New configuration scheme based on autoconf (please test it).
+	- DDE communication between separate Wine processes.
+	- Lots of file handling fixes.
+	- Fixes to built-in WINSOCK.DLL.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -17,11 +18,11 @@
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-    sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-950706.tar.gz
-    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950706.tar.gz
-    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950706.tar.gz
-    ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950706.tar.gz
-    aris.com:/pub/linux/ALPHA/Wine/development/Wine-950706.tar.gz
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-950727.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950727.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950727.tar.gz
+    ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950727.tar.gz
+    aris.com:/pub/linux/ALPHA/Wine/development/Wine-950727.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index 4eab56d..b093b41 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,193 @@
 ----------------------------------------------------------------------
-Wed Jul  5 19:06:35 1995  Alexandre Julliard  <alex@numenor>
+Sat Jul 22 22:39:09 IDT 1995 Michael Veksler <e1678223@tochnapc2.technion.ac.il>
+
+	* [ipc/*]
+	New directory. This directory contains the new inter-wine
+ 	communications support. It enables DDE protocols between two wine
+ 	instances.  Currently it is limited to DDE, but can be enhanced to
+ 	support OLE between 2 different wine instances.  This is very
+ 	important for libwine.a DDE/OLE support.
+
+	* [tools/ipcl]
+    	A script to delete garbage IPC handles (shared memory, semaphores
+ 	and message queues).  The current inter-wine communication is not
+ 	perfect, and sometimes leaves garbage behind.
+
+	* [if1632/relay.c] [include/atom.h] [include/global.h]
+ 	[loader/selector.c] [loader/task.c] [loader/module.c]
+ 	[loader/signal.c] [memory/global.c] [misc/atom.c]
+ 	[windows/class.c] [windows/message.c] [windows/win.c]
+	[Imakefile]
+    	Hooks for inter-wine DDE support, current Global.*Atom functions
+ 	renamed to Local.*Atom since Global.*Atom are used for Inter-Wine
+ 	DDE communication. (The first call to these functions sets up the
+ 	IPC structures - which otherwise cause unneeded overhead.
+
+Mon Jul 17 19:55:21 1995  Alexandre Julliard  <julliard@sunsite.unc.edu>
+
+	* [controls/menu.c]
+	Don't crash if a NULL string is passed to menu functions.
+
+	* [memory/selector.c]
+	We now use a bit in ldt_flags_copy to indicate free LDT entries.
+	Fixed a bug in SELECTOR_ReallocBlock that could cause it to
+	overwrite valid LDT entries when growing a block.
+
+	* [miscemu/instr.c]
+	Emulate int xx instruction by storing the interrupt vector in
+	CS:IP and returning directly. This allows a program to install an
+	interrupt vector.
+
+	* [windows/win.c]
+	Added function WIN_GetTopParent to get the top-level parent of a
+	window.
+
+Sun Jul  16 18:17:17 1995  Gregory Trubetskoy <grisha@mira.com>
+
+        * [loader/resource.c]
+        Added LoadIconHandler. It doesn't do anything yet, but now you
+        can use borland help files with winhelp.exe.
+
+Sun Jul 16 11:58:45 1996  Anand Kumria <akumria@ozemail.com.au>
+
+	* [misc/main.c]
+	Fixed to return 386 Enhanced mode correctly. Also return the same
+ 	type of CPU, for both Enhanced and Standard mode, namely a 386.
+
+Sun Jul 16 00:02:04 1995    Martin von Loewis <loewis@informatik.hu-berlin.de>
+
+	* [Configure] [include/options.h] [include/wineopts.h]
+	  [misc/main.c][misc/spy.c]
+	  Removed support of spy file. Redirected spy messages to stddeb.
+	  Removed -spy option. Added -debugmsg +spy option.
+
+	* [debugger/dbg.y][debugger/debug.l]
+	Enabled segmented addresses (seg:offs) for break and x commands.
+
+	* [if1632/gdi.spec] [objects/region.c] [windows/graphics.c]
+	  [include/region.h]
+	FrameRgn, REGION_FrameRgn: New functions
+
+	* [if1632/kernel.spec]
+	IsWinOldApTask: Return false
+
+	* [if1632/mouse.spec]
+	CplApplet: Removed
+
+	* [if1632/user.spec] [windows/win.c]
+	ShowOwnedPopups: New function
+
+	* [if1632/winsock.spec] [misc/winsocket.c]
+	inet_addr, select: New prototypes in relay code
+	Fixed memory layout for netdb functions (getXbyY).
+	WINSOCK_ioctlsocket: Translated FIONREAD, FIONBIO, and FIOASYNC
+
+	* [objects/clipping.c]
+	RectVisible: Fixed call to LPToDP
+
+	* [rc/winerc.c]
+	main: Removed extra argument to getopt for Linux.
+
+Tue Jul 11 00:14:41 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+        * [controls/listbox.c]
+	Yet another fix for ListBoxDirectory().
+	
+	* [loader/module.c] [if1632/kernel.spec]
+	Make GetModuleHandle() accept instance handles as parameter.
+
+        * [if1632/relay.c] [loader/task.c]
+	Put a magic cookie at the bottom of the 32 bit stack, and check on
+	each return from a 32 bit function whether it's still there. Complain
+	if it's not.
+
+        * [if1632/user.spec]
+	Wrong entry for CloseDriver().
+
+	* [misc/dos_fs.c] [loader/task.c] [include/dos_fs.h] [misc/file.c]
+	[miscemu/int21.c]
+	Large parts of dos_fs.c simplified. Changed it to use one
+	current drive/directory per task, which is set to the module path on
+	task creation.
+	Prevent CorelPaint from closing stdin.
+	open() with O_CREAT set must be passed three parameters.
+	DOS FindFirst()/FindNext() could crash when FA_LABEL was set. Fixed,
+	it's in DOS_readdir() now.
+
+	* [misc/profile.c]
+	Some badly written software (Lotus Freelance Graphics) passes a bogus
+	size parameter that caused Wine to write off the end of a segment.
+	Fixed. (It's probably too paranoid now.)
+	
+	* [multimedia/mmsystem.c] [multimedia/time.c] [multimedia/joystick.c]
+	[multimedia/Imakefile] [if1632/winprocs.spec]
+	16 bit entry point for MMSysTimeCallback.
+	Split off time.c and joystick.c from mmsystem.c.
+	
+	* [objects/dib.c]
+	GetDIBits(): call XGetImage() via CallTo32_LargeStack.
+
+        * [windows/cursor.c]
+	DestroyCursor(): do nothing for builtin cursors.
+	
+	* [windows/mdi.c]
+	Half of WM_MDISETMENU implemented.
+	
+	* [windows/win.c]
+	EnumWindows() and EnumTaskWindows() never enumerated any windows.
+	Fixed.
+
+	* [windows/*.c]
+	Fixed GetParent() to return correct values for owned windows.
+
+	* [windows/message.c]
+	Don't try to activate disabled top-level windows.
+
+        * [windows/nonclient.c]
+	Work around a bug in gcc-2.7.0.
+	
+	* [tools/build.c] [include/stackframe.h] [memory/global.c] 
+	[loader/task.c] [memory/selector.c]
+	Some Visual Basic programs (and possibly others, too) expect ES to be 
+	preserved by a call to an API function, so we have to save it.
+	In GlobalFree() and FreeSelector(), we must clear CURRENT_STACK16->es 
+	to prevent segfaults if ES contained the selector to be freed.
+
+Sun Jul  9 20:21:20 1995  Jon Tombs  <jon@gtex02.us.es>
+
+	* [*/*]
+	Added missing prototypes to header files and relevant includes
+	to reduce compile time warnings.
+
+Sun Jul  9 18:32:56 1995  Michael Patra  <micky@marie.physik.tu-berlin.de>
+
+	* [configure.in] [include/config.h] [*/Makefile.in]
+	New configuration scheme based on autoconf.
+
+Sat Jul  8 14:12:45 1995  Morten Welinder  <terra+@cs.cmu.edu>
+
+	* [miscemu/ioports.c]
+	Revamp to have only one in- and one out- variant, both really
+ 	implemented.
+
+	* [miscemu/instr.c]
+	INSTR_EmulateInstruction: Use new ioport interface.  Implement
+ 	string io.  Correct instruction pointer for 32-bit code.
+
+	* [include/miscemu.h]
+	Update port function prototypes.
+
+	* [include/registers.h]
+	Defined FS and GS.
+
+Sat Jul  8 13:38:54 1995  Hans de Graaff  <graaff@twi72.twi.tudelft.nl>
+
+	* [misc/dos_fs.c]
+	ChopOffSlash(): A path consisting off a single slash is left
+ 	intact, and multiple slashes are all removed.
+
+----------------------------------------------------------------------
+Wed Jul  5 19:06:35 1995  Alexandre Julliard  <julliard@sunsite.unc.edu>
 
 	* [controls/scroll.c]
 	Fixed drawing bug that caused part of a non-client scroll bar
diff --git a/Configure b/Configure
index 3a4c6f7..9a9435a 100644
--- a/Configure
+++ b/Configure
@@ -106,7 +106,6 @@
 	prompt "Where is COM1" CF_Com1 '/dev/cua0'
 	prompt "Where is COM2" CF_Com2 '/dev/cua1'
 	prompt "Where is LPT1" CF_Lpt1 '/dev/lp0'
-	prompt "Log messages to which file (CON = stdout)" CF_File 'CON'
 
 	echo
 	sed -n -e 's/^ *\"\(WM_[A-Z0-9]*\)\".*/\1/p' < misc/spy.c | \
@@ -147,7 +146,6 @@
 Lpt1=$CF_Lpt1
 
 [spy]
-File=$CF_File
 Exclude=$CF_Exclude
 EOF
 
diff --git a/Imakefile b/Imakefile
index 492798d..5488945 100644
--- a/Imakefile
+++ b/Imakefile
@@ -7,13 +7,6 @@
 #endif
 
 DEFINES = AutoDefines -DUSE_READLINE
-#ifdef __ELF__
-LD = /usr/i486-linuxaout/bin/ld -m i386linux
-CDEBUGFLAGS = -O2 -Wall -b i486-linuxaout
-ASFLAGS = -b i486-linuxaout
-#else
-CDEBUGFLAGS = -O2 -Wall
-#endif
 
 /*
  * This is the second try at using Imakefiles. There are probably many
@@ -33,6 +26,7 @@
 COMMONSUBDIRS = \
 	controls \
 	rc \
+	ipc \
 	loader \
 	misc \
 	multimedia \
@@ -53,6 +47,7 @@
 
 COMMONOBJS = \
 	controls/controls.o \
+	ipc/ipc.o \
 	loader/loader.o \
 	misc/misc.o \
 	multimedia/multimedia.o \
@@ -122,4 +117,4 @@
 distclean: clean
 	echo "/* autoconf.h generated automatically.  Run Configure */" >autoconf.h
 	echo "#error You must run Configure before you can build the makefiles." >>autoconf.h
-	$(RM) `find . -name Makefile -print`
+	$(RM) config.* `find . -name Makefile -print`
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..bec1f10
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,87 @@
+# This Makefile understands the following targets:
+#
+# all (default):	build wine
+# clean:		remove all intermediate files
+# distclean:		also remove all files created by configure
+# countryclean:		remove all files which have to be remade if
+#			a different LANGuage is selected
+# winelibclean:		remove all files which differ for the emulator
+#			and the library
+# depend:		create the dependencies
+#
+# Author: Michael Patra   <micky@marie.physik.tu-berlin.de>
+#                         <patra@itp1.physik.tu-berlin.de>
+
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include
+XPM_LIB	= -lXpm
+XLIB	= -lXext -lX11
+XDIR	= -L@x_libraries@
+LDLIBS	= -lm
+LD	= @LD@
+LANG	= @LANG@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+ 
+
+COMMONSUBDIRS = controls rc ipc loader misc multimedia objects windows
+
+EMUSUBDIRS = tools debugger if1632 memory miscemu
+
+LIBSUBDIRS = toolkit
+ 
+COMMONOBJS = controls/controls.o ipc/ipc.o loader/loader.o misc/misc.o \
+	multimedia/multimedia.o objects/objects.o rc/rc.o \
+	windows/windows.o
+
+EMUOBJS = debugger/debugger.o if1632/if1632.o memory/memory.o miscemu/miscemu.o
+
+LIBOBJS = toolkit/toolkit.o
+ 
+
+
+SUBDIRS = $(COMMONSUBDIRS) $(EMUSUBDIRS)
+
+OBJS = $(COMMONOBJS) $(EMUOBJS)
+
+
+all:
+	for i in $(SUBDIRS); do \
+	( cd $(TOPSRC)/$$i; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)' 'LANG=$(LANG)'); \
+	done
+	$(CC) -o wine $(OBJS) $(LDOPTIONS) $(XDIR) $(XPM_LIB) $(XLIB) $(LDLIBS)
+	nm wine | grep -v _compiled | sort >wine.sym
+
+depend:
+	for i in $(SUBDIRS); do \
+	( cd $(TOPSRC)/$$i; $(MAKE) depend); \
+	done
+
+clean:
+	for i in $(SUBDIRS); do \
+        ( cd $(TOPSRC)/$$i; $(MAKE) clean); \
+	done
+	rm -f *.o \#*\# *~ wine wine.sym
+
+distclean:
+	for i in $(SUBDIRS); do \
+	( cd $(TOPSRC)/$$i; $(MAKE) distclean); \
+	done
+	echo "/* autoconf.h generated automatically.  Run Configure */" >autoconf.h
+	echo "#error You must run Configure before you can build the makefiles." >>autoconf.h
+	rm -f *.o \#*\# *~ wine wine.sym
+	rm -f stamp-config config.* include/config.h Makefile
+
+countryclean:
+	for i in $(SUBDIRS); do \
+	( cd $(TOPSRC)/$$i; $(MAKE) countryclean); \
+	done
+	rm -f wine wine.sym
+
+winelibclean:
+	for i in $(SUBDIRS); do \
+	( cd $(TOPSRC)/$$i; $(MAKE) winelibclean); \
+	done
+	
diff --git a/autoconf.h.in b/autoconf.h.in
new file mode 100644
index 0000000..9c92cf4
--- /dev/null
+++ b/autoconf.h.in
@@ -0,0 +1,3 @@
+/* @configure_input@ */
+#define WINE_INI_GLOBAL @WINE_INI_GLOBAL@
+#define AutoDefines @LANG@
diff --git a/configure b/configure
new file mode 100755
index 0000000..f495a92
--- /dev/null
+++ b/configure
@@ -0,0 +1,1752 @@
+#! /bin/sh
+
+# From configure.in configure.in 1.00
+# Guess values for system-dependent variables and create Makefiles.
+# Generated automatically using autoconf version 2.4 
+# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+
+# Defaults:
+ac_help=
+ac_default_prefix=/usr/local
+# Any additions from configure.in:
+ac_help="$ac_help
+  --with-x                use the X Window System"
+
+# Initialize some variables set by options.
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+build=NONE
+cache_file=./config.cache
+exec_prefix=NONE
+host=NONE
+no_create=
+nonopt=NONE
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+target=NONE
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Initialize some other variables.
+subdirs=
+
+ac_prev=
+for ac_option
+do
+
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval "$ac_prev=\$ac_option"
+    ac_prev=
+    continue
+  fi
+
+  case "$ac_option" in
+  -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+  *) ac_optarg= ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case "$ac_option" in
+
+  -build | --build | --buil | --bui | --bu | --b)
+    ac_prev=build ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=* | --b=*)
+    build="$ac_optarg" ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file="$ac_optarg" ;;
+
+  -disable-* | --disable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    eval "enable_${ac_feature}=no" ;;
+
+  -enable-* | --enable-*)
+    ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
+    fi
+    ac_feature=`echo $ac_feature| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "enable_${ac_feature}='$ac_optarg'" ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix="$ac_optarg" ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he)
+    # Omit some internal or obsolete options to make the list less imposing.
+    # This message is too long to be a string in the A/UX 3.1 sh.
+    cat << EOF
+Usage: configure [options] [host]
+Options: [defaults in brackets after descriptions]
+Configuration:
+  --cache-file=FILE       cache test results in FILE
+  --help                  print this message
+  --no-create             do not create output files
+  --quiet, --silent       do not print \`checking...' messages
+  --version               print the version of autoconf that created configure
+Directory and file names:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=PREFIX    install architecture-dependent files in PREFIX
+                          [same as prefix]
+  --srcdir=DIR            find the sources in DIR [configure dir or ..]
+  --program-prefix=PREFIX prepend PREFIX to installed program names
+  --program-suffix=SUFFIX append SUFFIX to installed program names
+  --program-transform-name=PROGRAM run sed PROGRAM on installed program names
+Host type:
+  --build=BUILD           configure for building on BUILD [BUILD=HOST]
+  --host=HOST             configure for HOST [guessed]
+  --target=TARGET         configure for TARGET [TARGET=HOST]
+Features and packages:
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --x-includes=DIR        X include files are in DIR
+  --x-libraries=DIR       X library files are in DIR
+--enable and --with options recognized:$ac_help
+EOF
+    exit 0 ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host="$ac_optarg" ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix="$ac_optarg" ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix="$ac_optarg" ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix="$ac_optarg" ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name="$ac_optarg" ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site="$ac_optarg" ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir="$ac_optarg" ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target="$ac_optarg" ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers)
+    echo "configure generated by autoconf version 2.4"
+    exit 0 ;;
+
+  -with-* | --with-*)
+    ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    case "$ac_option" in
+      *=*) ;;
+      *) ac_optarg=yes ;;
+    esac
+    eval "with_${ac_package}='$ac_optarg'" ;;
+
+  -without-* | --without-*)
+    ac_package=`echo $ac_option|sed -e 's/-*without-//'`
+    # Reject names that are not valid shell variable names.
+    if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
+      { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
+    fi
+    ac_package=`echo $ac_package| sed 's/-/_/g'`
+    eval "with_${ac_package}=no" ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes="$ac_optarg" ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries="$ac_optarg" ;;
+
+  -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
+    ;;
+
+  *) 
+    if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
+      echo "configure: warning: $ac_option: invalid host type" 1>&2
+    fi
+    if test "x$nonopt" != xNONE; then
+      { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
+    fi
+    nonopt="$ac_option"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
+fi
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+# File descriptor usage:
+# 0 standard input
+# 1 file creation
+# 2 errors and warnings
+# 3 some systems may open it to /dev/tty
+# 4 used on the Kubota Titan
+# 6 checking for... messages and results
+# 5 compiler messages saved in config.log
+if test "$silent" = yes; then
+  exec 6>/dev/null
+else
+  exec 6>&1
+fi
+exec 5>./config.log
+
+echo "\
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+" 1>&5
+
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Also quote any args containing shell metacharacters.
+ac_configure_args=
+for ac_arg
+do
+  case "$ac_arg" in
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c) ;;
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
+  *" "*|*"	"*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
+  ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+  *) ac_configure_args="$ac_configure_args $ac_arg" ;;
+  esac
+done
+
+# NLS nuisances.
+# Only set LANG and LC_ALL to C if already set.
+# These must not be set unconditionally because not all systems understand
+# e.g. LANG=C (notably SCO).
+if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
+if test "${LANG+set}"   = set; then LANG=C;   export LANG;   fi
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo > confdefs.h
+
+# A filename unique to this package, relative to the directory that
+# configure is in, which we can look for to find out if srcdir is correct.
+ac_unique_file=controls/edit.c
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then its parent.
+  ac_prog=$0
+  ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
+  test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
+  srcdir=$ac_confdir
+  if test ! -r $srcdir/$ac_unique_file; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+  if test "$ac_srcdir_defaulted" = yes; then
+    { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
+  else
+    { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
+  fi
+fi
+srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
+
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+  if test "x$prefix" != xNONE; then
+    CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+  else
+    CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+  fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+  if test -r "$ac_site_file"; then
+    echo "loading site script $ac_site_file"
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  echo "loading cache $cache_file"
+  . $cache_file
+else
+  echo "creating cache $cache_file"
+  > $cache_file
+fi
+
+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 2>&5'
+ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5 2>&5'
+
+if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
+  # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
+  if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
+    ac_n= ac_c='
+' ac_t='	'
+  else
+    ac_n=-n ac_c= ac_t=
+  fi
+else
+  ac_n= ac_c='\c' ac_t=
+fi
+
+		
+
+
+# We want these before the checks, so the checks can modify their values.
+test -z "$CFLAGS" && CFLAGS="-g -O2 -Wall" 
+test -z "$LDFLAGS" && LDFLAGS=-g 
+
+echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
+set dummy ${MAKE-make}; ac_make=$2
+if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftestmake <<\EOF
+all:
+	@echo 'ac_maketemp="${MAKE}"'
+EOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
+if test -n "$ac_maketemp"; then
+  eval ac_cv_prog_make_${ac_make}_set=yes
+else
+  eval ac_cv_prog_make_${ac_make}_set=no
+fi
+rm -f conftestmake
+fi
+if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  SET_MAKE=
+else
+  echo "$ac_t""no" 1>&6
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+# 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
+if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_CC="gcc"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="cc"
+fi
+fi
+CC="$ac_cv_prog_CC"
+if test -n "$CC"; then
+  echo "$ac_t""$CC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+
+echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.c <<EOF
+#ifdef __GNUC__
+  yes;
+#endif
+EOF
+if ${CC-cc} -E conftest.c 2>&5 | egrep yes >/dev/null 2>&1; then
+  ac_cv_prog_gcc=yes
+else
+  ac_cv_prog_gcc=no
+fi
+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
+if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  echo 'void f(){}' > conftest.c
+if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
+  ac_cv_prog_gcc_g=yes
+else
+  ac_cv_prog_gcc_g=no
+fi
+rm -f conftest*
+
+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
+  fi
+else
+  GCC=
+  test "${CFLAGS+set}" = set || CFLAGS="-g"
+fi
+
+echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+    # This must be in double quotes, not single quotes, because CPP may get
+  # substituted into the Makefile and "${CC-cc}" will confuse make.
+  CPP="${CC-cc} -E"
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp.
+  cat > conftest.$ac_ext <<EOF
+#line 525 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  rm -rf conftest*
+  CPP="${CC-cc} -E -traditional-cpp"
+  cat > conftest.$ac_ext <<EOF
+#line 539 "configure"
+#include "confdefs.h"
+#include <assert.h>
+Syntax Error
+EOF
+eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+  :
+else
+  echo "$ac_err" >&5
+  rm -rf conftest*
+  CPP=/lib/cpp
+fi
+rm -f conftest*
+fi
+rm -f conftest*
+  ac_cv_prog_CPP="$CPP"
+fi
+  CPP="$ac_cv_prog_CPP"
+else
+  ac_cv_prog_CPP="$CPP"
+fi
+echo "$ac_t""$CPP" 1>&6
+
+# 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
+
+# Check whether --with-x or --without-x was given.
+withval="$with_x"
+if test -n "$withval"; then
+  :
+fi
+
+if test "x$with_x" = xno; then
+  no_x=yes
+else
+  if test "x$x_includes" != xNONE && test "x$x_libraries" != xNONE; then
+    no_x=
+  else
+if eval "test \"`echo '$''{'ac_cv_path_x'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  # One or both of the vars are not set, and there is no cached value.
+no_x=yes
+rm -fr conftestdir
+if mkdir conftestdir; then
+  cd conftestdir
+  # Make sure to not put "make" in the Imakefile rules, since we grep it out.
+  cat > Imakefile <<'EOF'
+acfindx:
+	@echo 'ac_im_incroot="${INCROOT}"; ac_im_usrlibdir="${USRLIBDIR}"; ac_im_libdir="${LIBDIR}"'
+EOF
+  if (xmkmf) >/dev/null 2>/dev/null && test -f Makefile; then
+    no_x=
+    # GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+    eval `make acfindx 2>/dev/null | grep -v make`
+    # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR.
+    for ac_extension in a so sl; do
+      if test ! -f $ac_im_usrlibdir/libX11.$ac_extension &&
+        test -f $ac_im_libdir/libX11.$ac_extension; then
+        ac_im_usrlibdir=$ac_im_libdir; break
+      fi
+    done
+    # Screen out bogus values from the imake configuration.
+    case "$ac_im_incroot" in
+	/usr/include) ;;
+	*) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes="$ac_im_incroot" ;;
+    esac
+    case "$ac_im_usrlibdir" in
+	/usr/lib | /lib) ;;
+	*) test -d "$ac_im_usrlibdir" && ac_x_libraries="$ac_im_usrlibdir" ;;
+    esac
+  fi
+  cd ..
+  rm -fr conftestdir
+fi
+
+if test "$no_x" = yes; then
+test -z "$x_direct_test_library" && x_direct_test_library=Xt
+test -z "$x_direct_test_function" && x_direct_test_function=XtMalloc
+test -z "$x_direct_test_include" && x_direct_test_include=X11/Intrinsic.h
+cat > conftest.$ac_ext <<EOF
+#line 625 "configure"
+#include "confdefs.h"
+#include <$x_direct_test_include>
+EOF
+eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  no_x= ac_x_includes=
+else
+  echo "$ac_err" >&5
+  rm -rf conftest*
+    for ac_dir in               \
+    /usr/X11R6/include        \
+    /usr/X11R5/include        \
+    /usr/X11R4/include        \
+                              \
+    /usr/include/X11R6        \
+    /usr/include/X11R5        \
+    /usr/include/X11R4        \
+                              \
+    /usr/local/X11R6/include  \
+    /usr/local/X11R5/include  \
+    /usr/local/X11R4/include  \
+                              \
+    /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  \
+                              \
+    /usr/include              \
+    /usr/local/include        \
+    /usr/unsupported/include  \
+    /usr/athena/include       \
+    /usr/local/x11r5/include  \
+    /usr/lpp/Xamples/include  \
+                              \
+    /usr/openwin/include      \
+    /usr/openwin/share/include \
+    ; \
+  do
+    if test -r "$ac_dir/$x_direct_test_include"; then
+      no_x= ac_x_includes=$ac_dir
+      break
+    fi
+  done
+fi
+rm -f conftest*
+
+# Check for the libraries.
+# See if we find them without any special options.
+# Don't add to $LIBS permanently.
+ac_save_LIBS="$LIBS"
+LIBS="-l$x_direct_test_library $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 688 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+${x_direct_test_function}()
+; return 0; }
+EOF
+if eval $ac_link; then
+  rm -rf conftest*
+  LIBS="$ac_save_LIBS" no_x= ac_x_libraries=
+else
+  rm -rf conftest*
+  LIBS="$ac_save_LIBS"
+# First see if replacing the include by lib works.
+for ac_dir in `echo "$ac_x_includes" | sed s/include/lib/` \
+    /usr/X11R6/lib        \
+    /usr/X11R5/lib        \
+    /usr/X11R4/lib        \
+                          \
+    /usr/lib/X11R6        \
+    /usr/lib/X11R5        \
+    /usr/lib/X11R4        \
+                          \
+    /usr/local/X11R6/lib  \
+    /usr/local/X11R5/lib  \
+    /usr/local/X11R4/lib  \
+                          \
+    /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  \
+                          \
+    /usr/lib              \
+    /usr/local/lib        \
+    /usr/unsupported/lib  \
+    /usr/athena/lib       \
+    /usr/local/x11r5/lib  \
+    /usr/lpp/Xamples/lib  \
+                          \
+    /usr/openwin/lib      \
+    /usr/openwin/share/lib \
+    ; \
+do
+  for ac_extension in a so sl; do
+    if test -r $ac_dir/lib${x_direct_test_library}.$ac_extension; then
+      no_x= ac_x_libraries=$ac_dir
+      break 2
+    fi
+  done
+done
+fi
+rm -f conftest*
+
+fi
+if test "$no_x" = yes; then
+  ac_cv_path_x="no_x=yes"
+else
+  ac_cv_path_x="no_x= ac_x_includes=$ac_x_includes ac_x_libraries=$ac_x_libraries"
+fi
+fi
+  fi
+  eval "$ac_cv_path_x"
+fi # $with_x != no
+
+if test "$no_x" = yes; then
+  echo "$ac_t""no" 1>&6
+else
+  test "x$x_includes" = xNONE && x_includes=$ac_x_includes
+  test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries
+  ac_cv_path_x="no_x= ac_x_includes=$x_includes ac_x_libraries=$x_libraries"
+  echo "$ac_t""libraries $x_libraries, headers $x_includes" 1>&6
+fi
+
+for ac_prog in 'bison -y' byacc
+do
+# 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
+if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_YACC="$ac_prog"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+fi
+fi
+YACC="$ac_cv_prog_YACC"
+if test -n "$YACC"; then
+  echo "$ac_t""$YACC" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+# 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
+if eval "test \"`echo '$''{'ac_cv_prog_LEX'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$ac_word; then
+      ac_cv_prog_LEX="flex"
+      break
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_prog_LEX" && ac_cv_prog_LEX="lex"
+fi
+fi
+LEX="$ac_cv_prog_LEX"
+if test -n "$LEX"; then
+  echo "$ac_t""$LEX" 1>&6
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+if test -z "$LEXLIB"
+then
+  case "$LEX" in
+  flex*) ac_lib=fl ;;
+  *) ac_lib=l ;;
+  esac
+  echo $ac_n "checking for -l$ac_lib""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib'+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 844 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+yywrap()
+; return 0; }
+EOF
+if eval $ac_link; then
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib=yes"
+else
+  rm -rf conftest*
+  eval "ac_cv_lib_$ac_lib=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'$ac_lib`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LEXLIB="-l$ac_lib"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+if test -n "$x_includes" ; then
+  x_includes="-I$x_includes"
+fi
+if test -n "$x_no" ; then
+  AXFILES='AXFILES='
+fi
+
+
+
+
+
+LD=ld
+LDCOMBINEFLAGS="-r"
+
+
+
+for ac_func in tcgetattr
+do
+echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
+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 895 "configure"
+#include "confdefs.h"
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func(); below.  */
+#include <assert.h>
+/* Override any gcc2 internal prototype to avoid an error.  */
+char $ac_func(); 
+
+int main() { return 0; }
+int t() {
+
+/* 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_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+$ac_func();
+#endif
+
+; return 0; }
+EOF
+if eval $ac_link; then
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=yes"
+else
+  rm -rf conftest*
+  eval "ac_cv_func_$ac_func=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_func=HAVE_`echo $ac_func | tr '[a-z]' '[A-Z]'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_func 1
+EOF
+ 
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+for ac_hdr in stdlib.h
+do
+ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 947 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+ac_err=`grep -v '^ *+' conftest.out`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | tr '[a-z]./\055' '[A-Z]___'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ 
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+ac_header_dirent=no
+for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
+do
+ac_safe=`echo "$ac_hdr" | tr './\055' '___'`
+echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 984 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <$ac_hdr>
+int main() { return 0; }
+int t() {
+DIR *dirp = 0;
+; return 0; }
+EOF
+if eval $ac_compile; then
+  rm -rf conftest*
+  eval "ac_cv_header_dirent_$ac_safe=yes"
+else
+  rm -rf conftest*
+  eval "ac_cv_header_dirent_$ac_safe=no"
+fi
+rm -f conftest*
+
+fi
+if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | tr '[a-z]./\055' '[A-Z]___'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ ac_header_dirent=$ac_hdr; break
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
+if test $ac_header_dirent = dirent.h; then
+echo $ac_n "checking for -ldir""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_lib_dir'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-ldir  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1023 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+opendir()
+; return 0; }
+EOF
+if eval $ac_link; then
+  rm -rf conftest*
+  eval "ac_cv_lib_dir=yes"
+else
+  rm -rf conftest*
+  eval "ac_cv_lib_dir=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'dir`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LIBS="$LIBS -ldir"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+else
+echo $ac_n "checking for -lx""... $ac_c" 1>&6
+if eval "test \"`echo '$''{'ac_cv_lib_x'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  ac_save_LIBS="$LIBS"
+LIBS="-lx  $LIBS"
+cat > conftest.$ac_ext <<EOF
+#line 1057 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+opendir()
+; return 0; }
+EOF
+if eval $ac_link; then
+  rm -rf conftest*
+  eval "ac_cv_lib_x=yes"
+else
+  rm -rf conftest*
+  eval "ac_cv_lib_x=no"
+fi
+rm -f conftest*
+LIBS="$ac_save_LIBS"
+
+fi
+if eval "test \"`echo '$ac_cv_lib_'x`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+  LIBS="$LIBS -lx"
+else
+  echo "$ac_t""no" 1>&6
+fi
+
+fi
+
+echo $ac_n "checking whether stat file-mode macros are broken""... $ac_c" 1>&6
+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 1090 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#if defined(S_ISBLK) && defined(S_IFDIR)
+# if S_ISBLK (S_IFDIR)
+You lose.
+# endif
+#endif
+
+#if defined(S_ISBLK) && defined(S_IFCHR)
+# if S_ISBLK (S_IFCHR)
+You lose.
+# endif
+#endif
+
+#if defined(S_ISLNK) && defined(S_IFREG)
+# if S_ISLNK (S_IFREG)
+You lose.
+# endif
+#endif
+
+#if defined(S_ISSOCK) && defined(S_IFREG)
+# if S_ISSOCK (S_IFREG)
+You lose.
+# endif
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "You lose" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_header_stat_broken=yes
+else
+  rm -rf conftest*
+  ac_cv_header_stat_broken=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_header_stat_broken" 1>&6
+if test $ac_cv_header_stat_broken = yes; then
+  cat >> confdefs.h <<\EOF
+#define STAT_MACROS_BROKEN 1
+EOF
+
+fi
+
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+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 1144 "configure"
+#include "confdefs.h"
+
+int main() { return 0; }
+int t() {
+
+/* Ultrix mips cc rejects this.  */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this.  */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this.  */
+struct point {int x, y;};
+static struct point const zero;
+/* AIX XL C 1.02.0.0 rejects this.
+   It does not let you subtract one const X* pointer from another in an arm
+   of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this.  */
+  char *t;
+  char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+  *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+  int x[] = {25, 17};
+  const int *foo = &x[0];
+  ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+  typedef const int *iptr;
+  iptr p = 0;
+  ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+     "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+  struct s { int j; const int *ap[3]; };
+  struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+  const int foo = 10;
+}
+
+; return 0; }
+EOF
+if eval $ac_compile; then
+  rm -rf conftest*
+  ac_cv_c_const=yes
+else
+  rm -rf conftest*
+  ac_cv_c_const=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+  cat >> confdefs.h <<\EOF
+#define const 
+EOF
+
+fi
+
+# If we cannot run a trivial program, we must be cross compiling.
+echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6
+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 1221 "configure"
+#include "confdefs.h"
+main(){return(0);}
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+  ac_cv_c_cross=no
+else
+  ac_cv_c_cross=yes
+fi
+fi
+rm -fr conftest*
+fi
+cross_compiling=$ac_cv_c_cross
+echo "$ac_t""$ac_cv_c_cross" 1>&6
+
+echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
+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 1242 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+EOF
+eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+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
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+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 1264 "configure"
+#include "confdefs.h"
+#include <string.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "memchr" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+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 1282 "configure"
+#include "confdefs.h"
+#include <stdlib.h>
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "free" >/dev/null 2>&1; then
+  :
+else
+  rm -rf conftest*
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+if test "$cross_compiling" = yes; then
+  ac_cv_header_stdc=no
+else
+cat > conftest.$ac_ext <<EOF
+#line 1303 "configure"
+#include "confdefs.h"
+#include <ctype.h>
+#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int main () { int i; for (i = 0; i < 256; i++)
+if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
+exit (0); }
+
+EOF
+eval $ac_link
+if test -s conftest && (./conftest; exit) 2>/dev/null; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+fi
+rm -fr conftest*
+fi
+fi
+echo "$ac_t""$ac_cv_header_stdc" 1>&6
+if test $ac_cv_header_stdc = yes; then
+  cat >> confdefs.h <<\EOF
+#define STDC_HEADERS 1
+EOF
+
+fi
+
+echo $ac_n "checking for size_t""... $ac_c" 1>&6
+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 1337 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#endif
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "size_t" >/dev/null 2>&1; then
+  rm -rf conftest*
+  ac_cv_type_size_t=yes
+else
+  rm -rf conftest*
+  ac_cv_type_size_t=no
+fi
+rm -f conftest*
+
+fi
+echo "$ac_t""$ac_cv_type_size_t" 1>&6
+if test $ac_cv_type_size_t = no; then
+  cat >> confdefs.h <<\EOF
+#define size_t unsigned
+EOF
+
+fi
+
+
+if test -z "${top_srcdir}"; then
+TOP_SRCDIR="."
+else
+TOP_SRCDIR="${top_srcdir}"
+fi
+echo $ac_n "checking for language in autoconf.h""... $ac_c" 1>&6
+if test -f ${TOP_SRCDIR}/autoconf.h; then
+LANG=`tr ' ' '\n' < ${TOP_SRCDIR}/autoconf.h | grep '\-ALANG' | head -1`
+if test -n "${LANG}"; then
+echo "$ac_t""`echo "${LANG}" | cut -b9-10`" 1>&6
+fi
+fi
+if test -z "${LANG}"; then
+echo "$ac_t""no" 1>&6
+fi
+
+
+if test -z "${LANG}"; then
+echo $ac_n "checking for language through domainname""... $ac_c" 1>&6
+DNAME=`domainname`
+if test `echo "${DNAME}" | grep -c "\.no"` -ne 0; then
+LANG="-ALANG\(No\)"
+echo "$ac_t""No" 1>&6
+fi
+if test `echo "${DNAME}" | grep -c "\.de"` -ne 0; then
+LANG="-ALANG\(De\)"
+echo "$ac_t""De" 1>&6
+fi
+if test `echo "${DNAME}" | grep -c "\.uk"` -ne 0; then
+LANG="-ALANG\(En\)"
+echo "$ac_t""En" 1>&6
+fi
+if test `echo "${DNAME}" | grep -c "\.com"` -ne 0; then
+LANG="-ALANG\(En\)"
+echo "$ac_t""En" 1>&6
+fi
+if test `echo "${DNAME}" | grep -c "\.edu"` -ne 0; then
+LANG="-ALANG\(En\)"
+echo "$ac_t""En" 1>&6
+fi
+if test `echo "${DNAME}" | grep -c "\.gov"` -ne 0; then
+LANG="-ALANG\(En\)"
+echo "$ac_t""En" 1>&6
+fi
+if test -z "${LANG}"; then
+echo "$ac_t""no" 1>&6
+fi
+fi
+
+if test -z "${LANG}"; then
+echo $ac_n "checking for linux""... $ac_c" 1>&6
+cat > conftest.$ac_ext <<EOF
+#line 1416 "configure"
+#include "confdefs.h"
+#ifdef linux
+   yes
+#endif
+
+EOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  egrep "yes" >/dev/null 2>&1; then
+  rm -rf conftest*
+  echo "$ac_t""yes" 1>&6
+echo $ac_n "checking for language by examining keymap""... $ac_c" 1>&6
+if test `dumpkeys | grep "keycode *26" | tr ' ' '\n' | grep -c udiaeresis` -ne 0; then
+echo "$ac_t""De" 1>&6
+LANG='-ALANG\(De\)'
+else
+echo "$ac_t""no" 1>&6
+LANG='-ALANG\(En\)'
+fi
+
+else
+  rm -rf conftest*
+  echo "$ac_t""no" 1>&6
+LANG='-ALANG\(En\)'
+
+fi
+rm -f conftest*
+
+fi
+
+echo $ac_n "checking for wine.ini in autoconf.h""... $ac_c" 1>&6
+if test -f ${TOP_SRCDIR}/autoconf.h; then
+if test `grep -c WINE_INI_GLOBAL ${TOP_SRCDIR}/autoconf.h` -ne 0; then
+WINE_INI_GLOBAL=`grep WINE_INI_GLOBAL ${TOP_SRCDIR}/autoconf.h | tr ' ' '\n' | tail -1`
+echo "$ac_t""${WINE_INI_GLOBAL}" 1>&6
+fi
+fi
+if test -z "${WINE_INI_GLOBAL}"; then
+echo "$ac_t""no" 1>&6
+fi
+
+if test -z "${WINE_INI_GLOBAL}"; then
+echo $ac_n "checking for /usr/local/etc/wine.conf""... $ac_c" 1>&6
+if test -f /usr/local/etc/wine.conf; then
+echo "$ac_t""yes" 1>&6
+WINE_INI_GLOBAL='"/usr/local/etc/wine.conf"'
+else
+echo "$ac_t""no" 1>&6
+WINE_INI_GLOBAL="\"${TOP_SRCDIR}/wine.ini\""
+fi
+fi
+
+
+
+test -z "$LDFLAGS" && LDFLAGS=-g 
+
+
+trap '' 1 2 15
+cat > confcache <<\EOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs.  It is not useful on other systems.
+# If it contains results you don't want to keep, you may remove or edit it.
+#
+# By default, configure uses ./config.cache as the cache file,
+# creating it if it does not exist already.  You can give configure
+# the --cache-file=FILE option to use a different cache file; that is
+# what configure does when it calls configure scripts in
+# subdirectories, so they share the cache.
+# Giving --cache-file=/dev/null disables caching, for debugging configure.
+# config.status only pays attention to the cache file if you give it the
+# --recheck option to rerun configure.
+#
+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.
+(set) 2>&1 |
+  sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \
+  >> confcache
+if cmp -s $cache_file confcache; then
+  :
+else
+  if test -w $cache_file; then
+    echo "updating cache $cache_file"
+    cat confcache > $cache_file
+  else
+    echo "not updating unwritable cache $cache_file"
+  fi
+fi
+rm -f confcache
+
+trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Any assignment to VPATH causes Sun make to only execute
+# the first set of double-colon rules, so remove it if not needed.
+# If there is a colon in the path, we need to keep it.
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[ 	]*VPATH[ 	]*=[^:]*$/d'
+fi
+
+trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
+
+DEFS=-DHAVE_CONFIG_H
+
+# Without the "./", some shells look in PATH for config.status.
+: ${CONFIG_STATUS=./config.status}
+
+echo creating $CONFIG_STATUS
+rm -f $CONFIG_STATUS
+cat > $CONFIG_STATUS <<EOF
+#! /bin/sh
+# Generated automatically by configure.
+# Run this file to recreate the current configuration.
+# This directory was configured as follows,
+# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+#
+# $0 $ac_configure_args
+#
+# Compiler output produced by configure, useful for debugging
+# configure, is in ./config.log if it exists.
+
+ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
+for ac_option
+do
+  case "\$ac_option" in
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    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.4"
+    exit 0 ;;
+  -help | --help | --hel | --he | --h)
+    echo "\$ac_cs_usage"; exit 0 ;;
+  *) echo "\$ac_cs_usage"; exit 1 ;;
+  esac
+done
+
+ac_given_srcdir=$srcdir
+
+trap 'rm -fr `echo "controls/Makefile ipc/Makefile loader/Makefile memory/Makefile misc/Makefile miscemu/Makefile multimedia/Makefile objects/Makefile windows/Makefile rc/Makefile debugger/Makefile debugger/readline/Makefile tools/Makefile if1632/Makefile Makefile autoconf.h include/config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
+
+# Protect against being on the right side of a sed subst in config.status. 
+sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\\\&%]/\\\\&/g; 
+ s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF
+$ac_vpsub
+$extrasub
+s%@CFLAGS@%$CFLAGS%g
+s%@CPPFLAGS@%$CPPFLAGS%g
+s%@CXXFLAGS@%$CXXFLAGS%g
+s%@DEFS@%$DEFS%g
+s%@LDFLAGS@%$LDFLAGS%g
+s%@LIBS@%$LIBS%g
+s%@exec_prefix@%$exec_prefix%g
+s%@prefix@%$prefix%g
+s%@program_transform_name@%$program_transform_name%g
+s%@SET_MAKE@%$SET_MAKE%g
+s%@CC@%$CC%g
+s%@CPP@%$CPP%g
+s%@YACC@%$YACC%g
+s%@LEX@%$LEX%g
+s%@LEXLIB@%$LEXLIB%g
+s%@AXFILES@%$AXFILES%g
+s%@x_includes@%$x_includes%g
+s%@x_libraries@%$x_libraries%g
+s%@LIBOBJS@%$LIBOBJS%g
+s%@LD@%$LD%g
+s%@LDCOMBINEFLAGS@%$LDCOMBINEFLAGS%g
+s%@LANG@%$LANG%g
+s%@WINE_INI_GLOBAL@%$WINE_INI_GLOBAL%g
+
+CEOF
+EOF
+cat >> $CONFIG_STATUS <<EOF
+
+CONFIG_FILES=\${CONFIG_FILES-"controls/Makefile ipc/Makefile loader/Makefile memory/Makefile misc/Makefile miscemu/Makefile multimedia/Makefile objects/Makefile windows/Makefile rc/Makefile debugger/Makefile debugger/readline/Makefile tools/Makefile if1632/Makefile Makefile autoconf.h"}
+EOF
+cat >> $CONFIG_STATUS <<\EOF
+for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
+  # Support "outfile[:infile]", defaulting infile="outfile.in".
+  case "$ac_file" in
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  # Adjust relative srcdir, etc. for subdirectories.
+
+  # Remove last slash and all that follows it.  Not all systems have dirname.
+  ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
+  if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
+    # The file is in a subdirectory.
+    test ! -d "$ac_dir" && mkdir "$ac_dir"
+    ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
+    # A "../" for each directory in $ac_dir_suffix.
+    ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
+  else
+    ac_dir_suffix= ac_dots=
+  fi
+
+  case "$ac_given_srcdir" in
+  .)  srcdir=.
+      if test -z "$ac_dots"; then top_srcdir=.
+      else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
+  /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
+  *) # Relative path.
+    srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
+    top_srcdir="$ac_dots$ac_given_srcdir" ;;
+  esac
+
+  echo creating "$ac_file"
+  rm -f "$ac_file"
+  configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
+  case "$ac_file" in
+  *Makefile*) ac_comsub="1i\\
+# $configure_input" ;;
+  *) ac_comsub= ;;
+  esac
+  sed -e "$ac_comsub
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
+" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file
+fi; done
+rm -f conftest.subs
+
+# 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.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s%^\([ 	]*\)#\([ 	]*define[ 	][ 	]*\)'
+ac_dB='\([ 	][ 	]*\)[^ 	]*%\1#\2'
+ac_dC='\3'
+ac_dD='%g'
+# ac_u turns "#undef NAME" with trailing blanks into "#define NAME VALUE".
+ac_uA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
+ac_uB='\([ 	]\)%\1#\2define\3'
+ac_uC=' '
+ac_uD='\4%g'
+# ac_e turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_eA='s%^\([ 	]*\)#\([ 	]*\)undef\([ 	][ 	]*\)'
+ac_eB='$%\1#\2define\3'
+ac_eC=' '
+ac_eD='%g'
+
+CONFIG_HEADERS=${CONFIG_HEADERS-"include/config.h"}
+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
+  *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'`
+       ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
+  *) ac_file_in="${ac_file}.in" ;;
+  esac
+
+  echo creating $ac_file
+
+  rm -f conftest.frag conftest.in conftest.out
+  cp $ac_given_srcdir/$ac_file_in conftest.in
+
+EOF
+
+# Transform confdefs.h into a sed script conftest.vals that substitutes
+# the proper values into config.h.in to produce config.h.  And first:
+# Protect against being on the right side of a sed subst in config.status. 
+# Protect against being in an unquoted here document in config.status.
+rm -f conftest.vals
+cat > conftest.hdr <<\EOF
+s/[\\&%]/\\&/g
+s%[\\$`]%\\&%g
+s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp
+s%ac_d%ac_u%gp
+s%ac_u%ac_e%gp
+EOF
+sed -n -f conftest.hdr confdefs.h > conftest.vals
+rm -f conftest.hdr
+
+# This sed command replaces #undef with comments.  This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >> conftest.vals <<\EOF
+s%^[ 	]*#[ 	]*undef[ 	][ 	]*[a-zA-Z_][a-zA-Z_0-9]*%/* & */%
+EOF
+
+# 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 :
+do
+  ac_lines=`grep -c . conftest.vals`
+  # grep -c gives empty output for an empty file on some AIX systems.
+  if test -z "$ac_lines" || test "$ac_lines" -eq 0; then break; fi
+  # Write a limited-size here document to conftest.frag.
+  echo '  cat > conftest.frag <<CEOF' >> $CONFIG_STATUS
+  sed ${ac_max_here_lines}q conftest.vals >> $CONFIG_STATUS
+  echo 'CEOF
+  sed -f conftest.frag conftest.in > conftest.out
+  rm -f conftest.in
+  mv conftest.out conftest.in
+' >> $CONFIG_STATUS
+  sed 1,${ac_max_here_lines}d conftest.vals > conftest.tail
+  rm -f conftest.vals
+  mv conftest.tail conftest.vals
+done
+rm -f conftest.vals
+
+cat >> $CONFIG_STATUS <<\EOF
+  rm -f conftest.frag conftest.h
+  echo "/* $ac_file.  Generated automatically by configure.  */" > conftest.h
+  cat conftest.in >> conftest.h
+  rm -f conftest.in
+  if cmp -s $ac_file conftest.h 2>/dev/null; then
+    echo "$ac_file is unchanged"
+    rm -f conftest.h
+  else
+    rm -f $ac_file
+    mv conftest.h $ac_file
+  fi
+fi; done
+
+
+touch stamp-config
+exit 0
+EOF
+chmod +x $CONFIG_STATUS
+rm -fr confdefs* $ac_clean_files
+test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
+
+
+echo
+echo "Configure finished.  Do 'make depend; make' to compile Wine."
+echo
+
diff --git a/configure.in b/configure.in
new file mode 100644
index 0000000..9912fa9
--- /dev/null
+++ b/configure.in
@@ -0,0 +1,148 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl Author: Michael Patra   <micky@marie.physik.tu-berlin.de>
+dnl                         <patra@itp1.physik.tu-berlin.de>
+AC_REVISION([configure.in 1.00])
+AC_INIT(controls/edit.c)		
+AC_CONFIG_HEADER(include/config.h)
+
+# We want these before the checks, so the checks can modify their values.
+test -z "$CFLAGS" && CFLAGS="-g -O2 -Wall" AC_SUBST(CFLAGS)
+test -z "$LDFLAGS" && LDFLAGS=-g AC_SUBST(LDFLAGS)
+
+AC_PROG_MAKE_SET
+AC_PROG_CC
+AC_PATH_X
+AC_PROG_YACC
+AC_PROG_LEX
+if test -n "$x_includes" ; then
+  x_includes="-I$x_includes"
+fi
+if test -n "$x_no" ; then
+  AXFILES='AXFILES='
+fi
+AC_SUBST(AXFILES)
+AC_SUBST(x_includes)
+AC_SUBST(x_libraries)
+AC_SUBST(LIBOBJS)
+
+LD=ld
+LDCOMBINEFLAGS="-r"
+AC_SUBST(LD)
+AC_SUBST(LDCOMBINEFLAGS)
+
+AC_CHECK_FUNCS(tcgetattr)
+AC_CHECK_HEADERS(stdlib.h)
+AC_HEADER_DIRENT()
+AC_HEADER_STAT()
+AC_C_CONST()
+AC_TYPE_SIZE_T()
+
+if test -z "${top_srcdir}"; then
+TOP_SRCDIR="."
+else
+TOP_SRCDIR="${top_srcdir}"
+fi
+AC_MSG_CHECKING(for language in autoconf.h)
+if test -f ${TOP_SRCDIR}/autoconf.h; then
+LANG=`tr ' ' '\n' < ${TOP_SRCDIR}/autoconf.h | grep '\-ALANG' | head -1`
+if test -n "${LANG}"; then
+AC_MSG_RESULT(`echo "${LANG}" | cut -b9-10`)
+fi
+fi
+if test -z "${LANG}"; then
+AC_MSG_RESULT(no)
+fi
+AC_SUBST(LANG)
+
+if test -z "${LANG}"; then
+AC_MSG_CHECKING(for language through domainname)
+DNAME=`domainname`
+if test `echo "${DNAME}" | grep -c "\.no"` -ne 0; then
+LANG="-ALANG\(No\)"
+AC_MSG_RESULT(No)
+fi
+if test `echo "${DNAME}" | grep -c "\.de"` -ne 0; then
+LANG="-ALANG\(De\)"
+AC_MSG_RESULT(De)
+fi
+if test `echo "${DNAME}" | grep -c "\.uk"` -ne 0; then
+LANG="-ALANG\(En\)"
+AC_MSG_RESULT(En)
+fi
+if test `echo "${DNAME}" | grep -c "\.com"` -ne 0; then
+LANG="-ALANG\(En\)"
+AC_MSG_RESULT(En)
+fi
+if test `echo "${DNAME}" | grep -c "\.edu"` -ne 0; then
+LANG="-ALANG\(En\)"
+AC_MSG_RESULT(En)
+fi
+if test `echo "${DNAME}" | grep -c "\.gov"` -ne 0; then
+LANG="-ALANG\(En\)"
+AC_MSG_RESULT(En)
+fi
+if test -z "${LANG}"; then
+AC_MSG_RESULT(no)
+fi
+fi
+
+if test -z "${LANG}"; then
+AC_MSG_CHECKING(for linux)
+AC_EGREP_CPP(yes,
+[#ifdef linux
+   yes
+#endif
+], AC_MSG_RESULT(yes)
+AC_MSG_CHECKING(for language by examining keymap)
+if test `dumpkeys | grep "keycode *26" | tr ' ' '\n' | grep -c udiaeresis` -ne 0; then
+AC_MSG_RESULT(De)
+LANG='-ALANG\(De\)'
+else
+AC_MSG_RESULT(no)
+LANG='-ALANG\(En\)'
+fi
+,
+AC_MSG_RESULT(no)
+LANG='-ALANG\(En\)'
+)
+fi
+
+AC_MSG_CHECKING(for wine.ini in autoconf.h)
+if test -f ${TOP_SRCDIR}/autoconf.h; then
+if test `grep -c WINE_INI_GLOBAL ${TOP_SRCDIR}/autoconf.h` -ne 0; then
+WINE_INI_GLOBAL=`grep WINE_INI_GLOBAL ${TOP_SRCDIR}/autoconf.h | tr ' ' '\n' | tail -1`
+AC_MSG_RESULT(${WINE_INI_GLOBAL})
+fi
+fi
+if test -z "${WINE_INI_GLOBAL}"; then
+AC_MSG_RESULT(no)
+fi
+
+if test -z "${WINE_INI_GLOBAL}"; then
+AC_MSG_CHECKING(for /usr/local/etc/wine.conf)
+if test -f /usr/local/etc/wine.conf; then
+AC_MSG_RESULT(yes)
+WINE_INI_GLOBAL='"/usr/local/etc/wine.conf"'
+else
+AC_MSG_RESULT(no)
+WINE_INI_GLOBAL="\"${TOP_SRCDIR}/wine.ini\""
+fi
+fi
+AC_SUBST(WINE_INI_GLOBAL)
+
+
+test -z "$LDFLAGS" && LDFLAGS=-g AC_SUBST(LDFLAGS)
+
+
+AC_OUTPUT(controls/Makefile ipc/Makefile loader/Makefile memory/Makefile misc/Makefile miscemu/Makefile multimedia/Makefile objects/Makefile windows/Makefile rc/Makefile debugger/Makefile debugger/readline/Makefile tools/Makefile if1632/Makefile Makefile autoconf.h, [touch stamp-config])
+
+echo
+echo "Configure finished.  Do 'make depend; make' to compile Wine."
+echo
+
+dnl Local Variables:
+dnl comment-start: "dnl "
+dnl comment-end: ""
+dnl comment-start-skip: "\\bdnl\\b\\s *"
+dnl compile-command: "make configure config.h.in"
+dnl End:
diff --git a/controls/Makefile.in b/controls/Makefile.in
new file mode 100644
index 0000000..5bdd7a9
--- /dev/null
+++ b/controls/Makefile.in
@@ -0,0 +1,49 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include
+LD      = @LD@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+
+MODULE 	= controls
+
+SRCS 	= button.c combo.c desktop.c edit.c listbox.c menu.c scroll.c \
+	static.c widgets.c
+
+OBJS = $(SRCS:.c=.o)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
+
+all: $(MODULE).o
+
+$(MODULE).o: $(OBJS)
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dummy:
+
+### Dependencies:
diff --git a/controls/listbox.c b/controls/listbox.c
index d1fc9ac..1a081f0 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -601,14 +601,12 @@
     }
     strcpy(temp,filespec);
     tstr = strrchr(temp, '\\');
-    if (tstr == NULL)
-      DOS_SetDefaultDrive( drive );
-    else {
-      *tstr = 0;
-      filespec = tstr + 1;
+    if (tstr != NULL) {
+      *(tstr+1) = 0;
+      filespec += tstr - temp + 1;
       if (!DOS_ChangeDir( drive, temp )) return 0;
-      DOS_SetDefaultDrive( drive );
     }
+    DOS_SetDefaultDrive( drive );
     dprintf_listbox(stddeb,"Changing directory to %c:%s, filemask is %s\n",
 		    drive+'A', temp, filespec);
   }
diff --git a/controls/menu.c b/controls/menu.c
index 6cea09d..d838e49 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -1660,15 +1660,17 @@
     HANDLE hNewItems;
     MENUITEM *lpitem, *newItems;
     LPPOPUPMENU	menu;
-    
+
     if (IS_STRING_ITEM(wFlags))
-	{
-	   dprintf_menu(stddeb,"InsertMenu (%04X, %04X, %04X, %04X, '%s') !\n",
-				 hMenu, nPos, wFlags, wItemID, lpNewItem);
-	}
+    {
+        dprintf_menu(stddeb,"InsertMenu (%04X, %04X, %04X, %04X, '%s') !\n",
+                     hMenu, nPos, wFlags, wItemID,
+                     lpNewItem ? lpNewItem : "(null)");
+        if (!lpNewItem) return FALSE;
+    }
     else
-	   dprintf_menu(stddeb,"InsertMenu (%04X, %04X, %04X, %04X, %p) !\n",
-		                  hMenu, nPos, wFlags, wItemID, lpNewItem);
+        dprintf_menu(stddeb,"InsertMenu (%04X, %04X, %04X, %04X, %p) !\n",
+                     hMenu, nPos, wFlags, wItemID, lpNewItem);
 
       /* Find where to insert new item */
 
@@ -1816,8 +1818,11 @@
 {
     LPMENUITEM 	lpitem;
     if (IS_STRING_ITEM(wFlags))
+    {
 	dprintf_menu(stddeb,"ModifyMenu (%04X, %04X, %04X, %04X, '%s') !\n",
-	       hMenu, nPos, wFlags, wItemID, lpNewItem);
+	       hMenu, nPos, wFlags, wItemID, lpNewItem ? lpNewItem : "(null)");
+        if (!lpNewItem) return FALSE;
+    }
     else
 	dprintf_menu(stddeb,"ModifyMenu (%04X, %04X, %04X, %04X, %p) !\n",
 	       hMenu, nPos, wFlags, wItemID, lpNewItem);
diff --git a/debugger/Makefile.in b/debugger/Makefile.in
new file mode 100644
index 0000000..39cada3
--- /dev/null
+++ b/debugger/Makefile.in
@@ -0,0 +1,68 @@
+CC	= @CC@
+CFLAGS	= @CFLAGS@
+TOPSRC	= @top_srcdir@
+DIVINCL	= -I$(TOPSRC)/include
+BISON	= @YACC@
+FLEX	= @LEX@
+DIVDEFS	= -DUSE_READLINE
+COMPILE	= $(CC) $(CFLAGS) $(DIVINCL) $(DIVDEFS)
+LD	= @LD@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+@SET_MAKE@
+
+
+MODULE	= debugger
+
+SRCS	= break.c db_disasm.c hash.c info.c registers.c stack.c
+
+OBJS = $(SRCS:.c=.o) dbg.tab.o lex.yy.o
+
+all: $(MODULE).o dbg.tab.o lex.yy.o
+
+dbg.tab.c: dbg.y
+	$(BISON) -b dbg -d dbg.y
+
+dbg.tab.h: dbg.y
+	$(BISON) -b dbg -d dbg.y
+
+lex.yy.c: debug.l dbg.tab.h dbg.tab.h
+	$(FLEX) -8 -I debug.l
+
+.c.o:
+	$(COMPILE) -c -o $*.o $<
+ 
+$(MODULE).o: $(OBJS)
+	(cd readline; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)')
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) readline/readline.o -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	(cd readline; $(MAKE) clean)
+	rm -f *.o \#*\# *~ dbg.tab.c dbg.tab.h lex.yy.c y.tab.c y.tab.h tmp_make
+
+distclean: clean
+	(cd readline; $(MAKE) distclean)
+	rm Makefile
+
+countryclean:
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dbg.tab.o: dbg.tab.c
+lex.yy.o: lex.yy.c
+ 
+dummy:
+
+### Dependencies:
diff --git a/debugger/dbg.y b/debugger/dbg.y
index c9a5585..7d0022f 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -72,7 +72,8 @@
 	| MODE NUM '\n'         { mode_command($2); }
 	| ENABLE NUM '\n'       { DEBUG_EnableBreakpoint( $2, TRUE ); }
 	| DISABLE NUM '\n'      { DEBUG_EnableBreakpoint( $2, FALSE ); }
-	| BREAK '*' expr        { DEBUG_AddBreakpoint( 0xffffffff, $3 ); }
+	| BREAK '*' expr '\n'       { DEBUG_AddBreakpoint( 0xffffffff, $3 ); }
+	| BREAK '*' expr ':' expr '\n'	{ DEBUG_AddBreakpoint( $3, $5); }
         | BREAK '\n'            { DEBUG_AddBreakpoint( 0xffffffff, EIP ); }
         | DELETE BREAK NUM '\n' { DEBUG_DelBreakpoint( $3 ); }
 	| BACKTRACE '\n'        { DEBUG_BackTrace(); }
@@ -90,6 +91,9 @@
 	  EXAM expr  '\n' { examine_memory( 0xffffffff, $2, 1, 'x'); }
 	| EXAM FORMAT expr  '\n' { examine_memory( 0xffffffff, $3,
                                                   $2 >> 8, $2 & 0xff ); }
+	| EXAM expr ':' expr '\n' { examine_memory( $2, $4, 1, 'x' ); }
+	| EXAM FORMAT expr ':' expr'\n'  { examine_memory( $3, $5, 
+	                                              $2 >> 8,  $2 & 0xff ); }
 
  print_command:
 	  PRINT expr '\n' { examine_memory( 0, ((unsigned int) &$2 ), 1,'x'); }
diff --git a/debugger/debug.l b/debugger/debug.l
index 4b8ccf1..862c1f8 100644
--- a/debugger/debug.l
+++ b/debugger/debug.l
@@ -37,7 +37,7 @@
 
 \n		{ syntax_error = 0; return '\n'; } /*Indicate end of command*/
 
-[-+=()*]        { return *yytext; }
+[-+=()*:]       { return *yytext; }
 
 "0x"{HEXDIGIT}+      { sscanf(yytext, "%x", &yylval); return NUM; }
 {DIGIT}+             { sscanf(yytext, "%d", &yylval); return NUM; }
diff --git a/debugger/info.c b/debugger/info.c
index 65f8bbd..109161d 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -10,11 +10,6 @@
 
 extern char * find_nearest_symbol( unsigned int seg, unsigned int addr );
 
-void application_not_running()
-{
-  fprintf(stderr,"Application not running\n");
-}
-
 void print_address( unsigned int segment, unsigned int addr, int addrlen )
 {
     char *name = find_nearest_symbol( segment, addr );
diff --git a/debugger/readline/Imakefile b/debugger/readline/Imakefile
index aebd03a..6678bcb 100644
--- a/debugger/readline/Imakefile
+++ b/debugger/readline/Imakefile
@@ -2,12 +2,9 @@
 
 MODULE = readline
 
-YACC = yacc -b dbg -d
-
-EXTRA_DEFINES= -DANSI_ARROWS -DHAVE_TCGETATTR -DHIDE -DUSE_DIRENT -DSYS_UNIX
+EXTRA_DEFINES= -DANSI_ARROWS -DHAVE_TCGETATTR -DHIDE
 
 SRCS = \
-	complete.c \
 	editline.c \
 	sysunix.c
 
diff --git a/debugger/readline/Makefile.in b/debugger/readline/Makefile.in
new file mode 100644
index 0000000..9f2023e
--- /dev/null
+++ b/debugger/readline/Makefile.in
@@ -0,0 +1,50 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include
+LD	= @LD@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+DIVDEFS	= -DHIDE -DANSI_ARROWS
+
+
+MODULE 	= readline
+
+SRCS 	= editline.c sysunix.c
+
+OBJS = $(SRCS:.c=.o)
+
+.c.o:
+	$(CC) -c $(DIVDEFS) $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
+
+all: $(MODULE).o
+
+$(MODULE).o: $(OBJS)
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dummy:
+
+### Dependencies:
diff --git a/debugger/readline/complete.c b/debugger/readline/complete.c
deleted file mode 100644
index c5cbaaa..0000000
--- a/debugger/readline/complete.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*  $Revision: 1.3 $
-**
-**  History and file completion functions for editline library.
-*/
-#include <stdlib.h>
-#include "editline.h"
-
-#if	defined(NEED_STRDUP)
-/*
-**  Return an allocated copy of a string.
-*/
-char *
-strdup(p)
-    char	*p;
-{
-    char	*new;
-
-    if ((new = NEW(char, strlen(p) + 1)) != NULL)
-	(void)strcpy(new, p);
-    return new;
-}
-#endif	/* defined(NEED_STRDUP) */
-
-/*
-**  strcmp-like sorting predicate for qsort.
-*/
-STATIC int
-compare(p1, p2)
-    CONST void	*p1;
-    CONST void	*p2;
-{
-    CONST char	**v1;
-    CONST char	**v2;
-
-    v1 = (CONST char **)p1;
-    v2 = (CONST char **)p2;
-    return strcmp(*v1, *v2);
-}
-
-/*
-**  Fill in *avp with an array of names that match file, up to its length.
-**  Ignore . and .. .
-*/
-STATIC int
-FindMatches(dir, file, avp)
-    char	*dir;
-    char	*file;
-    char	***avp;
-{
-    char	**av;
-    char	**new;
-    char	*p;
-    DIR		*dp;
-    DIRENTRY	*ep;
-    SIZE_T	ac;
-    SIZE_T	len;
-
-    if ((dp = opendir(dir)) == NULL)
-	return 0;
-
-    av = NULL;
-    ac = 0;
-    len = strlen(file);
-    while ((ep = readdir(dp)) != NULL) {
-	p = ep->d_name;
-	if (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')))
-	    continue;
-	if (len && strncmp(p, file, len) != 0)
-	    continue;
-
-	if ((ac % MEM_INC) == 0) {
-	    if ((new = NEW(char*, ac + MEM_INC)) == NULL)
-		break;
-	    if (ac) {
-		COPYFROMTO(new, av, ac * sizeof (char **));
-		DISPOSE(av);
-	    }
-	    *avp = av = new;
-	}
-
-	if ((av[ac] = strdup(p)) == NULL) {
-	    if (ac == 0)
-		DISPOSE(av);
-	    break;
-	}
-	ac++;
-    }
-
-    /* Clean up and return. */
-    (void)closedir(dp);
-    if (ac)
-	qsort(av, ac, sizeof (char **), compare);
-    return ac;
-}
-
-/*
-**  Split a pathname into allocated directory and trailing filename parts.
-*/
-STATIC int
-SplitPath(path, dirpart, filepart)
-    char	*path;
-    char	**dirpart;
-    char	**filepart;
-{
-    static char	DOT[] = ".";
-    char	*dpart;
-    char	*fpart;
-
-    if ((fpart = strrchr(path, '/')) == NULL) {
-	if ((dpart = strdup(DOT)) == NULL)
-	    return -1;
-	if ((fpart = strdup(path)) == NULL) {
-	    DISPOSE(dpart);
-	    return -1;
-	}
-    }
-    else {
-	if ((dpart = strdup(path)) == NULL)
-	    return -1;
-	dpart[fpart - path] = '\0';
-	if ((fpart = strdup(++fpart)) == NULL) {
-	    DISPOSE(dpart);
-	    return -1;
-	}
-    }
-    *dirpart = dpart;
-    *filepart = fpart;
-    return 0;
-}
-
-/*
-**  Attempt to complete the pathname, returning an allocated copy.
-**  Fill in *unique if we completed it, or set it to 0 if ambiguous.
-*/
-char *
-rl_complete(pathname, unique)
-    char	*pathname;
-    int		*unique;
-{
-    char	**av;
-    char	*dir;
-    char	*file;
-    char	*new;
-    char	*p;
-    SIZE_T	ac;
-    SIZE_T	end;
-    SIZE_T	i;
-    SIZE_T	j;
-    SIZE_T	len;
-
-    if (SplitPath(pathname, &dir, &file) < 0)
-	return NULL;
-    if ((ac = FindMatches(dir, file, &av)) == 0) {
-	DISPOSE(dir);
-	DISPOSE(file);
-	return NULL;
-    }
-
-    p = NULL;
-    len = strlen(file);
-    if (ac == 1) {
-	/* Exactly one match -- finish it off. */
-	*unique = 1;
-	j = strlen(av[0]) - len + 2;
-	if ((p = NEW(char, j + 1)) != NULL) {
-	    COPYFROMTO(p, av[0] + len, j);
-	    if ((new = NEW(char, strlen(dir) + strlen(av[0]) + 2)) != NULL) {
-		(void)strcpy(new, dir);
-		(void)strcat(new, "/");
-		(void)strcat(new, av[0]);
-		rl_add_slash(new, p);
-		DISPOSE(new);
-	    }
-	}
-    }
-    else {
-	*unique = 0;
-	if (len) {
-	    /* Find largest matching substring. */
-	    for (i = len, end = strlen(av[0]); i < end; i++)
-		for (j = 1; j < ac; j++)
-		    if (av[0][i] != av[j][i])
-			goto breakout;
-  breakout:
-	    if (i > len) {
-		j = i - len + 1;
-		if ((p = NEW(char, j)) != NULL) {
-		    COPYFROMTO(p, av[0] + len, j);
-		    p[j - 1] = '\0';
-		}
-	    }
-	}
-    }
-
-    /* Clean up and return. */
-    DISPOSE(dir);
-    DISPOSE(file);
-    for (i = 0; i < ac; i++)
-	DISPOSE(av[i]);
-    DISPOSE(av);
-    return p;
-}
-
-/*
-**  Return all possible completions.
-*/
-int
-rl_list_possib(pathname, avp)
-    char	*pathname;
-    char	***avp;
-{
-    char	*dir;
-    char	*file;
-    int		ac;
-
-    if (SplitPath(pathname, &dir, &file) < 0)
-	return 0;
-    ac = FindMatches(dir, file, avp);
-    DISPOSE(dir);
-    DISPOSE(file);
-    return ac;
-}
diff --git a/debugger/readline/editline.c b/debugger/readline/editline.c
index cd20bbb..eea22d7 100644
--- a/debugger/readline/editline.c
+++ b/debugger/readline/editline.c
@@ -78,8 +78,8 @@
 STATIC int		Point;
 STATIC int		PushBack;
 STATIC int		Pushed;
-FORWARD KEYMAP		Map[33];
-FORWARD KEYMAP		MetaMap[16];
+STATIC KEYMAP		Map[33];
+STATIC KEYMAP		MetaMap[16];
 STATIC SIZE_T		Length;
 STATIC SIZE_T		ScreenCount;
 STATIC SIZE_T		ScreenSize;
@@ -243,41 +243,6 @@
 }
 
 
-/*
-**  Print an array of words in columns.
-*/
-STATIC void
-columns(ac, av)
-    int		ac;
-    CHAR	**av;
-{
-    CHAR	*p;
-    int		i;
-    int		j;
-    int		k;
-    int		len;
-    int		skip;
-    int		longest;
-    int		cols;
-
-    /* Find longest name, determine column count from that. */
-    for (longest = 0, i = 0; i < ac; i++)
-	if ((j = strlen((char *)av[i])) > longest)
-	    longest = j;
-    cols = TTYwidth / (longest + 3);
-
-    TTYputs((CHAR *)NEWLINE);
-    for (skip = ac / cols + 1, i = 0; i < skip; i++) {
-	for (j = i; j < ac; j += skip) {
-	    for (p = av[j], len = strlen((char *)p), k = len; --k >= 0; p++)
-		TTYput(*p);
-	    if (j + skip < ac)
-		while (++len < longest + 3)
-		    TTYput(' ');
-	}
-	TTYputs((CHAR *)NEWLINE);
-    }
-}
 
 STATIC void
 reposition()
@@ -1026,71 +991,6 @@
     return CSstay;
 }
 
-/*
-**  Move back to the beginning of the current word and return an
-**  allocated copy of it.
-*/
-STATIC CHAR *
-find_word()
-{
-    static char	SEPS[] = "#;&|^$=`'{}()<>\n\t ";
-    CHAR	*p;
-    CHAR	*new;
-    SIZE_T	len;
-
-    for (p = &Line[Point]; p > Line && strchr(SEPS, (char)p[-1]) == NULL; p--)
-	continue;
-    len = Point - (p - Line) + 1;
-    if ((new = NEW(CHAR, len)) == NULL)
-	return NULL;
-    COPYFROMTO(new, p, len);
-    new[len - 1] = '\0';
-    return new;
-}
-
-STATIC STATUS
-c_complete()
-{
-    CHAR	*p;
-    CHAR	*word;
-    int		unique;
-    STATUS	s;
-
-    word = find_word();
-    p = (CHAR *)rl_complete((char *)word, &unique);
-    if (word)
-	DISPOSE(word);
-    if (p && *p) {
-	s = insert_string(p);
-	if (!unique)
-	    (void)ring_bell();
-	DISPOSE(p);
-	return s;
-    }
-    return ring_bell();
-}
-
-STATIC STATUS
-c_possible()
-{
-    CHAR	**av;
-    CHAR	*word;
-    int		ac;
-
-    word = find_word();
-    ac = rl_list_possib((char *)word, (char ***)&av);
-    if (word)
-	DISPOSE(word);
-    if (ac) {
-	columns(ac, av);
-	while (--ac >= 0)
-	    DISPOSE(av[ac]);
-	DISPOSE(av);
-	return CSmove;
-    }
-    return ring_bell();
-}
-
 STATIC STATUS
 accept_line()
 {
@@ -1335,7 +1235,7 @@
     {	CTL('F'),	fd_char		},
     {	CTL('G'),	ring_bell	},
     {	CTL('H'),	bk_del_char	},
-    {	CTL('I'),	c_complete	},
+    {	CTL('I'),	ring_bell	},
     {	CTL('J'),	accept_line	},
     {	CTL('K'),	kill_line	},
     {	CTL('L'),	redisplay	},
@@ -1367,7 +1267,7 @@
     {	'.',		last_argument	},
     {	'<',		h_first		},
     {	'>',		h_last		},
-    {	'?',		c_possible	},
+    {	'?',		ring_bell	},
     {	'b',		bk_word		},
     {	'd',		fd_kill_word	},
     {	'f',		fd_word		},
diff --git a/debugger/readline/editline.h b/debugger/readline/editline.h
index 40a2025..fa16f3b 100644
--- a/debugger/readline/editline.h
+++ b/debugger/readline/editline.h
@@ -3,20 +3,17 @@
 **  Internal header file for editline library.
 */
 #include <stdio.h>
-#if	defined(HAVE_STDLIB)
 #include <stdlib.h>
 #include <string.h>
-#endif	/* defined(HAVE_STDLIB) */
-#if	defined(SYS_UNIX)
-#include "unix.h"
-#endif	/* defined(SYS_UNIX) */
-#if	defined(SYS_OS9)
-#include "os9.h"
-#endif	/* defined(SYS_OS9) */
+#include <sys/types.h>
+#include <sys/stat.h>
 
-#if	!defined(SIZE_T)
-#define SIZE_T	unsigned int
-#endif	/* !defined(SIZE_T) */
+
+#define CRLF   "\r\n"
+
+
+#define SIZE_T	size_t
+#define CONST	const
 
 typedef unsigned char	CHAR;
 
@@ -26,15 +23,6 @@
 #define STATIC	/* NULL */
 #endif	/* !defined(HIDE) */
 
-#if	!defined(CONST)
-#if	defined(__STDC__)
-#define CONST	const
-#else
-#define CONST
-#endif	/* defined(__STDC__) */
-#endif	/* !defined(CONST) */
-
-
 #define MEM_INC		64
 #define SCREEN_INC	256
 
@@ -59,18 +47,3 @@
 extern int	rl_list_possib();
 extern void	rl_ttyset();
 extern void	rl_add_slash();
-
-#if	!defined(HAVE_STDLIB)
-extern char	*getenv();
-extern char	*malloc();
-extern char	*realloc();
-extern char	*memcpy();
-extern char	*strcat();
-extern char	*strchr();
-extern char	*strrchr();
-extern char	*strcpy();
-extern char	*strdup();
-extern int	strcmp();
-extern int	strlen();
-extern int	strncmp();
-#endif	/* !defined(HAVE_STDLIB) */
diff --git a/debugger/readline/sysunix.c b/debugger/readline/sysunix.c
index 010744e1..e2b72e1 100644
--- a/debugger/readline/sysunix.c
+++ b/debugger/readline/sysunix.c
@@ -3,6 +3,7 @@
 **  Unix system-dependant routines for editline library.
 */
 #include "editline.h"
+#include "config.h"
 
 #if	defined(HAVE_TCGETATTR)
 #include <termios.h>
diff --git a/debugger/readline/testit.c b/debugger/readline/testit.c
deleted file mode 100644
index e6384b8..0000000
--- a/debugger/readline/testit.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*  $Revision: 1.2 $
-**
-**  A "micro-shell" to test editline library.
-**  If given any arguments, commands aren't executed.
-*/
-#include <stdio.h>
-#if	defined(HAVE_STDLIB)
-#include <stdlib.h>
-#endif	/* defined(HAVE_STDLIB) */
-
-const char version_string[] = "4.321"; 
-
-
-extern char	*readline();
-extern void	add_history();
-
-#if	!defined(HAVE_STDLIB)
-extern int	chdir();
-extern int	free();
-extern int	strncmp();
-extern int	system();
-extern void	exit();
-#endif	/* !defined(HAVE_STDLIB) */
-
-
-#if	defined(NEED_PERROR)
-void
-perror(s)
-    char	*s;
-{
-    extern int	errno;
-
-    (voidf)printf(stderr, "%s: error %d\n", s, errno);
-}
-#endif	/* defined(NEED_PERROR) */
-
-
-/* ARGSUSED1 */
-int
-main(ac, av)
-    int		ac;
-    char	*av[];
-{
-    char	*p;
-    int		doit;
-
-    doit = ac == 1;
-    while ((p = readline("testit> ")) != NULL) {
-	(void)printf("\t\t\t|%s|\n", p);
-	if (doit)
-	    if (strncmp(p, "cd ", 3) == 0) {
-		if (chdir(&p[3]) < 0)
-		    perror(&p[3]);
-	    }
-	    else if (system(p) != 0)
-		perror(p);
-	add_history(p);
-	free(p);
-    }
-    exit(0);
-    /* NOTREACHED */
-}
diff --git a/debugger/readline/unix.h b/debugger/readline/unix.h
deleted file mode 100644
index fe6beed..0000000
--- a/debugger/readline/unix.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*  $Revision: 1.1 $
-**
-**  Editline system header file for Unix.
-*/
-
-#define CRLF		"\r\n"
-#define FORWARD		STATIC
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#if	defined(USE_DIRENT)
-#include <dirent.h>
-typedef struct dirent	DIRENTRY;
-#else
-#include <sys/dir.h>
-typedef struct direct	DIRENTRY;
-#endif	/* defined(USE_DIRENT) */
-
-#if	!defined(S_ISDIR)
-#define S_ISDIR(m)		(((m) & S_IFMT) == S_IFDIR)
-#endif	/* !defined(S_ISDIR) */
diff --git a/if1632/Makefile.in b/if1632/Makefile.in
new file mode 100644
index 0000000..71ea491
--- /dev/null
+++ b/if1632/Makefile.in
@@ -0,0 +1,88 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include
+LD	= @LD@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+BUILD	= $(TOPSRC)/tools/build
+@SET_MAKE@
+
+
+MODULE 	= if1632
+
+SRCS 	= callback.c relay.c relay32.c
+
+DLLS16	= commdlg.spec compobj.spec ddeml.spec gdi.spec kernel.spec \
+	keyboard.spec mmsystem.spec mouse.spec ole2.spec ole2conv.spec \
+	ole2disp.spec ole2nls.spec ole2prox.spec olecli.spec olesvr.spec \
+	shell.spec sound.spec storage.spec stress.spec system.spec \
+	toolhelp.spec user.spec win87em.spec winprocs.spec winsock.spec
+
+DLLS32	= gdi32.spec kernel32.spec shell32.spec user32.spec winprocs32.spec
+
+
+OBJS = $(SRCS:.c=.o) $(DLLS16:.spec=.o) $(DLLS32:.spec=.o) call16.o call32.o
+
+SFILES = $(DLLS16:.spec=.S)
+
+.SUFFIXES: .spec
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
+
+.spec.S:
+	$(BUILD) -spec16 $< > $*.S
+
+.S.o:
+	$(CC) -c -o $*.o $<  
+
+all: checkbuild $(MODULE).o
+
+gdi32.c: gdi32.spec
+	$(BUILD) -spec32 gdi32.spec > gdi32.c
+
+kernel32.c: kernel32.spec
+	$(BUILD) -spec32 kernel32.spec > kernel32.c
+
+shell32.c: shell32.spec
+	$(BUILD) -spec32 shell32.spec > shell32.c
+
+user32.c: user32.spec
+	$(BUILD) -spec32 user32.spec > user32.c
+
+winprocs32.c: winprocs32.spec
+	$(BUILD) -spec32 winprocs32.spec > winprocs32.c
+
+checkbuild:
+	(cd $(TOPSRC)/tools; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)')
+
+call16.S: $(TOPSRC)/include/callback.h
+	$(TOPSRC)/tools/build -call16 `cat $(TOPSRC)/include/callback.h | grep "extern.*CallTo16_" | sed 's/.*CallTo16_\(.*\)(.*/\1/' | sort | uniq` > call16.S
+
+call32.S: $(SFILES)
+	$(BUILD) -call32 `cat $(SFILES) | grep CallTo32_ | sed 's/.*CallTo32_\(.*\)/\1/' | sort | uniq` > call32.S
+
+
+$(MODULE).o: $(OBJS)
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM callback.c relay32.c relay.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ *.S gdi32.c kernel32.c shell32.c user32.c winprocs32.c tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+
+winelibclean:
+ 
+dummy:
+
+### Dependencies:
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index 94a31ec..7b302ad 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -47,7 +47,7 @@
 38  pascal Escape(word word word ptr ptr) Escape
 39  pascal16 RestoreDC(word s_word) RestoreDC
 40  pascal16 FillRgn(word word word) FillRgn
-41  stub FrameRgn
+41  pascal16 FrameRgn(word word word word word) FrameRgn
 42  pascal16 InvertRgn(word word) InvertRgn
 43  pascal16 PaintRgn(word word) PaintRgn
 44  pascal16 SelectClipRgn(word word) SelectClipRgn
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index e546d1d..a351242 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -42,7 +42,7 @@
 42  return DisableDos 0 0
 45  pascal16 LoadModule(ptr ptr) LoadModule
 46  pascal16 FreeModule(word) FreeModule
-47  pascal16 GetModuleHandle(ptr) GetModuleHandle
+47  pascal16 GetModuleHandle(segptr) WIN16_GetModuleHandle
 48  pascal16 GetModuleUsage(word) GetModuleUsage
 49  pascal16 GetModuleFileName(word ptr s_word) GetModuleFileName
 50  pascal GetProcAddress(word segptr) GetProcAddress
@@ -82,7 +82,7 @@
 84  pascal _llseek(word long word) _llseek
 85  pascal16 _lopen(ptr word) _lopen
 86  pascal16 _lwrite(word ptr word) _lwrite
-87 	stub RESERVED5
+87  pascal16 RESERVED5(ptr ptr) lstrcmp
 88  pascal lstrcpy(segptr segptr) lstrcpy
 89  pascal lstrcat(segptr segptr) lstrcat
 90  pascal16 lstrlen(ptr) lstrlen
@@ -146,7 +146,7 @@
 155 pascal16 GetTaskDS() GetTaskDS
 156 stub LimitEMSPages
 157 return GetCurPID 4 0
-158 stub IsWinOldApTask
+158 return IsWinOldApTask 2 0
 159 stub GlobalHandleNoRIP
 160 stub EMSCopy
 161 pascal16 LocalCountFree() LocalCountFree
diff --git a/if1632/keyboard.spec b/if1632/keyboard.spec
index afea764..af38f70 100644
--- a/if1632/keyboard.spec
+++ b/if1632/keyboard.spec
@@ -4,21 +4,21 @@
 #1	pascal	Inquire
 #2	pascal	Enable
 #3	pascal	Disable
-4	pascal	ToAscii(word word ptr ptr word) ToAscii
-5	pascal	AnsiToOem(ptr ptr) AnsiToOem
-6	pascal	OemToAnsi(ptr ptr) OemToAnsi
+4   pascal16 ToAscii(word word ptr ptr word) ToAscii
+5   pascal16 AnsiToOem(ptr ptr) AnsiToOem
+6   pascal16 OemToAnsi(ptr ptr) OemToAnsi
 #7	pascal	SetSpeed
 #100	pascal	ScreenSwitchEnable
 #126	pascal	GetTableSeg
 #127	pascal	NewTable
-128	pascal	OemKeyScan(word) OemKeyScan
-129	pascal	VkKeyScan(byte) VkKeyScan
-130	pascal	GetKeyboardType(byte) GetKeyboardType
-131	pascal	MapVirtualKey(word word) MapVirtualKey
-132	pascal	GetKbCodePage() GetKbCodePage
-133	pascal	GetKeyNameText(long ptr word) GetKeyNameText
-134	pascal	AnsiToOemBuff(ptr ptr word) AnsiToOemBuff
-135	pascal	OemToAnsiBuff(ptr ptr word) OemToAnsiBuff
+128 pascal   OemKeyScan(word) OemKeyScan
+129 pascal16 VkKeyScan(byte) VkKeyScan
+130 pascal16 GetKeyboardType(byte) GetKeyboardType
+131 pascal16 MapVirtualKey(word word) MapVirtualKey
+132 pascal16 GetKbCodePage() GetKbCodePage
+133 pascal16 GetKeyNameText(long ptr word) GetKeyNameText
+134 pascal16 AnsiToOemBuff(ptr ptr word) AnsiToOemBuff
+135 pascal16 OemToAnsiBuff(ptr ptr word) OemToAnsiBuff
 #136	pascal	EnableKbSysReq
 #137	pascal	GetBiosKeyProc
 
diff --git a/if1632/mouse.spec b/if1632/mouse.spec
index 879ecfc..0c04a8d 100644
--- a/if1632/mouse.spec
+++ b/if1632/mouse.spec
@@ -6,5 +6,6 @@
 3 stub DISABLE
 4 stub MOUSEGETINTVECT
 5 stub GETSETMOUSEDATA
-6 stub CPLAPPLET
+#Control Panel thinks this is implemented if it is available
+#6 stub CPLAPPLET
 7 stub POWEREVENTPROC
diff --git a/if1632/relay.c b/if1632/relay.c
index 1524517..72de966 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -8,6 +8,7 @@
 #include "dlls.h"
 #include "global.h"
 #include "module.h"
+#include "registers.h"
 #include "stackframe.h"
 #include "stddebug.h"
 /* #define DEBUG_RELAY */
@@ -80,7 +81,7 @@
 
     codesel = GLOBAL_CreateBlock( GMEM_FIXED, (void *)CALL16_Start,
                                    (int)CALL16_End - (int)CALL16_Start,
-                                   0, TRUE, TRUE, FALSE );
+                                   0, TRUE, TRUE, FALSE, NULL );
     if (!codesel) return FALSE;
 
       /* Patch the return addresses for CallTo16 routines */
@@ -97,7 +98,7 @@
 /***********************************************************************
  *           RELAY_DebugCall32
  */
-void RELAY_DebugCall32( char *args )
+void RELAY_DebugCall32( int func_type, char *args )
 {
     STACK16FRAME *frame;
     struct dll_table_s *table;
@@ -150,6 +151,13 @@
         if (*args) printf( "," );
     }
     printf( ") ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds );
+
+    if (func_type == 2)  /* register function */
+    {
+        struct sigcontext_struct *context = (struct sigcontext_struct *)args16;
+        printf( "     AX=%04x BX=%04x CX=%04x DX=%04x SI=%04x DI=%04x ES=%04x EFL=%08lx\n",
+                AX, BX, CX, DX, SI, DI, ES, EFL );
+    }
 }
 
 
@@ -162,6 +170,9 @@
     struct dll_table_s *table;
     char *name;
 
+    if (*(DWORD *)PTR_SEG_TO_LIN(IF1632_Stack32_base) != 0xDEADBEEF) {
+	fprintf(stderr, "Wine wrote past the end of the 32 bit stack. Please report this.\n");
+    }
     if (!debugging_relay) return;
 
     frame = CURRENT_STACK16;
diff --git a/if1632/user.spec b/if1632/user.spec
index b5512b3..8be2aa3 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -253,7 +253,7 @@
 250 pascal16 GetMenuState(word word word) GetMenuState
 251 pascal   SendDriverMessage(word word long long) SendDriverMessage
 252 pascal16 OpenDriver(ptr ptr long) OpenDriver
-253 pascal   CloseDriver(word word long) CloseDriver
+253 pascal   CloseDriver(word long long) CloseDriver
 254 pascal16 GetDriverModuleHandle(word) GetDriverModuleHandle
 255 pascal   DefDriverProc(long word word long long) DefDriverProc
 256 pascal16 GetDriverInfo(word ptr) GetDriverInfo
@@ -266,7 +266,7 @@
 262 pascal16 GetWindow(word word) GetWindow
 263 pascal16 GetMenuItemCount(word) GetMenuItemCount
 264 pascal16 GetMenuItemID(word word) GetMenuItemID
-265 stub ShowOwnedPopups
+265 pascal16 ShowOwnedPopups(word word) ShowOwnedPopups
 266 pascal16 SetMessageQueue(word) SetMessageQueue
 267 pascal16 ShowScrollBar(word word word) ShowScrollBar
 268 pascal16 GlobalAddAtom(ptr) GlobalAddAtom
@@ -371,7 +371,7 @@
                             word word word segptr) CreateWindowEx
 454 pascal16 AdjustWindowRectEx(ptr long word long) AdjustWindowRectEx
 455 stub GetIconId
-456 stub LoadIconHandler
+456 pascal16 LoadIconHandler(word word) LoadIconHandler
 457 pascal16 DestroyIcon(word) DestroyIcon
 458 pascal16 DestroyCursor(word) DestroyCursor
 459 pascal   DumpIcon(ptr ptr ptr ptr) DumpIcon
diff --git a/if1632/winprocs.spec b/if1632/winprocs.spec
index 8a0e88d..b95e074 100644
--- a/if1632/winprocs.spec
+++ b/if1632/winprocs.spec
@@ -25,23 +25,265 @@
 22 pascal ComboLBoxWndProc(word word word long) ComboLBoxWndProc
 23 pascal16 CARET_Callback(word word word long) CARET_Callback
 24 pascal16 TASK_Reschedule() TASK_Reschedule
+25 pascal MMSysTimeCallback(word word word long) MMSysTimeCallback
 
 # Interrupt vectors 0-255 are ordinals 100-355
-# Undefined functions are mapped to the dummy handler (ordinal 356)
 # The 'word' parameter are the flags pushed on the stack by the interrupt
-
+100 register INT_Int00Handler(word) INT_DummyHandler
+101 register INT_Int01Handler(word) INT_DummyHandler
+102 register INT_Int02Handler(word) INT_DummyHandler
+103 register INT_Int03Handler(word) INT_DummyHandler
+104 register INT_Int04Handler(word) INT_DummyHandler
+105 register INT_Int05Handler(word) INT_DummyHandler
+106 register INT_Int06Handler(word) INT_DummyHandler
+107 register INT_Int07Handler(word) INT_DummyHandler
+108 register INT_Int08Handler(word) INT_DummyHandler
+109 register INT_Int09Handler(word) INT_DummyHandler
+110 register INT_Int0aHandler(word) INT_DummyHandler
+111 register INT_Int0bHandler(word) INT_DummyHandler
+112 register INT_Int0cHandler(word) INT_DummyHandler
+113 register INT_Int0dHandler(word) INT_DummyHandler
+114 register INT_Int0eHandler(word) INT_DummyHandler
+115 register INT_Int0fHandler(word) INT_DummyHandler
 116 register INT_Int10Handler(word) INT_Int10Handler
+117 register INT_Int11Handler(word) INT_Int11Handler
+118 register INT_Int12Handler(word) INT_Int12Handler
 119 register INT_Int13Handler(word) INT_Int13Handler
+120 register INT_Int14Handler(word) INT_DummyHandler
 121 register INT_Int15Handler(word) INT_Int15Handler
 122 register INT_Int16Handler(word) INT_Int16Handler
+123 register INT_Int17Handler(word) INT_DummyHandler
+124 register INT_Int18Handler(word) INT_DummyHandler
+125 register INT_Int19Handler(word) INT_DummyHandler
 126 register INT_Int1aHandler(word) INT_Int1aHandler
-133 register INT_Int21Handler(word) INT_Int21Handler
-137 register INT_Int25Handler(word) INT_Int25Handler
-138 register INT_Int26Handler(word) INT_Int26Handler
+127 register INT_Int1bHandler(word) INT_DummyHandler
+128 register INT_Int1cHandler(word) INT_DummyHandler
+129 register INT_Int1dHandler(word) INT_DummyHandler
+130 register INT_Int1eHandler(word) INT_DummyHandler
+131 register INT_Int1fHandler(word) INT_DummyHandler
+132 register INT_Int20Handler(word) INT_DummyHandler
+133 register INT_Int21Handler(word) DOS3Call
+134 register INT_Int22Handler(word) INT_DummyHandler
+135 register INT_Int23Handler(word) INT_DummyHandler
+136 register INT_Int24Handler(word) INT_DummyHandler
+# Note: int 25 and 26 don't pop the flags from the stack
+137 register INT_Int25Handler()     INT_Int25Handler
+138 register INT_Int26Handler()     INT_Int26Handler
+139 register INT_Int27Handler(word) INT_DummyHandler
+140 register INT_Int28Handler(word) INT_DummyHandler
+141 register INT_Int29Handler(word) INT_DummyHandler
 142 register INT_Int2aHandler(word) INT_Int2aHandler
+143 register INT_Int2bHandler(word) INT_DummyHandler
+144 register INT_Int2cHandler(word) INT_DummyHandler
+145 register INT_Int2dHandler(word) INT_DummyHandler
+146 register INT_Int2eHandler(word) INT_DummyHandler
 147 register INT_Int2fHandler(word) INT_Int2fHandler
+148 register INT_Int30Handler(word) INT_DummyHandler
 149 register INT_Int31Handler(word) INT_Int31Handler
-192 register INT_Int5cHandler(word) INT_Int5cHandler
+150 register INT_Int32Handler(word) INT_DummyHandler
+151 register INT_Int33Handler(word) INT_DummyHandler
+152 register INT_Int34Handler(word) INT_DummyHandler
+153 register INT_Int35Handler(word) INT_DummyHandler
+154 register INT_Int36Handler(word) INT_DummyHandler
+155 register INT_Int37Handler(word) INT_DummyHandler
+156 register INT_Int38Handler(word) INT_DummyHandler
+157 register INT_Int39Handler(word) INT_DummyHandler
+158 register INT_Int3aHandler(word) INT_DummyHandler
+159 register INT_Int3bHandler(word) INT_DummyHandler
+160 register INT_Int3cHandler(word) INT_DummyHandler
+161 register INT_Int3dHandler(word) INT_DummyHandler
+162 register INT_Int3eHandler(word) INT_DummyHandler
+163 register INT_Int3fHandler(word) INT_DummyHandler
+164 register INT_Int40Handler(word) INT_DummyHandler
+165 register INT_Int41Handler(word) INT_DummyHandler
+166 register INT_Int42Handler(word) INT_DummyHandler
+167 register INT_Int43Handler(word) INT_DummyHandler
+168 register INT_Int44Handler(word) INT_DummyHandler
+169 register INT_Int45Handler(word) INT_DummyHandler
+170 register INT_Int46Handler(word) INT_DummyHandler
+171 register INT_Int47Handler(word) INT_DummyHandler
+172 register INT_Int48Handler(word) INT_DummyHandler
+173 register INT_Int49Handler(word) INT_DummyHandler
+174 register INT_Int4aHandler(word) INT_DummyHandler
+175 register INT_Int4bHandler(word) INT_DummyHandler
+176 register INT_Int4cHandler(word) INT_DummyHandler
+177 register INT_Int4dHandler(word) INT_DummyHandler
+178 register INT_Int4eHandler(word) INT_DummyHandler
+179 register INT_Int4fHandler(word) INT_DummyHandler
+180 register INT_Int50Handler(word) INT_DummyHandler
+181 register INT_Int51Handler(word) INT_DummyHandler
+182 register INT_Int52Handler(word) INT_DummyHandler
+183 register INT_Int53Handler(word) INT_DummyHandler
+184 register INT_Int54Handler(word) INT_DummyHandler
+185 register INT_Int55Handler(word) INT_DummyHandler
+186 register INT_Int56Handler(word) INT_DummyHandler
+187 register INT_Int57Handler(word) INT_DummyHandler
+188 register INT_Int58Handler(word) INT_DummyHandler
+189 register INT_Int59Handler(word) INT_DummyHandler
+190 register INT_Int5aHandler(word) INT_DummyHandler
+191 register INT_Int5bHandler(word) INT_DummyHandler
+192 register INT_Int5cHandler(word) NetBIOSCall
+193 register INT_Int5dHandler(word) INT_DummyHandler
+194 register INT_Int5eHandler(word) INT_DummyHandler
+195 register INT_Int5fHandler(word) INT_DummyHandler
+196 register INT_Int60Handler(word) INT_DummyHandler
+197 register INT_Int61Handler(word) INT_DummyHandler
+198 register INT_Int62Handler(word) INT_DummyHandler
+199 register INT_Int63Handler(word) INT_DummyHandler
+200 register INT_Int64Handler(word) INT_DummyHandler
+201 register INT_Int65Handler(word) INT_DummyHandler
+202 register INT_Int66Handler(word) INT_DummyHandler
+203 register INT_Int67Handler(word) INT_DummyHandler
+204 register INT_Int68Handler(word) INT_DummyHandler
+205 register INT_Int69Handler(word) INT_DummyHandler
+206 register INT_Int6aHandler(word) INT_DummyHandler
+207 register INT_Int6bHandler(word) INT_DummyHandler
+208 register INT_Int6cHandler(word) INT_DummyHandler
+209 register INT_Int6dHandler(word) INT_DummyHandler
+210 register INT_Int6eHandler(word) INT_DummyHandler
+211 register INT_Int6fHandler(word) INT_DummyHandler
+212 register INT_Int70Handler(word) INT_DummyHandler
+213 register INT_Int71Handler(word) INT_DummyHandler
+214 register INT_Int72Handler(word) INT_DummyHandler
+215 register INT_Int73Handler(word) INT_DummyHandler
+216 register INT_Int74Handler(word) INT_DummyHandler
+217 register INT_Int75Handler(word) INT_DummyHandler
+218 register INT_Int76Handler(word) INT_DummyHandler
+219 register INT_Int77Handler(word) INT_DummyHandler
+220 register INT_Int78Handler(word) INT_DummyHandler
+221 register INT_Int79Handler(word) INT_DummyHandler
+222 register INT_Int7aHandler(word) INT_DummyHandler
+223 register INT_Int7bHandler(word) INT_DummyHandler
+224 register INT_Int7cHandler(word) INT_DummyHandler
+225 register INT_Int7dHandler(word) INT_DummyHandler
+226 register INT_Int7eHandler(word) INT_DummyHandler
+227 register INT_Int7fHandler(word) INT_DummyHandler
+228 register INT_Int80Handler(word) INT_DummyHandler
+229 register INT_Int81Handler(word) INT_DummyHandler
+230 register INT_Int82Handler(word) INT_DummyHandler
+231 register INT_Int83Handler(word) INT_DummyHandler
+232 register INT_Int84Handler(word) INT_DummyHandler
+233 register INT_Int85Handler(word) INT_DummyHandler
+234 register INT_Int86Handler(word) INT_DummyHandler
+235 register INT_Int87Handler(word) INT_DummyHandler
+236 register INT_Int88Handler(word) INT_DummyHandler
+237 register INT_Int89Handler(word) INT_DummyHandler
+238 register INT_Int8aHandler(word) INT_DummyHandler
+239 register INT_Int8bHandler(word) INT_DummyHandler
+240 register INT_Int8cHandler(word) INT_DummyHandler
+241 register INT_Int8dHandler(word) INT_DummyHandler
+242 register INT_Int8eHandler(word) INT_DummyHandler
+243 register INT_Int8fHandler(word) INT_DummyHandler
+244 register INT_Int90Handler(word) INT_DummyHandler
+245 register INT_Int91Handler(word) INT_DummyHandler
+246 register INT_Int92Handler(word) INT_DummyHandler
+247 register INT_Int93Handler(word) INT_DummyHandler
+248 register INT_Int94Handler(word) INT_DummyHandler
+249 register INT_Int95Handler(word) INT_DummyHandler
+250 register INT_Int96Handler(word) INT_DummyHandler
+251 register INT_Int97Handler(word) INT_DummyHandler
+252 register INT_Int98Handler(word) INT_DummyHandler
+253 register INT_Int99Handler(word) INT_DummyHandler
+254 register INT_Int9aHandler(word) INT_DummyHandler
+255 register INT_Int9bHandler(word) INT_DummyHandler
+256 register INT_Int9cHandler(word) INT_DummyHandler
+257 register INT_Int9dHandler(word) INT_DummyHandler
+258 register INT_Int9eHandler(word) INT_DummyHandler
+259 register INT_Int9fHandler(word) INT_DummyHandler
+260 register INT_Inta0Handler(word) INT_DummyHandler
+261 register INT_Inta1Handler(word) INT_DummyHandler
+262 register INT_Inta2Handler(word) INT_DummyHandler
+263 register INT_Inta3Handler(word) INT_DummyHandler
+264 register INT_Inta4Handler(word) INT_DummyHandler
+265 register INT_Inta5Handler(word) INT_DummyHandler
+266 register INT_Inta6Handler(word) INT_DummyHandler
+267 register INT_Inta7Handler(word) INT_DummyHandler
+268 register INT_Inta8Handler(word) INT_DummyHandler
+269 register INT_Inta9Handler(word) INT_DummyHandler
+270 register INT_IntaaHandler(word) INT_DummyHandler
+271 register INT_IntabHandler(word) INT_DummyHandler
+272 register INT_IntacHandler(word) INT_DummyHandler
+273 register INT_IntadHandler(word) INT_DummyHandler
+274 register INT_IntaeHandler(word) INT_DummyHandler
+275 register INT_IntafHandler(word) INT_DummyHandler
+276 register INT_Intb0Handler(word) INT_DummyHandler
+277 register INT_Intb1Handler(word) INT_DummyHandler
+278 register INT_Intb2Handler(word) INT_DummyHandler
+279 register INT_Intb3Handler(word) INT_DummyHandler
+280 register INT_Intb4Handler(word) INT_DummyHandler
+281 register INT_Intb5Handler(word) INT_DummyHandler
+282 register INT_Intb6Handler(word) INT_DummyHandler
+283 register INT_Intb7Handler(word) INT_DummyHandler
+284 register INT_Intb8Handler(word) INT_DummyHandler
+285 register INT_Intb9Handler(word) INT_DummyHandler
+286 register INT_IntbaHandler(word) INT_DummyHandler
+287 register INT_IntbbHandler(word) INT_DummyHandler
+288 register INT_IntbcHandler(word) INT_DummyHandler
+289 register INT_IntbdHandler(word) INT_DummyHandler
+290 register INT_IntbeHandler(word) INT_DummyHandler
+291 register INT_IntbfHandler(word) INT_DummyHandler
+292 register INT_Intc0Handler(word) INT_DummyHandler
+293 register INT_Intc1Handler(word) INT_DummyHandler
+294 register INT_Intc2Handler(word) INT_DummyHandler
+295 register INT_Intc3Handler(word) INT_DummyHandler
+296 register INT_Intc4Handler(word) INT_DummyHandler
+297 register INT_Intc5Handler(word) INT_DummyHandler
+298 register INT_Intc6Handler(word) INT_DummyHandler
+299 register INT_Intc7Handler(word) INT_DummyHandler
+300 register INT_Intc8Handler(word) INT_DummyHandler
+301 register INT_Intc9Handler(word) INT_DummyHandler
+302 register INT_IntcaHandler(word) INT_DummyHandler
+303 register INT_IntcbHandler(word) INT_DummyHandler
+304 register INT_IntccHandler(word) INT_DummyHandler
+305 register INT_IntcdHandler(word) INT_DummyHandler
+306 register INT_IntceHandler(word) INT_DummyHandler
+307 register INT_IntcfHandler(word) INT_DummyHandler
+308 register INT_Intd0Handler(word) INT_DummyHandler
+309 register INT_Intd1Handler(word) INT_DummyHandler
+310 register INT_Intd2Handler(word) INT_DummyHandler
+311 register INT_Intd3Handler(word) INT_DummyHandler
+312 register INT_Intd4Handler(word) INT_DummyHandler
+313 register INT_Intd5Handler(word) INT_DummyHandler
+314 register INT_Intd6Handler(word) INT_DummyHandler
+315 register INT_Intd7Handler(word) INT_DummyHandler
+316 register INT_Intd8Handler(word) INT_DummyHandler
+317 register INT_Intd9Handler(word) INT_DummyHandler
+318 register INT_IntdaHandler(word) INT_DummyHandler
+319 register INT_IntdbHandler(word) INT_DummyHandler
+320 register INT_IntdcHandler(word) INT_DummyHandler
+321 register INT_IntddHandler(word) INT_DummyHandler
+322 register INT_IntdeHandler(word) INT_DummyHandler
+323 register INT_IntdfHandler(word) INT_DummyHandler
+324 register INT_Inte0Handler(word) INT_DummyHandler
+325 register INT_Inte1Handler(word) INT_DummyHandler
+326 register INT_Inte2Handler(word) INT_DummyHandler
+327 register INT_Inte3Handler(word) INT_DummyHandler
+328 register INT_Inte4Handler(word) INT_DummyHandler
+329 register INT_Inte5Handler(word) INT_DummyHandler
+330 register INT_Inte6Handler(word) INT_DummyHandler
+331 register INT_Inte7Handler(word) INT_DummyHandler
+332 register INT_Inte8Handler(word) INT_DummyHandler
+333 register INT_Inte9Handler(word) INT_DummyHandler
+334 register INT_InteaHandler(word) INT_DummyHandler
+335 register INT_IntebHandler(word) INT_DummyHandler
+336 register INT_IntecHandler(word) INT_DummyHandler
+337 register INT_IntedHandler(word) INT_DummyHandler
+338 register INT_InteeHandler(word) INT_DummyHandler
+339 register INT_IntefHandler(word) INT_DummyHandler
+340 register INT_Intf0Handler(word) INT_DummyHandler
+341 register INT_Intf1Handler(word) INT_DummyHandler
+342 register INT_Intf2Handler(word) INT_DummyHandler
+343 register INT_Intf3Handler(word) INT_DummyHandler
+344 register INT_Intf4Handler(word) INT_DummyHandler
+345 register INT_Intf5Handler(word) INT_DummyHandler
+346 register INT_Intf6Handler(word) INT_DummyHandler
+347 register INT_Intf7Handler(word) INT_DummyHandler
+348 register INT_Intf8Handler(word) INT_DummyHandler
+349 register INT_Intf9Handler(word) INT_DummyHandler
+350 register INT_IntfaHandler(word) INT_DummyHandler
+351 register INT_IntfbHandler(word) INT_DummyHandler
+352 register INT_IntfcHandler(word) INT_DummyHandler
+353 register INT_IntfdHandler(word) INT_DummyHandler
+354 register INT_IntfeHandler(word) INT_DummyHandler
+355 register INT_IntffHandler(word) INT_DummyHandler
 
-# Dummy interrupt vector
-356 register INT_DummyHandler(word) INT_DummyHandler
diff --git a/if1632/winsock.spec b/if1632/winsock.spec
index 2418716..813f364 100644
--- a/if1632/winsock.spec
+++ b/if1632/winsock.spec
@@ -15,7 +15,7 @@
 7   pascal16 getsockopt(word word word ptr ptr) WINSOCK_getsockopt
 8   pascal   htonl(long) WINSOCK_htonl
 9   pascal16 htons(word) WINSOCK_htons
-10  pascal   inet_addr(long) WINSOCK_inet_addr
+10  pascal   inet_addr(ptr) WINSOCK_inet_addr
 11  pascal   inet_ntoa(long) WINSOCK_inet_ntoa
 12  pascal16 ioctlsocket(word long ptr) WINSOCK_ioctlsocket
 13  pascal16 listen(word word) WINSOCK_listen
@@ -23,7 +23,7 @@
 15  pascal16 ntohs(word) WINSOCK_ntohs
 16  pascal16 recv(word ptr word word) WINSOCK_recv
 17  pascal16 recvfrom(word ptr word word ptr ptr) WINSOCK_recvfrom
-18  pascal16 select(word ptr ptr ptr ptr word) WINSOCK_select
+18  pascal16 select(word ptr ptr ptr ptr ptr) WINSOCK_select
 19  pascal16 send(word ptr word word) WINSOCK_send
 20  pascal16 sendto(word ptr word word ptr ptr) WINSOCK_sendto
 21  pascal16 setsockopt(word word word ptr word) WINSOCK_setsockopt
diff --git a/include/atom.h b/include/atom.h
index 045c343..631f185 100644
--- a/include/atom.h
+++ b/include/atom.h
@@ -31,4 +31,14 @@
 #define LocalAlign(flags,bytes) LocalAlloc((flags),(bytes))
 #endif
 
+ATOM LocalAddAtom( LPCSTR str );
+ATOM LocalDeleteAtom( ATOM atom );
+ATOM LocalFindAtom( LPCSTR str );
+WORD LocalGetAtomName( ATOM atom, LPSTR buffer, short count );
+
+ATOM LocalAddAtom( LPCSTR str );
+ATOM LocalDeleteAtom( ATOM atom );
+ATOM LocalFindAtom( LPCSTR str );
+WORD LocalGetAtomName( ATOM atom, LPSTR buffer, short count );
+
 #endif  /* ATOM_H */
diff --git a/include/bit_array.h b/include/bit_array.h
new file mode 100644
index 0000000..b07cdf6
--- /dev/null
+++ b/include/bit_array.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      bit_array.h
+ * Purpose :  manipulate array of bits,
+ * Important: operations may be considered atomic.
+ *
+ ***************************************************************************
+ */
+#ifndef __WINE_BIT_ARRAY_H
+#define __WINE_BIT_ARRAY_H
+
+
+#define BITS_PER_BYTE (8)
+#define BITS_PER_INT (sizeof(int)*BITS_PER_BYTE) /* must be power of 2 */
+
+#define BYTE_LOG2 (3)
+#if defined(INT_LOG2)
+/* nothing to do, IN_LOG2 is ok */
+#elif defined(__i386__)
+#  define INT_LOG2 (5)
+#else
+#  error "Can't find log2 of BITS_PER_INT, please code it manualy"
+#endif
+
+
+typedef struct bit_array {
+	int bits;		   /* number of bits in the array */
+	unsigned int *array;	   /* Actual array data (Never NULL) */
+} bit_array ;
+
+bit_array *AssembleArray(bit_array *new_array, unsigned int *buff, int bits);
+int ResetArray(bit_array *bits);
+
+/* Return index of first free bit, or -1 on failure */
+int VacantBit(bit_array *bits);
+
+
+/* Return the value of bit 'i' */
+int SampleBit(bit_array *bits, int i);
+
+/* Assign 'val' to a bit no. 'i'.      Return: old bit's value */
+int AssignBit(bit_array *bits, int i, int val);
+
+/*
+** Allocate a free bit (==0) and make it used (==1).
+** Return: allocated bit index, or -1 on failure.
+*/
+int AllocateBit(bit_array *bits);
+
+#endif /* __WINE_BIT_ARRAY_H */
diff --git a/include/config.h.in b/include/config.h.in
new file mode 100644
index 0000000..10c6b69
--- /dev/null
+++ b/include/config.h.in
@@ -0,0 +1,6 @@
+#undef HAVE_STDLIB_H
+#undef HAVE_TCGETATTR
+#undef HAVE_DIRENT_H
+#undef HAVE_SYS_NDIR_H
+#undef HAVE_NDIR_H
+#undef STAT_MACROS_BROKEN
diff --git a/include/dde.h b/include/dde.h
new file mode 100644
index 0000000..72d250c
--- /dev/null
+++ b/include/dde.h
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      dde.h
+ * Purpose:   dde declarations
+ *
+ *****************************************************************************
+ */
+#ifndef __WINE_DDE_H
+#define __WINE_DDE_H
+
+#include "wintypes.h"
+#include "dde_proc.h"
+
+#define WM_DDE_INITIATE   0x3E0
+#define WM_DDE_TERMINATE  0x3E1
+#define WM_DDE_ADVISE	  0x3E2
+#define WM_DDE_UNADVISE   0x3E3
+#define WM_DDE_ACK	  0x3E4
+#define WM_DDE_DATA	  0x3E5
+#define WM_DDE_REQUEST	  0x3E6
+#define WM_DDE_POKE	  0x3E7
+#define WM_DDE_EXECUTE	  0x3E8
+#define WM_DDE_LAST	  WM_DDE_EXECUTE
+#define WM_DDE_FIRST	  WM_DDE_INITIATE
+
+/* DDEACK: wStatus in WM_DDE_ACK message */
+struct tagDDEACK
+{
+    WORD bAppReturnCode:8, reserved:6, fBusy:1, fAck:1;
+};
+typedef struct tagDDEACK DDEACK;
+
+/* DDEDATA: hData in WM_DDE_DATA message */
+struct tagDDEDATA
+{
+    WORD unused:12, fResponse:1, fRelease:1, reserved:1, fAckReq:1,
+         cfFormat:16;
+    BYTE Value[1];		/* undetermined array */
+};
+typedef struct tagDDEDATA DDEDATA;
+
+
+/* DDEADVISE: hOptions in WM_DDE_ADVISE message */
+struct tagDDEADVISE
+{
+    WORD reserved:14, fDeferUpd:1, fAckReq:1, cfFormat:16;
+};
+typedef struct tagDDEADVISE DDEADVISE;
+
+/* DDEPOKE: hData in WM_DDE_POKE message. */
+struct tagDDEPOKE
+{
+    WORD unused:13, fRelease:1, fReserved:2, cfFormat:16;
+    BYTE Value[1];   	/* undetermined array */
+};
+typedef struct tagDDEPOKE DDEPOKE;
+
+#endif /* __WINE_DDE_H */
diff --git a/include/dde_atom.h b/include/dde_atom.h
new file mode 100644
index 0000000..56df6b7
--- /dev/null
+++ b/include/dde_atom.h
@@ -0,0 +1,23 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      dde_atom.h
+ * Purpose :  atom functionality for DDE
+ ***************************************************************************
+ */
+#ifndef __WINE_DDE_ATOM_H
+#define __WINE_DDE_ATOM_H
+#include "windows.h"
+
+#define DDE_ATOMS 157		   /* a prime number for hashing */
+
+void ATOM_GlobalInit(void);
+/*
+ATOM GlobalAddAtom( LPCSTR str );
+ATOM GlobalDeleteAtom( ATOM atom );
+ATOM GlobalFindAtom( LPCSTR str );
+WORD GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
+*/
+#endif __WINE_DDE_ATOM_H
diff --git a/include/dde_mem.h b/include/dde_mem.h
new file mode 100644
index 0000000..6a830e1
--- /dev/null
+++ b/include/dde_mem.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      dde_mem.h
+ * Purpose :  shared DDE memory functionality for DDE
+ ***************************************************************************
+ */
+#ifndef __WINE_DDE_MEM_H
+#define __WINE_DDE_MEM_H
+#include "wintypes.h"
+#include "global.h"
+#include "shm_block.h"
+
+#define DDE_HANDLES 0x0400
+#define is_dde_handle(block) ( (block) >= (1<<15)  &&  (block) < (1<<15)+DDE_HANDLES )
+typedef struct {
+    int shmid;
+    REL_PTR rel;
+}DDE_HWND;
+
+WORD DDE_SyncHandle(HGLOBAL handle, WORD sel);
+void *DDE_malloc(unsigned int flags,unsigned long size, SHMDATA *shmdata);
+HANDLE DDE_GlobalReAlloc(WORD,long,WORD);
+HANDLE DDE_GlobalFree(WORD block);
+void *DDE_AttachHandle(HGLOBAL handle, SEGPTR *segptr);
+WORD DDE_GlobalHandleToSel( HGLOBAL handle );
+int DDE_GlobalUnlock(int);
+HANDLE DDE_GlobalSize(WORD);
+HANDLE DDE_GlobalHandle(WORD);
+HANDLE DDE_GlobalFlags(WORD);
+
+#endif /* __WINE_DDE_MEM_H */
diff --git a/include/dde_proc.h b/include/dde_proc.h
new file mode 100644
index 0000000..85e682a
--- /dev/null
+++ b/include/dde_proc.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      dde_proc.h
+ * Purpose :  DDE signals and processes functionality for DDE
+ ***************************************************************************
+ */
+#ifndef __WINE_DDE_PROC_H
+#define __WINE_DDE_PROC_H
+#include <setjmp.h>
+#include "wintypes.h"
+#include "windows.h"
+#define DDE_PROCS 64
+#define DDE_WINDOWS 64
+struct _dde_proc {
+    int msg;			/* message queue for this process */
+    int shmid;			/* first shared memory block id. */
+    int sem;			/* semaphore for fragment allocation */
+    int pid;
+} ;
+typedef struct _dde_proc *dde_proc;
+
+extern sigjmp_buf env_wait_x;
+enum stop_wait_op {		/* The action to be taken upon SIGUSR2 */
+    CONT,			/* Don't do anything */
+    STOP_WAIT_ACK,		/* Use siglongjmp to stop wait_ack() */
+    STOP_WAIT_X			/* siglongjmp to stop MSG_WaitXEvent() */
+};
+
+typedef struct {
+    WORD  proc_idx;		/* index into wine's process table  */
+    HWND  wnd;			/* Window on the local proccess */
+} WND_DATA;
+extern enum stop_wait_op stop_wait_op;
+extern int had_SIGUSR2;
+
+extern int curr_proc_idx;
+void stop_wait(int a);		   /* signal handler for SIGUSR2
+				      (interrupts "select" system call) */
+void dde_proc_init(dde_proc proc); /* init proc array */
+void dde_proc_done(dde_proc proc); /* delete a proc entry */
+void dde_proc_refresh(dde_proc proc); /* delete entry, if old junk */
+void dde_proc_add(dde_proc proc);  /* Add current proc to proc array */
+void dde_msg_setup(int *msg_ptr);
+int  dde_reschedule();
+void dde_wnd_setup();		   /* setup Data structure of DDE windows */
+
+/* Send ack. to hnd indicating that posted/sent msg. got to destination*/
+void dde_proc_send_ack(HWND wnd, BOOL val);
+BOOL DDE_PostMessage( MSG *msg);
+BOOL DDE_SendMessage( MSG *msg);
+int DDE_GetRemoteMessage();
+void DDE_DestroyWindow(HWND hwnd); /* delete DDE info regarding hwnd */
+void DDE_TestDDE(HWND hwnd);	   /* do we have dde handling in the window ?*/
+#endif /* __WINE_DDE_PROC_H */
diff --git a/include/debug.h b/include/debug.h
index d728531..8d74615 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -17,6 +17,7 @@
 
 #ifdef DEBUG_NONE_EXT
 #undef DEBUG_ACCEL
+#undef DEBUG_ATOM
 #undef DEBUG_BITBLT
 #undef DEBUG_BITMAP
 #undef DEBUG_CARET
@@ -29,6 +30,7 @@
 #undef DEBUG_COMM
 #undef DEBUG_CURSOR
 #undef DEBUG_DC
+#undef DEBUG_DDE
 #undef DEBUG_DIALOG
 #undef DEBUG_DLL
 #undef DEBUG_DOSFS
@@ -77,6 +79,9 @@
 #undef DEBUG_SCROLL
 #undef DEBUG_SELECTOR
 #undef DEBUG_SELECTORS
+#undef DEBUG_SEM
+#undef DEBUG_SHM
+#undef DEBUG_SPY
 #undef DEBUG_STRESS
 #undef DEBUG_SYSCOLOR
 #undef DEBUG_TASK
@@ -90,6 +95,7 @@
 
 #ifdef DEBUG_ALL_EXT
 #define DEBUG_ACCEL
+#define DEBUG_ATOM
 #define DEBUG_BITBLT
 #define DEBUG_BITMAP
 #define DEBUG_CARET
@@ -102,6 +108,7 @@
 #define DEBUG_COMM
 #define DEBUG_CURSOR
 #define DEBUG_DC
+#define DEBUG_DDE
 #define DEBUG_DIALOG
 #define DEBUG_DLL
 #define DEBUG_DOSFS
@@ -150,6 +157,9 @@
 #define DEBUG_SCROLL
 #define DEBUG_SELECTOR
 #define DEBUG_SELECTORS
+#define DEBUG_SEM
+#define DEBUG_SHM
+#define DEBUG_SPY
 #define DEBUG_STRESS
 #define DEBUG_SYSCOLOR
 #define DEBUG_TASK
@@ -169,6 +179,11 @@
 #else
     0,
 #endif
+#ifdef DEBUG_ATOM
+    1,
+#else
+    0,
+#endif
 #ifdef DEBUG_BITBLT
     1,
 #else
@@ -229,6 +244,11 @@
 #else
     0,
 #endif
+#ifdef DEBUG_DDE
+    1,
+#else
+    0,
+#endif
 #ifdef DEBUG_DIALOG
     1,
 #else
@@ -469,6 +489,21 @@
 #else
     0,
 #endif
+#ifdef DEBUG_SEM
+    1,
+#else
+    0,
+#endif
+#ifdef DEBUG_SHM
+    1,
+#else
+    0,
+#endif
+#ifdef DEBUG_SPY
+    1,
+#else
+    0,
+#endif
 #ifdef DEBUG_STRESS
     1,
 #else
@@ -535,8 +570,21 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_bitblt if(!debug_msg_enabled[1]) ; else fprintf
-#define debugging_bitblt debug_msg_enabled[1]
+#define dprintf_atom if(!debug_msg_enabled[1]) ; else fprintf
+#define debugging_atom debug_msg_enabled[1]
+#else
+#ifdef DEBUG_ATOM
+#define dprintf_atom fprintf
+#define debugging_atom 1
+#else
+#define dprintf_atom while(0) fprintf
+#define debugging_atom 0
+#endif
+#endif
+
+#ifdef DEBUG_RUNTIME
+#define dprintf_bitblt if(!debug_msg_enabled[2]) ; else fprintf
+#define debugging_bitblt debug_msg_enabled[2]
 #else
 #ifdef DEBUG_BITBLT
 #define dprintf_bitblt fprintf
@@ -548,8 +596,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_bitmap if(!debug_msg_enabled[2]) ; else fprintf
-#define debugging_bitmap debug_msg_enabled[2]
+#define dprintf_bitmap if(!debug_msg_enabled[3]) ; else fprintf
+#define debugging_bitmap debug_msg_enabled[3]
 #else
 #ifdef DEBUG_BITMAP
 #define dprintf_bitmap fprintf
@@ -561,8 +609,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_caret if(!debug_msg_enabled[3]) ; else fprintf
-#define debugging_caret debug_msg_enabled[3]
+#define dprintf_caret if(!debug_msg_enabled[4]) ; else fprintf
+#define debugging_caret debug_msg_enabled[4]
 #else
 #ifdef DEBUG_CARET
 #define dprintf_caret fprintf
@@ -574,8 +622,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_catch if(!debug_msg_enabled[4]) ; else fprintf
-#define debugging_catch debug_msg_enabled[4]
+#define dprintf_catch if(!debug_msg_enabled[5]) ; else fprintf
+#define debugging_catch debug_msg_enabled[5]
 #else
 #ifdef DEBUG_CATCH
 #define dprintf_catch fprintf
@@ -587,8 +635,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_cdaudio if(!debug_msg_enabled[5]) ; else fprintf
-#define debugging_cdaudio debug_msg_enabled[5]
+#define dprintf_cdaudio if(!debug_msg_enabled[6]) ; else fprintf
+#define debugging_cdaudio debug_msg_enabled[6]
 #else
 #ifdef DEBUG_CDAUDIO
 #define dprintf_cdaudio fprintf
@@ -600,8 +648,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_class if(!debug_msg_enabled[6]) ; else fprintf
-#define debugging_class debug_msg_enabled[6]
+#define dprintf_class if(!debug_msg_enabled[7]) ; else fprintf
+#define debugging_class debug_msg_enabled[7]
 #else
 #ifdef DEBUG_CLASS
 #define dprintf_class fprintf
@@ -613,8 +661,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_clipboard if(!debug_msg_enabled[7]) ; else fprintf
-#define debugging_clipboard debug_msg_enabled[7]
+#define dprintf_clipboard if(!debug_msg_enabled[8]) ; else fprintf
+#define debugging_clipboard debug_msg_enabled[8]
 #else
 #ifdef DEBUG_CLIPBOARD
 #define dprintf_clipboard fprintf
@@ -626,8 +674,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_clipping if(!debug_msg_enabled[8]) ; else fprintf
-#define debugging_clipping debug_msg_enabled[8]
+#define dprintf_clipping if(!debug_msg_enabled[9]) ; else fprintf
+#define debugging_clipping debug_msg_enabled[9]
 #else
 #ifdef DEBUG_CLIPPING
 #define dprintf_clipping fprintf
@@ -639,8 +687,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_combo if(!debug_msg_enabled[9]) ; else fprintf
-#define debugging_combo debug_msg_enabled[9]
+#define dprintf_combo if(!debug_msg_enabled[10]) ; else fprintf
+#define debugging_combo debug_msg_enabled[10]
 #else
 #ifdef DEBUG_COMBO
 #define dprintf_combo fprintf
@@ -652,8 +700,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_comm if(!debug_msg_enabled[10]) ; else fprintf
-#define debugging_comm debug_msg_enabled[10]
+#define dprintf_comm if(!debug_msg_enabled[11]) ; else fprintf
+#define debugging_comm debug_msg_enabled[11]
 #else
 #ifdef DEBUG_COMM
 #define dprintf_comm fprintf
@@ -665,8 +713,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_cursor if(!debug_msg_enabled[11]) ; else fprintf
-#define debugging_cursor debug_msg_enabled[11]
+#define dprintf_cursor if(!debug_msg_enabled[12]) ; else fprintf
+#define debugging_cursor debug_msg_enabled[12]
 #else
 #ifdef DEBUG_CURSOR
 #define dprintf_cursor fprintf
@@ -678,8 +726,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_dc if(!debug_msg_enabled[12]) ; else fprintf
-#define debugging_dc debug_msg_enabled[12]
+#define dprintf_dc if(!debug_msg_enabled[13]) ; else fprintf
+#define debugging_dc debug_msg_enabled[13]
 #else
 #ifdef DEBUG_DC
 #define dprintf_dc fprintf
@@ -691,8 +739,21 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_dialog if(!debug_msg_enabled[13]) ; else fprintf
-#define debugging_dialog debug_msg_enabled[13]
+#define dprintf_dde if(!debug_msg_enabled[14]) ; else fprintf
+#define debugging_dde debug_msg_enabled[14]
+#else
+#ifdef DEBUG_DDE
+#define dprintf_dde fprintf
+#define debugging_dde 1
+#else
+#define dprintf_dde while(0) fprintf
+#define debugging_dde 0
+#endif
+#endif
+
+#ifdef DEBUG_RUNTIME
+#define dprintf_dialog if(!debug_msg_enabled[15]) ; else fprintf
+#define debugging_dialog debug_msg_enabled[15]
 #else
 #ifdef DEBUG_DIALOG
 #define dprintf_dialog fprintf
@@ -704,8 +765,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_dll if(!debug_msg_enabled[14]) ; else fprintf
-#define debugging_dll debug_msg_enabled[14]
+#define dprintf_dll if(!debug_msg_enabled[16]) ; else fprintf
+#define debugging_dll debug_msg_enabled[16]
 #else
 #ifdef DEBUG_DLL
 #define dprintf_dll fprintf
@@ -717,8 +778,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_dosfs if(!debug_msg_enabled[15]) ; else fprintf
-#define debugging_dosfs debug_msg_enabled[15]
+#define dprintf_dosfs if(!debug_msg_enabled[17]) ; else fprintf
+#define debugging_dosfs debug_msg_enabled[17]
 #else
 #ifdef DEBUG_DOSFS
 #define dprintf_dosfs fprintf
@@ -730,8 +791,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_driver if(!debug_msg_enabled[16]) ; else fprintf
-#define debugging_driver debug_msg_enabled[16]
+#define dprintf_driver if(!debug_msg_enabled[18]) ; else fprintf
+#define debugging_driver debug_msg_enabled[18]
 #else
 #ifdef DEBUG_DRIVER
 #define dprintf_driver fprintf
@@ -743,8 +804,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_edit if(!debug_msg_enabled[17]) ; else fprintf
-#define debugging_edit debug_msg_enabled[17]
+#define dprintf_edit if(!debug_msg_enabled[19]) ; else fprintf
+#define debugging_edit debug_msg_enabled[19]
 #else
 #ifdef DEBUG_EDIT
 #define dprintf_edit fprintf
@@ -756,8 +817,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_enum if(!debug_msg_enabled[18]) ; else fprintf
-#define debugging_enum debug_msg_enabled[18]
+#define dprintf_enum if(!debug_msg_enabled[20]) ; else fprintf
+#define debugging_enum debug_msg_enabled[20]
 #else
 #ifdef DEBUG_ENUM
 #define dprintf_enum fprintf
@@ -769,8 +830,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_event if(!debug_msg_enabled[19]) ; else fprintf
-#define debugging_event debug_msg_enabled[19]
+#define dprintf_event if(!debug_msg_enabled[21]) ; else fprintf
+#define debugging_event debug_msg_enabled[21]
 #else
 #ifdef DEBUG_EVENT
 #define dprintf_event fprintf
@@ -782,8 +843,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_exec if(!debug_msg_enabled[20]) ; else fprintf
-#define debugging_exec debug_msg_enabled[20]
+#define dprintf_exec if(!debug_msg_enabled[22]) ; else fprintf
+#define debugging_exec debug_msg_enabled[22]
 #else
 #ifdef DEBUG_EXEC
 #define dprintf_exec fprintf
@@ -795,8 +856,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_file if(!debug_msg_enabled[21]) ; else fprintf
-#define debugging_file debug_msg_enabled[21]
+#define dprintf_file if(!debug_msg_enabled[23]) ; else fprintf
+#define debugging_file debug_msg_enabled[23]
 #else
 #ifdef DEBUG_FILE
 #define dprintf_file fprintf
@@ -808,8 +869,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_fixup if(!debug_msg_enabled[22]) ; else fprintf
-#define debugging_fixup debug_msg_enabled[22]
+#define dprintf_fixup if(!debug_msg_enabled[24]) ; else fprintf
+#define debugging_fixup debug_msg_enabled[24]
 #else
 #ifdef DEBUG_FIXUP
 #define dprintf_fixup fprintf
@@ -821,8 +882,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_font if(!debug_msg_enabled[23]) ; else fprintf
-#define debugging_font debug_msg_enabled[23]
+#define dprintf_font if(!debug_msg_enabled[25]) ; else fprintf
+#define debugging_font debug_msg_enabled[25]
 #else
 #ifdef DEBUG_FONT
 #define dprintf_font fprintf
@@ -834,8 +895,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_gdi if(!debug_msg_enabled[24]) ; else fprintf
-#define debugging_gdi debug_msg_enabled[24]
+#define dprintf_gdi if(!debug_msg_enabled[26]) ; else fprintf
+#define debugging_gdi debug_msg_enabled[26]
 #else
 #ifdef DEBUG_GDI
 #define dprintf_gdi fprintf
@@ -847,8 +908,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_global if(!debug_msg_enabled[25]) ; else fprintf
-#define debugging_global debug_msg_enabled[25]
+#define dprintf_global if(!debug_msg_enabled[27]) ; else fprintf
+#define debugging_global debug_msg_enabled[27]
 #else
 #ifdef DEBUG_GLOBAL
 #define dprintf_global fprintf
@@ -860,8 +921,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_graphics if(!debug_msg_enabled[26]) ; else fprintf
-#define debugging_graphics debug_msg_enabled[26]
+#define dprintf_graphics if(!debug_msg_enabled[28]) ; else fprintf
+#define debugging_graphics debug_msg_enabled[28]
 #else
 #ifdef DEBUG_GRAPHICS
 #define dprintf_graphics fprintf
@@ -873,8 +934,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_icon if(!debug_msg_enabled[27]) ; else fprintf
-#define debugging_icon debug_msg_enabled[27]
+#define dprintf_icon if(!debug_msg_enabled[29]) ; else fprintf
+#define debugging_icon debug_msg_enabled[29]
 #else
 #ifdef DEBUG_ICON
 #define dprintf_icon fprintf
@@ -886,8 +947,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_int if(!debug_msg_enabled[28]) ; else fprintf
-#define debugging_int debug_msg_enabled[28]
+#define dprintf_int if(!debug_msg_enabled[30]) ; else fprintf
+#define debugging_int debug_msg_enabled[30]
 #else
 #ifdef DEBUG_INT
 #define dprintf_int fprintf
@@ -899,8 +960,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_key if(!debug_msg_enabled[29]) ; else fprintf
-#define debugging_key debug_msg_enabled[29]
+#define dprintf_key if(!debug_msg_enabled[31]) ; else fprintf
+#define debugging_key debug_msg_enabled[31]
 #else
 #ifdef DEBUG_KEY
 #define dprintf_key fprintf
@@ -912,8 +973,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_keyboard if(!debug_msg_enabled[30]) ; else fprintf
-#define debugging_keyboard debug_msg_enabled[30]
+#define dprintf_keyboard if(!debug_msg_enabled[32]) ; else fprintf
+#define debugging_keyboard debug_msg_enabled[32]
 #else
 #ifdef DEBUG_KEYBOARD
 #define dprintf_keyboard fprintf
@@ -925,8 +986,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_ldt if(!debug_msg_enabled[31]) ; else fprintf
-#define debugging_ldt debug_msg_enabled[31]
+#define dprintf_ldt if(!debug_msg_enabled[33]) ; else fprintf
+#define debugging_ldt debug_msg_enabled[33]
 #else
 #ifdef DEBUG_LDT
 #define dprintf_ldt fprintf
@@ -938,8 +999,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_listbox if(!debug_msg_enabled[32]) ; else fprintf
-#define debugging_listbox debug_msg_enabled[32]
+#define dprintf_listbox if(!debug_msg_enabled[34]) ; else fprintf
+#define debugging_listbox debug_msg_enabled[34]
 #else
 #ifdef DEBUG_LISTBOX
 #define dprintf_listbox fprintf
@@ -951,8 +1012,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_local if(!debug_msg_enabled[33]) ; else fprintf
-#define debugging_local debug_msg_enabled[33]
+#define dprintf_local if(!debug_msg_enabled[35]) ; else fprintf
+#define debugging_local debug_msg_enabled[35]
 #else
 #ifdef DEBUG_LOCAL
 #define dprintf_local fprintf
@@ -964,8 +1025,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_malloc if(!debug_msg_enabled[34]) ; else fprintf
-#define debugging_malloc debug_msg_enabled[34]
+#define dprintf_malloc if(!debug_msg_enabled[36]) ; else fprintf
+#define debugging_malloc debug_msg_enabled[36]
 #else
 #ifdef DEBUG_MALLOC
 #define dprintf_malloc fprintf
@@ -977,8 +1038,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mci if(!debug_msg_enabled[35]) ; else fprintf
-#define debugging_mci debug_msg_enabled[35]
+#define dprintf_mci if(!debug_msg_enabled[37]) ; else fprintf
+#define debugging_mci debug_msg_enabled[37]
 #else
 #ifdef DEBUG_MCI
 #define dprintf_mci fprintf
@@ -990,8 +1051,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mcianim if(!debug_msg_enabled[36]) ; else fprintf
-#define debugging_mcianim debug_msg_enabled[36]
+#define dprintf_mcianim if(!debug_msg_enabled[38]) ; else fprintf
+#define debugging_mcianim debug_msg_enabled[38]
 #else
 #ifdef DEBUG_MCIANIM
 #define dprintf_mcianim fprintf
@@ -1003,8 +1064,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mciwave if(!debug_msg_enabled[37]) ; else fprintf
-#define debugging_mciwave debug_msg_enabled[37]
+#define dprintf_mciwave if(!debug_msg_enabled[39]) ; else fprintf
+#define debugging_mciwave debug_msg_enabled[39]
 #else
 #ifdef DEBUG_MCIWAVE
 #define dprintf_mciwave fprintf
@@ -1016,8 +1077,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mdi if(!debug_msg_enabled[38]) ; else fprintf
-#define debugging_mdi debug_msg_enabled[38]
+#define dprintf_mdi if(!debug_msg_enabled[40]) ; else fprintf
+#define debugging_mdi debug_msg_enabled[40]
 #else
 #ifdef DEBUG_MDI
 #define dprintf_mdi fprintf
@@ -1029,8 +1090,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_menu if(!debug_msg_enabled[39]) ; else fprintf
-#define debugging_menu debug_msg_enabled[39]
+#define dprintf_menu if(!debug_msg_enabled[41]) ; else fprintf
+#define debugging_menu debug_msg_enabled[41]
 #else
 #ifdef DEBUG_MENU
 #define dprintf_menu fprintf
@@ -1042,8 +1103,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_menucalc if(!debug_msg_enabled[40]) ; else fprintf
-#define debugging_menucalc debug_msg_enabled[40]
+#define dprintf_menucalc if(!debug_msg_enabled[42]) ; else fprintf
+#define debugging_menucalc debug_msg_enabled[42]
 #else
 #ifdef DEBUG_MENUCALC
 #define dprintf_menucalc fprintf
@@ -1055,8 +1116,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_message if(!debug_msg_enabled[41]) ; else fprintf
-#define debugging_message debug_msg_enabled[41]
+#define dprintf_message if(!debug_msg_enabled[43]) ; else fprintf
+#define debugging_message debug_msg_enabled[43]
 #else
 #ifdef DEBUG_MESSAGE
 #define dprintf_message fprintf
@@ -1068,8 +1129,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_metafile if(!debug_msg_enabled[42]) ; else fprintf
-#define debugging_metafile debug_msg_enabled[42]
+#define dprintf_metafile if(!debug_msg_enabled[44]) ; else fprintf
+#define debugging_metafile debug_msg_enabled[44]
 #else
 #ifdef DEBUG_METAFILE
 #define dprintf_metafile fprintf
@@ -1081,8 +1142,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_midi if(!debug_msg_enabled[43]) ; else fprintf
-#define debugging_midi debug_msg_enabled[43]
+#define dprintf_midi if(!debug_msg_enabled[45]) ; else fprintf
+#define debugging_midi debug_msg_enabled[45]
 #else
 #ifdef DEBUG_MIDI
 #define dprintf_midi fprintf
@@ -1094,8 +1155,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mmio if(!debug_msg_enabled[44]) ; else fprintf
-#define debugging_mmio debug_msg_enabled[44]
+#define dprintf_mmio if(!debug_msg_enabled[46]) ; else fprintf
+#define debugging_mmio debug_msg_enabled[46]
 #else
 #ifdef DEBUG_MMIO
 #define dprintf_mmio fprintf
@@ -1107,8 +1168,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mmsys if(!debug_msg_enabled[45]) ; else fprintf
-#define debugging_mmsys debug_msg_enabled[45]
+#define dprintf_mmsys if(!debug_msg_enabled[47]) ; else fprintf
+#define debugging_mmsys debug_msg_enabled[47]
 #else
 #ifdef DEBUG_MMSYS
 #define dprintf_mmsys fprintf
@@ -1120,8 +1181,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mmtime if(!debug_msg_enabled[46]) ; else fprintf
-#define debugging_mmtime debug_msg_enabled[46]
+#define dprintf_mmtime if(!debug_msg_enabled[48]) ; else fprintf
+#define debugging_mmtime debug_msg_enabled[48]
 #else
 #ifdef DEBUG_MMTIME
 #define dprintf_mmtime fprintf
@@ -1133,8 +1194,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_module if(!debug_msg_enabled[47]) ; else fprintf
-#define debugging_module debug_msg_enabled[47]
+#define dprintf_module if(!debug_msg_enabled[49]) ; else fprintf
+#define debugging_module debug_msg_enabled[49]
 #else
 #ifdef DEBUG_MODULE
 #define dprintf_module fprintf
@@ -1146,8 +1207,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_msg if(!debug_msg_enabled[48]) ; else fprintf
-#define debugging_msg debug_msg_enabled[48]
+#define dprintf_msg if(!debug_msg_enabled[50]) ; else fprintf
+#define debugging_msg debug_msg_enabled[50]
 #else
 #ifdef DEBUG_MSG
 #define dprintf_msg fprintf
@@ -1159,8 +1220,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_nonclient if(!debug_msg_enabled[49]) ; else fprintf
-#define debugging_nonclient debug_msg_enabled[49]
+#define dprintf_nonclient if(!debug_msg_enabled[51]) ; else fprintf
+#define debugging_nonclient debug_msg_enabled[51]
 #else
 #ifdef DEBUG_NONCLIENT
 #define dprintf_nonclient fprintf
@@ -1172,8 +1233,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_ole if(!debug_msg_enabled[50]) ; else fprintf
-#define debugging_ole debug_msg_enabled[50]
+#define dprintf_ole if(!debug_msg_enabled[52]) ; else fprintf
+#define debugging_ole debug_msg_enabled[52]
 #else
 #ifdef DEBUG_OLE
 #define dprintf_ole fprintf
@@ -1185,8 +1246,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_palette if(!debug_msg_enabled[51]) ; else fprintf
-#define debugging_palette debug_msg_enabled[51]
+#define dprintf_palette if(!debug_msg_enabled[53]) ; else fprintf
+#define debugging_palette debug_msg_enabled[53]
 #else
 #ifdef DEBUG_PALETTE
 #define dprintf_palette fprintf
@@ -1198,8 +1259,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_profile if(!debug_msg_enabled[52]) ; else fprintf
-#define debugging_profile debug_msg_enabled[52]
+#define dprintf_profile if(!debug_msg_enabled[54]) ; else fprintf
+#define debugging_profile debug_msg_enabled[54]
 #else
 #ifdef DEBUG_PROFILE
 #define dprintf_profile fprintf
@@ -1211,8 +1272,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_prop if(!debug_msg_enabled[53]) ; else fprintf
-#define debugging_prop debug_msg_enabled[53]
+#define dprintf_prop if(!debug_msg_enabled[55]) ; else fprintf
+#define debugging_prop debug_msg_enabled[55]
 #else
 #ifdef DEBUG_PROP
 #define dprintf_prop fprintf
@@ -1224,8 +1285,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_reg if(!debug_msg_enabled[54]) ; else fprintf
-#define debugging_reg debug_msg_enabled[54]
+#define dprintf_reg if(!debug_msg_enabled[56]) ; else fprintf
+#define debugging_reg debug_msg_enabled[56]
 #else
 #ifdef DEBUG_REG
 #define dprintf_reg fprintf
@@ -1237,8 +1298,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_region if(!debug_msg_enabled[55]) ; else fprintf
-#define debugging_region debug_msg_enabled[55]
+#define dprintf_region if(!debug_msg_enabled[57]) ; else fprintf
+#define debugging_region debug_msg_enabled[57]
 #else
 #ifdef DEBUG_REGION
 #define dprintf_region fprintf
@@ -1250,8 +1311,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_relay if(!debug_msg_enabled[56]) ; else fprintf
-#define debugging_relay debug_msg_enabled[56]
+#define dprintf_relay if(!debug_msg_enabled[58]) ; else fprintf
+#define debugging_relay debug_msg_enabled[58]
 #else
 #ifdef DEBUG_RELAY
 #define dprintf_relay fprintf
@@ -1263,8 +1324,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_resource if(!debug_msg_enabled[57]) ; else fprintf
-#define debugging_resource debug_msg_enabled[57]
+#define dprintf_resource if(!debug_msg_enabled[59]) ; else fprintf
+#define debugging_resource debug_msg_enabled[59]
 #else
 #ifdef DEBUG_RESOURCE
 #define dprintf_resource fprintf
@@ -1276,8 +1337,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_scroll if(!debug_msg_enabled[58]) ; else fprintf
-#define debugging_scroll debug_msg_enabled[58]
+#define dprintf_scroll if(!debug_msg_enabled[60]) ; else fprintf
+#define debugging_scroll debug_msg_enabled[60]
 #else
 #ifdef DEBUG_SCROLL
 #define dprintf_scroll fprintf
@@ -1289,8 +1350,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_selector if(!debug_msg_enabled[59]) ; else fprintf
-#define debugging_selector debug_msg_enabled[59]
+#define dprintf_selector if(!debug_msg_enabled[61]) ; else fprintf
+#define debugging_selector debug_msg_enabled[61]
 #else
 #ifdef DEBUG_SELECTOR
 #define dprintf_selector fprintf
@@ -1302,8 +1363,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_selectors if(!debug_msg_enabled[60]) ; else fprintf
-#define debugging_selectors debug_msg_enabled[60]
+#define dprintf_selectors if(!debug_msg_enabled[62]) ; else fprintf
+#define debugging_selectors debug_msg_enabled[62]
 #else
 #ifdef DEBUG_SELECTORS
 #define dprintf_selectors fprintf
@@ -1315,8 +1376,47 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_stress if(!debug_msg_enabled[61]) ; else fprintf
-#define debugging_stress debug_msg_enabled[61]
+#define dprintf_sem if(!debug_msg_enabled[63]) ; else fprintf
+#define debugging_sem debug_msg_enabled[63]
+#else
+#ifdef DEBUG_SEM
+#define dprintf_sem fprintf
+#define debugging_sem 1
+#else
+#define dprintf_sem while(0) fprintf
+#define debugging_sem 0
+#endif
+#endif
+
+#ifdef DEBUG_RUNTIME
+#define dprintf_shm if(!debug_msg_enabled[64]) ; else fprintf
+#define debugging_shm debug_msg_enabled[64]
+#else
+#ifdef DEBUG_SHM
+#define dprintf_shm fprintf
+#define debugging_shm 1
+#else
+#define dprintf_shm while(0) fprintf
+#define debugging_shm 0
+#endif
+#endif
+
+#ifdef DEBUG_RUNTIME
+#define dprintf_spy if(!debug_msg_enabled[65]) ; else fprintf
+#define debugging_spy debug_msg_enabled[65]
+#else
+#ifdef DEBUG_SPY
+#define dprintf_spy fprintf
+#define debugging_spy 1
+#else
+#define dprintf_spy while(0) fprintf
+#define debugging_spy 0
+#endif
+#endif
+
+#ifdef DEBUG_RUNTIME
+#define dprintf_stress if(!debug_msg_enabled[66]) ; else fprintf
+#define debugging_stress debug_msg_enabled[66]
 #else
 #ifdef DEBUG_STRESS
 #define dprintf_stress fprintf
@@ -1328,8 +1428,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_syscolor if(!debug_msg_enabled[62]) ; else fprintf
-#define debugging_syscolor debug_msg_enabled[62]
+#define dprintf_syscolor if(!debug_msg_enabled[67]) ; else fprintf
+#define debugging_syscolor debug_msg_enabled[67]
 #else
 #ifdef DEBUG_SYSCOLOR
 #define dprintf_syscolor fprintf
@@ -1341,8 +1441,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_task if(!debug_msg_enabled[63]) ; else fprintf
-#define debugging_task debug_msg_enabled[63]
+#define dprintf_task if(!debug_msg_enabled[68]) ; else fprintf
+#define debugging_task debug_msg_enabled[68]
 #else
 #ifdef DEBUG_TASK
 #define dprintf_task fprintf
@@ -1354,8 +1454,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_text if(!debug_msg_enabled[64]) ; else fprintf
-#define debugging_text debug_msg_enabled[64]
+#define dprintf_text if(!debug_msg_enabled[69]) ; else fprintf
+#define debugging_text debug_msg_enabled[69]
 #else
 #ifdef DEBUG_TEXT
 #define dprintf_text fprintf
@@ -1367,8 +1467,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_timer if(!debug_msg_enabled[65]) ; else fprintf
-#define debugging_timer debug_msg_enabled[65]
+#define dprintf_timer if(!debug_msg_enabled[70]) ; else fprintf
+#define debugging_timer debug_msg_enabled[70]
 #else
 #ifdef DEBUG_TIMER
 #define dprintf_timer fprintf
@@ -1380,8 +1480,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_toolhelp if(!debug_msg_enabled[66]) ; else fprintf
-#define debugging_toolhelp debug_msg_enabled[66]
+#define dprintf_toolhelp if(!debug_msg_enabled[71]) ; else fprintf
+#define debugging_toolhelp debug_msg_enabled[71]
 #else
 #ifdef DEBUG_TOOLHELP
 #define dprintf_toolhelp fprintf
@@ -1393,8 +1493,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_utility if(!debug_msg_enabled[67]) ; else fprintf
-#define debugging_utility debug_msg_enabled[67]
+#define dprintf_utility if(!debug_msg_enabled[72]) ; else fprintf
+#define debugging_utility debug_msg_enabled[72]
 #else
 #ifdef DEBUG_UTILITY
 #define dprintf_utility fprintf
@@ -1406,8 +1506,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_win if(!debug_msg_enabled[68]) ; else fprintf
-#define debugging_win debug_msg_enabled[68]
+#define dprintf_win if(!debug_msg_enabled[73]) ; else fprintf
+#define debugging_win debug_msg_enabled[73]
 #else
 #ifdef DEBUG_WIN
 #define dprintf_win fprintf
@@ -1419,8 +1519,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_winsock if(!debug_msg_enabled[69]) ; else fprintf
-#define debugging_winsock debug_msg_enabled[69]
+#define dprintf_winsock if(!debug_msg_enabled[74]) ; else fprintf
+#define debugging_winsock debug_msg_enabled[74]
 #else
 #ifdef DEBUG_WINSOCK
 #define dprintf_winsock fprintf
@@ -1436,6 +1536,7 @@
 #ifdef DEBUG_DEFINE_VARIABLES
 static char *debug_msg_name[] = {
     "accel",
+    "atom",
     "bitblt",
     "bitmap",
     "caret",
@@ -1448,6 +1549,7 @@
     "comm",
     "cursor",
     "dc",
+    "dde",
     "dialog",
     "dll",
     "dosfs",
@@ -1496,6 +1598,9 @@
     "scroll",
     "selector",
     "selectors",
+    "sem",
+    "shm",
+    "spy",
     "stress",
     "syscolor",
     "task",
diff --git a/include/dos_fs.h b/include/dos_fs.h
index 01a458c..a6a91a3 100644
--- a/include/dos_fs.h
+++ b/include/dos_fs.h
@@ -10,10 +10,9 @@
 extern void DOS_SetDefaultDrive(int drive);
 extern void ToUnix(char *s); 
 extern void ToDos(char *s); 
-extern void ChopOffSlash(char *string);
 extern int DOS_DisableDrive(int drive);
 extern int DOS_EnableDrive(int drive); 
-extern char *DOS_GetUnixFileName(char *dosfilename);
+extern char *DOS_GetUnixFileName(const char *dosfilename);
 extern char *DOS_GetDosFileName(char *unixfilename);
 extern char *DOS_GetCurrentDir(int drive);
 extern int DOS_ChangeDir(int drive, char *dirname);
@@ -29,8 +28,6 @@
 extern struct dosdirent *DOS_opendir(char *dosdirname); 
 extern struct dosdirent *DOS_readdir(struct dosdirent *de);
 extern void DOS_closedir(struct dosdirent *de);
-extern void DOS_ExpandToFullPath(char *filename, int drive);
-extern void DOS_ExpandToFullUnixPath(char *filename);
 extern char *DOS_GetRedirectedDir(int drive);
 extern void errno_to_doserr(void);
 
diff --git a/include/global.h b/include/global.h
index dd912ce..6ea7b40 100644
--- a/include/global.h
+++ b/include/global.h
@@ -9,9 +9,17 @@
 
 #include "wintypes.h"
 
+typedef struct
+{
+    HGLOBAL handle;
+    WORD sel;
+    int shmid;
+} SHMDATA;
+
 extern HGLOBAL GLOBAL_CreateBlock( WORD flags, void *ptr, DWORD size,
                                    HGLOBAL hOwner, BOOL isCode,
-                                   BOOL is32Bit, BOOL isReadOnly );
+                                   BOOL is32Bit, BOOL isReadOnly,
+				   SHMDATA *shmdata);
 extern BOOL GLOBAL_FreeBlock( HGLOBAL handle );
 extern HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
                              BOOL isCode, BOOL is32Bit, BOOL isReadOnly );
diff --git a/include/ldt.h b/include/ldt.h
index 6e7c853..76f9ca0 100644
--- a/include/ldt.h
+++ b/include/ldt.h
@@ -44,13 +44,13 @@
 
 extern ldt_copy_entry ldt_copy[LDT_SIZE];
 
-#define __AHSHIFT  3
+#define __AHSHIFT  3  /* don't change! */
 #define __AHINCR   (1 << __AHSHIFT)
 
 #ifndef WINELIB
 #define SELECTOR_TO_ENTRY(sel)  (((int)(sel) & 0xffff) >> __AHSHIFT)
 #define ENTRY_TO_SELECTOR(i)    ((i) ? (((int)(i) << __AHSHIFT) | 7) : 0)
-#define IS_LDT_ENTRY_FREE(i)    (!(ldt_copy[(i)].base || ldt_copy[(i)].limit))
+#define IS_LDT_ENTRY_FREE(i)    (!(ldt_flags_copy[(i)] & LDT_FLAGS_ALLOCATED))
 #define IS_SELECTOR_FREE(sel)   (IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel)))
 #define GET_SEL_BASE(sel)       (ldt_copy[SELECTOR_TO_ENTRY(sel)].base)
 #define GET_SEL_LIMIT(sel)      (ldt_copy[SELECTOR_TO_ENTRY(sel)].limit)
@@ -59,6 +59,7 @@
 #define SELECTOR_TO_ENTRY(sel)  error.error
 #define ENTRY_TO_SELECTOR(i)    error.error
 #define IS_LDT_ENTRY_FREE(i)    error.error
+#define IS_SELECTOR_FREE(sel)   error.error
 #define GET_SEL_BASE(sel)       error.error
 #define GET_SEL_LIMIT(sel)      error.error
 #endif
@@ -83,6 +84,7 @@
 #define LDT_FLAGS_EXECONLY  0x04  /* Segment is execute-only (code) */
 #define LDT_FLAGS_32BIT     0x08  /* Segment is 32-bit (code or stack) */
 #define LDT_FLAGS_BIG       0x10  /* Segment is big (limit is in pages) */
+#define LDT_FLAGS_ALLOCATED 0x80  /* Segment is allocated (no longer free) */
 
 #define GET_SEL_FLAGS(sel)   (ldt_flags_copy[SELECTOR_TO_ENTRY(sel)])
 
diff --git a/include/miscemu.h b/include/miscemu.h
index e979ff1..2507a80 100644
--- a/include/miscemu.h
+++ b/include/miscemu.h
@@ -4,31 +4,10 @@
 #include "wintypes.h"
 #include "wine.h"
 
-extern BOOL INSTR_HandleInstruction( struct sigcontext_struct *context );
+extern BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context );
 
-extern int do_int10(struct sigcontext_struct *);
-extern int do_int13(struct sigcontext_struct *);
-extern int do_int15(struct sigcontext_struct *);
-extern int do_int16(struct sigcontext_struct *);
-extern int do_int1a(struct sigcontext_struct *);
-extern int do_int21(struct sigcontext_struct *);
-extern int do_int25(struct sigcontext_struct *);
-extern int do_int26(struct sigcontext_struct *);
-extern int do_int2a(struct sigcontext_struct *);
-extern int do_int2f(struct sigcontext_struct *);
-extern int do_int31(struct sigcontext_struct *);
-extern int do_int5c(struct sigcontext_struct *);
-
-extern void inportb( struct sigcontext_struct *context );
-extern void inport( struct sigcontext_struct *context, int long_op );
-extern void outportb( struct sigcontext_struct *context );
-extern void outport( struct sigcontext_struct *context, int long_op );
-extern void inportb_abs( struct sigcontext_struct *context);
-extern void inport_abs( struct sigcontext_struct *context, int long_op );
-extern void outportb_abs( struct sigcontext_struct *context );
-extern void outport_abs( struct sigcontext_struct *context, int long_op );
-
-extern void IntBarf(int i, struct sigcontext_struct *context);
+extern DWORD inport( int port, int count );
+extern void outport( int port, int count, DWORD value );
 
 extern BOOL INT_Init(void);
 extern SEGPTR INT_GetHandler( BYTE intnum );
@@ -36,4 +15,11 @@
 
 extern void INT21_Init(void);
 
+
+#define INT_BARF(num) \
+    fprintf( stderr, "int%x: unknown/not implemented parameters:\n" \
+                     "int%x: AX %04x, BX %04x, CX %04x, DX %04x, " \
+                     "SI %04x, DI %04x, DS %04x, ES %04x\n", \
+             (num), (num), AX, BX, CX, DX, SI, DI, DS, ES )
+
 #endif /* __WINE_MISCEMU_H */
diff --git a/include/msdos.h b/include/msdos.h
index 1a94bca..636ae22 100644
--- a/include/msdos.h
+++ b/include/msdos.h
@@ -40,21 +40,23 @@
 extern struct DosDeviceStruct COM[MAX_PORTS];
 extern struct DosDeviceStruct LPT[MAX_PORTS];
 
-#define setword(a,b)	*(BYTE*)(a)	  = (b) & 0xff; \
-			*((BYTE*)((a)+1)) = ((b)>>8) & 0xff;
+#define setword(a,b)	do { *(BYTE*)(a)	  = (b) & 0xff; \
+                             *((BYTE*)((a)+1)) = ((b)>>8) & 0xff;\
+                        } while(0)
 			
-#define setdword(a,b)	*(BYTE*)(a)	= (b) & 0xff; \
-			*((BYTE*)(a)+1) = ((b)>>8) & 0xff; \
-			*((BYTE*)(a)+2) = ((b)>>16) & 0xff; \
-			*((BYTE*)(a)+3) = ((b)>>24) & 0xff;
+#define setdword(a,b)	do { *(BYTE*)(a)	= (b) & 0xff; \
+			     *((BYTE*)(a)+1) = ((b)>>8) & 0xff; \
+			     *((BYTE*)(a)+2) = ((b)>>16) & 0xff; \
+			     *((BYTE*)(a)+3) = ((b)>>24) & 0xff; \
+                        } while(0)
 
-#define getword(a)	(WORD) *(BYTE*)(a) + \
-			(*((BYTE*)(a) + 1) << 8)
+#define getword(a)	( (WORD)*(BYTE*)(a) + \
+			  ((WORD)*((BYTE*)(a) + 1) << 8))
 
-#define getdword(a)	(DWORD) (*(BYTE*)(a) + \
-			(*((BYTE*)(a) + 1) << 8) + \
-			(*((BYTE*)(a) + 2) << 16) + \
-			(*((BYTE*)(a) + 3) << 24))
+#define getdword(a)	( (DWORD)*(BYTE*)(a) + \
+			  (DWORD)(*((BYTE*)(a) + 1) << 8) + \
+			  (DWORD)(*((BYTE*)(a) + 2) << 16) + \
+			  (DWORD)(*((BYTE*)(a) + 3) << 24))
 
 /* dos file attributes */
 
diff --git a/include/options.h b/include/options.h
index 80b8a73..a19ae57 100644
--- a/include/options.h
+++ b/include/options.h
@@ -9,7 +9,6 @@
 
 struct options
 {
-    char * spyFilename;
     char * desktopGeometry; /* NULL when no desktop */
     char * programName;     /* To use when loading resources */
     int    usePrivateMap;
diff --git a/include/pe_image.h b/include/pe_image.h
index d7fceee..169ddd8 100644
--- a/include/pe_image.h
+++ b/include/pe_image.h
@@ -1,6 +1,7 @@
 #ifndef __WINE_PE_IMAGE_H
 #define __WINE_PE_IMAGE_H
 
+extern void *RELAY32_GetEntryPoint(char *dll_name, char *item, int hint);
 extern int PE_unloadImage(struct w_files *wpnt);
 extern int PE_StartProgram(struct w_files *wpnt);
 extern void PE_InitDLL(struct w_files *wpnt);
diff --git a/include/prototypes.h b/include/prototypes.h
deleted file mode 100644
index 5c8d64d..0000000
--- a/include/prototypes.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* $Id: prototypes.h,v 1.3 1993/07/04 04:04:21 root Exp root $
- */
-/*
- * Copyright  Robert J. Amstadt, 1993
- */
-#ifndef _WINE_PROTOTYPES_H
-#define _WINE_PROTOTYPES_H
-
-#include <sys/types.h>
-
-#include "windows.h"
-
-#ifndef WINELIB
-
-/* loader/resource.c */
-
-extern HBITMAP ConvertCoreBitmap( HDC hdc, BITMAPCOREHEADER * image );
-extern HBITMAP ConvertInfoBitmap( HDC hdc, BITMAPINFO * image );
-
-/* loader/signal.c */
-
-extern void init_wine_signals(void);
-
-/* loader/wine.c */
-
-extern int _WinMain(int argc, char **argv);
-
-/* misc/spy.c */
-
-extern void SpyInit(void);
-
-#endif /* WINELIB */
-#endif /* _WINE_PROTOTYPES_H */
diff --git a/include/region.h b/include/region.h
index 7d87c13..e8f6261 100644
--- a/include/region.h
+++ b/include/region.h
@@ -18,5 +18,6 @@
 
 
 extern BOOL REGION_DeleteObject( HRGN hrgn, RGNOBJ * obj );
+extern BOOL REGION_FrameRgn(HRGN dest,HRGN src,int x,int y);
 
 #endif  /* __WINE_REGION_H */
diff --git a/include/registers.h b/include/registers.h
index 4af04bc..e6253f3 100644
--- a/include/registers.h
+++ b/include/registers.h
@@ -37,6 +37,14 @@
 #define ES (context->sc_es)
 #define SS (context->sc_ss)
 
+#ifdef linux
+#define FS (context->sc_fs)
+#define GS (context->sc_gs)
+#else  /* FIXME: are fs and gs supported under *BSD? */
+#define FS  0
+#define GS  0
+#endif
+
 #ifndef __FreeBSD__
 #define EFL (context->sc_eflags)
 #define FL (*(WORD*)&context->sc_eflags)
diff --git a/include/resource.h b/include/resource.h
index d389ce4..6a5eeb2 100644
--- a/include/resource.h
+++ b/include/resource.h
@@ -17,6 +17,9 @@
 extern HGLOBAL NE_AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size );
 extern HGLOBAL NE_LoadResource( HMODULE hModule,  HRSRC hRsrc );
 
+extern HBITMAP ConvertCoreBitmap( HDC hdc, BITMAPCOREHEADER * image );
+extern HBITMAP ConvertInfoBitmap( HDC hdc, BITMAPINFO * image );
+
 struct ResourceTable
 {
         int id,type;
diff --git a/include/shell.h b/include/shell.h
index 6a30151..b222e7e 100644
--- a/include/shell.h
+++ b/include/shell.h
@@ -2,6 +2,8 @@
  * 				Shell Library definitions
  */
 
+extern INT ShellAbout(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon);
+
 #define ERROR_SUCCESS           0L
 #define ERROR_BADDB             1L
 #define ERROR_BADKEY            2L
diff --git a/include/shm_block.h b/include/shm_block.h
new file mode 100644
index 0000000..c19c84f
--- /dev/null
+++ b/include/shm_block.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      shm_block.ch
+ * Purpose:   treat a shared memory block.
+ ***************************************************************************
+ */
+#ifndef __WINE_SHM_BLOCK_H
+#define __WINE_SHM_BLOCK_H
+#include <sys/shm.h>
+#include "wintypes.h"
+#define SEGSIZE                 0x10000 /* 64 */ 
+#define SHM_GRANULARITY         SEGSIZE
+#define SHM_MINBLOCK            SHM_GRANULARITY
+#define SHM_MAXBLOCK            (((int)SHMMAX/(int)SHM_GRANULARITY)*  \
+				 SHM_GRANULARITY)
+#define PTR2REL(block,ptr) (REL_PTR) ( (char *) (ptr) - (char *) (block) )
+#define REL2PTR(block,rel) (void *) ( (char *) (block) + (rel) )
+
+typedef  int REL_PTR;
+
+/* full info for each shm block. */
+struct shm_block {
+	/* private */
+	int next_shm_id;	   /* IPC shm ID (for initial linking) */
+    
+	/* public (read only) */
+	int size;		   /* size of the shm block */
+	int free;		   /* how much of the block is free */
+        int proc_idx;		   /* The index of the owner */
+	
+	/* public - writable for shm_fragment */
+	REL_PTR free_list;	   /* first item in the free list */
+};
+
+/* used for mapping local attachments */
+struct local_shm_map {
+	struct local_shm_map *next;
+	int shm_id;
+	int proc_idx;
+	
+	/* 32 bit pointer to the beginning of the block */
+	struct shm_block *ptr;
+};
+extern struct local_shm_map *shm_map;
+void shm_setup_block(struct shm_block *block, REL_PTR first, int size);
+
+/* shm_create_block:
+ *   allocate and setup a new block:
+ *   first - first non header byte.
+ *   size  - block size (in bytes).
+ *   shm_id- IPC shared memory ID.
+ */
+struct shm_block *shm_create_block(REL_PTR first, int size, int *shm_id);
+
+/* shm_locate_block:
+ *   locate existing block according to shm_id,
+ *   Attach the block if needed. Assume the shm_id is wine's
+ *   Set selectors also.
+ */
+struct shm_block *shm_locate_block(int shm_id, struct local_shm_map *map);
+
+/* shm_locate_attached_block: 
+ *   locate existing block according to shm_id,
+ *   Blocks are never attached.
+ * if proc_idx is not NULL, it will be set to owner's index.
+ * map - localy mapped info about block may be NULL;
+ */
+struct shm_block *shm_locate_attached_block(int shm_id, 
+					    struct local_shm_map *map);
+
+/* shm_attach_block: attach existing shm block, setup selectors
+ * shm_id - id of the block to attach.
+ * proc_idx - if not -1, puts this data into local mapping
+ * map - localy mapped info about this block. (may be NULL)
+ * NOTE: same block can be attached many times
+ */
+struct shm_block *shm_attach_block(int shm_id, int proc_idx,
+				   struct local_shm_map *map);
+
+/* delete chain of shm blocks (pointing to each other */
+void shm_delete_chain(int *shmid);
+
+#endif /* __WINE_SHM_BLOCK_H */
diff --git a/include/shm_fragment.h b/include/shm_fragment.h
new file mode 100644
index 0000000..81a4b66
--- /dev/null
+++ b/include/shm_fragment.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      shm_fragment.h
+ * Purpose:   Data fragments and free list items. Allocate and free blocks.
+ ***************************************************************************
+ */
+#ifndef __WINE_SHM_FRAGMENT_H
+#define __WINE_SHM_FRAGMENT_H
+
+#include "shm_block.h"
+
+#define NIL ((int) 0)
+/* memory fragment: used or free (when free - it's an item of "free list",
+ * when allocated it contains the data, and it's size) 
+ */
+struct shm_fragment {
+	int size;		/* fragment's size */
+	
+	/* The type of info depends on fragment's status (free/allocated) */
+	union info {		
+		int next;	/* next free fragment */
+		char data[1];	/* the data */
+	} info;
+};
+
+/* setup first item in the free list */
+void shm_FragmentInit(struct shm_block *block,REL_PTR first,int size);
+
+/* allocate shm fragment. return: offset to data in fragment, or NULL */
+REL_PTR shm_FragmentAlloc(struct shm_block *block, int size);
+
+/* like shm_FragmentAlloc, returns pointer instead of offset */
+char *shm_FragPtrAlloc(struct shm_block *block, int size);
+
+/* free shm fragment - according to offset */
+void shm_FragmentFree(struct shm_block *block, int ofs);
+
+/* free shm fragment - according to pointer */
+void shm_FragPtrFree(struct shm_block *block, void *ptr);
+
+/* This is used for debugging only */
+void shm_print_free_list(struct shm_block *block);
+
+#endif /* __WINE_SHM_FRAGMENT_H */
diff --git a/include/shm_main_blk.h b/include/shm_main_blk.h
new file mode 100644
index 0000000..e3f9e5b
--- /dev/null
+++ b/include/shm_main_blk.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      shm_main_blk.h
+ * Purpose:   Main Wine's shared memory block
+ ***************************************************************************
+ */
+#ifndef __WINE_SHM_MAIN_BLK_H
+#define __WINE_SHM_MAIN_BLK_H
+#include <sys/shm.h>
+#include "shm_block.h"
+#include "shm_semaph.h"
+#include "dde_proc.h"
+#include "dde_atom.h"
+#include "dde_mem.h"
+/*****************************************************************************
+ *
+ * main block object
+ *
+ *****************************************************************************
+ */
+#ifndef __inline__
+#ifndef __GNUC__
+#define __inline__
+#endif /* __GNUC__ */
+#endif /* __inline__ */
+
+#define DDE_HANDLES_BIT_ARRAY_SIZE (DDE_HANDLES/sizeof(int)/8)
+
+#define SHM_MAXID SHMSEG	/* maximum shm blocks (Wine's limit) */
+struct shm_main_block {
+	/* NOTE:  "block" declaration must be the first */
+	struct shm_block block;
+	char magic[64];		   /* magic string to identify the block */
+        int build_lock;		   /* =1 when data structure not stable yet */
+        shm_sem sem;		   /* semaphores for main_block integrity */
+	struct _dde_proc proc[DDE_PROCS];  /* information about processes  */
+	REL_PTR atoms[DDE_ATOMS];  /* relative reference to global atoms */
+        /* Translation from global window handles to local handles */
+        WND_DATA windows[DDE_WINDOWS];
+        DDE_HWND handles[DDE_HANDLES];
+	/* bit array stating if a handle is free (bit=0), LSB in */
+	/* free_handles[0] refers handle 0x8000, the MSB refers 0x801F */
+	unsigned free_handles[DDE_HANDLES_BIT_ARRAY_SIZE];
+};
+extern struct shm_main_block *main_block;
+int shm_init(void);
+void shm_delete_all(int shm_id);
+void DDE_mem_init();
+int DDE_no_of_attached();
+#define DDE_IPC_init()  ( (main_block==NULL) ?  (DDE_mem_init()) : 0 )
+
+#endif /* __WINE_SHM_MAIN_BLK_H */
diff --git a/include/shm_semaph.h b/include/shm_semaph.h
new file mode 100644
index 0000000..5562446
--- /dev/null
+++ b/include/shm_semaph.h
@@ -0,0 +1,24 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      shm_semaph.h
+ * Purpose:   Handle semaphores for shared memory operations.
+ ***************************************************************************
+ */
+
+#ifndef __WINE_SHM_SEMAPH_H
+#define __WINE_SHM_SEMAPH_H
+/* IMPORTANT: If possible, restrict usage of these functions. */
+
+typedef int shm_sem;
+
+void shm_read_wait(shm_sem semid);
+void shm_write_wait(shm_sem semid);
+void shm_write_signal(shm_sem semid);
+void shm_read_signal(shm_sem semid);
+void shm_sem_init(shm_sem *semptr);
+void shm_sem_done(shm_sem *semptr);
+
+#endif /* __WINE_SHM_SEMAPH_H */
diff --git a/include/stackframe.h b/include/stackframe.h
index ee0195b..81fcf8e 100644
--- a/include/stackframe.h
+++ b/include/stackframe.h
@@ -19,6 +19,7 @@
 {
     WORD    saved_ss;                /* saved previous 16-bit stack */
     WORD    saved_sp;
+    WORD    es;
     WORD    ds;                      /* 16-bit ds */
     DWORD   entry_point WINE_PACKED; /* entry point to call */
     WORD    ordinal_number;          /* ordinal number of entry point */
diff --git a/include/stddebug.h b/include/stddebug.h
index b568098..b262020 100644
--- a/include/stddebug.h
+++ b/include/stddebug.h
@@ -77,6 +77,7 @@
 
 #ifdef DEBUG_NONE
 #undef DEBUG_ACCEL
+#undef DEBUG_ATOM
 #undef DEBUG_BITBLT
 #undef DEBUG_BITMAP
 #undef DEBUG_CARET
@@ -89,6 +90,7 @@
 #undef DEBUG_COMM
 #undef DEBUG_CURSOR
 #undef DEBUG_DC
+#undef DEBUG_DDE
 #undef DEBUG_DIALOG
 #undef DEBUG_DLL
 #undef DEBUG_DOSFS
@@ -137,6 +139,9 @@
 #undef DEBUG_SCROLL
 #undef DEBUG_SELECTOR
 #undef DEBUG_SELECTORS
+#undef DEBUG_SEM
+#undef DEBUG_SHM
+#undef DEBUG_SPY
 #undef DEBUG_STRESS
 #undef DEBUG_SYSCOLOR
 #undef DEBUG_TASK
@@ -150,6 +155,7 @@
 
 #ifdef DEBUG_ALL
 #define DEBUG_ACCEL
+#define DEBUG_ATOM
 #define DEBUG_BITBLT
 #define DEBUG_BITMAP
 #define DEBUG_CARET
@@ -162,6 +168,7 @@
 #define DEBUG_COMM
 #define DEBUG_CURSOR
 #define DEBUG_DC
+#define DEBUG_DDE
 #define DEBUG_DIALOG
 #define DEBUG_DLL
 #define DEBUG_DOSFS
@@ -210,6 +217,9 @@
 #define DEBUG_SCROLL
 #define DEBUG_SELECTOR
 #define DEBUG_SELECTORS
+#define DEBUG_SEM
+#define DEBUG_SHM
+#define DEBUG_SPY
 #define DEBUG_STRESS
 #define DEBUG_SYSCOLOR
 #define DEBUG_TASK
diff --git a/include/task.h b/include/task.h
index cbd28ae..dd7e9e8 100644
--- a/include/task.h
+++ b/include/task.h
@@ -13,6 +13,10 @@
 #pragma pack(1)
 #endif
 
+
+extern BOOL TASK_Init(void);
+extern void TASK_KillCurrentTask( int exitCode );
+
   /* Process database (i.e. a normal DOS PSP) */
 
 typedef struct
diff --git a/include/user.h b/include/user.h
index f749007..dc5c68a 100644
--- a/include/user.h
+++ b/include/user.h
@@ -10,6 +10,7 @@
 #include "ldt.h"
 #include "local.h"
 
+extern BOOL USER_HeapInit(void);
 /* USER local heap */
 
 #ifdef WINELIB
diff --git a/include/win.h b/include/win.h
index e1d1efe..2322240 100644
--- a/include/win.h
+++ b/include/win.h
@@ -74,6 +74,7 @@
 extern HWND WIN_FindWinToRepaint( HWND hwnd );
 extern void WIN_SendParentNotify( HWND hwnd, WORD event, LONG lParam );
 extern BOOL WIN_CreateDesktopWindow(void);
+extern HWND WIN_GetTopParent( HWND hwnd );
 
 extern Display * display;
 extern Screen * screen;
diff --git a/include/windows.h b/include/windows.h
index 0389728..eb2f910 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -2455,6 +2455,8 @@
 Fa(DWORD,GetDCOrg,HDC,a)
 Fa(DWORD,GetFreeSpace,WORD,a)
 Fa(DWORD,GetHeapSpaces,HMODULE,a)
+Fa(DWORD,GetSelectorBase,WORD,a)
+Fa(DWORD,GetSelectorLimit,WORD,a)
 Fa(DWORD,GetViewportExt,HDC,a)
 Fa(DWORD,GetViewportOrg,HDC,a)
 Fa(DWORD,GetWindowExt,HDC,a)
@@ -2524,10 +2526,11 @@
 Fa(LPSTR,LockResource,HANDLE,a)
 Fa(SEGPTR,AnsiNext,SEGPTR,a)
 Fa(SEGPTR,GlobalWire,HGLOBAL,a)
-Fa(SEGPTR,WIN16_LockResource,HANDLE,a)
 Fa(SEGPTR,WIN16_GlobalLock,HGLOBAL,a)
+Fa(SEGPTR,WIN16_LockResource,HANDLE,a)
 Fa(UINT,GDIRealizePalette,HDC,a)
 Fa(UINT,RealizePalette,HDC,a)
+Fa(WORD,AllocCStoDSAlias,WORD,a)
 Fa(WORD,AllocDStoCSAlias,WORD,a)
 Fa(WORD,AllocSelector,WORD,a)
 Fa(WORD,AllocSelectorArray,WORD,a)
@@ -2716,6 +2719,8 @@
 Fb(WORD,SetPolyFillMode,HDC,a,WORD,b)
 Fb(WORD,SetROP2,HDC,a,WORD,b)
 Fb(WORD,SetRelAbs,HDC,a,WORD,b)
+Fb(WORD,SetSelectorBase,WORD,a,DWORD,b)
+Fb(WORD,SetSelectorLimit,WORD,a,DWORD,b)
 Fb(WORD,SetStretchBltMode,HDC,a,WORD,b)
 Fb(WORD,SetSystemPaletteUse,HDC,a,WORD,b)
 Fb(WORD,SetTextAlign,HDC,a,WORD,b)
@@ -2818,12 +2823,12 @@
 Fc(INT,OpenFile,LPSTR,a,LPOFSTRUCT,b,WORD,c)
 Fc(INT,_lread,INT,a,LPSTR,b,WORD,c)
 Fc(INT,_lwrite,INT,a,LPCSTR,b,WORD,c)
-Fc(LONG,_hread,INT,a,LPSTR,b,LONG,c)
-Fc(LONG,_hwrite,INT,a,LPCSTR,b,LONG,c)
 Fc(LONG,GetBitmapBits,HBITMAP,a,LONG,b,LPSTR,c)
 Fc(LONG,SetBitmapBits,HBITMAP,a,LONG,b,LPSTR,c)
 Fc(LONG,SetClassLong,HWND,a,short,b,LONG,c)
 Fc(LONG,SetWindowLong,HWND,a,short,b,LONG,c)
+Fc(LONG,_hread,INT,a,LPSTR,b,LONG,c)
+Fc(LONG,_hwrite,INT,a,LPCSTR,b,LONG,c)
 Fc(LONG,_llseek,INT,a,LONG,b,INT,c)
 Fc(SEGPTR,lstrcpyn,SEGPTR,a,SEGPTR,b,WORD,c)
 Fc(WORD,GetAtomName,ATOM,a,LPSTR,b,short,c)
@@ -2831,6 +2836,7 @@
 Fc(WORD,GetMenuState,HMENU,a,WORD,b,WORD,c)
 Fc(WORD,GetProfileInt,LPSTR,a,LPSTR,b,int,c)
 Fc(WORD,GlobalGetAtomName,ATOM,a,LPSTR,b,short,c)
+Fc(WORD,SelectorAccessRights,WORD,a,WORD,b,WORD,c)
 Fc(WORD,SetClassWord,HWND,a,short,b,WORD,c)
 Fc(WORD,SetWindowWord,HWND,a,short,b,WORD,c)
 Fc(int,FillRect,HDC,a,LPRECT,b,HBRUSH,c)
diff --git a/include/wineopts.h b/include/wineopts.h
deleted file mode 100644
index 6f3e66b..0000000
--- a/include/wineopts.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* WINEOPTS.H
- */
-
-#ifndef WINEOPTS_H
-#define WINEOPTS_H
-
-#include <stdio.h>
-
-FILE *SpyFp;
-
-#endif /* WINEOPTS_H */
diff --git a/include/winsock.h b/include/winsock.h
index 2a2674b..a0450c2 100644
--- a/include/winsock.h
+++ b/include/winsock.h
@@ -7,13 +7,13 @@
 #ifndef _WINSOCKAPI_
 #define _WINSOCKAPI_
 
-#include <windows.h>
 #include <sys/types.h>
 #include <sys/time.h>
 #include <fcntl.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
+#include "windows.h"
 
 /*
  * The new type to be used in all
diff --git a/ipc/Imakefile b/ipc/Imakefile
new file mode 100644
index 0000000..cf5d6df
--- /dev/null
+++ b/ipc/Imakefile
@@ -0,0 +1,33 @@
+#include "../Wine.tmpl"
+
+MODULE = ipc
+
+TEST_SRCS =  \
+          shm_fragment_test.c \
+          bit_array_test.c\
+          dde_proc_test.c \
+          dde_atom_test.c \
+          shm_semaph_test.c \
+          wine_test_stub.c \
+          hash_test.c \
+          dde_mem_test.c 
+
+SRCS =    bit_array.c \
+	  dde_atom.c  \
+	  dde_mem.c \
+          dde_proc.c  \
+          generic_hash.c \
+          shm_block.c \
+          shm_fragment.c \
+          shm_main_blk.c \
+          shm_semaph.c
+
+OBJS = $(SRCS:.c=.o)
+TEST_OBJS = $(TEST_SRCS:.c=.o)
+
+WineRelocatableTarget($(MODULE),,$(OBJS))
+DependTarget()
+
+includes::
+
+install::
diff --git a/ipc/Makefile.in b/ipc/Makefile.in
new file mode 100644
index 0000000..fea89fe
--- /dev/null
+++ b/ipc/Makefile.in
@@ -0,0 +1,57 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include
+LD	= @LD@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+
+
+MODULE 	= ipc
+
+SRCS =    bit_array.c \
+	  dde_atom.c  \
+	  dde_mem.c \
+          dde_proc.c  \
+          generic_hash.c \
+          shm_block.c \
+          shm_fragment.c \
+          shm_main_blk.c \
+          shm_semaph.c
+
+OBJS = $(SRCS:.c=.o)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
+
+all: $(MODULE).o
+
+$(MODULE).o: $(OBJS)
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dummy:
+
+### Dependencies:
diff --git a/ipc/README b/ipc/README
new file mode 100644
index 0000000..6903f53
--- /dev/null
+++ b/ipc/README
@@ -0,0 +1,8 @@
+This is a pre-alpha code, it does not work for 100%,
+but it does not break anything (I hope).
+Proper documentation (LaTeX) will be ready for the next release.
+
+You can use "ipcl" perl script to remove junk IPC stuff.
+You can use "ipcs" system program to find junk IPC stuff.
+
+Michael
diff --git a/ipc/TEST_FRAGMENT.std b/ipc/TEST_FRAGMENT.std
new file mode 100644
index 0000000..968a440
--- /dev/null
+++ b/ipc/TEST_FRAGMENT.std
@@ -0,0 +1,42 @@
+After shm_FragmentInit
+{0x0020,0xffe0}  [total free=ffe0]
+0: After shm_FragmentAlloc(block, 0x010000) == NULL
+{0x0020,0xffe0}  [total free=ffe0]
+1: After shm_FragmentAlloc(block, 0x003fdc) == 0x00c024
+{0x0020,0xc000}  [total free=c000]
+2: After shm_FragmentAlloc(block, 0x003ffc) == 0x008024
+{0x0020,0x8000}  [total free=8000]
+3: After shm_FragmentAlloc(block, 0x003ffc) == 0x004024
+{0x0020,0x4000}  [total free=4000]
+4: After shm_FragmentAlloc(block, 0x003ffd) == NULL
+{0x0020,0x4000}  [total free=4000]
+5: After shm_FragmentAlloc(block, 0x003ffc) == 0x000024
+no free fragments [total free=0000]
+6: Doing shm_FragmentFree(block, 0x000024)
+{0x0020,0x4000}  [total free=4000]
+7: After shm_FragmentAlloc(block, 0x001bfc) == 0x002424
+{0x0020,0x2400}  [total free=2400]
+8: After shm_FragmentAlloc(block, 0x0013fc) == 0x001024
+{0x0020,0x1000}  [total free=1000]
+9: After shm_FragmentAlloc(block, 0x000ffc) == 0x000024
+no free fragments [total free=0000]
+10: Doing shm_FragmentFree(block, 0x000024)
+{0x0020,0x1000}  [total free=1000]
+11: Doing shm_FragmentFree(block, 0x004024)
+{0x0020,0x1000} {0x4020,0x4000}  [total free=5000]
+12: Doing shm_FragmentFree(block, 0x00c024)
+{0x0020,0x1000} {0x4020,0x4000} {0xc020,0x3fe0}  [total free=8fe0]
+13: After shm_FragmentAlloc(block, 0x000ffc) == 0x000024
+{0x4020,0x4000} {0xc020,0x3fe0}  [total free=7fe0]
+14: Doing shm_FragmentFree(block, 0x000024)
+{0x0020,0x1000} {0x4020,0x4000} {0xc020,0x3fe0}  [total free=8fe0]
+15: After shm_FragmentAlloc(block, 0x000ffd) == 0x007014
+{0x0020,0x1000} {0x4020,0x2ff0} {0xc020,0x3fe0}  [total free=7fd0]
+16: Doing shm_FragmentFree(block, 0x008024)
+{0x0020,0x1000} {0x4020,0x2ff0} {0x8020,0x7fe0}  [total free=bfd0]
+17: Doing shm_FragmentFree(block, 0x001024)
+{0x0020,0x2400} {0x4020,0x2ff0} {0x8020,0x7fe0}  [total free=d3d0]
+18: Doing shm_FragmentFree(block, 0x002424)
+{0x0020,0x6ff0} {0x8020,0x7fe0}  [total free=efd0]
+19: Doing shm_FragmentFree(block, 0x007014)
+{0x0020,0xffe0}  [total free=ffe0]
diff --git a/ipc/bit_array.c b/ipc/bit_array.c
new file mode 100644
index 0000000..d4cede8
--- /dev/null
+++ b/ipc/bit_array.c
@@ -0,0 +1,276 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      bit_array.c
+ * Purpose :  manipulate array of bits
+ * Portability: This is not completely portable, non CISC arcitectures
+ *              Might not have atomic Clear/Set/Toggle bit. On those
+ *              architectures semaphores should be used.
+ * Big Endian Concerns: This code is big endian compatible,
+ *              but the byte order will be different (i.e. bit 0 will be
+ *              located in byte 3).
+ ***************************************************************************
+ */
+
+/*
+** uncoment the following line to disable assertions,
+** this may boost performance by up to 50%
+*/
+/* #define NDEBUG */
+
+#ifndef NO_ASM
+#define HAS_BITOPS
+#endif
+
+#include <stdio.h>
+
+#include <assert.h>
+
+#include "bit_array.h"
+#if defined(HAS_BITOPS)
+#  include <asm/bitops.h>
+#else
+static __inline__ int clear_bit(int bit, int *mem);
+static __inline__ int set_bit(int bit, int *mem);
+#endif /* HAS_BITOPS */
+
+
+#define INT_NR(bit_nr)       ((bit_nr) >> INT_LOG2)
+#define INT_COUNT(bit_count) INT_NR( bit_count + BITS_PER_INT - 1 )
+#define BIT_IN_INT(bit_nr)   ((bit_nr) & (BITS_PER_INT - 1))
+
+#if !defined(HAS_BITOPS)
+
+/* first_zero maps bytes value to the index of first zero bit */
+static char first_zero[256];
+static int arrays_initialized=0;
+
+
+/*
+** initialize static arrays used for bit operations speedup.
+** Currently initialized: first_zero[256]
+** set "arrays_initialized" to inidate that arrays where initialized
+*/
+
+static void initialize_arrays()
+{
+  int i;
+  int bit;
+
+  for (i=0 ; i<256 ; i++) {
+     /* find the first zero bit in `i' */
+     for (bit=0 ; bit < BITS_PER_BYTE ; bit++)
+	/* break if the bit is zero */
+	if ( ( (1 << bit) & i )
+	     == 0)
+	   break;
+     first_zero[i]= bit;
+  }
+  arrays_initialized=1;
+}
+
+/*
+** Find first zero bit in the integer.
+** Assume there is at least one zero.
+*/
+static __inline__ int find_zbit_in_integer(unsigned int integer)
+{
+  int i;
+
+  /* find the zero bit */
+  for (i=0 ; i < sizeof(int) ; i++, integer>>=8) {
+     int byte= integer & 0xff;
+
+     if (byte != 0xff)
+	return ( first_zero[ byte ]
+		 + (i << BYTE_LOG2) );
+  }
+  assert(0);			   /* never reached */
+  return 0;
+}
+
+/* return -1 on failure */
+static __inline__ int find_first_zero_bit(unsigned *array, int bits)
+{
+  unsigned int  integer;
+  int i;
+  int bytes=INT_COUNT(bits);
+
+  if (!arrays_initialized)
+     initialize_arrays();
+
+  for ( i=bytes ; i ; i--, array++) {
+     integer= *array;
+
+     /* test if integer contains a zero bit */
+     if (integer != ~0U)
+	return ( find_zbit_in_integer(integer)
+		 + ((bytes-i) << INT_LOG2) );
+  }
+
+  /* indicate failure */
+  return -1;
+}
+
+static __inline__ int test_bit(int pos, unsigned *array)
+{
+  unsigned int integer;
+  int bit = BIT_IN_INT(pos);
+
+  integer= array[ pos >> INT_LOG2 ];
+
+  return (  (integer & (1 << bit)) != 0
+	    ? 1
+	    : 0 ) ;
+}
+
+/*
+** The following two functions are x86 specific ,
+** other processors will need porting
+*/
+
+/* inputs: bit number and memory address (32 bit) */
+/* output: Value of the bit before modification */
+static __inline__ int clear_bit(int bit, int *mem)
+{
+  int ret;
+
+  __asm__("xor %1,%1
+	   btrl %2,%0
+	   adcl %1,%1"
+	  :"=m" (*mem), "=&r" (ret)
+	  :"r" (bit));
+  return (ret);
+}
+
+static __inline__ int set_bit(int bit, int *mem)
+{
+  int ret;
+  __asm__("xor %1,%1
+	   btsl %2,%0
+	   adcl %1,%1"
+	  :"=m" (*mem), "=&r" (ret)
+	  :"r" (bit));
+  return (ret);
+}
+
+#endif /* !deined(HAS_BITOPS) */
+
+
+/* AssembleArray: assemble an array object using existing data */
+bit_array *AssembleArray(bit_array *new_array, unsigned int *buff, int bits)
+{
+  assert(new_array!=NULL);
+  assert(buff!=NULL);
+  assert(bits>0);
+  assert((1 << INT_LOG2) == BITS_PER_INT); /* if fails, redefine INT_LOG2 */
+
+  new_array->bits=bits;
+  new_array->array=buff;
+  return new_array;
+}
+
+/* ResetArray: reset the bit array to zeros */
+int ResetArray(bit_array *bits)
+{
+  int i;
+  int *p;
+
+  assert(bits!=NULL);
+  assert(bits->array!=NULL);
+
+  for(i= INT_COUNT(bits->bits), p=bits->array; i ; p++, i--)
+     *p=0;
+  return 1;
+}
+
+
+/* VacantBit: find a vacant (zero) bit in the array,
+ * Return: Bit index on success, -1 on failure.
+ */
+int VacantBit(bit_array *bits)
+{
+  int bit;
+
+  assert(bits!=NULL);
+  assert(bits->array!=NULL);
+
+  bit= find_first_zero_bit(bits->array, bits->bits);
+
+  if (bit >= bits->bits)	   /* failed? */
+     return -1;
+
+  return bit;
+}
+
+int SampleBit(bit_array *bits, int i)
+{
+  assert(bits != NULL);
+  assert(bits->array != NULL);
+  assert(i >= 0  &&  i < bits->bits);
+
+  return ( test_bit(i,bits->array) != 0
+	   ? 1
+	   : 0
+	   );
+}
+
+
+/*
+** Use "compare and exchange" mechanism to make sure
+** that bits are not modified while "integer" value
+** is calculated.
+**
+** This may be the slowest technique, but it is the most portable
+** (Since most architectures have compare and exchange command)
+*/
+int AssignBit(bit_array *bits, int bit_nr, int val)
+{
+  int ret;
+
+  assert(bits != NULL);
+  assert(bits->array != NULL);
+  assert(val==0 || val==1);
+  assert(bit_nr >= 0  &&  bit_nr < bits->bits);
+
+  if (val==0)
+     ret= clear_bit(BIT_IN_INT(bit_nr), &bits->array[ INT_NR(bit_nr) ]);
+  else
+     ret= set_bit(BIT_IN_INT(bit_nr), &bits->array[ INT_NR(bit_nr) ]);
+
+  return ( (ret!=0) ? 1 : 0);
+}
+
+/*
+** Allocate a free bit (==0) and make it used (==1).
+** This operation is guaranteed to resemble an atomic instruction.
+**
+** Return: allocated bit index, or -1 on failure.
+**
+** There is a crack between locating free bit, and allocating it.
+** We assign 1 to the bit, test it was not '1' before the assignment.
+** If it was, restart the seek and assign cycle.
+**
+*/
+
+int AllocateBit(bit_array *bits)
+{
+  int bit_nr;
+  int orig_bit;
+
+  assert(bits != NULL);
+  assert(bits->array != NULL);
+
+  do {
+     bit_nr= VacantBit(bits);
+
+     if (bit_nr == -1)		   /* No vacant bit ? */
+	return -1;
+
+     orig_bit = AssignBit(bits, bit_nr, 1);
+  } while (orig_bit != 0);	   /* it got assigned before we tried */
+
+  return bit_nr;
+}
diff --git a/ipc/bit_array_test.c b/ipc/bit_array_test.c
new file mode 100644
index 0000000..14ecb34
--- /dev/null
+++ b/ipc/bit_array_test.c
@@ -0,0 +1,93 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "bit_array.h"
+#define SIZE (8*sizeof(int)*3)
+
+static bit_array array;
+static int simple_array[SIZE];
+static int bits;
+
+int are_equal()
+{
+  int i;
+  for (i=0 ; i < SIZE ; i++)
+     if (SampleBit(&array,i) != simple_array[i]){
+	printf("failed bit %d (packed=%d, simple=%d)\n", i,
+	       SampleBit(&array,i), simple_array[i]);
+	return 0;
+     }
+  return 1;
+}
+
+int is_same_vacant()
+{
+  int vacant;
+  for (vacant =0 ; simple_array[vacant]!=0  ; vacant++)
+     if ( vacant >= SIZE) {
+	vacant=-1;
+	break;
+     }
+
+
+  if ( VacantBit(&array) == vacant )
+     return 1;
+  else
+     return 0;
+}
+void assign_both(int bit_nr, int bit_val)
+{
+  int old_bit= simple_array[bit_nr];
+
+  simple_array[bit_nr]= bit_val;
+
+  bits+=bit_val - old_bit;
+
+  assert(AssignBit(&array, bit_nr, bit_val) == old_bit);
+  assert(are_equal());
+  assert(is_same_vacant());
+}
+
+
+int main()
+{
+  unsigned int integers[SIZE >> 5];
+  int i,j;
+
+  assert( AssembleArray(&array, integers, SIZE)
+	  == &array);
+  ResetArray(&array);
+  for (i=0 ; i<SIZE ; i++)
+     simple_array[i]=0;
+
+  for (j=5 ; j ; j--) {
+     printf("\rleft %d\r",j);
+
+     for (i=0 ; VacantBit(&array) != -1 ; i++ ) {
+	if (i % 256 == 0) {
+	   printf("left %d ",j);
+	   printf("%3d up  \r", bits);
+	   fflush(stdout);
+	}
+	assign_both(rand() % SIZE,
+		    (rand()% SIZE > bits ) ? 0 : 1 );
+     }
+
+     assign_both(rand() % SIZE, 1);
+
+     for (i=0 ; bits ; i++ ) {
+	if (i % 256 == 0) {
+	   printf("left %d ",j);
+	   printf("%3d down\r", bits);
+	   fflush(stdout);
+	}
+	assign_both(rand() % SIZE,
+		    (rand()% SIZE <= (SIZE-bits) ) ? 0 : 1 );
+     }
+
+     assign_both(rand() % SIZE, 0);
+  }
+
+  putchar('\n');
+  return 0;
+}
diff --git a/ipc/dde_atom.c b/ipc/dde_atom.c
new file mode 100644
index 0000000..c6ca2aa
--- /dev/null
+++ b/ipc/dde_atom.c
@@ -0,0 +1,273 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      dde_atom.c
+ * Purpose :  atom functionality for DDE
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "dde_atom.h"
+#include "shm_main_blk.h"
+#include "shm_fragment.h"
+#include "stddebug.h"
+#include "debug.h"
+
+typedef struct
+{
+	WORD        count;
+	BYTE        str[1];
+} AtomData, *AtomData_ptr;
+
+#define EMPTY   0		   /* empty hash entry */
+#define DELETED -1		   /* deleted hash entry */
+#define MIN_STR_ATOM 0xfc00
+
+/* OFS2AtomData_ptr: extract AtomData_ptr from ofs */
+#define OFS2AtomData_ptr(ofs) ((AtomData*)((int)&main_block->block+(ofs)))
+
+/* OFS2AtomStr: find the string of the atom */
+#define OFS2AtomStr(ofs)      (OFS2AtomData_ptr(atom_ofs)->str)
+
+/* offset of an atom according to index */
+#define ATOM_OFS(idx) (main_block->atoms[idx])
+
+/* rot_left: rotate (with wrap-around) */
+static __inline__ int rot_left(unsigned var,int count)
+{
+  return (var<<count) | (var>> (sizeof(var)-count));
+}
+/* find the entry in the atom table for this string */
+static int FindHash(LPCSTR str)	   /* ignore str case */
+{
+  int i,j;
+  unsigned hash1,hash2;
+  int deleted=-1;		   /* hash for deleted entry */
+  int atom_ofs;
+
+  /* get basic hash parameters */
+  for (i= hash1= hash2= 0; str[i] ; i++) {
+     hash1= rot_left(hash1,5) ^ toupper(str[i]);
+     hash2= rot_left(hash2,4) ^ toupper(str[i]);
+  }
+
+  hash1%= DDE_ATOMS;
+  atom_ofs=ATOM_OFS(hash1);
+  switch (atom_ofs) {
+    case EMPTY:			   /* empty atom entry */
+      return hash1;		   
+    case DELETED:		   /* deleted atom entry */
+      deleted=hash1;
+      break;
+    default :			   /* non empty atom entry */
+      if (  strcasecmp( OFS2AtomStr(atom_ofs) , str) == 0)
+	 return hash1;		   /* found string in atom table */
+  }
+  hash2%= DDE_ATOMS-1 ;		   /* hash2=0..(DDE_ATOMS-2) */
+  hash2++;			   /* hash2=1..(DDE_ATOMS-1) */
+
+  /* make jumps in the hash table by hash2 steps */
+  for (i=hash1+hash2 ; ; i+=hash2) {
+     /* i wraps around into j */
+     j=i-DDE_ATOMS;
+     if (j >= 0)
+	i=j;			   /* i wraps around */
+     
+     if (i==hash1) 
+	/* here if covered all hash locations, and got back to beginning */
+	return deleted;		   /* return first empty entry - if any */
+     atom_ofs=ATOM_OFS(i);
+     switch (atom_ofs) {
+       case EMPTY:		   /* empty atom entry */
+	 return i;		   
+       case DELETED:		   /* deleted atom entry */
+	 if (deleted < 0)
+	    /* consider only the first deleted entry */
+	    deleted= i;
+	 break;
+       default :		   /* nonempty atom entry */
+	 if (  strcasecmp( OFS2AtomStr(atom_ofs) , str) == 0)
+	    return i;	   /* found string in atom table */
+     }
+  }
+}
+
+void ATOM_GlobalInit(void)
+{
+  int i;
+  
+  for (i=0 ; i < DDE_ATOMS ; i++)
+     ATOM_OFS(i)=EMPTY;
+}
+
+/***********************************************************************
+ *           GlobalAddAtom   (USER.268)
+ */
+
+/* important! don't forget to unlock semaphores before return */
+ATOM GlobalAddAtom( LPCSTR str )
+{
+  int atom_idx;
+  int atom_ofs;
+  AtomData_ptr ptr;
+  ATOM atom;
+
+  dprintf_atom(stddeb,"GlobalAddAtom(%p)\n", str);
+  if ((unsigned) str < MIN_STR_ATOM)	   /* MS-windows convention */
+     return (ATOM) (unsigned) str;
+  if (str[0] == '#') {		   /* wine convention */
+     atom= (ATOM) atoi(&str[1]);
+     return (atom<MIN_STR_ATOM) ? atom : 0;
+  }
+  dprintf_atom(stddeb,"GlobalAddAtom(\"%s\")\n",str);
+
+  DDE_IPC_init();		/* will initialize only if needed */
+  
+  shm_write_wait(main_block->sem);
+
+  atom_idx=FindHash(str);
+  atom=(ATOM)0;
+
+  /* use "return" only at the end so semaphore handling is done only once */
+  if (atom_idx>=0) {
+     /* unless table full and item not found */
+     switch (atom_ofs= ATOM_OFS(atom_idx)) {
+       case DELETED:
+       case EMPTY:		   /* need to allocate new atom */
+	 atom_ofs= shm_FragmentAlloc(&main_block->block,
+				     strlen(str)+sizeof(AtomData));
+	 if (atom_ofs==NIL)
+	    break;		   /* no more memory (atom==0) */
+	 ATOM_OFS(atom_idx)=atom_ofs;
+	 ptr=OFS2AtomData_ptr(atom_ofs);
+	 strcpy(ptr->str,str);
+	 ptr->count=1;
+	 atom=(ATOM)(atom_idx+MIN_STR_ATOM);
+	 break;
+       default :		   /* has to update existing atom */
+	 OFS2AtomData_ptr(atom_ofs)->count++;
+	 atom=(ATOM)(atom_idx+MIN_STR_ATOM);
+     } /* end of switch */
+  } /* end of if */
+  shm_write_signal(main_block->sem);
+  return atom;
+}
+
+/***********************************************************************
+ *           GlobalDeleteAtom   (USER.269)
+ */
+
+ATOM GlobalDeleteAtom( ATOM atom )
+{
+  int atom_idx;
+  int atom_ofs;
+  AtomData_ptr atom_ptr;
+  ATOM retval=(ATOM) 0;
+  
+  dprintf_atom(stddeb,"GlobalDeleteAtom(\"%d\")\n",(int)atom);
+  atom_idx=(int)atom - MIN_STR_ATOM;
+  
+  if (atom_idx < 0 )
+     return 0;
+
+  DDE_IPC_init();	   /* will initialize only if needed */
+
+  shm_write_wait(main_block->sem);
+  /* return used only once from here on -- for semaphore simplicity */
+  switch (atom_ofs=ATOM_OFS(atom_idx)) {
+    case DELETED:
+    case EMPTY:
+      fprintf(stderr,"trying to free unallocated atom %d\n", atom);
+      retval=atom;
+      break;
+    default :
+      atom_ptr=OFS2AtomData_ptr(atom_ofs);
+      if ( --atom_ptr->count == 0) {
+	 shm_FragmentFree(&main_block->block,atom_ofs);
+	 ATOM_OFS(atom_idx)=DELETED;
+      }
+  }
+  
+  shm_write_signal(main_block->sem);
+  return retval;
+}
+
+/***********************************************************************
+ *           GlobalFindAtom   (USER.270)
+ */
+ATOM GlobalFindAtom( LPCSTR str )
+{
+  int atom_idx;
+  int atom_ofs;
+
+  dprintf_atom(stddeb,"GlobalFindAtom(%p)\n", str );
+  if ((unsigned) str < MIN_STR_ATOM) /* MS-windows convention */
+     return (ATOM) (unsigned) str;
+  if (str[0] == '#') {		   /* wine convention */
+     ATOM atom= (ATOM) atoi(&str[1]);
+     return (atom<MIN_STR_ATOM) ? atom : 0;
+  }
+  dprintf_atom(stddeb,"GlobalFindAtom(\"%s\")\n",str);
+
+  DDE_IPC_init();		/* will initialize only if needed */
+
+  shm_read_wait(main_block->sem);
+  atom_idx=FindHash(str);
+  if (atom_idx>=0)		   
+     atom_ofs=ATOM_OFS(atom_idx);  /* is it free ? */
+  else
+     atom_ofs=EMPTY;
+  shm_read_signal(main_block->sem);
+
+  if (atom_ofs==EMPTY || atom_ofs==DELETED)
+     return 0;
+  else
+     return (ATOM)(atom_idx+MIN_STR_ATOM);
+}
+
+/***********************************************************************
+ *           GlobalGetAtomName   (USER.271)
+ */
+WORD GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
+{
+  int atom_idx, atom_ofs;
+  int size;
+  /* temporary buffer to hold maximum "#65535\0" */
+  char str_num[7];
+  
+  if (count<2)			   /* no sense to go on */
+     return 0;
+  atom_idx=(int)atom - MIN_STR_ATOM;
+  
+  if (atom_idx < 0) {		   /* word atom */
+     /* use wine convention... */
+     sprintf(str_num,"#%d%n",(int)atom,&size);
+     if (size+1>count) {	   /* overflow ? */
+	/* truncate the string */
+	size=count-1;
+	str_num[size]='\0';
+     }
+     strcpy(buffer,str_num);
+     return size;
+  }
+
+  DDE_IPC_init();		/* will initialize only if needed */
+
+  /* string atom */
+  shm_read_wait(main_block->sem);
+  atom_ofs=ATOM_OFS(atom_idx);
+  if (atom_ofs==EMPTY || atom_ofs==DELETED) {
+     fprintf(stderr,"GlobalGetAtomName: illegal atom=%d\n",(int)atom);
+     size=0;
+  } else {			   /* non empty entry */
+     /* string length will be at most count-1, find actual size */
+     sprintf(buffer,"%.*s%n",count-1, OFS2AtomStr(atom_ofs), &size);
+  }
+  shm_read_signal(main_block->sem);
+  return size;
+}
+
diff --git a/ipc/dde_atom_test.c b/ipc/dde_atom_test.c
new file mode 100644
index 0000000..dd587c4
--- /dev/null
+++ b/ipc/dde_atom_test.c
@@ -0,0 +1,100 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      dde_atom_test.c
+ * Purpose :  tests for dde_atom object
+ ***************************************************************************
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <win.h>
+#include "dde_atom.h"
+#include "shm_main_blk.h"
+#include <stddebug.h>
+#include <debug.h>
+#define TOGETHER (DDE_ATOMS/5)
+
+
+/* run random sequences */
+int main()
+{
+  ATOM atom_list[TOGETHER];
+  char str[TOGETHER][80];
+  int i,j,atom_n;
+  int atom_len[TOGETHER];
+  
+  debugging_shm=1;
+  debugging_atom=0;
+  debugging_sem=0;
+  
+  for (i=0 ; i<=10000/TOGETHER ; i++) {
+     for (atom_n=0 ; atom_n<TOGETHER ; atom_n++) {
+	atom_len[atom_n]=rand()%64+1;
+	for (j=atom_len[atom_n]-1; j>=0; j--) 
+	   do {
+	      str[atom_n][j]=(char)(rand()%255+1);
+	   } while (j==0 && str[atom_n][j]=='#');
+
+	str[atom_n][ atom_len[atom_n] ]='\0';
+
+	atom_list[atom_n]=GlobalAddAtom(str[atom_n]);
+
+	if (atom_list[atom_n]==0) {
+	   fprintf(stderr,"failed i=%d, atom_n=%d\n",i,atom_n);
+	   return 1;
+	}
+	if (atom_list[atom_n]!=GlobalAddAtom(str[atom_n])) {
+	   fprintf(stderr,
+		   "wrong second GlobalAddAtom(\"%s\")\n", str[atom_n]);
+	   return 1;
+	}
+     } /* for */
+     for (atom_n=0 ; atom_n<TOGETHER ; atom_n++) {
+	char buf[80];
+	int len;
+
+	len=GlobalGetAtomName( atom_list[atom_n], buf, 79);
+	if (atom_len[atom_n] != len) {
+	   fprintf(stderr, "i=%d, atom_n=%d; ", i, atom_n);
+	   fprintf(stderr,
+		   "wrong length of GlobalGetAtomName(\"%s\")\n",
+		   str[atom_n]);
+
+	   return 1;
+	}
+	   
+     }
+     for (atom_n=0 ; atom_n<TOGETHER ; atom_n++) {
+	GlobalDeleteAtom(atom_list[atom_n]);
+	if (atom_list[atom_n]!=GlobalAddAtom(str[atom_n])) {
+	   fprintf(stderr, "i=%d, atom_n=%d; ", i, atom_n);
+	   fprintf(stderr,
+		   "wrong third GlobalAddAtom(\"%s\")\n", str[atom_n]);
+	   return 1;
+	}
+	GlobalDeleteAtom(atom_list[atom_n]);
+	GlobalDeleteAtom(atom_list[atom_n]);
+	
+	atom_list[atom_n]=GlobalAddAtom(str[atom_n]);
+	if (atom_list[atom_n]!=GlobalAddAtom(str[atom_n])) {
+	   fprintf(stderr,
+		   "i=%d, atom_n=%d wrong fifth GlobalAddAtom(\"%s\")\n",
+		   i, atom_n,
+		   str[atom_n]);
+	   return 1;
+	}
+	GlobalDeleteAtom(atom_list[atom_n]);
+	if (atom_list[atom_n]!=GlobalFindAtom(str[atom_n])) {
+	   fprintf(stderr,
+		   "i=%d, atom_n=%d wrong GlobalFindAtom(\"%s\")\n",
+		   i, atom_n,
+		   str[atom_n]);
+	   return 1;
+	}
+	GlobalDeleteAtom(atom_list[atom_n]);
+     }     
+  }
+  return 0;
+}
diff --git a/ipc/dde_mem.c b/ipc/dde_mem.c
new file mode 100644
index 0000000..f19b013
--- /dev/null
+++ b/ipc/dde_mem.c
@@ -0,0 +1,282 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      dde_mem.c
+ * Purpose :  shared DDE memory functionality for DDE
+ ***************************************************************************
+ */
+#include <stdio.h>
+#include <stddebug.h>
+#include <debug.h>
+#include <assert.h>
+#include "ldt.h"
+#include "shm_main_blk.h"
+#include "shm_fragment.h"
+#include "shm_semaph.h"
+#include "dde_mem.h"
+#include "bit_array.h"
+
+#define SEGPTR2HANDLE_INFO(sptr) ( (struct handle_info*)PTR_SEG_TO_LIN(sptr) )
+
+#define HINFO2DATAPTR(h_info_ptr) ( (void*) ( (char*)h_info_ptr +           \
+					     sizeof(struct handle_info) ) )
+#define DDE_MEM_IDX(handle) ((handle)& 0x7fff)
+#define DDE_MEM_HANDLE(idx) ((idx) | 0x8000)
+#define DDE_MEM_INFO(handle) (main_block->handles[ DDE_MEM_IDX(handle) ])
+/* List of shared handles.
+ * This entry resides on the shared memory, the data comes right
+ * after the `handle_info'.
+ * The entry is on the same block as the actual data.
+ * The `next' field gives relative reference (relative to the start of
+ * the blcok.
+ */
+struct handle_info {
+	WORD lock_count;
+	WORD flags;
+	int size;		/* size of the data (net)*/
+};
+
+static bit_array free_handles;
+int debug_last_handle_size= 0;	/* for debugging purpose only */
+
+
+/* locate_handle:
+ *   locate a shared memory handle.
+ * Application:
+ *   The handle is first searched for in attached blocks.
+ *   At the beginning, only blocks owned by this process are
+ *   attached.
+ *   If a handle is not found, new blocks are attached.
+ * Arguments:
+ *   h    - the handle.
+ * RETURN: pointer to handle info.
+ */
+static struct handle_info *locate_handle(HGLOBAL h, struct local_shm_map *map)
+{
+  struct shm_block *block;
+  
+  dprintf_global(stddeb,"shm:locate_handle(0x%04x)\n", h);
+
+
+  if (SampleBit( &free_handles, DDE_MEM_IDX(h)) == 0) {
+     dprintf_global(stddeb, "shm:locate_handle: return NULL\n");
+     return NULL;		   /* free!!! */
+  }
+  
+  block= shm_locate_block(DDE_MEM_INFO(h).shmid, map);
+  if (block == NULL) {
+      /* nothing found */
+      dprintf_global(stddeb, "shm:locate_handle: return NULL\n");
+      return NULL;
+  }
+
+  return (struct handle_info *) REL2PTR(block, DDE_MEM_INFO(h).rel);
+  
+}
+
+/* dde_alloc_handle: allocate shared DDE handle */
+static HGLOBAL dde_alloc_handle()
+{
+  int bit_nr;
+
+  bit_nr= AllocateBit( &free_handles);
+
+  if (bit_nr != -1)
+     return DDE_MEM_HANDLE(bit_nr);
+
+  dprintf_global(stddeb,"dde_alloc_handle: no free DDE handle found\n");
+  return 0;
+}
+/**********************************************************************
+ *					DDE_malloc
+ */
+void *
+DDE_malloc(unsigned int flags, unsigned long size, SHMDATA *shmdata)
+{
+    int shmid;
+    struct shm_block *block;
+    struct handle_info *h_info;
+    struct local_shm_map *curr;
+    HGLOBAL handle;
+    
+    dprintf_global(stddeb,"DDE_malloc flags %4X, size %ld\n", flags, size);
+    DDE_IPC_init();		/* make sure main shm block allocated */ 
+
+    shm_write_wait(main_block->proc[curr_proc_idx].sem);
+
+    /* Try to find fragment big enough for `size' */
+    /* iterate through all local shm blocks, and try to allocate
+       the fragment */
+
+    h_info= NULL;
+    for (curr=  shm_map ; curr != NULL ; curr= curr->next) {
+       if (curr->proc_idx == curr_proc_idx) {
+	  h_info= (struct handle_info *)
+	     shm_FragPtrAlloc(curr->ptr, size+sizeof(struct handle_info));
+	  if (h_info!=NULL) {
+	     shmid= curr->shm_id;
+	     break;
+	  }
+       }
+    }
+
+    if (h_info == NULL) {
+       
+       block= shm_create_block(0, size+sizeof(struct handle_info), &shmid);
+       if (block==NULL) {
+	  shm_write_signal(main_block->proc[curr_proc_idx].sem);
+	  return 0;
+       }
+       /* put the new block in the linked list */
+       block->next_shm_id= main_block->proc[curr_proc_idx].shmid;
+       main_block->proc[curr_proc_idx].shmid= shmid;
+       h_info= (struct handle_info *)
+	  shm_FragPtrAlloc(block, size+sizeof(struct handle_info));
+       if (h_info==NULL) {
+	  fprintf(stderr,"DDE_malloc: BUG! unallocated fragment\n");
+	  shm_write_signal(main_block->proc[curr_proc_idx].sem);
+	  return 0;
+       }
+    } else {
+       block= curr->ptr;
+    }
+
+    /* Here we have an allocated fragment */
+    h_info->flags= flags;
+    h_info->lock_count= 0;
+    h_info->size= size;
+    handle= dde_alloc_handle();
+    
+    if (handle) {
+       dprintf_global(stddeb,
+		      "DDE_malloc returning handle=0x%4x, ptr=0x%08lx\n",
+		      (int)handle, (long) HINFO2DATAPTR(h_info));
+       DDE_MEM_INFO(handle).rel=  PTR2REL(block, h_info);
+       DDE_MEM_INFO(handle).shmid= shmid;
+    }
+    else
+       dprintf_global(stddeb,"DDE_malloc failed\n");
+
+    shm_write_signal(main_block->proc[curr_proc_idx].sem);
+    
+    shmdata->handle= handle;
+    return (char *)HINFO2DATAPTR(h_info);
+}
+
+HGLOBAL DDE_GlobalFree(HGLOBAL h)
+{
+  struct handle_info *h_info;
+  int handle_index= h & 0x7fff;
+  struct local_shm_map map;
+
+  dprintf_global(stddeb,"DDE_GlobalFree(0x%04x)\n",h);
+
+  if (h==0)
+     return 0;
+
+  h_info= locate_handle(h, &map);
+  if (h_info == NULL)
+      return h;
+
+  shm_write_wait(main_block->proc[map.proc_idx].sem);
+
+  shm_FragPtrFree(map.ptr, (struct shm_fragment *) h_info);
+
+  AssignBit( &free_handles, handle_index, 0);
+  
+  /* FIXME: must free the shm block some day. */
+  shm_write_signal(main_block->proc[map.proc_idx].sem);
+  return 0;
+}
+
+WORD DDE_SyncHandle(HGLOBAL handle, WORD sel)
+    
+{
+    struct handle_info *h_info;
+    void *local_ptr;
+    ldt_entry entry;
+    
+    h_info= locate_handle(handle, NULL);
+    local_ptr= (void *)GET_SEL_BASE(sel);
+
+    
+    if (h_info == NULL)
+	return 0;
+    
+    if (local_ptr == (void *) HINFO2DATAPTR(h_info))
+	return sel;
+
+    /* need syncronization ! */
+    LDT_GetEntry( SELECTOR_TO_ENTRY(sel), &entry );
+    entry.base= (unsigned long) HINFO2DATAPTR(h_info);
+    LDT_SetEntry( SELECTOR_TO_ENTRY(sel), &entry );
+
+    return sel;
+}
+
+/*
+ * DDE_AttachHandle:
+ * Attach shm memory (The data must not be already attached).
+ * Parameters:
+ *   handle - the memory to attach.
+ *   segptr - in not null, return SEGPTR to the same block.
+ * return value:
+ *   32 bit pointer to the memory.
+ */
+
+void *DDE_AttachHandle(HGLOBAL handle, SEGPTR *segptr)
+{
+  struct handle_info *h_info;
+  SHMDATA shmdata;
+  void *ptr;
+  HGLOBAL hOwner = GetCurrentPDB();
+
+  assert(is_dde_handle(handle));
+  if (segptr != NULL)
+      *segptr=0;
+
+  dprintf_global(stddeb,"DDE_AttachHandle(%04x)\n",handle);
+  h_info=locate_handle(handle, NULL);
+
+  if (h_info == NULL) 
+      return NULL;
+
+  if ( !(h_info->flags & GMEM_DDESHARE) ) {
+      fprintf(stderr,"DDE_AttachHandle: Corrupted memory handle info\n");
+      return NULL;
+  }
+  
+  dprintf_global(stddeb,"DDE_AttachHandle: h_info=%06lx\n",(long)h_info);
+
+  shmdata.handle= handle;
+  shmdata.shmid= DDE_MEM_INFO(handle).shmid;
+
+  ptr= HINFO2DATAPTR(h_info);
+  /* Allocate the selector(s) */
+  if (! GLOBAL_CreateBlock( h_info->flags, ptr, h_info->size, hOwner,
+			    FALSE, FALSE, FALSE, &shmdata)) 
+      return NULL;
+
+  if (segptr != NULL) 
+      *segptr= (SEGPTR)MAKELONG( 0, shmdata.sel);
+
+  if (debugging_dde)
+      debug_last_handle_size= h_info->size;
+
+  dprintf_global(stddeb,"DDE_AttachHandle returns ptr=0x%08lx\n", (long)ptr);
+
+  return (LPSTR)ptr;
+
+}
+
+void DDE_mem_init()
+{
+  int nr_of_bits;
+
+  shm_init();
+  
+  nr_of_bits= BITS_PER_BYTE * sizeof(main_block->free_handles);
+  AssembleArray( &free_handles, main_block->free_handles, nr_of_bits);
+}
diff --git a/ipc/dde_mem_test.c b/ipc/dde_mem_test.c
new file mode 100644
index 0000000..2fe42a5
--- /dev/null
+++ b/ipc/dde_mem_test.c
@@ -0,0 +1,73 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      dde_mem_test.c
+ * Purpose :  test shared DDE memory functionality for DDE
+ * Usage:     Look for assertion failures
+ ***************************************************************************
+ */
+#include <stdio.h>
+#include <assert.h>
+#include <win.h>
+#include "dde_mem.h"
+/* stub */
+
+void ATOM_GlobalInit()
+{
+  printf("ATOM_GlobalInit\n");
+}
+
+
+int main()
+{
+  HWND h1,h2,h3;
+  int ret;
+  void *p1,*p2,*p3,*p;
+  SHMDATA shmdata;
+  
+  /* alloc h1, h2, h3 */
+
+  setbuf(stdout,NULL);
+  p1=DDE_malloc(GMEM_DDESHARE, 0x6000, &shmdata);
+  h1= shmdata.handle;
+  assert(p1 != NULL);
+  assert(h1 != 0);
+  p2=DDE_malloc(GMEM_DDESHARE, 0xff00, &shmdata);
+  h2= shmdata.handle;
+  assert(p2 != NULL);
+  assert(h2 != 0);
+  p3=DDE_malloc(GMEM_DDESHARE, 0x6000, &shmdata);
+  h3= shmdata.handle;
+  assert(p3 != 0);
+  assert(h3 != 0);
+
+  /* lock h1, h2, h3 */
+  p=DDE_AttachHandle(h1,NULL);
+  assert(p1==p);
+  p=DDE_AttachHandle(h2,NULL);
+  assert(p2==p);
+  p=DDE_AttachHandle(h3,NULL);
+  assert(p3==p);
+
+
+  
+  ret=DDE_GlobalFree(h1);
+  assert(ret==0);
+  /* do some implementation dependant tests */
+  p=DDE_malloc(GMEM_DDESHARE, 0x6000, &shmdata);
+  assert(p!=NULL);
+  assert(shmdata.handle==h1);
+  p=DDE_AttachHandle(h1,NULL);
+  assert(p1==p);
+
+  /* check freeing */
+  ret=DDE_GlobalFree(h1);
+  assert(ret==0);
+  ret=DDE_GlobalFree(h2);
+  assert(ret==0);
+  ret=DDE_GlobalFree(h3);
+  assert(ret==0);
+  return 0;
+}
diff --git a/ipc/dde_proc.c b/ipc/dde_proc.c
new file mode 100644
index 0000000..9f5f59e
--- /dev/null
+++ b/ipc/dde_proc.c
@@ -0,0 +1,718 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      dde_proc.c
+ * Purpose :  DDE signals and processes functionality for DDE
+ ***************************************************************************
+ */
+#include <sys/time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/msg.h>
+#include "wintypes.h"
+#include "win.h"
+#include "shm_semaph.h"
+#include "shm_main_blk.h"
+#include "dde_proc.h"
+#include "dde_mem.h"
+#include "dde.h"
+#include "stddebug.h"
+#include "debug.h"
+
+int curr_proc_idx= -1;
+
+enum stop_wait_op stop_wait_op=CONT;
+int had_SIGUSR2 = 0;
+sigjmp_buf env_get_ack;
+sigjmp_buf env_wait_x;
+
+#define IDX_TO_HWND(idx)  (0xfffe - (idx))
+#define HWND_TO_IDX(wnd)  (0xfffe - (wnd))
+#define DDE_WIN_INFO(win) ( main_block->windows[HWND_TO_IDX(win)] )
+#define DDE_WIN2PROC(win) ( DDE_WIN_INFO(win).proc_idx )
+#define DDE_IsRemoteWindow(win)	 (  (win)<0xffff && (win)>=(0xffff-DDE_PROCS))
+#define DDE_SEND 1
+#define DDE_POST 2
+#define DDE_ACK	 3
+#define DDE_MSG_SIZE   sizeof(MSG)
+#define FREE_WND (WORD)(-2)
+#define DELETED_WND (WORD)(-3)
+#if defined(DEBUG_MSG) || defined(DEBUG_RUNTIME)
+static char *msg_type[4]={"********", "DDE_SEND", "DDE_POST", "DDE_ACK"};
+#endif
+
+struct msg_dat {
+	struct msgbuf dat;
+	char filler[DDE_MSG_SIZE];
+} ;
+
+typedef struct fifo_element {
+	int value;
+	struct fifo_element *next;
+} fifo_element;
+
+struct fifo {
+	fifo_element *first;	   /* first element in the fifo or NULL */
+	fifo_element *last;	   /* last element in the fifo or NULL */
+};
+static struct fifo fifo = {NULL,NULL};
+
+void dde_proc_delete(int proc_idx);
+
+void dde_proc_add_fifo(int val)
+{
+  fifo_element *created;
+
+  created= (fifo_element*) malloc( sizeof(fifo_element) );
+  created->value = val;
+  created->next = NULL;
+  
+  if (fifo.first==NULL) 
+     fifo.first= created;
+  else 
+     fifo.last->next= created;
+  fifo.last = created;
+}
+
+/* get an item from the fifo, and return it.
+ * If fifo is empty, return -1
+ */
+int dde_proc_shift_fifo()
+{
+  int val;
+  fifo_element *deleted;
+  
+  if (fifo.first == NULL)
+     return -1;
+  
+  deleted= fifo.first;
+  val= deleted->value;
+  fifo.first= deleted->next;
+  if (fifo.first == NULL)
+     fifo.last= NULL;
+
+  free(deleted);
+  return val;
+}
+
+static void print_dde_message(char *desc, MSG *msg);
+
+/* This should be run only when main_block is first allocated.	*/
+void dde_proc_init(dde_proc proc)
+{
+  int proc_num;
+
+  for (proc_num=0 ; proc_num<DDE_PROCS ; proc_num++, proc++) {
+     proc->msg=-1;
+     proc->sem=-1;
+     proc->shmid=-1;
+     proc->pid=-1;
+  }
+}
+
+/* add current process to the list of processes */
+void dde_proc_add(dde_proc procs)
+{
+  dde_proc proc;
+  int proc_idx;
+  dprintf_dde(stddeb,"dde_proc_add(..)\n");
+  shm_write_wait(main_block->sem);
+
+  /* find free proc_idx and allocate it */
+  for (proc_idx=0, proc=procs ; proc_idx<DDE_PROCS ; proc_idx++, proc++)
+     if (proc->pid==-1)
+	break;			   /* found! */
+
+  if (proc_idx<DDE_PROCS) {	   /* got here beacuse a free was found ? */
+     dde_msg_setup(&proc->msg);
+     proc->pid=getpid();
+     curr_proc_idx=proc_idx;
+     shm_sem_init(&proc->sem);
+  }
+  else	{
+     fflush(stdout);
+     fprintf(stderr,"dde_proc_add: Can't allocate process\n");
+  }
+  shm_write_signal(main_block->sem);
+}
+
+/* wait for dde - acknowledge message - or timout */
+static BOOL get_ack()
+{
+    struct timeval timeout;
+    int size;
+    struct msg_dat ack_buff;
+
+    /* timeout after exactly one seconf */
+    timeout.tv_sec = 1;
+    timeout.tv_usec = 0;
+
+    sigsetjmp(env_get_ack, 1);
+    /* get here after normal execution, or after siglongjmp */
+
+    do {			   /* loop to wait for DDE_ACK */
+       had_SIGUSR2=0;
+       stop_wait_op=CONT;	   /*  sensitive code: disallow siglongjmp */
+       size= msgrcv( main_block->proc[curr_proc_idx].msg , &ack_buff.dat,
+		     1, DDE_ACK, IPC_NOWAIT);
+       if (size>=0) {
+	  dprintf_msg(stddeb,"get_ack: received DDE_ACK message\n");
+	  return TRUE;
+       }
+       if (DDE_GetRemoteMessage()) {
+	     had_SIGUSR2=1;  /* might have recieved SIGUSR2 */
+       }
+       stop_wait_op=STOP_WAIT_ACK; /* allow siglongjmp */
+
+    } while (had_SIGUSR2);	   /* loop if SIGUSR2 was recieved */
+
+    /* siglongjmp should be enabled at this moment */
+    select( 0, NULL, NULL, NULL, &timeout );
+    stop_wait_op=CONT;		   /* disallow further siglongjmp */
+
+    /* timeout !! (otherwise there would have been a siglongjmp) */
+    return FALSE;
+}
+
+/* Transfer one message to a given process */
+static BOOL DDE_DoOneMessage (int proc_idx, int size, struct msgbuf *msgbuf)
+{
+  dde_proc proc= &main_block->proc[ proc_idx ];
+
+
+  if (proc_idx == curr_proc_idx)
+     return FALSE;
+
+  if (kill(proc->pid,0) < 0) {
+     /* pid does not exist, or not our */
+     dde_proc_delete(proc_idx);
+     return FALSE;
+  }
+
+  if (debugging_dde) {
+     MSG *msg=(MSG*) &msgbuf->mtext;
+     char *title;
+     if (msgbuf->mtype==DDE_SEND)
+	title="sending dde:";
+     else if (msgbuf->mtype==DDE_POST)
+	title="posting dde:";
+     else
+	title=NULL;
+     if (title)
+	 print_dde_message(title, msg);
+     else
+       fprintf(stddeb,"Unknown message type=0x%lx\n",msgbuf->mtype);
+  }
+  dprintf_msg(stddeb,
+	      "DDE_DoOneMessage: to proc_idx=%d (pid=%d), queue=%u\n",
+	      proc_idx, proc->pid, (unsigned)proc->msg);
+  if ( proc->msg != -1) {
+     dprintf_msg(stddeb, "DDE_DoOneMessage: doing...(type=%s)\n",
+		 msg_type[msgbuf->mtype]);
+     size=msgsnd (proc->msg, msgbuf, size, 0);
+
+     if (size<0) {
+	 fflush(stdout);
+	 perror("msgsnd");
+     }
+     kill(proc->pid,SIGUSR2);	   /* tell the process there is a message */
+
+     dprintf_msg(stddeb,"DDE_DoOneMessage: "
+		 "Trying to get acknowledgment from msg queue=%d\n",
+		 proc->msg);
+     Yield();			/* force task switch, and */
+				/* acknowledgment sending */
+     if (get_ack()) {
+	return TRUE;
+     } else {
+	fflush(stdout);
+	fprintf(stderr,"get_ack: DDE_DoOneMessage: timeout\n");
+	return FALSE;
+     }
+  }
+  else {
+     dprintf_msg(stddeb,"DDE_DoOneMessage: message not sent, "
+		 "target has no message queue\n");
+     return FALSE;
+  }
+}
+
+/* Do some sort of premitive hash table */
+static HWND HWND_Local2Remote(HWND orig)
+{
+  int dde_wnd_idx;
+  int deleted_idx= -1;
+  WND_DATA *tested;
+  WND_DATA *deleted= NULL;
+  int i;
+  
+  dde_wnd_idx= orig % DDE_WINDOWS;
+  for ( i=0 ; i < DDE_WINDOWS ; i++, dde_wnd_idx++) {
+    if (dde_wnd_idx >= DDE_WINDOWS)
+      dde_wnd_idx -= DDE_WINDOWS; /* wrap-around */
+    
+    tested= &main_block->windows[ dde_wnd_idx ];
+    if (tested->proc_idx == FREE_WND)
+      break;
+    
+    if (deleted == NULL && tested->proc_idx == DELETED_WND) {
+      deleted= tested;
+      deleted_idx= dde_wnd_idx;
+    } else if (tested->wnd == orig && tested->proc_idx == curr_proc_idx) {
+      return IDX_TO_HWND(dde_wnd_idx);
+    }
+  }
+  if (deleted != NULL)	{	/* deleted is preferable */
+    /* free item, allocate it */
+    deleted->proc_idx= curr_proc_idx;
+    deleted->wnd = orig;
+    return IDX_TO_HWND(deleted_idx);
+  }
+  if (tested->proc_idx == FREE_WND) {
+    tested->proc_idx= curr_proc_idx;
+    tested->wnd = orig;
+    return IDX_TO_HWND(dde_wnd_idx);
+  }
+
+  fprintf(stderr,
+	  "HWND_Local2Remote: Can't map any more windows to DDE windows\n");
+  return 0;			
+}
+
+static BOOL DDE_DoMessage( MSG *msg, int type )
+{
+  int proc_idx;
+
+  MSG *remote_message;
+  struct msg_dat msg_dat;
+  BOOL success;
+  
+  if (msg->wParam == 0)
+      return FALSE;
+  
+  if (main_block==NULL) {
+    if (msg->message >=  WM_DDE_FIRST && msg->message <= WM_DDE_LAST) 
+      DDE_IPC_init();
+    else 
+      return FALSE;
+  }
+
+
+  if (msg->wParam == (HWND)-1)
+     return FALSE;
+
+  if ( ! DDE_IsRemoteWindow(msg->hwnd) && msg->hwnd!= (HWND)-1)
+     return FALSE;
+
+  dprintf_msg(stddeb, "%s: DDE_DoMessage(hwnd=0x%x,msg=0x%x,..)\n",
+	      msg_type[type], (int)msg->hwnd,(int)msg->message);
+
+
+  dprintf_msg(stddeb,
+	      "DDE_DoMessage(hwnd=0x%x,msg=0x%x,..) // HWND_BROADCAST !\n",
+	      (int)msg->hwnd,(int)msg->message);
+  remote_message=(void*)&msg_dat.dat.mtext;
+  
+  memcpy(remote_message, msg, sizeof(*msg));
+  remote_message->wParam= HWND_Local2Remote(msg->wParam);
+  if (remote_message->wParam == 0)
+    return FALSE;
+  
+  msg_dat.dat.mtype=type;
+
+  if (msg->hwnd == (HWND)-1) {
+     success= FALSE;
+     for ( proc_idx=0; proc_idx < DDE_PROCS ; proc_idx++) {
+	if (proc_idx == curr_proc_idx)
+	   continue;
+	if (main_block->proc[ proc_idx ].msg != -1)
+	   success|=DDE_DoOneMessage(proc_idx, DDE_MSG_SIZE, &msg_dat.dat);
+     }
+     return success;
+  } else {
+     return DDE_DoOneMessage(DDE_WIN2PROC(msg->hwnd), DDE_MSG_SIZE,
+			     &msg_dat.dat);
+  }
+}
+
+BOOL DDE_SendMessage( MSG *msg)
+{
+  return DDE_DoMessage(msg, DDE_SEND);
+}
+
+BOOL DDE_PostMessage( MSG *msg)
+{
+  return DDE_DoMessage(msg, DDE_POST);
+}
+
+
+void dde_proc_send_ack(HWND wnd, BOOL val) {
+   int proc,msg;
+
+   static struct msgbuf msg_ack={DDE_ACK,{'0'}};
+
+   proc=DDE_WIN2PROC(wnd);
+   msg=main_block->proc[proc].msg;
+   dprintf_msg(stddeb,"DDE_GetRemoteMessage: sending ACK "
+	       "to wnd=%4x, proc=%d,msg=%d, pid=%d\n",wnd,proc,msg,
+	       main_block->proc[proc].pid
+     );
+
+   msg_ack.mtext[0]=val;
+   msgsnd (msg, &msg_ack, 1, 0);
+   kill(main_block->proc[proc].pid, SIGUSR2);
+}
+
+/* return true (non zero) if had a remote message */
+#undef DDE_GetRemoteMessage
+
+int DDE_GetRemoteMessage()
+{
+  static int nesting=0;		   /* to avoid infinite recursion */
+
+  MSG *remote_message;
+  int size;
+  struct msg_dat msg_dat;
+  BOOL was_sent;		   /* sent/received */
+  BOOL passed;
+  HWND hwnd;
+  WND	*window;
+
+  if (curr_proc_idx==-1)	   /* do we have DDE initialized ? */
+     return 0;
+
+  if (nesting>10) {
+     fflush(stdout);
+     fprintf(stderr,"DDE_GetRemoteMessage: suspecting infinite recursion, exiting");
+     return 0;
+  }
+
+  remote_message=(void*)&msg_dat.dat.mtext;
+
+  /* test for SendMessage */
+  size= msgrcv( main_block->proc[curr_proc_idx].msg , &msg_dat.dat,
+		DDE_MSG_SIZE, DDE_SEND, IPC_NOWAIT);
+
+  if (size==DDE_MSG_SIZE) {	   /* is this a correct message (if any) ?*/
+     was_sent=TRUE;
+     dprintf_msg(stddeb,
+		 "DDE:receive sent message. msg=%04x wPar=%04x"
+		 " lPar=%08lx\n",
+		 remote_message->message, remote_message->wParam,
+		 remote_message->lParam);
+  } else {
+     size= msgrcv( main_block->proc[curr_proc_idx].msg , &msg_dat.dat,
+		   DDE_MSG_SIZE, DDE_POST, IPC_NOWAIT);
+
+     if (size==DDE_MSG_SIZE) {	   /* is this a correct message (if any) ?*/
+	was_sent=FALSE;
+	dprintf_msg(stddeb,
+		    "DDE:receive posted message. "
+		    "msg=%04x wPar=%04x lPar=%08lx\n",
+		    remote_message->message, remote_message->wParam,
+		    remote_message->lParam);
+     }
+     else
+	return 0;		   /* no DDE message found */
+  }
+
+  /* At this point we are sure that there is a DDE message,
+   * was_sent is TRUE is the message was sent, and false if it was posted
+   */
+
+  nesting++;
+
+  if (debugging_dde) {
+     char *title;
+     if (was_sent)
+	title="receive sent dde:";
+     else
+	title="receive posted dde:";
+     print_dde_message(title, remote_message);
+  }
+
+  if (remote_message->hwnd != (HWND) -1 ) {
+    HWND dde_window= DDE_WIN_INFO(remote_message->hwnd).wnd;
+     /* we should know exactly where to send the message (locally)*/
+     if (was_sent) {
+	dprintf_dde(stddeb,
+		    "SendMessage(wnd=0x%04x, msg=0x%04x, wPar=0x%04x,"
+		    "lPar=0x%08x\n",
+		    dde_window, remote_message->message,
+		    remote_message->wParam, (int)remote_message->lParam);
+
+	/* execute the recieved message */
+	passed= SendMessage(dde_window, remote_message->message,
+			    remote_message->wParam, remote_message->lParam);
+
+	/* Tell the sended, that the message is here */
+	dde_proc_send_ack(remote_message->wParam, passed);
+     }
+     else {
+	passed= PostMessage(dde_window, remote_message->message,
+			    remote_message->wParam, remote_message->lParam);
+	if (passed == FALSE) {
+	   /* Tell the sender, that the message is here, and failed */
+	    dde_proc_send_ack(remote_message->wParam, FALSE);
+	}
+	else {
+	   /* ack will be sent later, at the first peek/get message  */
+	   dde_proc_add_fifo(remote_message->wParam);
+	}
+     }
+     nesting--;
+     return 1;
+  }
+
+  /* iterate through all the windows */
+  for (hwnd = GetTopWindow(GetDesktopWindow());
+       hwnd && (window = WIN_FindWndPtr(hwnd))!=NULL ;
+       hwnd = window->hwndNext) {
+     if (window->dwStyle & WS_POPUP || window->dwStyle & WS_CAPTION) {
+	if (was_sent)
+	   SendMessage( hwnd, remote_message->message,
+			remote_message->wParam, remote_message->lParam );
+	else
+	   PostMessage( hwnd, remote_message->message,
+		     remote_message->wParam, remote_message->lParam );
+     } /* if */
+  } /* for */
+
+  /* replay with DDE_ACK after broadcasting in DDE_GetRemoteMessage */
+  dde_proc_send_ack(remote_message->wParam, TRUE);
+
+  nesting--;
+  return 1;
+}
+
+int dde_reschedule()
+{
+    int ack_wnd;
+	
+    ack_wnd= dde_proc_shift_fifo();
+    if (ack_wnd != -1) {
+	dde_proc_send_ack(ack_wnd, TRUE);
+	usleep(10000);		/* force unix task switch */
+	return 1;
+    }
+    return 0;
+}
+void dde_msg_setup(int *msg_ptr)
+{
+  *msg_ptr= msgget (IPC_PRIVATE, IPC_CREAT | 0700);
+  if (*msg_ptr==-1)
+     perror("dde_msg_setup fails to get message queue");
+}
+
+/* do we have dde handling in the window ?
+ * If we have, atom usage will make this instance of wine set up
+ * it's IPC stuff.
+ */
+void DDE_TestDDE(HWND hwnd)	   
+{
+
+  if (main_block != NULL)
+     return;
+  dprintf_msg(stddeb,"DDE_TestDDE(0x%04x)\n", hwnd);
+  if (hwnd==0)
+      hwnd=-1;
+  /* just send a message to see how things are going */
+  SendMessage( hwnd, WM_DDE_INITIATE, 0, 0);
+}
+
+void dde_proc_delete(int proc_idx)
+{
+  dde_proc_done(&main_block->proc[proc_idx]);
+}
+void stop_wait(int a)
+{
+
+  had_SIGUSR2=1;
+  switch(stop_wait_op) {
+    case STOP_WAIT_ACK:
+      siglongjmp(env_get_ack,1);
+      break;  /* never reached */
+    case STOP_WAIT_X:
+      siglongjmp(env_wait_x,1);
+      break;  /* never reached */
+    case CONT:
+      /* do nothing */
+  }
+}
+
+static void print_dde_message(char *desc, MSG *msg)
+{
+    extern const char *MessageTypeNames[];
+    extern int debug_last_handle_size;
+    WORD wStatus,hWord;
+    void *ptr;
+    DDEACK *ddeack;
+    DDEADVISE *ddeadvise;
+    DDEDATA *ddedata;
+    DDEPOKE *ddepoke;
+
+    if (is_dde_handle(msg->lParam & 0xffff) )
+	ptr=DDE_AttachHandle(msg->lParam&0xffff, NULL);
+    else
+	ptr =NULL;
+    wStatus=LOWORD(msg->lParam);
+    hWord=HIWORD(msg->lParam);
+
+    fprintf(stddeb,"%s", desc);
+    fprintf(stddeb,"%04x %04x==%s %04x %08lx ",
+	    msg->hwnd, msg->message,MessageTypeNames[msg->message],
+	    msg->wParam, msg->lParam);
+    switch(msg->message) {
+      case WM_DDE_INITIATE:
+      case WM_DDE_REQUEST:
+      case WM_DDE_EXECUTE:
+      case WM_DDE_TERMINATE:
+	/* nothing to do */
+	break;
+      case WM_DDE_ADVISE:
+	/* DDEADVISE: hOptions in WM_DDE_ADVISE message */
+	if (ptr) {
+	   ddeadvise=ptr;
+	   fprintf(stddeb,"fDeferUpd=%d,fAckReq=%d,cfFormat=0x%x",
+		   ddeadvise->fDeferUpd, ddeadvise->fAckReq,
+		   ddeadvise->cfFormat);
+	} else
+	   fprintf(stddeb,"NO-DATA");
+	fprintf(stddeb," atom=0x%x",hWord);
+	break;
+
+      case WM_DDE_UNADVISE:
+	fprintf(stddeb,"format=0x%x, atom=0x%x",wStatus,hWord);
+	break;
+      case WM_DDE_ACK:
+	ddeack=(DDEACK*)&wStatus;
+	fprintf(stddeb,"bAppReturnCode=%d,fBusy=%d,fAck=%d",
+		ddeack->bAppReturnCode, ddeack->fBusy, ddeack->fAck);
+	if (ddeack->fAck)
+	   fprintf(stddeb,"(True)");
+	else
+	   fprintf(stddeb,"(False)");
+	break;
+
+      case WM_DDE_DATA:
+	if (ptr) {
+	   ddedata=ptr;
+	   fprintf(stddeb,"fResponse=%d,fRelease=%d,"
+		   "fAckReq=%d,cfFormat=0x%x,value=\"%.*s\"",
+		   ddedata->fResponse, ddedata->fRelease,
+		   ddedata->fAckReq, ddedata->cfFormat,
+		   debug_last_handle_size- (int)sizeof(*ddedata)+1,
+		   ddedata->Value);
+	} else
+	   fprintf(stddeb,"NO-DATA");
+	fprintf(stddeb," atom=0x%04x",hWord);
+	break;
+
+      case WM_DDE_POKE:
+	if (ptr) {
+	   ddepoke=ptr;
+	   fprintf(stddeb,"fRelease=%d,cfFormat=0x%x,value[0]='%c'",
+		   ddepoke->fRelease, ddepoke->cfFormat, ddepoke->Value[0]);
+	} else
+	   fprintf(stddeb,"NO-DATA");
+	fprintf(stddeb," atom=0x%04x",hWord);
+	break;
+    }
+    fprintf(stddeb,"\n");
+}
+
+void dde_proc_done(dde_proc proc)
+{
+  if (proc->msg != -1)
+     msgctl(proc->msg, IPC_RMID, NULL);
+  proc->msg=-1;
+  proc->pid=-1;
+  shm_delete_chain(&proc->shmid);
+  shm_sem_done(&proc->sem);
+}
+
+/* delete entry, if old junk */
+void dde_proc_refresh(dde_proc proc)
+{
+  if (proc->pid == -1)		  
+     return;
+  
+  if (kill(proc->pid, 0) != -1)
+     return;
+
+  /* get here if entry non empty, and the process does not exist */
+  dde_proc_done(proc);
+}
+
+void dde_wnd_setup()
+{
+  int i;
+
+  for (i=0 ; i < DDE_WINDOWS ; i++)
+    main_block->windows[i].proc_idx = FREE_WND;
+}
+
+static BOOL DDE_ProcHasWindows(int proc_idx)
+{
+  WND_DATA *tested;
+  int i;
+  
+  for ( i=0 ; i < DDE_WINDOWS ; i++) {
+    tested= &main_block->windows[ i ];
+    
+    if (tested->proc_idx == proc_idx) 
+      return TRUE;
+  }
+  return FALSE;
+}
+/* Look for hwnd in the hash table of DDE windows,
+ * Delete it from there. If there are no more windows for this
+ * process, remove the process from the DDE data-structure.
+ * If there are no more processes - delete the whole DDE struff.
+ *
+ * This is inefficient, but who cares for the efficiency of this rare
+ * operation... 
+ */
+void DDE_DestroyWindow(HWND hwnd)
+{
+  int dde_wnd_idx;
+  WND_DATA *tested;
+  int i;
+  
+  if (main_block == NULL)
+    return;
+  
+  dde_wnd_idx= hwnd % DDE_WINDOWS;
+  
+  for ( i=0 ; i < DDE_WINDOWS ; i++, dde_wnd_idx++) {
+    if (dde_wnd_idx >= DDE_WINDOWS)
+      dde_wnd_idx -= DDE_WINDOWS; /* wrap-around */
+    
+    tested= &main_block->windows[ dde_wnd_idx ];
+    if (tested->proc_idx == FREE_WND)
+      return;			/* No window will get deleted here */
+    
+    if (tested->wnd == hwnd && tested->proc_idx == curr_proc_idx) {
+      dde_reschedule();
+      tested->proc_idx= DELETED_WND;
+      if (DDE_ProcHasWindows( curr_proc_idx ))
+	return;
+      while (dde_reschedule())	/* make sure there are no other */
+				/* processes waiting for acknowledgment */
+	;
+      dde_proc_delete( curr_proc_idx );
+      if (DDE_no_of_attached() == 1)
+	shm_delete_all(-1);
+      else {
+	shmdt( (void *) main_block);
+	main_block= NULL;
+      }
+      return;
+    }
+  }
+}
+
diff --git a/ipc/dde_proc_test.c b/ipc/dde_proc_test.c
new file mode 100644
index 0000000..1291fd8
--- /dev/null
+++ b/ipc/dde_proc_test.c
@@ -0,0 +1,117 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      dde_proc.c
+ * Purpose :  test DDE signals and processes functionality for DDE
+ * Usage:     run two independant processes, one with an argument another
+ *            without (with the argument is the server).
+ ***************************************************************************
+ */
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#include <sys/syscall.h>
+#include <sys/param.h>
+#else
+#include <syscall.h>
+#endif
+#include <stdio.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <win.h>
+#include "dde.h"
+#include "dde_proc.h"
+#include "shm_main_blk.h"
+
+#if !defined(BSD4_4) || defined(linux) || defined(__FreeBSD__)
+char * cstack[4096];
+#endif
+#ifdef linux
+extern void ___sig_restore();
+extern void ___masksig_restore();
+
+/* Similar to the sigaction function in libc, except it leaves alone the
+   restorer field */
+
+static int
+wine_sigaction(int sig,struct sigaction * new, struct sigaction * old)
+{
+	__asm__("int $0x80":"=a" (sig)
+		:"0" (SYS_sigaction),"b" (sig),"c" (new),"d" (old));
+	if (sig>=0)
+		return 0;
+	errno = -sig;
+	return -1;
+}
+#endif
+
+struct sigaction usr2_act;
+
+
+void init_signals()
+{
+#ifdef linux
+  usr2_act.sa_handler = (__sighandler_t) stop_wait;
+  usr2_act.sa_flags = 0;
+  usr2_act.sa_restorer = 
+    (void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
+  wine_sigaction(SIGUSR2,&usr2_act,NULL);
+#endif
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+  usr2_act.sa_hadnler = (void (*)) stop_wait;
+  usr2_act.sa_flags = SA_ONSTACK;
+  usr2_act.sa_mask = sig_mask;
+  usr2_act.sa_restorer = 
+    (void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
+  if (sigaction(SIGUSR2,&usr2_act,NULL) <0) {
+     perror("sigaction: SIGUSR2");
+     exit(1);
+  }
+#endif  
+}
+void ATOM_GlobalInit()
+{
+  printf("ATOM_GlobalInit\n");
+}
+
+
+void idle_loop()
+{
+  int timeout;
+  for(timeout=500; timeout ; timeout--) {
+     if (DDE_GetRemoteMessage())
+         exit(0); ;
+     usleep(1000);
+  }
+  exit(-1);
+}
+
+void client()
+{
+  MSG msg;
+  msg.hwnd=(HWND)-1;
+  msg.message= WM_DDE_INITIATE;
+  msg.wParam= 3;
+  msg.lParam= 4;
+  if (!DDE_SendMessage(&msg))
+       exit(-1);
+  idle_loop();
+}
+void server()
+{
+  DDE_IPC_init();
+  idle_loop();
+}
+
+int main(int argc, char *argv[])
+{
+  printf("Kill when done one message\n");
+  init_signals();
+  if (argc>1)
+     server();
+  else
+     client();
+  return 0;
+}
diff --git a/ipc/generic_hash.c b/ipc/generic_hash.c
new file mode 100644
index 0000000..6cee5d3
--- /dev/null
+++ b/ipc/generic_hash.c
@@ -0,0 +1,678 @@
+/***************************************************************************
+ * Copyright 1995 Michael Veksler. mveksler@vnet.ibm.com
+ ***************************************************************************
+ * File:      generic_hash.c
+ * Purpose :  dynamically growing hash, may use shared or local memory.
+ ***************************************************************************
+ */
+#include <stdlib.h>
+#include <assert.h>
+#include "generic_hash.h"
+
+#define ROUND_UP4(num) (( (num)+3) & ~3)
+
+#define FREE_ENTRY          0
+#define DELETED_ENTRY       ((DWORD)-1)
+
+#define NO_OF_PRIMES   512
+#define GET_ITEM(items,size,i)\
+           (*(HASH_ITEM*) \
+	    (  ((char *)(items))+ \
+	       (i)*(size)) )
+
+static HASH_ITEM *locate_entry(HASH_CONTAINER* hash, DWORD key,
+			       HASH_VAL *seeked_data, BOOL skip_deleted);
+
+static void copy_hash_items(HASH_CONTAINER *hash, HASH_ITEM *old_items,
+			    int old_n_items);
+
+static BOOL arrays_initialized = FALSE;
+static int primes[NO_OF_PRIMES];
+static int best_primes[NO_OF_PRIMES];
+static int no_of_primes;
+static int no_of_best_primes;
+static int max_num;
+
+/* binary search for `num' in the `primes' array */
+static BOOL prime_binary_search_found(int num)
+{
+  int min_idx, max_idx, idx;
+  
+  min_idx=0;
+  max_idx=no_of_primes-1;
+  
+  while (min_idx <= max_idx) {
+     idx = (max_idx + min_idx) >> 1;
+     if (num == primes[idx])
+	return TRUE;
+     if (num < primes[idx])
+	max_idx = idx-1;
+     else
+	min_idx = idx+1;
+  }
+  return FALSE;
+}
+
+static BOOL is_prime(int num)
+{
+  int i;
+  if ((num & 0x1) == 0)		   /* can be divided by 2 */
+     if (num == 2) 
+	return TRUE;
+     else
+	return FALSE;
+  
+  if (num <= primes[no_of_primes-1]) 
+     return prime_binary_search_found(num);
+
+  for (i=0 ; i < no_of_primes ; i++) {
+     if (num % primes[i] == 0)
+	return FALSE;
+     if (num < primes[i] * primes[i])
+	return TRUE;
+  }
+  return TRUE;
+}
+
+static void setup_primes()
+{
+  int num;
+  
+  primes[0]=2;
+  primes[1]=3;
+  no_of_primes=2;
+  
+  /* count in modulo 6 to avoid numbers that divide by 2 or 3 */
+  for (num=5 ; ; num+=6) {
+     if (is_prime(num)) {
+	primes[no_of_primes++]=num;
+	if (no_of_primes >= NO_OF_PRIMES)
+	   break;
+     }
+     if (is_prime(num+2)) {
+	primes[no_of_primes++]=num+2;
+	if (no_of_primes >= NO_OF_PRIMES)
+	   break;
+     }
+  }
+  max_num= primes[no_of_primes-1] * primes[no_of_primes-1];
+}
+
+
+/* Find primes which are far "enough" from powers of two */
+
+void setup_best_primes()
+{
+  int i;
+  int num;
+  int pow2before, pow2after;
+  int min_range, max_range;
+
+  min_range=3;
+  max_range=3;
+  pow2before= 2;
+  pow2after= 4;
+
+  no_of_best_primes= 0;
+  for (i=0 ; i < no_of_primes ; i++){
+     num= primes[i];
+
+     if (num > pow2after) {
+	pow2before= pow2after;
+	pow2after <<=1;
+	min_range= pow2before+ (pow2before >> 3);
+	max_range= pow2after-  (pow2before >> 2);
+     }
+     if (num > min_range && num < max_range) 
+	best_primes[no_of_best_primes++]=num;
+  }
+}
+
+/* binary search for `num' in the `best_primes' array,
+ * Return smallest best_prime >= num.
+ */
+static int best_prime_binary_search(int num)
+{
+  int min_idx, max_idx, idx;
+  
+  min_idx=0;
+  max_idx=no_of_best_primes-1;
+  
+  while (1) {
+     idx = (max_idx + min_idx) >> 1;
+     if (num == best_primes[idx])
+	return num;
+     if (num < best_primes[idx]) {
+	max_idx = idx-1;
+	if (max_idx <= min_idx)
+	    return best_primes[idx];
+    }
+     else {
+	min_idx = idx+1;
+	if (min_idx >= max_idx)
+	    return best_primes[max_idx];
+    }
+  }
+
+}
+
+/* Find the best prime, near `num' (which can be any number) */
+static int best_prime(int num)
+{
+  int log2;
+  int pow2less, pow2more;
+  int min_range, max_range;
+
+  if (num < 11)
+     return 11;
+  
+  if (num <= best_primes[no_of_best_primes-1])
+     return best_prime_binary_search(num);
+
+  assert( num < max_num );
+
+  for (log2=0 ; num >> log2 ; log2++)
+     ;
+
+  pow2less= 1 << log2;
+  pow2more= 1 << (log2+1);
+  min_range= pow2less + (pow2less >> 3);
+  max_range= pow2more - (pow2more >> 3);
+
+  if (num < min_range)
+     num= min_range;
+
+  num |= 1;			   /* make sure num can't be divided by 2 */
+  
+  while (1) {
+     if (num >= max_range) {
+	pow2less<<= 1;
+	pow2more<<= 1;
+	min_range= pow2less + (pow2less >> 3);
+	max_range= pow2more - (pow2more >> 3);
+	num= min_range | 1;	   /* make sure num can't be divided by 2 */
+     }
+     /* num should be here in the range: (min_range, max_range) */
+     if (is_prime(num))
+	return num;
+     num+=2;
+  }
+}
+
+/* FIXME: This can be done before compiling. (uning a script)*/
+static void setup_arrays()
+{
+  setup_primes();
+  setup_best_primes();
+}
+
+/* Discard all DELETED_ENTRYs moving the data to it's correct location.
+ * Done without a temporary buffer.
+ * May require some efficiency improvements ( currently it's o(N^2)
+ * or is it o(N^3) in the worst case ? In the avarege it seems to be
+ * something like o(N log (N)))
+ */
+static void static_collect_garbge(HASH_CONTAINER *hash)
+{
+   int i;
+   BOOL change;
+   HASH_ITEM *items;
+   HASH_ITEM *located;
+   HASH_ITEM *item;
+   int key;
+  
+   items= hash->items;
+   
+   do {
+      change= FALSE;
+      for (i=hash->shared->total_items-1 ; i >= 0 ; i--) {
+	 item= &GET_ITEM(items,hash->bytes_per_item,i);
+	 key= item->key;
+	 if (key != DELETED_ENTRY && key != FREE_ENTRY) {
+	    /* try to place the entry in a deleted location */
+	    located= locate_entry(hash, key, &item->data,
+				  0 /* no skip_deleted */);
+	    if (located->key == DELETED_ENTRY) {
+	       change= TRUE;
+	       memcpy(&located, &item,
+		      hash->bytes_per_item);
+	       item->key= DELETED_ENTRY;
+	    }
+	 }
+      }
+   } while (change);
+
+   /* No change means that there is no need to go through a DELETED_ENTRY
+    * in order to reach an item, so DELETED_ENTRY looses it's special
+    * meaning, and it is the same as FREE_ENTRY.
+    */
+   for (i=hash->shared->total_items-1 ; i >= 0 ; i--)
+      if (GET_ITEM(items,hash->bytes_per_item,i).key == DELETED_ENTRY)
+	 GET_ITEM(items,hash->bytes_per_item,i).key = FREE_ENTRY;
+   hash->shared->deleted_items=0;
+}
+
+static void collect_garbge(HASH_CONTAINER *hash)
+{
+   HASH_SHARED *shared= hash->shared;
+   HASH_ITEM *temp_items;
+   int size;
+    
+   size= shared->total_items * hash->bytes_per_item;
+   temp_items= (HASH_ITEM*)malloc(size);
+   if (temp_items==NULL) {
+      static_collect_garbge(hash);
+   } else {
+      memcpy(temp_items, hash->items, size);
+      copy_hash_items(hash, temp_items, shared->total_items);
+   }
+}
+
+
+static void copy_hash_items(HASH_CONTAINER *hash, HASH_ITEM *old_items,
+			    int old_n_items)
+{
+   HASH_SHARED *shared= hash->shared;
+   HASH_ITEM *item;
+   int i;
+   
+   shared->deleted_items = 0;
+   shared->free_items= shared->total_items;
+   
+   /* make all items free */
+   for (i= shared->total_items-1 ; i>=0 ; i--)
+      GET_ITEM(hash->items, hash->bytes_per_item, i).key = FREE_ENTRY;
+   
+   /* copy items */
+   for (i=0 ; i <= old_n_items; i++) {
+      item= &GET_ITEM(old_items, hash->bytes_per_item,i);
+      if (item->key != FREE_ENTRY && item->key != DELETED_ENTRY)
+	 hash_add_item(hash, item->key, &item->data);
+   } 
+}
+
+
+static void reorder_hash(HASH_CONTAINER *hash)
+{
+  HASH_SHARED *shared= hash->shared;
+  HASH_ITEM *items, *old_items;
+  HASH_PTR shared_items, old_shared_items;
+  int n_items, old_n_items;
+  int size;
+
+  if (shared->deleted_items > hash->min_free_items) {
+     collect_garbge(hash);
+     return;
+  }
+  n_items= best_prime(shared->total_items * HASH_REALLOC_JUMPS);
+
+  size= n_items *
+	(sizeof(items[0]) - sizeof(items[0].data) + hash->bytes_per_item);
+ 
+  shared_items= hash->allocate_mem(size);
+  items= hash->access_mem(shared_items);
+  
+  if (items == NULL) {
+	collect_garbge(hash);
+	return;
+  }
+  old_shared_items = shared->items;
+  old_n_items=       shared->total_items;
+  old_items=         hash->items;
+
+  /* setup a new clean hash based on the parameters of the original one */
+  hash->items=          items;
+  shared->total_items = n_items;
+  shared->items=        shared_items;
+  set_hash_parameters(hash, hash->maximum_load);
+  copy_hash_items(hash, old_items, old_n_items);
+  
+  hash->free_mem(old_shared_items);
+  hash->last_ptr_update= ++shared->ptr_updates;
+}
+
+/* low level: attach hash existing hash items, no checks are performed
+ * No complex calculations done.
+ */
+static HASH_CONTAINER *attach_no_check(HASH_ITEM *items, int bytes_per_datum)
+{
+    HASH_CONTAINER *hash;
+    int bytes_per_item;
+    HASH_ITEM dummy_item;
+    
+    hash= (HASH_CONTAINER*) malloc(sizeof(HASH_CONTAINER) );
+    if (hash == NULL)
+	return NULL;
+    
+    bytes_per_item= bytes_per_datum+
+                    sizeof(dummy_item)-sizeof(dummy_item.data);
+    hash->bytes_per_item= ROUND_UP4(bytes_per_item);
+    hash->items=          items;
+    hash->is_correct_item= NULL;
+    hash->allocate_mem=   HASH_MEM_ALLOC;
+    hash->access_mem=     HASH_MEM_ACCESS;
+    hash->free_mem=       HASH_MEM_FREE;
+    set_hash_parameters(hash, HASH_LOAD);
+    
+
+    return hash;
+}
+
+
+/* Attach existing & running remote (i.e. shared) hash.
+ * Attach the items using the data stored in "shared"
+ */
+HASH_CONTAINER *attach_remote_hash(HASH_SHARED *shared, int bytes_per_datum,
+				   HASH_ITEM *(*access_mem)(HASH_PTR))
+{
+    HASH_CONTAINER *hash;
+    HASH_ITEM *items;
+
+    assert(access_mem != NULL);
+    if (! arrays_initialized)
+	setup_arrays();
+
+    items=access_mem(shared->items);
+    hash= attach_no_check(items, bytes_per_datum);
+    if (hash == NULL)
+	return NULL;
+    
+    hash->shared_was_malloced = FALSE;
+    hash->shared= shared;
+    return (hash);
+}
+
+
+HASH_CONTAINER *create_remote_hash(HASH_SHARED *shared,
+				   int bytes_per_datum,
+				   int total_items,
+				   HASH_PTR (*allocate_mem)(int size),
+				   HASH_ITEM *(*access_mem)(HASH_PTR))
+{
+   HASH_CONTAINER *hash;
+   int size;
+   int i;
+    
+   assert(total_items >= 1);
+   assert(bytes_per_datum >=1);
+   assert(access_mem != NULL);
+   assert(allocate_mem != NULL);
+   assert(shared != NULL);
+   if (! arrays_initialized)
+      setup_arrays();
+
+   if (total_items < MIN_HASH)
+      total_items= MIN_HASH;
+   else 
+      total_items= best_prime(total_items);
+
+   hash= attach_no_check(NULL, bytes_per_datum);
+    
+   if (hash==NULL) {
+      free(hash);
+      return NULL;
+   }
+    
+   shared->total_items=  total_items;
+   hash->shared= shared;
+   hash->shared_was_malloced = FALSE;
+
+   size= total_items * hash->bytes_per_item;
+
+   shared->items = allocate_mem(size);
+   hash->items=    access_mem(shared->items);
+    
+   if (hash->items == NULL ) {
+      free(hash);
+      return NULL;
+   }
+   shared->items.ptr= hash->items;
+    
+   /* make all items free */
+   for (i=0 ; i < total_items ; i++)
+      GET_ITEM(hash->items,hash->bytes_per_item,i).key = FREE_ENTRY;
+    
+   shared->deleted_items= 0;
+   shared->free_items= total_items;
+   shared->ptr_updates= 0;
+   return hash;
+
+}
+
+/* hash constructor: create brand new hash */
+HASH_CONTAINER *create_hash(int bytes_per_datum, int total_items)
+{
+   HASH_CONTAINER *hash;
+   HASH_SHARED *shared;
+
+   
+   shared= (HASH_SHARED*)malloc(sizeof(HASH_SHARED));
+   if (shared == NULL)
+      return NULL;
+   
+   hash= create_remote_hash(shared, bytes_per_datum, total_items,
+			    HASH_MEM_ALLOC, HASH_MEM_ACCESS);
+
+   if (hash == NULL) {
+      free(shared);
+      return NULL;
+   }
+   
+   hash->shared_was_malloced = TRUE;
+   return hash;
+}
+
+/* set the extra handlers to non default values */
+void set_hash_handlers(HASH_CONTAINER *hash,
+		       HASH_ITEM_TEST *is_correct_item,
+		       HASH_PTR (*allocate_mem)(int size),
+		       void     (*free_mem)(HASH_PTR),
+		       HASH_ITEM *(*access_mem)(HASH_PTR))
+{
+   assert(hash);
+   assert(allocate_mem);
+   assert(free_mem);
+    
+   hash->free_mem     = free_mem;
+   hash->allocate_mem = allocate_mem;
+   hash->access_mem   = access_mem;
+   hash->is_correct_item = is_correct_item;
+}
+
+
+/* set extra parameters */
+void set_hash_parameters(HASH_CONTAINER *hash, int load)
+{
+   assert(hash);
+   assert(load>30);		/* no sence to realloc with less than */
+				/* 50% load, limiting to 30% to be on */
+				/* the safe size */
+   assert(load<=100);
+    
+   hash->maximum_load=   load;
+   hash->min_free_items= (1.0 - load/100.0) * hash->shared->total_items + 1 ;
+}
+
+/* hash destructor: destroy anything related to the hash */
+void destroy_hash(HASH_CONTAINER *hash)
+{
+   assert(hash);
+   hash->free_mem(hash->shared->items);
+   if (hash->shared_was_malloced)
+      free(hash->shared);
+   free(hash);
+}
+
+/* hash destructor: just detach hash, without destroing it (makes */
+/* sence in shared memory environment) */
+void detach_hash(HASH_CONTAINER *hash)
+{
+   assert(hash);
+   free(hash);
+}
+
+
+/********** Hash usage *************/
+static __inline__ BOOL
+correct_entry(HASH_ITEM *item, int key, HASH_VAL *seeked_data,
+	      HASH_ITEM_TEST *is_correct_item, BOOL skip_deleted)
+{
+   switch(item->key) {
+      case FREE_ENTRY:
+	 return TRUE;
+	
+      case DELETED_ENTRY:
+	 return skip_deleted ? FALSE : TRUE;
+	
+      default:
+	 if (item->key != key)
+	    return FALSE;
+	 if (is_correct_item != NULL)
+	    return is_correct_item(&item->data, seeked_data);
+	 else 
+	    return TRUE;
+   }
+
+}
+
+/* The algorithm of the hash (one of the 2 standard hash implementations):
+ *   Iterate through the hash table until
+ *    1. The entry has been found.
+ *    2. A FREE entry has been found.
+ *    3. For insert operations only- A DELETED entry has been found.
+ *       The difference between DELETED and FREE entires is that
+ *       DELETED entry was one occupied, while FREE was never allocated.
+ *       The idea behind this structure to keep other entries reachable.
+ */
+
+static HASH_ITEM *locate_entry(HASH_CONTAINER* hash, DWORD key,
+			       HASH_VAL *seeked_data, BOOL skip_deleted)
+{
+   DWORD hash_idx, hash_leaps;
+   HASH_ITEM *item;
+   int i;
+   int total_items;
+    
+   assert(hash);
+
+   total_items=     hash->shared->total_items;
+   hash_idx=        key % total_items;
+   
+   item= &GET_ITEM(hash->items, hash->bytes_per_item, hash_idx);
+    
+   if (  correct_entry( item, key, seeked_data,
+			hash->is_correct_item, skip_deleted)   )
+      return item;
+
+   /* get the WORDs in different order in this DWORD to avoid clustering */
+   hash_leaps=((DWORD)MAKELONG(HIWORD(key), LOWORD(key))
+	       % (total_items-1)) +1;
+
+   /* interate through the hash table using hash_leaps */
+   for (i= total_items ; i ; i--) {
+      hash_idx+= hash_leaps;
+      if (hash_idx > total_items)
+	 hash_idx -= total_items;
+	
+      item= &GET_ITEM(hash->items,hash->bytes_per_item, hash_idx);
+      if (  correct_entry( item, key, seeked_data,
+			   hash->is_correct_item, skip_deleted)   )
+	 return item;
+   }
+   return NULL;
+    
+}
+
+static __inline__ void sync_shared_hash(HASH_CONTAINER *hash)
+{
+    HASH_SHARED *shared= hash->shared;
+    
+    if (shared->ptr_updates == hash->last_ptr_update)
+	return;
+    
+    assert(shared->ptr_updates >= hash->last_ptr_update);
+    hash->last_ptr_update= shared->ptr_updates;
+    hash->min_free_items= (1.0 - hash->maximum_load/100.0) *
+	shared->total_items + 1 ;
+
+    hash->items= hash->access_mem(shared->items);
+}
+
+HASH_VAL *hash_locate_item(HASH_CONTAINER* hash,
+			   int key, HASH_VAL *seeked_data)
+{
+    HASH_ITEM *item;
+    
+    assert(hash != NULL);
+    sync_shared_hash(hash);
+    
+    item= locate_entry(hash, key, seeked_data, 1 /* skip_deleted */);
+    if (item == NULL)
+	return NULL;
+    if (item->key == FREE_ENTRY )
+	return NULL;
+
+    return &item->data;
+}
+
+
+BOOL hash_add_item(HASH_CONTAINER* hash, int key, HASH_VAL *data)
+{
+    HASH_SHARED *shared;
+    HASH_ITEM *item;
+    
+    assert(hash != NULL);
+
+    sync_shared_hash(hash);
+    shared= hash->shared;
+    
+    item=locate_entry(hash, key, data, 0 /* no skip_deleted */);
+    assert(item != NULL);
+    if (item->key == key)
+	return FALSE;
+    if (item->key == FREE_ENTRY)
+       shared->free_items--;
+    else
+       shared->deleted_items--;
+    
+    item->key=  key;
+    memcpy(&item->data, data, hash->bytes_per_item-sizeof(key));
+
+    if (shared->free_items < hash->min_free_items ||
+	shared->deleted_items > hash->min_free_items)
+       reorder_hash(hash);
+    
+    return TRUE;
+}
+
+
+BOOL hash_delete_item(HASH_CONTAINER* hash, int key, HASH_VAL *seeked_data)
+{
+    HASH_ITEM *item;
+    
+    assert(hash != NULL);
+    sync_shared_hash(hash);
+
+    item=locate_entry(hash, key, seeked_data, 1 /* skip_deleted */);
+    if (item == NULL)
+	return FALSE;
+
+    if (item->key == FREE_ENTRY) 
+	return FALSE;
+
+    item->key = DELETED_ENTRY;
+    hash->shared->deleted_items++;
+
+    return TRUE;
+}
+
+void *ret_null()
+{
+    return NULL;
+}
+
+
+HASH_ITEM *access_local_hash(HASH_PTR ptr)
+{
+   return ptr.ptr;
+}
diff --git a/ipc/generic_hash.h b/ipc/generic_hash.h
new file mode 100644
index 0000000..5def7e6
--- /dev/null
+++ b/ipc/generic_hash.h
@@ -0,0 +1,141 @@
+/***************************************************************************
+ * Copyright 1995    Michael Veksler. mveksler@vnet.ibm.com
+ ***************************************************************************
+ * File:      generic_hash.h 
+ * Purpose :  dynamically growing hash, may use shared or local memory.
+ ***************************************************************************
+ */
+#ifndef _GENERIC_HASH_H_
+#define _GENERIC_HASH_H_
+
+#include "wintypes.h"
+#include "shm_block.h"
+/* default hash values */
+#define HASH_LOAD           70
+#define HASH_MEM_ALLOC      (HASH_PTR (*)(int size)) malloc
+#define HASH_MEM_FREE       (void (*)(HASH_PTR)) free
+#define HASH_MEM_ACCESS     access_local_hash
+#define HASH_REALLOC_JUMPS  1.5	 /* Relative size of the new memory */
+#define MIN_HASH            13
+
+typedef union {
+    char string[1];
+    WORD words[1];
+    DWORD dwords[1];
+    char *ptr;
+    SEGPTR segptr;
+} HASH_VAL;
+
+typedef struct hash_item_struct {
+    DWORD key;
+    HASH_VAL data;
+} HASH_ITEM;
+
+/* point to the hash structure */
+typedef union {
+    HASH_ITEM* ptr;		/* Local pointer */
+    REL_PTR    rel;			/* IPC relative address */
+    SEGPTR segptr;		/* Universal (can be IPC or local) */
+} HASH_PTR;
+
+typedef struct hash_share_struct {
+    int total_items;		/* total number of items (array size) */
+    int free_items;		/* number of free items (excluding deleted) */
+    int deleted_items;		/* number of deleted items */
+    int ptr_updates;		/* Number of updates to `items' pointer */
+				/* (of items) - used for intecepting */
+				/* changes to the pointer. */
+    HASH_PTR items;		/* pointer to the items */
+} HASH_SHARED;
+typedef BOOL HASH_ITEM_TEST(HASH_VAL *value, HASH_VAL *seeked_data);
+
+/* NOTE:
+ * 1. Keys 0 and -1 are reserved.
+ * 2. none of these items should be accessed directly, use existing
+ *    functions. If they are not enough, add a new function.
+ */
+typedef struct hash_container_struct {
+    int bytes_per_item;
+    int maximum_load;		/* in percents (0..100) default is 70 */
+    int min_free_items;		/* minimum free items before reallocating 
+				   (Function of maximum_load) */
+
+    int last_ptr_update;	/* to be compared with shared.ptr_updates */
+    BOOL shared_was_malloced;	/* Need that to know how to destroy hash */
+    
+    /* This is an optional handler.
+     * If not NULL, this function is used for distinguishing between
+     * different data with the same key (key field holds integer and
+     * is too short for long keys like strings).
+     */
+    HASH_ITEM_TEST *is_correct_item;
+
+    /* Handlers used for reallocating memory
+     * [by allocating new data and then freeing old data]
+     */
+    HASH_PTR (*allocate_mem)(int size);
+    void     (*free_mem)(HASH_PTR);
+
+    /* Translator from HASH_PTR construct to a regular pointer.
+       use HASH_MEM_ACCESS, if no translation is needed */
+    HASH_ITEM *(*access_mem)(HASH_PTR);
+
+    HASH_ITEM *items;
+    HASH_SHARED *shared;	/* Things to be on shared memory. */
+} HASH_CONTAINER;
+
+
+/********** Hash maintenance functions ***********/
+
+
+
+/* Attach existing & running remote (i.e. shared) hash.
+ * Attach the items using the data stored in "shared"
+ */
+HASH_CONTAINER *attach_remote_hash(HASH_SHARED *shared, int bytes_per_datum,
+				   HASH_ITEM *(*access_mem)(HASH_PTR));
+
+
+HASH_CONTAINER *create_remote_hash(HASH_SHARED *shared,
+				   int bytes_per_datum,
+				   int total_items,
+				   HASH_PTR (*allocate_mem)(int size),
+				   HASH_ITEM *(*access_mem)(HASH_PTR));
+/* hash constructor: create brand new hash (not on shared memory) */
+HASH_CONTAINER *create_hash(int bytes_per_datum, int total_items);
+
+/* set the extra handlers to non default values */
+void set_hash_handlers(HASH_CONTAINER *hash,
+		       HASH_ITEM_TEST *is_correct_item,
+		       HASH_PTR (*allocate_mem)(int size),
+		       void     (*free_mem)(HASH_PTR),
+		       HASH_ITEM *(*access_mem)(HASH_PTR));
+
+/* set extra parameters */
+void set_hash_parameters(HASH_CONTAINER *hash, int load);
+
+/* hash destructors */
+void destroy_hash(HASH_CONTAINER *hash);
+void detach_hash(HASH_CONTAINER *hash);
+
+
+/********** Hash usage *************/
+
+/* All following functions have the same format:
+ *  hash- the hash structure to use
+ *  key-  used as primary means to get to the entry.
+ *  data- 1. a secondary key (used only if `is_correct_item' is set).
+ *        2. data to store. (for hash_add_item).
+ */
+HASH_VAL *hash_locate_item(HASH_CONTAINER* hash,int key, HASH_VAL* seeked_data);
+BOOL hash_add_item(HASH_CONTAINER*        hash, int key, HASH_VAL* data);
+BOOL hash_delete_item(HASH_CONTAINER*     hash, int key, HASH_VAL* seeked_data);
+
+
+void *ret_null();		/* function returning null (used for */
+				/* disabling memory reallocation) */
+
+/* access function used by local (non IPC) memory */
+HASH_ITEM *access_local_hash(HASH_PTR ptr);
+
+#endif /* _GENERIC_HASH_H_ */
diff --git a/ipc/hash_test.c b/ipc/hash_test.c
new file mode 100644
index 0000000..dec32c4
--- /dev/null
+++ b/ipc/hash_test.c
@@ -0,0 +1,117 @@
+/***************************************************************************
+ * Copyright 1995 Michael Veksler. mveksler@vnet.ibm.com
+ ***************************************************************************
+ * File:      hash_test.c
+ * Purpose :  test generic_hash correctness.
+ * NOTE:
+ *   This code covers only about 80% of generic_hash code.
+ *   There might be bugs in the remaining 20% - although most
+ *   of the functionality is tested with wine linckage.
+ *   For complete testing a little more work should be done.
+ ***************************************************************************
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include "generic_hash.h"
+
+#define SIZE 200
+typedef struct { int a,b;} DATA ;
+DATA data[SIZE];
+int keys[SIZE];
+int peeks=0;
+
+HASH_CONTAINER *hash1;
+HASH_CONTAINER *hash2;		/* actual data is shared with hash1 */
+
+/* test insertion using keys[] and data[] inserting using hash1 and */
+/* hash2 periodically, test hash after every 2 insertions */
+void test_insert()
+{
+    int i,j;
+    HASH_VAL *item;
+    
+    printf("testing insertion \n");
+    for (i=0 ; i < SIZE-1 ; i+=2) {
+	assert(hash_add_item(hash1, keys[i], (HASH_VAL *)&data[i]));
+	assert(hash_add_item(hash2, keys[i+1], (HASH_VAL *)&data[i+1]));
+	for (j=0 ; j <= i+1 ; j++) {
+	    item= hash_locate_item(hash1, keys[j], (HASH_VAL *)&data[j]);
+	    if (item == NULL) {
+		printf("NULL item: i=%d,j=%d\n",i,j);
+		continue;
+	    }
+	    peeks++;
+	    if (memcmp(item,&data[j],sizeof(DATA))!=0) {
+		printf("i=%d,j=%d\n",i,j);
+		printf("saved=(%d,%d), orig=(%d,%d)\n",
+		       ((DATA*)item)->a, ((DATA*)item)->b,
+		       data[j].a, data[j].b);
+	    }
+	}
+    } 
+}
+
+/* test deletion using keys[] and data[] deleting using hash1 and */
+/* hash2 periodicly, test hash after every 2 deletions */
+void test_delete()
+{
+    int i,j;
+    HASH_VAL *item;
+
+    printf("testing deletion\n");
+    for (i=0 ; i < SIZE-1 ; i+=2) {
+	assert(hash_delete_item(hash2, keys[i], NULL));
+	assert(hash_delete_item(hash1, keys[i+1], NULL));
+	for (j=0 ; j < SIZE ; j++) {
+	    item= hash_locate_item(hash2, keys[j], (HASH_VAL *)&data[j]);
+	    if (item == NULL) {
+		if ( j > i+1) 
+		    printf("NULL item: i=%d,j=%d\n",i,j);
+		continue;
+	    }
+	    if (item != NULL && j <= i+1) {
+		printf("Non NULL item: i=%d,j=%d\n",i,j);
+		continue;
+	    }
+	    if (memcmp(item,&data[j],sizeof(DATA))!=0) {
+		printf("i=%d,j=%d\n",i,j);
+		printf("saved=(%d,%d), orig=(%d,%d)\n",
+		       ((DATA*)item)->a, ((DATA*)item)->b,
+		       data[j].a, data[j].b);
+	    }
+	}
+    } 
+
+}
+
+
+int main()
+{
+    int i;
+    
+    hash1= create_hash(sizeof(DATA), 1);
+    assert(hash1);
+    hash2= attach_remote_hash(hash1->shared, sizeof(DATA), HASH_MEM_ACCESS);
+    assert(hash2);
+
+    for (i=0 ; i< SIZE ; i++) {
+	data[i].a= rand();
+	data[i].b= rand();
+	keys[i]= rand();
+    }
+
+    test_insert();
+    detach_hash(hash1);
+    free(hash1);
+    hash1= attach_remote_hash(hash2->shared, sizeof(DATA), HASH_MEM_ACCESS);
+    
+    test_delete();
+    test_insert();
+
+    detach_hash(hash1);
+    destroy_hash(hash2);
+    printf("peeks=%d\n", peeks);
+    return 0;
+}
diff --git a/ipc/run_tests b/ipc/run_tests
new file mode 100644
index 0000000..638fb18
--- /dev/null
+++ b/ipc/run_tests
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+bit_array_test
+bit_array=$?
+
+dde_mem_test
+mem=$?
+
+hash_test
+hash=$?
+
+shm_semaph_test 
+semaph=$?
+
+dde_atom_test
+atom=$?
+
+dde_proc_test 1 > proc_server &
+sleep 1
+dde_proc_test > proc_client 
+fgrep "DDE:receive sent message. msg=03e0 wPar=fffb lPar=00000004" proc_server &&
+fgrep "DDE_GetRemoteMessage: sending ACK to wnd=fffb, proc=1" proc_server &&
+fgrep "get_ack: received DDE_ACK message" proc_client 
+proc=$?
+rm proc_client proc_server
+
+shm_fragment_test | diff TEST_FRAGMENT.std -
+fragment=$?
+
+echo ====================================================================
+echo Test results:
+
+echo -n "bit_array "
+if [ $bit_array -eq 0 ] ; then echo OK ; else echo "** ERROR **" ; fi
+
+echo -n "dde_mem "
+if [ $mem -eq 0 ] ; then echo OK ; else echo "** ERROR **" ; fi
+
+echo -n "hash "
+if [ $hash -eq 0 ] ; then echo OK ; else echo "** ERROR **" ; fi
+
+echo -n "shm_semaph "
+if [ $semaph -eq 0 ] ; then echo OK ; else echo "** ERROR **" ; fi
+
+echo -n "dde_proc "
+if [ $proc -eq 0 ] ; then echo OK ; else echo "** ERROR **" ; fi
+
+echo -n "shm_fragment "
+if [ $fragment -eq 0 ] ; then echo OK ; else echo "** ERROR **" ; fi
diff --git a/ipc/shm_block.c b/ipc/shm_block.c
new file mode 100644
index 0000000..057c981
--- /dev/null
+++ b/ipc/shm_block.c
@@ -0,0 +1,191 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      shm_block.c
+ * Purpose:   Treat a shared memory block.
+ ***************************************************************************
+ */
+
+#define inline __inline__
+#include <sys/sem.h>
+#include <stdio.h>
+#include <assert.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stddebug.h>
+#include <debug.h>
+#include <global.h>
+#include "selectors.h"
+#include "shm_fragment.h"
+#include "shm_block.h"
+#include "shm_semaph.h"
+#include "dde_proc.h"
+
+/* How each shmid is maped to local pointer */
+/* Only attached shm blocks are in this construct */
+struct local_shm_map *shm_map=NULL;
+
+/* setup a new shm block (construct a shm block object).
+ *    block: The pointer to the memory block (local mapping)
+ *    first: The first data byte (excluding header stuff),
+ *           if 0  (zero) Use the default.
+ *    size:  The size of the memory block.
+ */
+void shm_setup_block(struct shm_block *block, int first, int size)
+{
+  dprintf_shm(stddeb,"Setting up shm block at 0x%08x\n",(int )block);
+  /* setup block internal data structure */
+  if (first <= 0) {
+     first=sizeof(*block);
+     /* round up - so everything starts on cache line boundary
+      * (assume cache line=32 bytes, may be bigger/smaller for
+      *  different processors and different L2 caches .)
+      */
+     first=(first+0x1f) & ~0x1f;
+  }
+  block->free=size-first;
+  block->next_shm_id=-1; /* IPC shm ID (for initial linking) */
+  block->proc_idx= curr_proc_idx;
+  /* block->size is initialized in shm_FragmentInit */
+  shm_FragmentInit(block, first, size);  /* first item in the free list */
+  
+  dprintf_shm(stddeb,
+	      "block was set up at 0x%08x, size=0x%04xKB, 1st usable=%02x\n",
+	      (int )block,size/1024,first);
+}
+
+/* shm_attach_block: attach existing shm block, setup selectors
+ * shm_id - id of the block to attach.
+ * proc_idx - if not -1, puts this data into local mapping
+ * map - localy mapped info about this block.
+ */
+/* NOTE: there is no check if this block is already attached.
+ *       Attaching the same block more than once - is possible
+ *       In case of doubt use shm_locate_block.
+ */
+struct shm_block *shm_attach_block(int shm_id, int proc_idx,
+				   struct local_shm_map *map)
+{
+  struct shm_block *block;
+  struct shmid_ds ds;
+  struct local_shm_map *this;
+  
+  shmctl(shm_id, IPC_STAT, &ds );
+
+  block=(struct shm_block*)shmat(shm_id, NULL, 0);
+  if (block==NULL) return NULL;
+
+  this=(struct local_shm_map *)malloc(sizeof(*this));
+  this->next= shm_map;
+  shm_map   = this;
+  this->shm_id= shm_id;
+  this->ptr = block;
+  
+  if (proc_idx < 0)
+      this->proc_idx=block->proc_idx;
+  else 
+      this->proc_idx=proc_idx;
+
+  if (map != NULL) {
+     memcpy(map, this, sizeof(map));
+     map->next= NULL;		/* don't pass private info */
+  }
+
+  return block;
+}
+
+struct shm_block *shm_create_block(int first, int size, int *shm_id) 
+{
+  struct shm_block *block;
+  
+  if (size==0)
+     size=SHM_MINBLOCK;
+  else
+     /* round up size to a multiple of SHM_MINBLOCK */
+     size= (size+SHM_MINBLOCK-1) & ~(SHM_MINBLOCK-1);
+  *shm_id= shmget ( IPC_PRIVATE, size ,0700);
+  if (*shm_id==-1)
+     return NULL;
+  block=shm_attach_block(*shm_id, curr_proc_idx, NULL);
+  if (block!=NULL)
+     shm_setup_block(block, first, size);
+
+  return block;
+}
+
+/*
+** Locate attached block. (return it, or NULL on failure)
+** shm_id is the block we look for.
+** *map - will get all the info related to this local map + proc_idx
+**        (may be NULL)
+** *seg - will get the segment this block is attached to.
+*/
+struct shm_block *shm_locate_attached_block(int shm_id,
+					    struct local_shm_map *map)
+{
+  struct local_shm_map *curr;
+  
+  for (curr=  shm_map ; curr != NULL ; curr= curr->next) {
+     if (curr->shm_id == shm_id) {
+	if (map) {
+	    memcpy(map, curr, sizeof(*curr) );
+	    map->next = NULL;	/* this is private info ! */
+	}
+	return curr->ptr;
+    }
+  }
+  
+  /* block not found !  */
+  return 0;
+}
+
+/* shm_locate_block: see shm_attach_block.
+   In addition to shm_attach_block, make sure this
+   block is not already attached.
+   */
+struct shm_block *shm_locate_block(int shm_id, struct local_shm_map *map)
+{
+  
+  struct shm_block *ret;
+  ret= shm_locate_attached_block(shm_id, map);
+  if (ret!=NULL)
+     return ret;
+  /* block not found ! , try to attach */
+  return shm_attach_block(shm_id, -1, map);
+}
+
+static void forget_attached(int shmid)
+{
+  struct local_shm_map *curr, **point_to_curr;
+  
+  for (curr= shm_map,    point_to_curr= &shm_map ;
+       curr != NULL ;
+       curr= curr->next, point_to_curr= &curr->next ) {
+     if (curr->shm_id == shmid) {
+	*point_to_curr= curr->next;
+	return;
+     }
+  }
+}
+
+/* delete chain of shm blocks (pointing to each other)
+ * Do it in reverse order. (This is what the recursion is for)
+ */
+void shm_delete_chain(int *shmid)
+{
+  struct shm_block *block;
+
+  if (*shmid == -1)
+      return;
+
+  block= shm_locate_block(*shmid, NULL);
+  forget_attached( *shmid );
+  if (block == NULL)
+      return;
+  shm_delete_chain(&block->next_shm_id);
+  shmctl(*shmid, IPC_RMID, NULL);
+  *shmid=-1;
+  shmdt((char *)block);
+}
diff --git a/ipc/shm_fragment.c b/ipc/shm_fragment.c
new file mode 100644
index 0000000..098d6cc
--- /dev/null
+++ b/ipc/shm_fragment.c
@@ -0,0 +1,178 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      shm_fragment.c
+ * Purpose:   Data fragments and free list items. Allocate and free blocks.
+ ***************************************************************************
+ */
+#include <stdio.h>		   /* for debugging only */
+#include <stddebug.h>
+#include <debug.h>		   /* for "stddeb" */
+
+#include "shm_fragment.h"
+#include "shm_block.h"
+
+/******************************************************************************
+ *
+ * Free list: all fragments are ordered according to memory location.
+ *            new fragments are inserted in this way.
+ *
+ ******************************************************************************
+ */
+
+#define FRAG_PTR(block,ofs) ((struct shm_fragment *) ((char *) block + ofs) )
+#define NEXT_FRAG(block,ofs) ( FRAG_PTR(block,ofs)->info.next )
+
+/* setup first item in the free list */
+void shm_FragmentInit(struct shm_block *block,int first, int size)
+{
+  struct shm_fragment *fragment;
+  
+  /* round up to nearest 16 byte boundary */
+  first=(first+15)& ~15;
+  block->free_list=first;
+  
+  /* make all the block (exluding the header) free */
+  fragment= FRAG_PTR(block, first);
+  block->free=  fragment->size=  size-first;
+  fragment->info.next=0;
+}
+
+void shm_FragPtrFree(struct shm_block *block, void *ptr)
+{
+  /* ptr points to fragment->info.data, find pointer to fragment,
+   * find the offset of this pointer in block.
+   */
+  if (ptr)
+     shm_FragmentFree(block, PTR2REL(block, ptr));
+}
+void shm_FragmentFree(struct shm_block *block, int fragment_ofs)
+{
+  struct shm_fragment *fragment=NULL;
+  int prev;
+  int next;
+
+  fragment_ofs-=(int )&fragment->info.data;
+  fragment= FRAG_PTR(block, fragment_ofs);
+
+  block->free+=fragment->size;
+  /* scan free list to find candidates for merging with fragment */
+  for (prev=0, next=block->free_list;
+       (next!=0) && (fragment_ofs > next)  ;
+       prev=next, next=NEXT_FRAG(block,next) )
+     ;
+  
+  /* insert fragment between, prev and next
+   *  prev==0: fragment will be the first item in free list
+   *  next==0: fragment will be the last item in free list
+   */
+
+
+  /* update fragment (point to next, or merge with next) */
+  
+  if ( fragment_ofs+fragment->size == next ) {
+     /* merge with the next free block */
+     fragment->size+=    FRAG_PTR(block,next)->size;
+     fragment->info.next=FRAG_PTR(block,next)->info.next;
+  } else 
+     /* fragment should be inserted before the next fragment or end of */
+     /* list. (not merged)  */
+     fragment->info.next=next;
+  /* now fragment has all the information about the rest of the list */
+
+
+  /* upate prev fragment (point or merge with fragment) */
+  
+  if (prev==0) 		   /* first item in free list */
+     block->free_list=fragment_ofs;
+  else if ( prev+FRAG_PTR(block,prev)->size == fragment_ofs ) {
+     /* merge fragment with previous fragment */
+     FRAG_PTR(block,prev)->size+=    fragment->size;
+     FRAG_PTR(block,prev)->info.next=fragment->info.next;
+  } else 
+     /* insert fragment after previous fragment */
+     FRAG_PTR(block,prev)->info.next=fragment_ofs;
+}
+
+/* use "first fit" algorithm,
+ * return: offset to data in fragment.
+ */
+int shm_FragmentAlloc(struct shm_block *block, int size)
+{
+  int prev;
+  int candidate;
+  struct shm_fragment *fragment;
+  struct shm_fragment *ret_fragment;
+
+  if (size <= 0)
+     return NIL;
+  /* add size of  "fragment->size" */
+  size+= (char *)&fragment->info.data - (char *)fragment ;
+
+  /* round "size" to nearest 16 byte value */
+  size= (size+15) & ~15;
+  if (size > block->free)
+     return NIL;
+  /* scan free list to find candidates for allocation */
+  for (prev=0, candidate=block->free_list;
+       candidate!=0 ;
+       prev=candidate, candidate= fragment->info.next )
+  { 
+     fragment=FRAG_PTR(block,candidate);
+     if (fragment->size >= size)
+	break;
+  }
+  
+  if (candidate == 0)
+     return NIL;
+
+  block->free-=size;
+  if (fragment->size == size) {
+     if (prev == 0) 
+	block->free_list= fragment->info.next;
+     else
+	FRAG_PTR(block,prev)->info.next= fragment->info.next;
+     return PTR2REL(block, &fragment->info.data);
+  }
+
+  /* fragment->size > size */
+
+  /* Split fragment in two, return one part, put the other in free list.  */
+  /* The part that starts at the old location - will stay in the free list. */
+  fragment->size -= size;
+  
+  ret_fragment=FRAG_PTR(block, candidate + fragment->size);
+  ret_fragment->size= size;
+  return PTR2REL(block, ret_fragment->info.data);
+}
+
+/* like shm_FragmentAlloc, returns pointer instead of offset */
+char *shm_FragPtrAlloc(struct shm_block *block, int size)
+{
+  int ofs;
+  ofs= shm_FragmentAlloc(block,size);
+  if (ofs == NIL)
+     return NULL;
+  else
+     return (char *) REL2PTR(block, ofs);
+}
+/* This is used for debugging only */
+void shm_print_free_list(struct shm_block *block)
+{
+  struct shm_fragment *fragment;
+  int item;
+
+  item=block->free_list;
+  if (item==0) {
+     fprintf(stddeb,"no free fragments");
+  } else {
+     for (; item ; item=fragment->info.next) {
+	fragment=FRAG_PTR(block,item);
+	fprintf(stddeb,"{0x%04x,0x%04x} ",item,fragment->size);
+     }
+  }
+  fprintf(stddeb," [total free=%04x]\n",block->free);
+  fflush(stddeb);
+}
diff --git a/ipc/shm_fragment_test.c b/ipc/shm_fragment_test.c
new file mode 100644
index 0000000..8964715
--- /dev/null
+++ b/ipc/shm_fragment_test.c
@@ -0,0 +1,100 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      shm_fragment_test.c
+ * Purpose:   Test data fragments and free list items. Allocate and free blocks.
+ ***************************************************************************
+ */
+#include <assert.h>
+#include <stdio.h>		   
+#include <stddebug.h>
+#define DEBUG_DEFINE_VARIABLES	   /* just avoid dumb errors */
+#include <debug.h>		   /* for "stddeb" */
+#include <stdlib.h>
+#include <string.h>
+#include "shm_block.h"
+#include "shm_fragment.h"
+
+#define DO_FREE(id) (-id)
+#define LIST_LENGTH 20
+
+int main()
+{
+  struct shm_block *block;
+  char *ret;
+  int size;
+  int i;
+
+  /* important: The test will work only for the current implementation of */
+  /* allocation, if the implementation will change, the list should also */
+  /* cahnge. */
+  static int sizes[LIST_LENGTH]={
+    SHM_MINBLOCK,		   /* 0: should fail */
+    0x3fe0-4,			   /* 1: */
+    0x4000-4,			   /* 2: */
+    0x4000-4,			   /* 3: */
+    0x4000-4+1,			   /* 4: should fail */
+    0x4000-4,			   /* 5: */
+    /* allocated(5,3,2,1) free() */
+    -5,				   /* 6: */
+    0x1c00-4,			   /* 7: */
+    0x1400-4,			   /* 8: */
+    0x1000-4,			   /* 9: */
+    /* allocated(9,8,7,3,2,1) free() */
+    -9,				   /* 10: */
+    -3,				   /* 11: */
+    -1,				   /* 12: */
+    /* allocated(8,7,2) free(9,3,1) */
+    0x1000-4,			   /* 13: */
+    -13,			   /* 14: */
+    0x1000+1-4,			   /* 15: */
+    /* allocated(8,7,15,2) free(9,[3-15],1) */
+    -2,				   /* 16: */
+    /* allocated(8,7,15) free(9,[3-15],1+2) */
+    -8,				   /* 17: */
+    -7,				   /* 18: */
+    -15				   /* 19: */
+    };
+  
+  static char *ptr[LIST_LENGTH];
+  
+  block=malloc(SHM_MINBLOCK);
+  assert(block);
+
+  /* setup first item in the free list */
+  shm_FragmentInit(block, sizeof(*block), SHM_MINBLOCK);
+  
+  fprintf(stddeb,"After shm_FragmentInit\n");
+  shm_print_free_list(block);
+
+  for(i=0 ; i < LIST_LENGTH; i++) {
+     size=sizes[i];
+     if (size>0) {		   /* allocate */
+	ret=shm_FragPtrAlloc(block, size);
+	ptr[i]=ret;
+	fprintf(stddeb,
+		"%d: After shm_FragmentAlloc(block, 0x%06x) == ",
+		i, size);
+	if (ret==NULL)
+	   fprintf(stddeb, "NULL\n");
+	else {
+	   fprintf(stddeb, "0x%06x\n", (int)ret-(int)block);
+	   bzero (ret,size);	   /* test boundaries */
+	}
+     } else {			   /* free */
+	/* free shm fragment */
+	ret=ptr[-sizes[i]];
+	fprintf(stddeb, "%d: Doing shm_FragmentFree(block, ", i);
+	if (ret==NULL)
+	   fprintf(stddeb, "NULL)\n");
+	else 
+	   fprintf(stddeb, "0x%06x)\n", (int)ret-(int)block);
+	fflush(stddeb);
+	shm_FragPtrFree(block, ret);
+     }
+     shm_print_free_list(block);
+  }
+  return 0;
+}
diff --git a/ipc/shm_main_blk.c b/ipc/shm_main_blk.c
new file mode 100644
index 0000000..3fb798e
--- /dev/null
+++ b/ipc/shm_main_blk.c
@@ -0,0 +1,264 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      shm_main_blk.c
+ * Purpose:   Main Wine's shared memory block
+ ***************************************************************************
+ */
+#define inline __inline__
+#include <sys/sem.h>
+#include <stdio.h>
+#include <time.h>
+#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <signal.h>
+#include <stddebug.h>
+#include <debug.h>
+#include "shm_fragment.h"
+#include "shm_block.h"
+#include "shm_main_blk.h"
+#include "shm_semaph.h"
+
+#define WineKey (   'W'+((int)'i'<<8)+((int)'n'<<16)+((int)'e'<<24)  )
+#define SHM_KEY_RANGE 8
+
+/* main block (set during initialization) */
+struct shm_main_block *main_block=NULL;
+static char *shm_header="Wine - Windows emulator DDE mechanism";
+static int main_shm_id;
+
+static void shm_main_refresh();
+
+/* for debugging only */
+static void print_perm(struct ipc_perm *perm)
+{
+  printf("Permission:\n");
+  printf("\tKey=%d,   mode=%03o,   sequence #=%d\n",
+	 (int)perm->key,perm->mode, perm->seq);
+  printf("\towner: uid=%d, gid=%d ;"  ,perm->uid, perm->gid);
+  printf("  creator: uid=%d, gid=%d\n",perm->cuid,perm->cgid);
+}
+
+/* for debugging only */
+/* print_shm_info: print shared memory descriptor info */
+static void print_shm_info(int shm_id)
+{
+  struct shmid_ds ds;
+  shmctl(shm_id, IPC_STAT, &ds );
+
+  printf("shm_id=%d, Size=0x%08x , Number of attaches=%d\n",
+	 shm_id, ds.shm_segsz, (int)ds.shm_nattch);
+  if (ds.shm_atime)
+     printf("Last attach=%s",ctime(&ds.shm_atime));
+  if (ds.shm_dtime)
+     printf("Last detach=%s",ctime(&ds.shm_dtime));
+  printf("Last change=%s",ctime(&ds.shm_ctime));
+  printf("pid: creator=%d, last operator=%d\n",
+	 (int)ds.shm_cpid,(int)ds.shm_lpid);
+  print_perm( &ds.shm_perm);
+
+}
+
+int proc_exist(__pid_t pid)
+{
+  if ( kill(pid,0) == 0)	   /* dummy signal to test existence */
+     return 1;
+  else if (errno==ESRCH)	   /* "no such process" */
+     return 0;
+  else
+     return 1;
+}
+
+/* setup a new main shm block (only construct a shm block object). */
+static void shm_setup_main_block()
+{
+  dprintf_shm(stddeb,"creating data structure\n");
+  main_block->build_lock=1;
+  strcpy(main_block->magic, shm_header);
+
+  shm_setup_block(&main_block->block,sizeof(*main_block),SHM_MINBLOCK);
+
+  dde_proc_init(main_block->proc);
+  ATOM_GlobalInit();
+  shm_sem_init(&main_block->sem);
+
+  /* main block set and data structure is stable now */
+  main_block->build_lock=0;
+}
+
+/* Delete everything related to main_block */
+void shm_delete_all(int shmid)
+{
+  int proc_idx;
+
+  if (shmid == -1) 
+    shmid= main_shm_id;
+  
+  shmctl( shmid, IPC_RMID, NULL);
+  
+  for (proc_idx= 0 ; proc_idx < DDE_PROCS ; proc_idx++)
+     dde_proc_done( &main_block->proc[proc_idx] );
+  
+  shm_sem_done(&main_block->sem);
+  shmdt( (void *) main_block);
+  main_block= NULL;
+}
+
+int DDE_no_of_attached()
+{
+  struct shmid_ds shm_info;
+  
+  if (shmctl(main_shm_id, IPC_STAT, &shm_info) == -1)
+    return -1;
+
+  return shm_info.shm_nattch;
+}
+/*
+** Test if shm_id is MainBlock and attach it (if it is),
+** Return 1 if ok, 0 otherwise.
+*/
+static int attach_MainBlock(int shm_id)
+{
+  struct shmid_ds shm_info;
+
+  if (shmctl(shm_id, IPC_STAT, &shm_info) == -1)
+     return 0;
+
+  /* Make sure we don't work on somebody else's block */
+  if (shm_info.shm_perm.cuid != getuid()) { /* creator is not me */
+     dprintf_shm(stddeb,"Creator is not me!\n");
+     return 0;
+  }
+
+  dprintf_shm(stddeb,"shared memory exist, attaching anywhere\n");
+  main_block=(struct shm_main_block *)shmat(shm_id, 0, 0);
+  if ( (int)main_block==-1) {
+     dprintf_shm(stddeb,"Attach failed\n");
+     return 0;
+  }
+
+  if (strcmp(main_block->magic, shm_header) != 0) {
+     dprintf_shm(stddeb,"Detaching, wrong magic\n");
+     shmdt((void *)main_block);
+     return 0;
+  }
+
+  if (debugging_shm)
+     print_shm_info(shm_id);
+
+  /* Is it an old unused block ? */
+  if (shm_info.shm_nattch == 0) {
+     dprintf_shm(stddeb,"No attaches, deleting old data\n");
+     shm_delete_all(shm_id);
+     return 0;
+  }
+
+  /* Wait for data structure to stabilize */
+  while (main_block->build_lock)
+     usleep(10000);
+
+  main_shm_id= shm_id;
+
+  shm_main_refresh();
+  return 1;
+}
+
+/* (Function used by the constructor)
+ * Try to get existing shared memory with key="Wine", size=SHM_MINBLOCK
+ * complete user permission.
+ * If such block is found - return true (1),  else return false (0)
+ */
+static int shm_locate_MainBlock(key_t shm_key)
+{
+    int shm_id;			/* Descriptor to this shared memory */
+    int i;
+
+    dprintf_shm(stddeb,"shm_locate_MainBlock: trying to attach, key=0x%x\n",
+		shm_key);
+    for (i=0 ; i < SHM_KEY_RANGE ; i++) {
+       dprintf_shm(stddeb,"iteration=%d\n", i);
+
+       shm_id= shmget ( shm_key+i, SHM_MINBLOCK ,0700);
+
+       if (shm_id != -1) {
+	 if ( attach_MainBlock(shm_id) ) {
+	   return 1;		   /* success! */
+	 }
+       } else {
+	  switch(errno) {
+	    case EIDRM:		   /* segment destroyed */
+	    case EACCES:	   /* no user permision */
+	      break;
+
+	    case ENOMEM:	   /* no free memory */
+	    case ENOENT:	   /* this key does not exist */
+	    default :
+	      dprintf_shm(stddeb,"shmget failed, errno=%d, %s\n",
+			  errno, strerror(errno) );
+	      return 0;		   /* Failed */
+	  }
+       } /* if .. else */
+    } /* for */
+    return 0;
+}
+
+/* (Function used by the constructor)
+ * Try to allocate new shared memory with key="Wine", size=SHM_MINBLOCK
+ * with complete user permission.
+ * If allocation succeeds - return true (1),  else return false (0)
+ */
+static int shm_create_MainBlock(key_t MainShmKey)
+{
+  int shm_id;
+  int flags= 0700 | IPC_CREAT | IPC_EXCL;
+  int i;
+
+  dprintf_shm(stddeb,"creating shared memory\n");
+
+  /* try to allocate shared memory with key="Wine", size=SHM_MINBLOCK, */
+  /* complete user permission */
+  for (i=0 ; i < SHM_KEY_RANGE ; i++) {
+     shm_id= shmget ( (key_t) MainShmKey, SHM_MINBLOCK, flags);
+     if (shm_id != -1)
+	break;
+  }
+  if (shm_id == -1) {
+     dprintf_shm(stddeb,"failed to create shared memory\n");
+     return 0;
+  }
+  dprintf_shm(stddeb,"shared memory created, attaching\n");
+  main_block=(struct shm_main_block*) shmat(shm_id, 0,0);
+  if (debugging_shm)
+     print_shm_info(shm_id);
+  main_shm_id= shm_id;
+  shm_setup_main_block();
+  dde_wnd_setup();
+  return 1;
+
+}
+
+/* link to the dde shared memory block */
+/* RETURN: 0 on success, non zero on failure */
+int shm_init(void)
+{
+  if ( !shm_locate_MainBlock(WineKey)
+       && !shm_create_MainBlock(WineKey)) { 
+     fflush(stdout);
+     fprintf(stderr,"shm_init: failed to init main shm block\n");
+     exit(1);
+  }
+
+  dde_proc_add(main_block->proc);
+  return 0;
+}
+
+static void shm_main_refresh()
+{
+  int proc_idx;
+  
+  for (proc_idx= 0 ; proc_idx < DDE_PROCS ; proc_idx++)
+     dde_proc_refresh( &main_block->proc[proc_idx] );
+}
diff --git a/ipc/shm_semaph.c b/ipc/shm_semaph.c
new file mode 100644
index 0000000..c226808
--- /dev/null
+++ b/ipc/shm_semaph.c
@@ -0,0 +1,136 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      shm_semaph.c
+ * Purpose:   Handle semaphores for shared memory operations.
+ ***************************************************************************
+ */
+#define inline __inline__
+#include <assert.h>
+#include <unistd.h>
+#include <sys/sem.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stddebug.h>
+#include <debug.h>
+#include "shm_semaph.h"
+#define SEM_READ  0
+#define SEM_WRITE 1
+
+/* IMPORTANT: Make sure that killed process will not lock everything.
+ *            If possible, restrict usage of these functions.
+ */
+void shm_read_wait(shm_sem semid)
+{
+  struct sembuf sop[2];
+  int ret;
+  
+  dprintf_sem(stddeb,"shm_read_wait(%d)\n",semid);
+  sop[0].sem_num=SEM_READ;
+  sop[0].sem_op=1;		   /* add this read instance */
+  sop[0].sem_flg=SEM_UNDO;	   /* undo in case process dies */
+  
+  sop[1].sem_num=SEM_WRITE;
+  sop[1].sem_op=0;		   /* wait until no writing instance exists */
+  sop[1].sem_flg=SEM_UNDO;
+
+  do {
+     ret=semop (semid,sop , 2);
+  } while (ret<0 && errno==EINTR);  /* interrupted system call? */
+  
+  if (ret<0) 
+     fprintf(stderr,"failed semaphore lock for read. semid=%d,errno=%d\n",
+	     semid, errno);
+}
+void shm_write_wait(shm_sem semid)
+{
+  struct sembuf sop[3];
+  int ret;
+  
+  dprintf_sem(stddeb,"shm_write_wait(%d)\n",semid);
+  sop[0].sem_num=SEM_READ;
+  sop[0].sem_op=0;		   /* wait until no reading instance exist */
+  sop[0].sem_flg=SEM_UNDO;		   
+
+  sop[1].sem_num=SEM_WRITE;
+  sop[1].sem_op=1;		   /* writing is in progress - disable read */
+  sop[1].sem_flg=SEM_UNDO;	   /* undo if process dies */
+
+  sop[2].sem_num=SEM_READ;
+  sop[2].sem_op=1;		   /* disable new writes */
+  sop[2].sem_flg=SEM_UNDO;
+  
+  do {
+     ret=semop (semid,sop , 3);
+  } while (ret<0 && errno==EINTR);  /* interrupted system call? */
+
+  if (ret<0) 			   /* test for the error */
+     fprintf(stderr,"failed semaphore lock for write. semid=%d,errno=%d\n",
+	     semid, errno);
+}
+void shm_write_signal(shm_sem semid)
+{
+  struct sembuf sop[2];
+  int ret;
+
+  dprintf_sem(stddeb,"shm_write_signal(%d)\n",semid);
+  sop[0].sem_num=SEM_READ;
+  sop[0].sem_op=-1;	
+  sop[0].sem_flg=IPC_NOWAIT | SEM_UNDO;	/* no reason to wait */
+
+  sop[1].sem_num=SEM_WRITE;
+  sop[1].sem_op=-1;		   
+  sop[1].sem_flg=IPC_NOWAIT | SEM_UNDO;	/* no reason to wait */
+
+  do {
+     ret=semop (semid,sop , 2);
+  } while (ret<0 && errno==EINTR);  /* interrupted system call? */
+
+  if (ret<0) 			   /* test for the error */
+     fprintf(stderr,"failed semaphore unlock for write. semid=%d,errno=%d\n",
+	     semid, errno);
+}
+
+void shm_read_signal(shm_sem semid)
+{
+  struct sembuf sop[2];
+  int ret;
+
+  dprintf_sem(stddeb,"shm_read_signal(%d)\n",semid);
+  sop[0].sem_num=SEM_READ;
+  sop[0].sem_op=-1;	
+  sop[0].sem_flg=IPC_NOWAIT | SEM_UNDO;	/* no reason to wait */
+
+  do {
+     ret=semop (semid,sop , 1);
+  } while (ret<0 && errno==EINTR);  /* interrupted system call? */
+
+  if (ret<0) 			   /* test for the error */
+     fprintf(stderr,"failed semaphore unlock for read. semid=%d,errno=%d\n",
+	     semid, errno);
+}
+
+void shm_sem_init(shm_sem *sptr)
+{
+  shm_sem semid;
+  union semun arg;
+
+  semid=semget (IPC_PRIVATE, 2, 0700 | IPC_CREAT);
+
+  arg.val=0;
+  semctl (semid, 0, SETVAL, arg);
+  semctl (semid, 1, SETVAL, arg);
+  *sptr=semid;
+}
+
+void shm_sem_done(shm_sem *semptr)
+{
+  union semun arg;
+
+  semctl (*semptr, 0, IPC_RMID , arg);
+  semctl (*semptr, 1, IPC_RMID , arg);
+
+  *semptr= -1;
+}
diff --git a/ipc/shm_semaph_test.c b/ipc/shm_semaph_test.c
new file mode 100644
index 0000000..fdceeb5
--- /dev/null
+++ b/ipc/shm_semaph_test.c
@@ -0,0 +1,128 @@
+/***************************************************************************
+ * Copyright 1995, Technion, Israel Institute of Technology
+ * Electrical Eng, Software Lab.
+ * Author:    Michael Veksler.
+ ***************************************************************************
+ * File:      shm_semaph_test.c
+ * Purpose:   Test semaphores handleingr shared memory operations.
+ ***************************************************************************
+ */
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include "shm_semaph.h"
+#include <sys/shm.h>
+#define DEBUG_DEFINE_VARIABLES
+#include <stddebug.h>
+#include <debug.h>
+
+static volatile int * volatile data;
+static int isparent=0;
+#define DELAY (rand()%10)
+shm_sem sem;
+
+static void read_write(int num)
+{
+  int i,j ;
+  volatile float dummy=0;
+  int val;
+
+  srand(num+time(NULL));
+  for (i=0x3fff;i>=0;i--) {
+     if((i&0x7ff)==0 && isparent)
+	fprintf(stderr,"0x%06x\r",i);
+     shm_write_wait(sem);
+     *data= num;
+     for (j=DELAY ; j>=0;j--)
+	dummy*=2;
+     if (*data!=num) {
+	fprintf(stderr,"\nbad shm_write_wait(), num=%d\n",num);
+	shm_write_signal(sem);
+	return;
+     }
+     shm_write_signal(sem);
+     for (j=DELAY ; j>=0 ;j--)
+	dummy*=2;
+     shm_read_wait(sem);
+     val=*data;
+     for (j=DELAY; j>=0 ;j--)
+	dummy*=0.5;
+     if (*data!=val) {
+	fprintf(stderr,"\nbad shm_read_wait(), num=%d,val=%d,*data=%d\n",
+		num,val,*data);
+	shm_read_signal(sem);
+	return;
+     }
+     shm_read_signal(sem);
+  }
+  if (isparent)
+     fputc('\n',stderr);
+}
+static void child1()
+{
+  read_write(2);
+}
+static void child2()
+{
+  read_write(10);
+}
+static void parent()
+{
+  isparent=1;
+  read_write(60);
+}
+
+int main()
+{
+  int shmid;
+  int ret1, ret2;
+  int pid1, pid2;
+  int stat=0;
+  
+  shm_sem_init(&sem);
+  shmid=shmget(IPC_PRIVATE, 0x100, IPC_CREAT | 0700);
+  data= (int *)shmat ( shmid, NULL, 0);
+  *data=0;
+  
+  switch (pid1=fork()) {
+    case -1:
+      perror("fork 1");
+      return 1;
+    case 0:
+      fprintf(stderr,"child1\n");
+      child1();
+      fprintf(stderr,"child1 done\n");
+      return 0;
+    default :
+  }
+  switch (pid2=fork()) {
+    case -1:
+      perror("fork 2");
+      stat|=1;
+      break;
+    case 0:
+      fprintf(stderr,"child2\n");
+      child2();
+      fprintf(stderr,"child2 done\n");
+      return 0;
+    default :
+  }
+  fprintf(stderr,"parent\n");
+  if (pid2>0) {			   /* if second fork did not fail */
+     parent();
+     fprintf(stderr,"parent done, waiting for child2\n");
+     waitpid(pid2,&ret2,WUNTRACED);
+     stat|=ret2;
+  }
+  fprintf(stderr,"parent done, waiting for child1\n");
+  waitpid(pid1,&ret1,WUNTRACED);
+  stat|=ret1;
+  fprintf(stderr,"all done\n");
+
+  shmctl(shmid, IPC_RMID,NULL);
+  shm_sem_done(&sem);
+  return stat;
+}
diff --git a/ipc/wine_test_stub.c b/ipc/wine_test_stub.c
new file mode 100644
index 0000000..fb1747e
--- /dev/null
+++ b/ipc/wine_test_stub.c
@@ -0,0 +1,117 @@
+#include <stdlib.h>
+#include "dde.h"
+#include <wintypes.h>
+#include "global.h"
+#include <win.h>
+#define DEBUG_DEFINE_VARIABLES
+#define DEBUG_ALL
+#include <stddebug.h>
+#include <debug.h>
+
+#define DDE_PROC2WIN(proc_idx)   (  (HWND) ~( (proc_idx)+1)  )
+#define DDE_WIN2PROC(win)        (  (int) ~(short) ((win)+1) )
+#define DDE_IsRemoteWindow(win)  (  (win)<0xffff && (win)>=(0xffff-DDE_PROCS))
+
+
+char *MessageTypeNames[0x400]={NULL};
+char *dummy_store_for_debug_msg_name;
+
+ldt_copy_entry ldt_copy[LDT_SIZE];
+
+int LDT_GetEntry( int entry, ldt_entry *content )
+{
+    return 0;
+}
+
+int LDT_SetEntry( int entry, ldt_entry *content )
+{
+    return 0;
+}
+
+void dummy_usage_of_debug_msg_name()
+{
+  dummy_store_for_debug_msg_name=debug_msg_name[0];
+}
+
+/* stub */
+HWND GetDesktopWindow()
+{
+  printf("GetDesktopWindow\n");
+  return 0;
+}
+/* stub */
+/* smart stub */
+LONG SendMessage(HWND a,WORD b,WORD c,LONG d)
+{
+  MSG msg;
+  printf("SendMessage(%04x,%04x,%04x,%04lx)\n",a,b,c,d);
+  if (DDE_IsRemoteWindow(a) || a==(HWND)-1)
+     return 0;
+  if (b!=WM_DDE_INITIATE)
+     return 0;
+  msg.hwnd=c;
+  msg.message= WM_DDE_ACK;
+  msg.lParam= 0;
+  msg.wParam= 0;
+  return DDE_SendMessage(&msg);
+}
+/* stub */
+BOOL PostMessage(HWND a,WORD b,WORD c,LONG d)
+{
+  printf("PostMessage(%04x,%04x,%04x,%04lx)\n",a,b,c,d);
+  return 0;
+}
+/* stub */
+HWND GetTopWindow(HWND a)
+{
+  printf("GetTopWindow(%04x)\n",a);
+  return 1;
+}
+/* stub */
+WORD FreeSelector(WORD a)
+{
+  printf("FreeSelector(%04x)\n",a);
+  return 0;
+}
+
+/* stub that partially emulates the true GLOBAL_CreateBlock function */
+HGLOBAL GLOBAL_CreateBlock( WORD flags, void *ptr, DWORD size,
+                            HGLOBAL hOwner, BOOL isCode,
+                            BOOL is32Bit, BOOL isReadOnly,
+			    SHMDATA *shmdata  )
+{
+  
+  printf("GLOBAL_CreateBlock(flags=0x%x,ptr=0x%08lx, size=0x%x,hOwner=0x%x\n",
+	 (int)flags, (long)ptr, (int)size, (int)hOwner);
+  printf("isCode=%d, is32Bit=%d, isReadOnly=%d, \n", isCode, is32Bit,
+	 isReadOnly);
+  printf("*shmdata={handle=0x%x,sel=0x%x, shmid=%d})\n",
+	 shmdata->handle, shmdata->sel, shmdata->shmid);
+  return 1;
+}
+
+/* stub */
+WND *WIN_FindWndPtr(HWND hwnd)
+{
+  static WND win;
+  printf("WIN_FindWndPtr(%d)\n",hwnd);
+  if (hwnd==0)
+     return NULL;
+  win.hwndNext=0;
+  win.dwStyle=WS_POPUP;
+  
+  return &win;
+}
+
+/* stub */
+WORD GetCurrentPDB(void)
+{
+  printf("GetCurrentPDB()\n");
+  
+  return 0;
+}
+
+/* stub */
+void Yield(void)
+{
+}
diff --git a/loader/Imakefile b/loader/Imakefile
index befe47a..3ec199f 100644
--- a/loader/Imakefile
+++ b/loader/Imakefile
@@ -3,7 +3,6 @@
 MODULE = loader
 
 SRCS = \
-	dump.c \
 	main.c \
 	module.c \
 	ne_image.c \
diff --git a/loader/Makefile.in b/loader/Makefile.in
new file mode 100644
index 0000000..b9cd285
--- /dev/null
+++ b/loader/Makefile.in
@@ -0,0 +1,50 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include
+LD	= @LD@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+
+
+MODULE 	= loader
+
+SRCS 	= main.c module.c ne_image.c ne_resource.c pe_image.c \
+	pe_resource.c selector.c signal.c resource.c task.c
+ 
+OBJS = $(SRCS:.c=.o)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
+
+all: $(MODULE).o
+
+$(MODULE).o: $(OBJS)
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dummy:
+
+### Dependencies:
diff --git a/loader/dump.c b/loader/dump.c
deleted file mode 100644
index 39344e5..0000000
--- a/loader/dump.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#ifndef WINELIB
-/*
-static char RCSId[] = "$Id: dump.c,v 1.2 1993/07/04 04:04:21 root Exp root $";
-static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#ifdef linux
-#include <linux/unistd.h>
-#include <linux/head.h>
-#include <linux/ldt.h>
-#endif
-#include <errno.h>
-#include "neexe.h"
-#include "prototypes.h"
-
-/**********************************************************************
- *					PrintFileHeader
- */
-void
-PrintFileHeader(struct ne_header_s *ne_header)
-{
-    printf("ne_header: %c%c\n",
-           ne_header->ne_magic & 0xff,
-           ne_header->ne_magic >> 8 );
-    printf("linker version: %d.%d\n", ne_header->linker_version,
-	   ne_header->linker_revision);
-    printf("format flags: %04x\n", ne_header->format_flags);
-    printf("automatic data segment: %04x\n", ne_header->auto_data_seg);
-    printf("CS:IP  %04x:%04x\n", ne_header->cs, ne_header->ip);
-    printf("SS:SP  %04x:%04x\n", ne_header->ss, ne_header->sp);
-    printf("additional flags: %02x\n", ne_header->additional_flags);
-    printf("operating system: %02x\n", ne_header->operating_system);
-    printf("fast load offset: %04x\n", ne_header->fastload_offset);
-    printf("fast load length: %04x\n", ne_header->fastload_length);
-}
-
-/**********************************************************************
- *					PrintRelocationTable
- */
-void 
-PrintRelocationTable(char *exe_ptr, 
-		     struct ne_segment_table_entry_s *seg_entry_p,
-		     int segment)
-{
-    struct relocation_entry_s *rep;
-    int i;
-    int offset;
-    u_short n_entries, *sp;
-
-    printf("RELOCATION TABLE %d:\n", segment + 1);
-    
-    if (seg_entry_p->seg_data_offset == 0)
-	return;
-
-    offset = seg_entry_p->seg_data_length;
-    if (offset == 0)
-	offset = 0x10000;
-
-    sp = (u_short *) (exe_ptr + seg_entry_p->seg_data_offset * 512 + offset);
-    n_entries = *sp;
-
-    rep = (struct relocation_entry_s *) (sp + 1);
-    for (i = 0; i < n_entries; i++, rep++)
-    {
-	printf("  ADDR TYPE %d,  TYPE %d,  OFFSET %04x,",
-	       rep->address_type, rep->relocation_type, rep->offset);
-	printf("TARGET %04x %04x\n", rep->target1, rep->target2);
-    }
-}
-#endif /* ifndef WINELIB */
diff --git a/loader/main.c b/loader/main.c
index 7a2d435..0e301df 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -11,6 +11,18 @@
 #include <string.h>
 #include <errno.h>
 #include "windows.h"
+#include "module.h"
+#include "task.h"
+#include "selectors.h"
+#include "comm.h"
+#include "user.h"
+#include "menu.h"
+#include "atom.h"
+#include "dialog.h"
+#include "message.h"
+#include "syscolor.h"
+#include "sysmetrics.h"
+#include "gdi.h"
 #include "debugger.h"
 #include "dos_fs.h"
 #include "dlls.h"
@@ -18,6 +30,7 @@
 #include "neexe.h"
 #include "options.h"
 #include "task.h"
+#include "dce.h"
 #include "pe_image.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -29,6 +42,7 @@
 int MAIN_Init(void)
 {
     extern BOOL RELAY_Init(void);
+    extern BOOL RELAY32_Init(void); 
 
     int queueSize;
 
@@ -103,14 +117,22 @@
 int _WinMain(int argc, char **argv)
 {
     int i;
+    HANDLE handle;
 
     if (!MAIN_Init()) return 0;
 
     for (i = 1; i < argc; i++)
     {
-        if (WinExec( argv[i], SW_SHOWNORMAL ) < 32)
+        if ((handle = WinExec( argv[i], SW_SHOWNORMAL )) < 32)
         {
-            fprintf(stderr, "wine: can't exec '%s'.\n", argv[i]);
+            fprintf(stderr, "wine: can't exec '%s': ", argv[i]);
+            switch (handle)
+            {
+            case 2: fprintf( stderr, "file not found\n" ); break;
+            case 11: fprintf( stderr, "invalid exe file\n" ); break;
+            case 21: fprintf( stderr, "win32 executable\n" ); break;
+            default: fprintf( stderr, "error=%d\n", handle ); break;
+            }
             exit(1);
         }
     }
diff --git a/loader/module.c b/loader/module.c
index 01d2678..12cf6ba 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -21,7 +21,6 @@
 #include "task.h"
 #include "toolhelp.h"
 #include "stddebug.h"
-/* #define DEBUG_MODULE */
 #include "debug.h"
 
 
@@ -53,7 +52,7 @@
 
         hModule = GLOBAL_CreateBlock( GMEM_MOVEABLE, table->module_start,
                                       table->module_end - table->module_start,
-                                      0, FALSE, FALSE, FALSE );
+                                      0, FALSE, FALSE, FALSE, NULL );
         if (!hModule) return FALSE;
         FarSetOwner( hModule, hModule );
 
@@ -69,7 +68,7 @@
 
         pSegTable->selector = GLOBAL_CreateBlock(GMEM_FIXED, table->code_start,
                                                  pSegTable->minsize, hModule,
-                                                 TRUE, TRUE, FALSE );
+                                                 TRUE, TRUE, FALSE, NULL );
         if (!pSegTable->selector) return FALSE;
         pSegTable++;
 
@@ -99,35 +98,34 @@
 
     MODULE_SetEntryPoint( hModule, 183,  /* KERNEL.183: __0000H */
                           GLOBAL_CreateBlock( GMEM_FIXED, dosmem,
-                                     0x10000, hModule, FALSE, FALSE, FALSE ) );
+                                0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
     MODULE_SetEntryPoint( hModule, 193,  /* KERNEL.193: __0040H */
                           GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x400,
-                                     0x100, hModule, FALSE, FALSE, FALSE ) );
+                                  0x100, hModule, FALSE, FALSE, FALSE, NULL ));
     MODULE_SetEntryPoint( hModule, 174,  /* KERNEL.174: __A000H */
                           GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x10000,
-                                     0x10000, hModule, FALSE, FALSE, FALSE ) );
+                                0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
     MODULE_SetEntryPoint( hModule, 181,  /* KERNEL.181: __B000H */
                           GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x20000,
-                                     0x10000, hModule, FALSE, FALSE, FALSE ) );
+                                0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
     MODULE_SetEntryPoint( hModule, 182,  /* KERNEL.182: __B800H */
                           GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x28000,
-                                     0x10000, hModule, FALSE, FALSE, FALSE ) );
+                                0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
     MODULE_SetEntryPoint( hModule, 195,  /* KERNEL.195: __C000H */
                           GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x30000,
-                                     0x10000, hModule, FALSE, FALSE, FALSE ) );
+                                0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
     MODULE_SetEntryPoint( hModule, 179,  /* KERNEL.179: __D000H */
                           GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x40000,
-                                     0x10000, hModule, FALSE, FALSE, FALSE ) );
+                                0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
     MODULE_SetEntryPoint( hModule, 190,  /* KERNEL.190: __E000H */
                           GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x50000,
-                                     0x10000, hModule, FALSE, FALSE, FALSE ) );
+                                0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
     MODULE_SetEntryPoint( hModule, 173,  /* KERNEL.173: __ROMBIOS */
                           GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x60000,
-                                     0x10000, hModule, FALSE, FALSE, FALSE ) );
+                                0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
     MODULE_SetEntryPoint( hModule, 194,  /* KERNEL.194: __F000H */
                           GLOBAL_CreateBlock( GMEM_FIXED, dosmem + 0x60000,
-                                     0x10000, hModule, FALSE, FALSE, FALSE ) );
-
+                                0x10000, hModule, FALSE, FALSE, FALSE, NULL ));
     return TRUE;
 }
 
@@ -304,15 +302,8 @@
     {
         minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
         if (i == pModule->ss) minsize += pModule->stack_size;
-        if (i == pModule->dgroup)
-        {
-#if 0
-            /* FIXME: this is needed because heap growing is not implemented */
-            pModule->heap_size = 0x10000 - minsize;
-#endif
-            /* The DGROUP is allocated by MODULE_CreateInstance */
-            continue;
-        }
+	/* The DGROUP is allocated by MODULE_CreateInstance */
+        if (i == pModule->dgroup) continue;
         pSegment->selector = GLOBAL_Alloc( GMEM_ZEROINIT | GMEM_FIXED,
                                       minsize, hModule,
                                       !(pSegment->flags & NE_SEGFLAGS_DATA),
@@ -1013,6 +1004,12 @@
 /**********************************************************************
  *	    GetModuleHandle    (KERNEL.47)
  */
+HMODULE WIN16_GetModuleHandle( SEGPTR name )
+{
+    if (HIWORD(name) == 0) return GetExePtr( LOWORD(name) );
+    return MODULE_FindModule( PTR_SEG_TO_LIN(name) );
+}
+
 HMODULE GetModuleHandle( LPCSTR name )
 {
     return MODULE_FindModule( name );
diff --git a/loader/pe_image.c b/loader/pe_image.c
index ee1b119..2d284b5 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -197,7 +197,7 @@
 		      wpnt->fd, wpnt->pe->pe_seg[i].PointerToRawData);
 	}
 	if(result==-1){
-		fprintf(stderr,"Could not load section %x to desired address %x\n",
+		fprintf(stderr,"Could not load section %x to desired address %lx\n",
 			i, load_addr+wpnt->pe->pe_seg[i].Virtual_Address);
 		fprintf(stderr,"Need to implement relocations now\n");
 		exit(0);
diff --git a/loader/resource.c b/loader/resource.c
index 4cf44cf..4e6bbfc 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -32,6 +32,16 @@
     else \
         dprintf_resource( stddeb, "#%04x", LOWORD(name)); 
 
+
+/**********************************************************************
+ *	    LoadIconHandler    (USER.456)
+ */
+HICON LoadIconHandler( HANDLE hResource, BOOL bNew )
+{
+  return 0;
+}
+
+
 /**********************************************************************
  *	    FindResource    (KERNEL.60)
  */
diff --git a/loader/selector.c b/loader/selector.c
index d04e4f1..ab211bd 100644
--- a/loader/selector.c
+++ b/loader/selector.c
@@ -8,33 +8,12 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <unistd.h>
 
 #ifndef WINELIB
 
-#ifdef __linux__
-#include <sys/mman.h>
-#include <linux/unistd.h>
-#include <linux/head.h>
-#include <linux/mman.h>
-#include <linux/a.out.h>
-#include <linux/ldt.h>
-#endif
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#include <sys/mman.h>
-#include <machine/segments.h>
-#endif
-
 #include "windows.h"
-#include "ldt.h"
-#include "wine.h"
 #include "global.h"
-#include "dlls.h"
-#include "neexe.h"
-#include "prototypes.h"
 #include "module.h"
 #include "stddebug.h"
 /* #define DEBUG_SELECTORS */
diff --git a/loader/signal.c b/loader/signal.c
index e7c8381..4ede072 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -15,7 +15,6 @@
 #endif
 
 #include "debugger.h"
-#include "prototypes.h"
 #include "miscemu.h"
 #include "registers.h"
 #include "win.h"
@@ -24,6 +23,7 @@
 char * cstack[4096];
 #endif
 struct sigaction segv_act;
+struct sigaction usr2_act;
 
 #ifdef linux
 extern void ___sig_restore();
@@ -71,15 +71,21 @@
 
 void init_wine_signals(void)
 {
+        extern void stop_wait(int a);
 #ifdef linux
 	segv_act.sa_handler = (__sighandler_t) win_fault;
 	/* Point to the top of the stack, minus 4 just in case, and make
 	   it aligned  */
 	segv_act.sa_restorer = 
-		(void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
+	    (void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
+	usr2_act.sa_restorer= segv_act.sa_restorer;
+	usr2_act.sa_handler = (__sighandler_t) stop_wait;
+	/* Point to the top of the stack, minus 4 just in case, and make
+	   it aligned  */
 	wine_sigaction(SIGSEGV, &segv_act, NULL);
 	wine_sigaction(SIGILL, &segv_act, NULL);
 	wine_sigaction(SIGFPE, &segv_act, NULL);
+	wine_sigaction(SIGUSR2, &usr2_act, NULL);
 #ifdef SIGBUS
 	wine_sigaction(SIGBUS, &segv_act, NULL);
 #endif
@@ -126,6 +132,13 @@
                 perror("sigaction: SIGTRAP");
                 exit(1);
         }
+        usr2_act.sa_handler = (void (*)) stop_wait; /* For breakpoints */
+	usr2_act.sa_flags = SA_ONSTACK;
+        usr2_act.sa_mask = sig_mask;
+	if (sigaction(SIGUSR2, &usr2_act, NULL) < 0) {
+                perror("sigaction: SIGUSR2");
+                exit(1);
+        }
 #endif
 }
 
diff --git a/loader/task.c b/loader/task.c
index 222bd01..53d1006 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -21,6 +21,7 @@
 #include "toolhelp.h"
 #include "stddebug.h"
 #include "debug.h"
+#include "dde_proc.h"
 
   /* Min. number of thunks allocated when creating a new segment */
 #define MIN_THUNKS  32
@@ -247,7 +248,8 @@
     STACK16FRAME *frame16;
     STACK32FRAME *frame32;
     extern DWORD CALL16_RetAddr_word;
-
+    char filename[256];
+    
     if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
     pSegTable = NE_SEG_TABLE( pModule );
 
@@ -258,6 +260,12 @@
     if (!hTask) return 0;
     pTask = (TDB *)GlobalLock( hTask );
 
+      /* get current directory */
+    
+    GetModuleFileName( hModule, filename, sizeof(filename) );
+    name = strrchr(filename, '\\');
+    if (name) *(name+1) = 0;
+
       /* Fill the task structure */
 
     pTask->nEvents       = 1;  /* So the task can be started */
@@ -268,10 +276,10 @@
     pTask->hPrevInstance = hPrevInstance;
     pTask->hModule       = hModule;
     pTask->hParent       = hCurrentTask;
-    pTask->curdrive      = 'C' - 'A' + 0x80;
+    pTask->curdrive      = filename[0] - 'A' + 0x80;
     pTask->magic         = TDB_MAGIC;
     pTask->nCmdShow      = cmdShow;
-    strcpy( pTask->curdir, "WINDOWS" );
+    strcpy( pTask->curdir, filename+2 );
 
       /* Create the thunks block */
 
@@ -302,13 +310,13 @@
       /* Allocate a selector for the PDB */
 
     pTask->hPDB = GLOBAL_CreateBlock( GMEM_FIXED, &pTask->pdb, sizeof(PDB),
-                                      hModule, FALSE, FALSE, FALSE );
+                                      hModule, FALSE, FALSE, FALSE, NULL );
 
       /* Allocate a code segment alias for the TDB */
 
     pTask->hCSAlias = GLOBAL_CreateBlock( GMEM_FIXED, (void *)pTask,
                                           sizeof(TDB), pTask->hPDB, TRUE,
-                                          FALSE, FALSE );
+                                          FALSE, FALSE, NULL );
 
       /* Set the owner of the environment block */
 
@@ -326,6 +334,7 @@
 
       /* Create the 32-bit stack frame */
 
+    *(DWORD *)GlobalLock(pTask->hStack32) = 0xDEADBEEF;
     stack32Top = (char*)GlobalLock(pTask->hStack32) + STACK32_SIZE;
     frame32 = (STACK32FRAME *)stack32Top - 1;
     frame32->saved_esp = (DWORD)stack32Top;
@@ -342,13 +351,13 @@
       /* Create the 16-bit stack frame */
 
     pTask->ss = hInstance;
-    pTask->sp = (pModule->sp != 0) ? pModule->sp :
-                pSegTable[pModule->ss-1].minsize + pModule->stack_size;
+    pTask->sp = ((pModule->sp != 0) ? pModule->sp :
+                 pSegTable[pModule->ss-1].minsize + pModule->stack_size) & ~1;
     stack16Top = (char *)PTR_SEG_OFF_TO_LIN( pTask->ss, pTask->sp );
     frame16 = (STACK16FRAME *)stack16Top - 1;
     frame16->saved_ss = pTask->ss;
     frame16->saved_sp = pTask->sp;
-    frame16->ds = pTask->hInstance;
+    frame16->ds = frame16->es = pTask->hInstance;
     frame16->entry_point = 0;
     frame16->ordinal_number = 24;  /* WINPROCS.24 is TASK_Reschedule */
     frame16->dll_id = 24; /* WINPROCS */
@@ -461,6 +470,7 @@
     TDB *pOldTask = NULL, *pNewTask;
     HTASK hTask = 0;
 
+    dde_reschedule();
       /* First check if there's a task to kill */
 
     if (hTaskToKill && (hTaskToKill != hCurrentTask))
diff --git a/memory/Makefile.in b/memory/Makefile.in
new file mode 100644
index 0000000..80be79a
--- /dev/null
+++ b/memory/Makefile.in
@@ -0,0 +1,49 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include
+LD	= @LD@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+
+
+MODULE 	= memory
+
+SRCS	= selector.c global.c ldt.c local.c
+ 
+OBJS = $(SRCS:.c=.o)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
+
+all: $(MODULE).o
+
+$(MODULE).o: $(OBJS)
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dummy:
+
+### Dependencies:
diff --git a/memory/global.c b/memory/global.c
index c1f5ab9..83c3213 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -6,10 +6,12 @@
 
 #include <stdlib.h>
 #include <string.h>
+
 #include "windows.h"
 #include "global.h"
 #include "toolhelp.h"
 #include "selectors.h"
+#include "dde_mem.h"
 #include "stackframe.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -25,12 +27,14 @@
     BYTE     pageLockCount;  /* Count of GlobalPageLock() calls */
     BYTE     flags;          /* Allocation flags */
     BYTE     selCount;       /* Number of selectors allocated for this block */
+    int      shmid;
 } GLOBALARENA;
 
   /* Flags definitions */
 #define GA_MOVEABLE     0x02  /* same as GMEM_MOVEABLE */
 #define GA_DGROUP       0x04
 #define GA_DISCARDABLE  0x08
+#define GA_IPCSHARE     0x10  /* same as GMEM_DDESHARE */
 
   /* Arena array */
 static GLOBALARENA *pGlobalArena = NULL;
@@ -62,6 +66,36 @@
 }
 
 
+void debug_handles()
+{
+    int printed=0;
+    int i;
+    for (i = globalArenaSize-1 ; i>=0 ; i--) {
+	if (pGlobalArena[i].size!=0 && (pGlobalArena[i].handle & 0x8000)){
+	    printed=1;
+	    printf("0x%08x, ",pGlobalArena[i].handle);
+	}
+    }
+    if (printed)
+	printf("\n");
+}
+/***********************************************************************
+ *           GLOBAL_FindArena
+ *
+ * Find the arena  for a given handle
+ * (when handle is not serial - e.g. DDE)
+ */
+static GLOBALARENA *GLOBAL_FindArena( HGLOBAL handle)
+{
+    int i;
+    for (i = globalArenaSize-1 ; i>=0 ; i--) {
+	if (pGlobalArena[i].size!=0 && pGlobalArena[i].handle == handle)
+	    return ( &pGlobalArena[i] );
+    }
+    return NULL;
+}
+
+
 /***********************************************************************
  *           GLOBAL_CreateBlock
  *
@@ -69,15 +103,18 @@
  */
 HGLOBAL GLOBAL_CreateBlock( WORD flags, void *ptr, DWORD size,
                             HGLOBAL hOwner, BOOL isCode,
-                            BOOL is32Bit, BOOL isReadOnly  )
+                            BOOL is32Bit, BOOL isReadOnly,
+			    SHMDATA *shmdata  )
 {
     WORD sel, selcount;
     GLOBALARENA *pArena;
 
       /* Allocate the selector(s) */
 
-    sel = SELECTOR_AllocBlock( ptr, size, isCode ? SEGMENT_CODE : SEGMENT_DATA,
-                               is32Bit, isReadOnly );
+    sel = SELECTOR_AllocBlock( ptr, size,
+			      isCode ? SEGMENT_CODE : SEGMENT_DATA,
+			      is32Bit, isReadOnly );
+    
     if (!sel) return 0;
     selcount = (size + 0xffff) / 0x10000;
 
@@ -91,12 +128,23 @@
 
     pArena->base = (DWORD)ptr;
     pArena->size = GET_SEL_LIMIT(sel) + 1;
-    pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
+    if (flags & GMEM_DDESHARE)
+    {
+	pArena->handle = shmdata->handle;
+	pArena->shmid  = shmdata->shmid;
+	shmdata->sel   = sel;
+    }
+    else
+    {
+	pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
+	pArena->shmid  = 0;
+    }
     pArena->hOwner = hOwner;
     pArena->lockCount = 0;
     pArena->pageLockCount = 0;
     pArena->flags = flags & GA_MOVEABLE;
     if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
+    if (flags & GMEM_DDESHARE) pArena->flags |= GA_IPCSHARE;
     if (!isCode) pArena->flags |= GA_DGROUP;
     pArena->selCount = selcount;
     if (selcount > 1)  /* clear the next arena blocks */
@@ -119,7 +167,7 @@
     if (!handle) return TRUE;
     sel = GlobalHandleToSel( handle );
     if (FreeSelector( sel )) return FALSE;  /* failed */
-    memset( GET_ARENA_PTR(handle), 0, sizeof(GLOBALARENA) );
+    memset( GET_ARENA_PTR(sel), 0, sizeof(GLOBALARENA) );
     return TRUE;
 }
 
@@ -134,6 +182,7 @@
 {
     void *ptr;
     HGLOBAL handle;
+    SHMDATA shmdata;
 
     dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
 
@@ -145,13 +194,16 @@
 
       /* Allocate the linear memory */
 
-    ptr = malloc( size );
+    if (flags & GMEM_DDESHARE) 
+        ptr= DDE_malloc(flags, size, &shmdata);
+    else 
+	ptr = malloc( size );
     if (!ptr) return 0;
 
       /* Allocate the selector(s) */
 
     handle = GLOBAL_CreateBlock( flags, ptr, size, hOwner,
-                                 isCode, is32Bit, isReadOnly);
+				isCode, is32Bit, isReadOnly, &shmdata);
     if (!handle)
     {
         free( ptr );
@@ -162,6 +214,29 @@
     return handle;
 }
 
+/***********************************************************************
+ *           DDE_GlobalHandleToSel
+ */
+
+WORD DDE_GlobalHandleToSel( HGLOBAL handle )
+{
+    GLOBALARENA *pArena;
+    SEGPTR segptr;
+    
+    pArena= GLOBAL_FindArena(handle);
+    if (pArena) {
+	int ArenaIdx = pArena - pGlobalArena;
+
+	/* See if synchronized to the shared memory  */
+	return DDE_SyncHandle(handle, ( ArenaIdx << __AHSHIFT) | 7);
+    }
+
+    /* attach the block */
+    DDE_AttachHandle(handle, &segptr);
+
+    return SELECTOROF( segptr );
+}
+
 
 /***********************************************************************
  *           GlobalAlloc   (KERNEL.15)
@@ -172,7 +247,6 @@
 
     if (flags & GMEM_DDESHARE)
         owner = GetExePtr(owner);  /* Make it a module handle */
-
     return GLOBAL_Alloc( flags, size, owner, FALSE, FALSE, FALSE );
 }
 
@@ -182,14 +256,22 @@
  */
 HGLOBAL GlobalReAlloc( HGLOBAL handle, DWORD size, WORD flags )
 {
-    WORD sel, selcount;
+    WORD selcount;
     DWORD oldsize;
     void *ptr;
     GLOBALARENA *pArena, *pNewArena;
+    WORD sel = GlobalHandleToSel( handle );
 
     dprintf_global( stddeb, "GlobalReAlloc: %04x %ld flags=%04x\n",
                     handle, size, flags );
     if (!handle) return 0;
+    
+    if (flags & GMEM_DDESHARE || is_dde_handle(handle)) {
+	fprintf(stdnimp,
+		"GlobalReAlloc: shared memory reallocating unimplemented\n"); 
+	return 0;
+    }
+
     pArena = GET_ARENA_PTR( handle );
 
       /* Discard the block if requested */
@@ -201,6 +283,10 @@
             (pArena->lockCount > 0) || (pArena->pageLockCount > 0)) return 0;
         free( (void *)pArena->base );
         pArena->base = 0;
+        /* Note: we rely on the fact that SELECTOR_ReallocBlock won't */
+        /* change the selector if we are shrinking the block */
+        SELECTOR_ReallocBlock( sel, 0, 1, SEGMENT_DATA, 0, 0 );
+        return handle;
     }
 
       /* Fixup the size */
@@ -221,7 +307,6 @@
 
       /* Reallocate the linear memory */
 
-    sel = GlobalHandleToSel( handle );
     ptr = (void *)pArena->base;
     oldsize = pArena->size;
     dprintf_global(stddeb,"oldsize %08lx\n",oldsize);
@@ -275,12 +360,12 @@
  */
 HGLOBAL GlobalFree( HGLOBAL handle )
 {
-    void *ptr;
+    void *ptr = GlobalLock( handle );
 
     dprintf_global( stddeb, "GlobalFree: %04x\n", handle );
-    if (!(ptr = GlobalLock( handle ))) return handle;  /* failed */
     if (!GLOBAL_FreeBlock( handle )) return handle;  /* failed */
-    free( ptr );
+    if (is_dde_handle(handle)) return DDE_GlobalFree(handle);
+    if (ptr) free( ptr );
     return 0;
 }
 
@@ -295,7 +380,9 @@
     dprintf_global( stddeb, "WIN16_GlobalLock(%04x) -> %08lx\n",
                     handle, MAKELONG( 0, GlobalHandleToSel(handle)) );
     if (!handle) return 0;
-    if (!GET_ARENA_PTR(handle)->base) return (SEGPTR)0;
+    if ( !is_dde_handle(handle) && !GET_ARENA_PTR(handle)->base)
+	return (SEGPTR)0;
+
     return (SEGPTR)MAKELONG( 0, GlobalHandleToSel(handle) );
 }
 
@@ -308,6 +395,9 @@
 LPSTR GlobalLock( HGLOBAL handle )
 {
     if (!handle) return 0;
+    if (is_dde_handle(handle)) {
+       return DDE_AttachHandle(handle, NULL);
+    }
     return (LPSTR)GET_ARENA_PTR(handle)->base;
 }
 
@@ -552,6 +642,9 @@
 {
     dprintf_toolhelp( stddeb, "GlobalHandleToSel: %04x\n", handle );
     if (!handle) return 0;
+    if (is_dde_handle(handle)) 
+	return DDE_GlobalHandleToSel(handle);
+
     if (!(handle & 7))
     {
         fprintf( stderr, "Program attempted invalid selector conversion\n" );
diff --git a/memory/ldt.c b/memory/ldt.c
index f80b2cc..2b07893 100644
--- a/memory/ldt.c
+++ b/memory/ldt.c
@@ -157,7 +157,8 @@
     ldt_flags_copy[entry] = (content->type & LDT_FLAGS_TYPE) |
                             (content->read_only ? LDT_FLAGS_READONLY : 0) |
                             (content->seg_32bit ? LDT_FLAGS_32BIT : 0) |
-                            (content->limit_in_pages ? LDT_FLAGS_BIG : 0);
+                            (content->limit_in_pages ? LDT_FLAGS_BIG : 0) |
+                            (ldt_flags_copy[entry] & LDT_FLAGS_ALLOCATED);
     return ret;
 }
 
diff --git a/memory/selector.c b/memory/selector.c
index 57afc7f..1959c71 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -8,6 +8,7 @@
 #include "windows.h"
 #include "ldt.h"
 #include "selectors.h"
+#include "stackframe.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -29,7 +30,9 @@
         else if (++size >= count) break;
     }
     if (i == LDT_SIZE) return 0;
-    return ENTRY_TO_SELECTOR( i - size + 1 );
+    /* Mark selector as allocated */
+    while (size--) ldt_flags_copy[i--] |= LDT_FLAGS_ALLOCATED;
+    return ENTRY_TO_SELECTOR( i + 1 );
 }
 
 
@@ -68,8 +71,22 @@
     if (IS_SELECTOR_FREE(sel)) return sel;  /* error */
     count = (GET_SEL_LIMIT(sel) >> 16) + 1;
     memset( &entry, 0, sizeof(entry) );  /* clear the LDT entries */
-    for (i = 0; i < count; i++)
-        LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
+    /* FIXME: is it correct to free the whole array? */
+    for (i = SELECTOR_TO_ENTRY(sel); count; i++, count--)
+    {
+        LDT_SetEntry( i, &entry );
+        ldt_flags_copy[i] &= ~LDT_FLAGS_ALLOCATED;
+    }
+
+    /* Clear the saved 16-bit selector */
+#ifndef WINELIB
+    if (CURRENT_STACK16)
+    {
+        /* FIXME: maybe we ought to walk up the stack and fix all frames */
+        if (CURRENT_STACK16->ds == sel) CURRENT_STACK16->ds = 0;
+        if (CURRENT_STACK16->es == sel) CURRENT_STACK16->es = 0;
+    }
+#endif
     return 0;
 }
 
@@ -108,38 +125,6 @@
 
 
 /***********************************************************************
- *           SELECTOR_ReallocArray
- *
- * Change the size of an allocated selector array.
- */
-static WORD SELECTOR_ReallocArray( WORD sel, WORD newcount )
-{
-    WORD i, oldcount;
-    ldt_entry entry;
-
-    oldcount = (GET_SEL_LIMIT(sel) >> 16) + 1;
-    if (oldcount < newcount)  /* We need to add selectors */
-    {
-          /* Check if the next selectors are free */
-        for (i = oldcount; i < newcount; i++)
-            if (!IS_SELECTOR_FREE(sel+i)) break;
-        if (i < newcount)
-        {
-            FreeSelector( sel );
-            sel = AllocSelectorArray( newcount );
-        }
-    }
-    else if (oldcount > newcount) /* We need to remove selectors */
-    {
-        memset( &entry, 0, sizeof(entry) );  /* clear the LDT entries */
-        for (i = oldcount; i < newcount; i++)
-            LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
-    }
-    return sel;
-}
-
-
-/***********************************************************************
  *           SELECTOR_AllocBlock
  *
  * Allocate selectors for a block of linear memory.
@@ -165,15 +150,41 @@
 WORD SELECTOR_ReallocBlock( WORD sel, void *base, DWORD size,
                             enum seg_type type, BOOL is32bit, BOOL readonly )
 {
-    WORD count;
+    WORD i, oldcount, newcount;
+    ldt_entry entry;
 
-    if (!size)
+    if (!size) size = 1;
+    oldcount = (GET_SEL_LIMIT(sel) >> 16) + 1;
+    newcount = (size + 0xffff) >> 16;
+
+    if (oldcount < newcount)  /* We need to add selectors */
     {
-        FreeSelector( sel );
-        return 0;
+          /* Check if the next selectors are free */
+        if (SELECTOR_TO_ENTRY(sel) + newcount > LDT_SIZE) i = oldcount;
+        else
+            for (i = oldcount; i < newcount; i++)
+                if (!IS_LDT_ENTRY_FREE(SELECTOR_TO_ENTRY(sel)+i)) break;
+
+        if (i < newcount)  /* they are not free */
+        {
+            FreeSelector( sel );
+            sel = AllocSelectorArray( newcount );
+        }
+        else  /* mark the selectors as allocated */
+        {
+            for (i = oldcount; i < newcount; i++)
+                ldt_flags_copy[SELECTOR_TO_ENTRY(sel)+i] |=LDT_FLAGS_ALLOCATED;
+        }
     }
-    count = (size + 0xffff) / 0x10000;
-    sel = SELECTOR_ReallocArray( sel, count );
+    else if (oldcount > newcount) /* We need to remove selectors */
+    {
+        memset( &entry, 0, sizeof(entry) );  /* clear the LDT entries */
+        for (i = oldcount; i < newcount; i++)
+        {
+            LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
+            ldt_flags_copy[SELECTOR_TO_ENTRY(sel) + i] &= ~LDT_FLAGS_ALLOCATED;
+        }
+    }
     if (sel) SELECTOR_SetEntries( sel, base, size, type, is32bit, readonly );
     return sel;
 }
diff --git a/misc/Makefile.in b/misc/Makefile.in
new file mode 100644
index 0000000..84afd90
--- /dev/null
+++ b/misc/Makefile.in
@@ -0,0 +1,59 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include -I$(TOPSRC)
+LD	= @LD@
+LANG	= @LANG@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+@SET_MAKE@
+
+
+MODULE 	= misc
+
+SRCS 	= atom.c clipboard.c comm.c commdlg.c compobj.c dos_fs.c \
+	driver.c exec.c escape.c file.c keyboard.c kernel32.c lstr.c \
+	main.c ole2.c ole2disp.c ole2nls.c olecli.c olesvr.c network.c \
+	profile.c rect.c shell.c sound.c spy.c stress.c user.c \
+	winsocket.c
+ 
+OBJS = $(SRCS:.c=.o)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) $(LANG) -o $*.o $<
+
+all: checkrc $(MODULE).o
+
+checkrc:
+	(cd $(TOPSRC)/rc; $(MAKE) 'CC=$(CC)' 'CFLAGS=$(CFLAGS)' 'LD=$(LD)' 'LDCOMBINEFLAGS=$(LDCOMBINEFLAGS)')
+
+$(MODULE).o: $(OBJS)
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+	rm -f ole2nls.o shell.o commdlg.o
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dummy:
+
+### Dependencies:
diff --git a/misc/atom.c b/misc/atom.c
index a34e062..f3286cd 100644
--- a/misc/atom.c
+++ b/misc/atom.c
@@ -329,36 +329,36 @@
 
 
 /***********************************************************************
- *           GlobalAddAtom   (USER.268)
+ *           LocalAddAtom   (USER.268)
  */
-ATOM GlobalAddAtom( LPCSTR str )
+ATOM LocalAddAtom( LPCSTR str )
 {
     return ATOM_AddAtom( USER_HeapSel, str );
 }
 
 
 /***********************************************************************
- *           GlobalDeleteAtom   (USER.269)
+ *           LocalDeleteAtom   (USER.269)
  */
-ATOM GlobalDeleteAtom( ATOM atom )
+ATOM LocalDeleteAtom( ATOM atom )
 {
     return ATOM_DeleteAtom( USER_HeapSel, atom );
 }
 
 
 /***********************************************************************
- *           GlobalFindAtom   (USER.270)
+ *           LocalFindAtom   (USER.270)
  */
-ATOM GlobalFindAtom( LPCSTR str )
+ATOM LocalFindAtom( LPCSTR str )
 {
     return ATOM_FindAtom( USER_HeapSel, str );
 }
 
 
 /***********************************************************************
- *           GlobalGetAtomName   (USER.271)
+ *           LocalGetAtomName   (USER.271)
  */
-WORD GlobalGetAtomName( ATOM atom, LPSTR buffer, short count )
+WORD LocalGetAtomName( ATOM atom, LPSTR buffer, short count )
 {
     return ATOM_GetAtomName( USER_HeapSel, atom, buffer, count );
 }
diff --git a/misc/dos_fs.c b/misc/dos_fs.c
index 08de3c0..c1fd240 100644
--- a/misc/dos_fs.c
+++ b/misc/dos_fs.c
@@ -31,6 +31,7 @@
 #include "dos_fs.h"
 #include "autoconf.h"
 #include "comm.h"
+#include "task.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -47,7 +48,7 @@
 struct DosDriveStruct {			/*  eg: */
 	char 		*rootdir;	/*  /usr/windows 	*/
 	char 		cwd[256];	/*  /			*/
-	char 		label[13];	/*  DRIVE-A		*/		
+	char 		label[13];	/*  DRIVE-A		*/
 	unsigned int	serialnumber;	/*  ABCD5678		*/
 	int 		disabled;	/*  0			*/
 };
@@ -83,146 +84,154 @@
     *s = 0;
 }
 
+/* Simplify the path in "name" by removing  "//"'s and
+   ".."'s in names like "/usr/bin/../lib/test" */
+static void DOS_SimplifyPath(char *name)
+{
+  char *l,*p;
+  BOOL changed;
+
+  dprintf_dosfs(stddeb,"SimplifyPath: Before %s\n",name);
+  do {
+    changed = FALSE;
+    while ((l = strstr(name,"//"))) {
+      strcpy(l,l+1); changed = TRUE;
+    } 
+    while ((l = strstr(name,"/../"))) {
+      *l = 0;
+      p = strrchr(name,'/');
+      if (p == NULL) p = name;
+      strcpy(p,l+3);
+      changed = TRUE;
+    }
+  } while (changed);
+  dprintf_dosfs(stddeb,"SimplifyPath: After %s\n",name);
+}
+
+
+/* ChopOffSlash takes care to strip directory slashes from the
+ * end off the path name, but leaves a single slash. Multiple
+ * slashes at the end of a path are all removed.
+ */
+
 void ChopOffSlash(char *path)
 {
-	if (path[strlen(path)-1] == '/' || path[strlen(path)-1] == '\\')
-		path[strlen(path)-1] = '\0';
+    char *p = path + strlen(path) - 1;
+    while ((*p == '\\') && (p > path)) *p-- = '\0';
 }
 
 void ToUnix(char *s)
 {
-	/*  \WINDOWS\\SYSTEM   =>   /windows/system */
-
-	char *p;
-
-	for (p = s; *p; p++) 
-	{
-		if (*p != '\\')
-			*s++ = tolower(*p);
-		else {
-			*s++ = '/';
-			if (*(p+1) == '/' || *(p+1) == '\\')
-				p++;
-		}
-	}
-	*s = '\0';
+    while(*s){
+	if (*s == '\\') *s = '/';
+	s++;
+    }
 }
 
 void ToDos(char *s)
 {
-	/* /windows//system   =>   \WINDOWS\SYSTEM */
-
-	char *p;
-	for (p = s; *p; p++) 
-	{
-		if (*p != '/')
-			*s++ = toupper(*p);
-		else {
-			*s++ = '\\';
-			if (*(p+1) == '/' || *(p+1) == '\\') 
-			    p++;
-		}
-	}
-	*s = '\0';
+    while(*s){
+	if (*s == '/') *s = '\\';
+	s++;
+    }
 }
 
 void DOS_InitFS(void)
 {
-	int x;
-	char drive[2], temp[256];
+    int x;
+    char drive[2], temp[256];
+    
+    GetPrivateProfileString("wine", "windows", "c:\\windows", 
+			    WindowsDirectory, sizeof(WindowsDirectory), WINE_INI);
+    
+    GetPrivateProfileString("wine", "system", "c:\\windows\\system", 
+			    SystemDirectory, sizeof(SystemDirectory), WINE_INI);
+    
+    GetPrivateProfileString("wine", "temp", "c:\\windows", 
+			    TempDirectory, sizeof(TempDirectory), WINE_INI);
 
-	GetPrivateProfileString("wine", "windows", "c:\\windows", 
-		WindowsDirectory, sizeof(WindowsDirectory), WINE_INI);
-
-	GetPrivateProfileString("wine", "system", "c:\\windows\\system", 
-		SystemDirectory, sizeof(SystemDirectory), WINE_INI);
-
-	GetPrivateProfileString("wine", "temp", "c:\\windows", 
-		TempDirectory, sizeof(TempDirectory), WINE_INI);
-
-	GetPrivateProfileString("wine", "path", "c:\\windows;c:\\windows\\system", 
-		WindowsPath, sizeof(WindowsPath), WINE_INI);
-
-	ChopOffSlash(WindowsDirectory);
-	ToDos(WindowsDirectory);
-
-	ChopOffSlash(SystemDirectory);
-	ToDos(SystemDirectory);
-
-	ChopOffSlash(TempDirectory);
-	ToDos(TempDirectory);
-
-	ToDos(WindowsPath);
-	ExpandTildeString(WindowsPath);
-
-	for (x=0; x!=MAX_DOS_DRIVES; x++) {
-		DosDrives[x].serialnumber = (0xEB0500L | x);
-		
-		drive[0] = 'A' + x;
-		drive[1] = '\0';
-		GetPrivateProfileString("drives", drive, "*", temp, sizeof(temp), WINE_INI);
-		if (!strcmp(temp, "*") || *temp == '\0') {
-			DosDrives[x].rootdir = NULL;		
-			DosDrives[x].cwd[0] = '\0';
-			DosDrives[x].label[0] = '\0';
-			DosDrives[x].disabled = 1;
-			continue;
-		}
-		ExpandTildeString(temp);
-		ChopOffSlash(temp);
-		DosDrives[x].rootdir = strdup(temp);
-		strcpy(DosDrives[x].rootdir, temp);
-		strcpy(DosDrives[x].cwd, "/windows/");
-		strcpy(DosDrives[x].label, "DRIVE-");
-		strcat(DosDrives[x].label, drive);
-		DosDrives[x].disabled = 0;
+    GetPrivateProfileString("wine", "path", "c:\\windows;c:\\windows\\system", 
+			    WindowsPath, sizeof(WindowsPath), WINE_INI);
+    
+    ChopOffSlash(WindowsDirectory);
+    ToDos(WindowsDirectory);
+    
+    ChopOffSlash(SystemDirectory);
+    ToDos(SystemDirectory);
+    
+    ChopOffSlash(TempDirectory);
+    ToDos(TempDirectory);
+    
+    ToDos(WindowsPath);
+    ExpandTildeString(WindowsPath);
+    
+    for (x=0; x!=MAX_DOS_DRIVES; x++) {
+	DosDrives[x].serialnumber = (0xEB0500L | x);
+	
+	drive[0] = 'A' + x;
+	drive[1] = '\0';
+	GetPrivateProfileString("drives", drive, "*", temp, sizeof(temp), WINE_INI);
+	if (!strcmp(temp, "*") || *temp == '\0') {
+	    DosDrives[x].rootdir = NULL;		
+	    DosDrives[x].cwd[0] = '\0';
+	    DosDrives[x].label[0] = '\0';
+	    DosDrives[x].disabled = 1;
+	    continue;
 	}
-	DosDrives[25].rootdir = "/";
-	strcpy(DosDrives[25].cwd, "/");
-	strcpy(DosDrives[25].label, "UNIX-FS");
-	DosDrives[25].serialnumber = 0x12345678;
-	DosDrives[25].disabled = 0;
+	ExpandTildeString(temp);
+	ChopOffSlash(temp);
+	DosDrives[x].rootdir = strdup(temp);
+	strcpy(DosDrives[x].rootdir, temp);
+	strcpy(DosDrives[x].cwd, "/windows/");
+	strcpy(DosDrives[x].label, "DRIVE-");
+	strcat(DosDrives[x].label, drive);
+	DosDrives[x].disabled = 0;
+    }
+    DosDrives[25].rootdir = "/";
+    strcpy(DosDrives[25].cwd, "/");
+    strcpy(DosDrives[25].label, "UNIX-FS");
+    DosDrives[25].serialnumber = 0x12345678;
+    DosDrives[25].disabled = 0;
+    
+    /* Get the startup directory and try to map it to a DOS drive
+     * and directory.  (i.e., if we start in /dos/windows/word and
+     * drive C is defined as /dos, the starting wd for C will be
+     * /windows/word)  Also set the default drive to whatever drive
+     * corresponds to the directory we started in.
+     */
 
-        /* Get the startup directory and try to map it to a DOS drive
-         * and directory.  (i.e., if we start in /dos/windows/word and
-         * drive C is defined as /dos, the starting wd for C will be
-         * /windows/word)  Also set the default drive to whatever drive
-         * corresponds to the directory we started in.
-         */
+    for (x=0; x!=MAX_DOS_DRIVES; x++) 
+        if (DosDrives[x].rootdir != NULL) 
+	    strcpy( DosDrives[x].cwd, "/" );
 
-        for (x=0; x!=MAX_DOS_DRIVES; x++) 
-	  if (DosDrives[x].rootdir != NULL) 
-	    strcpy( DosDrives[x].cwd, "\\" );
-
-        getcwd(temp, 254);
-        strcat(temp, "/");      /* For DOS_GetDosFileName */
-        strcpy(temp, DOS_GetDosFileName(temp));
-        if(temp[0] != 'Z')
-        {
-            ToUnix(&temp[2]);
-            strcpy(DosDrives[temp[0] - 'A'].cwd, &temp[2]);
-            DOS_SetDefaultDrive(temp[0] - 'A');
-        }
-        else
-        {
-	    DOS_SetDefaultDrive(2);
-        }
-
-	for (x=0; x!=MAX_DOS_DRIVES; x++) {
-		if (DosDrives[x].rootdir != NULL) {
-            dprintf_dosfs(stddeb, "DOSFS: %c: => %-40s %s %s %X %d\n",
-			'A'+x,
-			DosDrives[x].rootdir,
-			DosDrives[x].cwd,
-			DosDrives[x].label,
-			DosDrives[x].serialnumber,
-			DosDrives[x].disabled
-			);	
-		}
+    getcwd(temp, 254);
+    strcat(temp, "/");      /* For DOS_GetDosFileName */
+    strcpy(temp, DOS_GetDosFileName(temp));
+    if(temp[0] != 'Z')
+    {
+	ToUnix(temp + 2);
+	strcpy(DosDrives[temp[0] - 'A'].cwd, &temp[2]);
+	DOS_SetDefaultDrive(temp[0] - 'A');
+    }
+    else
+    {
+	DOS_SetDefaultDrive(2);
+    }
+    
+    for (x=0; x!=MAX_DOS_DRIVES; x++) {
+	if (DosDrives[x].rootdir != NULL) {
+	    dprintf_dosfs(stddeb, "DOSFS: %c: => %-40s %s %s %X %d\n",
+			  'A'+x,
+			  DosDrives[x].rootdir,
+			  DosDrives[x].cwd,
+			  DosDrives[x].label,
+			  DosDrives[x].serialnumber,
+			  DosDrives[x].disabled);	
 	}
-
-	for (x=0; x!=max_open_dirs ; x++)
-		DosDirs[x].inuse = 0;
+    }
+    
+    for (x=0; x!=max_open_dirs ; x++)
+        DosDirs[x].inuse = 0;
 
     dprintf_dosfs(stddeb,"wine.ini = %s\n",WINE_INI);
     dprintf_dosfs(stddeb,"win.ini = %s\n",WIN_INI);
@@ -234,11 +243,11 @@
 
 WORD DOS_GetEquipment(void)
 {
-	WORD equipment;
-	int diskdrives = 0;
-	int parallelports = 0;
-	int serialports = 0;
-	int x;
+    WORD equipment;
+    int diskdrives = 0;
+    int parallelports = 0;
+    int serialports = 0;
+    int x;
 
 /* borrowed from Ralph Brown's interrupt lists 
 
@@ -266,219 +275,102 @@
 		bit  2			(always set)
 */
 
-	if (DosDrives[0].rootdir != NULL)
-		diskdrives++;
-	if (DosDrives[1].rootdir != NULL)
-		diskdrives++;
-	if (diskdrives)
-		diskdrives--;
+    if (DosDrives[0].rootdir != NULL)
+        diskdrives++;
+    if (DosDrives[1].rootdir != NULL)
+        diskdrives++;
+    if (diskdrives)
+        diskdrives--;
 	
-	for (x=0; x!=MAX_PORTS; x++) {
-		if (COM[x].devicename)
-			serialports++;
-		if (LPT[x].devicename)
-			parallelports++;
-	}
-	if (serialports > 7)		/* 3 bits -- maximum value = 7 */
-		serialports=7;
-	if (parallelports > 3)		/* 2 bits -- maximum value = 3 */
-		parallelports=3;
-
-	equipment = (diskdrives << 6) | (serialports << 9) | 
-		    (parallelports << 14) | 0x02;
+    for (x=0; x!=MAX_PORTS; x++) {
+	if (COM[x].devicename)
+	    serialports++;
+	if (LPT[x].devicename)
+	    parallelports++;
+    }
+    if (serialports > 7)		/* 3 bits -- maximum value = 7 */
+        serialports=7;
+    if (parallelports > 3)		/* 2 bits -- maximum value = 3 */
+        parallelports=3;
+    
+    equipment = (diskdrives << 6) | (serialports << 9) | 
+                (parallelports << 14) | 0x02;
 
     dprintf_dosfs(stddeb, "DOS_GetEquipment : diskdrives = %d serialports = %d "
-			"parallelports = %d\n"
-			"DOS_GetEquipment : equipment = %d\n",
-			diskdrives, serialports, parallelports, equipment);
-
-	return (equipment);
+		  "parallelports = %d\n"
+		  "DOS_GetEquipment : equipment = %d\n",
+		  diskdrives, serialports, parallelports, equipment);
+    
+    return equipment;
 }
 
 int DOS_ValidDrive(int drive)
 {
-        int valid = 1;
+    dprintf_dosfs(stddeb,"ValidDrive %c (%d)\n",'A'+drive,drive);
 
-        dprintf_dosfs(stddeb,"ValidDrive %c (%d) -- ",'A'+drive,drive);
+    if (drive < 0 || drive >= MAX_DOS_DRIVES) return 0;
+    if (DosDrives[drive].rootdir == NULL) return 0;
+    if (DosDrives[drive].disabled) return 0;
 
-	if (drive < 0 || drive >= MAX_DOS_DRIVES)
-		valid = 0;
-	if (DosDrives[drive].rootdir == NULL)
-		valid = 0;
-	if (DosDrives[drive].disabled)
-		valid = 0;
-
-        dprintf_dosfs(stddeb, "%s\n", valid ? "Valid" : "Invalid");
-	return valid;
+    dprintf_dosfs(stddeb, " -- valid\n");
+    return 1;
 }
 
-
-int DOS_ValidDirectory(char *name)
+static void DOS_GetCurrDir_Unix(char *buffer, int drive)
 {
-	char *dirname;
-	struct stat s;
-	dprintf_dosfs(stddeb, "DOS_ValidDirectory: '%s'\n", name);
-	if ((dirname = DOS_GetUnixFileName(name)) == NULL)
-		return 0;
-	if (stat(dirname,&s))
-		return 0;
-	if (!S_ISDIR(s.st_mode))
-		return 0;
-	dprintf_dosfs(stddeb, "==> OK\n");
-	return 1;
-}
-
-
-
-/* Simplify the path in "name" by removing  "//"'s and
-   ".."'s in names like "/usr/bin/../lib/test" */
-void DOS_SimplifyPath(char *name)
-{
-  char *l,*p;
-  BOOL changed;
-
-  dprintf_dosfs(stddeb,"SimplifyPath: Before %s\n",name);
-  do {
-    changed = FALSE;
-    while ((l = strstr(name,"//"))) {
-      strcpy(l,l+1); changed = TRUE;
-    } 
-    while ((l = strstr(name,"/../"))) {
-      *l = 0;
-      p = strrchr(name,'/');
-      if (p == NULL) p = name;
-      strcpy(p,l+3);
-      changed = TRUE;
+    TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
+    
+    if (pTask != NULL && (pTask->curdrive & ~0x80) == drive) {
+	strcpy(buffer, pTask->curdir);
+	ToUnix(buffer);
+    } else {
+	strcpy(buffer, DosDrives[drive].cwd);
     }
-  } while (changed);
-  dprintf_dosfs(stddeb,"SimplifyPath: After %s\n",name);
 }
 
-
-int DOS_GetDefaultDrive(void)
-{
-    dprintf_dosfs(stddeb,"GetDefaultDrive (%c)\n",'A'+CurrentDrive);
-	return( CurrentDrive);
-}
-
-void DOS_SetDefaultDrive(int drive)
-{
-    dprintf_dosfs(stddeb,"SetDefaultDrive to %c:\n",'A'+drive);
-	if (DOS_ValidDrive(drive))
-		CurrentDrive = drive;
-}
-
-int DOS_DisableDrive(int drive)
-{
-	if (drive >= MAX_DOS_DRIVES)
-		return 0;
-	if (DosDrives[drive].rootdir == NULL)
-		return 0;
-
-	DosDrives[drive].disabled = 1;
-	return 1;
-}
-
-int DOS_EnableDrive(int drive)
-{
-	if (drive >= MAX_DOS_DRIVES)
-		return 0;
-	if (DosDrives[drive].rootdir == NULL)
-		return 0;
-
-	DosDrives[drive].disabled = 0;
-	return 1;
-}
-
-static void GetUnixDirName(char *rootdir, char *name)
-{
-	int filename = 1;
-	char *nameptr, *cwdptr;
-	
-	cwdptr = rootdir + strlen(rootdir);
-	nameptr = name;
-
-	dprintf_dosfs(stddeb,"GetUnixDirName: %s <=> %s => ",rootdir, name);
-
-	while (*nameptr) {
-		if (*nameptr == '.' & !filename) {
-			nameptr++;
-			if (*nameptr == '\0') {
-				cwdptr--;
-				break;
-			}
-			if (*nameptr == '.') {
-				cwdptr--;
-				while (cwdptr != rootdir) {
-					cwdptr--;
-					if (*cwdptr == '/') {
-						*(cwdptr+1) = '\0';
-						goto next;
-					}
-				}
-				goto next;
-			}
-			if (*nameptr == '\\' || *nameptr == '/') {
-			next:	nameptr++;		
-				filename = 0;
-				continue;
-			}
-		}
-		if (*nameptr == '\\' || *nameptr == '/') {
-			filename = 0;
-			if (nameptr == name)
-				cwdptr = rootdir;
-			*cwdptr++='/';		
-			nameptr++;
-			continue;
-		}
-		filename = 1;
-		*cwdptr++ = *nameptr++;
-	}
-	*cwdptr = '\0';
-
-	ToUnix(rootdir);
-
-	dprintf_dosfs(stddeb,"%s\n", rootdir);
-
-}
-
-char *DOS_GetUnixFileName(char *dosfilename)
+char *DOS_GetCurrentDir(int drive)
 { 
-	/*   a:\windows\system.ini  =>  /dos/windows/system.ini */
+    static char temp[256];
 
-        /* FIXME: should handle devices here (like LPT: or NUL:) */
+    if (!DOS_ValidDrive(drive)) return 0;
 
-	static char temp[256];
-	static char dostemp[256];
-	int drive;
+    DOS_GetCurrDir_Unix(temp, drive);
+    DOS_SimplifyPath( temp );
+    ToDos(temp);
+    ChopOffSlash(temp);
 
-	if (dosfilename[0] && (dosfilename[1] == ':'))
-	{
-		drive = (islower(*dosfilename) ? toupper(*dosfilename) : *dosfilename) - 'A';
-		
-		if (!DOS_ValidDrive(drive))		
-			return NULL;
-		else
-			dosfilename+=2;
-	} else
-		drive = CurrentDrive;
+    dprintf_dosfs(stddeb,"DOS_GetCWD: %c:%s\n", 'A'+drive, temp);
+    return temp + 1;
+}
 
-	/* Consider dosfilename const */
-	strncpy( dostemp, dosfilename, 255 );
-        dostemp[255] = '\0';
+char *DOS_GetUnixFileName(const char *dosfilename)
+{ 
+    /*   a:\windows\system.ini  =>  /dos/windows/system.ini */
+    
+    /* FIXME: should handle devices here (like LPT: or NUL:) */
+    
+    static char dostemp[256], temp[256];
+    int drive = DOS_GetDefaultDrive();
+    
+    if (dosfilename[0] && dosfilename[1] == ':')
+    {
+	drive = toupper(*dosfilename) - 'A';
+	dosfilename += 2;
+    }    
+    if (!DOS_ValidDrive(drive)) return NULL;
 
-        /* Expand the filename to it's full path if it doesn't
-         * start from the root.
-         */
-        DOS_ExpandToFullPath(dostemp, drive);
-
-	strcpy(temp, DosDrives[drive].rootdir);
-	strcat(temp, DosDrives[drive].cwd);
-	GetUnixDirName(temp + strlen(DosDrives[drive].rootdir), dostemp);
-
-	dprintf_dosfs(stddeb,"GetUnixFileName: %s => %s\n", dosfilename, temp);
-	return(temp);
+    strncpy( dostemp, dosfilename, 255 );
+    dostemp[255] = 0;
+    ToUnix(dostemp);
+    strcpy(temp, DosDrives[drive].rootdir);
+    if (dostemp[0] != '/') {
+	DOS_GetCurrDir_Unix(temp+strlen(temp), drive);
+    }
+    strcat(temp, dostemp);
+    DOS_SimplifyPath(temp);
+	
+    dprintf_dosfs(stddeb,"GetUnixFileName: %s => %s\n", dosfilename, temp);
+    return temp;
 }
 
 /* Note: This function works on directories as well as long as
@@ -486,136 +378,148 @@
  */
 char *DOS_GetDosFileName(char *unixfilename)
 { 
-	int i;
-	static char temp[256], rootdir[256];
-	/*   /dos/windows/system.ini => c:\windows\system.ini */
-	
-        /* Expand it if it's a relative name.
-         */
-        DOS_ExpandToFullUnixPath(unixfilename);
-
-	for (i = 0 ; i != MAX_DOS_DRIVES; i++) {
-		if (DosDrives[i].rootdir != NULL) {
- 			strcpy(rootdir, DosDrives[i].rootdir);
- 			strcat(rootdir, "/");
- 			if (strncmp(rootdir, unixfilename, strlen(rootdir)) == 0) {
- 				sprintf(temp, "%c:\\%s", 'A' + i, unixfilename + strlen(rootdir));
-				ToDos(temp);
-				return temp;
-			}	
-		}
+    int i;
+    static char temp[256], temp2[256];
+    /*   /dos/windows/system.ini => c:\windows\system.ini */
+    
+    dprintf_dosfs(stddeb,"DOS_GetDosFileName: %s\n", unixfilename);
+    if (unixfilename[0] == '/') {
+	strncpy(temp, unixfilename, 255);
+	temp[255] = 0;
+    } else {
+	/* Expand it if it's a relative name. */
+	getcwd(temp, 255);
+	if(strncmp(unixfilename, "./", 2) != 0) {
+	    strcat(temp, unixfilename + 1);
+	} else {	    
+	    strcat(temp, "/");
+	    strcat(temp, unixfilename);
 	}
-	sprintf(temp, "Z:%s", unixfilename);
-	ToDos(temp);
-	return(temp);
+    }
+    for (i = 0 ; i < MAX_DOS_DRIVES; i++) {
+	if (DosDrives[i].rootdir != NULL) {
+	    int len = strlen(DosDrives[i].rootdir);
+	    dprintf_dosfs(stddeb, "  check %c:%s\n", i+'A', DosDrives[i].rootdir);
+	    if (strncmp(DosDrives[i].rootdir, temp, len) == 0 && temp[len] == '/')
+	    {
+		sprintf(temp2, "%c:%s", 'A' + i, temp+len);
+		ToDos(temp2+2);
+		return temp2;
+	    }	
+	}
+    }
+    sprintf(temp, "Z:%s", unixfilename);
+    ToDos(temp+2);
+    return temp;
 }
 
-char *DOS_GetCurrentDir(int drive)
-{ 
-	static char temp[256];
+int DOS_ValidDirectory(int drive, char *name)
+{
+    char temp[256];
+    struct stat s;
+    
+    strcpy(temp, DosDrives[drive].rootdir);
+    strcat(temp, name);
+    if (stat(temp, &s)) return 0;
+    if (!S_ISDIR(s.st_mode)) return 0;
+    dprintf_dosfs(stddeb, "==> OK\n");
+    return 1;
+}
 
-	if (!DOS_ValidDrive(drive)) 
-		return 0;
-	
-	strcpy(temp, DosDrives[drive].cwd);
-	DOS_SimplifyPath( temp );
-	ToDos(temp);
-	ChopOffSlash(temp);
+int DOS_GetDefaultDrive(void)
+{
+    TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
+    int drive = pTask == NULL ? CurrentDrive : pTask->curdrive & ~0x80;
+    
+    dprintf_dosfs(stddeb,"GetDefaultDrive (%c)\n",'A'+drive);
+    return drive;
+}
 
-    	dprintf_dosfs(stddeb,"DOS_GetCWD: %c:%s\n", 'A'+drive, temp);
-	return (temp + 1);
+void DOS_SetDefaultDrive(int drive)
+{
+    TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
+    
+    dprintf_dosfs(stddeb,"SetDefaultDrive to %c:\n",'A'+drive);
+    if (DOS_ValidDrive(drive) && drive != DOS_GetDefaultDrive()) {
+	if (pTask == NULL) CurrentDrive = drive;
+	else {
+	    char temp[256];
+	    pTask->curdrive = drive | 0x80;
+	    strcpy(temp, DosDrives[drive].rootdir);
+	    strcat(temp, DosDrives[drive].cwd);
+	    strcpy(temp, DOS_GetDosFileName(temp));
+	    dprintf_dosfs(stddeb, "  curdir = %s\n", temp);
+	    if (strlen(temp)-2 < sizeof(pTask->curdir)) strcpy(pTask->curdir, temp+2);
+	    else fprintf(stderr, "dosfs: curdir too long\n");
+	}
+    }
+}
+
+int DOS_DisableDrive(int drive)
+{
+    if (drive >= MAX_DOS_DRIVES) return 0;
+    if (DosDrives[drive].rootdir == NULL) return 0;
+
+    DosDrives[drive].disabled = 1;
+    return 1;
+}
+
+int DOS_EnableDrive(int drive)
+{
+    if (drive >= MAX_DOS_DRIVES) return 0;
+    if (DosDrives[drive].rootdir == NULL) return 0;
+
+    DosDrives[drive].disabled = 0;
+    return 1;
 }
 
 int DOS_ChangeDir(int drive, char *dirname)
 {
-	char temp[256],old[256];
+    TDB *pTask = (TDB *)GlobalLock(GetCurrentTask());
+    char temp[256];
+    
+    if (!DOS_ValidDrive(drive)) return 0;
 
-	if (!DOS_ValidDrive(drive)) 
-		return 0;
-
+    if (dirname[0] == '\\') {
 	strcpy(temp, dirname);
-	ToUnix(temp);
-	strcpy(old, DosDrives[drive].cwd);
-	
-	GetUnixDirName(DosDrives[drive].cwd, temp);
-	strcat(DosDrives[drive].cwd,"/");
+    } else {
+	DOS_GetCurrDir_Unix(temp, drive);
+	strcat(temp, dirname);
+    }
+    ToUnix(temp);
+    strcat(temp, "/");
+    DOS_SimplifyPath(temp);
+    dprintf_dosfs(stddeb,"DOS_SetCWD: %c: %s ==> %s\n", 'A'+drive, dirname, temp);
 
-	dprintf_dosfs(stddeb,"DOS_SetCWD: %c: %s\n",'A'+drive,
-                      DosDrives[drive].cwd);
-
-	if (!DOS_ValidDirectory(DosDrives[drive].cwd))
-	{
-		strcpy(DosDrives[drive].cwd, old);
-		return 0;
-	}
-        DOS_SimplifyPath(DosDrives[drive].cwd);
-	return 1;
+    if (!DOS_ValidDirectory(drive, temp)) return 0;
+    strcpy(DosDrives[drive].cwd, temp);
+    if (pTask != NULL && DOS_GetDefaultDrive() == drive) {
+	strcpy(temp, DosDrives[drive].rootdir);
+	strcat(temp, DosDrives[drive].cwd);
+	strcpy(temp, DOS_GetDosFileName(temp));
+	dprintf_dosfs(stddeb, "  curdir = %s\n", temp);
+	if (strlen(temp)-2 < sizeof(pTask->curdir)) strcpy(pTask->curdir, temp+2);
+	else fprintf(stderr, "dosfs: curdir too long\n");
+    }
+    return 1;
 }
 
 int DOS_MakeDir(int drive, char *dirname)
 {
-	char temp[256];
-	
-	if (!DOS_ValidDrive(drive))
-		return 0;	
+    char temp[256], currdir[256];
+    
+    if (!DOS_ValidDrive(drive)) return 0;	
 
-	strcpy(temp, DosDrives[drive].cwd);
-	GetUnixDirName(temp, dirname);
-	strcat(DosDrives[drive].cwd,"/");
-
-	ToUnix(temp + strlen(DosDrives[drive].cwd));
-	mkdir(temp,0);	
-
-    	dprintf_dosfs(stddeb,
-		"DOS_MakeDir: %c:\%s => %s",'A'+drive, dirname, temp);
-	return 1;
-}
-
-/* DOS_ExpandToFullPath takes a dos-style filename and converts it
- * into a full path based on the current working directory.
- * (e.g., "foo.bar" => "d:\\moo\\foo.bar")
- */
-void DOS_ExpandToFullPath(char *filename, int drive)
-{
-        char temp[256];
-
-        dprintf_dosfs(stddeb, "DOS_ExpandToFullPath: Original = %s\n", filename);
-
-        /* If the filename starts with '/' or '\',
-         * don't bother -- we're already at the root.
-         */
-        if(filename[0] == '/' || filename[0] == '\\')
-            return;
-
-        strcpy(temp, DosDrives[drive].cwd);
-        strcat(temp, filename);
-        strcpy(filename, temp);
-
-        dprintf_dosfs(stddeb, "                      Expanded = %s\n", temp); 
-}
-
-/* DOS_ExpandToFullUnixPath takes a unix filename and converts it
- * into a full path based on the current working directory.  Thus,
- * it's probably not a good idea to get a relative name, change the
- * working directory, and then convert it...
- */
-void DOS_ExpandToFullUnixPath(char *filename)
-{
-        char temp[256];
-
-        if(filename[0] == '/')
-            return;
-
-        getcwd(temp, 255);
-        if(!strncmp(filename, "./", 2))
-                strcat(temp, filename + 1);
-        else
-        {
-                strcat(temp, "/");
-                strcat(temp, filename);
-        }
-        dprintf_dosfs(stddeb, "DOS_ExpandToFullUnixPath: %s => %s\n", filename, temp);
-        strcpy(filename, temp);
+    strcpy(temp, DosDrives[drive].rootdir);
+    DOS_GetCurrDir_Unix(currdir, drive);
+    strcat(temp, currdir);
+    strcat(temp, dirname);
+    ToUnix(temp);
+    DOS_SimplifyPath(temp);
+    mkdir(temp,0);	
+    
+    dprintf_dosfs(stddeb, "DOS_MakeDir: %c:\%s => %s",'A'+drive, dirname, temp);
+    return 1;
 }
 
 int DOS_GetSerialNumber(int drive, unsigned long *serialnumber)
@@ -641,7 +545,7 @@
 	if (!DOS_ValidDrive(drive)) 
 		return NULL;
 
-	return (DosDrives[drive].label);
+	return DosDrives[drive].label;
 }
 
 int DOS_SetVolumeLabel(int drive, char *label)
@@ -743,6 +647,7 @@
 		if (S_ISREG(filestat.st_mode)) {
 		    closedir(d);
 		    free(rootname);
+		    DOS_SimplifyPath(buffer);
 		    return buffer;
 		} 
 	    }
@@ -769,15 +674,15 @@
 	if ((fd = open(name, O_RDONLY)) != -1) {
 		close(fd);
 		filename = name;
-		return(filename);
+		return filename;
 	}
 	if ((fd = open(WINE_INI_GLOBAL, O_RDONLY)) != -1) {
 		close(fd);
 		filename = WINE_INI_GLOBAL;
-		return(filename);
+		return filename;
 	}
-	fprintf(stderr,"wine: can't open configuration file %s or %s !\n", 
-				WINE_INI_GLOBAL, WINE_INI_USER);
+	fprintf(stderr,"wine: can't open configuration file %s or %s !\n",
+		WINE_INI_GLOBAL, WINE_INI_USER);
 	exit(1);
 }
 
@@ -866,59 +771,48 @@
 
 struct dosdirent *DOS_opendir(char *dosdirname)
 {
-	int x,y;
-	char *unixdirname;
-	char temp[256];
-	DIR  *ds;
-	
-	if ((unixdirname = DOS_GetUnixFileName(dosdirname)) == NULL)
-		return NULL;
+    int x, len;
+    char *unixdirname;
+    char dirname[256];
+    DIR  *ds;
+    
+    if ((unixdirname = DOS_GetUnixFileName(dosdirname)) == NULL) return NULL;
+    
+    len = strrchr(unixdirname, '/') - unixdirname + 1;
+    strncpy(dirname, unixdirname, len);
+    dirname[len] = 0;
+    unixdirname = strrchr(unixdirname, '/') + 1;
 
-	strcpy(temp, unixdirname);
-	y = strlen(temp);
-	while (y--)
-	{
-		if (temp[y] == '/') 
-		{
-			temp[y++] = '\0';
-		        unixdirname += y;
-			break;
-		}
-	}
-
-        for (x=0; x <= max_open_dirs; x++) {
-	  if (x == max_open_dirs) {
+    for (x=0; x <= max_open_dirs; x++) {
+	if (x == max_open_dirs) {
 	    if (DosDirs) {
-	      DosDirs=(struct dosdirent*)realloc(DosDirs,(++max_open_dirs)*sizeof(DosDirs[0]));
+		DosDirs=(struct dosdirent*)realloc(DosDirs,(++max_open_dirs)*sizeof(DosDirs[0]));
 	    } else {
-	      DosDirs=(struct dosdirent*)malloc(sizeof(DosDirs[0]));
-	      max_open_dirs=1;
+		DosDirs=(struct dosdirent*)malloc(sizeof(DosDirs[0]));
+		max_open_dirs=1;
 	    }
 	    break; /* this one is definitely not in use */
-	  }
-	  if (!DosDirs[x].inuse) break;
-	  if (strcmp(DosDirs[x].unixpath,temp) == 0) break;
 	}
-        
-        strncpy(DosDirs[x].filemask, unixdirname, 12);
-        DosDirs[x].filemask[12] = 0;
-        ToDos(DosDirs[x].filemask);
-    	dprintf_dosfs(stddeb,"DOS_opendir: %s / %s\n", unixdirname, temp);
+	if (!DosDirs[x].inuse) break;
+	if (strcmp(DosDirs[x].unixpath, dirname) == 0) break;
+    }
+    
+    strncpy(DosDirs[x].filemask, unixdirname, 12);
+    DosDirs[x].filemask[12] = 0;
+    dprintf_dosfs(stddeb,"DOS_opendir: %s / %s\n", unixdirname, dirname);
 
-	DosDirs[x].inuse = 1;
-	strcpy(DosDirs[x].unixpath, temp);
-        DosDirs[x].entnum = 0;
+    DosDirs[x].inuse = 1;
+    strcpy(DosDirs[x].unixpath, dirname);
+    DosDirs[x].entnum = 0;
 
-	if ((ds = opendir(temp)) == NULL)
-		return NULL;
-	if (-1==(DosDirs[x].telldirnum=telldir(ds))) {
-		closedir(ds);
-		return NULL;
-	}
-	if (-1==closedir(ds))
-		return NULL;
+    if ((ds = opendir(dirname)) == NULL) return NULL;
+    if (-1==(DosDirs[x].telldirnum=telldir(ds))) {
+	closedir(ds);
+	return NULL;
+    }
+    if (-1==closedir(ds)) return NULL;
 
-	return &DosDirs[x];
+    return &DosDirs[x];
 }
 
 
@@ -931,22 +825,36 @@
 
 	if (!de->inuse)
 		return NULL;
-	if (-1==(ds=opendir(de->unixpath)))
-		return NULL;
+	if (!(ds=opendir(de->unixpath))) return NULL;
 	seekdir(ds,de->telldirnum); /* returns no error value. strange */
-	do {
-		if ((d = readdir(ds)) == NULL)  {
-			de->telldirnum=telldir(ds);
-			closedir(ds);
-			return NULL;
+   
+        if (de->search_attribute & FA_LABEL)  {	
+	    int drive;
+	    de->search_attribute &= ~FA_LABEL; /* don't find it again */
+	    for(drive = 0; drive < MAX_DOS_DRIVES; drive++) {
+		if (DosDrives[drive].rootdir != NULL &&
+		    strcmp(DosDrives[drive].rootdir, de->unixpath) == 0)
+		{
+		    strcpy(de->filename, DOS_GetVolumeLabel(drive));
+		    de->attribute = FA_LABEL;
+		    return de;
 		}
+	    }
+	}
+    
+	do {
+	    if ((d = readdir(ds)) == NULL)  {
+		de->telldirnum=telldir(ds);
+		closedir(ds);
+		return NULL;
+	    }
 
-                de->entnum++;   /* Increment the directory entry number */
-		strcpy(de->filename, d->d_name);
-		if (d->d_reclen > 12)
-			de->filename[12] = '\0';
-		
-		ToDos(de->filename);
+	    de->entnum++;   /* Increment the directory entry number */
+	    strcpy(de->filename, d->d_name);
+	    if (d->d_reclen > 12)
+	    de->filename[12] = '\0';
+
+	    ToDos(de->filename);
 	} while ( !match(de->filename, de->filemask) );
 
 	strcpy(temp,de->unixpath);
diff --git a/misc/exec.c b/misc/exec.c
index 635f4bd..ab5bc0e 100644
--- a/misc/exec.c
+++ b/misc/exec.c
@@ -8,7 +8,6 @@
 #include <string.h>
 #include <unistd.h>
 #include "neexe.h"
-#include "prototypes.h"
 #include "dlls.h"
 #include "windows.h"
 #include "callback.h"
diff --git a/misc/file.c b/misc/file.c
index ef45ec5..3581ce3 100644
--- a/misc/file.c
+++ b/misc/file.c
@@ -108,8 +108,8 @@
 {
     dprintf_file(stddeb, "_lclose: handle %d\n", hFile);
     
-    if (hFile == 1 || hFile == 2) {
-	fprintf( stderr, "Program attempted to close stdout or stderr!\n" );
+    if (hFile == 0 || hFile == 1 || hFile == 2) {
+	fprintf( stderr, "Program attempted to close stdin, stdout or stderr!\n" );
 	return 0;
     }
     if (close (hFile))
@@ -154,7 +154,7 @@
             ofs->nErrCode = ExtendedError;
             return -1;
         }
-        handle = open (unixfilename, (wStyle & 0x0003) | O_CREAT, 0x666);
+        handle = open (unixfilename, (wStyle & 0x0003) | O_CREAT, 0666);
         if (handle == -1)
         {
             errno_to_doserr();
@@ -325,7 +325,7 @@
 		lpszFilename, fnAttribute);
 	if ((UnixFileName = DOS_GetUnixFileName(lpszFilename)) == NULL)
   		return HFILE_ERROR;
-	handle =  open (UnixFileName, O_CREAT | O_TRUNC | O_WRONLY, 426);
+	handle =  open (UnixFileName, O_CREAT | O_TRUNC | O_WRONLY, 0666);
 
 	if (handle == -1)
 		return HFILE_ERROR;
@@ -372,8 +372,7 @@
 	
     	dprintf_file(stddeb,"GetWindowsDirectory (%s)\n",lpszSysPath);
 
-	ChopOffSlash(lpszSysPath);
-	return(strlen(lpszSysPath));
+	return strlen(lpszSysPath);
 }
 /***************************************************************************
  GetSystemDirectory
@@ -387,8 +386,7 @@
 
     	dprintf_file(stddeb,"GetSystemDirectory (%s)\n",lpszSysPath);
 
-	ChopOffSlash(lpszSysPath);
-	return(strlen(lpszSysPath));
+	return strlen(lpszSysPath);
 }
 /***************************************************************************
  GetTempFileName
diff --git a/misc/kernel32.c b/misc/kernel32.c
index 0be2b09..df6a5ba 100644
--- a/misc/kernel32.c
+++ b/misc/kernel32.c
@@ -9,6 +9,7 @@
 
 #include "windows.h"
 #include "winerror.h"
+#include <unistd.h>
 
 int WIN32_LastError;
 
diff --git a/misc/main.c b/misc/main.c
index f5f8544..3528df5 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -2,9 +2,8 @@
  * Main function.
  *
  * Copyright 1994 Alexandre Julliard
- *
-static char Copyright[] = "Copyright  Alexandre Julliard, 1994";
-*/
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -24,7 +23,6 @@
 #include "winsock.h"
 #include "options.h"
 #include "desktop.h"
-#include "prototypes.h"
 #include "dlls.h"
 #define DEBUG_DEFINE_VARIABLES
 #include "stddebug.h"
@@ -63,7 +61,6 @@
 
 struct options Options =
 {  /* default options */
-    NULL,           /* spyFilename */
     NULL,           /* desktopGeometry */
     NULL,           /* programName */
     FALSE,          /* usePrivateMap */
@@ -86,7 +83,6 @@
     { "-name",          ".name",            XrmoptionSepArg, (caddr_t)NULL },
     { "-privatemap",    ".privatemap",      XrmoptionNoArg,  (caddr_t)"on" },
     { "-synchronous",   ".synchronous",     XrmoptionNoArg,  (caddr_t)"on" },
-    { "-spy",           ".spy",             XrmoptionSepArg, (caddr_t)NULL },
     { "-debug",         ".debug",           XrmoptionNoArg,  (caddr_t)"on" },
     { "-debugmsg",      ".debugmsg",        XrmoptionSepArg, (caddr_t)NULL },
     { "-dll",           ".dll",             XrmoptionSepArg, (caddr_t)NULL },
@@ -109,11 +105,11 @@
   "    -privatemap     Use a private color map\n" \
   "    -synchronous    Turn on synchronous display mode\n" \
   "    -backingstore   Turn on backing store\n" \
-  "    -spy file       Turn on message spying to the specified file\n" \
+  "    -spy file       Obsolete. Use -debugmsg +spy for Spy messages\n" \
   "    -debugmsg name  Turn debugging-messages on or off\n" \
   "    -dll name       Enable or disable built-in DLLs\n" \
   "    -allowreadonly  Read only files may be opened in write mode\n" \
-  "    -enhanced       Start wine in enhanced mode\n"
+  "    -enhanced       Start wine in enhanced mode (like 'win /3') \n"
 
 
 
@@ -313,8 +309,6 @@
         Options.allowReadOnly = TRUE;
     if (MAIN_GetResource( db, ".enhanced", &value ))
         Options.enhanced = TRUE;
-    if (MAIN_GetResource( db, ".spy", &value))
-	Options.spyFilename = value.addr;
     if (MAIN_GetResource( db, ".depth", &value))
 	screenDepth = atoi( value.addr );
     if (MAIN_GetResource( db, ".desktop", &value))
@@ -463,14 +457,20 @@
     	KBBellPitch | KBBellDuration | KBAutoRepeatMode, &keyboard_value);
 }
 
+
+#ifdef MALLOC_DEBUGGING
 static void malloc_error()
 {
        fprintf(stderr,"malloc is not feeling well. Good bye\n");
        exit(1);
 }
+#endif  /* MALLOC_DEBUGGING */
+
 
 static void called_at_exit(void)
 {
+    extern void sync_profiles(void);
+
     sync_profiles();
     MAIN_RestoreSetup();
     WSACleanup();
@@ -485,8 +485,10 @@
     int depth_count, i;
     int *depth_list;
 
-	setbuf(stdout,NULL);
-	setbuf(stderr,NULL);
+    extern int _WinMain(int argc, char **argv);
+
+    setbuf(stdout,NULL);
+    setbuf(stderr,NULL);
 
     setlocale(LC_CTYPE,"");
 
@@ -565,9 +567,9 @@
 LONG GetWinFlags(void)
 {
   if (Options.enhanced)
-    return (WF_STANDARD | WF_ENHANCED | WF_CPU386 | WF_PMODE | WF_80x87);
+    return (WF_ENHANCED | WF_CPU386 | WF_PMODE | WF_80x87 | WF_PAGING);
   else
-    return (WF_STANDARD | WF_CPU286 | WF_PMODE | WF_80x87);
+    return (WF_STANDARD | WF_CPU386 | WF_PMODE | WF_80x87);
 }
 
 /***********************************************************************
diff --git a/misc/profile.c b/misc/profile.c
index 71e5373..0c3df91 100644
--- a/misc/profile.c
+++ b/misc/profile.c
@@ -96,7 +96,8 @@
     int state;
     TSecHeader *SecHeader = 0;
     char CharBuffer [STRSIZE];
-    char *next, *file;
+    char *next = '\0';
+    char *file;
     char c;
     char path[MAX_PATH+1];
 
@@ -287,6 +288,7 @@
 	    return (Size - 2 - left);
 	}
 	for (key = section->Keys; key; key = key->link){
+	    int slen;
 	    if (strcasecmp (key->KeyName, KeyName))
 		continue;
 	    if (set){
@@ -295,19 +297,21 @@
 		Current->changed=TRUE;
 		return 1;
 	    }
-	    ReturnedString [Size-1] = 0;
-	    strncpy (ReturnedString, key->Value, Size-1);
+	    slen = min(strlen(key->Value), Size - 1);
+	    ReturnedString[slen] = 0;
+	    strncpy (ReturnedString, key->Value, slen);
 	    dprintf_profile(stddeb,"GetSetProfile // Return ``%s''\n", ReturnedString);
 	    return 1; 
 	}
 	/* If Getting the information, then don't write the information
 	   to the INI file, need to run a couple of tests with windog */
 	/* No key found */
-	if (set)
+	if (set) {
 	    new_key (section, KeyName, Default);
-        else {
-            ReturnedString [Size-1] = 0;
-            strncpy (ReturnedString, Default, Size-1);
+        } else {
+	    int slen = min(strlen(Default), Size - 1);
+            ReturnedString[slen] = 0;
+            strncpy(ReturnedString, Default, slen);
 	    dprintf_profile(stddeb,"GetSetProfile // Key not found\n");
 	}
 	return 1;
@@ -322,8 +326,9 @@
 	Current->Section = section;
 	Current->changed = TRUE;
     } else {
-	ReturnedString [Size-1] = 0;
-	strncpy (ReturnedString, Default, Size-1);
+	int slen = min(strlen(Default), Size - 1);
+	ReturnedString[slen] = 0;
+	strncpy(ReturnedString, Default, slen);
 	dprintf_profile(stddeb,"GetSetProfile // Section not found\n");
     }
     return 1;
diff --git a/misc/spy.c b/misc/spy.c
index 7c82b10..835f8c6 100644
--- a/misc/spy.c
+++ b/misc/spy.c
@@ -8,14 +8,13 @@
 #include <X11/Xlib.h>
 #include <X11/Xresource.h>
 #include <string.h>
-#include "wineopts.h"
 #include "windows.h"
 #include "wine.h"
 #include "options.h"
+#include "stddebug.h"
+#include "debug.h"
 
-#ifndef NOSPY
-
-#define SPY_MAX_MSGNUM		0x0232
+#define SPY_MAX_MSGNUM		0x03e8
 
 const char *MessageTypeNames[SPY_MAX_MSGNUM + 1] =
 {
@@ -245,27 +244,115 @@
     "WM_MDIICONARRANGE",        /* 0x0228 */
     "WM_MDIGETACTIVE",          /* 0x0229 */
 
+    NULL, NULL, NULL, NULL, NULL, NULL,
+    /* 0x0230*/
     "WM_MDISETMENU",            /* 0x0230 */
     "WM_ENTERSIZEMOVE",		/* 0x0231 */
-    "WM_EXITSIZEMOVE"		/* 0x0232 */
+    "WM_EXITSIZEMOVE",		/* 0x0232 */
+    NULL, NULL, NULL, NULL, NULL, 
+    /* 0x0238*/
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    
+    /* 0x0240 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x0250 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    
+    /* 0x0260 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x0280 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x02c0 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x0300 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x0340 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x0380 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x03c0 */
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+    /* 0x03e0 */
+    "WM_DDE_INITIATE",  /* 0x3E0 */
+    "WM_DDE_TERMINATE",	/* 0x3E1 */
+    "WM_DDE_ADVISE",	/* 0x3E2 */
+    "WM_DDE_UNADVISE",	/* 0x3E3 */
+    "WM_DDE_ACK",	/* 0x3E4 */
+    "WM_DDE_DATA",	/* 0x3E5 */
+    "WM_DDE_REQUEST",	/* 0x3E6 */
+    "WM_DDE_POKE",	/* 0x3E7 */
+    "WM_DDE_EXECUTE"	/* 0x3E8 */
 };
 
 char SpyFilters[256+1];
 char SpyIncludes[256+1];
 
-#endif /* NOSPY */
-
 /**********************************************************************
  *					SpyMessage
  */
 void SpyMessage(HWND hwnd, WORD msg, WORD wParam, LONG lParam)
 {
-#ifndef NOSPY
     char msg_name[80];
     
-    if (SpyFp == NULL)
-	return;
-    
+	if(!debugging_spy)
+		return;
+
     if (msg > SPY_MAX_MSGNUM || MessageTypeNames[msg] == NULL)
 	sprintf(msg_name, "%04x", msg);
     else
@@ -277,10 +364,9 @@
 	strstr(SpyFilters, msg_name) == NULL)
     {
 	msg_name[strlen(msg_name) - 1] = '\0';
-	fprintf(SpyFp, "%04x  %20.20s  %04x  %04x  %08lx\n",
+	dprintf_spy(stddeb, "%04x  %20.20s  %04x  %04x  %08lx\n",
 		hwnd, msg_name, msg, wParam, lParam);
     }
-#endif
 }
 
 /**********************************************************************
@@ -288,30 +374,6 @@
  */
 void SpyInit(void)
 {
-#ifndef NOSPY
-    char filename[100];
-
-    if (SpyFp != NULL)
-	return;
-
-    if (Options.spyFilename == NULL)
-    {
-	GetPrivateProfileString("spy", "file", "", filename, sizeof(filename),
-				WINE_INI);
-    }
-    else
-	strncpy(filename, Options.spyFilename, 100);
-
-    if (strcasecmp(filename, "CON") == 0)
-	SpyFp = stdout;
-    else if (strlen(filename))
-	SpyFp = fopen(filename, "a");
-    else
-    {
-	SpyFp = NULL;
-	return;
-    }
-    
     GetPrivateProfileString("spy", "exclude", "", SpyFilters, 
 			    sizeof(SpyFilters)-1, WINE_INI);
     GetPrivateProfileString("spy", "include", "", SpyIncludes, 
@@ -323,5 +385,4 @@
     if (*SpyFilters != 0) {
       strcat(SpyFilters, ";");
     }
-#endif
 }
diff --git a/misc/user.c b/misc/user.c
index 86a09f5..98b7b1b 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -17,7 +17,6 @@
 #include "syscolor.h"
 #include "win.h"
 #include "windows.h"
-#include "prototypes.h"
 #include "user.h"
 #include "message.h"
 #include "toolhelp.h"
diff --git a/misc/winsocket.c b/misc/winsocket.c
index ee95375..2fdd5a6 100644
--- a/misc/winsocket.c
+++ b/misc/winsocket.c
@@ -20,6 +20,7 @@
 #include <netdb.h>
 #include <unistd.h>
 #include "winsock.h"
+#include "toolhelp.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -37,33 +38,36 @@
 	LONG	lParam;
 };
 
+#ifndef WINELIB
 #pragma pack(1)
+#endif
 
 #define IPC_PACKET_SIZE (sizeof(struct ipc_packet) - sizeof(long))
 #define MTYPE 0xb0b0eb05
-#define WINE_PACKED __attribute__ ((packed))
+
+/* These structures are Win16 only */
 
 struct WIN_hostent  {
-	char	*h_name WINE_PACKED;		/* official name of host */
-	char	**h_aliases WINE_PACKED;	/* alias list */
-	int	h_addrtype WINE_PACKED;		/* host address type */
-	int	h_length WINE_PACKED;		/* length of address */
+	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 {
-	char	*p_name WINE_PACKED;		/* official protocol name */
-	char	**p_aliases WINE_PACKED;	/* alias list */
-	int	p_proto WINE_PACKED;		/* protocol # */
+	SEGPTR	p_name WINE_PACKED;		/* official protocol name */
+	SEGPTR	p_aliases WINE_PACKED;	/* alias list */
+	INT	p_proto WINE_PACKED;		/* protocol # */
 };
 
 struct	WIN_servent {
-	char	*s_name WINE_PACKED;		/* official service name */
-	char	**s_aliases WINE_PACKED;	/* alias list */
-	int	s_port WINE_PACKED;		/* port # */
-	char	*s_proto WINE_PACKED;		/* protocol to use */
+	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 */
 };
 
 struct WinSockHeap {
@@ -82,10 +86,23 @@
 	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 struct WinSockHeap *Heap;
+static int HeapHandle;
+static int ScratchPtr;
 
+#ifndef WINELIB
+#define GET_SEG_PTR(x)	MAKELONG((int)((char*)(x)-(char*)Heap),	\
+							GlobalHandleToSel(HeapHandle))
+#else
+#define GET_SEG_PTR(x)	(x)
+#endif
+
+#ifndef WINELIB
 #pragma pack(4)
+#endif
 
 #define dump_sockaddr(a) \
 	fprintf(stderr, "sockaddr_in: family %d, address %s, port %d\n", \
@@ -93,6 +110,28 @@
 			inet_ntoa(((struct sockaddr_in *)a)->sin_addr), \
 			ntohs(((struct sockaddr_in *)a)->sin_port))
 
+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);
+}
+
 static WORD wsaerrno(void)
 {
 #ifdef DEBUG_WINSOCK
@@ -208,19 +247,70 @@
 }
 
 #ifndef WINELIB
-static void CONVERT_HOSTENT(struct WIN_hostent *heap, struct hostent *host)
+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 = 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 *heap, struct protoent *proto)
+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 *heap, struct servent *serv)
+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))
@@ -339,16 +429,45 @@
         	return NULL;
 	}
 
-	strncpy(heap->ntoa_buffer, s, sizeof(heap->ntoa_buffer) );
+	strncpy(Heap->ntoa_buffer, s, sizeof(Heap->ntoa_buffer) );
 
-	return (char *) &heap->ntoa_buffer;
+	return (char *) GET_SEG_PTR(&Heap->ntoa_buffer);
 }
 
-INT WINSOCK_ioctlsocket(SOCKET s, long cmd, u_long *argp)
+INT WINSOCK_ioctlsocket(SOCKET s, u_long cmd, u_long *argp)
 {
-	dprintf_winsock(stddeb, "WSA_ioctl: socket %d, cmd %ld, ptr %8x\n", s, cmd, (int) 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 (ioctl(s, cmd, argp) < 0) {
+	/* 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) {
         	errno_to_wsaerrno();
         	return SOCKET_ERROR;
 	}
@@ -485,7 +604,10 @@
     return sock;
 }
 
-struct WIN_hostent *WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
+/*
+struct WIN_hostent *
+*/
+SEGPTR WINSOCK_gethostbyaddr(const char *addr, INT len, INT type)
 {
 	struct hostent *host;
 
@@ -495,12 +617,15 @@
         	errno_to_wsaerrno();
         	return NULL;
 	}
-	CONVERT_HOSTENT(&heap->hostent_addr, host);
+	CONVERT_HOSTENT(&Heap->hostent_addr, host);
 
-	return &heap->hostent_addr;
+	return GET_SEG_PTR(&Heap->hostent_addr);
 }
 
-struct WIN_hostent *WINSOCK_gethostbyname(const char *name)
+/*
+struct WIN_hostent *
+*/
+SEGPTR WINSOCK_gethostbyname(const char *name)
 {
 	struct hostent *host;
 
@@ -510,9 +635,9 @@
         	errno_to_wsaerrno();
         	return NULL;
 	}
-	CONVERT_HOSTENT(&heap->hostent_name, host);
+	CONVERT_HOSTENT(&Heap->hostent_name, host);
 
-	return &heap->hostent_name;
+	return GET_SEG_PTR(&Heap->hostent_name);
 }
 
 INT WINSOCK_gethostname(char *name, INT namelen)
@@ -526,7 +651,10 @@
 	return 0;
 }          
 
-struct WIN_protoent *WINSOCK_getprotobyname(char *name)
+/*
+struct WIN_protoent *
+*/
+SEGPTR WINSOCK_getprotobyname(char *name)
 {
 	struct protoent *proto;
 
@@ -536,12 +664,15 @@
         	errno_to_wsaerrno();
         	return NULL;
 	}
-	CONVERT_PROTOENT(&heap->protoent_name, proto);
+	CONVERT_PROTOENT(&Heap->protoent_name, proto);
 
-	return &heap->protoent_name;
+	return GET_SEG_PTR(&Heap->protoent_name);
 }
 
-struct WIN_protoent *WINSOCK_getprotobynumber(INT number)
+/*
+struct WIN_protoent *
+*/
+SEGPTR WINSOCK_getprotobynumber(INT number)
 {
 	struct protoent *proto;
 
@@ -551,12 +682,15 @@
         	errno_to_wsaerrno();
         	return NULL;
 	}
-	CONVERT_PROTOENT(&heap->protoent_number, proto);
+	CONVERT_PROTOENT(&Heap->protoent_number, proto);
 
-	return &heap->protoent_number;
+	return GET_SEG_PTR(&Heap->protoent_number);
 }
 
-struct WIN_servent *WINSOCK_getservbyname(const char *name, const char *proto)
+/*
+struct WIN_servent *
+*/
+SEGPTR WINSOCK_getservbyname(const char *name, const char *proto)
 {
 	struct servent *service;
 
@@ -569,12 +703,15 @@
         	errno_to_wsaerrno();
         	return NULL;
 	}
-	CONVERT_SERVENT(&heap->servent_name, service);
+	CONVERT_SERVENT(&Heap->servent_name, service);
 
-	return &heap->servent_name;
+	return GET_SEG_PTR(&Heap->servent_name);
 }
 
-struct WIN_servent *WINSOCK_getservbyport(INT port, const char *proto)
+/*
+struct WIN_servent *
+*/
+SEGPTR WINSOCK_getservbyport(INT port, const char *proto)
 {
 	struct servent *service;
 
@@ -584,9 +721,9 @@
         	errno_to_wsaerrno();
         	return NULL;
 	}
-	CONVERT_SERVENT(&heap->servent_port, service);
+	CONVERT_SERVENT(&Heap->servent_port, service);
 
-	return &heap->servent_port;
+	return GET_SEG_PTR(&Heap->servent_port);
 }
 
 /******************** winsock specific functions ************************
@@ -831,7 +968,7 @@
           
 INT WSAGetLastError(void)
 {
-	dprintf_winsock(stddeb, "WSA_GetLastError\n");
+	dprintf_winsock(stddeb, "WSA_GetLastError = %x\n", wsa_errno);
 
     return wsa_errno;
 }
@@ -886,7 +1023,6 @@
 
 INT WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData)
 {
-    int HeapHandle;
 
     dprintf_winsock(stddeb, "WSAStartup: verReq=%x\n", wVersionRequested);
 
@@ -903,7 +1039,7 @@
     if ((HeapHandle = GlobalAlloc(GMEM_FIXED,sizeof(struct WinSockHeap))) == 0)
 	return WSASYSNOTREADY;
 
-    heap = (struct WinSockHeap *) GlobalLock(HeapHandle);
+    Heap = (struct WinSockHeap *) GlobalLock(HeapHandle);
     bcopy(&WINSOCK_data, lpWSAData, sizeof(WINSOCK_data));
 
     /* ipc stuff */
diff --git a/miscemu/Imakefile b/miscemu/Imakefile
index a73da1c..74a89df 100644
--- a/miscemu/Imakefile
+++ b/miscemu/Imakefile
@@ -8,8 +8,6 @@
 	instr.c \
 	int10.c \
 	int13.c \
-	int15.c \
-	int16.c \
 	int1a.c \
 	int21.c \
 	int25.c \
diff --git a/miscemu/Makefile.in b/miscemu/Makefile.in
new file mode 100644
index 0000000..8cf8cce
--- /dev/null
+++ b/miscemu/Makefile.in
@@ -0,0 +1,51 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include
+LD	= @LD@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+
+
+MODULE 	= miscemu
+
+SRCS 	= dpmi.c emulate.c instr.c int10.c int13.c \
+        int1a.c int21.c int25.c int26.c int2a.c int2f.c int5c.c interrupts.c \
+        ioports.c
+
+OBJS = $(SRCS:.c=.o)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
+
+all: $(MODULE).o
+
+$(MODULE).o: $(OBJS)
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dummy:
+
+### Dependencies:
diff --git a/miscemu/dpmi.c b/miscemu/dpmi.c
index c44a6af..2b63159 100644
--- a/miscemu/dpmi.c
+++ b/miscemu/dpmi.c
@@ -18,19 +18,16 @@
 
 
 /**********************************************************************
- *	    do_int31
+ *	    INT_Int31Handler
  *
- * Handle the DPMI interrupt (int 31h).
+ * Handler for int 31h (DPMI).
  */
-int do_int31( struct sigcontext_struct *context )
+void INT_Int31Handler( struct sigcontext_struct sigcontext )
 {
+#define context (&sigcontext)
     DWORD dw;
     BYTE *ptr;
 
-    dprintf_int( stddeb, "int31 (DPMI): AX %04x, BX %04x, CX %04x, DX %04x, "
-                 "SI %04x, DI %04x, DS %04x, ES %04x\n",
-                 AX, BX, CX, DX, SI, DI, DS, ES );
-
     ResetCflag;
     switch(AX)
     {
@@ -116,16 +113,27 @@
         SetCflag;
         break;
 
+    case 0x0204:  /* Get protected mode interrupt vector */
+	dw = (DWORD)INT_GetHandler( BL );
+	CX = HIWORD(dw);
+	DX = LOWORD(dw);
+	break;
+
+    case 0x0205:  /* Set protected mode interrupt vector */
+	INT_SetHandler( BL, (SEGPTR)MAKELONG( DX, CX ) );
+	break;
+
     case 0x0400:  /* Get DPMI version */
-        AX = 0x0009;  /* DPMI version 0.9 */
+        AX = 0x005a;  /* DPMI version 0.90 */
         BX = 0x0005;  /* Flags: 32-bit, virtual memory */
-        CL = 4;       /* CPU type: 486 */
+        CL = 3;       /* CPU type: 386 */
         DX = 0x0102;  /* Master and slave interrupt controller base */
         break;
 
     case 0x0500:  /* Get free memory information */
-        memset( PTR_SEG_OFF_TO_LIN( ES, DI ),
-                0xff, 0x30 );  /* No information supported */
+        ptr = (BYTE *)PTR_SEG_OFF_TO_LIN( ES, DI );
+        *(DWORD *)ptr = 0x00ff0000; /* Largest block available */
+        memset( ptr + 4, 0xff, 0x2c );  /* No other information supported */
         break;
 
     case 0x0501:  /* Allocate memory block */
@@ -165,9 +173,10 @@
         break;  /* Just ignore it */
 
     default:
+        INT_BARF( 0x31 );
         AX = 0x8001;  /* unsupported function */
         SetCflag;
         break;
     }
-    return 1;
+#undef context
 }
diff --git a/miscemu/instr.c b/miscemu/instr.c
index b025452..3be1990 100644
--- a/miscemu/instr.c
+++ b/miscemu/instr.c
@@ -6,55 +6,11 @@
 
 #include <stdio.h>
 #include "windows.h"
-#include "dos_fs.h"
 #include "ldt.h"
 #include "miscemu.h"
 #include "registers.h"
 
 
-static int do_int(int intnum, struct sigcontext_struct *context)
-{
-	switch(intnum)
-	{
-	      case 0x10: return do_int10(context);
-
-	      case 0x11:  
-		AX = DOS_GetEquipment();
-		return 1;
-
-	      case 0x12:               
-		AX = 640;
-		return 1;	/* get base mem size */                
-
-              case 0x13: return do_int13(context);
-	      case 0x15: return do_int15(context);
-	      case 0x16: return do_int16(context);
-	      case 0x1a: return do_int1a(context);
-	      case 0x21: return do_int21(context);
-
-	      case 0x22:
-		AX = 0x1234;
-		BX = 0x5678;
-		CX = 0x9abc;
-		DX = 0xdef0;
-		return 1;
-
-              case 0x25: return do_int25(context);
-              case 0x26: return do_int26(context);
-              case 0x2a: return do_int2a(context);
-	      case 0x2f: return do_int2f(context);
-	      case 0x31: return do_int31(context);
-              case 0x3d: return 1;
-	      case 0x5c: return do_int5c(context);
-
-              default:
-                fprintf(stderr,"int%02x: Unimplemented!\n", intnum);
-                break;
-	}
-	return 0;
-}
-
-
 /***********************************************************************
  *           INSTR_EmulateInstruction
  *
@@ -62,35 +18,38 @@
  */
 BOOL INSTR_EmulateInstruction( struct sigcontext_struct *context )
 {
-    int prefix, segprefix, long_op, long_addr;
-    BYTE *instr = (BYTE *) PTR_SEG_OFF_TO_LIN( CS, IP );
+    int prefix, segprefix, repX, long_op, long_addr;
+    BYTE *instr;
+
+    long_op = long_addr = (GET_SEL_FLAGS(CS) & LDT_FLAGS_32BIT) != 0;
+    instr = (BYTE *) PTR_SEG_OFF_TO_LIN( CS, long_op ? EIP : IP );
 
     /* First handle any possible prefix */
 
-    long_op = long_addr = (GET_SEL_FLAGS(CS) & LDT_FLAGS_32BIT) != 0;
-    segprefix = 0;  /* no prefix */
+    segprefix = -1;  /* no prefix */
     prefix = 1;
+    repX = 0;
     while(prefix)
     {
         switch(*instr)
         {
         case 0x2e:
-            segprefix = 1;  /* CS */
+            segprefix = CS;
             break;
         case 0x36:
-            segprefix = 2;  /* SS */
+            segprefix = SS;
             break;
         case 0x3e:
-            segprefix = 3;  /* DS */
+            segprefix = DS;
             break;
         case 0x26:
-            segprefix = 4;  /* ES */
+            segprefix = ES;
             break;
         case 0x64:
-            segprefix = 5;  /* FS */
+            segprefix = FS;
             break;
         case 0x65:
-            segprefix = 6;  /* GS */
+            segprefix = GS;
             break;
         case 0x66:
             long_op = !long_op;  /* opcode size prefix */
@@ -99,8 +58,12 @@
             long_addr = !long_addr;  /* addr size prefix */
             break;
         case 0xf0:  /* lock */
+	    break;
         case 0xf2:  /* repne */
+	    repX = 1;
+	    break;
         case 0xf3:  /* repe */
+	    repX = 2;
             break;
         default:
             prefix = 0;  /* no more prefixes */
@@ -117,22 +80,33 @@
 
     switch(*instr)
     {
-      case 0xcd: /* int <XX> */
-            instr++;
-            /* FIXME: should check if handler has been changed */
-	    if (!do_int(*instr, context))
+        case 0xcd: /* int <XX> */
+            if (long_op)
             {
-		fprintf(stderr,"Unexpected Windows interrupt %x\n", *instr);
-                return FALSE;
-	    }
-	    EIP += 2;  /* Bypass the int instruction */
+                fprintf(stderr, "int xx from 32-bit code is not supported.\n");
+                return FALSE;  /* Unable to emulate it */
+            }
+            else
+            {
+                SEGPTR addr = INT_GetHandler( instr[1] );
+                /* FIXME: should check the stack 'big' bit */
+                WORD *stack = (WORD *)PTR_SEG_OFF_TO_LIN( SS, SP );
+                /* Push the flags and return address on the stack */
+                *(--stack) = FL;
+                *(--stack) = CS;
+                *(--stack) = IP + 2;
+                SP -= 3 * sizeof(WORD);
+                /* Jump to the interrupt handler */
+                CS  = HIWORD(addr);
+                EIP = LOWORD(addr);
+            }
             break;
 
-      case 0xcf: /* iret */
+        case 0xcf: /* iret */
             if (long_op)
             {
                 /* FIXME: should check the stack 'big' bit */
-                DWORD *stack = (WORD *)PTR_SEG_OFF_TO_LIN( SS, SP );
+                DWORD *stack = (DWORD *)PTR_SEG_OFF_TO_LIN( SS, SP );
                 EIP = *stack++;
                 CS  = *stack++;
                 EFL = *stack;
@@ -144,59 +118,135 @@
                 WORD *stack = (WORD *)PTR_SEG_OFF_TO_LIN( SS, SP );
                 EIP = *stack++;
                 CS  = *stack++;
-                EFL = (EFL & 0xffff0000) | *stack;
+                FL  = *stack;
                 SP += 3*sizeof(WORD);  /* Pop the return address and flags */
             }
             break;
 
-      case 0xe4: /* inb al,XX */
-            inportb_abs(context);
+        case 0xe4: /* inb al,XX */
+            AL = inport( instr[1], 1 );
 	    EIP += 2;
             break;
 
-      case 0xe5: /* in ax,XX */
-            inport_abs( context, long_op );
+        case 0xe5: /* in (e)ax,XX */
+            if (long_op) EAX = inport( instr[1], 4 );
+            else AX = inport( instr[1], 2 );
 	    EIP += 2;
             break;
 
-      case 0xe6: /* outb XX,al */
-            outportb_abs(context);
+        case 0xe6: /* outb XX,al */
+            outport( instr[1], 1, AL );
 	    EIP += 2;
             break;
 
-      case 0xe7: /* out XX,ax */
-            outport_abs( context, long_op );
-	    EIP += 2;
+        case 0xe7: /* out XX,(e)ax */
+            if (long_op) outport( instr[1], 4, EAX );
+            else outport( instr[1], 2, AX );
+  	    EIP += 2;
             break;
 
-      case 0xec: /* inb al,dx */
-            inportb(context);
+        case 0xec: /* inb al,dx */
+            AL = inport( DX, 1 );
 	    EIP++;
             break;
 
-      case 0xed: /* in ax,dx */
-            inport( context, long_op );
+        case 0xed: /* in (e)ax,dx */
+            if (long_op) EAX = inport( DX, 4 );
+            else AX = inport( DX, 2 );
 	    EIP++;  
             break;
 
-      case 0xee: /* outb dx,al */
-            outportb(context);
+        case 0xee: /* outb dx,al */
+            outport( DX, 1, AL );
 	    EIP++;
             break;
       
-      case 0xef: /* out dx,ax */
-            outport( context, long_op );
+        case 0xef: /* out dx,(e)ax */
+            if (long_op) outport( DX, 4, EAX );
+            else outport( DX, 2, AX );
 	    EIP++;
             break;
 
-      case 0xfa: /* cli, ignored */
+        case 0xfa: /* cli, ignored */
 	    EIP++;
             break;
 
-      case 0xfb: /* sti, ignored */
+        case 0xfb: /* sti, ignored */
 	    EIP++;
             break;
 
+        case 0x6c: /* insb     */
+        case 0x6d: /* insw/d   */
+        case 0x6e: /* outsb    */
+        case 0x6f: /* outsw/d  */
+	    {
+	      int typ = *instr;  /* Just in case it's overwritten.  */
+	      int outp = (typ >= 0x6e);
+	      unsigned long count = repX ? (long_addr ? ECX : CX) : 1;
+	      int opsize = (typ & 1) ? (long_op ? 4 : 2) : 1;
+	      int step = (EFL & 0x400) ? -opsize : +opsize;
+	      /* FIXME: Check this, please.  */
+	      int seg = outp ? (segprefix >= 0 ? segprefix : DS) : ES;
+
+	      if (outp)
+		/* FIXME: Check segment readable.  */
+		;
+	      else
+		/* FIXME: Check segment writeable.  */
+		;
+
+	      if (repX)
+		if (long_addr)
+		  ECX = 0;
+		else
+		  CX = 0;
+
+	      while (count-- > 0)
+		{
+		  void *data;
+		  if (outp)
+		    {
+		      data = PTR_SEG_OFF_TO_LIN (seg, long_addr ? ESI : SI);
+		      if (long_addr)
+			ESI += step;
+		      else
+			SI += step;
+		    }
+		  else
+		    {
+		      data = PTR_SEG_OFF_TO_LIN (seg, long_addr ? EDI : DI);
+		      if (long_addr)
+			EDI += step;
+		      else
+			DI += step;
+		    }
+
+		  switch (typ)
+		    {
+		    case 0x6c:
+		      *((BYTE *)data) = inport (DX, 1);
+		      break;
+		    case 0x6d:
+		      if (long_op)
+			*((DWORD *)data) = inport (DX, 4);
+		      else
+			*((WORD *)data) = inport (DX, 2);
+		      break;
+		    case 0x6e:
+		      outport (DX, 1, *((BYTE *)data));
+		      break;
+		    case 0x6f:
+		      if (long_op)
+			outport (DX, 4, *((DWORD *)data));
+		      else
+			outport (DX, 2, *((WORD *)data));
+		      break;
+		    }
+		}
+	      EIP++;
+	      break;
+	    }
+
       default:
             fprintf(stderr, "Unexpected Windows program segfault"
                             " - opcode = %x\n", *instr);
diff --git a/miscemu/int10.c b/miscemu/int10.c
index 501b183..04a1a87 100644
--- a/miscemu/int10.c
+++ b/miscemu/int10.c
@@ -7,38 +7,35 @@
 /* #define DEBUG_INT */
 #include "debug.h"
 
-void IntBarf(int i, struct sigcontext_struct *context)
+
+/**********************************************************************
+ *	    INT_Int10Handler
+ *
+ * Handler for int 10h (video).
+ */
+void INT_Int10Handler( struct sigcontext_struct sigcontext )
 {
-	dprintf_int(stddeb, "int%x: unknown/not implemented parameters:\n", i);
-	dprintf_int(stddeb, "int%x: AX %04x, BX %04x, CX %04x, DX %04x, "
-	       "SI %04x, DI %04x, DS %04x, ES %04x\n",
-	       i, AX, BX, CX, DX, SI, DI, DS, ES);
-}
+#define context (&sigcontext)
+    switch(AH)
+    {
+    case 0x0f:
+        AL = 0x5b;
+        break;
 
-int do_int10(struct sigcontext_struct *context)
-{
-        dprintf_int(stddeb,"int10: AX %04x, BX %04x, CX %04x, DX %04x, "
-               "SI %04x, DI %04x, DS %04x, ES %04x\n",
-               AX, BX, CX, DX, SI, DI, DS, ES);
-
-	switch(AH) {
-	case 0x0f:
-		AL = 0x5b;
-		break;
-
-	case 0x12:
-		if (BL == 0x10) {
-			BX = 0x0003;
-			CX = 0x0009;
-		}
-		break;
+    case 0x12:
+        if (BL == 0x10)
+        {
+            BX = 0x0003;
+            CX = 0x0009;
+        }
+        break;
 			
-	case 0x1a:
-		BX = 0x0008;
-		break;
+    case 0x1a:
+        BX = 0x0008;
+        break;
 
-	default:
-		IntBarf(0x10, context);
-	};
-	return 1;
+    default:
+        INT_BARF( 0x10 );
+    }
+#undef context
 }
diff --git a/miscemu/int13.c b/miscemu/int13.c
index e0e62f5..d570768 100644
--- a/miscemu/int13.c
+++ b/miscemu/int13.c
@@ -7,13 +7,17 @@
 /* #define DEBUG_INT */
 #include "debug.h"
 
-int do_int13(struct sigcontext_struct *context)
-{
-        dprintf_int(stddeb,"int13: AX %04x, BX %04x, CX %04x, DX %04x, "
-               "SI %04x, DI %04x, DS %04x, ES %04x\n",
-               AX, BX, CX, DX, SI, DI, DS, ES);
 
-	switch(AH) {
+/**********************************************************************
+ *	    INT_Int13Handler
+ *
+ * Handler for int 13h (disk I/O).
+ */
+void INT_Int13Handler( struct sigcontext_struct sigcontext )
+{
+#define context (&sigcontext)
+    switch(AH)
+    {
 	case 0x00:                            /* RESET DISK SYSTEM     */
 	case 0x04:                            /* VERIFY DISK SECTOR(S) */
 		AH = 0;
@@ -52,7 +56,7 @@
 		break;
 
 	default:
-		IntBarf(0x13, context);
-	};
-	return 1;
+		INT_BARF( 0x13 );
+    }
+#undef context
 }
diff --git a/miscemu/int15.c b/miscemu/int15.c
deleted file mode 100644
index 9efc47c..0000000
--- a/miscemu/int15.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include "registers.h"
-#include "wine.h"
-#include "miscemu.h"
-#include "stddebug.h"
-/* #define DEBUG_INT */
-#include "debug.h"
-
-int do_int15(struct sigcontext_struct *context)
-{
-	switch(AH) {
-	case 0xc0:
-		
-	default:
-		IntBarf(0x15, context);
-	};
-	return 1;
-}
diff --git a/miscemu/int16.c b/miscemu/int16.c
deleted file mode 100644
index b3cc06e..0000000
--- a/miscemu/int16.c
+++ /dev/null
@@ -1,19 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include "registers.h"
-#include "wine.h"
-#include "miscemu.h"
-#include "stddebug.h"
-/* #define DEBUG_INT */
-#include "debug.h"
-
-int do_int16(struct sigcontext_struct *context)
-{
-	switch(AH) {
-	case 0xc0:
-		
-	default:
-		IntBarf(0x16, context);
-	};
-	return 1;
-}
diff --git a/miscemu/int1a.c b/miscemu/int1a.c
index 60a29ab..60cf634 100644
--- a/miscemu/int1a.c
+++ b/miscemu/int1a.c
@@ -13,16 +13,20 @@
 #define	BCD_TO_BIN(x) ((x&15) + (x>>4)*10)
 #define BIN_TO_BCD(x) ((x%10) + ((x/10)<<4))
 
-int do_int1a(struct sigcontext_struct * context){
+
+/**********************************************************************
+ *	    INT_Int1aHandler
+ *
+ * Handler for int 1ah (date and time).
+ */
+void INT_Int1aHandler( struct sigcontext_struct sigcontext )
+{
+#define context (&sigcontext)
 	time_t ltime;
         DWORD ticks;
 	struct tm *bdtime;
         struct timeval tvs;
 
-	dprintf_int(stddeb,"int1A: AX %04x, BX %04x, CX %04x, DX %04x, "
-	       "SI %04x, DI %04x, DS %04x, ES %04x\n",
-	       AX, BX, CX, DX, SI, DI, DS, ES);
-
 	switch(AH) {
 	case 0:
                 /* This should give us the (approximately) correct
@@ -68,8 +72,7 @@
 		break;
 
 	default:
-		IntBarf(0x1a, context);
-		return 1;
-	};
-	return 1;
+		INT_BARF( 0x1a );
+	}
+#undef context
 }
diff --git a/miscemu/int21.c b/miscemu/int21.c
index 078f34e..25b2f8c 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -24,7 +24,6 @@
 #include "options.h"
 #include "miscemu.h"
 #include "stddebug.h"
-/* #define DEBUG_INT */
 #include "debug.h"
 
 /* Define the drive parameter block, as used by int21/1F
@@ -196,7 +195,7 @@
 		return;
 	}
 
-	AX = 4;	
+	AX = (drive < 2) ? 1 : 64;  /* 64 for hard-disks, 1 for diskettes */
 	CX = 512;
 
 	BX = (available / (CX * AX));
@@ -206,8 +205,14 @@
 
 static void GetDriveAllocInfo(struct sigcontext_struct *context)
 {
+        int drive;
 	long size, available;
 	
+	if (DL == 0)
+		drive = DOS_GetDefaultDrive();
+	else
+		drive = DL - 1;
+
 	if (!DOS_ValidDrive(DL)) {
 		AX = 4;
 		CX = 512;
@@ -222,7 +227,7 @@
 		return;
 	}
 	
-	AX = 4;
+	AX = (drive < 2) ? 1 : 64;  /* 64 for hard-disks, 1 for diskettes */
 	CX = 512;
 	DX = (size / (CX * AX));
 
@@ -233,12 +238,6 @@
 	Error (0,0,0);
 }
 
-static void GetDefDriveAllocInfo(struct sigcontext_struct *context)
-{
-	DX = DOS_GetDefaultDrive();
-	GetDriveAllocInfo(context);
-}
-
 static void GetDrivePB(struct sigcontext_struct *context, int drive)
 {
         if(!DOS_ValidDrive(drive))
@@ -260,12 +259,12 @@
                 dpb->drive_num = dpb->unit_num = drive;    /* The same? */
                 dpb->sector_size = 512;
                 dpb->high_sector = 1;
-                dpb->shift = 0;
+                dpb->shift = drive < 2 ? 0 : 6; /* 6 for HD, 0 for floppy */
                 dpb->reserved = 0;
                 dpb->num_FAT = 1;
                 dpb->dir_entries = 2;
                 dpb->first_data = 2;
-                dpb->high_cluster = 1023;
+                dpb->high_cluster = 64000;
                 dpb->sectors_in_FAT = 1;
                 dpb->start_dir = 1;
                 dpb->driver_head = 0;
@@ -414,7 +413,7 @@
 	    
 		    if (fstat(BX, &sbuf) < 0)
 		    {
-			IntBarf(0x21, context);
+                        INT_BARF( 0x21 );
 			SetCflag;
 			return;
 		    }
@@ -444,8 +443,8 @@
 	}
 
 	if (CH != 0x08) {
-		IntBarf(0x21, context);
-		return;
+            INT_BARF( 0x21 );
+            return;
 	}
 	switch (CL) {
 		case 0x60: /* get device parameters */
@@ -469,7 +468,7 @@
 			ResetCflag;
 			return;
 		default:
-			IntBarf(0x21, context);
+                        INT_BARF( 0x21 );
 	}
 }
 
@@ -508,18 +507,18 @@
 
 static void CreateFile(struct sigcontext_struct *context)
 {
-	int handle;
-
-	if ((handle = open(DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS,DX)), 
-           O_CREAT | O_TRUNC | O_RDWR )) == -1) {
-		errno_to_doserr();
-		AX = ExtendedError;
-		SetCflag;
-		return;
-		}			
-	Error (0,0,0);
-        AX = handle;
-	ResetCflag;
+    int handle;
+    handle = open(DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS,DX)), 
+		  O_CREAT | O_TRUNC | O_RDWR, 0666 );
+    if (handle == -1) {
+	errno_to_doserr();
+	AX = ExtendedError;
+	SetCflag;
+	return;
+    }
+    Error (0,0,0);
+    AX = handle;
+    ResetCflag;
 }
 
 void OpenExistingFile(struct sigcontext_struct *context)
@@ -725,6 +724,7 @@
 
         memcpy(&dp, dta+0x11, sizeof(dp));
 
+        dprintf_int(stddeb, "int21: FindNext, dta %p, dp %p\n", dta, dp);
 	do {
 		if ((dp = DOS_readdir(dp)) == NULL) {
 			Error(NoMoreFiles, EC_MediaError , EL_Disk);
@@ -778,17 +778,6 @@
 	memset(dta + 1 , '?', 11);
 	*(dta + 0x0c) = ECX & (FA_LABEL | FA_DIREC);
 
-	if (ECX & FA_LABEL) {
-		/* return volume label */
-
-		if (DOS_GetVolumeLabel(drive) != NULL) 
-			strncpy(dta + 0x1e, DOS_GetVolumeLabel(drive), 8);
-
-		AX = 0;
-		ResetCflag;
-		return;
-	}
-
 	if ((dp = DOS_opendir(path)) == NULL) {
 		Error(PathNotFound, EC_MediaError, EL_Disk);
 		AX = FileNotFound;
@@ -841,7 +830,7 @@
 
 	dprintf_int(stddeb,"CreateTempFile %s\n",temp);
 
-	handle = open(DOS_GetUnixFileName(temp), O_CREAT | O_TRUNC | O_RDWR);
+	handle = open(DOS_GetUnixFileName(temp), O_CREAT | O_TRUNC | O_RDWR, 0666);
 
 	if (handle == -1) {
             Error( WriteProtected, EC_AccessDenied, EL_Disk );
@@ -860,7 +849,7 @@
 {
 	int handle;
 	
-	if ((handle = open(DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS,DX) ), O_CREAT | O_EXCL | O_RDWR)) == -1) {
+	if ((handle = open(DOS_GetUnixFileName( PTR_SEG_OFF_TO_LIN(DS,DX) ), O_CREAT | O_EXCL | O_RDWR, 0666)) == -1) {
             Error( WriteProtected, EC_AccessDenied, EL_Disk );
             AX = WriteProtected;
             SetCflag;
@@ -1204,20 +1193,18 @@
 
 extern void LOCAL_PrintHeap (WORD ds);
 
-/************************************************************************/
-
-int do_int21(struct sigcontext_struct * context)
+/***********************************************************************
+ *           DOS3Call  (KERNEL.102)
+ */
+void DOS3Call( struct sigcontext_struct sigcontext )
 {
+#define context (&sigcontext)
     int drive;
 
-    dprintf_int(stddeb,"int21: AX %04x, BX %04x, CX %04x, DX %04x, "
-           "SI %04x, DI %04x, DS %04x, ES %04x\n",
-           AX, BX, CX, DX, SI, DI, DS, ES);
-
     if (AH == 0x59) 
     {
 	GetExtendedErrorInfo(context);
-	return 1;
+	return;
     } 
     else 
     {
@@ -1255,7 +1242,7 @@
 	  case 0x28: /* RANDOM BLOCK WRITE TO FCB FILE */
 	  case 0x29: /* PARSE FILENAME INTO FCB */
 	  case 0x2e: /* SET VERIFY FLAG */
-	    IntBarf(0x21, context);
+            INT_BARF( 0x21 );
 	    break;
 
 	  case 0x2b: /* SET SYSTEM DATE */
@@ -1264,7 +1251,7 @@
 			"SWITCHAR" - SET SWITCH CHARACTER
 			"AVAILDEV" - SPECIFY \DEV\ PREFIX USE */
 	  case 0x54: /* GET VERIFY FLAG */
-            IntBarf(0x21, context);
+            INT_BARF( 0x21 );
 	    break;
 
 	  case 0x18: /* NULL FUNCTIONS FOR CP/M COMPATIBILITY */
@@ -1284,15 +1271,14 @@
             break;
 
 	  case 0x0e: /* SELECT DEFAULT DRIVE */
-		if (!DOS_ValidDrive(DL)) {
-			Error (InvalidDrive, EC_MediaError, EL_Disk);
-			AX = MAX_DOS_DRIVES; 
-			break;
-		} else {
-			DOS_SetDefaultDrive(DL);
-			AX = MAX_DOS_DRIVES; 
-			Error(0,0,0);
+		if (!DOS_ValidDrive(DL))
+                    Error (InvalidDrive, EC_MediaError, EL_Disk);
+		else
+                {
+                    DOS_SetDefaultDrive(DL);
+                    Error(0,0,0);
 		}
+                AL = MAX_DOS_DRIVES;
 		break;
 
 	  case 0x11: /* FIND FIRST MATCHING FILE USING FCB */
@@ -1321,7 +1307,8 @@
             break;
 
 	  case 0x1b: /* GET ALLOCATION INFORMATION FOR DEFAULT DRIVE */
-	    GetDefDriveAllocInfo(context);
+            DL = 0;
+	    GetDriveAllocInfo(context);
 	    break;
 	
 	  case 0x1c: /* GET ALLOCATION INFORMATION FOR SPECIFIC DRIVE */
@@ -1359,7 +1346,7 @@
 	    break;
 
 	  case 0x31: /* TERMINATE AND STAY RESIDENT */
-            IntBarf(0x21, context);
+            INT_BARF( 0x21 );
 	    break;
 
 	  case 0x32: /* GET DOS DRIVE PARAMETER BLOCK FOR SPECIFIC DRIVE */
@@ -1390,7 +1377,7 @@
 		break;
 
 	      default:
-		IntBarf(0x21, context);
+                INT_BARF( 0x21 );
 		break;			
 	    }
 	    break;	
@@ -1541,7 +1528,7 @@
                 break;
                 
 	      default:
-                IntBarf(0x21, context);
+                INT_BARF( 0x21 );
 		break;
 	    }
 	    break;
@@ -1575,8 +1562,8 @@
 	  case 0x48: /* ALLOCATE MEMORY */
 	  case 0x49: /* FREE MEMORY */
 	  case 0x4a: /* RESIZE MEMORY BLOCK */
-	    IntBarf(0x21, context);
-	    break;
+            INT_BARF( 0x21 );
+            break;
 	
 	  case 0x4b: /* "EXEC" - LOAD AND/OR EXECUTE PROGRAM */
             WinExec( PTR_SEG_OFF_TO_LIN(DS,DX), SW_NORMAL );
@@ -1597,12 +1584,19 @@
 	  case 0x4f: /* "FINDNEXT" - FIND NEXT MATCHING FILE */
 	    FindNext(context);
 	    break;
-			
-	  case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
-		ES = 0x0;
-		BX = 0x0;
-		IntBarf(0x21, context);
+
+	  case 0x51: /* GET PSP ADDRESS */
+	  case 0x62: /* GET PSP ADDRESS */
+	    /* FIXME: should we return the original DOS PSP upon */
+	    /*        Windows startup ? */
+	    BX = GetCurrentPDB();
 	    break;
+
+	  case 0x52: /* "SYSVARS" - GET LIST OF LISTS */
+            ES = 0x0;
+            BX = 0x0;
+            INT_BARF( 0x21 );
+            break;
 		
 	  case 0x56: /* "RENAME" - RENAME FILE */
 	    RenameFile(context);
@@ -1694,12 +1688,11 @@
 	    break;
 
 	  case 0x61: /* UNUSED */
-	  case 0x62: /* GET CURRENT PSP ADDRESS */
 	  case 0x63: /* UNUSED */
 	  case 0x64: /* OS/2 DOS BOX */
 	  case 0x65: /* GET EXTENDED COUNTRY INFORMATION */
-		IntBarf(0x21, context);
-	    break;
+            INT_BARF( 0x21 );
+            break;
 	
 	  case 0x66: /* GLOBAL CODE PAGE TABLE */
 	    switch (AL) {
@@ -1741,26 +1734,18 @@
 	    break;
 
 	  default:
-            IntBarf(0x21, context);
-	    return 1;
+            INT_BARF( 0x21 );
+            break;
 	}
     }
     dprintf_int(stddeb,"ret21: AX %04x, BX %04x, CX %04x, DX %04x, "
            "SI %04x, DI %04x, DS %04x, ES %04x EFL %08lx\n",
            AX, BX, CX, DX, SI, DI, DS, ES, EFL);
 
-    return 1;
+#undef context
 }
 
 
-/***********************************************************************
- *           DOS3Call  (KERNEL.102)
- */
-void DOS3Call( struct sigcontext_struct context )
-{
-    do_int21( &context );
-}
-
 void INT21_Init(void)
 {
     if ((DosHeapHandle = GlobalAlloc(GMEM_FIXED,sizeof(struct DosHeap))) == 0)
diff --git a/miscemu/int25.c b/miscemu/int25.c
index 6ebc32e..5427075 100644
--- a/miscemu/int25.c
+++ b/miscemu/int25.c
@@ -11,8 +11,14 @@
 /* #define DEBUG_INT */
 #include "debug.h"
 
-int do_int25(struct sigcontext_struct *context)
+/**********************************************************************
+ *	    INT_Int25Handler
+ *
+ * Handler for int 25h (absolute disk read).
+ */
+void INT_Int25Handler( struct sigcontext_struct sigcontext )
 {
+#define context (&sigcontext)
 	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS, BX);
 	DWORD begin, length;
 
@@ -20,11 +26,7 @@
         {
             SetCflag;
             AX = 0x0101;        /* unknown unit */
-
-            /* push flags on stack */
-            SP -= sizeof(WORD);
-            setword(PTR_SEG_OFF_TO_LIN(SS,SP), (WORD) EFL);
-            return 1;
+            return;
         }
 
 	if (CX == 0xffff) {
@@ -48,10 +50,5 @@
 		*dataptr = 0xf8;
 
 	ResetCflag;
-
-	/* push flags on stack */
-	SP -= sizeof(WORD);
-	setword(PTR_SEG_OFF_TO_LIN(SS,SP), (WORD) EFL);
-
-	return 1;
+#undef context
 }
diff --git a/miscemu/int26.c b/miscemu/int26.c
index 97bf02d..aa281d7 100644
--- a/miscemu/int26.c
+++ b/miscemu/int26.c
@@ -10,8 +10,14 @@
 /* #define DEBUG_INT */
 #include "debug.h"
 
-int do_int26(struct sigcontext_struct *context)
+/**********************************************************************
+ *	    INT_Int26Handler
+ *
+ * Handler for int 26h (absolute disk read).
+ */
+void INT_Int26Handler( struct sigcontext_struct sigcontext )
 {
+#define context (&sigcontext)
 	BYTE *dataptr = PTR_SEG_OFF_TO_LIN(DS, BX);
 	DWORD begin, length;
 
@@ -19,11 +25,7 @@
         {
             SetCflag;
             AX = 0x0101;        /* unknown unit */
-
-            /* push flags on stack */
-            SP -= sizeof(WORD);
-            setword(PTR_SEG_OFF_TO_LIN(SS,SP), (WORD) EFL);
-            return 1;
+            return;
         }
 
 	if (CX == 0xffff) {
@@ -40,10 +42,5 @@
 	"count %ld, buffer %d\n", AL, begin, length, (int) dataptr);
 
 	ResetCflag;
-
-	/* push flags on stack */
-	SP -= sizeof(WORD);
-	setword(PTR_SEG_OFF_TO_LIN(SS,SP), (WORD) EFL);
-
-	return 1;
+#undef context
 }
diff --git a/miscemu/int2a.c b/miscemu/int2a.c
index 63ed11d..35921fb 100644
--- a/miscemu/int2a.c
+++ b/miscemu/int2a.c
@@ -2,20 +2,27 @@
 #include <stdlib.h>
 #include "msdos.h"
 #include "wine.h"
+#include "registers.h"
 #include "miscemu.h"
 #include "stddebug.h"
 /* #define DEBUG_INT */
 #include "debug.h"
 
-int do_int2a(struct sigcontext_struct *context)
+/**********************************************************************
+ *	    INT_Int2aHandler
+ *
+ * Handler for int 2ah (network).
+ */
+void INT_Int2aHandler( struct sigcontext_struct sigcontext )
 {
-	switch((context->sc_eax >> 8) & 0xff)
-	{
-	case 0x00:                             /* NETWORK INSTALLATION CHECK */
-		break;
+#define context (&sigcontext)
+    switch(AH)
+    {
+    case 0x00:                             /* NETWORK INSTALLATION CHECK */
+        break;
 		
-	default:
-		IntBarf(0x2a, context);
-	};
-	return 1;
+    default:
+	INT_BARF( 0x2a );
+    }
+#undef context
 }
diff --git a/miscemu/int2f.c b/miscemu/int2f.c
index ad797d1..88bd229 100644
--- a/miscemu/int2f.c
+++ b/miscemu/int2f.c
@@ -9,35 +9,37 @@
 /* #define DEBUG_INT */
 #include "debug.h"
 
-int do_int2f_16(struct sigcontext_struct *context);
+static void do_int2f_16(struct sigcontext_struct *context);
 
-int do_int2f(struct sigcontext_struct *context)
+/**********************************************************************
+ *	    INT_Int2fHandler
+ *
+ * Handler for int 2fh (multiplex).
+ */
+void INT_Int2fHandler( struct sigcontext_struct sigcontext )
 {
-        dprintf_int(stddeb,"int2f: AX %04x, BX %04x, CX %04x, DX %04x, "
-               "SI %04x, DI %04x, DS %04x, ES %04x\n",
-               AX, BX, CX, DX, SI, DI, DS, ES);
-
-	switch(AH)
-	{
+#define context (&sigcontext)
+    switch(AH)
+    {
 	case 0x10:
                 AL = 0xff; /* share is installed */
 		break;
 
 	case 0x15: /* mscdex */
 		/* ignore requests */
-		return 1;
+		break;
 
 	case 0x16:
-		return do_int2f_16(context);
-
+		do_int2f_16( context );
+                break;
 	default:
-		IntBarf(0x2f, context);
-	};
-	return 1;
+		INT_BARF( 0x2f );
+            }
+#undef context
 }
 
 
-int do_int2f_16(struct sigcontext_struct *context)
+static void do_int2f_16(struct sigcontext_struct *context)
 {
     switch(AL)
     {
@@ -51,6 +53,9 @@
         CX = Options.enhanced ? 3 : 2;
         break;
 
+    case 0x80:  /* Release time-slice */
+        break;  /* nothing to do */
+
     case 0x86:  /* DPMI detect mode */
         AX = 0;  /* Running under DPMI */
         break;
@@ -58,17 +63,16 @@
     case 0x87:  /* DPMI installation check */
         AX = 0x0000;  /* DPMI Installed */
         BX = 0x0001;  /* 32bits available */
-        CX = 0x04;    /* processor 486 */
-        DX = 0x0009;  /* DPMI major/minor 0.9 */
+        CL = 0x03;    /* processor 386 */
+        DX = 0x005a;  /* DPMI major/minor 0.90 */
         SI = 0;       /* # of para. of DOS extended private data */
         ES = 0;       /* ES:DI is DPMI switch entry point */
         DI = 0;
         break;
 
     default:
-        IntBarf(0x2f, context);
+        INT_BARF( 0x2f );
     }
-    return 1;
 }
 
 
diff --git a/miscemu/int5c.c b/miscemu/int5c.c
index 0bd1fd1..ad94c25 100644
--- a/miscemu/int5c.c
+++ b/miscemu/int5c.c
@@ -13,21 +13,13 @@
 
 
 /***********************************************************************
- *           do_int5c
- */
-int do_int5c(struct sigcontext_struct * context)
-{
-    dprintf_int(stddeb,"NetBiosCall: AX %04x, BX %04x, CX %04x, DX %04x, "
-           "SI %04x, DI %04x, DS %04x, ES %04x\n",
-           AX, BX, CX, DX, SI, DI, DS, ES);
-    return 0;
-}
-
-
-/***********************************************************************
  *           NetBIOSCall  (KERNEL.103)
+ *
+ * Also handler for interrupt 5c.
  */
-void NetBIOSCall( struct sigcontext_struct context )
+void NetBIOSCall( struct sigcontext_struct sigcontext )
 {
-    do_int5c( &context );
+#define context (&sigcontext)
+    INT_BARF( 0x5c );
+#undef context
 }
diff --git a/miscemu/interrupts.c b/miscemu/interrupts.c
index 01f957e..b576424 100644
--- a/miscemu/interrupts.c
+++ b/miscemu/interrupts.c
@@ -6,7 +6,10 @@
 
 #include "windows.h"
 #include "miscemu.h"
+#include "dos_fs.h"
 #include "module.h"
+#include "registers.h"
+#include "stackframe.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -21,15 +24,17 @@
  */
 BOOL INT_Init(void)
 {
-    SEGPTR addr, dummyHandler;
     WORD vector;
     HMODULE hModule = GetModuleHandle( "WINPROCS" );
 
-    dummyHandler = MODULE_GetEntryPoint( hModule, FIRST_INTERRUPT_ORDINAL+256);
     for (vector = 0; vector < 256; vector++)
     {
-        addr = MODULE_GetEntryPoint( hModule, FIRST_INTERRUPT_ORDINAL+vector );
-        INT_Vectors[vector] = addr ? addr : dummyHandler;
+        if (!(INT_Vectors[vector] = MODULE_GetEntryPoint( hModule,
+		                             FIRST_INTERRUPT_ORDINAL+vector )))
+	{
+	    fprintf(stderr,"Internal error: no vector for int %02x\n",vector);
+	    return FALSE;
+	}
     }
     return TRUE;
 }
@@ -42,9 +47,6 @@
  */
 SEGPTR INT_GetHandler( BYTE intnum )
 {
-    dprintf_int( stddeb, "Get interrupt vector %02x -> %04x:%04x\n",
-                 intnum, HIWORD(INT_Vectors[intnum]),
-                 LOWORD(INT_Vectors[intnum]) );
     return INT_Vectors[intnum];
 }
 
@@ -65,126 +67,61 @@
 /**********************************************************************
  *	    INT_DummyHandler
  */
-void INT_DummyHandler( struct sigcontext_struct context )
+void INT_DummyHandler( struct sigcontext_struct sigcontext )
 {
-    dprintf_int( stddeb, "Dummy handler called!\n" );
-}
-
-/**********************************************************************
- *	    INT_Int10Handler
- */
-void INT_Int10Handler( struct sigcontext_struct context )
-{
-    dprintf_int( stddeb, "int 10 called indirectly through handler!\n" );
-    do_int10( &context );
+#define context (&sigcontext)
+    INT_BARF( CURRENT_STACK16->ordinal_number - FIRST_INTERRUPT_ORDINAL );
+#undef context
 }
 
 
 /**********************************************************************
- *	    INT_Int13Handler
+ *	    INT_Int11Handler
+ *
+ * Handler for int 11h (get equipment list).
  */
-void INT_Int13Handler( struct sigcontext_struct context )
+void INT_Int11Handler( struct sigcontext_struct sigcontext )
 {
-    dprintf_int( stddeb, "int 13 called indirectly through handler!\n" );
-    do_int13( &context );
+#define context (&sigcontext)
+    AX = DOS_GetEquipment();
+#undef context
+}
+
+
+/**********************************************************************
+ *	    INT_Int12Handler
+ *
+ * Handler for int 12h (get memory size).
+ */
+void INT_Int12Handler( struct sigcontext_struct sigcontext )
+{
+#define context (&sigcontext)
+    AX = 640;
+#undef context
 }
 
 
 /**********************************************************************
  *	    INT_Int15Handler
+ *
+ * Handler for int 15h.
  */
-void INT_Int15Handler( struct sigcontext_struct context )
+void INT_Int15Handler( struct sigcontext_struct sigcontext )
 {
-    dprintf_int( stddeb, "int 15 called indirectly through handler!\n" );
-    do_int15( &context );
+#define context (&sigcontext)
+    INT_BARF( 0x15 );
+#undef context
 }
 
 
 /**********************************************************************
  *	    INT_Int16Handler
+ *
+ * Handler for int 16h (keyboard).
  */
-void INT_Int16Handler( struct sigcontext_struct context )
+void INT_Int16Handler( struct sigcontext_struct sigcontext )
 {
-    dprintf_int( stddeb, "int 16 called indirectly through handler!\n" );
-    do_int16( &context );
-}
-
-
-/**********************************************************************
- *	    INT_Int1aHandler
- */
-void INT_Int1aHandler( struct sigcontext_struct context )
-{
-    dprintf_int( stddeb, "int 1a called indirectly through handler!\n" );
-    do_int1a( &context );
-}
-
-
-/**********************************************************************
- *	    INT_Int21Handler
- */
-void INT_Int21Handler( struct sigcontext_struct context )
-{
-    dprintf_int( stddeb, "int 21 called indirectly through handler!\n" );
-    do_int21( &context );
-}
-
-
-/**********************************************************************
- *	    INT_Int25Handler
- */
-void INT_Int25Handler( struct sigcontext_struct context )
-{
-    dprintf_int( stddeb, "int 25 called indirectly through handler!\n" );
-    do_int25( &context );
-}
-
-
-/**********************************************************************
- *	    INT_Int26Handler
- */
-void INT_Int26Handler( struct sigcontext_struct context )
-{
-    dprintf_int( stddeb, "int 26 called indirectly through handler!\n" );
-    do_int26( &context );
-}
-
-
-/**********************************************************************
- *	    INT_Int2aHandler
- */
-void INT_Int2aHandler( struct sigcontext_struct context )
-{
-    dprintf_int( stddeb, "int 2a called indirectly through handler!\n" );
-    do_int2a( &context );
-}
-
-
-/**********************************************************************
- *	    INT_Int2fHandler
- */
-void INT_Int2fHandler( struct sigcontext_struct context )
-{
-    dprintf_int( stddeb, "int 2f called indirectly through handler!\n" );
-    do_int2f( &context );
-}
-
-
-/**********************************************************************
- *	    INT_Int31Handler
- */
-void INT_Int31Handler( struct sigcontext_struct context )
-{
-    dprintf_int( stddeb, "int 31 called indirectly through handler!\n" );
-    do_int31( &context );
-}
-
-
-/**********************************************************************
- *	    INT_Int5cHandler
- */
-void INT_Int5cHandler( struct sigcontext_struct context )
-{
-    dprintf_int( stddeb, "int 5c called indirectly through handler!\n" );
-    do_int5c( &context );
+#define context (&sigcontext)
+    INT_BARF( 0x16 );
+#undef context
 }
diff --git a/miscemu/ioports.c b/miscemu/ioports.c
index 161ca06..3ea012a 100644
--- a/miscemu/ioports.c
+++ b/miscemu/ioports.c
@@ -1,87 +1,86 @@
+/*
+ * Emulation of processor ioports.
+ *
+ * Copyright 1995 Morten Welinder
+ */
+
+/* Known problems:
+   - only a few ports are emulated.
+   - real-time clock in "cmos" is bogus.  A nifty alarm() setup could
+     fix that, I guess.
+*/
+
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
-#include "registers.h"
-#include "wine.h"
+#include "windows.h"
 #include "stddebug.h"
 /* #define DEBUG_INT */
 #include "debug.h"
 
 static BYTE cmosaddress;
 
-static BYTE cmosimage[64] = {
-	0x27, 0x34, 0x31, 0x47, 0x16, 0x15, 0x00, 0x01,
-	0x04, 0x94, 0x26, 0x02, 0x50, 0x80, 0x00, 0x00,
-	0x40, 0xb1, 0x00, 0x9c, 0x01, 0x80, 0x02, 0x00,
-	0x1c, 0x00, 0x00, 0xad, 0x02, 0x10, 0x00, 0x00,
-	0x08, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x03, 0x58,
-	0x00, 0x1c, 0x19, 0x81, 0x00, 0x0e, 0x00, 0x80,
-	0x1b, 0x7b, 0x21, 0x00, 0x00, 0x00, 0x05, 0x5f };
-
-void inportb(struct sigcontext_struct *context)
+static BYTE cmosimage[64] =
 {
-	dprintf_int(stddeb, "IO: inb (%x)\n", DX);
+  0x27, 0x34, 0x31, 0x47, 0x16, 0x15, 0x00, 0x01,
+  0x04, 0x94, 0x26, 0x02, 0x50, 0x80, 0x00, 0x00,
+  0x40, 0xb1, 0x00, 0x9c, 0x01, 0x80, 0x02, 0x00,
+  0x1c, 0x00, 0x00, 0xad, 0x02, 0x10, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x03, 0x58,
+  0x00, 0x1c, 0x19, 0x81, 0x00, 0x0e, 0x00, 0x80,
+  0x1b, 0x7b, 0x21, 0x00, 0x00, 0x00, 0x05, 0x5f
+};
 
-	switch(DX) {
-		case 0x70:
-			AL = cmosaddress;
-			break;
-		case 0x71:
-			AL = cmosimage[cmosaddress & 0x3f];
-			break;
-		default:
-	}
-}
 
-void inport( struct sigcontext_struct *context, int long_op )
+DWORD inport( int port, int count )
 {
-    dprintf_int(stdnimp, "IO: in (%x)\n", DX);
-    if (long_op) EAX = 0xffffffff;
-    else AX = 0xffff;
-}
+    DWORD res = 0;
+    BYTE b;
 
-void inportb_abs(struct sigcontext_struct *context)
-{
-	dprintf_int(stdnimp, "IO: in (%x)\n", *(BYTE *)(EIP+1));
-	AL = 0xff;
-}
+    dprintf_int(stddeb, "IO: %d bytes from port 0x%02x\n", count, port );
 
-void inport_abs( struct sigcontext_struct *context, int long_op )
-{
-    dprintf_int(stdnimp, "IO: in (%x)\n", *(BYTE *)(EIP+1));
-    if (long_op) EAX = 0xffffffff;
-    else AX = 0xffff;
-}
-
-void outportb(struct sigcontext_struct *context)
-{
-	dprintf_int(stdnimp, "IO: outb (%x), %x\n", DX, AX);
-
-	switch (EDX & 0xffff)
+    while (count-- > 0)
+    {
+        switch (port++)
 	{
-		case 0x70:
-			cmosaddress = AL & 0x7f;
-			break;
-		case 0x71:
-			cmosimage[cmosaddress & 0x3f] = AL;
-			break;
-		default:
+	case 0x70:
+            b = cmosaddress;
+            break;
+	case 0x71:
+            b = cmosimage[cmosaddress & 0x3f];
+            break;
+	default:
+	  b = 0xff;
 	}
+        res = (res << 8) | b;
+    }
+    return res;
 }
 
-void outport( struct sigcontext_struct *context, int long_op )
-{
-    dprintf_int(stdnimp, "IO: out (%x), %lx\n", DX, long_op ? EAX : AX);
-}
 
-void outportb_abs(struct sigcontext_struct *context)
+void outport( int port, int count, DWORD value )
 {
-    dprintf_int(stdnimp, "IO: out (%x), %x\n", *(BYTE *)(EIP+1), AL);
-}
+    BYTE b;
 
-void outport_abs( struct sigcontext_struct *context, int long_op )
-{
-    dprintf_int(stdnimp, "IO: out (%x), %lx\n", *(BYTE *)(EIP+1),
-                long_op ? EAX : AX);
+    dprintf_int( stddeb, "IO: 0x%lx (%d bytes) to port 0x%02x\n",
+                 value, count, port );
+
+    while (count-- > 0)
+    {
+        b = value & 0xff;
+        value >>= 8;
+        switch (port++)
+	{
+	case 0x70:
+            cmosaddress = b & 0x7f;
+            break;
+	case 0x71:
+            cmosimage[cmosaddress & 0x3f] = b;
+            break;
+	default:
+            /* Rien du tout.  */
+	}
+    }
 }
diff --git a/multimedia/Imakefile b/multimedia/Imakefile
index c7db934..582e384 100644
--- a/multimedia/Imakefile
+++ b/multimedia/Imakefile
@@ -4,11 +4,13 @@
 
 SRCS = \
 	audio.c \
+	joystick.c \
 	mcianim.c \
 	mcicda.c \
 	midi.c \
 	mmaux.c \
-	mmsystem.c
+	mmsystem.c \
+	time.c
 
 OBJS = $(SRCS:.c=.o)
 
diff --git a/multimedia/Makefile.in b/multimedia/Makefile.in
new file mode 100644
index 0000000..ceec464
--- /dev/null
+++ b/multimedia/Makefile.in
@@ -0,0 +1,51 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include
+LD	= @LD@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+
+
+MODULE 	= multimedia
+
+SRCS 	= audio.c joystick.c mcianim.c mcicda.c midi.c mmaux.c \
+	  mmsystem.c time.c
+
+
+OBJS = $(SRCS:.c=.o)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
+
+all: $(MODULE).o
+
+$(MODULE).o: $(OBJS)
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dummy:
+
+### Dependencies:
diff --git a/multimedia/joystick.c b/multimedia/joystick.c
new file mode 100644
index 0000000..9eff801
--- /dev/null
+++ b/multimedia/joystick.c
@@ -0,0 +1,98 @@
+/*
+ * MMSYTEM functions
+ *
+ * Copyright 1993 Martin Ayotte
+ */
+
+#ifndef WINELIB
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include "windows.h"
+#include "ldt.h"
+#include "callback.h"
+#include "user.h"
+#include "driver.h"
+#include "mmsystem.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/**************************************************************************
+ * 				JoyGetNumDevs		[MMSYSTEM.101]
+ */
+WORD JoyGetNumDevs(void)
+{
+    fprintf(stdnimp, "EMPTY STUB !!! JoyGetNumDevs();\n");
+    return 0;
+}
+
+/**************************************************************************
+ * 				JoyGetDevCaps		[MMSYSTEM.102]
+ */
+WORD JoyGetDevCaps(WORD wID, LPJOYCAPS lpCaps, WORD wSize)
+{
+    fprintf(stdnimp, "EMPTY STUB !!! JoyGetDevCaps(%04X, %p, %d);\n",
+	    wID, lpCaps, wSize);
+    return MMSYSERR_NODRIVER;
+}
+
+/**************************************************************************
+ * 				JoyGetPos	       	[MMSYSTEM.103]
+ */
+WORD JoyGetPos(WORD wID, LPJOYINFO lpInfo)
+{
+    fprintf(stdnimp, "EMPTY STUB !!! JoyGetPos(%04X, %p);\n", wID, lpInfo);
+    return MMSYSERR_NODRIVER;
+}
+
+/**************************************************************************
+ * 				JoyGetThreshold		[MMSYSTEM.104]
+ */
+WORD JoyGetThreshold(WORD wID, LPWORD lpThreshold)
+{
+    fprintf(stdnimp, "EMPTY STUB !!! JoyGetThreshold(%04X, %p);\n", wID, lpThreshold);
+    return MMSYSERR_NODRIVER;
+}
+
+/**************************************************************************
+ * 				JoyReleaseCapture	[MMSYSTEM.105]
+ */
+WORD JoyReleaseCapture(WORD wID)
+{
+    fprintf(stdnimp, "EMPTY STUB !!! JoyReleaseCapture(%04X);\n", wID);
+    return MMSYSERR_NODRIVER;
+}
+
+/**************************************************************************
+ * 				JoySetCapture		[MMSYSTEM.106]
+ */
+WORD JoySetCapture(HWND hWnd, WORD wID, WORD wPeriod, BOOL bChanged)
+{
+    fprintf(stdnimp, "EMPTY STUB !!! JoySetCapture(%04X, %04X, %d, %d);\n",
+	    hWnd, wID, wPeriod, bChanged);
+    return MMSYSERR_NODRIVER;
+}
+
+/**************************************************************************
+ * 				JoySetThreshold		[MMSYSTEM.107]
+ */
+WORD JoySetThreshold(WORD wID, WORD wThreshold)
+{
+    fprintf(stdnimp, "EMPTY STUB !!! JoySetThreshold(%04X, %d);\n", wID, wThreshold);
+    return MMSYSERR_NODRIVER;
+}
+
+/**************************************************************************
+ * 				JoySetCalibration	[MMSYSTEM.109]
+ */
+WORD JoySetCalibration(WORD wID)
+{
+    fprintf(stdnimp, "EMPTY STUB !!! JoySetCalibration(%04X);\n", wID);
+    return MMSYSERR_NODRIVER;
+}
+
+#endif
diff --git a/multimedia/midi.c b/multimedia/midi.c
index 0a61f36..faa61b5 100644
--- a/multimedia/midi.c
+++ b/multimedia/midi.c
@@ -1227,16 +1227,6 @@
 
 
 /**************************************************************************
-* 				modGetPosition			[internal]
-*/
-static DWORD modGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
-{
-	dprintf_midi(stddeb, "modGetposition(%u, %p, %08lX);\n", wDevID, lpTime, uSize);
-	return MMSYSERR_NOTENABLED;
-}
-
-
-/**************************************************************************
 * 				modMessage			[sample driver]
 */
 DWORD modMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index 2a01641..0d130a0 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -25,40 +25,21 @@
 static int	InstalledListLen;
 static LPSTR	lpInstallNames = NULL;
 
-static BOOL		mmTimeStarted = FALSE;
-static MMTIME	mmSysTimeMS;
-static MMTIME	mmSysTimeSMPTE;
-
-typedef struct tagTIMERENTRY {
-	WORD		wDelay;
-	WORD		wResol;
-	FARPROC		lpFunc;
-	DWORD		dwUser;
-	WORD		wFlags;
-	WORD		wTimerID;
-	WORD		wCurTime;
-	struct tagTIMERENTRY	*Next;
-	struct tagTIMERENTRY	*Prev;
-	} TIMERENTRY;
-typedef TIMERENTRY *LPTIMERENTRY;
-
-static LPTIMERENTRY lpTimerList = NULL;
-
 static MCI_OPEN_DRIVER_PARMS	mciDrv[MAXMCIDRIVERS];
 
 UINT midiGetErrorText(UINT uError, LPSTR lpText, UINT uSize);
 UINT waveGetErrorText(UINT uError, LPSTR lpText, UINT uSize);
 LONG DrvDefDriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, 
-						DWORD dwParam1, DWORD dwParam2);
+		      DWORD dwParam1, DWORD dwParam2);
 
 LONG WAVE_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, 
-							DWORD dwParam1, DWORD dwParam2);
+		     DWORD dwParam1, DWORD dwParam2);
 LONG MIDI_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, 
-							DWORD dwParam1, DWORD dwParam2);
+		     DWORD dwParam1, DWORD dwParam2);
 LONG CDAUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, 
-							DWORD dwParam1, DWORD dwParam2);
+			DWORD dwParam1, DWORD dwParam2);
 LONG ANIM_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, 
-							DWORD dwParam1, DWORD dwParam2);
+		     DWORD dwParam1, DWORD dwParam2);
 
 /**************************************************************************
 * 				MMSYSTEM_WEP		[MMSYSTEM.1]
@@ -242,81 +223,6 @@
 }
 
 /**************************************************************************
-* 				JoyGetNumDevs		[MMSYSTEM.101]
-*/
-WORD JoyGetNumDevs()
-{
-	fprintf(stdnimp, "EMPTY STUB !!! JoyGetNumDevs();\n");
-	return 0;
-}
-
-/**************************************************************************
-* 				JoyGetDevCaps		[MMSYSTEM.102]
-*/
-WORD JoyGetDevCaps(WORD wID, LPJOYCAPS lpCaps, WORD wSize)
-{
-	fprintf(stdnimp, "EMPTY STUB !!! JoyGetDevCaps(%04X, %p, %d);\n", 
-										wID, lpCaps, wSize);
-	return MMSYSERR_NODRIVER;
-}
-
-/**************************************************************************
-* 				JoyGetPos			[MMSYSTEM.103]
-*/
-WORD JoyGetPos(WORD wID, LPJOYINFO lpInfo)
-{
-	fprintf(stdnimp, "EMPTY STUB !!! JoyGetPos(%04X, %p);\n", wID, lpInfo);
-	return MMSYSERR_NODRIVER;
-}
-
-/**************************************************************************
-* 				JoyGetThreshold		[MMSYSTEM.104]
-*/
-WORD JoyGetThreshold(WORD wID, LPWORD lpThreshold)
-{
-	fprintf(stdnimp, "EMPTY STUB !!! JoyGetThreshold(%04X, %p);\n", wID, lpThreshold);
-	return MMSYSERR_NODRIVER;
-}
-
-/**************************************************************************
-* 				JoyReleaseCapture	[MMSYSTEM.105]
-*/
-WORD JoyReleaseCapture(WORD wID)
-{
-	fprintf(stdnimp, "EMPTY STUB !!! JoyReleaseCapture(%04X);\n", wID);
-	return MMSYSERR_NODRIVER;
-}
-
-/**************************************************************************
-* 				JoySetCapture		[MMSYSTEM.106]
-*/
-WORD JoySetCapture(HWND hWnd, WORD wID, WORD wPeriod, BOOL bChanged)
-{
-	fprintf(stdnimp, "EMPTY STUB !!! JoySetCapture(%04X, %04X, %d, %d);\n", 
-							hWnd, wID, wPeriod, bChanged);
-	return MMSYSERR_NODRIVER;
-}
-
-/**************************************************************************
-* 				JoySetThreshold		[MMSYSTEM.107]
-*/
-WORD JoySetThreshold(WORD wID, WORD wThreshold)
-{
-	fprintf(stdnimp, "EMPTY STUB !!! JoySetThreshold(%04X, %d);\n", wID, wThreshold);
-	return MMSYSERR_NODRIVER;
-}
-
-/**************************************************************************
-* 				JoySetCalibration	[MMSYSTEM.109]
-*/
-WORD JoySetCalibration(WORD wID)
-{
-	fprintf(stdnimp, "EMPTY STUB !!! JoySetCalibration(%04X);\n", wID);
-	return MMSYSERR_NODRIVER;
-}
-
-
-/**************************************************************************
 * 				auxGetNumDevs		[MMSYSTEM.350]
 */
 UINT auxGetNumDevs()
@@ -1930,7 +1836,7 @@
 	lpDesc = (LPWAVEOPENDESC) USER_HEAP_LIN_ADDR(hWaveIn);
 	if (lpDesc == NULL) return MMSYSERR_INVALHANDLE;
 	return widMessage(0, WIDM_GETPOS, lpDesc->dwInstance,
-							(DWORD)lpTime, (DWORD)uSize);
+			  (DWORD)lpTime, (DWORD)uSize);
 }
 
 
@@ -1949,7 +1855,7 @@
 * 				waveInMessage 		[MMSYSTEM.514]
 */
 DWORD waveInMessage(HWAVEIN hWaveIn, UINT uMessage,
-							DWORD dwParam1, DWORD dwParam2)
+		    DWORD dwParam1, DWORD dwParam2)
 {
 	LPWAVEOPENDESC	lpDesc;
 	dprintf_mmsys(stddeb, "waveInMessage(%04X, %04X, %08lX, %08lX)\n", 
@@ -1961,161 +1867,7 @@
 
 
 /**************************************************************************
-* 				MMSysTimeCallback	[internal]
-*/
-WORD FAR PASCAL MMSysTimeCallback(HWND hWnd, WORD wMsg, int nID, DWORD dwTime)
-{
-	LPTIMERENTRY	lpTimer = lpTimerList;
-	mmSysTimeMS.u.ms += 33;
-	mmSysTimeSMPTE.u.smpte.frame++;
-	while (lpTimer != NULL) {
-		lpTimer->wCurTime--;
-		if (lpTimer->wCurTime == 0) {
-			lpTimer->wCurTime = lpTimer->wDelay;
-			if (lpTimer->lpFunc != (FARPROC)NULL) {
-				dprintf_mmtime(stddeb,"MMSysTimeCallback // before CallBack16 !\n");
-                                CallTimeFuncProc( lpTimer->lpFunc,
-                                                  lpTimer->wTimerID, 0,
-                                                  lpTimer->dwUser, 0, 0 );
-				dprintf_mmtime(stddeb, "MMSysTimeCallback // after CallBack16 !\n");
-				fflush(stdout);
-				}
-			if (lpTimer->wFlags & TIME_ONESHOT)
-				timeKillEvent(lpTimer->wTimerID);
-			}
-		lpTimer = lpTimer->Next;
-		}
-	return 0;
-}
-
-/**************************************************************************
-* 				StartMMTime			[internal]
-*/
-void StartMMTime()
-{
-	if (!mmTimeStarted) {
-		mmTimeStarted = TRUE;
-		mmSysTimeMS.wType = TIME_MS;
-		mmSysTimeMS.u.ms = 0;
-		mmSysTimeSMPTE.wType = TIME_SMPTE;
-		mmSysTimeSMPTE.u.smpte.hour = 0;
-		mmSysTimeSMPTE.u.smpte.min = 0;
-		mmSysTimeSMPTE.u.smpte.sec = 0;
-		mmSysTimeSMPTE.u.smpte.frame = 0;
-		mmSysTimeSMPTE.u.smpte.fps = 0;
-		mmSysTimeSMPTE.u.smpte.dummy = 0;
-		SetTimer(0, 1, 33, (FARPROC)MMSysTimeCallback);
-		}
-}
-
-/**************************************************************************
-* 				timeGetSystemTime	[MMSYSTEM.601]
-*/
-WORD timeGetSystemTime(LPMMTIME lpTime, WORD wSize)
-{
-	dprintf_mmsys(stddeb, "timeGetSystemTime(%p, %u);\n", lpTime, wSize);
-	if (!mmTimeStarted) StartMMTime();
-	return 0;
-}
-
-/**************************************************************************
-* 				timeSetEvent		[MMSYSTEM.602]
-*/
-WORD timeSetEvent(WORD wDelay, WORD wResol, 
-				LPTIMECALLBACK lpFunc, 
-				DWORD dwUser, WORD wFlags)
-{
-	WORD			wNewID = 0;
-	LPTIMERENTRY	lpNewTimer;
-	LPTIMERENTRY	lpTimer = lpTimerList;
-	dprintf_mmsys(stddeb, "timeSetEvent(%u, %u, %p, %08lX, %04X);\n",
-			wDelay, wResol, lpFunc, dwUser, wFlags);
-	if (!mmTimeStarted) StartMMTime();
-	lpNewTimer = (LPTIMERENTRY) malloc(sizeof(TIMERENTRY));
-	if (lpNewTimer == NULL)	return 0;
-	while (lpTimer != NULL) {
-		wNewID = max(wNewID, lpTimer->wTimerID);
-		if (lpTimer->Next == NULL) break;
-		lpTimer = lpTimer->Next;
-		}
-	if (lpTimerList == NULL) {
-		lpTimerList = lpNewTimer;
-		lpNewTimer->Prev = NULL;
-		}
-	else {
-		lpTimer->Next = lpNewTimer;
-		lpNewTimer->Prev = lpTimer;
-		}
-	lpNewTimer->Next = NULL;
-	lpNewTimer->wTimerID = wNewID + 1;
-	lpNewTimer->wCurTime = wDelay;
-	lpNewTimer->wDelay = wDelay;
-	lpNewTimer->wResol = wResol;
-	lpNewTimer->lpFunc = (FARPROC)lpFunc;
-	lpNewTimer->dwUser = dwUser;
-	lpNewTimer->wFlags = wFlags;
-	return lpNewTimer->wTimerID;
-}
-
-/**************************************************************************
-* 				timeKillEvent		[MMSYSTEM.603]
-*/
-WORD timeKillEvent(WORD wID)
-{
-	LPTIMERENTRY	lpTimer = lpTimerList;
-	while (lpTimer != NULL) {
-		if (wID == lpTimer->wTimerID) {
-			if (lpTimer->Prev != NULL) lpTimer->Prev->Next = lpTimer->Next;
-			if (lpTimer->Next != NULL) lpTimer->Next->Prev = lpTimer->Prev;
-			free(lpTimer);
-			return TRUE;
-			}
-		lpTimer = lpTimer->Next;
-		}
-	return 0;
-}
-
-/**************************************************************************
-* 				timeGetDevCaps		[MMSYSTEM.604]
-*/
-WORD timeGetDevCaps(LPTIMECAPS lpCaps, WORD wSize)
-{
-	dprintf_mmsys(stddeb, "timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
-	return 0;
-}
-
-/**************************************************************************
-* 				timeBeginPeriod		[MMSYSTEM.605]
-*/
-WORD timeBeginPeriod(WORD wPeriod)
-{
-	dprintf_mmsys(stddeb, "timeBeginPeriod(%u) !\n", wPeriod);
-	if (!mmTimeStarted) StartMMTime();
-	return 0;
-}
-
-/**************************************************************************
-* 				timeEndPeriod		[MMSYSTEM.606]
-*/
-WORD timeEndPeriod(WORD wPeriod)
-{
-	dprintf_mmsys(stddeb, "timeEndPeriod(%u) !\n", wPeriod);
-	return 0;
-}
-
-/**************************************************************************
-* 				timeGetTime			[MMSYSTEM.607]
-*/
-DWORD timeGetTime()
-{
-	dprintf_mmsys(stddeb, "timeGetTime(); !\n");
-	if (!mmTimeStarted) StartMMTime();
-	return 0;
-}
-
-
-/**************************************************************************
-* 				mmioOpen			[MMSYSTEM.1210]
+* 				mmioOpen       		[MMSYSTEM.1210]
 */
 HMMIO mmioOpen(LPSTR szFileName, MMIOINFO FAR* lpmmioinfo, DWORD dwOpenFlags)
 {
@@ -2134,13 +1886,12 @@
 	lpmminfo->dwReserved2 = MAKELONG(hFile, 0);
 	GlobalUnlock(hmmio);
 	dprintf_mmsys(stddeb, "mmioOpen // return hmmio=%04X\n", hmmio);
-	return (HMMIO)hmmio;
+	return hmmio;
 }
 
-
     
 /**************************************************************************
-* 				mmioClose			[MMSYSTEM.1211]
+* 				mmioClose      		[MMSYSTEM.1211]
 */
 UINT mmioClose(HMMIO hmmio, UINT uFlags)
 {
@@ -2157,7 +1908,7 @@
 
 
 /**************************************************************************
-* 				mmioRead			[MMSYSTEM.1212]
+* 				mmioRead	       	[MMSYSTEM.1212]
 */
 LONG mmioRead(HMMIO hmmio, HPSTR pch, LONG cch)
 {
@@ -2175,7 +1926,7 @@
 
 
 /**************************************************************************
-* 				mmioWrite			[MMSYSTEM.1213]
+* 				mmioWrite      		[MMSYSTEM.1213]
 */
 LONG mmioWrite(HMMIO hmmio, HPCSTR pch, LONG cch)
 {
@@ -2190,7 +1941,7 @@
 }
 
 /**************************************************************************
-* 				mmioSeek			[MMSYSTEM.1214]
+* 				mmioSeek       		[MMSYSTEM.1214]
 */
 LONG mmioSeek(HMMIO hmmio, LONG lOffset, int iOrigin)
 {
@@ -2208,7 +1959,7 @@
 }
 
 /**************************************************************************
-* 				mmioGetInfo			[MMSYSTEM.1215]
+* 				mmioGetInfo	       	[MMSYSTEM.1215]
 */
 UINT mmioGetInfo(HMMIO hmmio, MMIOINFO FAR* lpmmioinfo, UINT uFlags)
 {
@@ -2222,7 +1973,7 @@
 }
 
 /**************************************************************************
-* 				mmioSetInfo			[MMSYSTEM.1216]
+* 				mmioSetInfo    		[MMSYSTEM.1216]
 */
 UINT mmioSetInfo(HMMIO hmmio, const MMIOINFO FAR* lpmmioinfo, UINT uFlags)
 {
@@ -2245,7 +1996,7 @@
 }
 
 /**************************************************************************
-* 				mmioFlush			[MMSYSTEM.1218]
+* 				mmioFlush      		[MMSYSTEM.1218]
 */
 UINT mmioFlush(HMMIO hmmio, UINT uFlags)
 {
@@ -2258,7 +2009,7 @@
 }
 
 /**************************************************************************
-* 				mmioAdvance			[MMSYSTEM.1219]
+* 				mmioAdvance    		[MMSYSTEM.1219]
 */
 UINT mmioAdvance(HMMIO hmmio, MMIOINFO FAR* lpmmioinfo, UINT uFlags)
 {
@@ -2311,7 +2062,7 @@
 }
 
 /**************************************************************************
-* 				mmioDescend			[MMSYSTEM.1223]
+* 				mmioDescend	       	[MMSYSTEM.1223]
 */
 UINT mmioDescend(HMMIO hmmio, MMCKINFO FAR* lpck,
 		    const MMCKINFO FAR* lpckParent, UINT uFlags)
@@ -2372,7 +2123,7 @@
 }
 
 /**************************************************************************
-* 				mmioAscend			[MMSYSTEM.1224]
+* 				mmioAscend     		[MMSYSTEM.1224]
 */
 UINT mmioAscend(HMMIO hmmio, MMCKINFO FAR* lpck, UINT uFlags)
 {
@@ -2391,7 +2142,7 @@
 
 
 /**************************************************************************
-* 				mmioRename			[MMSYSTEM.1226]
+* 				mmioRename     		[MMSYSTEM.1226]
 */
 UINT mmioRename(LPCSTR szFileName, LPCSTR szNewFileName,
      MMIOINFO FAR* lpmmioinfo, DWORD dwRenameFlags)
@@ -2402,7 +2153,7 @@
 }
 
 /**************************************************************************
-* 				DrvOpen				[MMSYSTEM.1100]
+* 				DrvOpen	       		[MMSYSTEM.1100]
 */
 HDRVR DrvOpen(LPSTR lpDriverName, LPSTR lpSectionName, LPARAM lParam)
 {
@@ -2413,7 +2164,7 @@
 
 
 /**************************************************************************
-* 				DrvClose			[MMSYSTEM.1101]
+* 				DrvClose       		[MMSYSTEM.1101]
 */
 LRESULT DrvClose(HDRVR hDrvr, LPARAM lParam1, LPARAM lParam2)
 {
diff --git a/multimedia/time.c b/multimedia/time.c
new file mode 100644
index 0000000..bfa5abc
--- /dev/null
+++ b/multimedia/time.c
@@ -0,0 +1,198 @@
+/*
+ * MMSYTEM time functions
+ *
+ * Copyright 1993 Martin Ayotte
+ */
+
+#ifndef WINELIB
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "windows.h"
+#include "ldt.h"
+#include "callback.h"
+#include "user.h"
+#include "driver.h"
+#include "mmsystem.h"
+#include "selectors.h"
+#include "stddebug.h"
+#include "debug.h"
+
+static BOOL mmTimeStarted = FALSE;
+static MMTIME mmSysTimeMS;
+static MMTIME mmSysTimeSMPTE;
+
+typedef struct tagTIMERENTRY {
+    WORD wDelay;
+    WORD wResol;
+    FARPROC lpFunc;
+    DWORD dwUser;
+    WORD wFlags;
+    WORD wTimerID;
+    WORD wCurTime;
+    struct tagTIMERENTRY *Next;
+    struct tagTIMERENTRY *Prev;
+} TIMERENTRY, *LPTIMERENTRY;
+
+static LPTIMERENTRY lpTimerList = NULL;
+
+/**************************************************************************
+ * 				MMSysTimeCallback	[internal]
+ */
+WORD MMSysTimeCallback(HWND hWnd, WORD wMsg, INT nID, DWORD dwTime)
+{
+    LPTIMERENTRY lpTimer = lpTimerList;
+    mmSysTimeMS.u.ms += 33;
+    mmSysTimeSMPTE.u.smpte.frame++;
+    while (lpTimer != NULL) {
+	lpTimer->wCurTime--;
+	if (lpTimer->wCurTime == 0) {
+	    lpTimer->wCurTime = lpTimer->wDelay;
+	    if (lpTimer->lpFunc != (FARPROC) NULL) {
+		dprintf_mmtime(stddeb, "MMSysTimeCallback // before CallBack16 !\n");
+		CallTimeFuncProc(lpTimer->lpFunc, lpTimer->wTimerID, 0,
+				 lpTimer->dwUser, 0, 0);
+		dprintf_mmtime(stddeb, "MMSysTimeCallback // after CallBack16 !\n");
+		fflush(stdout);
+	    }
+	    if (lpTimer->wFlags & TIME_ONESHOT)
+		timeKillEvent(lpTimer->wTimerID);
+	}
+	lpTimer = lpTimer->Next;
+    }
+    return 0;
+}
+
+/**************************************************************************
+ * 				StartMMTime			[internal]
+ */
+void StartMMTime()
+{
+    if (!mmTimeStarted) {
+	mmTimeStarted = TRUE;
+	mmSysTimeMS.wType = TIME_MS;
+	mmSysTimeMS.u.ms = 0;
+	mmSysTimeSMPTE.wType = TIME_SMPTE;
+	mmSysTimeSMPTE.u.smpte.hour = 0;
+	mmSysTimeSMPTE.u.smpte.min = 0;
+	mmSysTimeSMPTE.u.smpte.sec = 0;
+	mmSysTimeSMPTE.u.smpte.frame = 0;
+	mmSysTimeSMPTE.u.smpte.fps = 0;
+	mmSysTimeSMPTE.u.smpte.dummy = 0;
+	SetTimer(0, 1, 33, GetWndProcEntry16("MMSysTimeCallback"));
+    }
+}
+
+/**************************************************************************
+ * 				timeGetSystemTime	[MMSYSTEM.601]
+ */
+WORD timeGetSystemTime(LPMMTIME lpTime, WORD wSize)
+{
+    dprintf_mmsys(stddeb, "timeGetSystemTime(%p, %u);\n", lpTime, wSize);
+    if (!mmTimeStarted)
+	StartMMTime();
+    return 0;
+}
+
+/**************************************************************************
+ * 				timeSetEvent		[MMSYSTEM.602]
+ */
+WORD timeSetEvent(WORD wDelay, WORD wResol, LPTIMECALLBACK lpFunc,
+		  DWORD dwUser, WORD wFlags)
+{
+    WORD wNewID = 0;
+    LPTIMERENTRY lpNewTimer;
+    LPTIMERENTRY lpTimer = lpTimerList;
+    dprintf_mmsys(stddeb, "timeSetEvent(%u, %u, %p, %08lX, %04X);\n",
+		  wDelay, wResol, lpFunc, dwUser, wFlags);
+    if (!mmTimeStarted)
+	StartMMTime();
+    lpNewTimer = (LPTIMERENTRY) malloc(sizeof(TIMERENTRY));
+    if (lpNewTimer == NULL)
+	return 0;
+    while (lpTimer != NULL) {
+	wNewID = max(wNewID, lpTimer->wTimerID);
+	if (lpTimer->Next == NULL)
+	    break;
+	lpTimer = lpTimer->Next;
+    }
+    if (lpTimerList == NULL) {
+	lpTimerList = lpNewTimer;
+	lpNewTimer->Prev = NULL;
+    } else {
+	lpTimer->Next = lpNewTimer;
+	lpNewTimer->Prev = lpTimer;
+    }
+    lpNewTimer->Next = NULL;
+    lpNewTimer->wTimerID = wNewID + 1;
+    lpNewTimer->wCurTime = wDelay;
+    lpNewTimer->wDelay = wDelay;
+    lpNewTimer->wResol = wResol;
+    lpNewTimer->lpFunc = (FARPROC) lpFunc;
+    lpNewTimer->dwUser = dwUser;
+    lpNewTimer->wFlags = wFlags;
+    return lpNewTimer->wTimerID;
+}
+
+/**************************************************************************
+ * 				timeKillEvent		[MMSYSTEM.603]
+ */
+WORD timeKillEvent(WORD wID)
+{
+    LPTIMERENTRY lpTimer = lpTimerList;
+    while (lpTimer != NULL) {
+	if (wID == lpTimer->wTimerID) {
+	    if (lpTimer->Prev != NULL)
+		lpTimer->Prev->Next = lpTimer->Next;
+	    if (lpTimer->Next != NULL)
+		lpTimer->Next->Prev = lpTimer->Prev;
+	    free(lpTimer);
+	    return TRUE;
+	}
+	lpTimer = lpTimer->Next;
+    }
+    return 0;
+}
+
+/**************************************************************************
+ * 				timeGetDevCaps		[MMSYSTEM.604]
+ */
+WORD timeGetDevCaps(LPTIMECAPS lpCaps, WORD wSize)
+{
+    dprintf_mmsys(stddeb, "timeGetDevCaps(%p, %u) !\n", lpCaps, wSize);
+    return 0;
+}
+
+/**************************************************************************
+ * 				timeBeginPeriod		[MMSYSTEM.605]
+ */
+WORD timeBeginPeriod(WORD wPeriod)
+{
+    dprintf_mmsys(stddeb, "timeBeginPeriod(%u) !\n", wPeriod);
+    if (!mmTimeStarted)
+	StartMMTime();
+    return 0;
+}
+
+/**************************************************************************
+ * 				timeEndPeriod		[MMSYSTEM.606]
+ */
+WORD timeEndPeriod(WORD wPeriod)
+{
+    dprintf_mmsys(stddeb, "timeEndPeriod(%u) !\n", wPeriod);
+    return 0;
+}
+
+/**************************************************************************
+ * 				timeGetTime    		[MMSYSTEM.607]
+ */
+DWORD timeGetTime()
+{
+    dprintf_mmsys(stddeb, "timeGetTime(); !\n");
+    if (!mmTimeStarted)
+	StartMMTime();
+    return 0;
+}
+
+#endif /* WINELIB */
diff --git a/objects/Makefile.in b/objects/Makefile.in
new file mode 100644
index 0000000..4196d0a
--- /dev/null
+++ b/objects/Makefile.in
@@ -0,0 +1,51 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include
+LD	= @LD@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+
+
+MODULE 	= objects
+
+SRCS 	= bitblt.c bitmap.c brush.c clipping.c color.c dc.c dcvalues.c \
+	dib.c font.c gdiobj.c linedda.c metafile.c oembitmap.c palette.c \
+	pen.c region.c text.c
+
+OBJS = $(SRCS:.c=.o)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
+
+all: $(MODULE).o
+
+$(MODULE).o: $(OBJS)
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dummy:
+
+### Dependencies:
diff --git a/objects/bitmap.c b/objects/bitmap.c
index e0f15c4..179d16d 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -12,7 +12,7 @@
 #include "callback.h"
 #include "dc.h"
 #include "bitmap.h"
-#include "prototypes.h"
+#include "resource.h"  /* for ConvertCore/InfoBitmap */
 #include "stddebug.h"
 /* #define DEBUG_GDI    */
 /* #define DEBUG_BITMAP */
diff --git a/objects/clipping.c b/objects/clipping.c
index 42dda4e..003a6ae 100644
--- a/objects/clipping.c
+++ b/objects/clipping.c
@@ -314,7 +314,9 @@
     dprintf_clipping(stddeb,"RectVisible: %x %d,%dx%d,%d\n",
                      hdc, rect->left, rect->top, rect->right, rect->bottom );
     if (!dc->w.hGCClipRgn) return FALSE;
-    LPtoDP( hdc, (LPPOINT)rect, 2 );
+    /* copy rectangle to avoid overwriting by LPtoDP */
+    tmpRect = *rect;
+    LPtoDP( hdc, (LPPOINT)&tmpRect, 2 );
     return RectInRegion( dc->w.hGCClipRgn, &tmpRect );
 }
 
diff --git a/objects/dib.c b/objects/dib.c
index 78ab1ee..c2538b4 100644
--- a/objects/dib.c
+++ b/objects/dib.c
@@ -517,17 +517,8 @@
 	break;
     }
     if (colorMapping) free(colorMapping);
-    {
-      WORD saved_ds = CURRENT_DS;
-      XPutImage( display, drawable, gc, bmpImage, xSrc, ySrc,
-		xDest, yDest, width, height );
-      if (saved_ds != CURRENT_DS) {
-	fprintf(stderr,"Uh oh. XPutImage clobbered the 16 bit stack.\n"
-		"Please report: %s compression, %d bitplanes!!\n",
-		info->bmiHeader.biCompression ? "" : "no", 
-		info->bmiHeader.biBitCount);
-      }
-    }
+    XPutImage( display, drawable, gc, bmpImage, xSrc, ySrc,
+	       xDest, yDest, width, height );
     XDestroyImage( bmpImage );
     return lines;
 }
@@ -656,8 +647,9 @@
 
     if (bits)
     {	
-	bmpImage = XGetImage( display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
-			      bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
+	bmpImage = (XImage *)CallTo32_LargeStack( (int (*)())XGetImage, 8, 
+		               display, bmp->pixmap, 0, 0, bmp->bitmap.bmWidth,
+		               bmp->bitmap.bmHeight, AllPlanes, ZPixmap );
 	dibImage = DIB_DIBmpToImage( &info->bmiHeader, bits );
 
 	for (y = 0; y < lines; y++)
@@ -733,4 +725,3 @@
     SetBkColor( hDC, oldBg );
     return TRUE;
 }
-
diff --git a/objects/font.c b/objects/font.c
index be92707..200b605 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -262,32 +262,31 @@
 /***********************************************************************
  *           GetGlyphOutLine    (GDI.309)
  */
-DWORD GetGlyphOutLine(
-	HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, 
-	DWORD cbBuffer, LPSTR lpBuffer, LPMAT2 lpmat2
-) {
-	dprintf_font(stdnimp,"GetGlyphOutLine(0x%x, '%c', 0x%x, %p, %d, %p, %p) // - empty stub!\n",
-		hdc,uChar,fuFormat,lpgm,cbBuffer,lpBuffer,lpmat2
-	);
-	return (DWORD)-1; /* failure */
+DWORD GetGlyphOutLine(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm, 
+                      DWORD cbBuffer, LPSTR lpBuffer, LPMAT2 lpmat2) 
+{
+    fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
+             hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
+    return (DWORD)-1; /* failure */
 }
+
+
 /***********************************************************************
  *           CreateScalableFontResource    (GDI.310)
  */
-BOOL CreateScalableFontResource(
-	UINT fHidden,LPSTR lpszResourceFile,
-	LPSTR lpszFontFile,LPSTR lpszCurrentPath
-) {
-	/* fHidden=1 - only visible for the calling app, read-only, not
-	 * enumbered with EnumFonts/EnumFontFamilies
-	 * lpszCurrentPath can be NULL
-	 */
-	dprintf_font(stdnimp,"CreateScalableFontResource(%d,%s,%s,%x(%s)) // empty stub!\n",
-		fHidden,lpszResourceFile,lpszFontFile,lpszCurrentPath
-	);
-	return FALSE; /* create failed */
+BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
+                                 LPSTR lpszFontFile, LPSTR lpszCurrentPath )
+{
+    /* fHidden=1 - only visible for the calling app, read-only, not
+     * enumbered with EnumFonts/EnumFontFamilies
+     * lpszCurrentPath can be NULL
+     */
+    fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
+            fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
+    return FALSE; /* create failed */
 }
 
+
 /***********************************************************************
  *           CreateFontIndirect    (GDI.57)
  */
@@ -737,7 +736,7 @@
   LPTEXTMETRIC lptm;
   LPSTR	       lpOldName;
   char	       FaceName[LF_FACESIZE];
-  int          nRet;
+  int          nRet = 0;
   int          i;
   
   dprintf_font(stddeb,"EnumFonts(%04X, %p='%s', %08lx, %p)\n", 
@@ -807,7 +806,7 @@
   LPTEXTMETRIC	lptm;
   LPSTR	       	lpOldName;
   char	       	FaceName[LF_FACESIZE];
-  int	       	nRet;
+  int	       	nRet = 0;
   int	       	i;
   
   dprintf_font(stddeb,"EnumFontFamilies(%04X, %p, %08lx, %p)\n",
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index 2cfcd75..af7cccc 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -416,7 +416,7 @@
   WORD         	wMagic;
   LPSTR		lpLog;  	/* Point to a LOGBRUSH or LOGPEN struct */
   HANDLE       	hLog;
-  int	       	i, nRet = 0;
+  int	       	nRet = 0;
   
   if (lpEnumFunc == NULL) {
     fprintf(stderr,"EnumObjects // Bad EnumProc callback address !\n");
diff --git a/objects/metafile.c b/objects/metafile.c
index 9a8208a..846964e 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -212,7 +212,7 @@
     METAHEADER *mh;
     METARECORD *mr;
     HANDLETABLE *ht;
-    char *buffer;
+    char *buffer = (char *)NULL;
 
     if (mf->wMagic != METAFILE_MAGIC)
 	return FALSE;
diff --git a/objects/region.c b/objects/region.c
index 41df11b..02a10d7 100644
--- a/objects/region.c
+++ b/objects/region.c
@@ -377,6 +377,27 @@
     }
 }
 
+/***********************************************************************
+ *           REGION_CreateFrameRgn
+ *
+ * Create a region that is a frame around another region
+ */
+BOOL REGION_FrameRgn( HRGN hDest, HRGN hSrc, int x, int y )
+{
+    RGNOBJ *destObj,*srcObj;
+    Region result;
+
+    destObj = (RGNOBJ*) GDI_GetObjPtr( hDest, REGION_MAGIC );
+    srcObj  = (RGNOBJ*) GDI_GetObjPtr( hSrc, REGION_MAGIC );
+    if (!srcObj->xrgn) return 0;
+    REGION_CopyRegion( srcObj, destObj );
+    XShrinkRegion( destObj->xrgn, -x, -y );
+    result = XCreateRegion();
+    XSubtractRegion( destObj->xrgn, srcObj->xrgn, result );
+    XDestroyRegion( destObj->xrgn );
+    destObj->xrgn = result;
+    return 1;
+}
 
 /***********************************************************************
  *           CombineRgn    (GDI.451)
diff --git a/objects/text.c b/objects/text.c
index 09a58e4..1ee64d0 100644
--- a/objects/text.c
+++ b/objects/text.c
@@ -188,7 +188,9 @@
     SIZE size;
     char *strPtr;
     static char line[1024];
-    int len, lh, prefix_x, prefix_end;
+    int len, lh;
+    int prefix_x = 0;
+    int prefix_end = 0;
     TEXTMETRIC tm;
     int x = rect->left, y = rect->top;
     int width = rect->right - rect->left;
diff --git a/rc/Imakefile b/rc/Imakefile
index 4984ba4..571cb8f 100644
--- a/rc/Imakefile
+++ b/rc/Imakefile
@@ -26,7 +26,7 @@
 	touch $(RCSRCS:.rc=.h)
 
 clean::
-	$(RM) $(RCSRCS:.rc=.c) $(RCSRCS:.rc=.h)
+	$(RM) $(RCSRCS:.rc=.c) $(RCSRCS:.rc=.h) $(RCSRCS:.rc=.rct)
 
 
 XCOMM Rules to build the winerc program
@@ -60,6 +60,6 @@
 	$(YACC) -d -t parser.y
 
 lex.yy.c: parser.l y.tab.h
-	$(LEX) -I parser.l
+	$(LEX) -8 -I parser.l
  
 
diff --git a/rc/Makefile.in b/rc/Makefile.in
new file mode 100644
index 0000000..b276281
--- /dev/null
+++ b/rc/Makefile.in
@@ -0,0 +1,59 @@
+CC	= @CC@
+CFLAGS	= @CFLAGS@
+TOPSRC	= @top_srcdir@
+DIVINCL	= -I$(TOPSRC)/include
+BISON	= @YACC@
+FLEX	= @LEX@
+LANG	= @LANG@
+COMPILE	= $(CC) $(CFLAGS) $(DIVINCL) $(LANG)
+
+all: rc.o
+
+y.tab.c: parser.y
+	$(BISON) -d -t parser.y
+
+y.tab.h: parser.y
+	$(BISON) -d -t parser.y
+
+lex.yy.c: parser.l parser.h y.tab.h
+	$(FLEX) -8 -I parser.l
+
+winerc: lex.yy.o winerc.o y.tab.o
+	$(COMPILE) lex.yy.o winerc.o y.tab.o -o winerc
+
+sysres.rct: sysres.rc
+	echo "#include \"windows.h\"" >sysres.rct
+	echo WINDOWS_H_ENDS_HERE >>sysres.rct
+	cat sysres.rc >>sysres.rct
+
+sysres.c: sysres.rct winerc
+	$(COMPILE) -E -x c -P sysres.rct > sysres.tmp
+	cat sysres.tmp | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | ./winerc -o sysres -v -p sysres
+
+sysres.h: sysres.rct winerc
+	$(COMPILE) -E -x c -P sysres.rct > sysres.tmp
+	cat sysres.tmp | sed -e '1,/^WINDOWS_H_ENDS_HERE/d' | ./winerc -o sysres -v -p sysres
+
+rc.o: sysres.o
+	cp sysres.o rc.o
+
+.c.o:
+	$(COMPILE) -c -o $*.o $<
+
+clean:
+	rm -f *.o \#*\# *~ lex.yy.c sysres.tmp sysres.rct winerc y.tab.c \
+	y.tab.h sysres.c sysres.h tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+
+winelibclean: clean
+
+depend: sysres.h
+
+y.tab.o: y.tab.c
+lex.yy.o: lex.yy.c
+winerc.o: $(TOPSRC)/include/windows.h $(TOPSRC)/include/neexe.h parser.h y.tab.h
+ 
diff --git a/rc/winerc.c b/rc/winerc.c
index 14f3af0..c8832cf 100644
--- a/rc/winerc.c
+++ b/rc/winerc.c
@@ -37,11 +37,7 @@
 	extern char* optarg;
 	int optc,lose,ret,binary;
 	lose=binary=0;
-#if defined(__NetBSD__) || defined(__FreeBSD__)
 	while((optc=getopt(argc,argv,"bdp:vo:"))!=EOF)
-#else
-	while((optc=getopt(argc,argv,"bdp:vo:",0))!=EOF)
-#endif
 		switch(optc)
 		{
 			/* bison will print state transitions on stderr */
@@ -531,7 +527,7 @@
 	fprintf(header,"extern %sstruct ResourceTable %sTable[];\n",
 		ISCONSTANT,prefix);
 
-	fprintf(code,"#include \"prototypes.h\"\n#include \"%s\"\n",hname);
+	fprintf(code,"#include \"windows.h\"\n#include \"%s\"\n",hname);
 
 	/* print the resource table (0 terminated) */
 	fprintf(code,"\n%sstruct ResourceTable %sTable[]={\n",ISCONSTANT,prefix);
diff --git a/toolkit/sup.c b/toolkit/sup.c
index 25ab9f1..9a66e74 100644
--- a/toolkit/sup.c
+++ b/toolkit/sup.c
@@ -1,5 +1,4 @@
 #include <stdio.h>
-#include "prototypes.h"
 #include "windows.h"
 #include "callback.h"
 #include "wine.h"
diff --git a/tools/Makefile.in b/tools/Makefile.in
new file mode 100644
index 0000000..e5b6a7b
--- /dev/null
+++ b/tools/Makefile.in
@@ -0,0 +1,41 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include
+
+
+all: build
+
+build: build.o
+	$(CC) $(CFLAGS) -o build build.o
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ build tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dummy:
+
+### Dependencies:
diff --git a/tools/build.c b/tools/build.c
index e88bbd9..4fab002 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -1145,10 +1145,10 @@
     printf( "\tmovl %%edx,%d(%%ebx)\n", CONTEXTOFFSET(sc_edx) );
     printf( "\tmovl %%esi,%d(%%ebx)\n", CONTEXTOFFSET(sc_esi) );
     printf( "\tmovl %%edi,%d(%%ebx)\n", CONTEXTOFFSET(sc_edi) );
-    printf( "\tpushw %%es\n" );
-    printf( "\tpopw %d(%%ebx)\n", CONTEXTOFFSET(sc_es) );
     printf( "\tmovw -10(%%ebp),%%ax\n" );  /* Get saved ds from stack */
     printf( "\tmovw %%ax,%d(%%ebx)\n", CONTEXTOFFSET(sc_ds) );
+    printf( "\tmovw -12(%%ebp),%%ax\n" );  /* Get saved es from stack */
+    printf( "\tmovw %%ax,%d(%%ebx)\n", CONTEXTOFFSET(sc_es) );
     printf( "\tpushfl\n" );
 #ifndef __FreeBSD__
     printf( "\tpopl %d(%%ebx)\n", CONTEXTOFFSET(sc_eflags) );
@@ -1175,10 +1175,9 @@
     printf( "\tmovl %d(%%ebx),%%edx\n", CONTEXTOFFSET(sc_edx) );
     printf( "\tmovl %d(%%ebx),%%esi\n", CONTEXTOFFSET(sc_esi) );
     printf( "\tmovl %d(%%ebx),%%edi\n", CONTEXTOFFSET(sc_edi) );
-    printf( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(sc_es) );
-    printf( "\tpopw %%es\n" );
-    printf( "\tpopw %%ax\n" );  /* Remove old ds from the stack */
+    printf( "\tpopl %%eax\n" );  /* Remove old ds and es from stack */
     printf( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(sc_ds) ); /* Push new ds */
+    printf( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(sc_es) ); /* Push new es */
 #ifndef __FreeBSD__
     printf( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(sc_eflags) );
 #else    
@@ -1241,14 +1240,17 @@
     printf( "\tmovzwl %%sp,%%ebp\n" );
     printf( "\taddw $8,%%bp\n" );
 
-    /* Save 16-bit ds */
+    /* Save 16-bit ds and es */
 
     printf( "\tpushw %%ds\n" );
+    printf( "\tpushw %%es\n" );
 
-    /* Restore 32-bit ds */
+    /* Restore 32-bit ds and es */
 
-    printf( "\tpushw $0x%04x\n", WINE_DATA_SELECTOR );
+    printf( "\tpushl $0x%04x%04x\n", WINE_DATA_SELECTOR, WINE_DATA_SELECTOR );
     printf( "\tpopw %%ds\n" );
+    printf( "\tpopw %%es\n" );
+
 
     /* Save the 16-bit stack */
 
@@ -1271,11 +1273,6 @@
     if (!reg_func && short_ret)
         printf( "\tmovl %%edx,-8(%%ebp)\n" );
 
-    /* Setup es */
-
-    printf( "\tpushw %%ds\n" );
-    printf( "\tpopw %%es\n" );
-
     /* Switch to the 32-bit stack */
 
     printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%ebp\n" );
@@ -1294,9 +1291,11 @@
     {
         printf( "\tpushl %%eax\n" );
         printf( "\tpushl $CALL32_Str_%s\n", profile );
+        printf( "\tpushl $%d\n", reg_func ? 2 : (short_ret ? 1 : 0) );
         printf( "\tcall " PREFIX "RELAY_DebugCall32\n" );
         printf( "\tpopl %%eax\n" );
         printf( "\tpopl %%eax\n" );
+        printf( "\tpopl %%eax\n" );
     }
 
     /* Call the entry point */
@@ -1346,8 +1345,9 @@
         }
     }
 
-    /* Restore ds */
+    /* Restore ds and es */
 
+    printf( "\tpopw %%es\n" );
     printf( "\tpopw %%ds\n" );
 
     /* Get the return value into dx:ax and clean up the stack */
@@ -1532,7 +1532,6 @@
     printf( "\tpushl 12(%%ebx)\n" );
 
     /* Get the 16-bit ds */
-    /* FIXME: this shouldn't be necessary if function prologs fixup worked. */
 
     if (reg_func)
     {
@@ -1544,8 +1543,6 @@
     {
         /* Set ax equal to ds for window procedures */
         printf( "\tmovw 16(%%ebx),%%ax\n" );
-
-        /* This seems to be needed, although I still don't see why... */
         printf( "\tmovw %%ax,%%ds\n" );
     }
 
diff --git a/tools/ipcl b/tools/ipcl
new file mode 100644
index 0000000..7a066d5
--- /dev/null
+++ b/tools/ipcl
@@ -0,0 +1,92 @@
+#!/usr/bin/perl
+
+#
+# Copyright 1995. Michael Veksler.
+#
+
+$IPC_RMID=0;
+$USER=$ENV{USER};
+
+do open_pipe(IPCS,"ipcs");
+
+#
+# The following part is OS dependant, it works under linux only.
+# To make it work under other OS 
+# You should fill in @shm, @sem, @msq lists, with the relevent IPC
+# keys.
+
+#
+# This code was written to be as much as possible generic, but...
+# It works for Linux and ALPHA. I had no BSD machine to test it.
+# (As I remember, AIX will work also).
+
+while(<IPCS>) {
+    split;
+
+    # try to find out the IPC-ID, assume it is the first number.
+    foreach (@_) {
+	$_ ne int($_) && next;	# not a decimal number
+	$num=$_;
+	last;
+    }
+    if (/mem/i .. /^\s*$/ ) {
+	index($_,$USER)>=0 || next;
+	push(@shm,$num);
+    }
+    if (/sem/i .. /^\s*$/ ) {
+	index($_,$USER)>=0 || next;
+	push(@sem,$num);
+    }
+    if (/mes/i .. /^\s*$/ ) {
+	index($_,$USER)>=0 || next;
+	push(@msq,$num);
+    }
+}
+
+
+#
+# This is the end of OS dependant code.
+#
+
+@shm && print "shmid ", join(":",@shm),"\n";
+@sem && print "semid ", join(":",@sem),"\n";
+@msq && print "msqid ", join(":",@msq),"\n";
+foreach (@shm) {
+    shmctl($_, $IPC_RMID,0);
+}
+foreach (@sem) {
+    semctl($_, 0, $IPC_RMID,0);
+}
+foreach (@msq) {
+    msgctl($_, $IPC_RMID,0);
+}
+
+exit(0);
+
+
+
+
+
+sub open_pipe {
+    local($pid);
+    local($handle,@params)=@_;
+    pipe($handle,WRITE) || die "can't pipe";
+
+    $pid=fork();
+
+    die "can't fork" if ($pid<0);
+    if ($pid>0) {
+	# whe are in the parent
+	close(WRITE);
+	waitpid($pid,0) || print "$params[0] exits status=$? ",$? >> 8, "\n";
+    } else {
+	# we are in the son.
+	open(STDOUT,">&WRITE");
+	open(STDERR, ">&WRITE");
+	close($handle);
+	close(WRITE);
+	exec(@params);
+	exit(-1);
+    }
+    
+}
diff --git a/windows/Makefile.in b/windows/Makefile.in
new file mode 100644
index 0000000..3b0d318
--- /dev/null
+++ b/windows/Makefile.in
@@ -0,0 +1,54 @@
+CC 	= @CC@
+CFLAGS 	= @CFLAGS@
+XINCL 	= @x_includes@
+TOPSRC  = @top_srcdir@
+DIVINCL = -I$(TOPSRC)/include
+LD	= @LD@
+LDCOMBINEFLAGS = @LDCOMBINEFLAGS@
+
+
+MODULE 	= windows
+
+SRCS 	= caret.c class.c cursor.c dce.c defdlg.c defwnd.c dialog.c \
+	event.c focus.c graphics.c hook.c keyboard.c mapping.c mdi.c \
+	message.c msgbox.c nonclient.c painting.c property.c scroll.c \
+	syscolor.c sysmetrics.c timer.c utility.c win.c \
+	winpos.c
+ 
+
+OBJS = $(SRCS:.c=.o)
+
+.c.o:
+	$(CC) -c $(CFLAGS) $(XINCL) $(DIVINCL) -o $*.o $<
+
+all: $(MODULE).o
+
+$(MODULE).o: $(OBJS)
+	$(LD) $(LDCOMBINEFLAGS) $(OBJS) -o $(MODULE).o
+
+depend:
+	sed '/\#\#\# Dependencies/q' < Makefile > tmp_make
+	$(CC) $(DIVINCL) $(XINCL) -MM *.c >> tmp_make
+	cp tmp_make Makefile
+	rm tmp_make
+
+clean:
+	rm -f *.o \#*\# *~ tmp_make
+
+distclean: clean
+	rm Makefile
+
+countryclean:
+
+NAMES = $(SRCS:.c=)
+
+winelibclean:
+	for i in $(NAMES); do \
+	if test `grep -c WINELIB $$i.c` -ne 0; then \
+	rm $$i.o; \
+	fi; \
+	done
+ 
+dummy:
+
+### Dependencies:
diff --git a/windows/class.c b/windows/class.c
index 050d4e7..4c60a79 100644
--- a/windows/class.c
+++ b/windows/class.c
@@ -11,6 +11,7 @@
 #include "user.h"
 #include "win.h"
 #include "dce.h"
+#include "atom.h"
 #include "toolhelp.h"
 #include "stddebug.h"
 /* #define DEBUG_CLASS */
@@ -32,7 +33,7 @@
     HCLASS class;
     CLASS * classPtr;
 
-    if (!(atom = GlobalFindAtom( name ))) return 0;
+    if (!(atom = LocalFindAtom( name ))) return 0;
 
       /* First search task-specific classes */
 
@@ -122,7 +123,7 @@
     newClass->wc.cbWndExtra = (class->cbWndExtra < 0) ? 0 : class->cbWndExtra;
     newClass->wc.cbClsExtra = classExtra;
 
-    newClass->atomName = GlobalAddAtom( name );
+    newClass->atomName = LocalAddAtom( name );
     newClass->wc.lpszClassName = NULL; 
 
     if (newClass->wc.style & CS_CLASSDC)
@@ -183,7 +184,7 @@
       /* Delete the class */
     if (classPtr->hdce) DCE_FreeDCE( classPtr->hdce );
     if (classPtr->wc.hbrBackground) DeleteObject( classPtr->wc.hbrBackground );
-    /*if (classPtr->wc.style & CS_GLOBALCLASS)*/ GlobalDeleteAtom( classPtr->atomName );
+    /*if (classPtr->wc.style & CS_GLOBALCLASS)*/ LocalDeleteAtom( classPtr->atomName );
     /*else DeleteAtom( classPtr->atomName );*/
     if ((int)classPtr->wc.lpszMenuName & 0xffff0000)
 	USER_HEAP_FREE( (int)classPtr->wc.lpszMenuName & 0xffff );
@@ -264,7 +265,7 @@
     if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
     if (!(classPtr = CLASS_FindClassPtr(wndPtr->hClass))) return 0;
     
-    return GlobalGetAtomName(classPtr->atomName, lpClassName, maxCount);
+    return LocalGetAtomName(classPtr->atomName, lpClassName, maxCount);
 }
 
 
@@ -328,7 +329,7 @@
 
     pClassEntry->hInst = classPtr->wc.hInstance;
     pClassEntry->wNext = classPtr->hNext;
-    GlobalGetAtomName( classPtr->atomName, pClassEntry->szClassName,
+    LocalGetAtomName( classPtr->atomName, pClassEntry->szClassName,
                        sizeof(pClassEntry->szClassName) );
     return TRUE;
 }
diff --git a/windows/cursor.c b/windows/cursor.c
index 810dcf2..5a41d3c 100644
--- a/windows/cursor.c
+++ b/windows/cursor.c
@@ -18,9 +18,8 @@
 #include "neexe.h"
 #include "wine.h"
 #include "cursor.h"
+#include "resource.h"
 #include "stddebug.h"
-/* #define DEBUG_CURSOR   */
-/* #define DEBUG_RESOURCE */
 #include "debug.h"
 #include "arch.h"
 
@@ -191,7 +190,7 @@
       fprintf(stderr,"No bitmap for cursor?\n");
       lpcur->hBitmap = 0;
     }
-    lpl = (char *)lpl + size + 8;
+    lpl = (LONG *)((char *)lpl + size + 8);
   /* This is rather strange! The data is stored *BACKWARDS* and       */
   /* mirrored! But why?? FIXME: the image must be flipped at the Y    */
   /* axis, either here or in CreateCusor(); */
@@ -308,8 +307,13 @@
  */
 BOOL DestroyCursor(HCURSOR hCursor)
 {
+    int i;
     CURSORALLOC	*lpcur;
-    if (hCursor == (HCURSOR)NULL) return FALSE;
+    
+    if (hCursor == 0) return FALSE;
+    for (i = 0; i < NB_SYS_CURSORS; i++) {
+	if (system_cursor[i].cursor == hCursor) return TRUE;
+    }
     lpcur = (CURSORALLOC *)GlobalLock(hCursor);
     if (lpcur->hBitmap != (HBITMAP)NULL) DeleteObject(lpcur->hBitmap);
     GlobalUnlock(hCursor);
@@ -451,7 +455,3 @@
     if (lpRetClipRect != NULL)
 	CopyRect(lpRetClipRect, &ClipCursorRect);
 }
-
-
-
-
diff --git a/windows/defwnd.c b/windows/defwnd.c
index e5811fb..6263dd5 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -2,9 +2,7 @@
  * Default window procedure
  *
  * Copyright 1993 Alexandre Julliard
-
-static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
-*/
+ */
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -38,7 +36,6 @@
     strcpy( textPtr, text );
 }
 
-#include <assert.h>
 
 /***********************************************************************
  *           DefWindowProc   (USER.107)
@@ -206,7 +203,7 @@
 		textPtr = (LPSTR)USER_HEAP_LIN_ADDR(wndPtr->hText);
 		return (DWORD)strlen(textPtr);
 	    }
-	    return (0L);
+	    return 0;
 	}
 
     case WM_SETTEXT:
@@ -226,14 +223,13 @@
     case WM_SYSKEYDOWN:
 	if (wParam == VK_MENU)
 	{   /* Send to WS_OVERLAPPED parent. TODO: Handle MDI */
-	    HWND top;
-            for(top=hwnd;GetParent(top)!=0;top=GetParent(top));
-	    SendMessage( top, WM_SYSCOMMAND, SC_KEYMENU, 0L );
+	    SendMessage( WIN_GetTopParent(hwnd), WM_SYSCOMMAND,
+                         SC_KEYMENU, 0L );
 	}
 	break;
 
     case WM_SYSKEYUP:
-		break;
+        break;
     }
     return 0;
 }
diff --git a/windows/dialog.c b/windows/dialog.c
index b5b78a4..79116d4 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -415,7 +415,7 @@
     int retval;
 
       /* Owner must be a top-level window */
-    while (owner && GetParent(owner)) owner = GetParent(owner);
+    owner = WIN_GetTopParent( owner );
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return -1;
     if (!(msgHandle = USER_HEAP_ALLOC( sizeof(MSG) ))) return -1;
     lpmsg = (MSG *) USER_HEAP_LIN_ADDR( msgHandle );
diff --git a/windows/event.c b/windows/event.c
index 05c21ce..9803e0a 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -283,7 +283,8 @@
     char Str[24]; 
     XComposeStatus cs; 
     KeySym keysym;
-    WORD xkey, vkey, key_type, key;
+    WORD vkey = 0;
+    WORD xkey, key_type, key;
     KEYLP keylp;
     BOOL extended = FALSE;
 
diff --git a/windows/graphics.c b/windows/graphics.c
index bbc674b..d623752 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -19,6 +19,7 @@
 #include "syscolor.h"
 #include "stddebug.h"
 #include "color.h"
+#include "region.h"
 #include "debug.h"
 
 static __inline__ void swap_int(int *a, int *b)
@@ -626,6 +627,17 @@
     return retval;
 }
 
+/***********************************************************************
+ *           FrameRgn     (GDI.41)
+ */
+BOOL FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush, int nWidth, int nHeight )
+{
+    HRGN tmp = CreateRectRgn( 0, 0, 0, 0 );
+    if(!REGION_FrameRgn( tmp, hrgn, nWidth, nHeight )) return 0;
+    FillRgn( hdc, tmp, hbrush );
+    DeleteObject( tmp );
+    return 1;
+}
 
 /***********************************************************************
  *           InvertRgn    (GDI.42)
diff --git a/windows/mdi.c b/windows/mdi.c
index 85b49b5..aa67bf0 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -15,7 +15,6 @@
 #include "menu.h"
 #include "sysmetrics.h"
 #include "stddebug.h"
-/* #define DEBUG_MDI */
 #include "debug.h"
 
 /**********************************************************************
@@ -61,6 +60,21 @@
     }
 }
 
+/**********************************************************************
+ *					MDISetMenu
+ * FIXME: This is not complete.
+ */
+HMENU MDISetMenu(HWND hwnd, BOOL fRefresh, HMENU hmenuFrame, HMENU hmenuWindow)
+{
+    dprintf_mdi(stddeb, "WM_MDISETMENU: %04x %04x %04x %04x\n", hwnd, fRefresh, hmenuFrame, hmenuWindow);
+    if (!fRefresh) {
+	HWND hwndFrame = GetParent(hwnd);
+	HMENU oldFrameMenu = GetMenu(hwndFrame);
+	SetMenu(hwndFrame, hmenuFrame);
+	return oldFrameMenu;
+    }
+    return 0;
+}
 
 /**********************************************************************
  *					MDIIconArrange
@@ -666,8 +680,7 @@
 	return MDIRestoreChild(hwnd, ci);
 
       case WM_MDISETMENU:
-	/* return MDISetMenu(...) */
-	break;
+	return MDISetMenu(hwnd, wParam, LOWORD(lParam), HIWORD(lParam));
 	
       case WM_MDITILE:
 	return MDITile(hwnd, ci);
diff --git a/windows/message.c b/windows/message.c
index 37a869c..957f611 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -7,15 +7,17 @@
 #include <stdlib.h>
 #include <sys/time.h>
 #include <sys/types.h>
+#include <errno.h>
 
 #include "message.h"
 #include "win.h"
 #include "gdi.h"
-#include "wineopts.h"
 #include "sysmetrics.h"
 #include "hook.h"
 #include "event.h"
 #include "winpos.h"
+#include "atom.h"
+#include "dde.h"
 #include "stddebug.h"
 /* #define DEBUG_MSG */
 #include "debug.h"
@@ -26,6 +28,15 @@
 #define MAX_QUEUE_SIZE   120  /* Max. size of a message queue */
 
 
+/* used for passing message information when sending message */ 
+typedef struct {
+    LONG lParam;
+    WORD wParam;
+    WORD wMsg;
+    WORD hWnd;
+} msgstruct;
+
+
 extern BOOL TIMER_CheckTimer( LONG *next, MSG *msg,
 			      HWND hwnd, BOOL remove );  /* timer.c */
 
@@ -135,6 +146,8 @@
 {
     int i, pos = msgQueue->nextMessage;
 
+    dprintf_msg(stddeb,"MSG_FindMsg: hwnd=0x%04x, proc=%d\n",
+		hwnd, curr_proc_idx);
     if (!msgQueue->msgCount) return -1;
     if (!hwnd && !first && !last) return pos;
         
@@ -191,7 +204,8 @@
 {
     WND *wndPtr;
     HWND hwnd;
-    INT hittest, x, y;
+    INT hittest = HTERROR;
+    INT x, y;
 
     *phwnd = hwnd = GetDesktopWindow();
     x = pt.x;
@@ -212,11 +226,11 @@
             (y < wndPtr->rectWindow.bottom))
 	{
 	    *phwnd = hwnd;
+	    x -= wndPtr->rectClient.left;
+	    y -= wndPtr->rectClient.top;
               /* If window is minimized or disabled, ignore its children */
             if ((wndPtr->dwStyle & WS_MINIMIZE) ||
                 (wndPtr->dwStyle & WS_DISABLED)) break;
-	    x -= wndPtr->rectClient.left;
-	    y -= wndPtr->rectClient.top;
 	    hwnd = wndPtr->hwndChild;
 	}
 	else hwnd = wndPtr->hwndNext;
@@ -276,7 +290,7 @@
 static BOOL MSG_TranslateMouseMsg( MSG *msg, BOOL remove )
 {
     BOOL eatMsg = FALSE;
-    INT hittest_result;
+    INT hittest;
     static DWORD lastClickTime = 0;
     static WORD  lastClickMsg = 0;
     static POINT lastClickPos = { 0, 0 };
@@ -294,38 +308,40 @@
 	ScreenToClient( msg->hwnd, (LPPOINT)&msg->lParam );
 	return TRUE;  /* No need to further process the message */
     }
-    else hittest_result = MSG_GetWindowForEvent( msg->pt, &msg->hwnd );
-
-      /* Send the WM_PARENTNOTIFY message */
-
-    if (mouseClick) WIN_SendParentNotify( msg->hwnd, msg->message,
-					  MAKELONG( msg->pt.x, msg->pt.y ) );
-
-      /* Activate the window if needed */
-
-    if (mouseClick)
+   
+    if ((hittest = MSG_GetWindowForEvent( msg->pt, &msg->hwnd )) != HTERROR)
     {
-	HWND parent, hwndTop = msg->hwnd;	
-	while ((parent = GetParent(hwndTop)) != 0) hwndTop = parent;
-	if (hwndTop != GetActiveWindow())
-	{
-	    LONG ret = SendMessage( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
-				    MAKELONG( hittest_result, msg->message ) );
-	    if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
-		eatMsg = TRUE;
-	    if ((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT))
-	    {
-		SetWindowPos( hwndTop, HWND_TOP, 0, 0, 0, 0,
-			      SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
-		WINPOS_ChangeActiveWindow( hwndTop, TRUE );
-	    }
-	}
+
+        /* Send the WM_PARENTNOTIFY message */
+
+        if (mouseClick) WIN_SendParentNotify( msg->hwnd, msg->message,
+                                            MAKELONG( msg->pt.x, msg->pt.y ) );
+
+        /* Activate the window if needed */
+
+        if (mouseClick)
+        {
+            HWND hwndTop = WIN_GetTopParent( msg->hwnd );
+            if (hwndTop != GetActiveWindow())
+            {
+                LONG ret = SendMessage( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
+                                        MAKELONG( hittest, msg->message ) );
+                if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
+                    eatMsg = TRUE;
+                if ((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT))
+                {
+                    SetWindowPos( hwndTop, HWND_TOP, 0, 0, 0, 0,
+                                 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
+                    WINPOS_ChangeActiveWindow( hwndTop, TRUE );
+                }
+            }
+        }
     }
 
       /* Send the WM_SETCURSOR message */
 
     SendMessage( msg->hwnd, WM_SETCURSOR, msg->hwnd,
-		 MAKELONG( hittest_result, msg->message ));
+                 MAKELONG( hittest, msg->message ));
     if (eatMsg) return FALSE;
 
       /* Check for double-click */
@@ -340,7 +356,7 @@
 	    (abs(msg->pt.y - lastClickPos.y) < SYSMETRICS_CYDOUBLECLK/2))
 	    dbl_click = TRUE;
 
-	if (dbl_click && (hittest_result == HTCLIENT))
+	if (dbl_click && (hittest == HTCLIENT))
 	{
 	    /* Check whether window wants the double click message. */
 	    WND * wndPtr = WIN_FindWndPtr( msg->hwnd );
@@ -366,13 +382,13 @@
       /* Build the translated message */
 
     msg->lParam = MAKELONG( msg->pt.x, msg->pt.y );
-    if (hittest_result == HTCLIENT)
+    if (hittest == HTCLIENT)
     {
 	ScreenToClient( msg->hwnd, (LPPOINT)&msg->lParam );
     }
     else
     {
-	msg->wParam = hittest_result;
+	msg->wParam = hittest;
 	msg->message += WM_NCLBUTTONDOWN - WM_LBUTTONDOWN;
     }
     
@@ -713,19 +729,43 @@
     XEvent event;
     int fd = ConnectionNumber(display);
 
-    if (!XPending(display) && (maxWait != -1))
+    if (!XPending(display))
     {
         FD_ZERO( &read_set );
         FD_SET( fd, &read_set );
-        timeout.tv_sec = maxWait / 1000;
-        timeout.tv_usec = (maxWait % 1000) * 1000;
-        if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1)
-            return FALSE;  /* Timeout or error */
+	sigsetjmp(env_wait_x, 1);
+	
+	stop_wait_op= CONT;
+	    
+	if (DDE_GetRemoteMessage()) {
+	    while(DDE_GetRemoteMessage())
+		;
+	    return TRUE;
+	}
+
+	timeout.tv_usec = (maxWait % 1000) * 1000;
+	timeout.tv_sec = maxWait / 1000;
+
+	stop_wait_op= STOP_WAIT_X;
+	/* The code up to the next "stop_wait_op= CONT" must be reentrant  */
+	if (select( fd+1, &read_set, NULL, NULL, &timeout ) != 1 &&
+	    !XPending(display)) {
+	    stop_wait_op= CONT;
+	    return FALSE;
+	} else {
+	    stop_wait_op= CONT;
+	}
+	    
     }
 
     /* Process the event (and possibly others that occurred in the meantime) */
     do
     {
+	if (DDE_GetRemoteMessage()) {
+	    while(DDE_GetRemoteMessage())
+		;
+	    return TRUE;
+	}
         XNextEvent( display, &event );
         EVENT_ProcessEvent( &event );
     }
@@ -744,6 +784,9 @@
     MESSAGEQUEUE *msgQueue;
     LONG nextExp;  /* Next timer expiration time */
 
+    DDE_TestDDE(hwnd);	/* do we have dde handling in the window ?*/
+    DDE_GetRemoteMessage();
+    
     if (first || last)
     {
 	mask = QS_POSTMESSAGE;  /* Always selectioned */
@@ -918,6 +961,17 @@
     MSG 	msg;
     WND 	*wndPtr;
 
+    msg.hwnd    = hwnd;
+    msg.message = message;
+    msg.wParam  = wParam;
+    msg.lParam  = lParam;
+    msg.time    = GetTickCount();
+    msg.pt.x    = 0;
+    msg.pt.y    = 0;
+
+    if (DDE_PostMessage(&msg))
+       return TRUE;
+    
     if (hwnd == HWND_BROADCAST) {
       dprintf_msg(stddeb,"PostMessage // HWND_BROADCAST !\n");
       hwnd = GetTopWindow(GetDesktopWindow());
@@ -928,11 +982,6 @@
 		      hwnd, message, wParam, lParam);
 	  PostMessage(hwnd, message, wParam, lParam);
 	}
-	/*{
-	  char	str[128];
-	  GetWindowText(hwnd, str, sizeof(str));
-	  dprintf_msg(stddeb, "BROADCAST GetWindowText()='%s' !\n", str); 
-	}*/
 	hwnd = wndPtr->hwndNext;
       }
       dprintf_msg(stddeb,"PostMessage // End of HWND_BROADCAST !\n");
@@ -941,13 +990,6 @@
 
     wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr || !wndPtr->hmemTaskQ) return FALSE;
-    msg.hwnd    = hwnd;
-    msg.message = message;
-    msg.wParam  = wParam;
-    msg.lParam  = lParam;
-    msg.time    = GetTickCount();
-    msg.pt.x    = 0;
-    msg.pt.y    = 0;
 
     return MSG_AddMsg( wndPtr->hmemTaskQ, &msg, 0 );
 }
@@ -979,35 +1021,48 @@
 {
     WND * wndPtr;
     LONG ret;
-
-    wndPtr = WIN_FindWndPtr( hwnd );
-    if (!wndPtr) return 0;
-    else {
-      /* Argh. This is inefficient. */
-      typedef struct {
+    MSG DDE_msg;
+    struct
+    {
 	LONG lParam;
 	WORD wParam;
 	WORD wMsg;
 	WORD hWnd;
-      } msgstruct;
-      HANDLE msgh    = GlobalAlloc(0,sizeof(msgstruct));
-      SEGPTR segmsg  = WIN16_GlobalLock(msgh);
-      msgstruct *Msg = PTR_SEG_TO_LIN(segmsg);
-    
-      Msg->hWnd    = hwnd;
-      Msg->wMsg    = msg;
-      Msg->wParam  = wParam;
-      Msg->lParam  = lParam;
-      CALL_SYSTEM_HOOK( WH_CALLWNDPROC, 0, 0, (LPARAM)segmsg );
-      CALL_TASK_HOOK( WH_CALLWNDPROC, 0, 0, (LPARAM)segmsg );
-      ret = CallWindowProc( wndPtr->lpfnWndProc, Msg->hWnd, Msg->wMsg, Msg->wParam,
-			   Msg->lParam );
-      GlobalUnlock(msgh);
-      GlobalFree(msgh);
-      dprintf_msg( stddeb,"SendMessage(%4.4x,%x,%x,%lx) -> %lx\n",
-		  hwnd, msg, wParam, lParam, ret );
-      return ret;
+    } msgstruct = { lParam, wParam, msg, hwnd };
+
+    DDE_msg.hwnd    = hwnd;
+    DDE_msg.message = msg;
+    DDE_msg.wParam  = wParam;
+    DDE_msg.lParam  = lParam;
+    if (DDE_SendMessage(&DDE_msg)) return TRUE;
+
+    if (hwnd == HWND_BROADCAST)
+    {
+        dprintf_msg(stddeb,"SendMessage // HWND_BROADCAST !\n");
+        hwnd = GetTopWindow(GetDesktopWindow());
+        while (hwnd)
+	{
+            if (!(wndPtr = WIN_FindWndPtr(hwnd))) break;
+            if (wndPtr->dwStyle & WS_POPUP || wndPtr->dwStyle & WS_CAPTION)
+            {
+                dprintf_msg(stddeb,"BROADCAST Message to hWnd=%04X m=%04X w=%04X l=%08lX !\n",
+                            hwnd, msg, wParam, lParam);
+                 ret |= SendMessage( hwnd, msg, wParam, lParam );
+	    }
+            hwnd = wndPtr->hwndNext;
+        }
+        dprintf_msg(stddeb,"SendMessage // End of HWND_BROADCAST !\n");
+        return TRUE;
     }
+
+    CALL_SYSTEM_HOOK( WH_CALLWNDPROC, 0, 0, MAKE_SEGPTR(&msgstruct) );
+    CALL_TASK_HOOK( WH_CALLWNDPROC, 0, 0, MAKE_SEGPTR(&msgstruct) );
+    if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return 0;
+    ret = CallWindowProc( wndPtr->lpfnWndProc, msgstruct.hWnd, msgstruct.wMsg,
+                          msgstruct.wParam, msgstruct.lParam );
+    dprintf_msg( stddeb,"SendMessage(%4.4x,%x,%x,%lx) -> %lx\n",
+                 hwnd, msg, wParam, lParam, ret );
+    return ret;
 }
 
 
@@ -1020,6 +1075,8 @@
     MESSAGEQUEUE *queue;
     LONG nextExp = -1;  /* Next timer expiration time */
 
+    DDE_GetRemoteMessage();
+    
     if (!(queue = (MESSAGEQUEUE *)GlobalLock( GetTaskQueue(0) ))) return;
     if ((queue->wPostQMsg) || 
         (queue->status & (QS_SENDMESSAGE | QS_PAINT)) ||
@@ -1028,6 +1085,7 @@
     if ((queue->status & QS_TIMER) && 
         TIMER_CheckTimer( &nextExp, &msg, 0, FALSE))
         return;
+    /* FIXME: (dde) must check DDE & X-events simultaneously */
     MSG_WaitXEvent( nextExp );
 }
 
@@ -1066,8 +1124,12 @@
     if ((msg->message == WM_TIMER) || (msg->message == WM_SYSTIMER))
     {
 	if (msg->lParam)
-	    return CallWndProc( (WNDPROC)msg->lParam, CURRENT_DS, msg->hwnd,
-				   msg->message, msg->wParam, GetTickCount() );
+        {
+            WORD ds = msg->hwnd ? GetWindowWord( msg->hwnd, GWW_HINSTANCE )
+                                : CURRENT_DS;
+	    return CallWndProc( (WNDPROC)msg->lParam, ds, msg->hwnd,
+                                msg->message, msg->wParam, GetTickCount() );
+        }
     }
 
     if (!msg->hwnd) return 0;
@@ -1131,7 +1193,7 @@
 {
 	WORD	wRet;
     dprintf_msg(stddeb, "RegisterWindowMessage: '%s'\n", str );
-	wRet = GlobalAddAtom( str );
+	wRet = LocalAddAtom( str );
     return wRet;
 }
 
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 8af8dd3..a192262 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -10,6 +10,7 @@
 #include "message.h"
 #include "sysmetrics.h"
 #include "user.h"
+#include "shell.h"
 #include "dialog.h"
 #include "syscolor.h"
 #include "menu.h"
@@ -152,7 +153,10 @@
     MinMax.ptMaxSize.x += 2 * xinc;
     MinMax.ptMaxSize.y += 2 * yinc;
 
-    if ((wndPtr->ptMaxPos.x != -1) || (wndPtr->ptMaxPos.y != -1))
+    /* Note: The '+' in the following test should really be a ||, but
+     * that would cause gcc-2.7.0 to generate incorrect code.
+     */
+    if ((wndPtr->ptMaxPos.x != -1) + (wndPtr->ptMaxPos.y != -1))
         MinMax.ptMaxPosition = wndPtr->ptMaxPos;
     else
     {
diff --git a/windows/painting.c b/windows/painting.c
index e29056e..b188ac3 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -124,7 +124,7 @@
 
     if (!hwnd) hwnd = GetDesktopWindow();
     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
-    if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
+    if (!IsWindowVisible(hwnd) || (wndPtr->flags & WIN_NO_REDRAW))
         return TRUE;  /* No redraw needed */
 
     if (rectUpdate)
diff --git a/windows/timer.c b/windows/timer.c
index 96fff6a..88b7073 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -114,6 +114,8 @@
 	TIMER_RestartTimer( pTimer, curTime );
     }
 
+    dprintf_timer(stddeb, "Timer expired: %p, %04x, %04x, %04x, %08lx\n", 
+		  pTimer, pTimer->hwnd, pTimer->msg, pTimer->id, pTimer->proc);
       /* Build the message */
     msg->hwnd    = pTimer->hwnd;
     msg->message = pTimer->msg;
@@ -168,6 +170,8 @@
     pTimer->timeout = timeout;
     pTimer->expires = GetTickCount() + timeout;
     pTimer->proc    = proc;
+    dprintf_timer(stddeb, "Timer added: %p, %04x, %04x, %04x, %08lx\n", 
+		  pTimer, pTimer->hwnd, pTimer->msg, pTimer->id, pTimer->proc);
     TIMER_InsertTimer( pTimer );
     MSG_IncTimerCount( GetTaskQueue(0) );
     if (!id)
diff --git a/windows/win.c b/windows/win.c
index aad3546..de84af9 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -21,6 +21,8 @@
 #include "nonclient.h"
 #include "winpos.h"
 #include "color.h"
+#include "shm_main_blk.h"
+#include "dde_proc.h"
 #include "callback.h"
 #include "stddebug.h"
 /* #define DEBUG_WIN  */ 
@@ -165,14 +167,14 @@
  */
 void WIN_SendParentNotify( HWND hwnd, WORD event, LONG lParam )
 {
-    HWND current = GetParent( hwnd );
     WND *wndPtr = WIN_FindWndPtr( hwnd );
     
-    if (!wndPtr || (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY)) return;
-    while (current)
+    while (wndPtr && (wndPtr->dwStyle & WS_CHILD))
     {
-	SendMessage( current, WM_PARENTNOTIFY, event, lParam );
-	current = GetParent( current );
+        if (wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) break;
+	SendMessage( wndPtr->hwndParent, WM_PARENTNOTIFY, event, lParam );
+        wndPtr = WIN_FindWndPtr( wndPtr->hwndParent );
+
     }
 }
 
@@ -187,6 +189,9 @@
     WND *wndPtr = WIN_FindWndPtr( hwnd );
     CLASS *classPtr = CLASS_FindClassPtr( wndPtr->hClass );
 
+    if (main_block)
+	DDE_DestroyWindow(hwnd);
+	
     if (!wndPtr || !classPtr) return;
     WIN_UnlinkWindow( hwnd ); /* Remove the window from the linked list */
     wndPtr->dwMagic = 0;  /* Mark it as invalid */
@@ -364,7 +369,7 @@
     wndPtr->window         = 0;
     wndPtr->dwMagic        = WND_MAGIC;
     wndPtr->hwndParent     = (style & WS_CHILD) ? parent : hwndDesktop;
-    wndPtr->hwndOwner      = (style & WS_CHILD) ? 0 : parent;
+    wndPtr->hwndOwner      = (style & WS_CHILD) ? 0 : WIN_GetTopParent(parent);
     wndPtr->hClass         = class;
     wndPtr->hInstance      = instance;
     wndPtr->ptIconPos.x    = -1;
@@ -390,11 +395,6 @@
 	memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
     classPtr->cWindows++;
 
-      /* Make sure owner is a top-level window */
-
-    while (wndPtr->hwndOwner && GetParent(wndPtr->hwndOwner))
-        wndPtr->hwndOwner = GetParent(wndPtr->hwndOwner);
-
       /* Get class or window DC if needed */
 
     if (classPtr->wc.style & CS_OWNDC)
@@ -844,10 +844,29 @@
 HWND GetParent(HWND hwnd)
 {
     WND *wndPtr = WIN_FindWndPtr(hwnd);
-    if (!wndPtr || !(wndPtr->dwStyle & WS_CHILD)) return 0;
-    return wndPtr->hwndParent;
+    if (!wndPtr) return 0;
+    return (wndPtr->dwStyle & WS_CHILD) ?
+            wndPtr->hwndParent : wndPtr->hwndOwner;
 }
 
+
+/*****************************************************************
+ *         WIN_GetTopParent
+ *
+ * Get the top-level parent for a child window.
+ */
+HWND WIN_GetTopParent( HWND hwnd )
+{
+    while (hwnd)
+    {
+        WND *wndPtr = WIN_FindWndPtr( hwnd );
+        if (wndPtr->dwStyle & WS_CHILD) hwnd = wndPtr->hwndParent;
+        else break;
+    }
+    return hwnd;
+}
+
+
 /*****************************************************************
  *         SetParent              (USER.233)
  */
@@ -984,6 +1003,20 @@
     return GetWindow( hwnd, flag );
 }
 
+/*******************************************************************
+ *         ShowOwnedPopups  (USER.265)
+ */
+void ShowOwnedPopups( HWND owner, BOOL fShow )
+{
+    HWND hwnd = GetWindow( hwndDesktop, GW_CHILD );
+    while (hwnd)
+    {
+        WND *wnd = WIN_FindWndPtr(hwnd);
+        if (wnd->hwndOwner == owner && (wnd->dwStyle & WS_POPUP))
+            ShowWindow( hwnd, fShow ? SW_SHOW : SW_HIDE );
+        hwnd = wnd->hwndNext;
+    }
+}
 
 
 /*******************************************************************
@@ -1015,7 +1048,7 @@
       /* First count the windows */
 
     count = 0;
-    for (hwnd = hwndDesktop; hwnd != 0; hwnd = wndPtr->hwndNext)
+    for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
     {
         if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
         count++;
@@ -1025,7 +1058,7 @@
       /* Now build the list of all windows */
 
     if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
-    for (hwnd = hwndDesktop, pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
+    for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
     {
         wndPtr = WIN_FindWndPtr( hwnd );
         *pWnd++ = hwnd;
@@ -1061,7 +1094,7 @@
       /* First count the windows */
 
     count = 0;
-    for (hwnd = hwndDesktop; hwnd != 0; hwnd = wndPtr->hwndNext)
+    for (hwnd = GetTopWindow(hwndDesktop); hwnd != 0; hwnd = wndPtr->hwndNext)
     {
         if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
         if (wndPtr->hmemTaskQ == hQueue) count++;
@@ -1071,7 +1104,7 @@
       /* Now build the list of all windows */
 
     if (!(list = (HWND *)malloc( sizeof(HWND) * count ))) return FALSE;
-    for (hwnd = hwndDesktop, pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
+    for (hwnd = GetTopWindow(hwndDesktop), pWnd = list; hwnd != 0; hwnd = wndPtr->hwndNext)
     {
         wndPtr = WIN_FindWndPtr( hwnd );
         if (wndPtr->hmemTaskQ == hQueue) *pWnd++ = hwnd;
diff --git a/windows/winpos.c b/windows/winpos.c
index b241afc..577221d 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -773,7 +773,8 @@
         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
       /* hwndInsertAfter must be a sibling of the window */
     if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM) &&
-	(GetParent(hwnd) != GetParent(hwndInsertAfter))) return FALSE;
+	(wndPtr->hwndParent != WIN_FindWndPtr(hwndInsertAfter)->hwndParent))
+        return FALSE;
 
       /* Fill the WINDOWPOS structure */
 
@@ -965,14 +966,16 @@
     DWP *pDWP;
     int i;
     HDWP newhdwp = hdwp;
+    HWND parent;
 
     pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
     if (!pDWP) return 0;
 
       /* All the windows of a DeferWindowPos() must have the same parent */
 
-    if (pDWP->actualCount == 0) pDWP->hwndParent = GetParent( hwnd );
-    else if (GetParent( hwnd ) != pDWP->hwndParent)
+    parent = WIN_FindWndPtr( hwnd )->hwndParent;
+    if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
+    else if (parent != pDWP->hwndParent)
     {
         USER_HEAP_FREE( hdwp );
         return 0;