Release 950403

Sun Apr  2 18:31:12 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)

	* [Configure] [if1632/Imakefile]
	Removed new build and short names options.

	* [if1632/*.c] [tools/build.c]
	Implemented compiled call-back functions for better performance;
	all the relay code is now done in assembly code generated by the
	build program.
	Relay code is no longer dependent on being loaded below 64K.

	* [loader/resource.c]
	Fixed memory leak in LoadString(). A fix will also be needed for
	other resources.

	* [memory/global.c]
	Implemented global heap arenas, so we can store informations about
	global blocks, like lock counts or owner handle.
	Implemented FarGetOwner() and FarSetOwner().
	Implemented global heap TOOLHELP functions.

	* [memory/selector.c]
	Bug fix: it was not possible to re-use a free selector.

Sun Apr 2 01:34:52 1995 Constantine Sapuntzakis  (csapuntz@mit.edu)

	*  [controls/listbox.c]
	Major work on listbox code
         - Many bugs fixed (still many bugs)
         - More messages supported
         - Code simplified

Fri Mar 31 03:27:16 EST 1995 William Magro (wmagro@tc.cornell.edu)

	* [controls/edit.c]
	Lots of bug fixes related to diappearing text, lost carets,
	highlighting, segmentation faults, occurance of random
	characters, insertion of characters over selection, misplaced
	caret location, display corruption, end of line behavior, etc.

	* [controls/widgets.c]
	EDIT class doesn't want to use CS_PARENTDC flag.

Thu Mar 30 20:58:25 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
        
	* [loader/selector.c]
	  FixupFunctionPrologs() should also handle multiple data modules.
	  (this bug only became visible because MakeProcInstance() was fixed
	  in 950319)
	
	* [misc/dosfs.c]
	  Simplified DOS_SimplifyPath.
	  Small fix to DOS_opendir to reuse an entry if an open directory
	  is opened again, to prevent "too many open directories" messages.

Thu Mar 30 12:05:05 1995 Martin von Loewis  <loewis@informatik.hu-berlin.de>

	* [if1632/compobj.spec][include/compobj.h][misc/compobj.c]
	CoDisconnectObject: new stub function

	* [include/msdos.h]
	fix DOSVERSION

	* [loader/ne_image.c]
	NE_FixupSegment: Be more generous on additive fixups

	* [if1632/user.spec][misc/network.c]
	Add more WNet* stubs

Wed Mar 29 11:47:22 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

        * [controls/listbox.c]
	  DlgDirList(): send segptr instead of linear pointer 
	  in message to static control
	* [controls/menu.c]
	  Tried to implement ownerdrawn menuitems. Doesn't work.
	* [if1632/gdi.spec] [include/windows.h] [objects/font.c]
	  Provide a stub for GetRasterizerCaps()
	* [loader/selector.c]
	  Pass end address instead of length to LocalInit() in 
	  CreateSelectors()
	* [memory/local.c]
	  LocalInit(): If there's already a local heap in the segment, do
	  nothing and return TRUE
	* [objects/linedda.c]
	  Replaced buggy LineDDA() with a Bresenham algorithm. Should work
	  now.
	* [windows/cursor.c]
	  LoadCursor()/CreateCursor(): Cleaned up the mess. Needs some
	  more work still.

Tue Mar 21 17:54:43 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

        * [if1632/relay.c] [if1632/callback.c] [include/dlls.h]
	  [if1632/winprocs.spec] [if1632/winprocs.c] [include/winprocs.h]
	  [controls/widgets.c] [misc/shell.c] [misc/commdlg.c]
	  [windows/nonclient.c] [misc/message.c]
	  Added a new builtin DLL that provides 16 bit entry points for all
	  the Def*Procs (DefDlgProc, ButtonProc etc.). OWL programs work
	  again.
	* [misc/shell.c]
	  RegOpenKey()/RegCreateKey() bugs fixed.
        * [loader/ne_image.c]
	  Skipping the initialization of a DLL when CS == 0 was broken.
diff --git a/ANNOUNCE b/ANNOUNCE
index 8b5e519..f1033c9 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,17 +1,17 @@
-This is release 950319 of Wine the MS Windows emulator.  This is still a
+This is release 950403 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-950319: (see ChangeLog for details)
-	- New memory management scheme. This will probably cause many
-	  new problems, please report them. I'm particularly interested
-	  to hear how it works for the *BSD people.
-	- Many fixes in file and directory handling.
-	- Handling of additive fixup records.
-	- Lots of bug fixes
+WHAT'S NEW with Wine-950403: (see ChangeLog for details)
+	- Compiled callbacks for better performance.
+	- Many listbox fixes.
+	- Many edit control fixes.
+	- 16-bit entry points for built-in window procedures to make
+	  Borland programs happy.
+	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
 
@@ -19,10 +19,10 @@
 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-950319.tar.gz
-    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950319.tar.gz
-    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950319.tar.gz
-    ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950319.tar.gz
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-950403.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950403.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-950403.tar.gz
+    ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950403.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index 1f66b98..dae439c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,110 @@
 ----------------------------------------------------------------------
+Sun Apr  2 18:31:12 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)
+
+	* [Configure] [if1632/Imakefile]
+	Removed new build and short names options.
+
+	* [if1632/*.c] [tools/build.c]
+	Implemented compiled call-back functions for better performance;
+	all the relay code is now done in assembly code generated by the
+	build program.
+	Relay code is no longer dependent on being loaded below 64K.
+
+	* [loader/resource.c]
+	Fixed memory leak in LoadString(). A fix will also be needed for
+	other resources.
+
+	* [memory/global.c]
+	Implemented global heap arenas, so we can store informations about
+	global blocks, like lock counts or owner handle.
+	Implemented FarGetOwner() and FarSetOwner().
+	Implemented global heap TOOLHELP functions.
+
+	* [memory/selector.c]
+	Bug fix: it was not possible to re-use a free selector.
+
+Sun Apr 2 01:34:52 1995 Constantine Sapuntzakis  (csapuntz@mit.edu)
+
+	*  [controls/listbox.c]
+	Major work on listbox code
+         - Many bugs fixed (still many bugs)
+         - More messages supported
+         - Code simplified
+
+Fri Mar 31 03:27:16 EST 1995 William Magro (wmagro@tc.cornell.edu)
+
+	* [controls/edit.c]
+	Lots of bug fixes related to diappearing text, lost carets,
+	highlighting, segmentation faults, occurance of random
+	characters, insertion of characters over selection, misplaced
+	caret location, display corruption, end of line behavior, etc.
+
+	* [controls/widgets.c]
+	EDIT class doesn't want to use CS_PARENTDC flag.
+
+Thu Mar 30 20:58:25 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+        
+	* [loader/selector.c]
+	  FixupFunctionPrologs() should also handle multiple data modules.
+	  (this bug only became visible because MakeProcInstance() was fixed
+	  in 950319)
+	
+	* [misc/dosfs.c]
+	  Simplified DOS_SimplifyPath.
+	  Small fix to DOS_opendir to reuse an entry if an open directory
+	  is opened again, to prevent "too many open directories" messages.
+
+Thu Mar 30 12:05:05 1995 Martin von Loewis  <loewis@informatik.hu-berlin.de>
+
+	* [if1632/compobj.spec][include/compobj.h][misc/compobj.c]
+	CoDisconnectObject: new stub function
+
+	* [include/msdos.h]
+	fix DOSVERSION
+
+	* [loader/ne_image.c]
+	NE_FixupSegment: Be more generous on additive fixups
+
+	* [if1632/user.spec][misc/network.c]
+	Add more WNet* stubs
+
+Wed Mar 29 11:47:22 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+        * [controls/listbox.c]
+	  DlgDirList(): send segptr instead of linear pointer 
+	  in message to static control
+	* [controls/menu.c]
+	  Tried to implement ownerdrawn menuitems. Doesn't work.
+	* [if1632/gdi.spec] [include/windows.h] [objects/font.c]
+	  Provide a stub for GetRasterizerCaps()
+	* [loader/selector.c]
+	  Pass end address instead of length to LocalInit() in 
+	  CreateSelectors()
+	* [memory/local.c]
+	  LocalInit(): If there's already a local heap in the segment, do
+	  nothing and return TRUE
+	* [objects/linedda.c]
+	  Replaced buggy LineDDA() with a Bresenham algorithm. Should work
+	  now.
+	* [windows/cursor.c]
+	  LoadCursor()/CreateCursor(): Cleaned up the mess. Needs some
+	  more work still.
+
+Tue Mar 21 17:54:43 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+        * [if1632/relay.c] [if1632/callback.c] [include/dlls.h]
+	  [if1632/winprocs.spec] [if1632/winprocs.c] [include/winprocs.h]
+	  [controls/widgets.c] [misc/shell.c] [misc/commdlg.c]
+	  [windows/nonclient.c] [misc/message.c]
+	  Added a new builtin DLL that provides 16 bit entry points for all
+	  the Def*Procs (DefDlgProc, ButtonProc etc.). OWL programs work
+	  again.
+	* [misc/shell.c]
+	  RegOpenKey()/RegCreateKey() bugs fixed.
+        * [loader/ne_image.c]
+	  Skipping the initialization of a DLL when CS == 0 was broken.
+
+----------------------------------------------------------------------
 Sun Mar 19 16:30:20 1995  Alexandre Julliard  (julliard@sunsite.unc.edu)
 
 	* [*/*]
diff --git a/Configure b/Configure
index b1b4a6d..892e481 100644
--- a/Configure
+++ b/Configure
@@ -6,9 +6,7 @@
 : ${PAGER:=more}
 
 WINELIB=''
-SHORTNAMES=''
 LANGUAGE=not_matching
-NEWBUILD=''
 ALLDEFINES=''
 
 # Ask question 'str' and set 'var' to reply (defaulting to 'def' on CR)
@@ -28,6 +26,7 @@
 	fi
 }
 
+echo
 echo Read the RELEASE-NOTES for an explanation of the various flags
 echo
 
@@ -39,15 +38,6 @@
 	ALLDEFINES="$ALLDEFINES -DWINELIB"
 fi
 
-echo
-echo -n 'Short filenames (Y/N) [N]? '
-read input
-if [ "$input" = 'y' -o "$input" = 'Y' ]
-then
-	SHORTNAMES='#define ShortNames -DSHORTNAMES'
-	ALLDEFINES="$ALLDEFINES -DSHORTNAMES"
-fi
-
 LANGS=`echo En rc/sysres_*.rc | sed -e 's/rc\/sysres_//g' -e 's/\.rc//g' -e 's/ /\//g;'`
 while	expr "$LANGS" : ".*$LANGUAGE" = 0 > /dev/null
 do
@@ -68,18 +58,6 @@
        MALLOC_DEBUGGING=''
 fi
 
-if [ "`(domainname)`" = 'amscons.com' ]
-then
-	echo
-	echo -n 'New build program (Y/N) [N]? '
-	read input
-	if [ "$input" = 'y' -o "$input" = 'Y' ]
-	then
-		NEWBUILD='#define NewBuild -DNEWBUILD'
-		ALLDEFINES="$ALLDEFINES -DNEWBUILD"
-	fi
-fi
-
 prompt "Global configfile name" WINE_CONFIGFILE /usr/local/etc/wine.conf
 
 if [ -r $WINE_CONFIGFILE ]
@@ -197,8 +175,6 @@
 cat > autoconf.h << EOF
 /* autoconf.h generated automatically.  Run Configure. */
 $WINELIB
-$SHORTNAMES
-$NEWBUILD
 $MALLOC_DEBUGGING
 #define WINE_INI_GLOBAL "$WINE_CONFIGFILE"
 #define AutoDefines $ALLDEFINES
diff --git a/Imakefile b/Imakefile
index 8405d0a..33ee887 100644
--- a/Imakefile
+++ b/Imakefile
@@ -58,13 +58,9 @@
 	rc/rc.o \
 	windows/windows.o
 
-/*
- * WARNING: if1632.o must be the first object file because its code must be
- *          linked at the lowest possible addresses.
- */
 EMUOBJS = \
-	if1632/if1632.o \
 	debugger/debugger.o \
+	if1632/if1632.o \
 	memory/memory.o \
 	miscemu/miscemu.o
 
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 8d53b91..85028b1 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -15,9 +15,6 @@
 Emulator/Library: You need an emulator when you want to run MS-Win
 binaries. You need a library when you want to compile the source code
 of a Windows program.
-Short filenames: Some file systems are limited to 11 characters per
-file name. Files generated in if1632 will get gracefully translated
-names.
 Language: Wine can present the system menu in multiple languages. Select
 one of English, German, or Norwegian here.
 Malloc debugging: When enabled, the mtrace and mcheck GNU libc functions
diff --git a/Wine.tmpl b/Wine.tmpl
index e1f7e0b..1cc3320 100644
--- a/Wine.tmpl
+++ b/Wine.tmpl
@@ -1,38 +1,7 @@
-XCOMM $Id$
-
 INCLUDES = -I$(TOP)/include -I$(TOP)
 
 XCOMM Imake rules go here
 
-XCOMM First, dll description to files etc
-#ifndef MakeDllFromSpec
-#ifndef NewBuild
-#ifndef ShortNames
-#define MakeDllFromSpec(name)						@@\
-Concat(dll_,name.S) Concat3(dll_,name,_tab.c): name.spec $(TOP)/tools/build  @@\
-	$(TOP)/tools/build name.spec					@@\
-
-#else /* ShortNames */
-#define MakeDllFromSpec(name)						@@\
-Concat(dll_,name.S) Concat(dtb_,name.c): name.spec $(TOP)/tools/build   @@\
-	$(TOP)/tools/build name.spec					@@\
-
-#endif /* ShortNames */
-#else /* NewBuild */
-#ifndef ShortNames
-#define MakeDllFromSpec(name)						@@\
-Concat(dll_,name.S) Concat(rly_,name.S) Concat3(dll_,name,_tab.c): name.spec $(TOP)/tools/newbuild  @@\
-	$(TOP)/tools/newbuild name.spec					@@\
-
-#else /* ShortNames */
-#define MakeDllFromSpec(name)						@@\
-Concat(dll_,name.S) Concat(rly_,name.S) Concat(dtb_,name.c): name.spec $(TOP)/tools/newbuild   @@\
-	$(TOP)/tools/newbuild name.spec					@@\
-
-#endif /* ShortNames */
-#endif /* NewBuild */
-#endif /* MakeDllFromSpec */
-
 /*
  * WineRelocatableTarget - generate rules to produce a relocatable object
  * file instead of a library.  
diff --git a/controls/edit.c b/controls/edit.c
index 5a42a13..2109aa3 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -4,6 +4,7 @@
  * Copyright  David W. Metcalfe, 1994
  *
  * Release 3, July 1994
+ * April 1995 bug fixes (William Magro)
 
 static char Copyright[] = "Copyright  David W. Metcalfe, 1994";
 */
@@ -65,6 +66,7 @@
     int DeletedCurrCol;      /* starting col from which text was deleted */
     int NumTabStops;         /* number of tab stops in buffer hTabStops */
     HANDLE hTabStops;        /* handle of tab stops buffer */
+    BOOL HaveFocus;          /* TRUE if this edit has the focus */
 } EDITSTATE;
 
 
@@ -147,7 +149,7 @@
 void EDIT_ClearSel(HWND hwnd);
 int EDIT_TextLineNumber(HWND hwnd, char *lp);
 void EDIT_SetAnchor(HWND hwnd, int row, int col);
-void EDIT_ExtendSel(HWND hwnd, int x, int y);
+void EDIT_ExtendSel(HWND hwnd, INT x, INT y);
 void EDIT_WriteSel(HWND hwnd, int y, int start, int end);
 void EDIT_StopMarking(HWND hwnd);
 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam);
@@ -380,29 +382,32 @@
 	break;
 
     case WM_KILLFOCUS:
+	es->HaveFocus = FALSE;
 	DestroyCaret();
+	if (SelMarked(es)) EDIT_ClearSel(hwnd);
 	NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
 	break;
 
     case WM_LBUTTONDOWN:
 	HideCaret(hwnd);
 	SetFocus(hwnd);
+	SetCapture(hwnd);
 	EDIT_LButtonDownMsg(hwnd, wParam, lParam);
 	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
 	ShowCaret(hwnd);
 	break;
 
     case WM_LBUTTONUP:
+	if (GetCapture() != hwnd) break;
+	ReleaseCapture();
 	ButtonDown = FALSE;
 	if (TextMarking)
 	    EDIT_StopMarking(hwnd);
 	break;
 
     case WM_MOUSEMOVE:
-	HideCaret(hwnd);
-	EDIT_MouseMoveMsg(hwnd, wParam, lParam);
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-	ShowCaret(hwnd);
+	if (es->HaveFocus)
+	    EDIT_MouseMoveMsg(hwnd, wParam, lParam);
 	break;
 
     case WM_MOVE:
@@ -422,6 +427,7 @@
 	break;
 
     case WM_SETFOCUS:
+	es->HaveFocus = TRUE;
 	CreateCaret(hwnd, 0, 2, es->txtht);
 	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
 	ShowCaret(hwnd);
@@ -506,6 +512,8 @@
         es->wlines = 0;
         es->textwidth = 0;
 	EDIT_ClearTextPointers(hwnd);
+	if(IsMultiLine()) strcpy(text, "\r\n");
+	EDIT_BuildTextPointers(hwnd);
     }
     else
     {
@@ -516,14 +524,18 @@
 	    es->hText = EDIT_HeapAlloc(hwnd, EditBufLen(wndPtr) + 2);
 	    text = EDIT_HeapAddr(hwnd, es->hText);
 	    strcpy(text, windowName);
+	    if(IsMultiLine()) strcat(text, "\r\n");
+	    es->textlen += 2;
 	    *(text + es->textlen) = '\0';
 	}
 	else
 	{
-	    es->hText = EDIT_HeapAlloc(hwnd, strlen(windowName) + 2);
+	    es->hText = EDIT_HeapAlloc(hwnd, strlen(windowName) + 4);
 	    text = EDIT_HeapAddr(hwnd, es->hText);
 	    strcpy(text, windowName);
-	    es->textlen = strlen(windowName) + 1;
+	    if(IsMultiLine()) strcat(text, "\r\n");
+	    es->textlen = strlen(windowName) + 3;
+	    *(text + es->textlen) = '\0';
 	}
 	*(text + es->textlen + 1) = '\0';
 	EDIT_BuildTextPointers(hwnd);
@@ -727,7 +739,7 @@
 
     for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++)
     {
-	if (y < es->wlines - es->wtop)
+	if (y < (IsMultiLine() ? es->wlines : 1) - es->wtop)
 	    EDIT_WriteTextLine(hwnd, &rc, y + es->wtop);
     }
 
@@ -885,17 +897,23 @@
     lnlen1 = lnlen;
 
     /* build the line to display */
-    if (lnlen < es->wleft)
+    if (lnlen < (es->wleft + rc.left))
+    {
 	lnlen = 0;
+        return;
+    }
     else
+    {
 	off += es->wleft;
+	lnlen -= off;
+    }
 
     if (lnlen > rc.left)
     {
 	off += rc.left;
 	lnlen = lnlen1 - off;
-	len = min(lnlen, rc.right - rc.left);
     }
+    len = min(lnlen, rc.right - rc.left);
 
     if (SelMarked(es))
     {
@@ -1141,7 +1159,7 @@
     str = (char *)EDIT_HeapAddr(hwnd, hStr);
     for (i = ch1, j = 0; i < ch; i++, j++)
 	str[j] = lp[i];
-    str[++j] = '\0';
+    str[j] = '\0';
     dprintf_edit(stddeb,"EDIT_GetStr: returning %s\n", str);
     return hStr;
 }
@@ -1193,7 +1211,7 @@
     EDITSTATE *es = 
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
     char *text = EDIT_HeapAddr(hwnd, es->hText);
-    char *currchar = CurrChar;
+    char *currchar;
     RECT rc;
     BOOL FullPaint = FALSE;
 
@@ -1203,6 +1221,9 @@
     if (SelMarked(es))
 	EDIT_DeleteSel(hwnd);
 
+    /* currchar must be assigned after deleting the selection */
+    currchar = CurrChar;
+
     /* test for typing at end of maximum buffer size */
     if (currchar == text + es->MaxTextLen)
     {
@@ -1271,7 +1292,6 @@
     else
 	es->textwidth = max(es->textwidth,
 			    EDIT_StrLength(hwnd, text, strlen(text), 0));
-    EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
 
     if (ch == '\n')
     {
@@ -1306,6 +1326,7 @@
     }
     es->WndCol += EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft);
     es->CurrCol++;
+    EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
     SetCaretPos(es->WndCol, es->WndRow * es->txtht);
     ShowCaret(hwnd);
     NOTIFY_PARENT(hwnd, EN_CHANGE);
@@ -1382,8 +1403,11 @@
 
     if (*CurrChar == '\r')
     {
-	EDIT_Home(hwnd);
-	EDIT_Downward(hwnd);
+        if (es->CurrLine < (es->wlines - 1))
+        {
+	    EDIT_Home(hwnd);
+	    EDIT_Downward(hwnd);
+        }
     }
     else
     {
@@ -1549,7 +1573,7 @@
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
     int len = EDIT_LineLength(hwnd, es->CurrLine);
     char *cp = EDIT_TextLine(hwnd, es->CurrLine);
-    char currpel;
+    int currpel;
 
     es->CurrCol = min(len, es->CurrCol);
     es->WndCol = min(EDIT_StrLength(hwnd, cp, len, 0) - es->wleft, es->WndCol);
@@ -2150,22 +2174,22 @@
 	EDIT_ClearSel(hwnd);
 
     es->WndRow = HIWORD(lParam) / es->txtht;
-    if (es->WndRow > es->wlines - es->wtop - 1)
+    if (!IsMultiLine())
+        es->WndRow = 0;
+    else if (es->WndRow > es->wlines - es->wtop - 1)
     {
-	if (es->wlines)
-	    es->WndRow = es->wlines - es->wtop - 1;
-	else
-	    es->WndRow = 0;
+        es->WndRow = es->wlines - es->wtop - 1;
 	end = TRUE;
     }
     es->CurrLine = es->wtop + es->WndRow;
 
     cp = EDIT_TextLine(hwnd, es->CurrLine);
     len = EDIT_LineLength(hwnd, es->CurrLine);
-    es->WndCol = LOWORD(lParam);
-    if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) - es->wleft || end)
-	es->WndCol = EDIT_StrLength(hwnd, cp, len, 0) - es->wleft;
+    es->WndCol = LOWORD(lParam) + es->wleft;
+    if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) || end)
+	es->WndCol = EDIT_StrLength(hwnd, cp, len, 0);
     es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
+    es->WndCol -= es->wleft;
 
     ButtonDown = TRUE;
     ButtonRow = es->CurrLine;
@@ -2179,9 +2203,14 @@
 
 void EDIT_MouseMoveMsg(HWND hwnd, WORD wParam, LONG lParam)
 {
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    EDITSTATE *es = 
+	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
+
     if (wParam != MK_LBUTTON)
 	return;
 
+    HideCaret(hwnd);
     if (ButtonDown)
     {
 	EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol);
@@ -2190,7 +2219,11 @@
     }
 
     if (TextMarking)
+    {
 	EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
+        SetCaretPos(es->WndCol, es->WndRow * es->txtht);
+    }
+    ShowCaret(hwnd);
 }
 
 
@@ -2297,7 +2330,7 @@
 
 void EDIT_SetSelMsg(HWND hwnd, WORD wParam, LONG lParam)
 {
-    int so, eo;
+    INT so, eo;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = 
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
@@ -2313,7 +2346,7 @@
 
     if (so == eo)       /* if so == eo, set caret only */
     {
-	EDIT_GetLineCol(hwnd, so, &(es->CurrLine), &(es->CurrCol));
+	EDIT_GetLineCol(hwnd, (int) so, &(es->CurrLine), &(es->CurrCol));
 	es->WndRow = es->CurrLine - es->wtop;
 
 	if (!wParam)
@@ -2340,11 +2373,16 @@
     }
     else                /* otherwise set selection */
     {
-	if (so > eo)
-	    swap(&so, &eo);
+	if (eo >= 0 && so > eo)	  /* eo == -1 flag to extend to end of text */
+        {
+            INT tmp;
+            tmp = so;
+            so = eo;
+            eo = tmp;
+        }
 
-	EDIT_GetLineCol(hwnd, so, &(es->SelBegLine), &(es->SelBegCol));
-	EDIT_GetLineCol(hwnd, eo, &(es->SelEndLine), &(es->SelEndCol));
+	EDIT_GetLineCol(hwnd, (int) so, &(es->SelBegLine), &(es->SelBegCol));
+	EDIT_GetLineCol(hwnd, (int) eo, &(es->SelEndLine), &(es->SelEndCol));
 	es->CurrLine = es->SelEndLine;
 	es->CurrCol = es->SelEndCol;
 	es->WndRow = es->SelEndLine - es->wtop;
@@ -2407,7 +2445,7 @@
 	return;
     }
 
-    if (off > strlen(text)) off = strlen(text);
+    if (off < 0 || off > strlen(text)) off = strlen(text);
     cp1 = text;
     for (lineno = 0; lineno < es->wlines; lineno++)
     {
@@ -2536,8 +2574,10 @@
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
 
     if (SelMarked(es))
+    {
 	sel = TRUE;
-    EDIT_ClearSel(hwnd);
+        EDIT_ClearSel(hwnd);
+    }
     es->SelBegLine = es->SelEndLine = row;
     es->SelBegCol = es->SelEndCol = col;
     if (sel)
@@ -2554,12 +2594,11 @@
  *  Extend selection to the given screen co-ordinates.
  */
 
-void EDIT_ExtendSel(HWND hwnd, int x, int y)
+void EDIT_ExtendSel(HWND hwnd, INT x, INT y)
 {
     int bbl, bel, bbc, bec;
     char *cp;
     int len, line;
-    BOOL end = FALSE;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = 
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
@@ -2568,28 +2607,31 @@
 
     bbl = es->SelEndLine;
     bbc = es->SelEndCol;
-    line = es->wtop + y / es->txtht;
-    if (line > es->wlines)
-	line = es->wlines;
+    y = max(y,0);
+    if (IsMultiLine())
+    {
+        if ((line = es->wtop + y / es->txtht) >= es->wlines)
+	    line = es->wlines - 1;
+    }
+    else
+        line = 0;
+        
     cp = EDIT_TextLine(hwnd, line);
     len = EDIT_LineLength(hwnd, line);
 
     es->WndRow = y / es->txtht;
-    if (es->WndRow > es->wlines - es->wtop - 1)
-    {
-	if (es->wlines)
-	    es->WndRow = es->wlines - es->wtop - 1;
-	else
+    if (!IsMultiLine())
 	    es->WndRow = 0;
-	end = TRUE;
-    }
+    else if (es->WndRow > es->wlines - es->wtop - 1)
+	    es->WndRow = es->wlines - es->wtop - 1;
     es->CurrLine = es->wtop + es->WndRow;
     es->SelEndLine = es->CurrLine;
 
-    es->WndCol = x;
-    if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) - es->wleft || end)
-	es->WndCol = EDIT_StrLength(hwnd, cp, len, 0) - es->wleft;
+    es->WndCol = es->wleft + max(x,0);
+    if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0))
+	es->WndCol = EDIT_StrLength(hwnd, cp, len, 0);
     es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
+    es->WndCol -= es->wleft;
     es->SelEndCol = es->CurrCol;
 
     bel = es->SelEndLine;
@@ -2631,12 +2673,10 @@
 
 void EDIT_WriteSel(HWND hwnd, int y, int start, int end)
 {
-    RECT rc;
+    RECT rc, rcInvert;
     int scol, ecol;
     char *cp;
     HDC hdc;
-    HBRUSH hbrush, holdbrush;
-    int olddm;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = 
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
@@ -2660,20 +2700,19 @@
      * lines.  I have kludged this by adding on two pixels to ecol and
      * to the line height in the call to Rectangle.
      */
-    scol = EDIT_StrLength(hwnd, cp, start, 0);
+    scol = EDIT_StrLength(hwnd, cp, start, 0) - es->wleft;
     if (scol > rc.right) return;
     if (scol < rc.left) scol = rc.left;
-    ecol = EDIT_StrLength(hwnd, cp, end, 0) + 2;   /* ??? */
+    ecol = EDIT_StrLength(hwnd, cp, end, 0) - es->wleft;
     if (ecol < rc.left) return;
     if (ecol > rc.right) ecol = rc.right;
 
     hdc = GetDC(hwnd);
-    hbrush = GetStockObject(BLACK_BRUSH);
-    holdbrush = (HBRUSH)SelectObject(hdc, (HANDLE)hbrush);
-    olddm = SetROP2(hdc, R2_XORPEN);
-    Rectangle(hdc, scol, y * es->txtht, ecol, (y + 1) * es->txtht + 2);
-    SetROP2(hdc, olddm);
-    SelectObject(hdc, (HANDLE)holdbrush);
+    rcInvert.left = scol;
+    rcInvert.top = y * es->txtht;
+    rcInvert.right = ecol;
+    rcInvert.bottom = (y + 1) * es->txtht;
+    InvertRect(hdc, (LPRECT) &rcInvert);
     ReleaseDC(hwnd, hdc);
 }
 
@@ -2931,7 +2970,10 @@
     EDITSTATE *es = 
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
 
-    es->hDeletedText = GlobalReAlloc(es->hDeletedText, len, GMEM_MOVEABLE);
+    if (!es->hDeletedText)
+        es->hDeletedText = GlobalAlloc( GMEM_MOVEABLE, len );
+    else 
+        es->hDeletedText = GlobalReAlloc(es->hDeletedText, len, GMEM_MOVEABLE);
     if (!es->hDeletedText) return;
     text = (char *)GlobalLock(es->hDeletedText);
     memcpy(text, deltext, len);
diff --git a/controls/listbox.c b/controls/listbox.c
index ebfab3a..58d204c 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -2,6 +2,7 @@
  * Interface code to listbox widgets
  *
  * Copyright  Martin Ayotte, 1993
+ * Copyright  Constantine Sapuntzakis, 1995
  *
 static char Copyright[] = "Copyright Martin Ayotte, 1993";
 */
@@ -23,11 +24,11 @@
 
 #define GMEM_ZEROINIT 0x0040
 
-
+LPLISTSTRUCT ListBoxGetItem (HWND hwnd, UINT uIndex);
+int ListBoxScrolltoFocus(HWND hwnd);
 LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr);
 LPHEADLIST ListBoxGetStorageHeader(HWND hwnd);
-void StdDrawListBox(HWND hwnd);
-void OwnerDrawListBox(HWND hwnd);
+void RepaintListBox(HWND hwnd);
 int ListBoxFindMouse(HWND hwnd, int X, int Y);
 int CreateListBoxStruct(HWND hwnd);
 void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls);
@@ -50,10 +51,13 @@
 int ListMaxFirstVisible(LPHEADLIST lphl);
 void ListBoxSendNotification(HWND hwnd, WORD code);
 
-#define HasStrings(wndPtr) ( \
-  ( ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) != LBS_OWNERDRAWFIXED) && \
-    ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) != LBS_OWNERDRAWVARIABLE) ) || \
-  ((wndPtr->dwStyle & LBS_HASSTRINGS) == LBS_HASSTRINGS) )
+#define OWNER_DRAWN(wndPtr) \
+  ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) ||  \
+   (wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE))
+
+#define HasStrings(wndPtr) (  \
+  (! OWNER_DRAWN (wndPtr)) || \
+  (wndPtr->dwStyle & LBS_HASSTRINGS))
 
 #if 0
 #define LIST_HEAP_ALLOC(lphl,f,size) ((int)HEAP_Alloc(&lphl->Heap,f,size) & 0xffff)
@@ -68,433 +72,1170 @@
 
 #define LIST_HEAP_SIZE 0x10000
 
+/* Design notes go here */
+
+LONG LBCreate( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetDlgCode( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBDestroy( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBVScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBHScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBLButtonDown( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBLButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBRButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBMouseMove( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBKeyDown( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetFont( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetRedraw( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBPaint( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBKillFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBResetContent( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBDir( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBAddString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetText( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBInsertString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBDeleteString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBFindString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetCount( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetHorizontalExtent(HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetItemRect( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetSelCount( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetSelItems( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetTextLen( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBGetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSelectString( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSelItemRange( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetColumnWidth( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetHorizontalExtent(HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetTabStops( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+LONG LBSetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+
+
+typedef struct {
+  WORD   message;
+  LONG  (*handler)(HWND, WORD, WPARAM, LPARAM);
+} msg_tbl;
+
+static msg_tbl methods[] = {
+  {WM_CREATE, LBCreate},
+  {WM_DESTROY, LBDestroy},
+  {WM_GETDLGCODE, LBGetDlgCode},
+  {WM_VSCROLL, LBVScroll},
+  {WM_HSCROLL, LBHScroll},
+  {WM_LBUTTONDOWN, LBLButtonDown},
+  {WM_LBUTTONUP, LBLButtonUp},
+  {WM_RBUTTONUP, LBRButtonUp},
+  {WM_LBUTTONDBLCLK, LBRButtonUp},
+  {WM_MOUSEMOVE, LBMouseMove},
+  {WM_KEYDOWN, LBKeyDown},
+  {WM_SETFONT, LBSetFont},
+  {WM_SETREDRAW, LBSetRedraw},
+  {WM_PAINT, LBPaint},
+  {WM_SETFOCUS, LBSetFocus},
+  {WM_KILLFOCUS, LBKillFocus},
+  {LB_RESETCONTENT, LBResetContent},
+  {LB_DIR, LBDir},
+  {LB_ADDSTRING, LBAddString},
+  {LB_INSERTSTRING, LBInsertString},
+  {LB_DELETESTRING, LBDeleteString},
+  {LB_FINDSTRING, LBFindString},
+  {LB_GETCARETINDEX, LBGetCaretIndex},
+  {LB_GETCOUNT, LBGetCount},
+  {LB_GETCURSEL, LBGetCurSel},
+  {LB_GETHORIZONTALEXTENT, LBGetHorizontalExtent},
+  {LB_GETITEMDATA, LBGetItemData},
+  {LB_GETITEMHEIGHT, LBGetItemHeight},
+  {LB_GETITEMRECT, LBGetItemRect},
+  {LB_GETSEL, LBGetSel},
+  {LB_GETSELCOUNT, LBGetSelCount},
+  {LB_GETSELITEMS, LBGetSelItems},
+  {LB_GETTEXT, LBGetText},
+  {LB_GETTEXTLEN, LBGetTextLen},
+  {LB_GETTOPINDEX, LBGetTopIndex},
+  {LB_SELECTSTRING, LBSelectString},
+  {LB_SELITEMRANGE, LBSelItemRange},
+  {LB_SETCARETINDEX, LBSetCaretIndex},
+  {LB_SETCOLUMNWIDTH, LBSetColumnWidth},
+  {LB_SETHORIZONTALEXTENT, LBSetHorizontalExtent},
+  {LB_SETITEMDATA, LBSetItemData},
+  {LB_SETTABSTOPS, LBSetTabStops},
+  {LB_SETCURSEL, LBSetCurSel},
+  {LB_SETSEL, LBSetSel},
+  {LB_SETTOPINDEX, LBSetTopIndex},
+  {LB_SETITEMHEIGHT, LBSetItemHeight}
+};
+
 /***********************************************************************
- *           ListBoxWndProc 
+ *           LBCreate
  */
-LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
-{    
-	WND  *wndPtr;
-	LPHEADLIST  lphl;
-	HWND	hWndCtl;
-	WORD	wRet;
-	LONG	lRet;
-	RECT	rect;
-	int		y;
-	CREATESTRUCT *createStruct;
-	static RECT rectsel;
-    switch(message) {
-	case WM_CREATE:
-		CreateListBoxStruct(hwnd);
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		dprintf_listbox(stddeb,"ListBox WM_CREATE %p !\n", lphl);
-		if (lphl == NULL) return 0;
-		createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
-		if (HIWORD(createStruct->lpCreateParams) != 0)
-			lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
-		else
-			lphl->hWndLogicParent = GetParent(hwnd);
-		lphl->hFont = GetStockObject(SYSTEM_FONT);
-		lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
-                SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
-                SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
-		if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
-			}
-		return 0;
-	case WM_DESTROY:
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		ListBoxResetContent(hwnd);
-		/* XXX need to free lphl->Heap */
-		free(lphl);
-		*((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
-		dprintf_listbox(stddeb,"ListBox WM_DESTROY %p !\n", lphl);
-		return 0;
+LONG LBCreate( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 
-	case WM_VSCROLL:
-		dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
-				wParam, lParam);
-		lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl == NULL) return 0;
-		y = lphl->FirstVisible;
-		switch(wParam) {
-			case SB_LINEUP:
-				if (lphl->FirstVisible > 1)	
-					lphl->FirstVisible--;
-				break;
-			case SB_LINEDOWN:
-				if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
-					lphl->FirstVisible++;
-				break;
-			case SB_PAGEUP:
-				if (lphl->FirstVisible > 1)  
-					lphl->FirstVisible -= lphl->ItemsVisible;
-				break;
-			case SB_PAGEDOWN:
-				if (lphl->FirstVisible < ListMaxFirstVisible(lphl))  
-					lphl->FirstVisible += lphl->ItemsVisible;
-				break;
-			case SB_THUMBTRACK:
-				lphl->FirstVisible = LOWORD(lParam);
-				break;
-			}
-		if (lphl->FirstVisible < 1)    lphl->FirstVisible = 1;
-		if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
-			lphl->FirstVisible = ListMaxFirstVisible(lphl);
-		if (y != lphl->FirstVisible) {
-			SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-			InvalidateRect(hwnd, NULL, TRUE);
-			UpdateWindow(hwnd);
-			}
-		return 0;
-	
-	case WM_HSCROLL:
-		dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
-				wParam, lParam);
-		lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl == NULL) return 0;
-		y = lphl->FirstVisible;
-		switch(wParam) {
-			case SB_LINEUP:
-				if (lphl->FirstVisible > 1)
-					lphl->FirstVisible -= lphl->ItemsPerColumn;
-				break;
-			case SB_LINEDOWN:
-				if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
-					lphl->FirstVisible += lphl->ItemsPerColumn;
-				break;
-			case SB_PAGEUP:
-				if (lphl->FirstVisible > 1 && lphl->ItemsPerColumn != 0)  
-					lphl->FirstVisible -= lphl->ItemsVisible /
-					lphl->ItemsPerColumn * lphl->ItemsPerColumn;
-				break;
-			case SB_PAGEDOWN:
-				if (lphl->FirstVisible < ListMaxFirstVisible(lphl) &&
-							lphl->ItemsPerColumn != 0)  
-					lphl->FirstVisible += lphl->ItemsVisible /
-					lphl->ItemsPerColumn * lphl->ItemsPerColumn;
-				break;
-			case SB_THUMBTRACK:
-				lphl->FirstVisible = lphl->ItemsPerColumn * 
-								(LOWORD(lParam) - 1) + 1;
-				break;
-			}
-		if (lphl->FirstVisible < 1)    lphl->FirstVisible = 1;
-		if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
-			lphl->FirstVisible = ListMaxFirstVisible(lphl);
-		if (lphl->ItemsPerColumn != 0) {
-			lphl->FirstVisible = lphl->FirstVisible /
-				lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
-			if (y != lphl->FirstVisible) {
-				SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible / 
-				lphl->ItemsPerColumn + 1, TRUE);
-				InvalidateRect(hwnd, NULL, TRUE);
-				UpdateWindow(hwnd);
-				}
-			}
-		return 0;
-	
-	case WM_LBUTTONDOWN:
-		SetFocus(hwnd);
-		SetCapture(hwnd);
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		lphl->PrevFocused = lphl->ItemFocused;
-	        y = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
-		if (y==-1)
-		    return 0;
-		if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
-		    lphl->ItemFocused = y;
-		    wRet = ListBoxGetSel(hwnd, y);
-		    ListBoxSetSel(hwnd, y, !wRet);
-		    }
-		else
-		    ListBoxSetCurSel(hwnd, y);
-		if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL)
-		  ListBoxSendNotification( hwnd, LBN_SELCHANGE );
-		ListBoxGetItemRect(hwnd, y, &rectsel);
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		return 0;
-	case WM_LBUTTONUP:
-		ReleaseCapture();
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		if (lphl->PrevFocused != lphl->ItemFocused)
-		  ListBoxSendNotification( hwnd, LBN_SELCHANGE );
-		return 0;
-	case WM_RBUTTONUP:
-	case WM_LBUTTONDBLCLK:
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
-										MAKELONG(hwnd, LBN_DBLCLK));
-		return 0;
-	case WM_MOUSEMOVE:
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		if ((wParam & MK_LBUTTON) != 0) {
-			y = HIWORD(lParam);
-			if (y < 4) {
-				if (lphl->FirstVisible > 1) {
-					lphl->FirstVisible--;
-					SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-					InvalidateRect(hwnd, NULL, TRUE);
-					UpdateWindow(hwnd);
-					break;
-					}
-				}
-			GetClientRect(hwnd, &rect);
-			if (y > (rect.bottom - 4)) {
-				if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
-					lphl->FirstVisible++;
-					SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-					InvalidateRect(hwnd, NULL, TRUE);
-					UpdateWindow(hwnd);
-					break;
-					}
-				}
-			if ((y > 0) && (y < (rect.bottom - 4))) {
-				if ((y < rectsel.top) || (y > rectsel.bottom)) {
-					wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
-					if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
-						lphl->ItemFocused = wRet;
-						ListBoxSendNotification(hwnd, LBN_SELCHANGE);
-						}
-					else
-						ListBoxSetCurSel(hwnd, wRet);
-					ListBoxGetItemRect(hwnd, wRet, &rectsel);
-					InvalidateRect(hwnd, NULL, TRUE);
-					UpdateWindow(hwnd);
-					}
-				}
-			}
-		break;
-	case WM_KEYDOWN:
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		switch(wParam) {
-			case VK_TAB:
-				hWndCtl = GetNextDlgTabItem(lphl->hWndLogicParent,
-					hwnd, !(GetKeyState(VK_SHIFT) < 0));
-				SetFocus(hWndCtl);
-				if(debugging_listbox){
-				if ((GetKeyState(VK_SHIFT) < 0))
-					dprintf_listbox(stddeb,"ListBox PreviousDlgTabItem %04X !\n", hWndCtl);
-				else
-					dprintf_listbox(stddeb,"ListBox NextDlgTabItem %04X !\n", hWndCtl);
-				}
-				break;
-			case VK_HOME:
-				lphl->ItemFocused = 0;
-				break;
-			case VK_END:
-				lphl->ItemFocused = lphl->ItemsCount - 1;
-				break;
-			case VK_LEFT:
-				if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
-					lphl->ItemFocused -= lphl->ItemsPerColumn;
-					}
-				break;
-			case VK_UP:
-				lphl->ItemFocused--;
-				break;
-			case VK_RIGHT:
-				if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
-					lphl->ItemFocused += lphl->ItemsPerColumn;
-					}
-				break;
-			case VK_DOWN:
-				lphl->ItemFocused++;
-				break;
-			case VK_PRIOR:
-				lphl->ItemFocused -= lphl->ItemsVisible;
-				break;
-			case VK_NEXT:
-				lphl->ItemFocused += lphl->ItemsVisible;
-				break;
-			case VK_SPACE:
-				wRet = ListBoxGetSel(hwnd, lphl->ItemFocused);
-				ListBoxSetSel(hwnd, lphl->ItemFocused, !wRet);
-				break;
-			default:
-				ListBoxFindNextMatch(hwnd, wParam);
-				return 0;
-			}
-		if (lphl->ItemFocused < 0) lphl->ItemFocused = 0;
-		if (lphl->ItemFocused >= lphl->ItemsCount)
-			lphl->ItemFocused = lphl->ItemsCount - 1;
-		lphl->FirstVisible = lphl->ItemFocused / lphl->ItemsVisible * 
-											lphl->ItemsVisible + 1;
-		if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
-		if ((wndPtr->dwStyle & LBS_MULTIPLESEL) != LBS_MULTIPLESEL) {
-			ListBoxSetCurSel(hwnd, lphl->ItemFocused);
-			ListBoxSendNotification(hwnd, LBN_SELCHANGE);
-			}
-                SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		break;
-	case WM_SETFONT:
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		if (wParam == 0)
-			lphl->hFont = GetStockObject(SYSTEM_FONT);
-		else
-			lphl->hFont = wParam;
-		if (wParam == 0) break;
-		break;
-	case WM_SETREDRAW:
-		dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04X w=%04X !\n", hwnd, wParam);
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		if (lphl == NULL) return 0;
-		lphl->bRedrawFlag = wParam;
-		break;
-	case WM_PAINT:
-		wndPtr = WIN_FindWndPtr(hwnd);
-		if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) {
-			OwnerDrawListBox(hwnd);
-			break;
-			}
-		if ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) {
-			OwnerDrawListBox(hwnd);
-			break;
-			}
-		StdDrawListBox(hwnd);
-		break;
-	case WM_SETFOCUS:
-		dprintf_listbox(stddeb,"ListBox WM_SETFOCUS !\n");
-		lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-		break;
-	case WM_KILLFOCUS:
-		dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS !\n");
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		break;
+{
+  LPHEADLIST  lphl;
+  CREATESTRUCT *createStruct;
+  WND          *wndPtr;
 
-    case LB_RESETCONTENT:
-		dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
-		ListBoxResetContent(hwnd);
-		return 0;
-    case LB_DIR:
-		dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
-		wRet = ListBoxDirectory(hwnd, wParam,
-                                        (LPSTR)PTR_SEG_TO_LIN(lParam));
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		return wRet;
-	case LB_ADDSTRING:
-		wRet = ListBoxAddString(hwnd, (LPSTR)PTR_SEG_TO_LIN(lParam));
-		return wRet;
-	case LB_GETTEXT:
-		dprintf_listbox(stddeb, "LB_GETTEXT  wParam=%d\n",wParam);
-		wRet = ListBoxGetText(hwnd, wParam,
-                                      (LPSTR)PTR_SEG_TO_LIN(lParam), FALSE);
-                return wRet;
-	case LB_INSERTSTRING:
-		wRet = ListBoxInsertString(hwnd, wParam,
-                                           (LPSTR)PTR_SEG_TO_LIN(lParam));
-		return wRet;
-	case LB_DELETESTRING:
-		wRet = ListBoxDeleteString(hwnd, wParam);
-		return wRet;
-	case LB_FINDSTRING:
-		wRet = ListBoxFindString(hwnd, wParam,
-                                         (LPSTR)PTR_SEG_TO_LIN(lParam));
-		return wRet;
-	case LB_GETCARETINDEX:
-		return wRet;
-	case LB_GETCOUNT:
-		lphl = ListBoxGetStorageHeader(hwnd);
-		return lphl->ItemsCount;
-	case LB_GETCURSEL:
-		lphl = ListBoxGetStorageHeader(hwnd);
-		dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %u !\n", 
-				lphl->ItemFocused);
-		return lphl->ItemFocused;
-	case LB_GETHORIZONTALEXTENT:
-		return wRet;
-	case LB_GETITEMDATA:
-		dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
-		lRet = ListBoxGetText(hwnd, wParam,
-                                      (LPSTR)PTR_SEG_TO_LIN(lParam), TRUE);
-		return lRet;
-	case LB_GETITEMHEIGHT:
-                ListBoxGetItemRect(hwnd, wParam, &rect);
-                return (rect.bottom - rect.top);
-	case LB_GETITEMRECT:
-                ListBoxGetItemRect(hwnd,wParam,(LPRECT)PTR_SEG_TO_LIN(lParam));
-                return 0;
-	case LB_GETSEL:
-		wRet = ListBoxGetSel(hwnd, wParam);
-		return wRet;
-	case LB_GETSELCOUNT:
-		lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl == NULL) return LB_ERR;
-		return lphl->SelCount;
-	case LB_GETSELITEMS:
-		return wRet;
-	case LB_GETTEXTLEN:
-		return wRet;
-	case LB_GETTOPINDEX:
-		lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl == NULL) return LB_ERR;
-		return lphl->FirstVisible;
-	case LB_SELECTSTRING:
-		return wRet;
-	case LB_SELITEMRANGE:
-		return wRet;
-	case LB_SETCARETINDEX:
-		return wRet;
-	case LB_SETCOLUMNWIDTH:
-		lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl == NULL) return LB_ERR;
-		lphl->ColumnsWidth = wParam;
-		break;
-	case LB_SETHORIZONTALEXTENT:
-		return wRet;
-	case LB_SETITEMDATA:
-		dprintf_listbox(stddeb, "LB_SETITEMDATA  wParam=%x  lParam=%lx\n", wParam, lParam);
-		wRet = ListBoxSetItemData(hwnd, wParam, lParam);
-		return wRet;
-	case LB_SETTABSTOPS:
-		lphl = ListBoxGetStorageHeader(hwnd);
-		if (lphl == NULL) return LB_ERR;
-		lphl->FirstVisible = wParam;
-		return 0;
-	case LB_SETCURSEL:
-		dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n", 
-				wParam);
-		wRet = ListBoxSetCurSel(hwnd, wParam);
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		return wRet;
-	case LB_SETSEL:
-		dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
-		wRet = ListBoxSetSel(hwnd, LOWORD(lParam), wParam);
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		return wRet;
-	case LB_SETTOPINDEX:
-		dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
-				wParam);
-		lphl = ListBoxGetStorageHeader(hwnd);
-		lphl->FirstVisible = wParam;
-                SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		break;
-	case LB_SETITEMHEIGHT:
-		dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
-		wRet = ListBoxSetItemHeight(hwnd, wParam, lParam);
-		return wRet;
+  CreateListBoxStruct(hwnd);
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
 
-	default:
-		return DefWindowProc( hwnd, message, wParam, lParam );
-    }
-return 0;
+  dprintf_listbox(stddeb,"ListBox WM_CREATE %p !\n", lphl);
+
+  if (lphl == NULL) return 0;
+
+  createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
+
+  if (HIWORD(createStruct->lpCreateParams) != 0)
+    lphl->hWndLogicParent = (HWND)HIWORD(createStruct->lpCreateParams);
+  else
+    lphl->hWndLogicParent = GetParent(hwnd);
+
+  lphl->hFont = GetStockObject(SYSTEM_FONT);
+  lphl->ColumnsWidth = wndPtr->rectClient.right - wndPtr->rectClient.left;
+
+  SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
+  SetScrollRange(hwnd, SB_HORZ, 1, 1, TRUE);
+
+  return 0;
+}
+
+int CreateListBoxStruct(HWND hwnd)
+
+{
+  WND  *wndPtr;
+  LPHEADLIST lphl;
+
+  wndPtr = WIN_FindWndPtr(hwnd);
+
+  lphl = (LPHEADLIST)malloc(sizeof(HEADLIST));
+  *((LPHEADLIST *)&wndPtr->wExtra[1]) = lphl;
+
+  lphl->lpFirst        = NULL;
+  lphl->ItemsCount     = 0;
+  lphl->ItemsVisible   = 0;
+  lphl->FirstVisible   = 1;
+  lphl->ColumnsVisible = 1;
+  lphl->ItemsPerColumn = 0;
+  lphl->StdItemHeight  = 15;
+  lphl->ItemFocused    = -1;
+  lphl->PrevFocused    = -1;
+  lphl->DrawCtlType    = ODT_LISTBOX;
+  lphl->bRedrawFlag    = TRUE;
+  lphl->iNumStops      = 0;
+  lphl->TabStops       = NULL;
+
+  if (OWNER_DRAWN(wndPtr)) 
+    lphl->hDrawItemStruct = USER_HEAP_ALLOC(sizeof(DRAWITEMSTRUCT));
+  else
+    lphl->hDrawItemStruct = 0;
+
+#if 0
+  HeapHandle = GlobalAlloc(GMEM_FIXED, LIST_HEAP_SIZE);
+  HeapBase = GlobalLock(HeapHandle);
+  HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
+#endif
+  return TRUE;
 }
 
 
+/***********************************************************************
+ *           LBDestroy
+ */
+LONG LBDestroy( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+  WND        *wndPtr;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  if (lphl == NULL) return 0;
+  ListBoxResetContent(hwnd);
+
+  if (lphl->hDrawItemStruct)
+    USER_HEAP_FREE(lphl->hDrawItemStruct);
+
+  /* XXX need to free lphl->Heap */
+  free(lphl);
+  *((LPHEADLIST *)&wndPtr->wExtra[1]) = 0;
+  dprintf_listbox(stddeb,"ListBox WM_DESTROY %p !\n", lphl);
+  return 0;
+}
+
+/* get the maximum value of lphl->FirstVisible */
+int ListMaxFirstVisible(LPHEADLIST lphl)
+{
+    int m = lphl->ItemsCount-lphl->ItemsVisible+1;
+    return (m < 1) ? 1 : m;
+}
+
+
+/***********************************************************************
+ *           LBVScroll
+ */
+LONG LBVScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+  int  y;
+
+  dprintf_listbox(stddeb,"ListBox WM_VSCROLL w=%04X l=%08lX !\n",
+		  wParam, lParam);
+  lphl = ListBoxGetStorageHeader(hwnd);
+  if (lphl == NULL) return 0;
+  y = lphl->FirstVisible;
+
+  switch(wParam) {
+  case SB_LINEUP:
+    if (lphl->FirstVisible > 1)	
+      lphl->FirstVisible--;
+    break;
+
+  case SB_LINEDOWN:
+    if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
+      lphl->FirstVisible++;
+    break;
+
+  case SB_PAGEUP:
+    if (lphl->FirstVisible > 1)  
+      lphl->FirstVisible -= lphl->ItemsVisible;
+    break;
+
+  case SB_PAGEDOWN:
+    if (lphl->FirstVisible < ListMaxFirstVisible(lphl))  
+      lphl->FirstVisible += lphl->ItemsVisible;
+    break;
+
+  case SB_THUMBTRACK:
+    lphl->FirstVisible = LOWORD(lParam);
+    break;
+  }
+
+  if (lphl->FirstVisible < 1)    lphl->FirstVisible = 1;
+  if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
+    lphl->FirstVisible = ListMaxFirstVisible(lphl);
+
+  if (y != lphl->FirstVisible) {
+    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+    InvalidateRect(hwnd, NULL, TRUE);
+    UpdateWindow(hwnd);
+  }
+  return 0;
+}
+
+/***********************************************************************
+ *           LBHScroll
+ */
+LONG LBHScroll( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+  int        y;
+
+  dprintf_listbox(stddeb,"ListBox WM_HSCROLL w=%04X l=%08lX !\n",
+		  wParam, lParam);
+  lphl = ListBoxGetStorageHeader(hwnd);
+  if (lphl == NULL) return 0;
+  y = lphl->FirstVisible;
+  switch(wParam) {
+  case SB_LINEUP:
+    if (lphl->FirstVisible > 1)
+      lphl->FirstVisible -= lphl->ItemsPerColumn;
+    break;
+  case SB_LINEDOWN:
+    if (lphl->FirstVisible < ListMaxFirstVisible(lphl))
+      lphl->FirstVisible += lphl->ItemsPerColumn;
+    break;
+  case SB_PAGEUP:
+    if (lphl->FirstVisible > 1 && lphl->ItemsPerColumn != 0)  
+      lphl->FirstVisible -= lphl->ItemsVisible /
+	lphl->ItemsPerColumn * lphl->ItemsPerColumn;
+    break;
+  case SB_PAGEDOWN:
+    if (lphl->FirstVisible < ListMaxFirstVisible(lphl) &&
+	lphl->ItemsPerColumn != 0)  
+      lphl->FirstVisible += lphl->ItemsVisible /
+	lphl->ItemsPerColumn * lphl->ItemsPerColumn;
+    break;
+  case SB_THUMBTRACK:
+    lphl->FirstVisible = lphl->ItemsPerColumn * 
+      (LOWORD(lParam) - 1) + 1;
+    break;
+  } 
+  if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
+  if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
+    lphl->FirstVisible = ListMaxFirstVisible(lphl);
+
+  if (lphl->ItemsPerColumn != 0) {
+    lphl->FirstVisible = lphl->FirstVisible /
+      lphl->ItemsPerColumn * lphl->ItemsPerColumn + 1;
+    if (y != lphl->FirstVisible) {
+      SetScrollPos(hwnd, SB_HORZ, lphl->FirstVisible / 
+		   lphl->ItemsPerColumn + 1, TRUE);
+      InvalidateRect(hwnd, NULL, TRUE);
+      UpdateWindow(hwnd);
+    }
+  }
+  return 0;
+}
+
+/***********************************************************************
+ *           LBLButtonDown
+ */
+LONG LBLButtonDown( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+  WND        *wndPtr;
+  WORD       wRet;
+  int        y;
+  RECT       rectsel;
+
+  SetFocus(hwnd);
+  SetCapture(hwnd);
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+
+  lphl->PrevFocused = lphl->ItemFocused;
+
+  y = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
+  if (y==-1)
+    return 0;
+
+  if (wndPtr->dwStyle & LBS_MULTIPLESEL) {
+    lphl->ItemFocused = y;
+    wRet = ListBoxGetSel(hwnd, y);
+    ListBoxSetSel(hwnd, y, !wRet);
+  }
+  else
+    ListBoxSetCurSel(hwnd, y);
+
+  if (wndPtr->dwStyle & LBS_MULTIPLESEL)
+    ListBoxSendNotification( hwnd, LBN_SELCHANGE );
+
+  ListBoxGetItemRect(hwnd, y, &rectsel);
+
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBLButtonUp
+ */
+LONG LBLButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+  WND        *wndPtr;
+
+  ReleaseCapture();
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+  if (lphl->PrevFocused != lphl->ItemFocused)
+    ListBoxSendNotification( hwnd, LBN_SELCHANGE );
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBRButtonUp
+ */
+LONG LBRButtonUp( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+  WND        *wndPtr;
+  
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+  SendMessage(lphl->hWndLogicParent, WM_COMMAND, wndPtr->wIDmenu,
+		MAKELONG(hwnd, LBN_DBLCLK));
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBMouseMove
+ */
+LONG LBMouseMove( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+  WND        *wndPtr;
+  int  y;
+  WORD        wRet;
+  RECT        rect, rectsel;   /* XXX Broken */
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+  if ((wParam & MK_LBUTTON) != 0) {
+    y = HIWORD(lParam);
+    if (y < 4) {
+      if (lphl->FirstVisible > 1) {
+	lphl->FirstVisible--;
+	SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
+	return 0;
+      }
+    }
+    GetClientRect(hwnd, &rect);
+    if (y > (rect.bottom - 4)) {
+      if (lphl->FirstVisible < ListMaxFirstVisible(lphl)) {
+	lphl->FirstVisible++;
+	SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
+	return 0;
+      }
+    }
+    if ((y > 0) && (y < (rect.bottom - 4))) {
+      if ((y < rectsel.top) || (y > rectsel.bottom)) {
+	wRet = ListBoxFindMouse(hwnd, LOWORD(lParam), HIWORD(lParam));
+	if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
+	  lphl->ItemFocused = wRet;
+	  ListBoxSendNotification(hwnd, LBN_SELCHANGE);
+	}
+	else
+	  ListBoxSetCurSel(hwnd, wRet);
+	ListBoxGetItemRect(hwnd, wRet, &rectsel);
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
+      }
+    }
+  }
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBKeyDown
+ */
+LONG LBKeyDown( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+  WND        *wndPtr;
+  HWND        hWndCtl;
+  WORD        wRet;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+  switch(wParam) {
+  case VK_TAB:
+    hWndCtl = GetNextDlgTabItem(lphl->hWndLogicParent,
+				hwnd, !(GetKeyState(VK_SHIFT) < 0));
+    SetFocus(hWndCtl);
+    if(debugging_listbox){
+      if ((GetKeyState(VK_SHIFT) < 0))
+	dprintf_listbox(stddeb,"ListBox PreviousDlgTabItem %04X !\n", hWndCtl);
+      else
+	dprintf_listbox(stddeb,"ListBox NextDlgTabItem %04X !\n", hWndCtl);
+    }
+    break;
+  case VK_HOME:
+    lphl->ItemFocused = 0;
+    break;
+  case VK_END:
+    lphl->ItemFocused = lphl->ItemsCount - 1;
+    break;
+  case VK_LEFT:
+    if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
+      lphl->ItemFocused -= lphl->ItemsPerColumn;
+    }
+    break;
+  case VK_UP:
+    lphl->ItemFocused--;
+    break;
+  case VK_RIGHT:
+    if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
+      lphl->ItemFocused += lphl->ItemsPerColumn;
+    }
+    break;
+  case VK_DOWN:
+    lphl->ItemFocused++;
+    break;
+  case VK_PRIOR:
+    lphl->ItemFocused -= lphl->ItemsVisible;
+    break;
+  case VK_NEXT:
+    lphl->ItemFocused += lphl->ItemsVisible;
+    break;
+  case VK_SPACE:
+    wRet = ListBoxGetSel(hwnd, lphl->ItemFocused);
+    ListBoxSetSel(hwnd, lphl->ItemFocused, !wRet);
+    break;
+  default:
+    ListBoxFindNextMatch(hwnd, wParam);
+    return 0;
+  }
+
+  if (lphl->ItemFocused < 0) lphl->ItemFocused = 0;
+  if (lphl->ItemFocused >= lphl->ItemsCount)
+    lphl->ItemFocused = lphl->ItemsCount - 1;
+
+  if (lphl->ItemsVisible != 0)
+    lphl->FirstVisible = lphl->ItemFocused / lphl->ItemsVisible * 
+      lphl->ItemsVisible + 1;
+
+  if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
+  if (lphl->FirstVisible > ListMaxFirstVisible(lphl))
+    lphl->FirstVisible = ListMaxFirstVisible(lphl);
+
+  if ((wndPtr->dwStyle & LBS_MULTIPLESEL) != LBS_MULTIPLESEL) {
+    ListBoxSetCurSel(hwnd, lphl->ItemFocused);
+    ListBoxSendNotification(hwnd, LBN_SELCHANGE);
+  }
+
+  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetRedraw
+ */
+LONG LBSetRedraw( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+  WND        *wndPtr;
+
+  dprintf_listbox(stddeb,"ListBox WM_SETREDRAW hWnd=%04X w=%04X !\n", hwnd, wParam);
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+  lphl->bRedrawFlag = wParam;
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetFont
+ */
+
+LONG LBSetFont( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+  WND        *wndPtr;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return 0;
+
+  if (wParam == 0)
+    lphl->hFont = GetStockObject(SYSTEM_FONT);
+  else
+    lphl->hFont = wParam;
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBPaint
+ */
+LONG LBPaint( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  RepaintListBox(hwnd);
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetFocus
+ */
+LONG LBSetFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+  WND       *wndPtr;
+
+  dprintf_listbox(stddeb,"ListBox WM_SETFOCUS !\n");
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBKillFocus
+ */
+LONG LBKillFocus( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  dprintf_listbox(stddeb,"ListBox WM_KILLFOCUS !\n");
+
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+  
+  return 0;
+}
+
+/***********************************************************************
+ *           LBResetContent
+ */
+LONG LBResetContent( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  dprintf_listbox(stddeb,"ListBox LB_RESETCONTENT !\n");
+  ListBoxResetContent(hwnd);
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBDir
+ */
+LONG LBDir( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  WORD   wRet;
+  dprintf_listbox(stddeb,"ListBox LB_DIR !\n");
+
+  wRet = ListBoxDirectory(hwnd, wParam,
+			  (LPSTR)PTR_SEG_TO_LIN(lParam));
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+  return wRet;
+}
+
+/***********************************************************************
+ *           LBAddString
+ */
+LONG LBAddString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  WORD  wRet;
+  WND  *wndPtr;
+
+  wndPtr = WIN_FindWndPtr(hwnd);
+
+  if (HasStrings(wndPtr))
+    wRet = ListBoxAddString(hwnd, (LPSTR)PTR_SEG_TO_LIN(lParam));
+  else
+    wRet = ListBoxAddString(hwnd, (LPSTR)lParam);
+
+  return wRet;
+}
+
+/***********************************************************************
+ *           LBGetText
+ */
+LONG LBGetText( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LONG   wRet;
+
+  dprintf_listbox(stddeb, "LB_GETTEXT  wParam=%d\n",wParam);
+  wRet = ListBoxGetText(hwnd, wParam,
+			(LPSTR)PTR_SEG_TO_LIN(lParam), FALSE);
+
+  return wRet;
+}
+
+/***********************************************************************
+ *           LBInsertString
+ */
+LONG LBInsertString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  WORD  wRet;
+  WND  *wndPtr;
+
+  wndPtr = WIN_FindWndPtr(hwnd);
+
+  if (HasStrings(wndPtr))
+    wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)PTR_SEG_TO_LIN(lParam));
+  else
+    wRet = ListBoxInsertString(hwnd, wParam, (LPSTR)lParam);
+
+  return wRet;
+}
+
+/***********************************************************************
+ *           LBDeleteString
+ */    
+LONG LBDeleteString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  return ListBoxDeleteString(hwnd, wParam); 
+}
+
+/***********************************************************************
+ *           LBFindString
+ */
+LONG LBFindString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  return ListBoxFindString(hwnd, wParam,
+			   (LPSTR)PTR_SEG_TO_LIN(lParam));
+}
+
+/***********************************************************************
+ *           LBGetCaretIndex
+ */
+LONG LBGetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+  if (lphl == NULL) return LB_ERR;
+
+  return lphl->ItemFocused;
+}
+
+/***********************************************************************
+ *           LBGetCount
+ */
+LONG LBGetCount( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+  return lphl->ItemsCount;
+}
+
+/***********************************************************************
+ *           LBGetCurSel
+ */
+LONG LBGetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+  dprintf_listbox(stddeb,"ListBox LB_GETCURSEL %u !\n", 
+		  lphl->ItemFocused);
+  return lphl->ItemFocused;
+}
+
+/***********************************************************************
+ *           LBGetHorizontalExtent
+ */
+LONG LBGetHorizontalExtent( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{    
+  return 0;
+}
+
+/***********************************************************************
+ *           LBGetItemData
+ */
+LONG LBGetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+    dprintf_listbox(stddeb, "LB_GETITEMDATA wParam=%x\n", wParam);
+    return ListBoxGetText(hwnd, wParam,
+			  (LPSTR)PTR_SEG_TO_LIN(lParam), TRUE);
+}
+
+/***********************************************************************
+ *           LBGetItemHeight
+ */
+LONG LBGetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  RECT   rect;
+
+  ListBoxGetItemRect(hwnd, wParam, &rect);
+  return (rect.bottom - rect.top);
+}
+
+/***********************************************************************
+ *           LBGetItemRect
+ */
+LONG LBGetItemRect( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  return ListBoxGetItemRect (hwnd, wParam, PTR_SEG_TO_LIN(lParam));
+}
+
+/***********************************************************************
+ *           LBGetSel
+ */
+LONG LBGetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  return ListBoxGetSel (hwnd, wParam);
+}
+
+/***********************************************************************
+ *           LBGetSelCount
+ */
+LONG LBGetSelCount( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST   lphl;
+  LPLISTSTRUCT lpls;
+  int          cnt = 0;
+  WND        *wndPtr;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
+
+  lpls = lphl->lpFirst;
+
+  while (lpls != NULL) {
+    if (lpls->dis.itemState > 0) cnt++;
+
+    lpls = lpls->lpNext;
+  }
+
+  return cnt;
+}
+
+/***********************************************************************
+ *           LBGetSelItems
+ */
+LONG LBGetSelItems( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST   lphl;
+  LPLISTSTRUCT lpls;
+  int          cnt, idx;
+  WND         *wndPtr;
+  int         *lpItems = PTR_SEG_TO_LIN(lParam);
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
+
+  if (wParam == 0) return 0;
+
+  lpls = lphl->lpFirst;
+  cnt = 0; idx = 0;
+
+  while (lpls != NULL) {
+    if (lpls->dis.itemState > 0) lpItems[cnt++] = idx;
+
+    if (cnt == wParam) break;
+    idx++;
+    lpls = lpls->lpNext;
+  }
+
+  return cnt;
+}
+
+/***********************************************************************
+ *           LBGetTextLen
+ */
+LONG LBGetTextLen( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST   lphl;
+  LPLISTSTRUCT lpls;
+  WND         *wndPtr;
+  int          cnt = 0;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!HasStrings(wndPtr)) return LB_ERR;
+
+  if (wParam >= lphl->ItemsCount) return LB_ERR;
+    
+  lpls = lphl->lpFirst;
+
+  while (cnt++ < wParam) lpls = lpls->lpNext;
+  
+  return strlen(lpls->itemText);
+}
+
+/***********************************************************************
+ *           LBGetDlgCode
+ */
+LONG LBGetDlgCode( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  return DLGC_WANTALLKEYS;
+}
+
+/***********************************************************************
+ *           LBGetTopIndex
+ */
+LONG LBGetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+  if (lphl == NULL) return LB_ERR;
+
+  return (lphl->FirstVisible - 1);
+}
+
+
+/***********************************************************************
+ *           LBSelectString
+ */
+LONG LBSelectString( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  WND  *wndPtr;
+  WORD  wRet;
+
+  wndPtr = WIN_FindWndPtr(hwnd);
+
+  wRet = ListBoxFindString(hwnd, wParam,
+			   (LPSTR)PTR_SEG_TO_LIN(lParam));
+
+  /* XXX add functionality here */
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSelItemRange
+ */
+LONG LBSelItemRange( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST   lphl;
+  LPLISTSTRUCT lpls;
+  WND         *wndPtr;
+  WORD         cnt;
+  WORD         first = LOWORD(lParam);
+  WORD         last = HIWORD(lParam);
+  BOOL         select = wParam;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return LB_ERR;
+
+  if (first >= lphl->ItemsCount ||
+      last >= lphl->ItemsCount) return LB_ERR;
+
+  lpls = lphl->lpFirst;
+  cnt = 0;
+
+  while (lpls != NULL) {
+    if (cnt++ >= first)
+      lpls->dis.itemState = select ? ODS_SELECTED : 0;
+
+    if (cnt > last)
+      break;
+
+    lpls = lpls->lpNext;
+  }
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetCaretIndex
+ */
+LONG LBSetCaretIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST   lphl;
+  WND         *wndPtr;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return 0;
+  if (wParam >= lphl->ItemsCount) return LB_ERR;
+
+  lphl->ItemFocused = wParam;
+  ListBoxScrolltoFocus (hwnd);
+
+  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetColumnWidth
+ */
+LONG LBSetColumnWidth( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST   lphl;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+  if (lphl == NULL) return LB_ERR;
+  lphl->ColumnsWidth = wParam;
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetHorizontalExtent
+ */
+LONG LBSetHorizontalExtent( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetItemData
+ */
+LONG LBSetItemData( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  dprintf_listbox(stddeb, "LB_SETITEMDATA  wParam=%x  lParam=%lx\n", wParam, lParam);
+  return ListBoxSetItemData(hwnd, wParam, lParam);
+}
+
+/***********************************************************************
+ *           LBSetTabStops
+ */
+LONG LBSetTabStops( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+
+  if (lphl->TabStops != NULL) {
+    lphl->iNumStops = 0;
+    free (lphl->TabStops);
+  }
+
+  lphl->TabStops = malloc (wParam * sizeof (short));
+  if (lphl->TabStops) {
+    lphl->iNumStops = wParam;
+    memcpy (lphl->TabStops, PTR_SEG_TO_LIN(lParam), wParam * sizeof (short));
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+/***********************************************************************
+ *           LBSetCurSel
+ */
+LONG LBSetCurSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST  lphl;
+  WORD  wRet;
+
+  lphl = ListBoxGetStorageHeader(hwnd);
+  if (lphl == NULL) return LB_ERR; 
+
+  dprintf_listbox(stddeb,"ListBox LB_SETCURSEL wParam=%x !\n", 
+		  wParam);
+
+  wRet = ListBoxSetCurSel(hwnd, wParam);
+
+  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+
+  return wRet;
+}
+
+/***********************************************************************
+ *           LBSetSel
+ */
+LONG LBSetSel( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  WORD wRet;
+
+  dprintf_listbox(stddeb,"ListBox LB_SETSEL wParam=%x lParam=%lX !\n", wParam, lParam);
+
+  wRet = ListBoxSetSel(hwnd, LOWORD(lParam), wParam);
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+
+  return wRet;
+}
+
+/***********************************************************************
+ *           LBSetTopIndex
+ */
+LONG LBSetTopIndex( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{
+  LPHEADLIST lphl;
+
+  dprintf_listbox(stddeb,"ListBox LB_SETTOPINDEX wParam=%x !\n",
+		  wParam);
+  lphl = ListBoxGetStorageHeader(hwnd);
+  lphl->FirstVisible = wParam;
+  SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+
+  return 0;
+}
+
+/***********************************************************************
+ *           LBSetItemHeight
+ */
+LONG LBSetItemHeight( HWND hwnd, WORD message, WORD wParam, LONG lParam)
+
+{
+  WORD  wRet;
+
+  dprintf_listbox(stddeb,"ListBox LB_SETITEMHEIGHT wParam=%x lParam=%lX !\n", wParam, lParam);
+  wRet = ListBoxSetItemHeight(hwnd, wParam, lParam);
+  return wRet;
+}
+
+
+/***********************************************************************
+ *           ListBoxWndProc 
+ */
+
+LONG ListBoxWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
+
+{ 
+  int idx = 0;
+  int table_size = sizeof (methods) / sizeof (msg_tbl);
+
+  while (idx < table_size) {
+    if (message == methods[idx].message) {
+      return (*(methods[idx].handler))(hwnd, message, wParam, lParam);
+    }
+    idx++;
+  }
+  
+  return DefWindowProc (hwnd, message, wParam, lParam);
+}
+
+
+LPLISTSTRUCT ListBoxGetItem(HWND hwnd, UINT uIndex)
+
+{
+  LPHEADLIST lphl = ListBoxGetStorageHeader(hwnd);
+  LPLISTSTRUCT lpls;
+  UINT         Count = 0;
+
+  if (uIndex >= lphl->ItemsCount) return NULL;
+
+  lpls = lphl->lpFirst;
+
+  while (Count++ < uIndex) lpls = lpls->lpNext;
+
+  return lpls;
+}
+
+ 
 LPHEADLIST ListBoxGetWindowAndStorage(HWND hwnd, WND **wndPtr)
 {
     WND  *Ptr;
@@ -515,266 +1256,240 @@
 }
 
 
-void StdDrawListBox(HWND hwnd)
+void ListBoxDrawItem (HWND hwnd, HDC hdc, LPLISTSTRUCT lpls,
+		      WORD itemAction, WORD itemState)
+
 {
-	WND 	*wndPtr;
-	LPHEADLIST  lphl;
-	LPLISTSTRUCT lpls;
-	PAINTSTRUCT ps;
-	HBRUSH 	hBrush;
-	int 	OldBkMode;
-	DWORD 	dwOldTextColor;
-	HDC 	hdc;
-	RECT 	rect;
-	int     i, h, h2, maxwidth, ipc;
-	h = 0;
-	hdc = BeginPaint( hwnd, &ps );
-	if (!IsWindowVisible(hwnd)) {
-		EndPaint( hwnd, &ps );
-		return;
-		}
-	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-	if (lphl == NULL) goto EndOfPaint;
-	if (!lphl->bRedrawFlag) goto EndOfPaint;
-	SelectObject(hdc, lphl->hFont);
-	hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
-		    MAKELONG(hwnd, CTLCOLOR_LISTBOX));
-	if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
-	GetClientRect(hwnd, &rect);
-	FillRect(hdc, &rect, hBrush);
-	maxwidth = rect.right;
-	rect.right = lphl->ColumnsWidth;
-	if (lphl->ItemsCount == 0) goto EndOfPaint;
-	lpls = lphl->lpFirst;
-	if (lpls == NULL) goto EndOfPaint;
-	lphl->ItemsVisible = 0;
-	lphl->ItemsPerColumn = ipc = 0;
-	for(i = 1; i <= lphl->ItemsCount; i++) {
-	    if (i >= lphl->FirstVisible) {
-	        if (lpls == NULL) break;
-		if ((h + lpls->dis.rcItem.bottom - lpls->dis.rcItem.top) > rect.bottom) {
-		    if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
-			lphl->ItemsPerColumn = max(lphl->ItemsPerColumn, ipc);
-			ipc = 0;
-			h = 0;
-			rect.left += lphl->ColumnsWidth;
-			rect.right += lphl->ColumnsWidth;
-			if (rect.left > maxwidth) break;
-			}
-		    else 
-			break;
-		    }
-		h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
-		lpls->dis.rcItem.top = h;
-		lpls->dis.rcItem.bottom = h + h2;
-		lpls->dis.rcItem.left = rect.left;
-		lpls->dis.rcItem.right = rect.right;
-		OldBkMode = SetBkMode(hdc, TRANSPARENT);
-		if (lpls->dis.itemState != 0) {
-			dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
-		    FillRect(hdc, &lpls->dis.rcItem, GetStockObject(BLACK_BRUSH));
-		    }
-		TextOut(hdc, rect.left + 5, h + 2, (char *)lpls->itemText, 
-			strlen((char *)lpls->itemText));
-		if (lpls->dis.itemState != 0) {
-			SetTextColor(hdc, dwOldTextColor);
-		    }
-		SetBkMode(hdc, OldBkMode);
-		if ((lphl->ItemFocused == i - 1) && GetFocus() == hwnd) {
-		    DrawFocusRect(hdc, &lpls->dis.rcItem);
-		    }
-		h += h2;
-		lphl->ItemsVisible++;
-		ipc++;
-		}
-	    if (lpls->lpNext == NULL) goto EndOfPaint;
-	    lpls = (LPLISTSTRUCT)lpls->lpNext;
-	}
-EndOfPaint:
+  LPHEADLIST  lphl;
+  WND        *wndPtr;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  if (OWNER_DRAWN(wndPtr)) {
+    DRAWITEMSTRUCT   *dis = USER_HEAP_LIN_ADDR(lphl->hDrawItemStruct);
+
+    memcpy (dis, &lpls->dis, sizeof(DRAWITEMSTRUCT));
+
+    dis->CtlType  = ODT_LISTBOX;
+    dis->hDC      = hdc;
+
+    if ((!dis->CtlID) && lphl->hWndLogicParent) {
+      WND   *ParentWndPtr;
+
+      ParentWndPtr = WIN_FindWndPtr(lphl->hWndLogicParent);
+      dis->CtlID   = ParentWndPtr->wIDmenu;
+    }
+
+    if (HasStrings(wndPtr)) dis->itemData = (DWORD)lpls->itemText;
+   
+    dis->itemAction = itemAction;
+    dis->itemState  = itemState;
+
+    SendMessage(lphl->hWndLogicParent, WM_DRAWITEM, 
+		0, (LPARAM)USER_HEAP_SEG_ADDR(lphl->hDrawItemStruct));
+  }
+  else {
+
+    if (itemAction == ODA_DRAWENTIRE ||
+	itemAction == ODA_SELECT) {
+      int 	OldBkMode;
+      DWORD 	dwOldTextColor;
+
+      OldBkMode = SetBkMode(hdc, TRANSPARENT);
+
+      if (itemState != 0) {
+	dwOldTextColor = SetTextColor(hdc, 0x00FFFFFFL);
+	FillRect(hdc, &lpls->dis.rcItem, GetStockObject(BLACK_BRUSH));
+      }
+
+      if (wndPtr->dwStyle & LBS_USETABSTOPS)
+	TabbedTextOut(hdc, lpls->dis.rcItem.left + 5, 
+		      lpls->dis.rcItem.top + 2, 
+		      (char *)lpls->itemText, 
+		      strlen((char *)lpls->itemText), lphl->iNumStops,
+		      lphl->TabStops, 0);
+      else
+	TextOut(hdc, lpls->dis.rcItem.left + 5, lpls->dis.rcItem.top + 2, 
+		(char *)lpls->itemText, strlen((char *)lpls->itemText));
+
+      if (itemState != 0) {
+	SetTextColor(hdc, dwOldTextColor);
+      }
+      
+      SetBkMode(hdc, OldBkMode);
+    } else DrawFocusRect(hdc, &lpls->dis.rcItem);
+  }
+
+  return;
+}
+
+void RepaintListBox(HWND hwnd)
+
+{
+  WND 	*wndPtr;
+  LPHEADLIST  lphl;
+  LPLISTSTRUCT lpls;
+  PAINTSTRUCT ps;
+  HBRUSH 	hBrush;
+
+  HDC 	hdc;
+  RECT 	rect;
+  int   i, top, height, maxwidth, ipc;
+
+  top = 0;
+
+  hdc = BeginPaint( hwnd, &ps );
+
+  if (!IsWindowVisible(hwnd)) {
     EndPaint( hwnd, &ps );
-}
+    return;
+  }
 
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) goto EndOfPaint;
+  if (!lphl->bRedrawFlag) goto EndOfPaint;
 
+  SelectObject(hdc, lphl->hFont);
 
-void OwnerDrawListBox(HWND hwnd)
-{
-	WND 	*wndPtr,*ParentWndPtr;
-	LPHEADLIST  lphl;
-	LPLISTSTRUCT lpls;
-	PAINTSTRUCT ps;
-	HBRUSH 	hBrush;
-	DWORD   itemData;
-	HDC 	hdc;
-	RECT 	rect;
-	int     i, h, h2, maxwidth;
-        HANDLE hDrawItemStruct;
-	h = 0;
-	hdc = BeginPaint(hwnd, &ps);
-	if (!IsWindowVisible(hwnd)) {
-		EndPaint( hwnd, &ps );
-		return;
-		}
-	lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-	if (lphl == NULL) goto EndOfPaint;
-	if (!lphl->bRedrawFlag) goto EndOfPaint;
-	hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
-		    MAKELONG(hwnd, CTLCOLOR_LISTBOX));
-	if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
-	GetClientRect(hwnd, &rect);
-	FillRect(hdc, &rect, hBrush);
-	maxwidth = rect.right;
-	rect.right = lphl->ColumnsWidth;
-	if (lphl->ItemsCount == 0) goto EndOfPaint;
-	lpls = lphl->lpFirst;
-	if (lpls == NULL) goto EndOfPaint;
-	lphl->ItemsVisible = 0;
-        hDrawItemStruct = USER_HEAP_ALLOC( sizeof(DRAWITEMSTRUCT) );
-	for (i = 1; i <= lphl->ItemsCount; i++) {
-	    if (i >= lphl->FirstVisible) {
-		lpls->dis.hDC = hdc;
-		lpls->dis.hwndItem = hwnd;
-		lpls->dis.CtlType = ODT_LISTBOX;
-		lpls->dis.itemID = i - 1;
-		if ((!lpls->dis.CtlID) && (lphl->hWndLogicParent)) {
-			ParentWndPtr = WIN_FindWndPtr(lphl->hWndLogicParent);
-			lpls->dis.CtlID = ParentWndPtr->wIDmenu;
-			}
-		h2 = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
-		lpls->dis.rcItem.top = h;
-		lpls->dis.rcItem.bottom = h + h2;
-		lpls->dis.rcItem.left = rect.left;
-		lpls->dis.rcItem.right = rect.right;
-		lpls->dis.itemAction = ODA_DRAWENTIRE;
-/*		if (lpls->dis.itemState != 0) {
-		    lpls->dis.itemAction |= ODA_SELECT;
-		    }
-		if (lphl->ItemFocused == i - 1) {
-		    lpls->dis.itemAction |= ODA_FOCUS;
-		    }*/
-		dprintf_listbox(stddeb,"LBOX WM_DRAWITEM #%d left=%d top=%d right=%d bottom=%d !\n", 
-			i-1, lpls->dis.rcItem.left, lpls->dis.rcItem.top, 
-			lpls->dis.rcItem.right, lpls->dis.rcItem.bottom);
-		dprintf_listbox(stddeb,"LBOX WM_DRAWITEM &dis=%lX CtlID=%u !\n", 
-			(LONG)&lpls->dis, lpls->dis.CtlID);
-		dprintf_listbox(stddeb,"LBOX WM_DRAWITEM %08lX!\n",lpls->dis.itemData);
-		if (HasStrings(wndPtr))
-		  dprintf_listbox(stddeb,"  '%s'\n",lpls->itemText);
-		if (HasStrings(wndPtr)) {
-			itemData = lpls->dis.itemData;
-			lpls->dis.itemData = (DWORD)lpls->itemText;
-			}
-                memcpy( USER_HEAP_LIN_ADDR(hDrawItemStruct), &lpls->dis,
-                        sizeof(DRAWITEMSTRUCT) );
-		SendMessage(lphl->hWndLogicParent, WM_DRAWITEM, 
-                            i-1, (LPARAM)USER_HEAP_SEG_ADDR(hDrawItemStruct));
-		if (HasStrings(wndPtr))
-			lpls->dis.itemData = itemData;
+  hBrush = SendMessage(lphl->hWndLogicParent, WM_CTLCOLOR, (WORD)hdc,
+		       MAKELONG(hwnd, CTLCOLOR_LISTBOX));
 
-/*		if (lpls->dis.itemState != 0) {
-  		    InvertRect(hdc, &lpls->dis.rcItem);  
-		    }  */
-		h += h2;
-		lphl->ItemsVisible++;
-		/* if (h > rect.bottom) goto EndOfPaint;*/
-		}
-	    if (lpls->lpNext == NULL) break;
-	    lpls = (LPLISTSTRUCT)lpls->lpNext;
+  if (hBrush == (HBRUSH)NULL)  hBrush = GetStockObject(WHITE_BRUSH);
+
+  GetClientRect(hwnd, &rect);
+  FillRect(hdc, &rect, hBrush);
+
+  maxwidth = rect.right;
+  rect.right = lphl->ColumnsWidth;
+
+  if (lphl->ItemsCount == 0) goto EndOfPaint;
+
+  lpls = lphl->lpFirst;
+
+  lphl->ItemsVisible = 0;
+  lphl->ItemsPerColumn = ipc = 0;
+
+  for(i = 0; i < lphl->ItemsCount; i++) {
+    if (lpls == NULL) goto EndOfPaint;
+
+    if (i >= lphl->FirstVisible - 1) {
+      height = lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
+
+      if (top > rect.bottom) {
+	if ((wndPtr->dwStyle & LBS_MULTICOLUMN) == LBS_MULTICOLUMN) {
+	  lphl->ItemsPerColumn = max(lphl->ItemsPerColumn, ipc);
+	  ipc = 0;
+	  top = 0;
+	  rect.left += lphl->ColumnsWidth;
+	  rect.right += lphl->ColumnsWidth;
+	  if (rect.left > maxwidth) break;
 	}
-        USER_HEAP_FREE( hDrawItemStruct );
-EndOfPaint:
-        EndPaint( hwnd, &ps );
+	else 
+	  break;
+      }
+
+      lpls->dis.rcItem.top    = top;
+      lpls->dis.rcItem.bottom = top + height;
+      lpls->dis.rcItem.left   = rect.left;
+      lpls->dis.rcItem.right  = rect.right;
+
+      if (OWNER_DRAWN(wndPtr)) {
+	ListBoxDrawItem (hwnd, hdc, lpls, ODA_DRAWENTIRE, 0);
+	if (lpls->dis.itemState)
+	  ListBoxDrawItem (hwnd, hdc, lpls, ODA_SELECT, ODS_SELECTED);
+      }
+      else 
+	ListBoxDrawItem (hwnd, hdc, lpls, ODA_DRAWENTIRE, lpls->dis.itemState);
+
+      if ((lphl->ItemFocused == i) && GetFocus() == hwnd)
+	ListBoxDrawItem (hwnd, hdc, lpls, ODA_FOCUS, ODS_FOCUS);
+
+      top += height;
+      lphl->ItemsVisible++;
+      ipc++;
+    }
+
+    lpls = lpls->lpNext;
+  }
+ EndOfPaint:
+  EndPaint( hwnd, &ps );
 }
 
-
-
 int ListBoxFindMouse(HWND hwnd, int X, int Y)
+
 {
-    WND 		*wndPtr;
-    LPHEADLIST 		lphl;
-    LPLISTSTRUCT	lpls;
-    RECT 		rect;
-    int                 i, h, h2, w, w2;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    if (lphl->ItemsCount == 0) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    GetClientRect(hwnd, &rect);
-    h = w2 = 0;
-    w = lphl->ColumnsWidth;
-    for(i = 1; i <= lphl->ItemsCount; i++) {
-	if (i >= lphl->FirstVisible) {
-	    h2 = h;
-	    h += lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
-	    if ((Y > h2) && (Y < h) &&
-		(X > w2) && (X < w)) return(i - 1);
-	    if (h > rect.bottom) {
-		if ((wndPtr->dwStyle & LBS_MULTICOLUMN) != LBS_MULTICOLUMN) return LB_ERR;
-		h = 0;
-		w2 = w;
-		w += lphl->ColumnsWidth;
-		if (w2 > rect.right) return LB_ERR;
-		}
-	    }
-	if (lpls->lpNext == NULL) return LB_ERR;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	}
-    return(LB_ERR);
+  WND 		*wndPtr;
+  LPHEADLIST 		lphl;
+  LPLISTSTRUCT	lpls;
+  RECT 		rect;
+  int                 i, h, h2, w, w2;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  if (lphl == NULL) return LB_ERR;
+  if (lphl->ItemsCount == 0) return LB_ERR;
+
+  lpls = lphl->lpFirst;
+  if (lpls == NULL) return LB_ERR;
+  GetClientRect(hwnd, &rect);
+  h = w2 = 0;
+  w = lphl->ColumnsWidth;
+
+  for(i = 1; i <= lphl->ItemsCount; i++) {
+    if (i >= lphl->FirstVisible) {
+      h2 = h;
+      h += lpls->dis.rcItem.bottom - lpls->dis.rcItem.top;
+      if ((Y > h2) && (Y < h) &&
+	  (X > w2) && (X < w)) return(i - 1);
+      if (h > rect.bottom) {
+	if ((wndPtr->dwStyle & LBS_MULTICOLUMN) != LBS_MULTICOLUMN) return LB_ERR;
+	h = 0;
+	w2 = w;
+	w += lphl->ColumnsWidth;
+	if (w2 > rect.right) return LB_ERR;
+      }
+    }
+    if (lpls->lpNext == NULL) return LB_ERR;
+    lpls = (LPLISTSTRUCT)lpls->lpNext;
+  }
+  return(LB_ERR);
 }
 
-
-
-int CreateListBoxStruct(HWND hwnd)
-{
-	WND  *wndPtr;
-	LPHEADLIST lphl;
-	wndPtr = WIN_FindWndPtr(hwnd);
-	lphl = (LPHEADLIST)malloc(sizeof(HEADLIST));
-	lphl->lpFirst = NULL;
-	*((LPHEADLIST *)&wndPtr->wExtra[1]) = lphl;     /* HEAD of List */
-	lphl->ItemsCount = 0;
-	lphl->ItemsVisible = 0;
-	lphl->FirstVisible = 1;
-	lphl->ColumnsVisible = 1;
-	lphl->ItemsPerColumn = 0;
-	lphl->StdItemHeight = 15;
-	lphl->ItemFocused = 0;
-	lphl->PrevFocused = 0;
-	lphl->SelCount = 0;
-	lphl->DrawCtlType = ODT_LISTBOX;
-	lphl->bRedrawFlag = TRUE;
-#if 0
-	HeapHandle = GlobalAlloc(GMEM_FIXED, LIST_HEAP_SIZE);
-	HeapBase = GlobalLock(HeapHandle);
-	HEAP_Init(&lphl->Heap, HeapBase, LIST_HEAP_SIZE);
-#endif
-	return TRUE;
-}
-
-
 void ListBoxAskMeasure(WND *wndPtr, LPHEADLIST lphl, LPLISTSTRUCT lpls)  
+
 {
-	MEASUREITEMSTRUCT 	*lpmeasure;
-	HANDLE hTemp = USER_HEAP_ALLOC( sizeof(MEASUREITEMSTRUCT) );
-	lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_LIN_ADDR(hTemp);
-	if (lpmeasure == NULL) {
-		fprintf(stderr,"ListBoxAskMeasure() // Bad allocation of Measure struct !\n");
-		return;
-		}
-	lpmeasure->CtlType = ODT_LISTBOX;
-	lpmeasure->CtlID = wndPtr->wIDmenu;
-	lpmeasure->itemID = lpls->dis.itemID;
-	lpmeasure->itemWidth = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
-	lpmeasure->itemHeight = 0;
-	if (HasStrings(wndPtr))
-		lpmeasure->itemData = (DWORD)lpls->itemText;
-	else
-		lpmeasure->itemData = lpls->dis.itemData;
-	SendMessage(lphl->hWndLogicParent, WM_MEASUREITEM,
-                    0, USER_HEAP_SEG_ADDR(hTemp));
-	lpls->dis.rcItem.right = lpls->dis.rcItem.left + lpmeasure->itemWidth;
-	lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + lpmeasure->itemHeight;
-	USER_HEAP_FREE(hTemp);			
+  MEASUREITEMSTRUCT 	*lpmeasure;
+
+  HANDLE hTemp = USER_HEAP_ALLOC( sizeof(MEASUREITEMSTRUCT) );
+
+  lpmeasure = (MEASUREITEMSTRUCT *) USER_HEAP_LIN_ADDR(hTemp);
+
+  if (lpmeasure == NULL) {
+    fprintf(stderr,"ListBoxAskMeasure() // Bad allocation of Measure struct !\n");
+    return;
+  }
+ 
+  lpmeasure->CtlType    = ODT_LISTBOX;
+  lpmeasure->CtlID      = wndPtr->wIDmenu;
+  lpmeasure->itemID     = lpls->dis.itemID;
+  lpmeasure->itemWidth  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
+  lpmeasure->itemHeight = 0;
+
+  if (HasStrings(wndPtr))
+    lpmeasure->itemData = (DWORD)lpls->itemText;
+  else
+    lpmeasure->itemData = lpls->dis.itemData;
+
+  SendMessage(lphl->hWndLogicParent, WM_MEASUREITEM,
+	      0, USER_HEAP_SEG_ADDR(hTemp));
+
+  if (wndPtr->dwStyle & LBS_OWNERDRAWFIXED) {
+    lphl->StdItemHeight = lpmeasure->itemHeight;
+  }
+
+  lpls->dis.rcItem.right  = lpls->dis.rcItem.left + lpmeasure->itemWidth;
+  lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + lpmeasure->itemHeight;
+  USER_HEAP_FREE(hTemp);			
 }
 
 
@@ -786,6 +1501,7 @@
     
     lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
     if (lphl == NULL) return LB_ERR;
+
     if (HasStrings(wndPtr) && (wndPtr->dwStyle & LBS_SORT)) {
 	LPLISTSTRUCT lpls = lphl->lpFirst;
 	for (pos = 0; lpls; lpls = lpls->lpNext, pos++)
@@ -796,193 +1512,230 @@
 }
 
 int ListBoxInsertString(HWND hwnd, UINT uIndex, LPSTR newstr)
-{
-    WND  	*wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT *lppls, lplsnew;
-    HANDLE 	hItem;
-    HANDLE 	hStr;
-    LPSTR	str;
-    UINT	Count;
-    
-    dprintf_listbox(stddeb,"ListBoxInsertString(%04X, %d, %p);\n", 
-		    hwnd, uIndex, newstr);
-    
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    
-    if (uIndex == (UINT)-1)
-	uIndex = lphl->ItemsCount;
-    if (uIndex > lphl->ItemsCount) return LB_ERR;
-    lppls = (LPLISTSTRUCT *) &lphl->lpFirst;
-    
-    for(Count = 0; Count < uIndex; Count++) {
-	if (*lppls == NULL) return LB_ERR;
-	lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
-        }
-    
-	hItem = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, sizeof(LISTSTRUCT));
-	lplsnew = (LPLISTSTRUCT) LIST_HEAP_ADDR(lphl, hItem);
-    if (lplsnew == NULL) {
-		printf("ListBoxInsertString() // Bad allocation of new item !\n");
-		return LB_ERRSPACE;
-		}
-	ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
-	lplsnew->hMem = hItem;
-	lplsnew->lpNext = *lppls;
-	*lppls = lplsnew;
-	lphl->ItemsCount++;
-	hStr = 0;
 
-	if (HasStrings(wndPtr)) {
-		hStr = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, strlen(newstr) + 1);
-		str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
-		if (str == NULL) return LB_ERRSPACE;
-		strcpy(str, newstr);
-		newstr = str;
-		lplsnew->itemText = str;
-		dprintf_listbox(stddeb,"ListBoxInsertString // LBS_HASSTRINGS after strcpy '%s'\n", str);
-		}
-	else {
-		lplsnew->itemText = NULL;
-		lplsnew->dis.itemData = (DWORD)newstr;
-		}
-	lplsnew->dis.itemID = lphl->ItemsCount;
-	lplsnew->hData = hStr;
-	if (((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE) ||
-		((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED))
-		ListBoxAskMeasure(wndPtr, lphl, lplsnew);
-        SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), 
-                       (lphl->FirstVisible != 1 && lphl->bRedrawFlag));
-	if (lphl->ItemsPerColumn != 0)
-		SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
-			lphl->ItemsPerColumn + 1,
-			(lphl->FirstVisible != 1 && lphl->bRedrawFlag));
-	if ((lphl->FirstVisible <= uIndex) &&
-		((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
-		InvalidateRect(hwnd, NULL, TRUE);
-		UpdateWindow(hwnd);
-		}
-        dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
-	return uIndex;
+{
+  WND  	       *wndPtr;
+  LPHEADLIST 	lphl;
+  LPLISTSTRUCT *lppls, lplsnew;
+  HANDLE 	hItem;
+  HANDLE 	hStr;
+  LPSTR	str;
+  UINT	Count;
+    
+  dprintf_listbox(stddeb,"ListBoxInsertString(%04X, %d, %p);\n", 
+		  hwnd, uIndex, newstr);
+    
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+    
+  if (uIndex == (UINT)-1)
+    uIndex = lphl->ItemsCount;
+
+  if (uIndex > lphl->ItemsCount) return LB_ERR;
+
+  lppls = (LPLISTSTRUCT *) &lphl->lpFirst;
+    
+  for(Count = 0; Count < uIndex; Count++) {
+    if (*lppls == NULL) return LB_ERR;
+    lppls = (LPLISTSTRUCT *) &(*lppls)->lpNext;
+  }
+    
+  hItem = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, sizeof(LISTSTRUCT));
+  lplsnew = (LPLISTSTRUCT) LIST_HEAP_ADDR(lphl, hItem);
+
+  if (lplsnew == NULL) {
+    printf("ListBoxInsertString() // Bad allocation of new item !\n");
+    return LB_ERRSPACE;
+  }
+
+  ListBoxDefaultItem(hwnd, wndPtr, lphl, lplsnew);
+  lplsnew->hMem = hItem;
+  lplsnew->lpNext = *lppls;
+  *lppls = lplsnew;
+  lphl->ItemsCount++;
+  hStr = 0;
+
+  if (HasStrings(wndPtr)) {
+    hStr = LIST_HEAP_ALLOC(lphl, GMEM_MOVEABLE, strlen(newstr) + 1);
+    str = (LPSTR)LIST_HEAP_ADDR(lphl, hStr);
+    if (str == NULL) return LB_ERRSPACE;
+    strcpy(str, newstr);
+    newstr = str;
+    lplsnew->itemText = str;
+    dprintf_listbox(stddeb,"ListBoxInsertString // LBS_HASSTRINGS after strcpy '%s'\n", str);
+  }
+  else {
+    lplsnew->itemText = NULL;
+    lplsnew->dis.itemData = (DWORD)newstr;
+  }
+
+  lplsnew->dis.itemID = lphl->ItemsCount;
+  lplsnew->hData = hStr;
+ 
+  if ((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) && (lphl->ItemsCount == 1)) {
+    ListBoxAskMeasure(wndPtr, lphl, lplsnew);
+  }
+
+  if (wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE)
+    ListBoxAskMeasure(wndPtr, lphl, lplsnew);   
+
+  SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), 
+		 (lphl->FirstVisible != 1 && lphl->bRedrawFlag));
+
+  if (lphl->ItemsPerColumn != 0)
+    SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
+		   lphl->ItemsPerColumn + 1,
+		   (lphl->FirstVisible != 1 && lphl->bRedrawFlag));
+
+  if ((lphl->FirstVisible <= uIndex) &&
+      ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
+    InvalidateRect(hwnd, NULL, TRUE);
+    UpdateWindow(hwnd);
+  }
+
+  dprintf_listbox(stddeb,"ListBoxInsertString // count=%d\n", lphl->ItemsCount);
+  return uIndex;
 }
 
 
 int ListBoxGetText(HWND hwnd, UINT uIndex, LPSTR OutStr, BOOL bItemData)
+
 {
-    WND  	*wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls;
-    UINT	Count;
-    if ((!OutStr)&&(!bItemData))
-	fprintf(stderr, "ListBoxGetText // OutStr==NULL\n"); 
-    if (!bItemData)   	*OutStr=0;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    if (uIndex >= lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    if (uIndex > lphl->ItemsCount) return LB_ERR;
-    for(Count = 0; Count < uIndex; Count++) {
-	if (lpls->lpNext == NULL) return LB_ERR;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-    }
-    if (bItemData)
-	return lpls->dis.itemData;
-    if (!(HasStrings(wndPtr)) )
-      {
-	*((long *)OutStr) = lpls->dis.itemData;
-	return 4;
-      }
+  WND  	*wndPtr;
+  LPLISTSTRUCT lpls;
+
+  wndPtr = WIN_FindWndPtr(hwnd);
+
+  if (!OutStr && !bItemData) {
+    dprintf_listbox(stddeb, "ListBoxGetText // OutStr==NULL\n");
+    return 0;
+  }
+
+  if (!bItemData) *OutStr=0;
+
+  if ((lpls = ListBoxGetItem (hwnd, uIndex)) == NULL) 
+    return 0;
+
+  if (bItemData)
+    return lpls->dis.itemData;
+
+  if (!HasStrings(wndPtr)) {
+    *((long *)OutStr) = lpls->dis.itemData;
+    return 4;
+  }
 	
-    strcpy(OutStr, lpls->itemText);
-    return strlen(OutStr);
+  strcpy(OutStr, lpls->itemText);
+  return strlen(OutStr);
 }
 
 int ListBoxSetItemData(HWND hwnd, UINT uIndex, DWORD ItemData)
+
 {
-    WND         *wndPtr;
-    LPHEADLIST  lphl;
-    LPLISTSTRUCT lpls;
-    UINT        Count;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    if (uIndex >= lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    if (uIndex > lphl->ItemsCount) return LB_ERR;
-    for(Count = 0; Count < uIndex; Count++) {
-        if (lpls->lpNext == NULL) return LB_ERR;
-        lpls = (LPLISTSTRUCT)lpls->lpNext;
-    }
-    lpls->dis.itemData = ItemData;
-    return 1;
+  LPLISTSTRUCT lpls;
+
+  if ((lpls = ListBoxGetItem(hwnd, uIndex)) == NULL)
+    return 0;
+
+  lpls->dis.itemData = ItemData;
+  return 1;
 }
 
 
 int ListBoxDeleteString(HWND hwnd, UINT uIndex)
+
 {
-    WND  	*wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
-    UINT	Count;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    if (uIndex >= lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    if (uIndex > lphl->ItemsCount) return LB_ERR;
-    if( uIndex == 0 )
-      lphl->lpFirst = lpls->lpNext;
-    else {
-      for(Count = 0; Count < uIndex; Count++) {
-	if (lpls->lpNext == NULL) return LB_ERR;
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-      }
-      lpls2->lpNext = (LPLISTSTRUCT)lpls->lpNext;
+  WND  	*wndPtr;
+  LPHEADLIST 	lphl;
+  LPLISTSTRUCT lpls, lpls2;
+  UINT	Count;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (uIndex >= lphl->ItemsCount) return LB_ERR;
+
+  lpls = lphl->lpFirst;
+  if (lpls == NULL) return LB_ERR;
+
+  if( uIndex == 0 )
+    lphl->lpFirst = lpls->lpNext;
+  else {
+    for(Count = 0; Count < uIndex; Count++) {
+      if (lpls->lpNext == NULL) return LB_ERR;
+
+      lpls2 = lpls;
+      lpls = (LPLISTSTRUCT)lpls->lpNext;
     }
-    lphl->ItemsCount--;
-    if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
-    if (lpls->hMem != 0) LIST_HEAP_FREE(lphl, lpls->hMem);
-    SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
-    if (lphl->ItemsPerColumn != 0)
-	SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
-	    lphl->ItemsPerColumn + 1, TRUE);
-    if ((lphl->FirstVisible <= uIndex) &&
-        ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
-        InvalidateRect(hwnd, NULL, TRUE);
-        UpdateWindow(hwnd);
-        }
-    return lphl->ItemsCount;
+    lpls2->lpNext = (LPLISTSTRUCT)lpls->lpNext;
+  }
+
+  lphl->ItemsCount--;
+
+  if (lpls->hData != 0) LIST_HEAP_FREE(lphl, lpls->hData);
+  if (lpls->hMem != 0) LIST_HEAP_FREE(lphl, lpls->hMem);
+
+  SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
+  if (lphl->ItemsPerColumn != 0)
+    SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
+		   lphl->ItemsPerColumn + 1, TRUE);
+
+  if ((lphl->FirstVisible <= uIndex) &&
+      ((lphl->FirstVisible + lphl->ItemsVisible) >= uIndex)) {
+    InvalidateRect(hwnd, NULL, TRUE);
+    UpdateWindow(hwnd);
+  }
+
+  return lphl->ItemsCount;
 }
 
 
 int ListBoxFindString(HWND hwnd, UINT nFirst, LPSTR MatchStr)
 {
-    WND          *wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls;
-    UINT	Count;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    if (nFirst > lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    Count = 0;
-    while(lpls != NULL) {
-      if (HasStrings(wndPtr))
-	{
-	  if (strcmp(lpls->itemText, MatchStr) == 0) return Count;
-	}
-      else
-	{
-	  if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
-	}
-      lpls = (LPLISTSTRUCT)lpls->lpNext;
-      Count++;
+  WND          *wndPtr;
+  LPHEADLIST   lphl;
+  LPLISTSTRUCT lpls;
+  UINT	       Count;
+  UINT         First = nFirst + 1;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  if (lphl == NULL) return LB_ERR;
+
+  if (First > lphl->ItemsCount) return LB_ERR;
+ 
+  lpls = ListBoxGetItem(hwnd, First);
+  Count = 0;
+  while(lpls != NULL) {
+    if (HasStrings(wndPtr)) {
+      if (strstr(lpls->itemText, MatchStr) == lpls->itemText) return Count;
+    } else if (wndPtr->dwStyle & LBS_SORT) {
+      /* XXX Do a compare item */
     }
-    return LB_ERR;
+    else
+      if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
+
+    lpls = lpls->lpNext;
+    Count++;
+  }
+
+  /* Start over at top */
+  Count = 0;
+  lpls = lphl->lpFirst;
+
+  while (Count < First) {
+    if (HasStrings(wndPtr)) {
+      if (strstr(lpls->itemText, MatchStr) == lpls->itemText) return Count;
+    } else if (wndPtr->dwStyle & LBS_SORT) {
+      /* XXX Do a compare item */
+    }
+    else
+      if (lpls->dis.itemData == (DWORD)MatchStr) return Count;
+
+    lpls = lpls->lpNext;
+    Count++;
+  }
+
+  return LB_ERR;
 }
 
 
@@ -990,112 +1743,123 @@
 {
     WND  *wndPtr;
     LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
+    LPLISTSTRUCT lpls;
     UINT	i;
+
     lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
     if (lphl == NULL) return LB_ERR;
+
+    if (lphl->ItemsCount == 0) return 0;
+
     lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
+
     dprintf_listbox(stddeb, "ListBoxResetContent // ItemCount = %d\n",
 	lphl->ItemsCount);
-    for(i = 0; i <= lphl->ItemsCount; i++) {
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	if (i != 0) {
-	    dprintf_listbox(stddeb,"ResetContent #%u\n", i);
-	    if (lpls2->hData != 0 && lpls2->hData != lpls2->hMem)
-		LIST_HEAP_FREE(lphl, lpls2->hData);
-	    if (lpls2->hMem != 0) LIST_HEAP_FREE(lphl, lpls2->hMem);
-	    }  
-	if (lpls == NULL)  break;
+
+    for(i = 0; i < lphl->ItemsCount; i++) {
+      LPLISTSTRUCT lpls2;
+
+      if (lpls == NULL) return LB_ERR;
+
+      lpls2 = lpls->lpNext;
+
+      if (i != 0) {
+	dprintf_listbox(stddeb,"ResetContent #%u\n", i);
+	if (lpls->hData != 0 && lpls->hData != lpls->hMem)
+	  LIST_HEAP_FREE(lphl, lpls->hData);
+
+	if (lpls->hMem != 0) LIST_HEAP_FREE(lphl, lpls->hMem);
+      }  
+
+      lpls = lpls2;
     }
-    lphl->lpFirst = NULL;
+
+    lphl->lpFirst      = NULL;
     lphl->FirstVisible = 1;
-    lphl->ItemsCount = 0;
-    lphl->ItemFocused = -1;
-    lphl->PrevFocused = -1;
+    lphl->ItemsCount   = 0;
+    lphl->ItemFocused  = -1;
+    lphl->PrevFocused  = -1;
+
     SetScrollRange(hwnd, SB_VERT, 1, ListMaxFirstVisible(lphl), TRUE);
+
     if (lphl->ItemsPerColumn != 0)
 	SetScrollRange(hwnd, SB_HORZ, 1, lphl->ItemsVisible / 
 	    lphl->ItemsPerColumn + 1, TRUE);
+
     InvalidateRect(hwnd, NULL, TRUE);
     UpdateWindow(hwnd);
+
     return TRUE;
 }
 
 
 int ListBoxSetCurSel(HWND hwnd, WORD wIndex)
+
 {
-    WND  *wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
-    UINT	i;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    if( (wIndex != (WORD)(-1)) && (wIndex > lphl->ItemsCount) )
-      return LB_ERR;
-    lphl->ItemFocused = LB_ERR; 
-    if (wIndex >= lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    for(i = 0; i < lphl->ItemsCount; i++) {
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	if (i == wIndex)
-	    lpls2->dis.itemState = 1;
-	else 
-	    if (lpls2->dis.itemState != 0)
-	        lpls2->dis.itemState = 0;
-	if (lpls == NULL)  break;
-    }
+  WND  *wndPtr;
+  LPHEADLIST 	lphl;
+  LPLISTSTRUCT lpls;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (wndPtr->dwStyle & LBS_MULTIPLESEL) return 0;
+
+  if (lphl->ItemFocused != -1) {
+    lpls = ListBoxGetItem(hwnd, lphl->ItemFocused);
+    lpls->dis.itemState = 0;
+  }
+
+  if (wIndex != (UINT)-1) {
     lphl->ItemFocused = wIndex;
-    return wIndex;
+    lpls = ListBoxGetItem(hwnd, wIndex);
+    lpls->dis.itemState = ODS_SELECTED | ODS_FOCUS;
+
+    return 0;
+  }
+
+  return LB_ERR;
 }
 
-
-
 int ListBoxSetSel(HWND hwnd, WORD wIndex, WORD state)
+
 {
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
-    UINT	i;
-    lphl = ListBoxGetStorageHeader(hwnd);
-    if (lphl == NULL) return LB_ERR;
-    if (wIndex >= lphl->ItemsCount) return LB_ERR;
+  LPHEADLIST 	lphl;
+  LPLISTSTRUCT lpls;
+  WND         *wndPtr;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!(wndPtr->dwStyle & LBS_MULTIPLESEL)) return 0;
+
+  if (wIndex == (UINT)-1) {
     lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    for(i = 0; i < lphl->ItemsCount; i++) {
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	if ((i == wIndex) || (wIndex == (WORD)-1)) {
-	    lpls2->dis.itemState = state;
-	    break;
-	    }  
-	if (lpls == NULL)  break;
+
+    while (lpls != NULL) {
+      lpls->dis.itemState = state;
+      lpls = lpls->lpNext;
     }
-    return LB_ERR;
+
+    return 0;
+  }
+
+  if (wIndex >= lphl->ItemsCount) return LB_ERR;
+
+  lpls = ListBoxGetItem(hwnd, wIndex);
+  lpls->dis.itemState = state;
+
+  return 0;
 }
 
 
 int ListBoxGetSel(HWND hwnd, WORD wIndex)
 {
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
-    UINT	i;
-    lphl = ListBoxGetStorageHeader(hwnd);
-    if (lphl == NULL) return LB_ERR;
-    if (wIndex >= lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    for(i = 0; i < lphl->ItemsCount; i++) {
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	if (i == wIndex) {
-	    return lpls2->dis.itemState;
-	    }  
-	if (lpls == NULL)  break;
-    }
-    return LB_ERR;
+  LPLISTSTRUCT lpls;
+
+  if ((lpls = ListBoxGetItem(hwnd, wIndex)) == NULL) return LB_ERR;
+
+  return lpls->dis.itemState;
 }
 
 
@@ -1184,145 +1948,136 @@
 
 
 int ListBoxGetItemRect(HWND hwnd, WORD wIndex, LPRECT lprect)
-{
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
-    UINT	i;
-    lphl = ListBoxGetStorageHeader(hwnd);
-    if (lphl == NULL) return LB_ERR;
-    if (wIndex > lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    for(i = 0; i < lphl->ItemsCount; i++) {
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	if (i == wIndex) {
-	    *(lprect) = lpls2->dis.rcItem;
-	    break;
-	    }  
-	if (lpls == NULL)  break;
-    }
-    return LB_ERR;
-}
 
+{
+  LPLISTSTRUCT lpls;
+
+  if ((lpls = ListBoxGetItem(hwnd, wIndex)) == NULL) return LB_ERR;
+
+  *(lprect) = lpls->dis.rcItem;
+
+  return 0;
+}
 
 
 int ListBoxSetItemHeight(HWND hwnd, WORD wIndex, long height)
+
 {
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls, lpls2;
-    UINT	i;
-    lphl = ListBoxGetStorageHeader(hwnd);
-    if (lphl == NULL) return LB_ERR;
-    if (wIndex > lphl->ItemsCount) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    for(i = 0; i < lphl->ItemsCount; i++) {
-	lpls2 = lpls;
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	if (i == wIndex) {
-	    lpls2->dis.rcItem.bottom = lpls2->dis.rcItem.top + (short)height;
-	    InvalidateRect(hwnd, NULL, TRUE);
-	    UpdateWindow(hwnd);
-	    break;
-	    }  
-	if (lpls == NULL)  break;
-    }
-    return LB_ERR;
+  LPHEADLIST    lphl;
+  WND          *wndPtr;
+  LPLISTSTRUCT  lpls;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+
+  if (!(wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE)) {
+    lphl->StdItemHeight = (short)height;
+    InvalidateRect(hwnd, NULL, TRUE);
+    UpdateWindow(hwnd);
+
+    return 0;
+  }
+
+  if ((lpls = ListBoxGetItem(hwnd, wIndex)) == NULL) return LB_ERR;
+  
+  lpls->dis.rcItem.bottom = lpls->dis.rcItem.top + (short)height;
+  InvalidateRect(hwnd, NULL, TRUE);
+  UpdateWindow(hwnd);
+
+  return 0;
 }
 
-
-
-
-
 int ListBoxDefaultItem(HWND hwnd, WND *wndPtr, 
 	LPHEADLIST lphl, LPLISTSTRUCT lpls)
+
 {
-    RECT	rect;
-	if (wndPtr == NULL || lphl == NULL || lpls == NULL) {
-		fprintf(stderr,"ListBoxDefaultItem() // Bad Pointers !\n");
-		return FALSE;
-		}
-    GetClientRect(hwnd, &rect);
-    SetRect(&lpls->dis.rcItem, 0, 0, rect.right, lphl->StdItemHeight);
-    lpls->dis.CtlType = lphl->DrawCtlType;
-    lpls->dis.CtlID = wndPtr->wIDmenu;
-    lpls->dis.itemID = 0;
-    lpls->dis.itemAction = 0;
-    lpls->dis.itemState = 0;
-    lpls->dis.hwndItem = hwnd;
-    lpls->dis.hDC = 0;
-    lpls->dis.itemData = 0;
-	return TRUE;
+  RECT	rect;
+
+  if (wndPtr == NULL || lphl == NULL || lpls == NULL) {
+    fprintf(stderr,"ListBoxDefaultItem() // Bad Pointers !\n");
+    return FALSE;
+  }
+
+  GetClientRect(hwnd, &rect);
+  SetRect(&lpls->dis.rcItem, 0, 0, rect.right, lphl->StdItemHeight);
+
+  lpls->dis.CtlType    = lphl->DrawCtlType;
+  lpls->dis.CtlID      = wndPtr->wIDmenu;
+  lpls->dis.itemID     = 0;
+  lpls->dis.itemAction = 0;
+  lpls->dis.itemState  = 0;
+  lpls->dis.hwndItem   = hwnd;
+  lpls->dis.hDC        = 0;
+  lpls->dis.itemData   = 0;
+
+  return TRUE;
 }
 
 
 
 int ListBoxFindNextMatch(HWND hwnd, WORD wChar)
+
 {
-    WND  	*wndPtr;
-    LPHEADLIST 	lphl;
-    LPLISTSTRUCT lpls;
-    UINT	Count;
-    lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-    if (lphl == NULL) return LB_ERR;
-    lpls = lphl->lpFirst;
-    if (lpls == NULL) return LB_ERR;
-    if (wChar < ' ') return LB_ERR;
-    if (((wndPtr->dwStyle & LBS_OWNERDRAWFIXED) == LBS_OWNERDRAWFIXED) ||
-	    ((wndPtr->dwStyle & LBS_OWNERDRAWVARIABLE) == LBS_OWNERDRAWVARIABLE)) {
-	if ((wndPtr->dwStyle & LBS_HASSTRINGS) != LBS_HASSTRINGS) { 
-	    return LB_ERR;
-	    }
+  WND  	        *wndPtr;
+  LPHEADLIST 	lphl;
+  LPLISTSTRUCT  lpls;
+  UINT	        Count;
+
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+  if (lphl == NULL) return LB_ERR;
+  lpls = lphl->lpFirst;
+  if (lpls == NULL) return LB_ERR;
+  if (wChar < ' ') return LB_ERR;
+
+  if (!HasStrings(wndPtr)) return LB_ERR;
+
+  Count = 0;
+  while(lpls != NULL) {
+    if (Count > lphl->ItemFocused) {
+      if (*(lpls->itemText) == (char)wChar) {
+	if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
+	  lphl->ItemFocused = Count;
+	  ListBoxScrolltoFocus(hwnd);
 	}
-    Count = 0;
-    while(lpls != NULL) {
-        if (Count > lphl->ItemFocused) {
-	    if (*(lpls->itemText) == (char)wChar) {
-		lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
-		if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
-		if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
-		    lphl->ItemFocused = Count;
-		    }
-		else {
-		    ListBoxSetCurSel(hwnd, Count);
-		    }
-		SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-	        InvalidateRect(hwnd, NULL, TRUE);
-	        UpdateWindow(hwnd);
-	        return Count;
-	        }
-	    }
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	Count++;
+	else {
+	  ListBoxSetCurSel(hwnd, Count);
 	}
-    Count = 0;
-    lpls = lphl->lpFirst;
-    while(lpls != NULL) {
-	if (*(lpls->itemText) == (char)wChar) {
-	    if (Count == lphl->ItemFocused)    return LB_ERR;
-	    lphl->FirstVisible = Count - lphl->ItemsVisible / 2;
-	    if (lphl->FirstVisible < 1) lphl->FirstVisible = 1;
-	    if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
-		lphl->ItemFocused = Count;
-		}
-	    else {
-		ListBoxSetCurSel(hwnd, Count);
-		}
-	    SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
-	    InvalidateRect(hwnd, NULL, TRUE);
-	    UpdateWindow(hwnd);
-	    return Count;
-	    }
-	lpls = (LPLISTSTRUCT)lpls->lpNext;
-	Count++;
-        }
-    return LB_ERR;
+	SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
+	return Count;
+      }
+    }
+    lpls = (LPLISTSTRUCT)lpls->lpNext;
+    Count++;
+  }
+  Count = 0;
+  lpls = lphl->lpFirst;
+  while(lpls != NULL) {
+    if (*(lpls->itemText) == (char)wChar) {
+      if (Count == lphl->ItemFocused)    return LB_ERR;
+
+      if ((wndPtr->dwStyle & LBS_MULTIPLESEL) == LBS_MULTIPLESEL) {
+	lphl->ItemFocused = Count;
+	ListBoxScrolltoFocus(hwnd);
+      }
+      else {
+	ListBoxSetCurSel(hwnd, Count);
+      }
+      SetScrollPos(hwnd, SB_VERT, lphl->FirstVisible, TRUE);
+      InvalidateRect(hwnd, NULL, TRUE);
+      UpdateWindow(hwnd);
+      return Count;
+    }
+    lpls = lpls->lpNext;
+    Count++;
+  }
+  return LB_ERR;
 }
 
 
 /************************************************************************
- * 					DlgDirSelect			[USER.99]
+ * 		      	DlgDirSelect			[USER.99]
  */
 BOOL DlgDirSelect(HWND hDlg, LPSTR lpStr, int nIDLBox)
 {
@@ -1364,53 +2119,85 @@
 
 
 /************************************************************************
- * 					DlgDirList				[USER.100]
+ * 			   DlgDirList				[USER.100]
  */
 int DlgDirList(HWND hDlg, LPSTR lpPathSpec, 
 	int nIDLBox, int nIDStat, WORD wType)
 {
-	HWND	hWnd;
-	int ret;
-	dprintf_listbox(stddeb,"DlgDirList(%04X, '%s', %d, %d, %04X) \n",
-			hDlg, lpPathSpec, nIDLBox, nIDStat, wType);
-	if (nIDLBox)
-	  hWnd = GetDlgItem(hDlg, nIDLBox);
-	else
-	  hWnd = 0;
-	if (hWnd)
-	  ListBoxResetContent(hWnd);
-	if (hWnd)
-	  ret=ListBoxDirectory(hWnd, wType, lpPathSpec);
-	else
-	  ret=0;
-	if (nIDStat)
-	  {
-	    int drive;
-	    char temp[255];
-	    drive = DOS_GetDefaultDrive();
-	    strcpy( temp+3, DOS_GetCurrentDir(drive) );
-	    if( temp[3] == '\\' ) {
-	      temp[1] = 'A'+drive;
-	      temp[2] = ':';
-	      SendDlgItemMessage(hDlg, nIDStat, WM_SETTEXT, 0, (LONG)(temp+1));
-	    }
-	    else {
-	      temp[0] = 'A'+drive;
-	      temp[1] = ':';
-	      temp[2] = '\\';
-	      SendDlgItemMessage(hDlg, nIDStat, WM_SETTEXT, 0, (LONG) temp );
-	    }
-	  } 
-	return ret;
+  HWND	hWnd;
+  int ret;
+  dprintf_listbox(stddeb,"DlgDirList(%04X, '%s', %d, %d, %04X) \n",
+		  hDlg, lpPathSpec, nIDLBox, nIDStat, wType);
+  if (nIDLBox)
+    hWnd = GetDlgItem(hDlg, nIDLBox);
+  else
+    hWnd = 0;
+  if (hWnd)
+    ListBoxResetContent(hWnd);
+  if (hWnd)
+    ret=ListBoxDirectory(hWnd, wType, lpPathSpec);
+  else
+    ret=0;
+  if (nIDStat)
+    {
+      int drive;
+      HANDLE hTemp;
+      char *temp;
+      drive = DOS_GetDefaultDrive();
+      hTemp = USER_HEAP_ALLOC( 256 );
+      temp = (char *) USER_HEAP_LIN_ADDR( hTemp );
+      strcpy( temp+3, DOS_GetCurrentDir(drive) );
+      if( temp[3] == '\\' ) {
+	temp[1] = 'A'+drive;
+	temp[2] = ':';
+	SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0,
+                            USER_HEAP_SEG_ADDR(hTemp) + 1 );
+      }
+      else {
+	temp[0] = 'A'+drive;
+	temp[1] = ':';
+	temp[2] = '\\';
+	SendDlgItemMessage( hDlg, nIDStat, WM_SETTEXT, 0,
+                            USER_HEAP_SEG_ADDR(hTemp) );
+      }
+      USER_HEAP_FREE( hTemp );
+    } 
+  return ret;
 }
 
-/* get the maximum value of lphl->FirstVisible */
-int ListMaxFirstVisible(LPHEADLIST lphl)
+
+/* Returns: 0 if nothing needs to be changed */
+/*          1 if FirstVisible changed */
+
+int ListBoxScrolltoFocus(HWND hwnd)
+
 {
-    int m = lphl->ItemsCount-lphl->ItemsVisible+1;
-    return (m < 1) ? 1 : m;
-}
+  WND  *wndPtr;
+  LPHEADLIST  lphl;
+  short       end;
 
+  lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
+
+  if (lphl->ItemsCount == 0) return 0;
+  if (lphl->ItemFocused == -1) return 0;
+
+  end = lphl->FirstVisible + lphl->ItemsVisible - 2;
+
+  if (lphl->ItemFocused < lphl->FirstVisible - 1) {
+    lphl->FirstVisible = lphl->ItemFocused + 1;
+  }
+  else if (lphl->ItemFocused > end) {
+    UINT maxFirstVisible = ListMaxFirstVisible(lphl);
+
+    lphl->FirstVisible = lphl->ItemFocused;
+
+    if (lphl->FirstVisible > maxFirstVisible) {
+      lphl->FirstVisible = maxFirstVisible;
+    }
+  } else return 0;
+
+  return 1;
+}
 
 /* Send notification "code" as part of a WM_COMMAND-message if hwnd
    has the LBS_NOTIFY style */
@@ -1419,7 +2206,8 @@
   WND  *wndPtr;
   LPHEADLIST  lphl;
   lphl = ListBoxGetWindowAndStorage(hwnd, &wndPtr);
-  if( wndPtr && ( (wndPtr->dwStyle && LBS_NOTIFY) != 0) )
+
+  if (wndPtr && (wndPtr->dwStyle & LBS_NOTIFY))
     SendMessage(lphl->hWndLogicParent, WM_COMMAND,
 		wndPtr->wIDmenu, MAKELONG(hwnd, code));
-} 
+}
diff --git a/controls/menu.c b/controls/menu.c
index ac118e9..2b20dbe 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -246,6 +246,27 @@
 
     SetRect( &lpitem->rect, orgX, orgY, orgX, orgY );
     lpitem->xTab = 0;
+    if (lpitem->item_flags & MF_OWNERDRAW)  {
+      static HANDLE mistrh = 0;
+      static SEGPTR mistrsegp = 0;
+      static LPMEASUREITEMSTRUCT mistruct=NULL;
+      if (mistruct == NULL)  {
+	mistrh = GlobalAlloc(0,sizeof(MEASUREITEMSTRUCT));
+	mistrsegp = WIN16_GlobalLock(mistrh);
+	mistruct = PTR_SEG_TO_LIN(mistrsegp);
+      }
+      mistruct->CtlType = ODT_MENU;
+      mistruct->itemID = lpitem->item_id;
+      mistruct->itemData = (long int)lpitem->item_text;
+      mistruct->itemHeight = 16;
+      mistruct->itemWidth = 30;
+      SendMessage(hwndOwner,WM_MEASUREITEM,0,mistrsegp);
+      lpitem->rect.bottom += mistruct->itemHeight;
+      lpitem->rect.right += mistruct->itemWidth;
+      dprintf_menu(stddeb,"DrawMenuItem: MeasureItem %04x %d:%d!\n",
+		   lpitem->item_id,mistruct->itemWidth, mistruct->itemHeight);
+      return;
+    } 
 
     if (lpitem->item_flags & MF_SEPARATOR)
     {
@@ -422,11 +443,35 @@
  *
  * Draw a single menu item.
  */
-static void MENU_DrawMenuItem( HDC hdc, LPMENUITEM lpitem,
+static void MENU_DrawMenuItem( HWND hwnd, HDC hdc, LPMENUITEM lpitem,
 			       WORD height, BOOL menuBar )
 {
     RECT rect;
 
+    if (lpitem->item_flags & MF_OWNERDRAW)  {
+      static HANDLE distrh = 0;
+      static SEGPTR distrsegp = 0;
+      static LPDRAWITEMSTRUCT distruct=NULL;
+      if (distruct == NULL)  {
+	distrh = GlobalAlloc(0,sizeof(DRAWITEMSTRUCT));
+	distrsegp = WIN16_GlobalLock(distrh);
+	distruct = PTR_SEG_TO_LIN(distrsegp);
+      }
+      dprintf_menu(stddeb,"DrawMenuItem: Ownerdraw!\n");
+      distruct->CtlType = ODT_MENU;
+      distruct->itemID = lpitem->item_id;
+      distruct->itemData = (long int)lpitem->item_text;
+      distruct->itemState = 0;
+      if (lpitem->item_flags & MF_CHECKED) distruct->itemState |= ODS_CHECKED;
+      if (lpitem->item_flags & MF_GRAYED) distruct->itemState |= ODS_GRAYED;
+      if (lpitem->item_flags & MF_HILITE) distruct->itemState |= ODS_SELECTED;
+      distruct->itemAction = ODA_DRAWENTIRE | ODA_SELECT | ODA_FOCUS;
+      distruct->hwndItem = hwnd;
+      distruct->hDC = hdc;
+      distruct->rcItem = lpitem->rect;
+      SendMessage(hwnd,WM_DRAWITEM,0,distrsegp);
+      return;
+    }
     if (menuBar && (lpitem->item_flags & MF_SEPARATOR)) return;
     rect = lpitem->rect;
 
@@ -566,7 +611,7 @@
     if (!menu || !menu->nItems) return;
     item = (MENUITEM *) USER_HEAP_LIN_ADDR( menu->hItems );
     for (i = menu->nItems; i > 0; i--, item++)
-	MENU_DrawMenuItem( hdc, item, menu->Height, FALSE );
+	MENU_DrawMenuItem( hwnd, hdc, item, menu->Height, FALSE );
 }
 
 
@@ -599,7 +644,7 @@
     lpitem = (MENUITEM *) USER_HEAP_LIN_ADDR( lppop->hItems );
     for (i = 0; i < lppop->nItems; i++, lpitem++)
     {
-	MENU_DrawMenuItem( hDC, lpitem, lppop->Height, TRUE );
+	MENU_DrawMenuItem( hwnd, hDC, lpitem, lppop->Height, TRUE );
     }
     return lppop->Height;
 } 
@@ -677,7 +722,7 @@
 	else
 	{
 	    items[lppop->FocusedItem].item_flags &=~(MF_HILITE|MF_MOUSESELECT);
-	    MENU_DrawMenuItem( hdc, &items[lppop->FocusedItem], lppop->Height,
+	    MENU_DrawMenuItem( lppop->hWnd, hdc, &items[lppop->FocusedItem], lppop->Height,
 			       !(lppop->wFlags & MF_POPUP) );
 	}
     }
@@ -691,7 +736,7 @@
 	else
 	{
 	    items[lppop->FocusedItem].item_flags |= MF_HILITE;
-	    MENU_DrawMenuItem( hdc, &items[lppop->FocusedItem], lppop->Height,
+	    MENU_DrawMenuItem( lppop->hWnd, hdc, &items[lppop->FocusedItem], lppop->Height,
 			       !(lppop->wFlags & MF_POPUP) );
 	    SendMessage(lppop->hWnd, WM_MENUSELECT,
 			items[lppop->FocusedItem].item_id, 
diff --git a/controls/widgets.c b/controls/widgets.c
index 20e22dc..a2f17a9 100644
--- a/controls/widgets.c
+++ b/controls/widgets.c
@@ -14,37 +14,31 @@
 #include "mdi.h"
 #include "gdi.h"
 #include "user.h"
-
-LONG ListBoxWndProc  ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
-LONG ComboBoxWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
-LONG EditWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam );
-LONG PopupMenuWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
-LONG DesktopWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
-LONG MDIClientWndProc ( HWND hwnd, WORD message, WORD wParam, LONG lParam );
+#include "selectors.h"
 
 
 static WNDCLASS WIDGETS_BuiltinClasses[] =
 {
-    { CS_GLOBALCLASS | CS_PARENTDC, ButtonWndProc, 0, sizeof(BUTTONINFO), 
-      0, 0, 0, 0, NULL, "BUTTON" },
-    { CS_GLOBALCLASS | CS_PARENTDC, StaticWndProc, 0, sizeof(STATICINFO),
-      0, 0, 0, 0, NULL, "STATIC" },
-    { CS_GLOBALCLASS | CS_PARENTDC, ScrollBarWndProc, 0, sizeof(SCROLLINFO),
-      0, 0, 0, 0, NULL, "SCROLLBAR" },
-    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, ListBoxWndProc, 0, 8,
-      0, 0, 0, 0, NULL, "LISTBOX" },
-    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, ComboBoxWndProc, 0, 8,
-      0, 0, 0, 0, NULL, "COMBOBOX" },
-    { CS_GLOBALCLASS | CS_PARENTDC, EditWndProc, 0, sizeof(WORD), 
-      0, 0, 0, 0, NULL, "EDIT" },
-    { CS_GLOBALCLASS | CS_SAVEBITS, PopupMenuWndProc, 0, 8,
-      0, 0, 0, 0, NULL, POPUPMENU_CLASS_NAME },
-    { CS_GLOBALCLASS, DesktopWndProc, 0, sizeof(DESKTOPINFO),
-      0, 0, 0, 0, NULL, DESKTOP_CLASS_NAME },
-    { CS_GLOBALCLASS | CS_SAVEBITS, DefDlgProc, 0, DLGWINDOWEXTRA,
-      0, 0, 0, 0, NULL, DIALOG_CLASS_NAME },
-    { CS_GLOBALCLASS, MDIClientWndProc, 0, sizeof(MDICLIENTINFO),
-      0, 0, 0, STOCK_LTGRAY_BRUSH, NULL, "MDICLIENT" }
+    { CS_GLOBALCLASS | CS_PARENTDC, (WNDPROC)"ButtonWndProc", 0,
+      sizeof(BUTTONINFO), 0, 0, 0, 0, NULL, "BUTTON" },
+    { CS_GLOBALCLASS | CS_PARENTDC, (WNDPROC)"StaticWndProc", 0,
+      sizeof(STATICINFO), 0, 0, 0, 0, NULL, "STATIC" },
+    { CS_GLOBALCLASS | CS_PARENTDC, (WNDPROC)"ScrollBarWndProc", 0,
+      sizeof(SCROLLINFO), 0, 0, 0, 0, NULL, "SCROLLBAR" },
+    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, (WNDPROC)"ListBoxWndProc", 0,
+      8, 0, 0, 0, 0, NULL, "LISTBOX" },
+    { CS_GLOBALCLASS | CS_PARENTDC | CS_DBLCLKS, (WNDPROC)"ComboBoxWndProc", 0,
+      8, 0, 0, 0, 0, NULL, "COMBOBOX" },
+    { CS_GLOBALCLASS, (WNDPROC)"EditWndProc", 0,
+      sizeof(WORD), 0, 0, 0, 0, NULL, "EDIT" },
+    { CS_GLOBALCLASS | CS_SAVEBITS, (WNDPROC)"PopupMenuWndProc", 0,
+      8, 0, 0, 0, 0, NULL, POPUPMENU_CLASS_NAME },
+    { CS_GLOBALCLASS, (WNDPROC)"DesktopWndProc", 0,
+      sizeof(DESKTOPINFO), 0, 0, 0, 0, NULL, DESKTOP_CLASS_NAME },
+    { CS_GLOBALCLASS | CS_SAVEBITS, (WNDPROC)"DefDlgProc", 0,
+      DLGWINDOWEXTRA, 0, 0, 0, 0, NULL, DIALOG_CLASS_NAME },
+    { CS_GLOBALCLASS, (WNDPROC)"MDIClientWndProc", 0,
+      sizeof(MDICLIENTINFO), 0, 0, 0, STOCK_LTGRAY_BRUSH, NULL, "MDICLIENT" }
 };
 
 #define NB_BUILTIN_CLASSES \
@@ -70,6 +64,7 @@
         strcpy( name, class->lpszClassName );
         class->lpszClassName = (LPSTR)USER_HEAP_SEG_ADDR( hName );
 	class->hCursor = LoadCursor( 0, IDC_ARROW );
+        class->lpfnWndProc = GetWndProcEntry16( (char *)class->lpfnWndProc );
 	if (!RegisterClass( class )) return FALSE;
     }
     USER_HEAP_FREE( hName );
diff --git a/debugger/info.c b/debugger/info.c
index 9506240..8b1604f 100644
--- a/debugger/info.c
+++ b/debugger/info.c
@@ -277,11 +277,12 @@
   while((cs & 3) == 3) {
     /* See if in 32 bit mode or not.  Assume GDT means 32 bit. */
     if ((cs & 7) != 7) {
-      void CallTo32();
+      extern int main();
       fprintf(stderr,"%d ",frameno++);
       print_address(frame->u.win32.saved_ip,stderr,32);
       fprintf( stderr, "\n" );
-      if(frame->u.win32.saved_ip<((unsigned long)CallTo32+1000))break;
+      if (frame->u.win32.saved_ip >= ((unsigned long)main) &&
+          frame->u.win32.saved_ip <= ((unsigned long)main+1000)) break;
       frame = (struct frame *) frame->u.win32.saved_bp;
     } else {
       if (frame->u.win16.saved_bp & 1) cs = frame->u.win16.saved_cs;
diff --git a/if1632/Imakefile b/if1632/Imakefile
index 85ef1ea..99e872b 100644
--- a/if1632/Imakefile
+++ b/if1632/Imakefile
@@ -9,40 +9,45 @@
 
 #ifdef WINELIB
 CALLOBJS =
-DLLOBJS =
+DLLS =
 #else
-CALLOBJS = call.o
-DLLOBJS = \
-	dll_commdlg.o \
-	dll_compobj.o \
-	dll_gdi.o \
-	dll_kernel.o \
-	dll_keyboard.o \
-	dll_mmsystem.o \
-	dll_mouse.o \
-	dll_ole2.o \
-	dll_ole2conv.o \
-	dll_ole2disp.o \
-	dll_ole2nls.o \
-	dll_ole2prox.o \
-	dll_olecli.o \
-	dll_olesvr.o \
-	dll_shell.o \
-	dll_sound.o \
-	dll_storage.o \
-	dll_stress.o \
-	dll_system.o \
-	dll_toolhelp.o \
-	dll_user.o \
-	dll_win87em.o \
-	dll_winsock.o
+CALLOBJS = \
+	call16.o \
+	call32.o
+DLLS = \
+	commdlg \
+	compobj \
+	gdi \
+	kernel \
+	keyboard \
+	mmsystem \
+	mouse \
+	ole2 \
+	ole2conv \
+	ole2disp \
+	ole2nls \
+	ole2prox \
+	olecli \
+	olesvr \
+	shell \
+	sound \
+	storage \
+	stress \
+	system \
+	toolhelp \
+	user \
+	win87em \
+	winprocs \
+	winsock
 #endif
 
-#ifndef NewBuild
-OBJS = $(CALLOBJS) $(DLLOBJS) $(SRCS:.c=.o) $(DLLOBJS:.o=_tab.o)
-#else
-OBJS = $(CALLOBJS) $(DLLOBJS) $(SRCS:.c=.o) $(DLLOBJS:.o=_tab.o) $(DLLOBJS:dll_.rly_)
-#endif
+OBJS = $(DLLS:%=dll_%.o) $(CALLOBJS) $(SRCS:.c=.o) $(DLLS:%=tab_%.o)
+
+BUILD = $(TOP)/tools/build
+
+#define MakeDllFromSpec(name)					@@\
+Concat(dll_,name.S) Concat(tab_,name.c): name.spec $(BUILD)	@@\
+	$(BUILD) -spec name.spec				@@\
 
 /*
  * If you add a new spec file, copy one of these lines
@@ -69,23 +74,25 @@
 MakeDllFromSpec(toolhelp)
 MakeDllFromSpec(user)
 MakeDllFromSpec(win87em)
+MakeDllFromSpec(winprocs)
 MakeDllFromSpec(winsock)
 
 WineRelocatableTarget($(MODULE),,$(OBJS))
 DependTarget()
 
 #ifndef WINELIB
-pop.h: $(TOP)/tools/build
-	$(TOP)/tools/build -p
 
-call.o: call.S pop.h
-	$(CC) -I. -c -o call.o call.S
-#endif
+call32.S: $(BUILD) $(DLLS:%=dll_%.S)
+	$(BUILD) -call32 `cat $(DLLS:%=dll_%.S) | grep CallTo32_ | sed 's/.*CallTo32_\(.*\)/\1/' | sort | uniq` > call32.S
+
+call16.S: $(BUILD) $(TOP)/include/callback.h
+	$(BUILD) -call16 `cat $(TOP)/include/callback.h | grep "extern.*CallTo16_" | sed 's/.*CallTo16_\(.*\)(.*/\1/' | sort | uniq` > call16.S
+
+#endif  /* WINELIB */
 
 includes::
-	touch pop.h
 
 install::
 
 clean::
-	$(RM) dll* dtb* pop.h call.s
+	$(RM) dll_* tab_* call32.S call16.S
diff --git a/if1632/call.S b/if1632/call.S
deleted file mode 100644
index e6ab7b3..0000000
--- a/if1632/call.S
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * Copyright  Robert J. Amstadt, 1993
- */
-#ifdef linux
-#define UDATASEL 0x2b
-#endif
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#define UDATASEL 0x27
-#endif
-#ifdef __ELF__
-#define A(addr) addr
-#else
-#define A(addr) _##addr
-#endif
-	.data
-jump_target:
-return_value:
-	.long	0
-
-/**********************************************************************
- *	Places to keep info about the current 32-bit stack frame.
- */
-	.globl	A( IF1632_Saved32_esp), A(IF1632_Saved32_ebp), A(IF1632_Saved32_ss)
-A(IF1632_Saved32_esp:)
-	.long	0
-A(IF1632_Saved32_ebp:)
-	.long	0
-A(IF1632_Saved32_ss:)
-	.word	0
-#ifdef __ELF__
-A(IF1632_ELF_KLUDGE:)
-	.long	0
-	.word	0x0f
-#endif
-
-/**********************************************************************
- *	Places to keep info about the current 16-bit stack frame.
- */
-	.globl A(IF1632_Saved16_sp),A(IF1632_Saved16_bp),A(IF1632_Saved16_ss)
-A(IF1632_Saved16_sp:)
-	.word	0
-A(IF1632_Saved16_bp:)
-	.word	0
-A(IF1632_Saved16_ss:)
-	.word	0
-
-nbytes:
-	.word	0
-selector:
-	.word	0
-offset:
-	.word	0
-
-	.text
-
-/**********************************************************************
- *	int CallToInit16(unsigned long csip, unsigned long sssp,
- *		     unsigned short ds)
- *
- *	Stack:	 	0	ebp
- *		 	4	eip
- *		 	8	target ip
- *			10	target cs
- *			12	target sp
- *			14	target ss
- *			16	target ds
- */
-	.align	4
-	.globl A(CallToInit16)
-A(CallToInit16:)
-	pushl	%ebp
-	movl	%esp,%ebp
-
-	/*
- 	 * Save our registers
-	 */
-	pushal
-	pushl	A(IF1632_Saved32_esp)
-	pushl	A(IF1632_Saved32_ebp)
-	pushw	A(IF1632_Saved32_ss)
-
-#ifdef __ELF__
-	/* change to the other code segment */
-	movw	$0x0f, %ax
-	movw	%ax, A(IF1632_ELF_KLUDGE)+4
-	movl	$L4, %eax
-	andl	$0x0000ffff, %eax
-	movl	%eax,A(IF1632_ELF_KLUDGE)
-	ljmp	A(IF1632_ELF_KLUDGE)
-L4:
-#endif
-	/*
-	 * Get target address.
-	 */
-	movl	8(%ebp),%eax
-	movl	%eax,jump_target
-	lea	jump_target,%edx
-
-	/*
-	 * Put stack registers where we can get them after stack switch.
-	 */
-	movw	%ss,A(IF1632_Saved32_ss)
-	movl	%esp,A(IF1632_Saved32_esp)
-	movl	%ebp,A(IF1632_Saved32_ebp)
-
-	/*
-	 * Load initial registers
-	 */
-	movw	A(WIN_StackSize),%bx
-	movw	A(WIN_HeapSize),%cx
-	movl	$0,%esi
-	xorl	%eax,%eax
-	movw	A(PSPSelector),%ax
-	movw	%ax,%es
-	movw	16(%ebp),%ax
-	movw	%ax,%ds
-	movl	%eax,%edi
-	xorl	%eax,%eax
-	movw	12(%ebp),%ax
-	movl	%eax,%esp
-	movw	14(%ebp),%ax
-	movw	%ax,%ss
-	movl	%esp,%eax
-	movl	%eax,%ebp
-	movw	$UDATASEL,%ax
-	movw	%ax,%fs
-	movw	%ax,%gs
-	movw	%ds,%ax
-
-	/*
-	 * Call entry point
-	 */
-	.byte	0x66
-	lcall	%fs:(%edx)
-
-	/*
-	 * Restore old stack and segment registers.
-	 *
-	 * Two choices here:
-	 *	1. Trust that fs or gs hasn't changed.
-	 *	2. Rely on knowledge of Linux use of segments.
-	 *
-	 * I'll opt for choice 2 because who knows what programs we
-	 * going to run.  Linux should be fairly stable in terms of
-	 * GDT usage.
-	 */
-	pushl	%eax
-	movw	$UDATASEL,%ax
-	movw	%ax,%ds
-	movw	%ax,%es
-	movw	%ax,%fs
-	movw	%ax,%gs
-	popl	%eax
-	movw	A(IF1632_Saved32_ss),%ss
-	movl	A(IF1632_Saved32_esp),%esp
-	movl	A(IF1632_Saved32_ebp),%ebp
-
-	/*
- 	 * Restore registers, but do not destroy return value.
-	 */
-	popw	A(IF1632_Saved32_ss)
-	popl	A(IF1632_Saved32_ebp)
-	popl	A(IF1632_Saved32_esp)
-	movl	%eax,return_value
-#ifdef __ELF__
-	/* change back  */
-	movw	$0x23, %ax
-	movw	%ax, A(IF1632_ELF_KLUDGE)+4
-	movl	$L5, %eax
-	movl	%eax,A(IF1632_ELF_KLUDGE)
-	ljmp	A(IF1632_ELF_KLUDGE)
-L5:
-#endif
-	popal
-	movl	return_value,%eax
-	.align	2,0x90
-	leave
-	ret
-
-/**********************************************************************
- *	int CallTo16  (unsigned long csip, unsigned short ds)
- *      int CallTo16cx(unsigned long csip, unsigned long dscx);
- *
- *	Stack:	 	0	ebp
- *		 	4	eip
- *		 	8	target ip
- *			10	target cs
- *			12	target ds
- *			14      target cx  (only CallTo16cx)
- *                      16      target di
- */
-	.align	4
-	.globl A(CallTo16), A(CallTo16cx), A(CallToLibMain)
-A(CallToLibMain:)
-        pushl   %ebp
-        movl    %esp,%ebp
-        movw    16(%ebp),%di
-        movw    0,%si
-        movw    0,%es
-        jmp     L1
-A(CallTo16:)
-A(CallTo16cx:)
-	pushl	%ebp
-	movl	%esp,%ebp
-
-	/*
-	 * Get target address and new ds
-	 */
-L1:
-#ifdef __ELF__
-	/* change code segments */
-	movw	$0x0f, %ax
-	movw	%ax, A(IF1632_ELF_KLUDGE)+4
-	movl	$L2, %eax
-	andl	$0x0000ffff, %eax
-	movl	%eax,A(IF1632_ELF_KLUDGE)
-	ljmp	A(IF1632_ELF_KLUDGE)
-L2:
-#endif
-	/* At this point we have changed segments. */
-	movl	8(%ebp),%eax
-	movl	%eax,jump_target
-	lea	jump_target,%edx
-	movw	12(%ebp),%ax
-	movw	14(%ebp),%cx
-
-	/*
-	 * Switch to 16-bit stack
-	 */
-	pushl	A(IF1632_Saved32_esp)
-	pushl	A(IF1632_Saved32_ebp)
-	pushw	A(IF1632_Saved32_ss)
-
-	movw	%ss,A(IF1632_Saved32_ss)
-	movl	%esp,A(IF1632_Saved32_esp)
-	movl	%ebp,A(IF1632_Saved32_ebp)
-
-	movw	A(IF1632_Saved16_ss),%ss
-	movw	A(IF1632_Saved16_sp),%sp
-	movw	A(IF1632_Saved16_bp),%bp
-
-	/*
-	 * Call entry point
-	 */
- 	movw	%ax,%ds
-	movw	%ax,%di
-	.byte	0x66
-	lcall	%fs:(%edx)
-
-	/*
-	 * Restore old stack and segment registers.
-	 *
-	 * Two choices here:
-	 *	1. Trust that fs or gs hasn't changed.
-	 *	2. Rely on knowledge of Linux use of segments.
-	 *
-	 * I'll opt for choice 2 because who knows what programs we
-	 * going to run.  Linux should be fairly stable in terms of
-	 * GDT usage.
-	 */
-	pushl	%eax
-	movw	$UDATASEL,%ax
-	movw	%ax,%ds
-	movw	%ax,%es
-	movw	%ax,%fs
-	movw	%ax,%gs
-	popl	%eax
-
-	movw	%ss,A(IF1632_Saved16_ss)
-	movw	%esp,A(IF1632_Saved16_sp)
-	movw	%ebp,A(IF1632_Saved16_bp)
-
-	movw	A(IF1632_Saved32_ss),%ss
-	movl	A(IF1632_Saved32_esp),%esp
-	movl	A(IF1632_Saved32_ebp),%ebp
-
-	popw	A(IF1632_Saved32_ss)
-	popl	A(IF1632_Saved32_ebp)
-	popl	A(IF1632_Saved32_esp)
-
-	movl	%eax,return_value
-	movw	return_value+2,%dx
-	/* switch segments */
-#ifdef __ELF__
-	movw	$0x23, %ax
-	movw	%ax, A(IF1632_ELF_KLUDGE)+4
-	movl	$L3, %eax
-	movl	%eax,A(IF1632_ELF_KLUDGE)
-	ljmp	A(IF1632_ELF_KLUDGE)
-L3:
-	/* back in the regular segment set up. */
-	/* restore eax */
-	movl	return_value, %eax
-#endif
-	.align	2,0x90
-	leave
-	ret
-
-/**********************************************************************
- *	CallTo32()
- *
- *	This function is called as a relay point to the built function
- *	handler.  KERNEL, USER and GDI calls are dealt with by this
- *	handler.  Calls to these DLLs will be mapped to a call handler
- *	which will set EAX to a number indicating which DLL and which
- *	function within that DLL.
- *
- *	This function will pass to the function handler two arguments.
- *	The first argument will be the contents of EAX, the second
- *	argument will be a segment:offset pair that points to the
- *	16-bit stack.
- */
-	.align	4
-	.globl A(CallTo32)
-A(CallTo32:)
-	andl	$0x0000ffff,%esp
-	pushw	%bp
-	movl	%esp,%ebp
-
-	/*
- 	 * Save registers.  286 mode does not have fs or gs.
-	 */
-	pushw	%ds
-
-	/*
-	 * Restore segment registers.
-	 */
-	pushl	%eax
-	movw	$UDATASEL,%ax
-	movw	%ax,%ds
-	movw	%ax,%es
-	popl	%eax
-
-	/*
-	 * Save old stack save variables, save stack registers, reload
-	 * stack registers.
-	 */
-	pushw	A(IF1632_Saved16_sp)
-	pushw	A(IF1632_Saved16_bp)
-	pushw	A(IF1632_Saved16_ss)
-
-	movw	%ss,A(IF1632_Saved16_ss)
-	movw	%sp,A(IF1632_Saved16_sp)
-	movw	%bp,A(IF1632_Saved16_bp)
-
-	movw	A(IF1632_Saved32_ss),%ss
-	movl	A(IF1632_Saved32_esp),%esp
-	movl	A(IF1632_Saved32_ebp),%ebp
-
-	/*
-	 * Call entry point
-	 */
-	pushl	%edx
-	pushw	A(IF1632_Saved16_ss)
-	pushw	A(IF1632_Saved16_sp)
-	pushl	%eax
-	call	A(DLLRelay)
-
-	popl	%edx
-	popl	%edx
-	popl	%edx
-
-	/*
- 	 * Restore registers, but do not destroy return value.
-	 */
-	movw	A(IF1632_Saved16_ss),%ss
-	movw	A(IF1632_Saved16_sp),%sp
-	movw	A(IF1632_Saved16_bp),%bp
-
-	popw	A(IF1632_Saved16_ss)
-	popw	A(IF1632_Saved16_bp)
-	popw	A(IF1632_Saved16_sp)
-
-	popw	%ds
-	popw	%bp
-
-	/*
-	 * Now we need to ditch the parameter bytes that were left on the
-	 * stack. We do this by effectively popping the number of bytes,
-	 * and the return address, removing the parameters and then putting
-	 * the return address back on the stack.
-	 * Normally this field is filled in by the relevant function in
-	 * the emulation library, since it should know how many bytes to
-	 * expect.
-	 */
-	popw	%gs:nbytes
-	cmpw	$0,%gs:nbytes
-	je	noargs
-	popw	%gs:offset
-	popw	%gs:selector
-	addw	%gs:nbytes,%esp
-	pushw	%gs:selector
-	pushw	%gs:offset
-noargs:
-
-	/*
-	 * Last, but not least we need to move the high word from eax to dx
-	 */
-
-	pushl	%eax
-	popw	%dx
-	popw	%dx
-
-	.byte	0x66
-	lret
-
-/**********************************************************************
- *	CallTo32_16()
- *
- *	This function is same one as CallTo32() except that the high
- *	word of EAX won't be moved to DX.
- */
-	.align	4
-	.globl A(CallTo32_16)
-A(CallTo32_16:)
-	andl	$0x0000ffff,%esp
-	pushw	%bp
-	movl	%esp,%ebp
-
-	/*
- 	 * Save registers.  286 mode does not have fs or gs.
-	 */
-	pushw	%ds
-
-	/*
-	 * Restore segment registers.
-	 */
-	pushl	%eax
-	movw	$UDATASEL,%ax
-	movw	%ax,%ds
-	movw	%ax,%es
-	popl	%eax
-
-	/*
-	 * Save old stack save variables, save stack registers, reload
-	 * stack registers.
-	 */
-	pushw	A(IF1632_Saved16_sp)
-	pushw	A(IF1632_Saved16_bp)
-	pushw	A(IF1632_Saved16_ss)
-
-	movw	%ss,A(IF1632_Saved16_ss)
-	movw	%esp,A(IF1632_Saved16_sp)
-	movw	%ebp,A(IF1632_Saved16_bp)
-
-	movw	A(IF1632_Saved32_ss),%ss
-	movl	A(IF1632_Saved32_esp),%esp
-	movl	A(IF1632_Saved32_ebp),%ebp
-
-	/*
-	 * Call entry point
-	 */
-	pushl	%edx
-	pushw	A(IF1632_Saved16_ss)
-	pushw	A(IF1632_Saved16_sp)
-	pushl	%eax
-	call	A(DLLRelay)
-
-	popl	%edx
-	popl	%edx
-	popl	%edx
-
-	/*
- 	 * Restore registers, but do not destroy return value.
-	 */
-	movw	A(IF1632_Saved16_ss),%ss
-	movw	A(IF1632_Saved16_sp),%sp
-	movw	A(IF1632_Saved16_bp),%bp
-
-	popw	A(IF1632_Saved16_ss)
-	popw	A(IF1632_Saved16_bp)
-	popw	A(IF1632_Saved16_sp)
-
-	popw	%ds
-	popw	%bp
-
-	/*
-	 * Now we need to ditch the parameter bytes that were left on the
-	 * stack. We do this by effectively popping the number of bytes,
-	 * and the return address, removing the parameters and then putting
-	 * the return address back on the stack.
-	 * Normally this field is filled in by the relevant function in
-	 * the emulation library, since it should know how many bytes to
-	 * expect.
-	 */
-	popw	%gs:nbytes
-	cmpw	$0,%gs:nbytes
-	je	noargs2
-	popw	%gs:offset
-	popw	%gs:selector
-	addw	%gs:nbytes,%esp
-	pushw	%gs:selector
-	pushw	%gs:offset
-noargs2:
-	.byte	0x66
-	lret
-
-/**********************************************************************
- *	ReturnFromRegisterFunc()
- */
-	.globl A(ReturnFromRegisterFunc)
-A(ReturnFromRegisterFunc:)
-	/*
- 	 * Restore 16-bit stack
-	 */
-	movw	A(IF1632_Saved16_ss),%ss
-	movw	A(IF1632_Saved16_sp),%sp
-	movw	A(IF1632_Saved16_bp),%bp
-
-	popw	A(IF1632_Saved16_ss)
-	popw	A(IF1632_Saved16_bp)
-	popw	A(IF1632_Saved16_sp)
-
-	popw	%ds
-	popw	%bp
-
-	/*
-	 * This leaves us with a stack that has number of arguments,
-	 * the return address, the saved registers, and the return 
-	 * address again.
-	 */
-	add	$6,%esp		/* argument count, return address */
-#include "pop.h"		/* restore context                */
-
-	/*
-	 * Return to original caller.
-	 */
-	.byte	0x66
-	lret
-
diff --git a/if1632/callback.c b/if1632/callback.c
index db210f2..a941b16 100644
--- a/if1632/callback.c
+++ b/if1632/callback.c
@@ -7,18 +7,17 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <strings.h>
+#include <setjmp.h>
 #include "windows.h"
 #include "callback.h"
 #include "wine.h"
-#include <setjmp.h>
-#include "ldt.h"
+#include "global.h"
 #include "stackframe.h"
 #include "dlls.h"
 #include "stddebug.h"
 #include "debug.h"
 #include "if1632.h"
 
-extern unsigned short IF1632_Saved32_ss;
 extern unsigned long  IF1632_Saved32_ebp;
 extern unsigned long  IF1632_Saved32_esp;
 
@@ -30,64 +29,6 @@
     unsigned char thunk[8];
 };
 
-#ifdef __ELF__
-#define FIRST_SELECTOR 2
-#define IS_16_BIT_ADDRESS(addr)  \
-    (((unsigned int)(addr) < 0x8000000) || ((unsigned int)(addr) >= 0x8400000))
-#else
-#define FIRST_SELECTOR	8
-#define IS_16_BIT_ADDRESS(addr)  \
-     ((unsigned int)(addr) >= (((FIRST_SELECTOR << __AHSHIFT) | 7) << 16))
-#endif
-
-/**********************************************************************
- *					PushOn16
- */
-static void
-PushOn16(int size, unsigned int value)
-{
-    char *p = PTR_SEG_OFF_TO_LIN( IF1632_Saved16_ss, IF1632_Saved16_sp );
-    if (size)
-    {
-	unsigned long *lp = (unsigned long *) p - 1;
-	
-	*lp = value;
-	IF1632_Saved16_sp -= 4;
-    }
-    else
-    {
-	unsigned short *sp = (unsigned short *) p - 1;
-	
-	*sp = value;
-	IF1632_Saved16_sp -= 2;
-    }
-}
-
-
-/**********************************************************************
- *					CallBack16
- */
-int
-CallBack16(void *func, int n_args, ...)
-{
-    va_list ap;
-    int i;
-    int arg_type, arg_value;
-    WORD ds = CURRENT_DS;
-
-    va_start(ap, n_args);
-
-    for (i = 0; i < n_args; i++)
-    {
-	arg_type = va_arg(ap, int);
-	arg_value = va_arg(ap, int);
-	PushOn16(arg_type, arg_value);
-    }
-
-    va_end(ap);
-
-    return CallTo16((unsigned int) func, ds );
-}
 
 /**********************************************************************
  *					MakeProcInstance
@@ -100,18 +41,8 @@
 
     if (!ThunkSelector)
     {
-        ldt_entry entry;
-
-          /* Allocate a segment for thunks */
-        ThunkSelector = AllocSelector( 0 );
-        entry.base           = (unsigned long) malloc( 0x10000 );
-        entry.limit          = 0xffff;
-        entry.seg_32bit      = 0;
-        entry.limit_in_pages = 0;
-        entry.type           = SEGMENT_CODE;
-        entry.read_only      = 0;
-        memset( (char *)entry.base, 0, 0x10000 );
-        LDT_SetEntry( SELECTOR_TO_ENTRY(ThunkSelector), &entry );
+        HGLOBAL handle = GLOBAL_Alloc( GMEM_ZEROINIT, 0x10000, 0, TRUE, FALSE);
+        ThunkSelector = GlobalHandleToSel(handle);
     }
 
     thunks = (char *)PTR_SEG_OFF_TO_LIN( ThunkSelector, 0 );
@@ -173,110 +104,9 @@
 		     WORD wParam, LONG lParam )
 {
     SpyMessage(hwnd, message, wParam, lParam);
-
-    if (HIWORD((LONG)func) == WINE_CODE_SELECTOR) 
-    {
-	static struct dll_table_entry_s *user_tab = NULL;
-	void *address = (void *) ((LONG) func & 0xffff);
-
-	if (user_tab == NULL)
-	    user_tab = FindDLLTable("USER");
-
-	/* DefWindowProc */
-	if (((LONG)user_tab[107].address &0xffff) == (LONG) address)
-	    return DefWindowProc(hwnd, message, wParam, lParam);
-	
-	/* DefDlgProc */
-	else if (((LONG)user_tab[308].address &0xffff) == (LONG)address)
-	    return DefDlgProc(hwnd, message, wParam, lParam);
-	
-	/* DefMDIChildProc */
-	else if (((LONG)user_tab[447].address &0xffff) == (LONG)address)
-	    return DefMDIChildProc(hwnd, message, wParam, lParam);
-	
-	/* default */
-	else
-	{
-	    fprintf(stderr, "wine: Unknown wine callback %08x\n", 
-	    	(unsigned int) func);
-	    exit(1);
-	}
-    }
-    else if (IS_16_BIT_ADDRESS(func))
-    {	
-        WORD ds = CURRENT_DS;
-	dprintf_callback(stddeb, "CallWindowProc // 16bit func=%08x ds=%04x!\n", 
-		(unsigned int) func, ds );
-	PushOn16( CALLBACK_SIZE_WORD, hwnd );
-	PushOn16( CALLBACK_SIZE_WORD, message );
-	PushOn16( CALLBACK_SIZE_WORD, wParam );
-	PushOn16( CALLBACK_SIZE_LONG, lParam );
-	return CallTo16((unsigned int) func, ds );
-    }
-    else
-    {
-	dprintf_callback(stddeb, "CallWindowProc // 32bit func=%08X !\n",
-		(unsigned int) func);
-	return (*func)(hwnd, message, wParam, lParam);
-    }
+    return CallWndProc( (FARPROC)func, hwnd, message, wParam, lParam );
 }
 
-/**********************************************************************
- *					CallLineDDAProc
- */
-void CallLineDDAProc(FARPROC func, short xPos, short yPos, long lParam)
-{
-    WORD ds = CURRENT_DS;
-    if (IS_16_BIT_ADDRESS(func))
-    {
-	PushOn16( CALLBACK_SIZE_WORD, xPos );
-	PushOn16( CALLBACK_SIZE_WORD, yPos );
-	PushOn16( CALLBACK_SIZE_LONG, lParam );
-	CallTo16((unsigned int) func, ds );
-    }
-    else
-    {
-	(*func)(xPos, yPos, lParam);
-    }
-}
-
-/**********************************************************************
- *					CallHookProc
- */
-DWORD CallHookProc( HOOKPROC func, short code, WPARAM wParam, LPARAM lParam )
-{
-    WORD ds = CURRENT_DS;
-    if (IS_16_BIT_ADDRESS(func))
-    {
-	PushOn16( CALLBACK_SIZE_WORD, code );
-	PushOn16( CALLBACK_SIZE_WORD, wParam );
-	PushOn16( CALLBACK_SIZE_LONG, lParam );
-	return CallTo16((unsigned int) func, ds );
-    }
-    else
-    {
-	return (*func)( code, wParam, lParam );
-    }
-}
-
-/**********************************************************************
- *					CallGrayStringProc
- */
-BOOL CallGrayStringProc(FARPROC func, HDC hdc, LPARAM lParam, INT cch )
-{
-    WORD ds = CURRENT_DS;
-    if (IS_16_BIT_ADDRESS(func))
-    {
-	PushOn16( CALLBACK_SIZE_WORD, hdc );
-	PushOn16( CALLBACK_SIZE_LONG, lParam );
-	PushOn16( CALLBACK_SIZE_WORD, cch );
-	return CallTo16((unsigned int) func, ds );
-    }
-    else
-    {
-	return (*func)( hdc, lParam, cch );
-    }
-}
 
 /* ------------------------------------------------------------------------ */
 /*
@@ -295,7 +125,7 @@
 
 struct special_buffer {
 	jmp_buf buffer;
-	long 	regs [6];
+	long 	regs [5];
 	char 	stack_part [STACK_DEPTH_16];
 } *sb;
 
@@ -303,8 +133,6 @@
 {
 	WORD retval;
 	jmp_buf *tmp_jmp;
-	char *stack16 =  (char *) (((unsigned int)IF1632_Saved16_ss << 16) +
-                                   IF1632_Saved16_sp);
 
 	sb = malloc (sizeof (struct special_buffer));
 	
@@ -313,8 +141,7 @@
 	sb -> regs [2] = IF1632_Saved16_ss & 0xffff;
 	sb -> regs [3] = IF1632_Saved32_esp;
 	sb -> regs [4] = IF1632_Saved32_ebp;
-	sb -> regs [5] = IF1632_Saved32_ss & 0xffff;
-	memcpy (sb -> stack_part, stack16, STACK_DEPTH_16);
+	memcpy (sb -> stack_part, CURRENT_STACK16, STACK_DEPTH_16);
 	tmp_jmp = &sb -> buffer;
 	*((struct special_buffer **)cbuf) = sb;
 	
@@ -325,11 +152,8 @@
 		IF1632_Saved16_ss = sb -> regs [2] & 0xffff;
 		IF1632_Saved32_esp = sb -> regs [3];
 		IF1632_Saved32_ebp = sb -> regs [4];
-		IF1632_Saved32_ss = sb -> regs [5] & 0xffff;
-		stack16 = (char *) (((unsigned int)IF1632_Saved16_ss << 16) +
-                                    IF1632_Saved16_sp);
 
-		memcpy (stack16, sb -> stack_part, STACK_DEPTH_16);
+		memcpy (CURRENT_STACK16, sb -> stack_part, STACK_DEPTH_16);
 		dprintf_catch (stddeb, "Been thrown here: %d, retval = %d\n", 
 			(int) sb, (int) retval);
 		free ((void *) sb);
diff --git a/if1632/compobj.spec b/if1632/compobj.spec
index a4b0993..06618a8 100644
--- a/if1632/compobj.spec
+++ b/if1632/compobj.spec
@@ -16,7 +16,7 @@
 #12 COFREEALLLIBRARIES
 #13 COCREATEINSTANCE
 #14 STRINGFROMIID
-#15 CODISCONNECTOBJECT
+15 pascal CoDisconnectObject(ptr long) CoDisconnectObject
 #16 CORELEASEMARSHALDATA
 #17 COFREEUNUSEDLIBRARIES
 #18 ISEQUALGUID
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index ea11970..4389097 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -212,7 +212,7 @@
 #310 pascal CREATESCALABLEFONTRESOURCE
 #311 pascal GETFONTDATA
 #312 pascal CONVERTOUTLINEFONTFILE
-#313 pascal GETRASTERIZERCAPS
+313 pascal16 GetRasterizerCaps(ptr word) GetRasterizerCaps
 #314 pascal ENGINEEXTTEXTOUT
 330 pascal16 EnumFontFamilies(word ptr segptr long) EnumFontFamilies
 #332 pascal GETKERNINGPAIRS
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index a9eec05..bdaa2ef 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -207,10 +207,10 @@
 #318 FATALEXITHOOK
 #319 FLUSHCACHEDFILEHANDLE
 #320 ISTASK
-323 pascal IsRomModule() IsRomModule
+323 return IsRomModule 2 0
 #324 LOGERROR
 #325 LOGPARAMERROR
-#326 ISROMFILE
+326 return IsRomFile 2 0
 #327 K327
 #328 _DEBUGOUTPUT
 #329 K329
@@ -237,5 +237,5 @@
 #354 GETAPPCOMPATFLAGS
 #355 GETWINDEBUGINFO
 #356 SETWINDEBUGINFO
-#403 K403
-#404 K404
+403 pascal16 FarSetOwner(word word) FarSetOwner
+404 pascal16 FarGetOwner(word) FarGetOwner
diff --git a/if1632/olecli.spec b/if1632/olecli.spec
index ea21107..97c3ded 100644
--- a/if1632/olecli.spec
+++ b/if1632/olecli.spec
@@ -1,8 +1,6 @@
 name	olecli
 id	20
-length	43
-## 954 is too large for now
-##length	954
+length	954
 
 #1 WEP
 #2 OLEDELETE
diff --git a/if1632/relay.c b/if1632/relay.c
index e717b5a..c855e81 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -23,16 +23,16 @@
 #include "prototypes.h"
 #include "dlls.h"
 #include "options.h"
+#include "selectors.h"
 #include "stackframe.h"
+#include "wine.h"
 #include "stddebug.h"
 /* #define DEBUG_RELAY */
-/* #define DEBUG_STACK */
 #include "debug.h"
 
 #if 0
 /* Make make_debug think these were really used */
 dprintf_relay
-dprintf_stack
 #endif
 
 #ifdef WINELIB
@@ -43,256 +43,210 @@
 
 struct dll_name_table_entry_s dll_builtin_table[N_BUILTINS] =
 {
-    { "KERNEL",  WineLibSkip(KERNEL_table), 	410, 1, 1 },
-    { "USER",    WineLibSkip(USER_table), 	540, 2, 1 },
-    { "GDI",     WineLibSkip(GDI_table), 	490, 3, 1 },
-    { "WIN87EM", WineLibSkip(WIN87EM_table),  10, 4, 1 },
-    { "SHELL",   WineLibSkip(SHELL_table),   103, 5, 1 },
-    { "SOUND",   WineLibSkip(SOUND_table),    20, 6, 1 },
-    { "KEYBOARD",WineLibSkip(KEYBOARD_table),137, 7, 1 },
-    { "WINSOCK", WineLibSkip(WINSOCK_table), 155, 8, 1 },
-    { "STRESS",  WineLibSkip(STRESS_table),   15, 9, 1},
-    { "MMSYSTEM",WineLibSkip(MMSYSTEM_table),1226,10, 1},
-    { "SYSTEM",  WineLibSkip(SYSTEM_table),   20 ,11, 1},
-    { "TOOLHELP",WineLibSkip(TOOLHELP_table), 83, 12, 1},
-    { "MOUSE",   WineLibSkip(MOUSE_table),     8, 13, 1},
-    { "COMMDLG", WineLibSkip(COMMDLG_table),  31, 14, 1},
-    { "OLE2",    WineLibSkip(OLE2_table),     31, 15, 1},
-    { "OLE2CONV",WineLibSkip(OLE2CONV_table), 31, 16, 1},
-    { "OLE2DISP",WineLibSkip(OLE2DISP_table), 31, 17, 1},
-    { "OLE2NLS", WineLibSkip(OLE2NLS_table),  31, 18, 1},
-    { "OLE2PROX",WineLibSkip(OLE2PROX_table), 31, 19, 1},
-    { "OLECLI",  WineLibSkip(OLECLI_table),   31, 20, 1},
-    { "OLESVR",  WineLibSkip(OLESVR_table),   31, 21, 1},
-    { "COMPOBJ", WineLibSkip(COMPOBJ_table),  31, 22, 1},
-    { "STORAGE", WineLibSkip(STORAGE_table),  31, 23, 1}
+    { "KERNEL",   WineLibSkip(&KERNEL_table), 1 },
+    { "USER",     WineLibSkip(&USER_table), 1 },
+    { "GDI",      WineLibSkip(&GDI_table), 1 },
+    { "WIN87EM",  WineLibSkip(&WIN87EM_table), 1 },
+    { "SHELL",    WineLibSkip(&SHELL_table), 1 },
+    { "SOUND",    WineLibSkip(&SOUND_table), 1 },
+    { "KEYBOARD", WineLibSkip(&KEYBOARD_table), 1 },
+    { "WINSOCK",  WineLibSkip(&WINSOCK_table), 1 },
+    { "STRESS",   WineLibSkip(&STRESS_table), 1 },
+    { "MMSYSTEM", WineLibSkip(&MMSYSTEM_table), 1 },
+    { "SYSTEM",   WineLibSkip(&SYSTEM_table), 1 },
+    { "TOOLHELP", WineLibSkip(&TOOLHELP_table), 1 },
+    { "MOUSE",    WineLibSkip(&MOUSE_table), 1 },
+    { "COMMDLG",  WineLibSkip(&COMMDLG_table), 1 },
+    { "OLE2",     WineLibSkip(&OLE2_table), 1 },
+    { "OLE2CONV", WineLibSkip(&OLE2CONV_table), 1 },
+    { "OLE2DISP", WineLibSkip(&OLE2DISP_table), 1 },
+    { "OLE2NLS",  WineLibSkip(&OLE2NLS_table), 1 },
+    { "OLE2PROX", WineLibSkip(&OLE2PROX_table), 1 },
+    { "OLECLI",   WineLibSkip(&OLECLI_table), 1 },
+    { "OLESVR",   WineLibSkip(&OLESVR_table), 1 },
+    { "COMPOBJ",  WineLibSkip(&COMPOBJ_table), 1 },
+    { "STORAGE",  WineLibSkip(&STORAGE_table), 1 },
+    { "WINPROCS", WineLibSkip(&WINPROCS_table), 1 },
 };
-/* don't forget to increase N_BUILTINS in dll.h if you add a dll */
+/* don't forget to increase N_BUILTINS in dlls.h if you add a dll */
 
-/* the argument conversion tables for each dll */
-struct dll_conversions {
-	unsigned short *dst_args;   /*  Offsets to arguments on stack */
-	unsigned char *src_types;   /* Argument types              */
-} dll_conversion_table[N_BUILTINS]= {
-  { KERNEL_offsets,   KERNEL_types },   /* KERNEL     */
-  { USER_offsets,     USER_types },     /* USER       */
-  { GDI_offsets,      GDI_types },      /* GDI        */
-  { WIN87EM_offsets,  WIN87EM_types },  /* WIN87EM    */
-  { SHELL_offsets,    SHELL_types },    /* SHELL      */
-  { SOUND_offsets,    SOUND_types },    /* SOUND      */
-  { KEYBOARD_offsets, KEYBOARD_types }, /* KEYBOARD   */
-  { WINSOCK_offsets,  WINSOCK_types },  /* WINSOCK    */
-  { STRESS_offsets,   STRESS_types },   /* STRESS,     */
-  { MMSYSTEM_offsets, MMSYSTEM_types }, /* MMSYSTEM   */
-  { SYSTEM_offsets,   SYSTEM_types },   /* SYSTEM     */
-  { TOOLHELP_offsets, TOOLHELP_types }, /* TOOLHELP   */
-  { MOUSE_offsets,    MOUSE_types },    /* MOUSE      */
-  { COMMDLG_offsets,  COMMDLG_types },  /* EMUCOMMDLG */
-  { OLE2_offsets,     OLE2_types },     /* OLE2       */
-  { OLE2CONV_offsets, OLE2CONV_types }, /* OLE2CONV   */
-  { OLE2DISP_offsets, OLE2DISP_types }, /* OLE2DISP   */
-  { OLE2NLS_offsets,  OLE2NLS_types },  /* OLE2NLS    */
-  { OLE2DISP_offsets, OLE2DISP_types }, /* OLE2PROX   */
-  { OLECLI_offsets,   OLECLI_types },   /* OLE2CLI    */
-  { OLESVR_offsets,   OLESVR_types },   /* OLE2CLI    */
-  { COMPOBJ_offsets,  COMPOBJ_types },  /* COMPOBJ    */
-  { STORAGE_offsets,  STORAGE_types }   /* STORAGE    */
-};
+  /* Saved 16-bit stack */
+WORD IF1632_Saved16_ss = 0;
+WORD IF1632_Saved16_sp = 0;
+WORD IF1632_Saved16_bp = 0;
+
+  /* Saved 32-bit stack */
+DWORD IF1632_Saved32_esp = 0;
+DWORD IF1632_Saved32_ebp = 0;
+
+/***********************************************************************
+ *           RELAY_Init
+ */
+BOOL RELAY_Init(void)
+{
+    WORD codesel, datasel;
+    struct dll_table_s *table;
+    struct dll_table_entry_s *entry;
+    int i, j;
+
+      /* Allocate the code selector for CallTo16 routines */
+
+    extern void CALL16_Start(), CALL16_End();
+    extern void CALL16_Ret_word(), CALL16_Ret_long();
+    extern DWORD CALL16_RetAddr_word, CALL16_RetAddr_long;
+
+    codesel = SELECTOR_AllocBlock( (void *)CALL16_Start,
+                                   (int)CALL16_End - (int)CALL16_Start,
+                                   SEGMENT_CODE, TRUE, FALSE );
+    if (!codesel) return FALSE;
+
+      /* Patch the return addresses for CallTo16 routines */
+
+    CALL16_RetAddr_word = MAKELONG( (int)CALL16_Ret_word - (int)CALL16_Start,
+                                    codesel );
+    CALL16_RetAddr_long = MAKELONG( (int)CALL16_Ret_long - (int)CALL16_Start,
+                                    codesel );
+
+      /* Allocate the selectors for built-in dlls */
+
+    for (i = 0; i < N_BUILTINS; i++)
+    {
+        table = dll_builtin_table[i].table;
+        codesel = SELECTOR_AllocBlock( table->code_start,
+                                   (int)table->code_end-(int)table->code_start,
+                                   SEGMENT_CODE, TRUE, FALSE );
+        if (!codesel) return FALSE;
+        if (table->data_start != table->data_end)
+            datasel = SELECTOR_AllocBlock( table->data_start,
+                                   (int)table->data_end-(int)table->data_start,
+                                   SEGMENT_DATA, TRUE, FALSE );
+        else datasel = 0;
+        entry = table->dll_table;
+        for (j = 0; j < table->dll_table_length; j++, entry++)
+        {
+            if (entry->selector == 1)  /* code selector */
+                entry->selector = codesel;
+            else if (entry->selector == 2)  /* data selector */
+                entry->selector = datasel;
+            else entry->selector = 0;  /* constant selector */
+        }
+    }
+
+    return TRUE;
+}
 
 
 #ifndef WINELIB
 
-extern unsigned short IF1632_Saved16_sp;
-extern unsigned short IF1632_Saved16_bp;
-extern unsigned short IF1632_Saved16_ss;
-
-void RelayDebug( unsigned int func_num )
+void RELAY_DebugCall32( char *args )
 {
-    unsigned int dll_id, ordinal;
-
-    if (debugging_relay)
-    {
-        dll_id  = ((func_num >> 16) & 0xffff) - 1;
-        ordinal = func_num & 0xffff;
-        printf( "Calling %s.%d\n",
-               dll_builtin_table[dll_id].dll_table[ordinal].export_name,
-               ordinal );
-    }
-}
-
-
-/**********************************************************************
- *					DLLRelay
- *
- * We get a stack frame pointer to data that looks like this:
- *
- *   Hex Offset Contents
- *   ---------- -------
- *	+00	previous saved_16ss
- *	+02	previous saved_16ebp
- *	+06	previous saved_16esp
- *	+0A	16-bit es
- *	+0C	16-bit ds
- *	+0E	16-bit ebp
- *	+12	length of 16-bit arguments
- *	+14	16-bit ip
- *	+16	16-bit cs
- *	+18	arguments
- */
-int
-DLLRelay(unsigned int func_num, unsigned int seg_off)
-{
-    struct dll_table_entry_s *dll_p;
-    STACK16FRAME *pStack16Frame;
-    unsigned int offset;
-    unsigned int dll_id;
-    unsigned int ordinal;
-    int arg_table[DLL_MAX_ARGS];
-    void *arg_ptr;
-    int (*func_ptr)();
+    STACK16FRAME *frame;
+    char *args16;
     int i;
-    int ret_val;
-    int conv_ref;
-    unsigned char *type_conv;
-    unsigned short *offset_conv;
-    STACK16FRAME stackFrameCopy;
 
-    /*
-     * Determine address of arguments.
-     */
-    pStack16Frame = (STACK16FRAME *) PTR_SEG_TO_LIN(seg_off);
-    arg_ptr = (void *)pStack16Frame->args;
+    if (!debugging_relay) return;
 
-    /*
-     * Extract the DLL number and ordinal number.
-     */
-    dll_id  = ((func_num >> 16) & 0xffff) - 1;
-    ordinal = func_num & 0xffff;
-    dll_p   = &dll_builtin_table[dll_id].dll_table[ordinal];
-
-    dprintf_relay( stddeb, "Call %s (%s.%d), stack=%04x:%04x ret=%04x:%04x ds=%04x bp=%04x args=%d\n",
-                  dll_p->export_name,
-                  dll_builtin_table[dll_id].dll_name, ordinal,
-                  seg_off >> 16, seg_off & 0xffff,
-                  pStack16Frame->cs, pStack16Frame->ip,
-                  pStack16Frame->ds, pStack16Frame->bp,
-                  pStack16Frame->arg_length );
-
-    if(debugging_stack)
+    frame = CURRENT_STACK16;
+    printf( "Call %s.%d: %s(",
+            dll_builtin_table[frame->dll_id-1].dll_name,
+            frame->ordinal_number,
+            dll_builtin_table[frame->dll_id-1].table->dll_table[frame->ordinal_number].export_name );
+    args16 = (char *)frame->args;
+    for (i = 0; i < strlen(args); i++)
     {
-        unsigned short *stack_p = (unsigned short *) pStack16Frame;
-        /* FIXME: Is there an end-of-stack-pointer somewhere ? */
-        int n = min(24, (0x10000 - (seg_off & 0xffff)) / sizeof(*stack_p));
-        for (i = 0; i < n; i++, stack_p++)
+        switch(args[i])
         {
-            printf("%04x ", *stack_p);
-            if ((i & 7) == 7)
-                printf("\n");
+        case 'w':
+        case 's':
+            args16 += 2;
+            break;
+        case 'l':
+        case 'p':
+            args16 += 4;
+            break;
         }
-        printf("\n");
     }
 
-    /*
-     * Make sure we have a handler defined for this call.
-     */
-    if (dll_p->handler == NULL)
+    while (*args)
     {
-	char buffer[100];
-	
-	sprintf(buffer, "No handler for routine %s.%d", 
-		dll_builtin_table[dll_id].dll_name, ordinal);
-	myerror(buffer);
-    }
-    func_ptr = dll_p->handler;
-
-    /*
-     * OK, special case.  If the handler is define as taking no arguments
-     * then pass the address of the arguments on the 16-bit stack to the
-     * handler.  It will just ignore the pointer if it really takes no
-     * arguments.  This allows us to write slightly faster library routines
-     * if we choose.
-     */
-    if (dll_p->n_args == 0)
-    {
-	ret_val = (*func_ptr)(arg_ptr);
-	dprintf_relay( stddeb, "Returning %08x from %s (%s.%d) ds=%04x\n",
-                       ret_val, dll_p->export_name,
-                       dll_builtin_table[dll_id].dll_name, ordinal,
-                       pStack16Frame->ds );
-	return ret_val;
-    }
-
-    /*
-     * Getting this far means we need to convert the 16-bit argument stack.
-     */
-    conv_ref= dll_p->conv_reference;
-    type_conv= dll_conversion_table[dll_id].src_types + conv_ref;
-    offset_conv= dll_conversion_table[dll_id].dst_args + conv_ref;
-    for (i = 0; i < dll_p->n_args; i++,type_conv++,offset_conv++)
-    {
-	short *sp;
-	int *ip;
-	
-	offset = *offset_conv;
-
-	switch (*type_conv)
-	{
-	  case DLL_ARGTYPE_SIGNEDWORD:
-	    sp = (short *) ((char *) arg_ptr + offset);
-	    arg_table[i] = *sp;
-	    break;
-	    
-	  case DLL_ARGTYPE_WORD:
-	    sp = (short *) ((char *) arg_ptr + offset);
-	    arg_table[i] = (int) *sp & 0xffff;
-	    break;
-	    
-	  case DLL_ARGTYPE_LONG:
-	    ip = (int *) ((char *) arg_ptr + offset);
-	    arg_table[i] = *ip;
-	    break;
-
-	  case DLL_ARGTYPE_FARPTR:
-	    ip = (int *) ((char *) arg_ptr + offset);
-            arg_table[i] = (unsigned int) PTR_SEG_TO_LIN( *ip );
-	    break;
-	}
-    }
-
-    if (debugging_relay)
-        memcpy( &stackFrameCopy, pStack16Frame, sizeof(stackFrameCopy) );
-
-    /*
-     * Call the handler
-     */
-    ret_val = (*func_ptr)(arg_table[0], arg_table[1], arg_table[2], 
-			  arg_table[3], arg_table[4], arg_table[5], 
-			  arg_table[6], arg_table[7], arg_table[8], 
-			  arg_table[9], arg_table[10], arg_table[11],
-			  arg_table[12], arg_table[13], arg_table[14], 
-			  arg_table[15]);
-
-    if (debugging_relay)
-    {
-        if (memcmp( &stackFrameCopy, pStack16Frame, sizeof(stackFrameCopy) ))
+        switch(*args)
         {
-            printf( "**** 16-bit stack corrupted!\n" );
+        case 'w':
+        case 's':
+            args16 -= 2;
+            printf( "0x%04x", *(WORD *)args16 );
+            break;
+        case 'l':
+            args16 -= 4;
+            printf( "0x%08x", *(int *)args16 );
+            break;
+        case 'p':
+            args16 -= 4;
+            printf( "%04x:%04x", *(WORD *)(args16+2), *(WORD *)args16 );
+            break;
         }
-	printf("Returning %08x from %s (%s.%d) ds=%04x\n",
-	       ret_val,
-	       dll_p->export_name,
-	       dll_builtin_table[dll_id].dll_name, ordinal,
-               pStack16Frame->ds );
+        args++;
+        if (*args) printf( "," );
     }
-
-    return ret_val;
+    printf( ") ret=%04x:%04x ds=%04x\n", frame->cs, frame->ip, frame->ds );
 }
-#endif
+
+
+void RELAY_DebugReturn( int short_ret, int ret_val )
+{
+    STACK16FRAME *frame;
+
+    if (!debugging_relay) return;
+
+    frame = CURRENT_STACK16;
+    printf( "Ret  %s.%d: %s() ",
+            dll_builtin_table[frame->dll_id-1].dll_name,
+            frame->ordinal_number,
+            dll_builtin_table[frame->dll_id-1].table->dll_table[frame->ordinal_number].export_name );
+    if (short_ret) printf( "retval=0x%04x\n", ret_val & 0xffff );
+    else printf( "retval=0x%08x\n", ret_val );
+}
+
+
+void RELAY_Unimplemented(void)
+{
+    STACK16FRAME *frame = CURRENT_STACK16;
+
+    fprintf( stderr, "No handler for routine %s.%d\n",
+             dll_builtin_table[frame->dll_id-1].dll_name,
+             frame->ordinal_number );
+    exit(1);
+}
+
+
+/***********************************************************************
+ *           RELAY_DebugCall16
+ *
+ * 'stack' points to the called function address on the 32-bit stack.
+ * Stack layout:
+ *  ...        ...
+ * (stack+12)  arg2
+ * (stack+8)   arg1
+ * (stack+4)   16-bit ds
+ * (stack)     func to call
+ */
+void RELAY_DebugCall16( int* stack, int nbargs )
+{
+    if (!debugging_relay) return;
+
+    printf( "CallTo16(func=%04x:%04x,ds=%04x",
+            HIWORD(stack[0]), LOWORD(stack[0]), LOWORD(stack[1]) );
+    stack += 2;
+    while (nbargs--) printf( ",0x%x", *stack++ );
+    printf( ")\n" );
+}
+
+#endif  /* WINELIB */
 
 /**********************************************************************
  *					FindDLLTable
  */
-struct  dll_table_entry_s *
+struct dll_table_s *
 FindDLLTable(char *dll_name)
 {
     int i;
@@ -300,11 +254,7 @@
     for (i = 0; i < N_BUILTINS; i++)
 	if (strcasecmp(dll_builtin_table[i].dll_name, dll_name) == 0
 	  && dll_builtin_table[i].dll_is_used)
-#ifdef WINELIB
-	    return dll_builtin_table[i].dll_number;
-#else
-	    return dll_builtin_table[i].dll_table;
-#endif
+	    return dll_builtin_table[i].table;
     return NULL;
 }
 
@@ -317,27 +267,19 @@
     int i, limit;
 
     for (i = 0; i < N_BUILTINS; i++)
-	if (dll_table == dll_builtin_table[i].dll_table)
+	if (dll_table == dll_builtin_table[i].table->dll_table)
 	    break;
     
     if (i == N_BUILTINS)
 	return 0;
 
-    limit = dll_builtin_table[i].dll_table_length;
+    limit = dll_builtin_table[i].table->dll_table_length;
     for (i = 0; i < limit; i++)
 	if (strcasecmp(dll_table[i].export_name, func_name) == 0)
 	    return i;
     
     return 0;
 }
-/**********************************************************************
- *					ReturnArg
- */
-int
-ReturnArg(int arg)
-{
-    return arg;
-}
 
 #ifndef WINELIB
 #ifdef WINESTAT
@@ -351,13 +293,13 @@
 	tused = 0;
 	timplemented = 0;
     for (i = 0; i < N_BUILTINS; i++) {
-	    table = dll_builtin_table[i].dll_table;
+	    table = dll_builtin_table[i].table->dll_table;
 	    used = 0;
 	    implemented = 0;
-	    for(j=0; j < dll_builtin_table[i].dll_table_length; j++) {
+	    for(j=0; j < dll_builtin_table[i].table->dll_table_length; j++) {
 		    if(table[j].used){
 			    used++;
-			    if (table[j].handler) implemented++;
+			    if (table[j].export_name[0]) implemented++;
 			    else 
 				    printf("%s.%d not implemented\n",
 					   dll_builtin_table[i].dll_name,
diff --git a/if1632/toolhelp.spec b/if1632/toolhelp.spec
index 775ee81..a7d8243 100644
--- a/if1632/toolhelp.spec
+++ b/if1632/toolhelp.spec
@@ -3,11 +3,11 @@
 length	83
 
 50 pascal16 GlobalHandleToSel(word) GlobalHandleToSel
-# 51   1  0318  GLOBALFIRST exported, shared data
-# 52   1  0399  GLOBALNEXT exported, shared data
-# 53   1  02a2  GLOBALINFO exported, shared data
-# 54   1  0417  GLOBALENTRYHANDLE exported, shared data
-# 55   1  04a9  GLOBALENTRYMODULE exported, shared data
+51 pascal16 GlobalFirst(ptr word) GlobalFirst
+52 pascal16 GlobalNext(ptr word) GlobalNext
+53 pascal16 GlobalInfo(ptr) GlobalInfo
+54 pascal16 GlobalEntryHandle(ptr word) GlobalEntryHandle
+55 pascal16 GlobalEntryModule(ptr word word) GlobalEntryModule
 56 pascal16 LocalInfo(ptr word) LocalInfo
 57 pascal16 LocalFirst(ptr word) LocalFirst
 58 pascal16 LocalNext(ptr) LocalNext
@@ -24,7 +24,7 @@
 69 pascal16 ClassFirst(ptr) ClassFirst
 70 pascal16 ClassNext(ptr) ClassNext
 71 pascal16 SystemHeapInfo(ptr) SystemHeapInfo
-#72 pascal16 MemManInfo(ptr) MemManInfo
+72 pascal16 MemManInfo(ptr) MemManInfo
 # 73   1  1b72  NOTIFYREGISTER exported, shared data
 # 74   1  1c29  NOTIFYUNREGISTER exported, shared data
 # 75   1  2060  INTERRUPTREGISTER exported, shared data
diff --git a/if1632/user.spec b/if1632/user.spec
index 73de7b6..58a1a79 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -392,36 +392,36 @@
 482 pascal16 EnableScrollBar(word word word) EnableScrollBar
 483 pascal SystemParametersInfo(word word ptr word) SystemParametersInfo
 #484 __GP
-#499 WNETERRORTEXT
-#501 WNETOPENJOB
-#502 WNETCLOSEJOB
-#503 WNETABORTJOB
-#504 WNETHOLDJOB
-#505 WNETRELEASEJOB
-#506 WNETCANCELJOB
-#507 WNETSETJOBCOPIES
-#508 WNETWATCHQUEUE
-#509 WNETUNWATCHQUEUE
-#510 WNETLOCKQUEUEDATA
-#511 WNETUNLOCKQUEUEDATA
+499 pascal WNetErrorText(word ptr word) WNetErrorText
+501 pascal WNetOpenJob(ptr ptr word ptr)  WNetOpenJob
+502 pascal WNetCloseJob(word ptr ptr) WNetCloseJob
+503 pascal WNetAbortJob(ptr word) WNetAbortJob
+504 pascal WNetHoldJob(ptr word) WNetHoldJob
+505 pascal WNetReleaseJob(ptr word) WNetReleaseJob
+506 pascal WNetCancelJob(ptr word) WNetCancelJob
+507 pascal WNetSetJobCopies(ptr word word) WNetSetJobCopies
+508 pascal WNetWatchQueue(word ptr ptr word) WNetWatchQueue
+509 pascal WNetUnwatchQueue(word ptr ptr word) WNetUnwatchQueue
+510 pascal WNetLockQueueData(ptr ptr ptr) WNetLockQueueData
+511 pascal WNetUnlockQueueData(ptr) WNetUnlockQueueData
 512 pascal16 WNetGetConnection(ptr ptr ptr) WNetGetConnection
 513 pascal WNetGetCaps(word) WNetGetCaps
-#514 WNETDEVICEMODE
-#515 WNETBROWSEDIALOG
+514 pascal WNetDeviceMode(word) WNetDeviceMode
+515 pascal WNetBrowseDialog(word word ptr) WNetBrowseDialog
 516 pascal WNetGetUser(ptr ptr ptr) WNetGetUser
 517 pascal16 WNetAddConnection(ptr ptr ptr) WNetAddConnection
 518 pascal16 WNetCancelConnection(ptr word) WNetCancelConnection
-#519 WNETGETERROR
-#520 WNETGETERRORTEXT
+519 pascal WNetGetError(ptr) WNetGetError
+520 pascal WNetGetErrorText(word ptr ptr) WNetGetErrorText
 #521 WNETENABLE
 #522 WNETDISABLE
-#523 WNETRESTORECONNECTION
-#524 WNETWRITEJOB
-#525 WNETCONNECTDIALOG
-#526 WNETDISCONNECTDIALOG
-#527 WNETCONNECTIONDIALOG
-#528 WNETVIEWQUEUEDIALOG
-#529 WNETPROPERTYDIALOG
-#530 WNETGETDIRECTORYTYPE
-#531 WNETDIRECTORYNOTIFY
-#532 WNETGETPROPERTYTEXT
+523 pascal WNetRestoreConnection(word ptr) WNetRestoreConnection
+524 pascal WNetWriteJob(word ptr ptr) WNetWriteJob
+525 pascal WnetConnectDialog(word word) WNetConnectDialog
+526 pascal WNetDisconnectDialog(word word) WNetDisconnectDialog
+527 pascal WNetConnectionDialog(word word) WNetConnectionDialog
+528 pascal WNetViewQueueDialog(word ptr) WNetViewQueueDialog
+529 pascal WNetPropertyDialog(word word ptr word) WNetPropertyDialog
+530 pascal WNetGetDirectoryType(ptr ptr) WNetGetDirectoryType
+531 pascal WNetDirectoryNotify(word ptr word) WNetDirectoryNotify
+532 pascal WNetGetPropertyText(word word word ptr word) WNetGetPropertyText
diff --git a/if1632/winprocs.spec b/if1632/winprocs.spec
new file mode 100644
index 0000000..c276817
--- /dev/null
+++ b/if1632/winprocs.spec
@@ -0,0 +1,27 @@
+name	winprocs
+id	24
+length	23
+
+1  pascal ButtonWndProc(word word word long) ButtonWndProc
+2  pascal StaticWndProc(word word word long) StaticWndProc
+3  pascal ScrollBarWndProc(word word word long) ScrollBarWndProc
+4  pascal ListBoxWndProc(word word word long) ListBoxWndProc
+5  pascal ComboBoxWndProc(word word word long) ComboBoxWndProc
+6  pascal EditWndProc(word word word long) EditWndProc
+7  pascal PopupMenuWndProc(word word word long) PopupMenuWndProc
+8  pascal DesktopWndProc(word word word long) DesktopWndProc
+9  pascal DefDlgProc(word word word long) DefDlgProc
+10 pascal MDIClientWndProc(word word word long) MDIClientWndProc
+11 pascal DefWindowProc(word word word long) DefWindowProc
+12 pascal DefMDIChildProc(word word word long) DefMDIChildProc
+13 pascal SystemMessageBoxProc(word word word long) SystemMessageBoxProc
+14 pascal FileOpenDlgProc(word word word long) FileOpenDlgProc
+15 pascal FileSaveDlgProc(word word word long) FileSaveDlgProc
+16 pascal ColorDlgProc(word word word long) ColorDlgProc
+17 pascal FindTextDlgProc(word word word long) FindTextDlgProc
+18 pascal ReplaceTextDlgProc(word word word long) ReplaceTextDlgProc
+19 pascal PrintSetupDlgProc(word word word long) PrintSetupDlgProc
+20 pascal PrintDlgProc(word word word long) PrintDlgProc
+21 pascal AboutDlgProc(word word word long) AboutDlgProc
+22 pascal AboutWine_Proc(word word word long) AboutWine_Proc
+23 pascal16 CARET_Callback(word word word long) CARET_Callback
diff --git a/include/callback.h b/include/callback.h
index 18206c9..01a87d6 100644
--- a/include/callback.h
+++ b/include/callback.h
@@ -1,21 +1,93 @@
-/* $Id$
- */
 /*
- * Copyright  Robert J. Amstadt, 1993
+ * 16-bit mode callback functions
+ *
+ * Copyright 1995 Alexandre Julliard
  */
 
-#ifndef CALLBACK_H
-#define CALLBACK_H
+#ifndef WINE_CALLBACK_H
+#define WINE_CALLBACK_H
 
 #include <stdlib.h>
 #include <stdarg.h>
 
-#define CALLBACK_SIZE_WORD	0
-#define CALLBACK_SIZE_LONG	1
+#include "stackframe.h"
 
-extern int CallTo16(unsigned int csip, unsigned short ds);
-extern int CallBack16(void *func, int n_args, ...);
+#ifndef WINELIB
 
-extern BOOL CallGrayStringProc(FARPROC func, HDC hdc, LPARAM lParam, INT cch);
+/* List of the 16-bit callback functions. This list is used  */
+/* by the build program to generate the file if1632/call16.S */
 
-#endif /* CALLBACK_H */
+                               /* func     ds    parameters */
+extern WORD CallTo16_word_wl   ( FARPROC, WORD, WORD, LONG );
+extern WORD CallTo16_word_ll   ( FARPROC, WORD, LONG, LONG );
+extern WORD CallTo16_word_wwl  ( FARPROC, WORD, WORD, WORD, LONG );
+extern WORD CallTo16_word_wlw  ( FARPROC, WORD, WORD, LONG, WORD );
+extern LONG CallTo16_long_wwl  ( FARPROC, WORD, WORD, WORD, LONG );
+extern WORD CallTo16_word_llwl ( FARPROC, WORD, LONG, LONG, WORD, LONG );
+extern LONG CallTo16_long_wwwl ( FARPROC, WORD, WORD, WORD, WORD, LONG );
+extern WORD CallTo16_word_wllwl( FARPROC, WORD, WORD, LONG, LONG, WORD, LONG );
+extern WORD CallTo16_word_wwlll( FARPROC, WORD, WORD, WORD, LONG, LONG, LONG );
+
+extern WORD CallTo16_regs_( FARPROC func, WORD ds, WORD es, WORD ax, WORD bx,
+                            WORD cx, WORD dx, WORD si, WORD di );
+
+#define CallEnumChildProc( func, hwnd, lParam ) \
+    CallTo16_word_wl( func, CURRENT_DS, hwnd, lParam )
+#define CallEnumFontFamProc( func, lpfont, lpmetric, type, lParam ) \
+    CallTo16_word_llwl( func, CURRENT_DS, lpfont, lpmetric, type, lParam )
+#define CallEnumFontsProc( func, lpfont, lpmetric, type, lParam ) \
+    CallTo16_word_llwl( func, CURRENT_DS, lpfont, lpmetric, type, lParam )
+#define CallEnumMetafileProc( func, hdc, lptable, lprecord, objs, lParam ) \
+    CallTo16_word_wllwl(func, CURRENT_DS, hdc, lptable, lprecord, objs, lParam)
+#define CallEnumObjectsProc( func, lpobj, lParam ) \
+    CallTo16_word_ll( func, CURRENT_DS, lpobj, lParam )
+#define CallEnumPropProc( func, hwnd, lpstr, data ) \
+    CallTo16_word_wlw( func, CURRENT_DS, hwnd, lpstr, data )
+#define CallEnumTaskWndProc( func, hwnd, lParam ) \
+    CallTo16_word_wl( func, CURRENT_DS, hwnd, lParam )
+#define CallEnumWindowsProc( func, hwnd, lParam ) \
+    CallTo16_word_wl( func, CURRENT_DS, hwnd, lParam )
+#define CallLineDDAProc( func, xPos, yPos, lParam ) \
+    CallTo16_word_wwl( func, CURRENT_DS, xPos, yPos, lParam )
+#define CallGrayStringProc( func, hdc, lParam, cch ) \
+    CallTo16_word_wlw( func, CURRENT_DS, hdc, lParam, cch )
+#define CallHookProc( func, code, wParam, lParam ) \
+    CallTo16_long_wwl( func, CURRENT_DS, code, wParam, lParam )
+#define CallTimeFuncProc( func, id, msg, dwUser, dw1, dw2 ) \
+    CallTo16_word_wwlll( func, CURRENT_DS, id, msg, dwUser, dw1, dw2 )
+#define CallWndProc( func, hwnd, msg, wParam, lParam ) \
+    CallTo16_long_wwwl( func, CURRENT_DS, hwnd, msg, wParam, lParam )
+
+#else  /* WINELIB */
+
+#define CallEnumChildProc( func, hwnd, lParam ) \
+    (*func)( hwnd, lParam )
+#define CallEnumFontFamProc( func, lpfont, lpmetric, type, lParam ) \
+    (*func)( lpfont, lpmetric, type, lParam )
+#define CallEnumFontsProc( func, lpfont, lpmetric, type, lParam ) \
+    (*func)( lpfont, lpmetric, type, lParam )
+#define CallEnumMetafileProc( func, hdc, lptable, lprecord, objs, lParam ) \
+    (*func)( hdc, lptable, lprecord, objs, lParam)
+#define CallEnumObjectsProc( func, lpobj, lParam ) \
+    (*func)( lpobj, lParam )
+#define CallEnumPropProc( func, hwnd, lpstr, data ) \
+    (*func)( hwnd, lpstr, data )
+#define CallEnumTaskWndProc( func, hwnd, lParam ) \
+    (*func)( hwnd, lParam )
+#define CallEnumWindowsProc( func, hwnd, lParam ) \
+    (*func)( hwnd, lParam )
+#define CallLineDDAProc( func, xPos, yPos, lParam ) \
+    (*func)( xPos, yPos, lParam )
+#define CallGrayStringProc( func, hdc, lParam, cch ) \
+    (*func)( hdc, lParam, cch )
+#define CallHookProc( func, code, wParam, lParam ) \
+    (*func)( code, wParam, lParam )
+#define CallTimeFuncProc( func, id, msg, dwUser, dw1, dw2 ) \
+    (*func)( id, msg, dwUser, dw1, dw2 )
+#define CallWndProc( func, hwnd, msg, wParam, lParam ) \
+    (*func)( hwnd, msg, wParam, lParam )
+
+#endif  /* WINELIB */
+
+
+#endif /* WINE_CALLBACK_H */
diff --git a/include/compobj.h b/include/compobj.h
new file mode 100644
index 0000000..d9482dc
--- /dev/null
+++ b/include/compobj.h
@@ -0,0 +1,5 @@
+/*
+ *	compobj.h	-	Declarations for COMPOBJ
+ */
+
+typedef	LPVOID	LPUNKNOWN;
diff --git a/include/debug.h b/include/debug.h
index 34493c8..24c4730 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -69,7 +69,6 @@
 #undef DEBUG_SCROLL
 #undef DEBUG_SELECTOR
 #undef DEBUG_SELECTORS
-#undef DEBUG_STACK
 #undef DEBUG_STRESS
 #undef DEBUG_SYSCOLOR
 #undef DEBUG_TASK
@@ -145,7 +144,6 @@
 #define DEBUG_SCROLL
 #define DEBUG_SELECTOR
 #define DEBUG_SELECTORS
-#define DEBUG_STACK
 #define DEBUG_STRESS
 #define DEBUG_SYSCOLOR
 #define DEBUG_TASK
@@ -475,11 +473,6 @@
 #else
     0,
 #endif
-#ifdef DEBUG_STACK
-    1,
-#else
-    0,
-#endif
 #ifdef DEBUG_STRESS
     1,
 #else
@@ -1352,21 +1345,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_stack if(!debug_msg_enabled[63]) ; else fprintf
-#define debugging_stack debug_msg_enabled[63]
-#else
-#ifdef DEBUG_STACK
-#define dprintf_stack fprintf
-#define debugging_stack 1
-#else
-#define dprintf_stack while(0) fprintf
-#define debugging_stack 0
-#endif
-#endif
-
-#ifdef DEBUG_RUNTIME
-#define dprintf_stress if(!debug_msg_enabled[64]) ; else fprintf
-#define debugging_stress debug_msg_enabled[64]
+#define dprintf_stress if(!debug_msg_enabled[63]) ; else fprintf
+#define debugging_stress debug_msg_enabled[63]
 #else
 #ifdef DEBUG_STRESS
 #define dprintf_stress fprintf
@@ -1378,8 +1358,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_syscolor if(!debug_msg_enabled[65]) ; else fprintf
-#define debugging_syscolor debug_msg_enabled[65]
+#define dprintf_syscolor if(!debug_msg_enabled[64]) ; else fprintf
+#define debugging_syscolor debug_msg_enabled[64]
 #else
 #ifdef DEBUG_SYSCOLOR
 #define dprintf_syscolor fprintf
@@ -1391,8 +1371,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_task if(!debug_msg_enabled[66]) ; else fprintf
-#define debugging_task debug_msg_enabled[66]
+#define dprintf_task if(!debug_msg_enabled[65]) ; else fprintf
+#define debugging_task debug_msg_enabled[65]
 #else
 #ifdef DEBUG_TASK
 #define dprintf_task fprintf
@@ -1404,8 +1384,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_text if(!debug_msg_enabled[67]) ; else fprintf
-#define debugging_text debug_msg_enabled[67]
+#define dprintf_text if(!debug_msg_enabled[66]) ; else fprintf
+#define debugging_text debug_msg_enabled[66]
 #else
 #ifdef DEBUG_TEXT
 #define dprintf_text fprintf
@@ -1417,8 +1397,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_timer if(!debug_msg_enabled[68]) ; else fprintf
-#define debugging_timer debug_msg_enabled[68]
+#define dprintf_timer if(!debug_msg_enabled[67]) ; else fprintf
+#define debugging_timer debug_msg_enabled[67]
 #else
 #ifdef DEBUG_TIMER
 #define dprintf_timer fprintf
@@ -1430,8 +1410,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_toolhelp if(!debug_msg_enabled[69]) ; else fprintf
-#define debugging_toolhelp debug_msg_enabled[69]
+#define dprintf_toolhelp if(!debug_msg_enabled[68]) ; else fprintf
+#define debugging_toolhelp debug_msg_enabled[68]
 #else
 #ifdef DEBUG_TOOLHELP
 #define dprintf_toolhelp fprintf
@@ -1443,8 +1423,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_utility if(!debug_msg_enabled[70]) ; else fprintf
-#define debugging_utility debug_msg_enabled[70]
+#define dprintf_utility if(!debug_msg_enabled[69]) ; else fprintf
+#define debugging_utility debug_msg_enabled[69]
 #else
 #ifdef DEBUG_UTILITY
 #define dprintf_utility fprintf
@@ -1456,8 +1436,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_win if(!debug_msg_enabled[71]) ; else fprintf
-#define debugging_win debug_msg_enabled[71]
+#define dprintf_win if(!debug_msg_enabled[70]) ; else fprintf
+#define debugging_win debug_msg_enabled[70]
 #else
 #ifdef DEBUG_WIN
 #define dprintf_win fprintf
@@ -1469,8 +1449,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_winsock if(!debug_msg_enabled[72]) ; else fprintf
-#define debugging_winsock debug_msg_enabled[72]
+#define dprintf_winsock if(!debug_msg_enabled[71]) ; else fprintf
+#define debugging_winsock debug_msg_enabled[71]
 #else
 #ifdef DEBUG_WINSOCK
 #define dprintf_winsock fprintf
@@ -1548,7 +1528,6 @@
     "scroll",
     "selector",
     "selectors",
-    "stack",
     "stress",
     "syscolor",
     "task",
diff --git a/include/dlls.h b/include/dlls.h
index cdceae5..10f2f08 100644
--- a/include/dlls.h
+++ b/include/dlls.h
@@ -7,6 +7,8 @@
 #ifndef DLLS_H
 #define DLLS_H
 
+#include "wintypes.h"
+
 #define MAX_NAME_LENGTH		64
 
 typedef struct resource_name_table
@@ -54,119 +56,67 @@
 #define DLL	0
 #define EXE	1
 
-#define DLL_ARGTYPE_SIGNEDWORD	0
-#define DLL_ARGTYPE_WORD	1
-#define DLL_ARGTYPE_LONG	2
-#define DLL_ARGTYPE_FARPTR	3
-#define DLL_MAX_ARGS		16
-
-#define DLL_HANDLERTYPE_PASCAL	16
-
 struct dll_table_entry_s
 {
     /*
      * Relocation data
      */
-    unsigned int selector;	/* Selector to access this entry point	  */
-    void *address;		/* Offset in segment of entry point	  */
+    WORD selector;  /* Selector of entry point */
+    WORD offset;    /* Offset in segment of entry point */
 
     /*
      * 16->32 bit interface data
      */
     char *export_name;
-    void *handler;		/* Address of function to process request */
-    char n_args;			/* Number of arguments passed to function */
-    short conv_reference ; /* reference to Argument conversion data  */
 #ifdef WINESTAT
     int used;			/* Number of times this function referenced */
 #endif
-    
+};
+
+struct dll_table_s
+{
+    struct dll_table_entry_s *dll_table;
+    int dll_table_length;
+    int dll_number;
+    void *code_start;  /* 32-bit address of DLL code */
+    void *code_end;
+    void *data_start;  /* 32-bit address of DLL data */
+    void *data_end;
 };
 
 struct dll_name_table_entry_s
 {
     char *dll_name;
-    struct dll_table_entry_s *dll_table;
-    int dll_table_length;
-    int dll_number;
+    struct dll_table_s *table;
     int dll_is_used;   /* use MS provided if set to zero */
 };
 
-extern struct dll_table_entry_s KERNEL_table[];
-extern struct dll_table_entry_s USER_table[];
-extern struct dll_table_entry_s GDI_table[];
-extern struct dll_table_entry_s WIN87EM_table[];
-extern struct dll_table_entry_s MMSYSTEM_table[];
-extern struct dll_table_entry_s SHELL_table[];
-extern struct dll_table_entry_s SOUND_table[];
-extern struct dll_table_entry_s KEYBOARD_table[];
-extern struct dll_table_entry_s WINSOCK_table[];
-extern struct dll_table_entry_s STRESS_table[];
-extern struct dll_table_entry_s SYSTEM_table[];
-extern struct dll_table_entry_s TOOLHELP_table[];
-extern struct dll_table_entry_s MOUSE_table[];
-extern struct dll_table_entry_s COMMDLG_table[];
-extern struct dll_table_entry_s OLE2_table[];
-extern struct dll_table_entry_s OLE2CONV_table[];
-extern struct dll_table_entry_s OLE2DISP_table[];
-extern struct dll_table_entry_s OLE2NLS_table[];
-extern struct dll_table_entry_s OLE2PROX_table[];
-extern struct dll_table_entry_s OLECLI_table[];
-extern struct dll_table_entry_s OLESVR_table[];
-extern struct dll_table_entry_s COMPOBJ_table[];
-extern struct dll_table_entry_s STORAGE_table[];
+extern struct dll_table_s KERNEL_table;
+extern struct dll_table_s USER_table;
+extern struct dll_table_s GDI_table;
+extern struct dll_table_s WIN87EM_table;
+extern struct dll_table_s MMSYSTEM_table;
+extern struct dll_table_s SHELL_table;
+extern struct dll_table_s SOUND_table;
+extern struct dll_table_s KEYBOARD_table;
+extern struct dll_table_s WINSOCK_table;
+extern struct dll_table_s STRESS_table;
+extern struct dll_table_s SYSTEM_table;
+extern struct dll_table_s TOOLHELP_table;
+extern struct dll_table_s MOUSE_table;
+extern struct dll_table_s COMMDLG_table;
+extern struct dll_table_s OLE2_table;
+extern struct dll_table_s OLE2CONV_table;
+extern struct dll_table_s OLE2DISP_table;
+extern struct dll_table_s OLE2NLS_table;
+extern struct dll_table_s OLE2PROX_table;
+extern struct dll_table_s OLECLI_table;
+extern struct dll_table_s OLESVR_table;
+extern struct dll_table_s COMPOBJ_table;
+extern struct dll_table_s STORAGE_table;
+extern struct dll_table_s WINPROCS_table;
 
-
-extern unsigned short KERNEL_offsets[];
-extern unsigned short USER_offsets[];
-extern unsigned short GDI_offsets[];
-extern unsigned short WIN87EM_offsets[];
-extern unsigned short MMSYSTEM_offsets[];
-extern unsigned short SHELL_offsets[];
-extern unsigned short SOUND_offsets[];
-extern unsigned short KEYBOARD_offsets[];
-extern unsigned short WINSOCK_offsets[];
-extern unsigned short STRESS_offsets[];
-extern unsigned short SYSTEM_offsets[];
-extern unsigned short TOOLHELP_offsets[];
-extern unsigned short MOUSE_offsets[];
-extern unsigned short COMMDLG_offsets[];
-extern unsigned short OLE2_offsets[];
-extern unsigned short OLE2CONV_offsets[];
-extern unsigned short OLE2DISP_offsets[];
-extern unsigned short OLE2NLS_offsets[];
-extern unsigned short OLE2PROX_offsets[];
-extern unsigned short OLECLI_offsets[];
-extern unsigned short OLESVR_offsets[];
-extern unsigned short COMPOBJ_offsets[];
-extern unsigned short STORAGE_offsets[];
-
-
-extern unsigned char KERNEL_types[];
-extern unsigned char USER_types[];
-extern unsigned char GDI_types[];
-extern unsigned char WIN87EM_types[];
-extern unsigned char MMSYSTEM_types[];
-extern unsigned char SHELL_types[];
-extern unsigned char SOUND_types[];
-extern unsigned char KEYBOARD_types[];
-extern unsigned char WINSOCK_types[];
-extern unsigned char STRESS_types[];
-extern unsigned char SYSTEM_types[];
-extern unsigned char TOOLHELP_types[];
-extern unsigned char MOUSE_types[];
-extern unsigned char COMMDLG_types[];
-extern unsigned char OLE2_types[];
-extern unsigned char OLE2CONV_types[];
-extern unsigned char OLE2DISP_types[];
-extern unsigned char OLE2NLS_types[];
-extern unsigned char OLE2PROX_types[];
-extern unsigned char OLECLI_types[];
-extern unsigned char OLESVR_types[];
-extern unsigned char COMPOBJ_types[];
-extern unsigned char STORAGE_types[];
-
-#define N_BUILTINS	23
+#define N_BUILTINS	24
 
 #endif /* DLLS_H */
 
diff --git a/include/global.h b/include/global.h
new file mode 100644
index 0000000..626890f
--- /dev/null
+++ b/include/global.h
@@ -0,0 +1,16 @@
+/*
+ * Global heap declarations
+ *
+ * Copyright 1995 Alexandre Julliard
+ */
+
+#ifndef __WINE_GLOBAL_H
+#define __WINE_GLOBAL_H
+
+#include "wintypes.h"
+
+extern HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
+                             BOOL isCode, BOOL isReadOnly );
+extern WORD GlobalHandleToSel( HGLOBAL handle );
+
+#endif  /* __WINE_GLOBAL_H */
diff --git a/include/hook.h b/include/hook.h
index 303fdd8..bd91822 100644
--- a/include/hook.h
+++ b/include/hook.h
@@ -9,6 +9,7 @@
 
 #include "windows.h"
 #include "ldt.h"
+#include "callback.h"
 
   /* Hook data (pointed to by a HHOOK) */
 typedef struct
@@ -34,9 +35,6 @@
 #define CALL_TASK_HOOK(id,code,wparam,lparam) \
     INTERNAL_CALL_HOOK(TASK_HOOK(id),code,wparam,lparam)
 
-extern DWORD CallHookProc( HOOKPROC func, short code,
-			   WPARAM wParam, LPARAM lParam );  /* callback.c */
-
 extern HHOOK systemHooks[];
 extern HHOOK taskHooks[];
 
diff --git a/include/if1632.h b/include/if1632.h
index 03621a6..96726dd 100644
--- a/include/if1632.h
+++ b/include/if1632.h
@@ -7,12 +7,11 @@
 			unsigned short ds);
 extern int CallTo16cx(unsigned long csip, unsigned long dscx);
 extern int CallToDllEntry(unsigned long csip, unsigned long dscx, unsigned short di);
-extern int CallBack16(void *func, int n_args, ...);
-extern void CallLineDDAProc(FARPROC func, short xPos, short yPos, long lParam);
 extern void winestat(void);
-extern int DLLRelay(unsigned int func_num, unsigned int seg_off);
-extern struct dll_table_entry_s *FindDLLTable(char *dll_name);
+extern struct dll_table_s *FindDLLTable(char *dll_name);
 extern int FindOrdinalFromName(struct dll_table_entry_s *dll_table, char *func_name);
 extern int ReturnArg(int arg);
 
+extern BOOL RELAY_Init(void);
+
 #endif /* __WINE_IF1632_H */
diff --git a/include/listbox.h b/include/listbox.h
index c1b2278..307a74e 100644
--- a/include/listbox.h
+++ b/include/listbox.h
@@ -8,7 +8,7 @@
 	HANDLE		hMem;
 	HANDLE		hData;
 	char		*itemText;
-	void		*lpNext;
+	struct tagLISTSTRUCT *lpNext;
 } LISTSTRUCT;
 typedef LISTSTRUCT FAR* LPLISTSTRUCT;
 
@@ -21,15 +21,17 @@
 	short	ItemsPerColumn;
 	short	ItemFocused;
 	short	PrevFocused;
-	short	SelCount;
 	short 	StdItemHeight;
 	short	ColumnsWidth;
 	short	DrawCtlType;
-	void	*lpFirst; 
+	void	*lpFirst;
 	DWORD	dwStyle;
 	HWND	hWndLogicParent;
 	HFONT	hFont;
 	BOOL	bRedrawFlag;
+	WORD    iNumStops;
+	LPINT   TabStops;
+	HANDLE  hDrawItemStruct;
 /*	MDESC	*Heap; */
 } HEADLIST;
 typedef HEADLIST FAR* LPHEADLIST;
diff --git a/include/local.h b/include/local.h
index eb813e9..a676a13 100644
--- a/include/local.h
+++ b/include/local.h
@@ -4,8 +4,8 @@
  * Copyright 1995 Alexandre Julliard
  */
 
-#ifndef __WINE_HEAP_H
-#define __WINE_HEAP_H
+#ifndef __WINE_LOCAL_H
+#define __WINE_LOCAL_H
 
 #include "wintypes.h"
 
@@ -21,4 +21,4 @@
 extern WORD LOCAL_Flags( WORD ds, HLOCAL handle );
 extern WORD LOCAL_HeapSize( WORD ds );
 
-#endif  /* __WINE_HEAP_H */
+#endif  /* __WINE_LOCAL_H */
diff --git a/include/msdos.h b/include/msdos.h
index 35b8d92..7b2bda7 100644
--- a/include/msdos.h
+++ b/include/msdos.h
@@ -30,7 +30,7 @@
 	BYTE dummy2[9];
 };
 
-#define DOSVERSION 0x0500;      /* Might as well pretend we're DOS 5.0 */
+#define DOSVERSION 0x0005;      /* Major version in low byte: DOS 5.00 */
 #define MAX_DOS_DRIVES	26
 
 extern WORD ExtendedError;
diff --git a/include/neexe.h b/include/neexe.h
index ad26cbe..51e860d 100644
--- a/include/neexe.h
+++ b/include/neexe.h
@@ -12,18 +12,19 @@
  */
 struct mz_header_s
 {
-    u_char dont_care1[0x18];	/* MZ Header stuff			*/
-    u_char must_be_0x40;	/* 0x40 for non-MZ program		*/
-    u_char dont_care2[0x23];	/* More MZ header stuff			*/
-    u_short ne_offset;		/* Offset to extended header		*/
+    u_short mz_magic;         /* MZ Header signature */
+    u_char  dont_care[0x3a];  /* MZ Header stuff */
+    u_short ne_offset;        /* Offset to extended header */
 };
 
+#define MZ_SIGNATURE  ('M' | ('Z' << 8))
+
 /*
  * This is the Windows executable (NE) header.
  */
 struct ne_header_s
 {
-    char    header_type[2];	/* Must contain 'N' 'E'			*/
+    u_short ne_magic;           /* NE signature 'NE' */
     u_char  linker_version;	/* Linker version number		*/
     u_char  linker_revision;	/* Linker revision number		*/
     u_short entry_tab_offset;	/* Offset to entry table relative to NE */
@@ -57,6 +58,9 @@
     u_short expect_version;	/* Expected Windows version number	*/
 };
 
+#define NE_SIGNATURE  ('N' | ('E' << 8))
+#define PE_SIGNATURE  ('P' | ('E' << 8))
+
 /*
  * NE Header FORMAT FLAGS
  */
diff --git a/include/registers.h b/include/registers.h
index ce06a0f..0298c23 100644
--- a/include/registers.h
+++ b/include/registers.h
@@ -5,6 +5,8 @@
 
 #ifndef PROCEMU
 
+#include "wine.h"
+
 #define EAX context->sc_eax
 #define EBX context->sc_ebx
 #define ECX context->sc_ecx
diff --git a/include/selectors.h b/include/selectors.h
index 55715b9..13cb836 100644
--- a/include/selectors.h
+++ b/include/selectors.h
@@ -20,12 +20,14 @@
 
 extern WORD *CreateSelectors( struct w_files * wpnt );
 
-extern unsigned int GetEntryDLLName(char *dll_name, char *function, WORD *sel,
-					int *addr);
-extern unsigned int GetEntryDLLOrdinal(char *dll_name, int ordinal, WORD *sel,
-					int *addr);
-extern unsigned int GetEntryPointFromOrdinal(struct w_files * wpnt, 
-					int ordinal);
+extern unsigned int GetEntryDLLName(char *dll_name, char *function,
+                                    WORD *sel, WORD *offset);
+extern unsigned int GetEntryDLLOrdinal(char *dll_name, int ordinal,
+                                       WORD *sel, WORD *offset);
+extern unsigned int GetEntryPointFromOrdinal(struct w_files * wpnt,
+                                             int ordinal);
 extern void InitSelectors(void);
 
+extern WNDPROC GetWndProcEntry16( char *name );
+
 #endif /* __WINE_SELECTORS_H */
diff --git a/include/stackframe.h b/include/stackframe.h
index d029ec1..3a1bf2d 100644
--- a/include/stackframe.h
+++ b/include/stackframe.h
@@ -10,19 +10,29 @@
 #include <windows.h>
 #include "ldt.h"
 
+#ifndef WINELIB
+#pragma pack(1)
+#endif
+
 typedef struct
 {
-    WORD    saved_ss;
+    WORD    saved_ss;                /* saved previous 16-bit stack */
     WORD    saved_bp;
     WORD    saved_sp;
-    WORD    ds;
-    WORD    bp;
-    WORD    arg_length;
-    WORD    ip;
+    WORD    ds;                      /* 16-bit ds */
+    DWORD   entry_point WINE_PACKED; /* entry point to call */
+    WORD    ordinal_number;          /* ordinal number of entry point */
+    WORD    dll_id;                  /* DLL id of entry point */
+    WORD    bp;                      /* 16-bit bp */
+    WORD    ip;                      /* return address */
     WORD    cs;
-    WORD    args[1];
+    WORD    args[1];                 /* arguments to API function */
 } STACK16FRAME;
 
+#ifndef WINELIB
+#pragma pack(4)
+#endif
+
 extern WORD IF1632_Saved16_ss;
 extern WORD IF1632_Saved16_sp;
 extern WORD IF1632_Saved16_bp;
diff --git a/include/stddebug.h b/include/stddebug.h
index 4abb78e..2b4114e 100644
--- a/include/stddebug.h
+++ b/include/stddebug.h
@@ -139,7 +139,6 @@
 #undef DEBUG_SCROLL
 #undef DEBUG_SELECTOR
 #undef DEBUG_SELECTORS
-#undef DEBUG_STACK
 #undef DEBUG_STRESS
 #undef DEBUG_SYSCOLOR
 #undef DEBUG_TASK
@@ -215,7 +214,6 @@
 #define DEBUG_SCROLL
 #define DEBUG_SELECTOR
 #define DEBUG_SELECTORS
-#define DEBUG_STACK
 #define DEBUG_STRESS
 #define DEBUG_SYSCOLOR
 #define DEBUG_TASK
diff --git a/include/toolhelp.h b/include/toolhelp.h
index 85ab7b3..ba1a05a 100644
--- a/include/toolhelp.h
+++ b/include/toolhelp.h
@@ -10,8 +10,76 @@
 
 /* Global heap */
 
-WORD GlobalHandleToSel( HANDLE handle );
+typedef struct
+{
+    DWORD dwSize;
+    WORD  wcItems;
+    WORD  wcItemsFree;
+    WORD  wcItemsLRU;
+} GLOBALINFO;
 
+typedef struct
+{
+    DWORD   dwSize;
+    DWORD   dwAddress;
+    DWORD   dwBlockSize;
+    HGLOBAL hBlock;
+    WORD    wcLock;
+    WORD    wcPageLock;
+    WORD    wFlags;
+    BOOL    wHeapPresent;
+    HGLOBAL hOwner;
+    WORD    wType;
+    WORD    wData;
+    DWORD   dwNext;
+    DWORD   dwNextAlt;
+} GLOBALENTRY;
+
+  /* GlobalFirst()/GlobalNext() flags */
+#define GLOBAL_ALL      0
+#define GLOBAL_LRU      1
+#define GLOBAL_FREE     2
+
+  /* wType values */
+#define GT_UNKNOWN      0
+#define GT_DGROUP       1
+#define GT_DATA         2
+#define GT_CODE         3
+#define GT_TASK         4
+#define GT_RESOURCE     5
+#define GT_MODULE       6
+#define GT_FREE         7
+#define GT_INTERNAL     8
+#define GT_SENTINEL     9
+#define GT_BURGERMASTER 10
+
+/* wData values */
+#define GD_USERDEFINED      0
+#define GD_CURSORCOMPONENT  1
+#define GD_BITMAP           2
+#define GD_ICONCOMPONENT    3
+#define GD_MENU             4
+#define GD_DIALOG           5
+#define GD_STRING           6
+#define GD_FONTDIR          7
+#define GD_FONT             8
+#define GD_ACCELERATORS     9
+#define GD_RCDATA           10
+#define GD_ERRTABLE         11
+#define GD_CURSOR           12
+#define GD_ICON             14
+#define GD_NAMETABLE        15
+#define GD_MAX_RESOURCE     15
+
+/* wFlags values */
+#define GF_PDB_OWNER        0x0100      /* Low byte is KERNEL flags */
+
+BOOL GlobalInfo( GLOBALINFO *pInfo );
+BOOL GlobalFirst( GLOBALENTRY *pGlobal, WORD wFlags );
+BOOL GlobalNext( GLOBALENTRY *pGlobal, WORD wFlags) ;
+BOOL GlobalEntryHandle( GLOBALENTRY *pGlobal, HGLOBAL hItem );
+BOOL GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE hModule, WORD wSeg );
+WORD GlobalHandleToSel( HGLOBAL handle );
 
 /* Local heap */
 
diff --git a/include/windows.h b/include/windows.h
index 5ff1c25..2e639f9 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -680,6 +680,17 @@
 #define ETO_OPAQUE          0x02
 #define ETO_CLIPPED         0x04
 
+  /* Rasterizer status */
+typedef struct
+{
+    WORD nSize;
+    WORD wFlags;
+    WORD nLanguageID;
+} RASTERIZER_STATUS, *LPRASTERIZER_STATUS;
+
+#define TT_AVAILABLE        0x0001
+#define TT_ENABLED          0x0002
+
 typedef struct tagPALETTEENTRY
 {
 	BYTE peRed, peGreen, peBlue, peFlags;
@@ -2469,8 +2480,8 @@
 Fa(SEGPTR,AnsiNext,SEGPTR,a)
 Fa(LPSTR,AnsiUpper,LPSTR,a)
 Fa(LPSTR,GlobalLock,HGLOBAL,a)
-Fa(LPSTR,GlobalWire,HGLOBAL,a)
 Fa(LPSTR,LockResource,HANDLE,a)
+Fa(SEGPTR,GlobalWire,HGLOBAL,a)
 Fa(SEGPTR,WIN16_GlobalLock,HGLOBAL,a)
 Fa(UINT,GDIRealizePalette,HDC,a)
 Fa(UINT,RealizePalette,HDC,a)
diff --git a/include/wine.h b/include/wine.h
index bd426f3..101f50e 100644
--- a/include/wine.h
+++ b/include/wine.h
@@ -1,8 +1,5 @@
 #ifndef  WINE_H
 #define  WINE_H
-#if 0
-#define __ELF__
-#endif
 
 extern char *WineIniFileName(void);
 extern char *WinIniFileName(void);
@@ -36,12 +33,8 @@
 	unsigned long cr2;
 };
 #define WINE_DATA_SELECTOR 0x2b
-#ifdef __ELF__
-#define WINE_CODE_SELECTOR 0x0f
-#else
 #define WINE_CODE_SELECTOR 0x23
-#endif
-#endif
+#endif  /* linux */
 
 #if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <signal.h>
diff --git a/loader/dump.c b/loader/dump.c
index 77a2a06..2011bbe 100644
--- a/loader/dump.c
+++ b/loader/dump.c
@@ -25,8 +25,8 @@
 PrintFileHeader(struct ne_header_s *ne_header)
 {
     printf("ne_header: %c%c\n",
-	   ne_header->header_type[0], 
-	   ne_header->header_type[1]);
+           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);
diff --git a/loader/library.c b/loader/library.c
index e610d3c..8c02181 100644
--- a/loader/library.c
+++ b/loader/library.c
@@ -381,6 +381,8 @@
 {
 	HANDLE h;
 	
+        dprintf_module(stddeb,"LoadLibrary: (%08x) %s\n",(int)libname,libname);
+
 	if ((h = LoadImage(libname, DLL, 0)) < 32)
 		return h;
 
@@ -435,8 +437,8 @@
 #ifdef WINELIB
     WINELIB_UNIMP ("GetProcAddress");
 #else
-    int		addr, ret;
-    WORD        sel;
+    int		ret;
+    WORD        sel, addr;
     register struct w_files *w = wine_files;
     int 	ordinal, len;
     char 	* cpnt;
@@ -541,9 +543,9 @@
 static void 
 FillModStructBuiltIn(MODULEENTRY *lpModule, struct dll_name_table_entry_s *dll)
 {
-	lpModule->dwSize = dll->dll_table_length * 1024;
+	lpModule->dwSize = dll->table->dll_table_length * 1024;
 	strcpy(lpModule->szModule, dll->dll_name);
-	lpModule->hModule = 0xff00 + dll->dll_number;
+	lpModule->hModule = 0xff00 + dll->table->dll_number;
 	lpModule->wcUsage = GetModuleUsage(lpModule->hModule);
 	GetModuleFileName(lpModule->hModule, lpModule->szExePath, MAX_PATH + 1);
 	lpModule->wNext = 0;
diff --git a/loader/ne_image.c b/loader/ne_image.c
index 0c18f4d..d0bd137 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -18,6 +18,7 @@
 #include "library.h"
 #include "if1632.h"
 #include "selectors.h"
+#include "callback.h"
 #include "ne_image.h"
 #include "prototypes.h"
 #include "stddebug.h"
@@ -146,7 +147,7 @@
 	    ordinal = rep->target2;
 
   	    status = GetEntryDLLOrdinal(dll_name, ordinal, &selector,
-					&address);
+					&offset);
 	    if (status)
 	    {
 		char s[80];
@@ -157,7 +158,7 @@
 	    }
 
 	    dprintf_fixup(stddeb,"%d: %s.%d: %04x:%04x\n", i + 1, 
-		   dll_name, ordinal, selector, address);
+		   dll_name, ordinal, selector, offset);
 	    break;
 	    
 	  case NE_RELTYPE_NAME:
@@ -172,7 +173,7 @@
 	    }
 
   	    status = GetEntryDLLName(dll_name, func_name, &selector, 
-					   &address);
+					   &offset);
 	    if (status)
 	    {
 		char s[80];
@@ -181,8 +182,8 @@
 		myerror(s);
 		return -1;
 	    }
-/*	    dprintf_fixup(stddeb,"%d: %s %s.%d: %04x:%04x\n", i + 1, 
-                   func_name, dll_name, ordinal, selector, address);*/
+            dprintf_fixup(stddeb,"%d: %s %s.%d: %04x:%04x\n", i + 1, 
+                          func_name, dll_name, ordinal, selector, offset);
 	    break;
 	    
 	  case NE_RELTYPE_INTERNAL:
@@ -190,16 +191,16 @@
 	    {
 		address  = GetEntryPointFromOrdinal(wpnt, rep->target2);
 		selector = (address >> 16) & 0xffff;
-		address &= 0xffff;
+		offset   = address & 0xffff;
 	    }
 	    else
 	    {
 		selector = selector_table[rep->target1-1];
-		address  = rep->target2;
+		offset   = rep->target2;
 	    }
 	    
 	    dprintf_fixup(stddeb,"%d: %04x:%04x\n", 
-			  i + 1, selector, address);
+			  i + 1, selector, offset);
 	    break;
 
 	  case NE_RELTYPE_OSFIXUP:
@@ -240,7 +241,8 @@
                           i+1, rep->address_type, rep->relocation_type,
                           rep->offset, rep->target1, rep->target2);
 
-	offset = rep->offset;
+        address = (unsigned int)offset;
+	offset  = rep->offset;
 
 	switch (rep->address_type)
 	{
@@ -290,8 +292,9 @@
                               sel, offset, *sp, additive ? " additive" : "" );
 		offset = *sp;
 		*sp    = (unsigned short) selector;
-		if(additive)
-                    fprintf(stderr,"Additive selector, please report\n");
+		/* Borland creates additive records with offset zero. Strange, but OK */
+		if(additive && offset)
+        	fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
 	    } 
 	    while (offset != 0xffff && !additive);
 	    break;
@@ -321,20 +324,39 @@
 
 int NE_StartProgram(struct w_files *wpnt)
 {
-    int cs_reg, ds_reg, ss_reg, ip_reg, sp_reg;
+    extern WORD PSPSelector;
+
+    int cs_reg, ds_reg, ip_reg;
+
+    /* Registers at initialization must be:
+     * ax   zero
+     * bx   stack size in bytes
+     * cx   heap size in bytes
+     * si   previous app instance
+     * di   current app instance
+     * bp   zero
+     * es   selector to the PSP
+     * ds   dgroup of the application
+     * ss   stack selector
+     * sp   top of the stack
+     */
+
     /*
      * Fixup stack and jump to start. 
      */
     WIN_StackSize = wpnt->ne->ne_header->stack_length;
     WIN_HeapSize = wpnt->ne->ne_header->local_heap_length;
 
-    ds_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->auto_data_seg-1];
     cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1];
     ip_reg = wpnt->ne->ne_header->ip;
-    ss_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->ss-1];
-    sp_reg = wpnt->ne->ne_header->sp;
+    ds_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->auto_data_seg-1];
 
-    return CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
+    IF1632_Saved16_ss = wpnt->ne->selector_table[wpnt->ne->ne_header->ss-1];
+    IF1632_Saved16_sp = wpnt->ne->ne_header->sp;
+    IF1632_Saved16_bp = 0;
+    return CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
+                           PSPSelector /*es*/, 0 /*ax*/, WIN_StackSize /*bx*/,
+                           WIN_HeapSize, 0 /*dx*/, 0 /*si*/, ds_reg /*di*/ );
 }
 
 void NE_InitDLL(struct w_files *wpnt)
@@ -363,7 +385,9 @@
 		    cx_reg = wpnt->ne->ne_header->local_heap_length;
   	    }
   
-  	    cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1];
+            dprintf_dll(stddeb,"InitDLL: ne_header->cs = %04x\n",wpnt->ne->ne_header->cs);
+            if (!wpnt->ne->ne_header->cs) cs_reg = 0;
+            else cs_reg = wpnt->ne->selector_table[wpnt->ne->ne_header->cs-1];
   	    ip_reg = wpnt->ne->ne_header->ip;
   
             di_reg = wpnt->hinstance;
@@ -372,7 +396,9 @@
 		dprintf_dll(stddeb,"Initializing %s, cs:ip %04x:%04x, ds %04x, cx %04x\n", 
 		    wpnt->name, cs_reg, ip_reg, ds_reg, cx_reg);
 	    	    
-		rv = CallTo16cx(cs_reg << 16 | ip_reg, ds_reg | (cx_reg<<16));
+                rv = CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
+                                     0 /*es*/, 0 /*ax*/, 0 /*bx*/, cx_reg,
+                                     0 /*dx*/, 0 /*si*/, di_reg );
 		dprintf_exec(stddeb,"rv = %x\n", rv);
 	    } else
 		dprintf_exec(stddeb,"%s skipped\n", wpnt->name);
diff --git a/loader/resource.c b/loader/resource.c
index 0446393..0d1249b 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -623,8 +623,7 @@
 int
 LoadString(HANDLE instance, WORD resource_id, LPSTR buffer, int buflen)
 {
-    HANDLE hmem;
-    int rsc_size;
+    HANDLE hmem, hrsrc;
     unsigned char *p;
     int string_num;
     int i;
@@ -632,10 +631,11 @@
     dprintf_resource(stddeb, "LoadString: instance = %04x, id = %d, buffer = %08x, "
 	   "length = %d\n", instance, resource_id, (int) buffer, buflen);
 
-    hmem = RSC_LoadResource(instance, (SEGPTR)((resource_id >> 4) + 1),
-			    (SEGPTR) NE_RSCTYPE_STRING, &rsc_size );
-    if (hmem == 0)
-	return 0;
+    hrsrc = FindResource( instance, (SEGPTR)((resource_id >> 4) + 1),
+                          (SEGPTR) NE_RSCTYPE_STRING );
+    if (!hrsrc) return 0;
+    hmem = LoadResource( instance, hrsrc );
+    if (!hmem) return 0;
     
     p = GlobalLock(hmem);
     string_num = resource_id & 0x000f;
@@ -655,7 +655,7 @@
 		fprintf(stderr,"LoadString // I dont know why , but caller give buflen=%d *p=%d !\n", buflen, *p);
 		fprintf(stderr,"LoadString // and try to obtain string '%s'\n", p + 1);
 		}
-    GlobalFree(hmem);
+    FreeResource( hrsrc );
 
     dprintf_resource(stddeb,"LoadString // '%s' copied !\n", buffer);
     return i;
diff --git a/loader/selector.c b/loader/selector.c
index a8e6871..142c703 100644
--- a/loader/selector.c
+++ b/loader/selector.c
@@ -31,7 +31,7 @@
 #include "windows.h"
 #include "ldt.h"
 #include "wine.h"
-
+#include "global.h"
 #include "dlls.h"
 #include "neexe.h"
 #include "if1632.h"
@@ -51,8 +51,6 @@
 int max_selectors = 0;
 
 
-extern void KERNEL_Ordinal_1();    /* FatalExit() */
-extern void KERNEL_Ordinal_102();  /* Dos3Call() */
 extern char WindowsPath[256];
 
 extern char **Argv;
@@ -62,46 +60,6 @@
 unsigned int 
 GetEntryPointFromOrdinal(struct w_files * wpnt, int ordinal);
 
-#if 0
-
-
-/**********************************************************************
- *					InitSelectors
- */
-void
-InitSelectors(void) 
-{
-    int i;
-    max_selectors = MAX_SELECTORS;
-    SelectorMap = malloc(max_selectors * sizeof(unsigned short));
-    Segments    = malloc(max_selectors * sizeof(SEGDESC));
-    for (i = 0; i < max_selectors; i++) {
-	if (i < FIRST_SELECTOR) {
-	    SelectorMap[i] = SELECTOR_IS32BIT;
-#ifdef __ELF__
-	    /* quick hack, just reserves 4 meg for wine. */
-	} else if ((i << (16 + __AHSHIFT)) >= 0x8000000 &&
-		   (i << (16 + __AHSHIFT)) <= 0x8400000) {
-	    SelectorMap[i]= SELECTOR_IS32BIT;
-#endif
-	} else {
-	    SelectorMap[i]=0;
-	}
-    }
-#ifdef __ELF__
-    /* create an ldt. */
-    if (set_ldt_entry(1, 0x8000000, 65535, 1,0x1a ,1,0)) {
-	perror ("set_ldt_entry");
-	exit (1);
-    }
-#endif
-    }
-
-
-#endif /* 0 */
-
-
-
 
 /**********************************************************************
  *  Check whether pseudo-functions like __0040H for direct memory
@@ -110,8 +68,8 @@
  *         (e.g. reading from the Bios data segment (esp. clock!) )
  */
 
-unsigned int GetMemoryReference(char *dll_name, char *function, WORD *sel,
-				 int *addr)
+unsigned int GetMemoryReference( char *dll_name, char *function,
+                                 WORD *sel, WORD *offset )
 {
   static HANDLE memory_handles[ 10 ] = { 0,0,0,0,0,0,0,0,0,0 };
   static char *memory_names[ 10 ] = { "segment 0xA000",
@@ -143,13 +101,11 @@
     else if( !strcasecmp( function, "__C000H" ) ) nr = 8;
     else if( !strcasecmp( function, "__0040H" ) ) nr = 9;
     else if( !strcasecmp( function, "__AHIncr" ) ) {
-      *sel = __AHINCR;   
-      *addr = MAKELONG(__AHINCR,__AHINCR);
+      *sel = *offset = __AHINCR;   
       return 1;      
     }
     else if( !strcasecmp( function, "__AHShift" ) ) {
-      *sel = __AHSHIFT;
-      *addr = MAKELONG(__AHSHIFT,__AHSHIFT);
+      *sel = *offset = __AHSHIFT;
       return 1;
     }
      else
@@ -168,12 +124,10 @@
     case 195: nr = 8; break;
     case 193: nr = 9; break;
     case 114:
-      *sel = __AHINCR;  
-      *addr = MAKELONG(__AHINCR,__AHINCR);
+      *sel = *offset = __AHINCR;  
       return 1;
     case 113:
-      *sel = __AHSHIFT;
-      *addr = MAKELONG(__AHSHIFT,__AHSHIFT);
+      *sel = *offset = __AHSHIFT;
       return 1;
     default: return 0;
     }
@@ -183,8 +137,7 @@
     fprintf( stderr, "Warning: Direct access to %s!\n", memory_names[ nr ] );
     memory_handles[ nr ] = GlobalAlloc( GMEM_FIXED, 65535 );
   }
-  *sel = memory_handles[ nr ];
-  *addr = MAKELONG(*sel,*sel);
+  *sel = *offset = memory_handles[ nr ];
   return 1;
 }
  
@@ -200,32 +153,31 @@
     char  * cpnt;
 };
 
-unsigned int GetEntryDLLName(char * dll_name, char * function, WORD* sel, 
-				int  * addr)
+unsigned int GetEntryDLLName( char * dll_name, char * function,
+                              WORD* sel, WORD *offset )
 {
-	struct dll_table_entry_s *dll_table;
+	struct dll_table_s *dll_table;
 	struct w_files * wpnt;
 	char * cpnt;
 	int ordinal, j, len;
 
-	if( GetMemoryReference( dll_name, function, sel, addr ) )
+	if( GetMemoryReference( dll_name, function, sel, offset ) )
 	  return 0;
 
 	dll_table = FindDLLTable(dll_name);
 
 	if(dll_table) {
-		ordinal = FindOrdinalFromName(dll_table, function);
+		ordinal = FindOrdinalFromName(dll_table->dll_table,function);
 		if(!ordinal){
 			dprintf_module(stddeb,"GetEntryDLLName: %s.%s not found\n",
 				dll_name, function);
-			*sel=0;
-			*addr=0;
+			*sel = *offset = 0;
 			return -1;
 		}
-		*sel = dll_table[ordinal].selector;
-		*addr  = (unsigned int) dll_table[ordinal].address;
+		*sel    = dll_table->dll_table[ordinal].selector;
+		*offset = dll_table->dll_table[ordinal].offset;
 #ifdef WINESTAT
-		dll_table[ordinal].used++;
+		dll_table->dll_table[ordinal].used++;
 #endif
 		return 0;
 	};
@@ -244,31 +196,30 @@
 		};
 		ordinal =  *((unsigned short *)  (cpnt +  len));
 		j = GetEntryPointFromOrdinal(wpnt, ordinal);		
-		*addr  = j & 0xffff;
-		j = j >> 16;
-		*sel = j;
+		*offset = LOWORD(j);
+		*sel    = HIWORD(j);
 		return 0;
 	};
 	return 1;
 }
 
-unsigned int GetEntryDLLOrdinal(char * dll_name, int ordinal, WORD *sel, 
-				int  * addr)
+unsigned int GetEntryDLLOrdinal( char * dll_name, int ordinal,
+                                 WORD *sel, WORD *offset )
 {
-	struct dll_table_entry_s *dll_table;
+	struct dll_table_s *dll_table;
 	struct w_files * wpnt;
 	int j;
 
-	if( GetMemoryReference( dll_name, (char*)ordinal, sel, addr ) )
+	if( GetMemoryReference( dll_name, (char*)ordinal, sel, offset ) )
 	  return 0;
 
 	dll_table = FindDLLTable(dll_name);
 
 	if(dll_table) {
-	    *sel = dll_table[ordinal].selector;
-	    *addr  = (unsigned int) dll_table[ordinal].address;
+	    *sel    = dll_table->dll_table[ordinal].selector;
+	    *offset = dll_table->dll_table[ordinal].offset;
 #ifdef WINESTAT
-		dll_table[ordinal].used++;
+            dll_table->dll_table[ordinal].used++;
 #endif
 	    return 0;
 	};
@@ -277,9 +228,8 @@
 	for(wpnt = wine_files; wpnt; wpnt = wpnt->next){
 		if(strcasecmp(wpnt->name, dll_name)) continue;
 		j = GetEntryPointFromOrdinal(wpnt, ordinal);
-		*addr  = j & 0xffff;
-		j = j >> 16;
-		*sel = j;
+		*offset = LOWORD(j);
+		*sel    = HIWORD(j);
 		return 0;
 	};
 	return 1;
@@ -345,6 +295,15 @@
 }
 
 
+WNDPROC GetWndProcEntry16( char *name )
+{
+    WORD sel, offset;
+
+    GetEntryDLLName( "WINPROCS", name, &sel, &offset );
+    return (WNDPROC) MAKELONG( offset, sel );
+}
+
+
 /***********************************************************************
  *           GetDOSEnvironment   (KERNEL.131)
  */
@@ -413,9 +372,9 @@
 {
     HANDLE handle;
     struct dos_psp_s *psp;
-    unsigned short *usp;
     char *p1, *p2;
     int i;
+    WORD sel, offset;
 
     handle = GlobalAlloc( GMEM_MOVEABLE, sizeof(*psp) );
     if (!handle) return 0;
@@ -426,15 +385,16 @@
      */
     psp->pspInt20 = 0x20cd;
     psp->pspDispatcher[0] = 0x9a;
-    usp = (unsigned short *) &psp->pspDispatcher[1];
-    *usp       = (unsigned short) KERNEL_Ordinal_102;
-    *(usp + 1) = WINE_CODE_SELECTOR;
-    psp->pspTerminateVector[0] = (unsigned short) KERNEL_Ordinal_1;
-    psp->pspTerminateVector[1] = WINE_CODE_SELECTOR;
-    psp->pspControlCVector[0] = (unsigned short) KERNEL_Ordinal_1;
-    psp->pspControlCVector[1] = WINE_CODE_SELECTOR;
-    psp->pspCritErrorVector[0] = (unsigned short) KERNEL_Ordinal_1;
-    psp->pspCritErrorVector[1] = WINE_CODE_SELECTOR;
+    GetEntryDLLName( "KERNEL", "DOS3Call", &sel, &offset );
+    *(unsigned short *)&psp->pspDispatcher[1] = offset;
+    *(unsigned short *)&psp->pspDispatcher[3] = sel;
+    GetEntryDLLName( "KERNEL", "FatalAppExit", &sel, &offset );
+    psp->pspTerminateVector[0] = offset;
+    psp->pspTerminateVector[1] = sel;
+    psp->pspControlCVector[0]  = offset;
+    psp->pspControlCVector[1]  = sel;
+    psp->pspCritErrorVector[0] = offset;
+    psp->pspCritErrorVector[1] = sel;
     psp->pspEnvironment = SELECTOROF( GetDOSEnvironment() );
 
     p1 = psp->pspCommandTail;
@@ -473,7 +433,7 @@
     int i, length;
     void *base_addr;
     WORD *selectors;
-    ldt_entry entry;
+    HGLOBAL handle;
 
     auto_data_sel=0;
     /*
@@ -523,36 +483,21 @@
             dprintf_selectors(stddeb,"Auto data image length %x\n",file_image_length);
  	}
 
-        if (!(selectors[i] = AllocSelector( 0 )))
-        {
-            fprintf( stderr, "CreateSelectors: out of free LDT entries\n" );
-            exit( 1 );
-        }
-        if (!(base_addr = (void *) malloc( length )))
-        {
-            fprintf( stderr, "CreateSelectors: malloc() failed\n" );
-            exit( 1 );
-        }
-        entry.base           = (unsigned long) base_addr;
-        entry.limit          = length - 1;
-        entry.seg_32bit      = 0;
-        entry.limit_in_pages = 0;
-
 	/*
 	 * Is this a DATA or CODE segment?
 	 */
         if (seg_table[i].seg_flags & NE_SEGFLAGS_DATA)
         {
-            entry.type = SEGMENT_DATA;
-            entry.read_only = seg_table[i].seg_flags & NE_SEGFLAGS_READONLY;
-            memset( base_addr, 0, length );
+            handle = GLOBAL_Alloc( GMEM_ZEROINIT, length, 0, FALSE,
+                               seg_table[i].seg_flags & NE_SEGFLAGS_READONLY );
         }
         else
         {
-            entry.type = SEGMENT_CODE;
-            entry.read_only = seg_table[i].seg_flags & NE_SEGFLAGS_EXECUTEONLY;
+            handle = GLOBAL_Alloc( 0, length, 0, TRUE,
+                            seg_table[i].seg_flags & NE_SEGFLAGS_EXECUTEONLY );
         }
-        LDT_SetEntry( SELECTOR_TO_ENTRY(selectors[i]), &entry );
+        base_addr = GlobalLock( handle );
+        selectors[i] = GlobalHandleToSel( handle );
 
 	if (seg_table[i].seg_data_offset != 0)
 	{
@@ -578,14 +523,13 @@
 	    saved_old_length = old_length;
 	}
     }
-
     if(!auto_data_sel)dprintf_selectors(stddeb,"Warning: No auto_data_sel\n");
     for (i = 0; i < ne_header->n_segment_tab; i++)
     {
 /*	Segments[s->selector >> __AHSHIFT].owner = auto_data_sel; */
 	if (selectors[i] == auto_data_sel)
             LocalInit( auto_data_sel, saved_old_length,
-			   0x10000 - 2 - saved_old_length 
+			   0x10000 - 2
 			   - ne_header->stack_length );
 #if 0
 	    HEAP_LocalInit(auto_data_sel,
@@ -610,7 +554,6 @@
 void
 FixupFunctionPrologs(struct w_files * wpnt)
 {
-    struct ne_header_s *ne_header = wpnt->ne->ne_header;   
     union lookup entry_tab_pointer;
     struct entry_tab_header_s *eth;
     struct entry_tab_movable_s *etm;
@@ -618,9 +561,9 @@
     unsigned char *fixup_ptr;
     int i;
 
-    if (!(ne_header->format_flags & 0x0001))
+/*    if (!(ne_header->format_flags & NE_FFLAGS_SINGLEDATA))
 	return;
-
+*/
     entry_tab_pointer.cpnt = wpnt->ne->lookup_table;
     /*
      * Let's walk through the table and fixup prologs as we go.
@@ -645,26 +588,42 @@
 	    if (eth->seg_number >= 0xfe)
 	    {
 		etm = entry_tab_pointer.etm++;
+	      /* FIXME: Does anyone know the exact meaning of these flags? */
+	      /* 0x0001 seems to mean: Fix up the function prolog          */
+	        dprintf_selector(stddeb,"ETM_Flags: %04x ",etm->flags);
+	        if (!(etm->flags & 0x0001)) continue;
 		fixup_ptr = (char *)GET_SEL_BASE(wpnt->ne->selector_table[etm->seg_number-1]) + etm->offset;
 	    }
 	    else
 	    {
 		etf = entry_tab_pointer.etf++;
+	        dprintf_selector(stddeb,"ETF_Flags: %04x ",etf->flags);
+	        if (!(etf->flags & 0x0001)) continue;
 		fixup_ptr = (char *)GET_SEL_BASE(wpnt->ne->selector_table[eth->seg_number-1])
 			     + (int) etf->offset[0] 
 			     + ((int) etf->offset[1] << 8);
 
 	    }
+	    dprintf_selector(stddeb,"Signature: %02x %02x %02x,ff %x\n",
+			     fixup_ptr[0],fixup_ptr[1],fixup_ptr[2],
+			     wpnt->ne->ne_header->format_flags);
 
 	    /* Verify the signature */
 	    if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
 		 || (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
 		&& fixup_ptr[2] == 0x90)
 	    {
+	      if (wpnt->ne->ne_header->format_flags & NE_FFLAGS_SINGLEDATA) {
+		
 		fixup_ptr[0] = 0xb8;	/* MOV AX, */
 		fixup_ptr[1] = wpnt->hinstance;
 		fixup_ptr[2] = (wpnt->hinstance >> 8);
-	    }
+	      } else  {
+		fixup_ptr[0] = 0x90; /* non-library: NOPs */	
+		fixup_ptr[1] = 0x90;
+		fixup_ptr[2] = 0x90;
+	      }
+	    } 
 	}
     }
 }
diff --git a/loader/signal.c b/loader/signal.c
index 5b34839..c6943de 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -287,38 +287,4 @@
 #endif
 }
 
-static sigjmp_buf segv_jmpbuf;
-
-static void
-segv_handler()
-{
-    siglongjmp(segv_jmpbuf, 1);
-}
-
-int
-test_memory( char *p, int write )
-{
-    int ret = FALSE;
-    struct sigaction new_act;
-    struct sigaction old_act;
-
-    memset(&new_act, 0, sizeof new_act);
-    new_act.sa_handler = segv_handler;
-    if (sigsetjmp( segv_jmpbuf, 1 ) == 0) {
-	char c = 100;
-	if (sigaction(SIGSEGV, &new_act, &old_act) < 0)
-	    perror("sigaction");
-	c = *p;
-	if (write)
-	    *p = c;
-	ret = TRUE;
-    }
-#ifdef linux
-    wine_sigaction(SIGSEGV, &old_act, NULL);
-#else
-    sigaction(SIGSEGV, &old_act, NULL);
-#endif
-    return ret;
-}
-
 #endif /* ifndef WINELIB */
diff --git a/loader/task.c b/loader/task.c
index de42cc3..93c14a5 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -9,7 +9,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include "windows.h"
-#include "if1632.h"
+#include "callback.h"
 #include "task.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -102,11 +102,7 @@
 	while ((hWnd = *(wptr++)) != 0) {
 		if (++count >= MAXWIN_PER_TASK) return FALSE;
 		dprintf_task(stddeb,"EnumTaskWindows // hWnd=%04X count=%d !\n", hWnd, count);
-#ifdef WINELIB
-		bRet = (*lpEnumFunc)(hWnd, lParam); 
-#else
-		bRet = CallBack16(lpEnumFunc, 2, 0, (int)hWnd, 2, (int)lParam);
-#endif
+                bRet = CallEnumTaskWndProc( lpEnumFunc, hWnd, lParam );
 		if (bRet == 0) break;
 		}
 	return TRUE;
diff --git a/memory/global.c b/memory/global.c
index f62f2fd..2067ad0 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -13,20 +13,62 @@
 #include "stddebug.h"
 #include "debug.h"
 
+  /* Global arena block */
+typedef struct
+{
+    DWORD    base;           /* Base address  */
+    DWORD    size;           /* Size in bytes */
+    HGLOBAL  handle;         /* Handle for this block */
+    HGLOBAL  hOwner;         /* Owner of this block */
+    BYTE     lockCount;      /* Count of GlobalFix() calls */
+    BYTE     pageLockCount;  /* Count of GlobalPageLock() calls */
+    BYTE     flags;          /* Allocation flags */
+    BYTE     selCount;       /* Number of selectors allocated for this block */
+} GLOBALARENA;
+
+  /* Flags definitions */
+#define GA_DGROUP       0x04
+#define GA_DISCARDABLE  0x08
+
+  /* Arena array */
+static GLOBALARENA *pGlobalArena = NULL;
+static int globalArenaSize = 0;
+
 #define GLOBAL_MAX_ALLOC_SIZE 0x00ff0000  /* Largest allocation is 16M - 64K */
 
-#define HGLOBAL_TO_SEL(handle) \
-     ((handle == (HGLOBAL)-1) ? CURRENT_DS : GlobalHandleToSel(handle))
+#define GET_ARENA_PTR(handle)  (pGlobalArena + ((handle) >> __AHSHIFT))
 
 /***********************************************************************
- *           GlobalAlloc   (KERNEL.15)
+ *           GLOBAL_GetArena
+ *
+ * Return the arena for a given selector, growing the arena array if needed.
  */
-HGLOBAL GlobalAlloc( WORD flags, DWORD size )
+static GLOBALARENA *GLOBAL_GetArena( WORD sel, WORD selcount )
 {
-    WORD sel;
-    void *ptr;
+    if (((sel >> __AHSHIFT) + selcount) >= globalArenaSize)
+    {
+        GLOBALARENA *pNewArena = realloc( pGlobalArena,
+                               (globalArenaSize + 256) * sizeof(GLOBALARENA) );
+        if (!pNewArena) return 0;
+        pGlobalArena = pNewArena;
+        memset( pGlobalArena + globalArenaSize, 0, 256 * sizeof(GLOBALARENA) );
+        globalArenaSize += 256;
+    }
+    return pGlobalArena + (sel >> __AHSHIFT);
+}
 
-    dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
+
+/***********************************************************************
+ *           GLOBAL_Alloc
+ *
+ * Implementation of GlobalAlloc()
+ */
+HGLOBAL GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL hOwner,
+                      BOOL isCode, BOOL isReadOnly )
+{
+    WORD sel, selcount;
+    void *ptr;
+    GLOBALARENA *pArena;
 
       /* Fixup the size */
 
@@ -41,20 +83,50 @@
 
       /* Allocate the selector(s) */
 
-    sel = SELECTOR_AllocBlock( ptr, size, SEGMENT_DATA, 0, 0 );
+    sel = SELECTOR_AllocBlock( ptr, size, isCode ? SEGMENT_CODE : SEGMENT_DATA,
+                               0, isReadOnly );
     if (!sel)
     {
         free( ptr );
         return 0;
     }
+    selcount = (size + 0xffff) / 0x10000;
+
+    if (!(pArena = GLOBAL_GetArena( sel, selcount )))
+    {
+        free( ptr );
+        FreeSelector( sel );
+        return 0;
+    }
+
+      /* Fill the arena block */
+
+    pArena->base = (DWORD)ptr;
+    pArena->size = GET_SEL_LIMIT(sel) + 1;
+    pArena->handle = (flags & GMEM_MOVEABLE) ? sel - 1 : sel;
+    pArena->hOwner = hOwner;
+    pArena->lockCount = 0;
+    pArena->pageLockCount = 0;
+    pArena->flags = flags & 0xff;
+    if (flags & GMEM_DISCARDABLE) pArena->flags |= GA_DISCARDABLE;
+    if (!isCode) pArena->flags |= GA_DGROUP;
+    pArena->selCount = selcount;
+    if (selcount > 1)  /* clear the next arena blocks */
+        memset( pArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
 
     if (flags & GMEM_ZEROINIT) memset( ptr, 0, size );
+    return pArena->handle;
+}
 
-      /* Return the handle */
-      /* If allocating a GMEM_FIXED block, the handle is the selector. */
-      /* Otherwise, the handle is the selector-1 (don't ask me why :-) */
-    if (flags & GMEM_MOVEABLE) return sel - 1;
-    else return sel;
+
+/***********************************************************************
+ *           GlobalAlloc   (KERNEL.15)
+ */
+HGLOBAL GlobalAlloc( WORD flags, DWORD size )
+{
+    dprintf_global( stddeb, "GlobalAlloc: %ld flags=%04x\n", size, flags );
+
+    return GLOBAL_Alloc( flags, size, GetCurrentPDB(), 0, 0 );
 }
 
 
@@ -63,12 +135,18 @@
  */
 HGLOBAL GlobalReAlloc( HGLOBAL handle, DWORD size, WORD flags )
 {
-    WORD sel;
+    WORD sel, selcount;
     DWORD oldsize;
     void *ptr;
+    GLOBALARENA *pArena, *pNewArena;
 
     dprintf_global( stddeb, "GlobalReAlloc: %04x %ld flags=%04x\n",
                     handle, size, flags );
+    if (!handle)
+    {
+        printf( "GlobalReAlloc: handle is 0.\n" );
+        return 0;
+    }
 
       /* Fixup the size */
 
@@ -78,15 +156,17 @@
 
       /* Reallocate the linear memory */
 
+    pArena = GET_ARENA_PTR( handle );
     sel = GlobalHandleToSel( handle );
-    ptr = (void *)GET_SEL_BASE( sel );
-    oldsize = GlobalSize( handle );
+    ptr = (void *)pArena->base;
+    oldsize = pArena->size;
     if (size == oldsize) return handle;  /* Nothing to do */
 
     ptr = realloc( ptr, size );
     if (!ptr)
     {
         FreeSelector( sel );
+        memset( pArena, 0, sizeof(GLOBALARENA) );
         return 0;
     }
 
@@ -96,17 +176,39 @@
     if (!sel)
     {
         free( ptr );
+        memset( pArena, 0, sizeof(GLOBALARENA) );
+        return 0;
+    }
+    selcount = (size + 0xffff) / 0x10000;
+
+    if (!(pNewArena = GLOBAL_GetArena( sel, selcount )))
+    {
+        free( ptr );
+        FreeSelector( sel );
         return 0;
     }
 
+      /* Fill the new arena block */
+
+    if (pNewArena != pArena) memcpy( pNewArena, pArena, sizeof(GLOBALARENA) );
+    pNewArena->base = (DWORD)ptr;
+    pNewArena->size = GET_SEL_LIMIT(sel) + 1;
+    pNewArena->selCount = selcount;
+    if (flags & GMEM_MODIFY)
+    {
+          /* Change the flags, leaving GA_DGROUP alone */
+        pNewArena->flags = (pNewArena->flags & GA_DGROUP) |
+                           (flags & ~GA_DGROUP);
+        if (flags & GMEM_DISCARDABLE) pNewArena->flags |= GA_DISCARDABLE;
+    }
+    pNewArena->handle = (pNewArena->flags & GMEM_MOVEABLE) ? sel - 1 : sel;
+
+    if (selcount > 1)  /* clear the next arena blocks */
+        memset( pNewArena + 1, 0, (selcount - 1) * sizeof(GLOBALARENA) );
+
     if ((oldsize < size) && (flags & GMEM_ZEROINIT))
         memset( (char *)ptr + oldsize, 0, size - oldsize );
-
-    if (sel == GlobalHandleToSel( handle ))
-        return handle;  /* Selector didn't change */
-
-    if (flags & GMEM_MOVEABLE) return sel - 1;
-    else return sel;
+    return pNewArena->handle;
 }
 
 
@@ -119,10 +221,12 @@
     void *ptr;
 
     dprintf_global( stddeb, "GlobalFree: %04x\n", handle );
+    if (!handle) return 0;
     sel = GlobalHandleToSel( handle );
     ptr = (void *)GET_SEL_BASE(sel);
     if (FreeSelector( sel )) return handle;  /* failed */
     free( ptr );
+    memset( GET_ARENA_PTR(handle), 0, sizeof(GLOBALARENA) );
     return 0;
 }
 
@@ -136,7 +240,7 @@
 {
     dprintf_global( stddeb, "WIN16_GlobalLock: %04x\n", handle );
     if (!handle) return 0;
-    return (SEGPTR)MAKELONG( 0, HGLOBAL_TO_SEL(handle) );
+    return (SEGPTR)MAKELONG( 0, GlobalHandleToSel(handle) );
 }
 
 
@@ -149,7 +253,7 @@
 {
     dprintf_global( stddeb, "GlobalLock: %04x\n", handle );
     if (!handle) return 0;
-    return (LPSTR)GET_SEL_BASE( HGLOBAL_TO_SEL(handle) );
+    return (LPSTR)GET_ARENA_PTR(handle)->base;
 }
 
 
@@ -170,7 +274,7 @@
 {
     dprintf_global( stddeb, "GlobalSize: %04x\n", handle );
     if (!handle) return 0;
-    return GET_SEL_LIMIT( HGLOBAL_TO_SEL(handle) ) + 1;
+    return GET_ARENA_PTR(handle)->size;
 }
 
 
@@ -179,11 +283,8 @@
  */
 DWORD GlobalHandle( WORD sel )
 {
-      /* FIXME: what about GMEM_FIXED blocks? */
-    WORD handle = sel & ~1;
-    dprintf_global( stddeb, "GlobalHandle(%04x): returning %08lx\n",
-                    sel, MAKELONG( handle, sel ) );
-    return MAKELONG( handle, sel );
+    dprintf_global( stddeb, "GlobalHandle: %04x\n", sel );
+    return MAKELONG( GET_ARENA_PTR(sel)->handle, sel );
 }
 
 
@@ -192,8 +293,12 @@
  */
 WORD GlobalFlags( HGLOBAL handle )
 {
+    GLOBALARENA *pArena;
+
     dprintf_global( stddeb, "GlobalFlags: %04x\n", handle );
-    return 0;  /* lock count is always 0 */
+    pArena = GET_ARENA_PTR(handle);
+    return pArena->lockCount |
+           ((pArena->flags & GA_DISCARDABLE) ? GMEM_DISCARDABLE : 0);
 }
 
 
@@ -204,6 +309,7 @@
 {
     dprintf_global( stddeb, "LockSegment: %04x\n", handle );
     if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
+    GET_ARENA_PTR(handle)->lockCount++;
     return handle;
 }
 
@@ -214,6 +320,8 @@
 void UnlockSegment( HGLOBAL handle )
 {
     dprintf_global( stddeb, "UnlockSegment: %04x\n", handle );
+    if (handle == (HGLOBAL)-1) handle = CURRENT_DS;
+    GET_ARENA_PTR(handle)->lockCount--;
     /* FIXME: this ought to return the lock count in CX (go figure...) */
 }
 
@@ -230,9 +338,9 @@
 /***********************************************************************
  *           GlobalWire   (KERNEL.111)
  */
-LPSTR GlobalWire( HGLOBAL handle )
+SEGPTR GlobalWire( HGLOBAL handle )
 {
-    return GlobalLock( handle );
+    return WIN16_GlobalLock( handle );
 }
 
 
@@ -312,8 +420,7 @@
 WORD GlobalPageLock( HGLOBAL handle )
 {
     dprintf_global( stddeb, "GlobalPageLock: %04x\n", handle );
-    /* Nothing to do, as we can't page-lock a block (and we don't want to) */
-    return 1;  /* lock count */
+    return ++(GET_ARENA_PTR(handle)->pageLockCount);
 }
 
 
@@ -323,7 +430,7 @@
 WORD GlobalPageUnlock( HGLOBAL handle )
 {
     dprintf_global( stddeb, "GlobalPageUnlock: %04x\n", handle );
-    return 0;  /* lock count */
+    return --(GET_ARENA_PTR(handle)->pageLockCount);
 }
 
 
@@ -333,7 +440,7 @@
 void GlobalFix( HGLOBAL handle )
 {
     dprintf_global( stddeb, "GlobalFix: %04x\n", handle );
-    /* Nothing to do, as all the blocks are fixed in linear memory anyway */
+    GET_ARENA_PTR(handle)->lockCount++;
 }
 
 
@@ -343,7 +450,25 @@
 void GlobalUnfix( HGLOBAL handle )
 {
     dprintf_global( stddeb, "GlobalUnfix: %04x\n", handle );
-    /* This one is even more complicated that GlobalFix() :-) */
+    GET_ARENA_PTR(handle)->lockCount--;
+}
+
+
+/***********************************************************************
+ *           FarSetOwner   (KERNEL.403)
+ */
+void FarSetOwner( HANDLE handle, WORD hOwner )
+{
+    GET_ARENA_PTR(handle)->hOwner = hOwner;
+}
+
+
+/***********************************************************************
+ *           FarGetOwner   (KERNEL.404)
+ */
+WORD FarGetOwner( HANDLE handle )
+{
+    return GET_ARENA_PTR(handle)->hOwner;
 }
 
 
@@ -353,21 +478,98 @@
 WORD GlobalHandleToSel( HGLOBAL handle )
 {
     dprintf_toolhelp( stddeb, "GlobalHandleToSel: %04x\n", handle );
+    if (!handle) return 0;
     if (!(handle & 7))
     {
         fprintf( stderr, "Program attempted invalid selector conversion\n" );
         return handle - 1;
     }
-    return handle | 1;
+    return handle | 7;
 }
 
 
-/**********************************************************************
- *                      MemManInfo (toolhelp.72)
+/***********************************************************************
+ *           GlobalFirst   (TOOLHELP.51)
  */
-/*
-BOOL MemManInfo(LPMEMMANINFO lpmmi)
+BOOL GlobalFirst( GLOBALENTRY *pGlobal, WORD wFlags )
 {
-	return 1;
+    if (wFlags == GLOBAL_LRU) return FALSE;
+    pGlobal->dwNext = 0;
+    return GlobalNext( pGlobal, wFlags );
 }
-*/
+
+
+/***********************************************************************
+ *           GlobalNext   (TOOLHELP.52)
+ */
+BOOL GlobalNext( GLOBALENTRY *pGlobal, WORD wFlags)
+{
+    GLOBALARENA *pArena;
+
+    pArena = pGlobalArena + pGlobal->dwNext;
+    if (wFlags == GLOBAL_FREE)  /* only free blocks */
+    {
+        int i;
+        for (i = pGlobal->dwNext; i < globalArenaSize; i++, pArena++)
+            if (pArena->size == 0) break;  /* block is free */
+        if (i >= globalArenaSize) return FALSE;
+        pGlobal->dwNext = i;
+    }
+
+    pGlobal->dwAddress    = pArena->base;
+    pGlobal->dwBlockSize  = pArena->size;
+    pGlobal->hBlock       = pArena->handle;
+    pGlobal->wcLock       = pArena->lockCount;
+    pGlobal->wcPageLock   = pArena->pageLockCount;
+    pGlobal->wFlags       = (GetCurrentPDB() == pArena->hOwner);
+    pGlobal->wHeapPresent = FALSE;
+    pGlobal->hOwner       = pArena->hOwner;
+    pGlobal->wType        = GT_UNKNOWN;
+    pGlobal->wData        = 0;
+    pGlobal->dwNext++;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           GlobalInfo   (TOOLHELP.53)
+ */
+BOOL GlobalInfo( GLOBALINFO *pInfo )
+{
+    int i;
+    GLOBALARENA *pArena;
+
+    pInfo->wcItems = globalArenaSize;
+    pInfo->wcItemsFree = 0;
+    pInfo->wcItemsLRU = 0;
+    for (i = 0, pArena = pGlobalArena; i < globalArenaSize; i++, pArena++)
+        if (pArena->size == 0) pInfo->wcItemsFree++;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           GlobalEntryHandle   (TOOLHELP.54)
+ */
+BOOL GlobalEntryHandle( GLOBALENTRY *pGlobal, HGLOBAL hItem )
+{
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           GlobalEntryModule   (TOOLHELP.55)
+ */
+BOOL GlobalEntryModule( GLOBALENTRY *pGlobal, HMODULE hModule, WORD wSeg )
+{
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           MemManInfo   (TOOLHELP.72)
+ */
+BOOL MemManInfo( MEMMANINFO *pInfo )
+{
+    return TRUE;
+}
diff --git a/memory/local.c b/memory/local.c
index 5adf693..8c9a829 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -285,11 +285,19 @@
       /* - large free block    (FREE)       */
       /* - last arena          (FREE)       */
 
-      /* FIXME: What should be done if there's already */
-      /* a local heap in this segment? */
     dprintf_local(stddeb, "LocalInit: %04x %04x-%04x\n", selector, start, end);
     if (!selector) selector = CURRENT_DS;
     ptr = PTR_SEG_OFF_TO_LIN( selector, 0 );
+    pHeapInfo = LOCAL_GetHeap(selector);
+      /* If there's already a local heap in this segment, */
+      /* we simply return TRUE. Helps some programs, but  */
+      /* does not seem to be 100% correct yet (there are  */
+      /* still some "heap corrupted" messages in LocalAlloc */
+    if (pHeapInfo)  {
+      dprintf_local(stddeb,"LocalInit: Heap %04x initialized twice.\n",selector);
+      if (debugging_local) LOCAL_PrintHeap(selector);
+      return TRUE;
+    }
     start = LALIGN( max( start, sizeof(INSTANCEDATA) ) );
     heapInfoArena = LALIGN(start + sizeof(LOCALARENA) );
     freeArena = LALIGN( heapInfoArena + ARENA_HEADER_SIZE
@@ -368,14 +376,20 @@
 
       /* Find a suitable free block */
 
-    if (!(pInfo = LOCAL_GetHeap( ds ))) return 0;
+    if (!(pInfo = LOCAL_GetHeap( ds ))) {
+	  LOCAL_PrintHeap(ds);
+      return 0;
+    }
     size += ARENA_HEADER_SIZE;
     size = LALIGN( max( size, sizeof(LOCALARENA) ) );
     arena = pInfo->first;
     pArena = ARENA_PTR( ptr, arena );
     for (;;)
     {
-        if (arena == pArena->free_next) return 0;  /* not found */
+        if (arena == pArena->free_next) {
+	  LOCAL_PrintHeap(ds);
+	   return 0;  /* not found */
+	}
         arena = pArena->free_next;
         pArena = ARENA_PTR( ptr, arena );
         if (pArena->size >= size) break;
@@ -635,6 +649,7 @@
  */
 DWORD GetHeapSpaces( HMODULE module )
 {
+    return MAKELONG( 0x7fff, 0xffff );
 }
 
 
diff --git a/memory/selector.c b/memory/selector.c
index c9dc5ae..60556c2 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -4,22 +4,16 @@
  * Copyright 1995 Alexandre Julliard
  */
 
+#include <string.h>
 #include "windows.h"
 #include "ldt.h"
+#include "selectors.h"
 #include "stddebug.h"
 #include "debug.h"
 
 ldt_copy_entry ldt_copy[LDT_SIZE] = { {0,0}, };
 
-#define FIRST_LDT_ENTRY_TO_ALLOC  10
-
-
-/***********************************************************************
- *           SELECTOR_Init
- */
-void SELECTOR_Init()
-{
-}
+#define FIRST_LDT_ENTRY_TO_ALLOC  4
 
 
 /***********************************************************************
@@ -74,7 +68,7 @@
     dprintf_selector( stddeb, "FreeSelector(%04x)\n", sel );
     if (IS_SELECTOR_FREE(sel)) return sel;  /* error */
     count = (GET_SEL_LIMIT(sel) >> 16) + 1;
-    entry.base = entry.limit = 0;  /* clear the LDT entries */
+    memset( &entry, 0, sizeof(entry) );  /* clear the LDT entries */
     for (i = 0; i < count; i++)
         LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
     return 0;
@@ -129,7 +123,7 @@
     {
           /* Check if the next selectors are free */
         for (i = oldcount; i < newcount; i++)
-            if (!IS_SELECTOR_FREE(sel)) break;
+            if (!IS_SELECTOR_FREE(sel+i)) break;
         if (i < newcount)
         {
             FreeSelector( sel );
@@ -138,7 +132,7 @@
     }
     else if (oldcount > newcount) /* We need to remove selectors */
     {
-        entry.base = entry.limit = 0;  /* clear the LDT entries */
+        memset( &entry, 0, sizeof(entry) );  /* clear the LDT entries */
         for (i = oldcount; i < newcount; i++)
             LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
     }
diff --git a/misc/Imakefile b/misc/Imakefile
index a5f54d2..c2b1811 100644
--- a/misc/Imakefile
+++ b/misc/Imakefile
@@ -7,6 +7,7 @@
 	clipboard.c \
 	comm.c \
 	commdlg.c \
+	compobj.c \
 	dos_fs.c \
 	driver.c \
 	exec.c \
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 1b6cd82..31ad412 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -19,6 +19,7 @@
 #include "library.h"
 #include "commdlg.h"
 #include "dlgs.h"
+#include "selectors.h"
 
 #define OPENFILEDLG2			11
 #define SAVEFILEDLG2			12
@@ -97,7 +98,8 @@
 	printf("GetOpenFileName // apres LoadResource hDlgTmpl=%04X!\n", hDlgTmpl);
     wndPtr = WIN_FindWndPtr(lpofn->hwndOwner);
 	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpofn->hwndOwner, (WNDPROC)FileOpenDlgProc, (DWORD)lpofn); 
+		lpofn->hwndOwner, GetWndProcEntry16("FileOpenDlgProc"), 
+	        (DWORD)lpofn); 
 
 /*	strcpy(lpofn->lpstrFile, "SETUP.TXT"); */
 /*	strcpy(lpofn->lpstrFileTitle, "SETUP.TXT");*/
@@ -156,7 +158,8 @@
 		}
     wndPtr = WIN_FindWndPtr(lpofn->hwndOwner);
 	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpofn->hwndOwner, (WNDPROC)FileSaveDlgProc, (DWORD)lpofn);
+		lpofn->hwndOwner, GetWndProcEntry16("FileSaveDlgProc"), 
+		(DWORD)lpofn);
 	printf("GetSaveFileName // return lpstrFile='%s' !\n", PTR_SEG_TO_LIN(lpofn->lpstrFile));
 	return bRet;
 }
@@ -175,7 +178,8 @@
 	hDlgTmpl = LoadResource(hSysRes, hResInfo);
     wndPtr = WIN_FindWndPtr(lpChCol->hwndOwner);
 	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpChCol->hwndOwner, (WNDPROC)ColorDlgProc, (DWORD)lpChCol);
+		lpChCol->hwndOwner, GetWndProcEntry16("ColorDlgProc"), 
+		(DWORD)lpChCol);
 	return bRet;
 }
 
@@ -909,7 +913,8 @@
 		}
     wndPtr = WIN_FindWndPtr(lpFind->hwndOwner);
 	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpFind->hwndOwner, (WNDPROC)FindTextDlgProc, (DWORD)lpFind);
+		lpFind->hwndOwner, GetWndProcEntry16("FindTextDlgProc"), 
+	        (DWORD)lpFind);
 	return bRet;
 }
 
@@ -935,7 +940,8 @@
 		}
     wndPtr = WIN_FindWndPtr(lpFind->hwndOwner);
 	bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-		lpFind->hwndOwner, (WNDPROC)ReplaceTextDlgProc, (DWORD)lpFind);
+		lpFind->hwndOwner, GetWndProcEntry16("ReplaceTextDlgProc"), 
+		(DWORD)lpFind);
 	return bRet;
 }
 
@@ -1018,10 +1024,12 @@
     wndPtr = WIN_FindWndPtr(lpPrint->hwndOwner);
 	if (lpPrint->Flags & PD_PRINTSETUP)
 		bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-			lpPrint->hwndOwner, (WNDPROC)PrintSetupDlgProc, (DWORD)lpPrint);
+			lpPrint->hwndOwner, GetWndProcEntry16("PrintSetupDlgProc"),
+			(DWORD)lpPrint);
 	else
 		bRet = DialogBoxIndirectParam(wndPtr->hInstance, hDlgTmpl, 
-			lpPrint->hwndOwner, (WNDPROC)PrintDlgProc, (DWORD)lpPrint);
+			lpPrint->hwndOwner, GetWndProcEntry16("PrintDlgProc"),
+		        (DWORD)lpPrint);
 	return bRet;
 }
 
diff --git a/misc/compobj.c b/misc/compobj.c
new file mode 100644
index 0000000..c527b0f
--- /dev/null
+++ b/misc/compobj.c
@@ -0,0 +1,25 @@
+/*
+ *	COMPOBJ library
+ *
+ *	Copyright 1995	Martin von Loewis
+ */
+
+/*	At the moment, these are only empty stubs.
+ */
+
+#include "windows.h"
+#include "compobj.h"
+#include "ole.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/***********************************************************************
+ *           CoDisconnectObject
+ */
+OLESTATUS WINAPI CoDisconnectObject(
+	LPUNKNOWN lpUnk,
+	DWORD reserved)
+{
+    dprintf_ole(stdnimp,"CoDisconnectObject:%x %x\n",lpUnk,reserved);
+    return OLE_OK;
+}
diff --git a/misc/dos_fs.c b/misc/dos_fs.c
index f275256..dfc69dd 100644
--- a/misc/dos_fs.c
+++ b/misc/dos_fs.c
@@ -334,38 +334,24 @@
    ".."'s in names like "/usr/bin/../lib/test" */
 void DOS_SimplifyPath(char *name)
 {
-  char *p = name, *q = name, *l = NULL;
+  char *l,*p;
   BOOL changed;
 
- start:
-  p = name;
-  q = name;
-  while( *p ) {
-    *q++ = *p++;
-    if( ( *p == '/' ) && ( *(p-1) == '/' ) )
-      p++;
-  }
-  *q = 0;
-
-  p = name;
-  q = name;
-  changed = FALSE;
-  while( *p ) {
-    if( (!changed) &&( *p == '/' ) && ( *(p+1) == '.' ) && ( *(p+2) == '.' ) ) {
-      if( l ) {
-	q = l;
-	p += 3;
-        changed = TRUE;
-	continue;
-      }
+  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;
     }
-    else if( *p == '/' )
-      l = q;
-    *q++ = *p++;
-  }
-  *q = 0;
-  if( changed)
-    goto start;
+  } while (changed);
+  dprintf_dosfs(stddeb,"SimplifyPath: After %s\n",name);
 }
 
 
@@ -887,14 +873,6 @@
 	char *unixdirname;
 	char temp[256];
 	
-	for (x=0; x != MAX_OPEN_DIRS && DosDirs[x].inuse; x++)
-		;
-
-	if (x == MAX_OPEN_DIRS) {
-		fprintf( stderr, "DOS_opendir(): Too many open directories\n");
-		return NULL;
-	}
-
 	if ((unixdirname = DOS_GetUnixFileName(dosdirname)) == NULL)
 		return NULL;
 
@@ -905,13 +883,23 @@
 		if (temp[y] == '/') 
 		{
 			temp[y++] = '\0';
-			strcpy(DosDirs[x].filemask, temp +y);
-			ToDos(DosDirs[x].filemask);
+		        unixdirname += y;
 			break;
 		}
 	}
 
-    	dprintf_dosfs(stddeb,"DOS_opendir: %s -> %s\n", unixdirname, temp);
+        for (x=0; x <= MAX_OPEN_DIRS; x++) {
+	  if (x == MAX_OPEN_DIRS) {
+	    fprintf( stderr, "DOS_opendir(): Too many open directories\n");
+	    return NULL;
+	  }
+	  if (!DosDirs[x].inuse) break;
+	  if (strcmp(DosDirs[x].unixpath,temp) == 0) break;
+	}
+        
+        strcpy(DosDirs[x].filemask, unixdirname);
+        ToDos(DosDirs[x].filemask);
+    	dprintf_dosfs(stddeb,"DOS_opendir: %s / %s\n", unixdirname, temp);
 
 	DosDirs[x].inuse = 1;
 	strcpy(DosDirs[x].unixpath, temp);
diff --git a/misc/exec.c b/misc/exec.c
index 7d53906..771fba2 100644
--- a/misc/exec.c
+++ b/misc/exec.c
@@ -85,7 +85,9 @@
         dprintf_exec(stddeb, "Initializing %s, cs:ip %04x:%04x, ds %04x\n",
 		    wpnt->name, cs_reg, ip_reg, ds_reg);
 
-	    rv = CallTo16(cs_reg << 16 | ip_reg, ds_reg);
+            rv = CallTo16_regs_( (FARPROC)(cs_reg << 16 | ip_reg), ds_reg,
+                                 0 /*es*/, 0 /*ax*/, 0 /*bx*/, 0 /*cx*/,
+                                 0 /*dx*/, 0 /*si*/, wpnt->hinstance /*di*/ );
         dprintf_exec(stddeb,"rv = %x\n", rv);
 	}
     }
@@ -123,7 +125,9 @@
     sp_reg = wpnt->ne->ne_header->sp;
 
 	dprintf_exec(stddeb,"StartNewTask() before CallToInit16() !\n");
+/*
     rv = CallToInit16(cs_reg << 16 | ip_reg, ss_reg << 16 | sp_reg, ds_reg);
+*/
     dprintf_exec(stddeb,"rv = %x\n", rv);
 
 }
diff --git a/misc/file.c b/misc/file.c
index 2f3aa2f..c71673a 100644
--- a/misc/file.c
+++ b/misc/file.c
@@ -23,11 +23,8 @@
 #include <sys/stat.h>
 #include <string.h>
 #include "dos_fs.h"
-#include "regfunc.h"
 #include "windows.h"
-#include "wine.h"
 #include "msdos.h"
-#include "registers.h"
 #include "options.h"
 #include "stddebug.h"
 #include "debug.h"
@@ -118,11 +115,6 @@
 #ifdef WINELIB
     dprintf_file(stdnimp, "OpenFile: not implemented\n");
 #else
-#ifndef PROCEMU
-    struct sigcontext_struct  ccontext;
-                              /* To make macros like EAX happy */
-    struct sigcontext_struct *context=&ccontext; 
-#endif
     char                      filename[MAX_PATH+1];
     int                       action;
     struct stat               s;
diff --git a/misc/main.c b/misc/main.c
index b672f44..4da1c08 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -28,8 +28,9 @@
 #include "desktop.h"
 #include "prototypes.h"
 #include "texts.h"
-#include "dlls.h"
 #include "library.h"
+#include "dlls.h"
+#include "if1632.h"
 #define DEBUG_DEFINE_VARIABLES
 #include "stddebug.h"
 #include "debug.h"
@@ -573,6 +574,7 @@
     if (Options.desktopGeometry) MAIN_CreateDesktop( argc, argv );
     else rootWindow = DefaultRootWindow( display );
 
+    RELAY_Init();
     MAIN_SaveSetup();
     DOS_InitFS();
     Comm_Init();
@@ -863,17 +865,6 @@
 }
 
 /***********************************************************************
-*	ISROMMODULE (KERNEL.323)
-*/
-BOOL IsRomModule(HANDLE x)
-{
-	/* I don't know the prototype, I assume that it returns true
-	   if the dll is located in rom */
-	   
-	return FALSE;
-}
-
-/***********************************************************************
 *	FileCDR (KERNEL.130)
 */
 void FileCDR(FARPROC x)
diff --git a/misc/message.c b/misc/message.c
index 6daf380..7d23f7e 100644
--- a/misc/message.c
+++ b/misc/message.c
@@ -19,6 +19,7 @@
 #include "win.h"
 #include "texts.h"
 #include "user.h"
+#include "selectors.h"
 #include "stddebug.h"
 /* #define DEBUG_MSGBOX */
 #include "debug.h"
@@ -83,7 +84,7 @@
 	HINSTANCE	hInst;
 	int			nRet;
 
-	if (title == NULL)
+        if (title == NULL)
 		title = "Error";
 	wndPtr = WIN_FindWndPtr(hWnd);
 	if (wndPtr == NULL) {
@@ -115,7 +116,7 @@
 	lpmb->wType = type;
 	lpmb->ActiveFlg = TRUE;
 	wndClass.style           = CS_HREDRAW | CS_VREDRAW ;
-	wndClass.lpfnWndProc     = (WNDPROC)SystemMessageBoxProc;
+	wndClass.lpfnWndProc     = GetWndProcEntry16("SystemMessageBoxProc");
 	wndClass.cbClsExtra      = 0;
 	wndClass.cbWndExtra      = 4;
 	wndClass.hInstance       = hInst;
diff --git a/misc/network.c b/misc/network.c
index b662d99..5c7ab4f 100644
--- a/misc/network.c
+++ b/misc/network.c
@@ -31,6 +31,124 @@
 typedef LPSTR 	LPNETRESOURCE;
 
 /**************************************************************************
+ *              WNetErrorText       [USER.499]
+ */
+int WNetErrorText(WORD nError,LPSTR lpszText,WORD cbText)
+{
+	printf("EMPTY STUB !!! WNetErrorText(%x,%p,%x)\n",
+		nError,lpszText,cbText);
+	return FALSE;
+}
+
+/**************************************************************************
+ *              WNetOpenJob       [USER.501]
+ */
+int WNetOpenJob(LPSTR szQueue,LPSTR szJobTitle,WORD nCopies,LPWORD pfh)
+{
+	printf("EMPTY STUB !!! WNetOpenJob('%s','%s',%x,%p)\n",
+		szQueue,szJobTitle,nCopies,pfh);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetCloseJob       [USER.502]
+ */
+int WNetCloseJob(WORD fh,LPWORD pidJob,LPSTR szQueue)
+{
+	printf("EMPTY STUB !!! WNetCloseJob(%x,%p,'%s')\n",
+		fh,pidJob,szQueue);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetAbortJob       [USER.503]
+ */
+int WNetAbortJob(LPSTR szQueue,WORD wJobId)
+{
+	printf("EMPTY STUB !!! WNetAbortJob('%s',%x)\n",
+		szQueue,wJobId);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetHoldJob       [USER.504]
+ */
+int WNetHoldJob(LPSTR szQueue,WORD wJobId)
+{
+	printf("EMPTY STUB !!! WNetHoldJob('%s',%x)\n",
+		szQueue,wJobId);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetReleaseJob       [USER.505]
+ */
+int WNetReleaseJob(LPSTR szQueue,WORD wJobId)
+{
+	printf("EMPTY STUB !!! WNetReleaseJob('%s',%x)\n",
+		szQueue,wJobId);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetCancelJob       [USER.506]
+ */
+int WNetCancelJob(LPSTR szQueue,WORD wJobId)
+{
+	printf("EMPTY STUB !!! WNetCancelJob('%s',%x)\n",
+		szQueue,wJobId);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetSetJobCopies       [USER.507]
+ */
+int WNetSetJobCopies(LPSTR szQueue,WORD wJobId,WORD nCopies)
+{
+	printf("EMPTY STUB !!! WNetSetJobCopies('%s',%x,%x)\n",
+		szQueue,wJobId,nCopies);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetWatchQueue       [USER.508]
+ */
+int WNetWatchQueue(HWND hWnd,LPSTR szLocal,LPSTR szUser,WORD nQueue)
+{
+	printf("EMPTY STUB !!! WNetWatchQueue(%x,'%s','%s',%x)\n",
+		hWnd,szLocal,szUser,nQueue);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetUnwatchQueue       [USER.509]
+ */
+int WNetUnwatchQueue(LPSTR szQueue)
+{
+	printf("EMPTY STUB !!! WNetUnwatchQueue('%s')\n", szQueue);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetLockQueueData       [USER.510]
+ */
+int WNetLockQueueData(LPSTR szQueue,LPSTR szUser,void *lplpQueueStruct)
+{
+	printf("EMPTY STUB !!! WNetLockQueueData('%s','%s',%p)\n",
+		szQueue,szUser,lplpQueueStruct);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetUnlockQueueData       [USER.511]
+ */
+int WNetUnlockQueueData(LPSTR szQueue)
+{
+	printf("EMPTY STUB !!! WNetUnlockQueueData('%s')\n",szQueue);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
  *				WNetGetConnection	[USER.512]
  */
 int WNetGetConnection(LPSTR lpLocalName, 
@@ -50,6 +168,25 @@
 }
 
 /**************************************************************************
+ *              WNetDeviceMode       [USER.514]
+ */
+int WNetDeviceMode(HWND hWndOwner)
+{
+	printf("EMPTY STUB !!! WNetDeviceMode(%x)\n",hWndOwner);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetBrowseDialog       [USER.515]
+ */
+int WNetBrowseDialog(HWND hParent,WORD nType,LPSTR szPath)
+{
+	printf("EMPTY STUB !!! WNetBrowseDialog(%x,%x,'%s')\n",
+		hParent,nType,szPath);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
  *				WNetGetUser			[USER.516]
  */
 UINT WNetGetUser(LPSTR lpLocalName, LPSTR lpUserName, DWORD *lpSize)
@@ -81,6 +218,126 @@
 }
 
 /**************************************************************************
+ *              WNetGetError       [USER.519]
+ */
+int WNetGetError(LPWORD nError)
+{
+	printf("EMPTY STUB !!! WNetGetError(%p)\n",nError);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetGetErrorText       [USER.520]
+ */
+int WNetGetErrorText(WORD nError, LPSTR lpBuffer, LPWORD nBufferSize)
+{
+	printf("EMPTY STUB !!! WNetGetErrorText(%x,%p,%p)\n",
+		nError,lpBuffer,nBufferSize);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetRestoreConnection       [USER.523]
+ */
+int WNetRestoreConnection(HWND hwndOwner,LPSTR lpszDevice)
+{
+	printf("EMPTY STUB !!! WNetRestoreConnection(%x,'%s')\n",
+		hwndOwner,lpszDevice);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetWriteJob       [USER.524]
+ */
+int WNetWriteJob(WORD hJob,void *lpData,LPWORD lpcbData)
+{
+	printf("EMPTY STUB !!! WNetWriteJob(%x,%p,%p)\n",
+		hJob,lpData,lpcbData);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WnetConnectDialog       [USER.525]
+ */
+UINT WNetConnectDialog(HWND hWndParent, WORD iType)
+{
+	printf("EMPTY STUB !!! WNetConnectDialog(%4X, %4X)\n", hWndParent, iType);
+	return WN_SUCCESS;
+}
+
+/**************************************************************************
+ *              WNetDisconnectDialog       [USER.526]
+ */
+int WNetDisconnectDialog(HWND hwndOwner, WORD iType)
+{
+	printf("EMPTY STUB !!! WNetDisconnectDialog(%x,%x)\n",
+		hwndOwner,iType);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WnetConnectionDialog     [USER.527]
+ */
+UINT WNetConnectionDialog(HWND hWndParent, WORD iType)
+{
+	printf("EMPTY STUB !!! WNetConnectionDialog(%4X, %4X)\n", 
+		hWndParent, iType);
+	return WN_SUCCESS;
+}
+
+/**************************************************************************
+ *              WNetViewQueueDialog       [USER.528]
+ */
+int WNetViewQueueDialog(HWND hwndOwner,LPSTR lpszQueue)
+{
+	printf("EMPTY STUB !!! WNetViewQueueDialog(%x,'%s')\n",
+		hwndOwner,lpszQueue);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetPropertyDialog       [USER.529]
+ */
+int WNetPropertyDialog(HWND hwndParent,WORD iButton,
+	WORD nPropSel,LPSTR lpszName,WORD nType)
+{
+	printf("EMPTY STUB !!! WNetPropertyDialog(%x,%x,%x,'%s',%x)\n",
+		hwndParent,iButton,nPropSel,lpszName,nType);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetGetDirectoryType       [USER.530]
+ */
+int WNetGetDirectoryType(LPSTR lpName,void *lpType)
+{
+	printf("EMPTY STUB !!! WNetGetDirectoryType('%s',%p)\n",
+		lpName,lpType);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetDirectoryNotify       [USER.531]
+ */
+int WNetDirectoryNotify(HWND hwndOwner,void *lpDir,WORD wOper)
+{
+	printf("EMPTY STUB !!! WNetDirectoryNotify(%x,%p,%x)\n",
+		hwndOwner,lpDir,wOper);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
+ *              WNetGetPropertyText       [USER.532]
+ */
+int WNetGetPropertyText(HWND hwndParent,WORD iButton,WORD nPropSel,
+	LPSTR lpszName,WORD nType)
+{
+	printf("EMPTY STUB !!! WNetGetPropertyText(%x,%x,%x,'%s',%x)\n",
+		hwndParent,iButton,nPropSel,lpszName,nType);
+	return WN_NET_ERROR;
+}
+
+/**************************************************************************
  *				WNetAddConnection2	[USER.???]
  */
 UINT WNetAddConnection2(LPSTR lpNetPath, LPSTR lpPassWord, 
diff --git a/misc/property.c b/misc/property.c
index e97c3ea..75f442f 100644
--- a/misc/property.c
+++ b/misc/property.c
@@ -218,15 +218,8 @@
 	    	printf("EnumProps // lpProp->PropName='%s' !\n", lpProp->PropName);
 			str = lpProp->PropName; 
 			}
-#ifdef WINELIB
-		nRet = (*lpEnumFunc)((HWND)hWnd, (WORD)0, 
-			(LPSTR)str, (HANDLE)lpProp->hData);
-#else
-		nRet = CallBack16(lpEnumFunc, 3,
-		    CALLBACK_SIZE_WORD, (HWND)hWnd,
-		    CALLBACK_SIZE_LONG, (LPSTR)str,
-		    CALLBACK_SIZE_WORD, (HANDLE)lpProp->hData);
-#endif
+                nRet = CallEnumPropProc( lpEnumFunc, hWnd,
+                                         (LONG)str, lpProp->hData);
 		if (nRet == 0) break;
 		if (lpProp->lpNextProp == NULL) break;
 		lpProp = lpProp->lpNextProp;
diff --git a/misc/shell.c b/misc/shell.c
index e5c8043..f412887 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -9,6 +9,7 @@
 #include "library.h"
 #include "shell.h"
 #include "neexe.h"
+#include "selectors.h"
 #include "../rc/sysres.h"
 #include "stddebug.h"
 /* #define DEBUG_REG */
@@ -81,6 +82,7 @@
 	  dprintf_reg(stddeb,"RegOpenKey // specific key = %08lX !\n", hKey);
 	  lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
         }
+        if (!*lpSubKey)  { *lphKey = hKey; return ERROR_SUCCESS; }
         while(*lpSubKey) {
           ptr = strchr(lpSubKey,'\\');
           if (!ptr) ptr = lpSubKey + strlen(lpSubKey);
@@ -128,6 +130,7 @@
 	  dprintf_reg(stddeb,"RegCreateKey // specific key = %08lX !\n", hKey);
 	  lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
         }
+        if (!*lpSubKey)  { *lphKey = hKey; return ERROR_SUCCESS; }
         while (*lpSubKey) {
           dprintf_reg(stddeb, "RegCreateKey: Looking for subkey %s\n", lpSubKey);
           ptr = strchr(lpSubKey,'\\');
@@ -389,7 +392,7 @@
 
 	return DialogBoxIndirectPtr( GetWindowWord(hWnd, GWW_HINSTANCE),
                                      sysres_DIALOG_SHELL_ABOUT_MSGBOX,
-                                     hWnd, (WNDPROC)AboutDlgProc);
+                                     hWnd, GetWndProcEntry16("AboutDlgProc"));
 }
 
 
diff --git a/miscemu/emulate.c b/miscemu/emulate.c
index 31c9634..70d8153 100644
--- a/miscemu/emulate.c
+++ b/miscemu/emulate.c
@@ -1,6 +1,6 @@
 #include <stdlib.h>
 #include <stdio.h>
-#include "regfunc.h"
+#include "wine.h"
 #include "stddebug.h"
 /* #define DEBUG_INT */
 #include "debug.h"
@@ -14,20 +14,21 @@
   unsigned short Unused;
 };
 
-int
-WIN87_fpmath()
+void
+WIN87_fpmath( struct sigcontext_struct context )
 {
-  dprintf_int(stddeb, "_fpmath: (%x:%lx %x %x)\n",_CONTEXT->sc_cs, 
-	 _CONTEXT->sc_eip, _CONTEXT->sc_es, (unsigned int)_BX & 0xffff);
+  dprintf_int(stddeb, "_fpmath: (%x:%lx %x %x)\n",context.sc_cs, 
+              context.sc_eip, context.sc_es, (int)context.sc_ebx & 0xffff );
 
-  switch(_BX & 0xffff)
+  switch(context.sc_ebx & 0xffff)
     {
     case 11:
-      return 1;
+        context.sc_eax = 1;
+        break;
     default:
-      return 0;
+        context.sc_eax = 0;
+        break;
     }
-
 }
 
 void
diff --git a/miscemu/int21.c b/miscemu/int21.c
index 03afeef..28d4dca 100644
--- a/miscemu/int21.c
+++ b/miscemu/int21.c
@@ -16,7 +16,6 @@
 #include <utime.h>
 #include <ctype.h>
 #include "dos_fs.h"
-#include "regfunc.h"
 #include "windows.h"
 #include "msdos.h"
 #include "registers.h"
@@ -1669,10 +1668,9 @@
 /**********************************************************************
  *			DOS3Call
  */
-void DOS3Call(void)
+void DOS3Call( struct sigcontext_struct context )
 {
-    do_int21((struct sigcontext_struct *) _CONTEXT);
-    ReturnFromRegisterFunc();
+    do_int21( &context );
 }
 
 void INT21_Init(void)
diff --git a/miscemu/kernel.c b/miscemu/kernel.c
index 8f24c72..f81410b 100644
--- a/miscemu/kernel.c
+++ b/miscemu/kernel.c
@@ -6,8 +6,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "prototypes.h"
-#include "regfunc.h"
 #include "options.h"
+#include "wine.h"
 #include "stddebug.h"
 #include "debug.h"
 
@@ -16,20 +16,14 @@
 /**********************************************************************
  *					KERNEL_InitTask
  */
-void KERNEL_InitTask(void)
+void KERNEL_InitTask( struct sigcontext_struct context )
 {
-    _BX = 0x81;
-    _AX = 1;
-    _CX = WIN_StackSize;
-    _DX = Options.cmdShow;
-    _DI = _DS;
-
-/* FIXME: DI should contain the instance handle of the caller, _DS doesn't
-          always work as the caller might have changed it. */
-
-    _SI = 0;
-    ReturnFromRegisterFunc();
-    /* Function does not return */
+    context.sc_eax = 1;
+    context.sc_ebx = 0x81;
+    context.sc_ecx = WIN_StackSize;
+    context.sc_edx = Options.cmdShow;
+    context.sc_edi = 0;
+    context.sc_edi = context.sc_ds;
 }
 
 /**********************************************************************
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index 27a2b3c..e2af222 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -1833,14 +1833,9 @@
 			lpTimer->wCurTime = lpTimer->wDelay;
 			if (lpTimer->lpFunc != NULL) {
 				dprintf_mmtime(stddeb,"MMSysTimeCallback // before CallBack16 !\n");
-#ifdef WINELIB
-				(*lpTimer->lpFunc)(lpTimer->wTimerID, (WORD)0, 
-						lpTimer->dwUser, (DWORD)0, (DWORD)0);
-#else
-				CallBack16(lpTimer->lpFunc, 5, 
-					0, (int)lpTimer->wTimerID, 0, (int)0, 
-					2, lpTimer->dwUser, 2, 0, 2, 0);
-#endif
+                                CallTimeFuncProc( lpTimer->lpFunc,
+                                                  lpTimer->wTimerID, 0,
+                                                  lpTimer->dwUser, 0, 0 );
 				dprintf_mmtime(stddeb, "MMSysTimeCallback // after CallBack16 !\n");
 				fflush(stdout);
 				}
diff --git a/objects/font.c b/objects/font.c
index 15d1785..5272b4f 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -736,14 +736,10 @@
 		SelectObject(hDC, hOldFont);
 		DeleteObject(hFont);
 		dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
-
-#ifdef WINELIB
-		nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
-#else
-		nRet = CallBack16(lpEnumFunc, 4, 2, GDI_HEAP_SEG_ADDR(hLog),
-					2, GDI_HEAP_SEG_ADDR(hMet),
-                                        0, (int)0, 2, (int)lpData);
-#endif
+                nRet = CallEnumFontsProc( lpEnumFunc,
+                                          GDI_HEAP_SEG_ADDR(hLog),
+                                          GDI_HEAP_SEG_ADDR(hMet),
+                                          0, (LONG)lpData );
 		if (nRet == 0) {
 			dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
 			break;
@@ -823,13 +819,10 @@
 		DeleteObject(hFont);
 		dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
 
-#ifdef WINELIB
-		nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
-#else
-		nRet = CallBack16(lpEnumFunc, 4, 2, GDI_HEAP_SEG_ADDR(hLog),
-					2, GDI_HEAP_SEG_ADDR(hMet),
-                                        0, (int)0, 2, (int)lpData);
-#endif
+                nRet = CallEnumFontFamProc( lpEnumFunc,
+                                            GDI_HEAP_SEG_ADDR(hLog),
+                                            GDI_HEAP_SEG_ADDR(hMet),
+                                            0, (LONG)lpData );
 		if (nRet == 0) {
 			dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
 			break;
@@ -840,5 +833,17 @@
 	return 0;
 }
 
+/*************************************************************************
+ *				GetRasterizerCaps	[GDI.313]
+ */
 
-
+BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, WORD cbNumBytes)
+{
+  /* This is not much more than a dummy */
+  RASTERIZER_STATUS rs;
+  
+  rs.nSize = sizeof(rs);
+  rs.wFlags = 0;
+  rs.nLanguageID = 0;
+  return True;
+}
diff --git a/objects/gdiobj.c b/objects/gdiobj.c
index fff10ce..ed86582 100644
--- a/objects/gdiobj.c
+++ b/objects/gdiobj.c
@@ -16,6 +16,7 @@
 #include "palette.h"
 #include "pen.h"
 #include "region.h"
+#include "callback.h"
 #include "stddebug.h"
 /* #define DEBUG_GDI */
 #include "debug.h"
@@ -486,16 +487,10 @@
 				dprintf_gdi(stddeb,"EnumObjects // StockPen lopnWidth=%d\n", ((LPLOGPEN)lpLog)->lopnWidth.x);
 				dprintf_gdi(stddeb,"EnumObjects // StockPen lopnColor=%08lX\n", ((LPLOGPEN)lpLog)->lopnColor);
 				}
-			nRet = 1;
-/*
-#ifdef WINELIB
-			nRet = (*lpEnumFunc)(lpLog, lpData);
-#else
-			nRet = CallBack16(lpEnumFunc, 4, 2,
-                                      GDI_HEAP_SEG_ADDR(hLog), 2, (int)lpData);
-#endif
-*/
-			dprintf_gdi(stddeb,"EnumObjects // after CallBack16 !\n");
+			nRet = CallEnumObjectsProc( lpEnumFunc,
+                                                    GDI_HEAP_SEG_ADDR(hLog),
+                                                    (int)lpData );
+			dprintf_gdi(stddeb,"EnumObjects // after Callback!\n");
 			if (nRet == 0) {
 				GDI_HEAP_FREE(hLog);
 				dprintf_gdi(stddeb,"EnumObjects // EnumEnd requested by application !\n");
@@ -524,16 +519,10 @@
 				dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnWidth=%d\n", ((LPLOGPEN)lpLog)->lopnWidth.x);
 				dprintf_gdi(stddeb,"EnumObjects // DC_Pen lopnColor=%08lX\n", ((LPLOGPEN)lpLog)->lopnColor);
 				}
-/*
-#ifdef WINELIB
-			nRet = (*lpEnumFunc)(lpLog, lpData);
-#else
-			nRet = CallBack16(lpEnumFunc, 4, 2,
-                                      GDI_HEAP_SEG_ADDR(hLog), 2, (int)lpData);
-#endif
-*/
-			nRet = 1;
-			dprintf_gdi(stddeb,"EnumObjects // after CallBack16 !\n");
+			nRet = CallEnumObjectsProc( lpEnumFunc,
+                                                    GDI_HEAP_SEG_ADDR(hLog),
+                                                    (int)lpData );
+			dprintf_gdi(stddeb,"EnumObjects // after Callback!\n");
 			if (nRet == 0) {
 				GDI_HEAP_FREE(hLog);
 				dprintf_gdi(stddeb,"EnumObjects // EnumEnd requested by application !\n");
diff --git a/objects/linedda.c b/objects/linedda.c
index 729f9ec..d53e133 100644
--- a/objects/linedda.c
+++ b/objects/linedda.c
@@ -8,7 +8,7 @@
 
 #include <stdlib.h>
 #include "windows.h"
-#include "if1632.h"
+#include "callback.h"
 
 /**********************************************************************
  *		LineDDA		(GDI.100)
@@ -16,32 +16,41 @@
 void LineDDA(short nXStart, short nYStart, short nXEnd, short nYEnd,
 	     FARPROC callback, long lParam)
 {
-    int x, y;
-    int b;
-    int x_diff = nXEnd - nXStart;
-    int y_diff = nYEnd - nYStart;
+    int xadd = 1, yadd = 1;
+    int err,erradd;
+    int cnt;
+    int dx = nXEnd - nXStart;
+    int dy = nYEnd - nYStart;
 
-    if (x_diff == 0 && y_diff == 0)
-	return;
-    
-    if ((abs(x_diff) < abs(y_diff) && x_diff != 0) || y_diff == 0)
-    {
-	b = (nXStart * y_diff) / x_diff - nYStart;
-
-	for (x = nXStart; x <= nXEnd; x++)
-	{
-	    y = (x * y_diff) / x_diff + b;
-	    CallLineDDAProc(callback, x, y, lParam);
-	}
+    if (dx < 0)  {
+      dx = -dx; xadd = -1;
     }
-    else
-    {
-	b = (nYStart * x_diff) / y_diff - nXStart;
-
-	for (y = nYStart; y <= nYEnd; y++)
-	{
-	    x = (y * x_diff) / y_diff + b;
-	    CallLineDDAProc(callback, x, y, lParam);
+    if (dy < 0)  {
+      dy = -dy; yadd = -1;
+    }
+    if (dx > dy) { /* line is "more horizontal" */
+      err = 2*dy - dx; erradd = 2*dy - 2*dx;
+      for(cnt = 0;cnt <= dx; cnt++) {
+	CallLineDDAProc(callback,nXStart,nYStart,lParam);
+	if (err > 0) {
+	  nYStart += yadd;
+	  err += erradd;
+	} else  {
+	  err += 2*dy;
 	}
+	nXStart += xadd;
+      }
+    } else  { /* line is "more vertical" */
+      err = 2*dx - dy; erradd = 2*dx - 2*dy;
+      for(cnt = 0;cnt <= dy; cnt++) {
+	CallLineDDAProc(callback,nXStart,nYStart,lParam);
+	if (err > 0) {
+	  nXStart += xadd;
+	  err += erradd;
+	} else  {
+	  err += 2*dx;
+	}
+	nYStart += yadd;
+      }
     }
 }
diff --git a/toolkit/sup.c b/toolkit/sup.c
index 3d1be0c..f22343c 100644
--- a/toolkit/sup.c
+++ b/toolkit/sup.c
@@ -13,21 +13,6 @@
     return (*func)(hwnd, message, wParam, lParam);
 }
 
-CallLineDDAProc (FARPROC back, int x, int y, long lParam)
-{
-    return (*back)(x, y, lParam);
-}
-
-DWORD CallHookProc (HOOKPROC func, short code, WPARAM wParam, LPARAM lParam)
-{
-    return (*func)(code, wParam, lParam);
-}
-
-BOOL CallGrayStringProc (FARPROC func, HDC hdc, LPARAM lParam, INT cch)
-{
-    return (*func) (hdc, lParam, cch);
-}
-
 /*
  * Header loading routines for WineLib.
  */
diff --git a/tools/Imakefile b/tools/Imakefile
index 2c6613b..e5abd7b 100644
--- a/tools/Imakefile
+++ b/tools/Imakefile
@@ -6,11 +6,7 @@
 
 AllTarget(build)
 
-#ifndef NewBuild
 NormalProgramTarget(build,build.o,$(DEPLIBS),,)
-#else
-NormalProgramTarget(newbuild,$(OBJS),$(DEPLIBS),,)
-#endif
 
 DependTarget()
 
diff --git a/tools/build-spec.txt b/tools/build-spec.txt
index 25dfed6..af4c7fa 100644
--- a/tools/build-spec.txt
+++ b/tools/build-spec.txt
@@ -4,8 +4,7 @@
 
 ORDINAL VARTYPE EXPORTNAME (DATA [DATA [DATA [...]]])
 
-ORDINAL FUNCTYPE EXPORTNAME([ARGTYPE [ARGTYPE [...]]])
-		 HANDLERNAME([ARGNUM [ARGNUM [...]]])
+ORDINAL FUNCTYPE EXPORTNAME([ARGTYPE [ARGTYPE [...]]]) HANDLERNAME
 
 ORDINAL equate EXPORTNAME DATA
 
@@ -36,34 +35,22 @@
 
 Function ordinals:
 
-    This type defines a function entry point.  The prototype defined
-by "EXPORTNAME ([ARGTYPE [ARGTYPE [...]]])" specifies the name available
-for dynamic linking and the format of the 16-bit stack.  By specifying
-"FUNCTYPE", the loader can automatically determine which order the
-parameters were pushed by the calling routine.  The prototype
-specified by "HANDLERNAME([ARGNUM [ARGNUM [...]]])"  specifies to
-the loader how to call the 32-bit library routine which will handle this
-call.  Note that specifying "ARGNUM" as 1 means the leftmost argument
-given to the function call, and not the first argument on the stack.
-For "pascal" functions, "ARGNUM" equal to 1 specifies the last
-argument on the stack.  If you do not specify any arguments to the
-handler function, then address of the 16-bit argument stack is
-passed to the handler function.
-    "ORDINAL" is replaced by the ordinal number corresponding to the
-function.  "FUNCTYPE" should be "c" or "pascal" ("pascal" may be
-shortened to "p").  "EXPORTNAME" will be the name available for
-dynamic linking.  "ARGTYPE" should be "byte", "word", "long", "ptr",
-"s_byte" (signed byte), "s_word" (signed word) or "s_long"
-(signed long).  "HANDLERNAME" is the name of the actual function
-that will process the request in 32-bit mode.  "ARGNUM" is the
-original argument number.  The first argument is numbered "1".
+    This type defines a function entry point.  The prototype defined by
+"EXPORTNAME ([ARGTYPE [ARGTYPE [...]]])" specifies the name available for
+dynamic linking and the format of the 16-bit stack. "ORDINAL" is replaced
+by the ordinal number corresponding to the function.  "FUNCTYPE" should be
+"pascal16" or "pascal" for 16-bit or 32-bit return values.  "ARGTYPE"
+should be "byte", "word", "long", "ptr" (linear pointer), "s_byte" (signed
+byte), "s_word" (signed word), "s_long" (signed long), or "segptr"
+(segmented pointer).  "HANDLERNAME" is the name of the actual function that
+will process the request in 32-bit mode.
 
     This first example defines an entry point for the CreateWindow()
 call (the ordinal 100 is just an example):
 
 	100 pascal CreateWindow(ptr ptr long s_word s_word s_word s_word
 				word word word ptr)
-		   WIN_CreateWindow(1 2 3 4 5 6 7 8 9 10 11)
+		   WIN_CreateWindow
 
    This second example defines an entry point for the GetFocus()
 call (the ordinal 100 is just an example):
diff --git a/tools/build.c b/tools/build.c
index c4e8125..6c1d179 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -1,4 +1,7 @@
-/* static char Copyright[] = "Copyright  Robert J. Amstadt, 1993"; */
+/*
+ * Copyright 1993 Robert J. Amstadt
+ * Copyright 1995 Alexandre Julliard
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -6,17 +9,6 @@
 #include <ctype.h>
 #include "wine.h"
 
-#ifdef linux
-#ifdef __ELF__
-#define UTEXTSEL 0x0f
-#else
-#define UTEXTSEL 0x23
-#endif
-#endif
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#define UTEXTSEL 0x1f
-#endif
-
 /* ELF symbols do not have an underscore in front */
 #ifdef __ELF__
 #define PREFIX
@@ -24,66 +16,22 @@
 #define PREFIX "_"
 #endif
 
-#define VARTYPE_BYTE	0
-#define VARTYPE_SIGNEDWORD	0
-#define VARTYPE_WORD	1
-#define VARTYPE_LONG	2
-#define VARTYPE_FARPTR	3
+#define TYPE_INVALID     0
+#define TYPE_BYTE        1
+#define TYPE_WORD        2
+#define TYPE_LONG        3
+#define TYPE_PASCAL_16   4
+#define TYPE_PASCAL      5
+#define TYPE_REGISTER    6
+#define TYPE_ABS         7
+#define TYPE_RETURN      8
 
-#define FUNCTYPE_PASCAL_16	16
-#define FUNCTYPE_PASCAL		17
-#define FUNCTYPE_REG		18
-
-#define EQUATETYPE_ABS	19
-#define TYPE_RETURN	20
-
-/*#define MAX_ORDINALS	1024*/
 #define MAX_ORDINALS	1299
 
-#define PUSH_0		"\tpushl\t$0\n"
-#define PUSH_SS		"\tpushw\t$0\n\tpushw\t%%ss\n"
-#define PUSH_ESP	"\tpushl\t%%esp\n"
-#define PUSH_EFL	"\tpushfl\n"
-#define PUSH_CS		"\tpushw\t$0\n\tpushw\t%%cs\n"
-#define PUSH_EIP	"\tpushl\t$0\n"
-#define PUSH_DS		"\tpushw\t$0\n\tpushw\t%%ds\n"
-#define PUSH_ES		"\tpushw\t$0\n\tpushw\t%%es\n"
-#define PUSH_FS		"\tpushw\t$0\n\tpushw\t%%fs\n"
-#define PUSH_GS		"\tpushw\t$0\n\tpushw\t%%gs\n"
-#define PUSH_EAX	"\tpushl\t%%eax\n"
-#define PUSH_ECX	"\tpushl\t%%ecx\n"
-#define PUSH_EDX	"\tpushl\t%%edx\n"
-#define PUSH_EBX	"\tpushl\t%%ebx\n"
-#define PUSH_EBP	"\tpushl\t%%ebp\n"
-#define PUSH_ESI	"\tpushl\t%%esi\n"
-#define PUSH_EDI	"\tpushl\t%%edi\n"
-
-#define POP_0		"\tadd\t$4,%%esp\n"
-#define POP_SS		"\tpopw\t%%ss\n\tadd\t$2,%%esp\n"
-#define POP_ESP		"\tpopl\t%%esp\n"
-#define POP_EFL		"\tpopl\t%%gs:return_value\n"
-#define POP_CS		"\tpopw\t%%cs\n\tadd\t$2,%%esp\n"
-#define POP_EIP		"\tpopl\t$0\n"
-#define POP_DS		"\tpopw\t%%ds\n\tadd\t$2,%%esp\n"
-#define POP_ES		"\tpopw\t%%es\n\tadd\t$2,%%esp\n"
-#define POP_FS		"\tpopw\t%%fs\n\tadd\t$2,%%esp\n"
-#define POP_GS		"\tpopw\t%%gs\n\tadd\t$2,%%esp\n"
-#define POP_EAX		"\tpopl\t%%eax\n"
-#define POP_ECX		"\tpopl\t%%ecx\n"
-#define POP_EDX		"\tpopl\t%%edx\n"
-#define POP_EBX		"\tpopl\t%%ebx\n"
-#define POP_EBP		"\tpopl\t%%ebp\n"
-#define POP_ESI		"\tpopl\t%%esi\n"
-#define POP_EDI		"\tpopl\t%%edi\n"
-
-char **context_strings;
-char **pop_strings;
-int    n_context_strings;
-
 typedef struct ordinal_definition_s
 {
-    int valid;
     int type;
+    int offset;
     char export_name[80];
     void *additional_data;
 } ORDDEF;
@@ -96,10 +44,8 @@
 
 typedef struct ordinal_function_definition_s
 {
-    int n_args_16;
-    int arg_types_16[16];
-    int arg_16_offsets[16];
-    int arg_16_size;
+    int  n_args;
+    char arg_types[32];
     char internal_name[80];
 } ORDFUNCDEF;
 
@@ -109,7 +55,7 @@
     int ret_value;
 } ORDRETDEF;
 
-ORDDEF OrdinalDefinitions[MAX_ORDINALS];
+static ORDDEF OrdinalDefinitions[MAX_ORDINALS];
 
 char LowerDLLName[80];
 char UpperDLLName[80];
@@ -122,7 +68,14 @@
 char ParseSaveChar;
 int Line;
 
-int IsNumberString(char *s)
+static int debugging = 1;
+
+  /* Offset of register relative to the end of the context struct */
+#define CONTEXTOFFSET(reg) \
+   ((int)&(((struct sigcontext_struct *)1)->reg) - 1 \
+    - sizeof(struct sigcontext_struct))
+
+static int IsNumberString(char *s)
 {
     while (*s != '\0')
 	if (!isdigit(*s++))
@@ -131,7 +84,7 @@
     return 1;
 }
 
-char *strlower(char *s)
+static char *strlower(char *s)
 {
     char *p;
     
@@ -141,7 +94,7 @@
     return s;
 }
 
-char *strupper(char *s)
+static char *strupper(char *s)
 {
     char *p;
     
@@ -151,20 +104,7 @@
     return s;
 }
 
-int stricmp(char *s1, char *s2)
-{
-    if (strlen(s1) != strlen(s2))
-	return -1;
-    
-    while (*s1 != '\0')
-	if (*s1++ != *s2++)
-	    return -1;
-    
-    return 0;
-}
-
-char *
-GetTokenInLine(void)
+static char * GetTokenInLine(void)
 {
     char *p;
     char *token;
@@ -200,8 +140,7 @@
     return token;
 }
 
-char *
-GetToken(void)
+static char * GetToken(void)
 {
     char *token;
 
@@ -235,8 +174,7 @@
     return token;
 }
 
-int
-ParseVariable(int ordinal, int type)
+static int ParseVariable(int ordinal, int type)
 {
     ORDDEF *odp;
     ORDVARDEF *vdp;
@@ -294,7 +232,6 @@
     }
     
     odp = &OrdinalDefinitions[ordinal];
-    odp->valid = 1;
     odp->type = type;
     strcpy(odp->export_name, export_name);
     
@@ -307,16 +244,12 @@
     return 0;
 }
 
-int
-ParseExportFunction(int ordinal, int type)
+static int ParseExportFunction(int ordinal, int type)
 {
     char *token;
     ORDDEF *odp;
     ORDFUNCDEF *fdp;
     int i;
-    int current_offset;
-    int arg_size;
-	
     
     if (ordinal >= MAX_ORDINALS)
     {
@@ -326,7 +259,6 @@
     
     odp = &OrdinalDefinitions[ordinal];
     strcpy(odp->export_name, GetToken());
-    odp->valid = 1;
     odp->type = type;
     fdp = malloc(sizeof(*fdp));
     odp->additional_data = fdp;
@@ -338,60 +270,39 @@
 	exit(1);
     }
 
-    fdp->arg_16_size = 0;
     for (i = 0; i < 16; i++)
     {
 	token = GetToken();
 	if (*token == ')')
 	    break;
 
-	if (stricmp(token, "byte") == 0 || stricmp(token, "word") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_WORD;
-	    fdp->arg_16_size += 2;
-	    fdp->arg_16_offsets[i] = 2;
-	}
-	else if (stricmp(token, "s_byte") == 0 || 
-		 stricmp(token, "s_word") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_SIGNEDWORD;
-	    fdp->arg_16_size += 2;
-	    fdp->arg_16_offsets[i] = 2;
-	}
-	else if (stricmp(token, "long") == 0 || stricmp(token, "segptr") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_LONG;
-	    fdp->arg_16_size += 4;
-	    fdp->arg_16_offsets[i] = 4;
-	}
-	else if (stricmp(token, "ptr") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_FARPTR;
-	    fdp->arg_16_size += 4;
-	    fdp->arg_16_offsets[i] = 4;
-	}
+	if (!strcmp(token, "byte") || !strcmp(token, "word"))
+            fdp->arg_types[i] = 'w';
+	else if (!strcmp(token, "s_byte") || !strcmp(token, "s_word"))
+            fdp->arg_types[i] = 's';
+	else if (!strcmp(token, "long") || !strcmp(token, "segptr"))
+            fdp->arg_types[i] = 'l';
+	else if (!strcmp(token, "ptr"))
+            fdp->arg_types[i] = 'p';
 	else
 	{
 	    fprintf(stderr, "%d: Unknown variable type '%s'\n", Line, token);
 	    exit(1);
 	}
     }
-    fdp->n_args_16 = i;
+    fdp->arg_types[i] = '\0';
 
-    current_offset = 0;
-    for (i--; i >= 0; i--)
+    if ((type == TYPE_REGISTER) && (i > 0))
     {
-        arg_size = fdp->arg_16_offsets[i];
-        fdp->arg_16_offsets[i] = current_offset;
-        current_offset += arg_size;
+        fprintf( stderr, "%d: Register function can't have arguments\n", Line);
+        exit(1);
     }
 
     strcpy(fdp->internal_name, GetToken());
     return 0;
 }
 
-int
-ParseEquate(int ordinal)
+static int ParseEquate(int ordinal)
 {
     ORDDEF *odp;
     char *token;
@@ -416,15 +327,13 @@
 	exit(1);
     }
 
-    odp->valid = 1;
-    odp->type = EQUATETYPE_ABS;
+    odp->type = TYPE_ABS;
     odp->additional_data = (void *) value;
 
     return 0;
 }
 
-int
-ParseReturn(int ordinal)
+static int ParseReturn(int ordinal)
 {
     ORDDEF *odp;
     ORDRETDEF *rdp;
@@ -441,7 +350,6 @@
     
     odp = &OrdinalDefinitions[ordinal];
     strcpy(odp->export_name, GetToken());
-    odp->valid = 1;
     odp->type = TYPE_RETURN;
     odp->additional_data = rdp;
 
@@ -466,8 +374,7 @@
     return 0;
 }
 
-int
-ParseOrdinal(int ordinal)
+static int ParseOrdinal(int ordinal)
 {
     char *token;
     
@@ -478,23 +385,23 @@
 	exit(1);
     }
 
-    if (stricmp(token, "byte") == 0)
-	return ParseVariable(ordinal, VARTYPE_BYTE);
-    else if (stricmp(token, "word") == 0)
-	return ParseVariable(ordinal, VARTYPE_WORD);
-    else if (stricmp(token, "long") == 0)
-	return ParseVariable(ordinal, VARTYPE_LONG);
-    else if (stricmp(token, "p") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
-    else if (stricmp(token, "pascal") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
-    else if (stricmp(token, "pascal16") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_PASCAL_16);
-    else if (stricmp(token, "register") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_REG);
-    else if (stricmp(token, "equate") == 0)
+    if (strcmp(token, "byte") == 0)
+	return ParseVariable(ordinal, TYPE_BYTE);
+    else if (strcmp(token, "word") == 0)
+	return ParseVariable(ordinal, TYPE_WORD);
+    else if (strcmp(token, "long") == 0)
+	return ParseVariable(ordinal, TYPE_LONG);
+    else if (strcmp(token, "p") == 0)
+	return ParseExportFunction(ordinal, TYPE_PASCAL);
+    else if (strcmp(token, "pascal") == 0)
+	return ParseExportFunction(ordinal, TYPE_PASCAL);
+    else if (strcmp(token, "pascal16") == 0)
+	return ParseExportFunction(ordinal, TYPE_PASCAL_16);
+    else if (strcmp(token, "register") == 0)
+	return ParseExportFunction(ordinal, TYPE_REGISTER);
+    else if (strcmp(token, "equate") == 0)
 	return ParseEquate(ordinal);
-    else if (stricmp(token, "return") == 0)
+    else if (strcmp(token, "return") == 0)
 	return ParseReturn(ordinal);
     else
     {
@@ -505,14 +412,13 @@
     }
 }
 
-int
-ParseTopLevel(void)
+static int ParseTopLevel(void)
 {
     char *token;
     
     while ((token = GetToken()) != NULL)
     {
-	if (stricmp(token, "name") == 0)
+	if (strcmp(token, "name") == 0)
 	{
 	    strcpy(LowerDLLName, GetToken());
 	    strlower(LowerDLLName);
@@ -520,7 +426,7 @@
 	    strcpy(UpperDLLName, LowerDLLName);
 	    strupper(UpperDLLName);
 	}
-	else if (stricmp(token, "id") == 0)
+	else if (strcmp(token, "id") == 0)
 	{
 	    token = GetToken();
 	    if (!IsNumberString(token))
@@ -531,7 +437,7 @@
 	    
 	    DLLId = atoi(token);
 	}
-	else if (stricmp(token, "length") == 0)
+	else if (strcmp(token, "length") == 0)
 	{
 	    token = GetToken();
 	    if (!IsNumberString(token))
@@ -562,85 +468,14 @@
     return 0;
 }
 
-void
-InitContext(void)
-{
-    struct sigcontext_struct context;
-    int i;
-    
-    n_context_strings = sizeof(context) / 4;
-    context_strings   = (char **) malloc(n_context_strings * sizeof(char **));
-    pop_strings       = (char **) malloc(n_context_strings * sizeof(char **));
-    for (i = 0; i < n_context_strings; i++)
-    {
-	context_strings[i] = PUSH_0;
-	pop_strings[i]     = POP_0;
-    }
 
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_esp) / 4;
-    context_strings[i] = PUSH_ESP;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ebp) / 4;
-    context_strings[i] = PUSH_EBP;
-    pop_strings[n_context_strings - 1 - i] = POP_EBP;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_eip) / 4;
-    context_strings[i] = PUSH_EIP;
-
-#ifndef __FreeBSD__
-    i = n_context_strings - 1 + ((int) &context - (int)&context.sc_eflags) / 4;
-#else
-    i = n_context_strings - 1 + ((int) &context - (int)&context.sc_efl) / 4;
-#endif
-    context_strings[i] = PUSH_EFL;
-    pop_strings[n_context_strings - 1 - i] = POP_EFL;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_es) / 4;
-    context_strings[i] = PUSH_ES;
-    pop_strings[n_context_strings - 1 - i] = POP_ES;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ds) / 4;
-    context_strings[i] = PUSH_DS;
-    pop_strings[n_context_strings - 1 - i] = POP_DS;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_cs) / 4;
-    context_strings[i] = PUSH_CS;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ss) / 4;
-    context_strings[i] = PUSH_SS;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_edi) / 4;
-    context_strings[i] = PUSH_EDI;
-    pop_strings[n_context_strings - 1 - i] = POP_EDI;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_esi) / 4;
-    context_strings[i] = PUSH_ESI;
-    pop_strings[n_context_strings - 1 - i] = POP_ESI;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ebx) / 4;
-    context_strings[i] = PUSH_EBX;
-    pop_strings[n_context_strings - 1 - i] = POP_EBX;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_edx) / 4;
-    context_strings[i] = PUSH_EDX;
-    pop_strings[n_context_strings - 1 - i] = POP_EDX;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_ecx) / 4;
-    context_strings[i] = PUSH_ECX;
-    pop_strings[n_context_strings - 1 - i] = POP_ECX;
-
-    i = n_context_strings - 1 + ((int) &context - (int) &context.sc_eax) / 4;
-    context_strings[i] = PUSH_EAX;
-    pop_strings[n_context_strings - 1 - i] = POP_EAX;
-}
-
-void
-OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
+static int OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
 {
     ORDVARDEF *vdp;
     int i;
 
     vdp = odp->additional_data;
+    fprintf( fp, "\t.data\n" );
     for (i = 0; i < vdp->n_values; i++)
     {
 	if ((i & 7) == 0)
@@ -654,64 +489,24 @@
 	    fprintf(fp, ", ");
     }
     fprintf(fp, "\n");
+    fprintf( fp, "\t.text\n" );
+    return vdp->n_values;
 }
 
-int main(int argc, char **argv)
+static void BuildSpecFiles( char *specname)
 {
     ORDDEF *odp;
     ORDFUNCDEF *fdp;
     ORDRETDEF *rdp;
     FILE *fp;
     char filename[80];
-    int i, ci, add_count, argnum;
-    int prev_index;      /* Index to previous #define (-1 if none) */
+    int i;
+    int code_offset, data_offset;
 
-    /* the difference between last #define and the current */
-    int prev_n_args;
-    
-    if (argc < 2)
-    {
-	fprintf(stderr, "usage: build SPECNAME\n       build -p\n");
-	exit(1);
-    }
-
-    InitContext();
-
-    if (strcmp("-p", argv[1]) == 0)
-    {
-	fp = fopen("pop.h", "w");
-	add_count = 0;
-	for (i = 0; i < n_context_strings; i++)
-	{
-	    if (strncmp(pop_strings[i], "\tadd\t", 5) == 0)
-	    {
-		add_count += atoi(pop_strings[i] + 6);
-	    }
-	    else
-	    {
-		if (add_count > 0)
-		{
-		    fprintf(fp, "\tadd\t$%d,%%esp\n", add_count);
-		    add_count = 0;
-		}
-		
-		fprintf(fp, pop_strings[i]);
-	    }
-	}
-    
-	if (add_count > 0)
-	    fprintf(fp, "\tadd\t$%d,%%esp\n", add_count);
-
-	fprintf(fp, "\tpushl\t%%gs:return_value\n\tpopfl\n");
-		
-	fclose(fp);
-	exit(0);
-    }
-
-    SpecFp = fopen(argv[1], "r");
+    SpecFp = fopen( specname, "r");
     if (SpecFp == NULL)
     {
-	fprintf(stderr, "Could not open specification file, '%s'\n", argv[1]);
+	fprintf(stderr, "Could not open specification file, '%s'\n", specname);
 	exit(1);
     }
 
@@ -719,255 +514,745 @@
 
     sprintf(filename, "dll_%s.S", LowerDLLName);
     fp = fopen(filename, "w");
-#ifdef __ELF__
-    fprintf (fp, "#define __ASSEMBLY__\n");
-    fprintf (fp, "#include <asm/segment.h>\n");
-#endif
+    fprintf( fp, "/* File generated automatically; do not edit! */\n" );
+    fprintf( fp, "\t.data\n" );
+    fprintf( fp, "\t.globl " PREFIX "%s_Data_Start\n", UpperDLLName );
+    fprintf( fp, PREFIX "%s_Data_Start:\n", UpperDLLName );
+    fprintf( fp, "\t.text\n" );
+    fprintf( fp, "\t.globl " PREFIX "%s_Code_Start\n", UpperDLLName );
+    fprintf( fp, PREFIX "%s_Code_Start:\n", UpperDLLName );
+    code_offset = data_offset = 0;
 
     odp = OrdinalDefinitions;
     for (i = 0; i <= Limit; i++, odp++)
     {
-	fprintf(fp, "\t.globl " PREFIX "%s_Ordinal_%d\n", UpperDLLName, i);
-
-	if (!odp->valid)
-	{
-	    fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-	    fprintf(fp, "\tmovl\t$0x%08x,%%eax\n", (DLLId << 16) | i);
-	    fprintf(fp, "\tpushw\t$0\n");
-#ifdef __ELF__
-            fprintf(fp, "\tljmp\t$USER_CS, $" PREFIX "CallTo32\n\n");
-#else
-            fprintf(fp, "\tjmp\t_CallTo32\n\n");
-#endif
-	}
-	else
-	{
-	    fdp = odp->additional_data;
-	    rdp = odp->additional_data;
+        fdp = odp->additional_data;
+        rdp = odp->additional_data;
 	    
-	    switch (odp->type)
-	    {
-	      case EQUATETYPE_ABS:
-		fprintf(fp, PREFIX "%s_Ordinal_%d = %d\n\n", 
-			UpperDLLName, i, (int) odp->additional_data);
-		break;
+        switch (odp->type)
+        {
+          case TYPE_INVALID:
+            fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
+            fprintf( fp, "\tpushw %%bp\n" );
+            fprintf( fp, "\tpushl $0x%08x\n", (DLLId << 16) | i);
+            fprintf( fp, "\tpushl $" PREFIX "RELAY_Unimplemented\n" );
+            fprintf( fp, "\tljmp $0x%04x, $" PREFIX "CallTo32_word_\n",
+                         WINE_CODE_SELECTOR );
+            odp->offset = code_offset;
+            code_offset += 19;  /* Assembly code is 19 bytes long */
+            break;
 
-	      case VARTYPE_BYTE:
-                fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-		OutputVariableCode(fp, ".byte", odp);
-		break;
+          case TYPE_ABS:
+            odp->offset = (int)odp->additional_data & 0xffff;
+            break;
 
-	      case VARTYPE_WORD:
-                fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-		OutputVariableCode(fp, ".word", odp);
-		break;
+          case TYPE_BYTE:
+            fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
+            odp->offset = data_offset;
+            data_offset += OutputVariableCode(fp, ".byte", odp);
+            break;
 
-	      case VARTYPE_LONG:
-                fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-		OutputVariableCode(fp, ".long", odp);
-		break;
+          case TYPE_WORD:
+            fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
+            odp->offset = data_offset;
+            data_offset += 2 * OutputVariableCode(fp, ".word", odp);
+            break;
 
-	      case TYPE_RETURN:
-		fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-		fprintf(fp, "\tmovw\t$%d,%%ax\n", rdp->ret_value & 0xffff);
-		fprintf(fp, "\tmovw\t$%d,%%dx\n", 
-			(rdp->ret_value >> 16) & 0xffff);
-		fprintf(fp, "\t.byte\t0x66\n");
-		if (rdp->arg_size != 0)
-		    fprintf(fp, "\tlret\t$%d\n", rdp->arg_size);
-		else
-		    fprintf(fp, "\tlret\n");
-		break;
+          case TYPE_LONG:
+            fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
+            odp->offset = data_offset;
+            data_offset += 4 * OutputVariableCode(fp, ".long", odp);
+            break;
 
-	      case FUNCTYPE_REG:
-		fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-		fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-		fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
+          case TYPE_RETURN:
+            fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
+            fprintf( fp, "\tmovw $%d,%%ax\n", rdp->ret_value & 0xffff );
+            fprintf( fp, "\tmovw $%d,%%dx\n", (rdp->ret_value >> 16) & 0xffff);
+            fprintf(fp, "\t.byte 0x66\n");
+            if (rdp->arg_size != 0)
+                fprintf(fp, "\tlret $%d\n", rdp->arg_size);
+            else
+                fprintf(fp, "\tlret\n");
+            odp->offset = code_offset;
+            code_offset += 10;  /* Assembly code is 10 bytes long */
+            if (rdp->arg_size != 0) code_offset += 2;
+            break;
 
-		for (ci = 0; ci < n_context_strings; ci++)
-		    fprintf(fp, context_strings[ci]);
-
-		fprintf(fp, "\tmovl\t%%ebp,%%eax\n");
-		fprintf(fp, "\tmovw\t%%esp,%%ebp\n");
-		fprintf(fp, "\tpushl\t%d(%%ebp)\n",
-			sizeof(struct sigcontext_struct));
-		fprintf(fp, "\tmovl\t%%eax,%%ebp\n");
-                fprintf(fp, "\tmovl\t$0x%08x,%%eax\n", (DLLId << 16) | i);
-		fprintf(fp, "\tpushw\t$%d\n", 
-			sizeof(struct sigcontext_struct) + 4);
-#ifdef __ELF__
-                fprintf(fp, "\tljmp\t$USER_CS, $" PREFIX "CallTo32\n\n");
-#else
-                fprintf(fp, "\tjmp\t_CallTo32\n\n");
-#endif
-		break;
-
-	      case FUNCTYPE_PASCAL:
-		fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-                fprintf(fp, "\tmovl\t$0x%08x,%%eax\n", (DLLId << 16) | i);
-		fprintf(fp, "\tpushw\t$%d\n", fdp->arg_16_size);
-#ifdef __ELF__
-                fprintf(fp, "\tljmp\t$USER_CS, $" PREFIX "CallTo32\n\n");
-#else
-                fprintf(fp, "\tjmp\t_CallTo32\n\n");
-#endif
-                break;
+          case TYPE_REGISTER:
+          case TYPE_PASCAL:
+          case TYPE_PASCAL_16:
+            fprintf( fp, "/* %s.%d */\n", UpperDLLName, i);
+            fprintf(fp, "\tpushw %%bp\n" );
+            fprintf(fp, "\tpushl $0x%08x\n", (DLLId << 16) | i);
+            fprintf(fp, "\tpushl $" PREFIX "%s\n", fdp->internal_name );
+            fprintf(fp, "\tljmp $0x%04x, $" PREFIX "CallTo32_%s_%s\n\n",
+                        WINE_CODE_SELECTOR,
+                        (odp->type == TYPE_REGISTER) ? "regs" :
+                        (odp->type == TYPE_PASCAL) ? "long" : "word",
+                        fdp->arg_types );
+            odp->offset = code_offset;
+            code_offset += 19;  /* Assembly code is 19 bytes long */
+            break;
 		
-	      case FUNCTYPE_PASCAL_16:
-		fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-                fprintf(fp, "\tmovl\t$0x%08x,%%eax\n", (DLLId << 16) | i);
-		fprintf(fp, "\tpushw\t$%d\n", fdp->arg_16_size);
-#ifdef __ELF__
-                fprintf(fp, "\tljmp\t$USER_CS, $" PREFIX "CallTo32_16\n\n");
-#else
-                fprintf(fp, "\tjmp\t_CallTo32_16\n\n");
-#endif
-		break;
-		
-	      default:
-		fprintf(fp, PREFIX "%s_Ordinal_%d:\n", UpperDLLName, i);
-                fprintf(fp, "\tmovl\t$0x%08x,%%eax\n", (DLLId << 16) | i);
-		fprintf(fp, "\tpushw\t$0\n");
-#ifdef __ELF__
-                fprintf(fp, "\tljmp\t$USER_CS, $" PREFIX "CallTo32\n\n");
-#else
-                fprintf(fp, "\tjmp\t_CallTo32\n\n");
-#endif
-		break;
-	    }
+          default:
+            fprintf( stderr, "build: Unknown function type; please report.\n");
+            break;
 	}
     }
 
+    fprintf( fp, "\t.data\n" );
+    fprintf( fp, "\t.globl " PREFIX "%s_Data_End\n", UpperDLLName );
+    fprintf( fp, PREFIX "%s_Data_End:\n", UpperDLLName );
+    fprintf( fp, "\t.text\n" );
+    fprintf( fp, "\t.globl " PREFIX "%s_Code_End\n", UpperDLLName );
+    fprintf( fp, PREFIX "%s_Code_End:\n", UpperDLLName );
+
     fclose(fp);
 
-#ifndef SHORTNAMES
-    sprintf(filename, "dll_%s_tab.c", LowerDLLName);
-#else
-    sprintf(filename, "dtb_%s.c", LowerDLLName);
-#endif
+    sprintf(filename, "tab_%s.c", LowerDLLName);
     fp = fopen(filename, "w");
 
-    fprintf(fp, "#include <stdio.h>\n");
-    fprintf(fp, "#include <stdlib.h>\n");
-    fprintf(fp, "#include \042dlls.h\042\n\n");
-
-    for (i = 0; i <= Limit; i++)
-    {
-	fprintf(fp, "extern void %s_Ordinal_%d();\n", UpperDLLName, i);
-    }
-    
+    fprintf( fp, "/* File generated automatically; do not edit! */\n\n" );
+    fprintf( fp, "#include \"dlls.h\"\n\n" );
+    fprintf( fp, "static struct dll_table_entry_s %s_table_entries[%d] =\n{\n",
+                 UpperDLLName, Limit + 1);
     odp = OrdinalDefinitions;
     for (i = 0; i <= Limit; i++, odp++)
     {
-	if (odp->valid && 
-	    (odp->type == FUNCTYPE_PASCAL || odp->type == FUNCTYPE_PASCAL_16 ||
-	     odp->type == FUNCTYPE_REG))
-	{
-	    fdp = odp->additional_data;
-	    fprintf(fp, "extern int %s();\n", fdp->internal_name);
-	}
-    }
-    /******* Michael Veksler 95-2-3 (pointers instead of fixed data) ****/
-    fprintf(fp,"unsigned short  %s_offsets[]={\n" , UpperDLLName);
-    prev_index=-1;  /* Index to previous #define (-1 if none) */
+        int selector;
 
-    /* the difference between last #define and the current */
-    prev_n_args= 0;
-    
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
-    {
 	fdp = odp->additional_data;
 
 	switch (odp->type)
 	{
-	  case FUNCTYPE_PASCAL:
-	  case FUNCTYPE_PASCAL_16:
-	  case FUNCTYPE_REG:
-            if (!odp->valid || fdp->n_args_16 <= 0) continue;
-            if (prev_index<0) 
-                fprintf(fp,"#\tdefine %s_ref_%d   0\n\t", UpperDLLName, i);
-            else
-                fprintf(fp,"#\tdefine %s_ref_%d   %s_ref_%d+%d\n\t",
-                        UpperDLLName,i, UpperDLLName,prev_index ,prev_n_args);
-            for (argnum = 0; argnum < fdp->n_args_16; argnum++)
-                fprintf(fp, "%d, ", fdp->arg_16_offsets[argnum]);
-            fprintf(fp,"\n");
-	    
-            prev_n_args=fdp->n_args_16;
-            prev_index=i;
+        case TYPE_INVALID:
+        case TYPE_PASCAL:
+        case TYPE_PASCAL_16:
+        case TYPE_REGISTER:
+            selector = 1;  /* Code selector */
+            break;
+
+        case TYPE_BYTE:
+        case TYPE_WORD:
+        case TYPE_LONG:
+            selector = 2;  /* Data selector */
+            break;
+
+        case TYPE_ABS:
+            selector = 0xff;  /* Constant selector */
+            break;
         }
-    }    
-    fprintf(fp,"};\n");
 
-
-    fprintf(fp,"unsigned char  %s_types[]={\n" , UpperDLLName);
-
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
-    {
-	int argnum;
-
-	fdp = odp->additional_data;
-
-	switch (odp->type)
-	{
-	  case FUNCTYPE_PASCAL:
-	  case FUNCTYPE_PASCAL_16:
-	  case FUNCTYPE_REG:
-            if (!odp->valid || fdp->n_args_16 <= 0) continue;
-	    
-            fprintf(fp,"/* %s_%d */\n\t", UpperDLLName, i);
-	    
-            for (argnum = 0; argnum < fdp->n_args_16; argnum++)
-                fprintf(fp, "%d, ", fdp->arg_types_16[argnum]);
-            fprintf(fp,"\n");
-        }
-    }    
-    fprintf(fp,"};\n");
-
-
-    /**************************************************/
-    fprintf(fp, "\nstruct dll_table_entry_s %s_table[%d] =\n", 
-	    UpperDLLName, Limit + 1);
-    fprintf(fp, "{\n");
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
-    {
-	fdp = odp->additional_data;
-
-	if (!odp->valid)
-	    odp->type = -1;
-	
-	switch (odp->type)
-	{
-	  case FUNCTYPE_PASCAL:
-	  case FUNCTYPE_PASCAL_16:
-	  case FUNCTYPE_REG:
-	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
-	    fprintf(fp, "\042%s\042, ", odp->export_name);
-	    fprintf(fp, "%s, ", fdp->internal_name);
-	    fprintf(fp, "%d, ", fdp->n_args_16);
-	    if (fdp->n_args_16 > 0)
-	       fprintf(fp,"%s_ref_%d", UpperDLLName, i);
-	    else
-	       fprintf(fp,"      0    ");
-	       
+        fprintf(fp, "    { %d, %d, ", selector, odp->offset );
+        fprintf(fp, "\"%s\" ", odp->export_name);
 #ifdef WINESTAT
-	    fprintf(fp, ",0 ");
+        fprintf(fp, ",0 ");
 #endif	    
-	    fprintf(fp, "}, \n");
-	    break;
-		
-	  default:
-	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, \042\042, NULL },\n", 
-		    UTEXTSEL, UpperDLLName, i);
-	    break;
-	}
+        fprintf(fp, "}, \n");
     }
-    fprintf(fp, "};\n");
 
+    fprintf(fp, "};\n\n");
+
+    fprintf( fp, "extern void %s_Code_Start();\n", UpperDLLName );
+    fprintf( fp, "extern void %s_Code_End();\n", UpperDLLName );
+    fprintf( fp, "extern void %s_Data_Start();\n", UpperDLLName );
+    fprintf( fp, "extern void %s_Data_End();\n\n", UpperDLLName );
+    fprintf( fp, "struct dll_table_s %s_table =\n{\n", UpperDLLName );
+    fprintf( fp, "  %s_table_entries, %d, %d,\n",
+             UpperDLLName, Limit + 1, DLLId );
+    fprintf( fp, "  (void *)%s_Code_Start, (void *)%s_Code_End,\n",
+             UpperDLLName, UpperDLLName );
+    fprintf( fp, "  (void *)%s_Data_Start, (void *)%s_Data_End\n};\n",
+             UpperDLLName, UpperDLLName );
     fclose(fp);
-    return 0;
 }
 
+
+/*******************************************************************
+ *         TransferArgs16To32
+ *
+ * Get the arguments from the 16-bit stack and push them on the 32-bit stack.
+ * The 16-bit stack layout is:
+ *   ...     ...
+ *  (bp+8)    arg2
+ *  (bp+6)    arg1
+ *  (bp+4)    cs
+ *  (bp+2)    ip
+ *  (bp)      bp
+ */
+static int TransferArgs16To32( char *args )
+{
+    int i, pos16, pos32;
+
+    /* Save ebx first */
+
+    printf( "\tpushl %%ebx\n" );
+
+    /* Get the 32-bit stack pointer */
+
+    printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%ebx\n" );
+
+    /* Copy the arguments */
+
+    pos16 = 6;  /* skip bp and return address */
+    pos32 = 0;
+
+    for (i = strlen(args); i > 0; i--)
+    {
+        pos32 -= 4;
+        switch(args[i-1])
+        {
+        case 'w':  /* word */
+            printf( "\tmovzwl %d(%%ebp),%%eax\n", pos16 );
+            printf( "\tmovl %%eax,%d(%%ebx)\n", pos32 );
+            pos16 += 2;
+            break;
+
+        case 's':  /* s_word */
+            printf( "\tmovswl %d(%%ebp),%%eax\n", pos16 );
+            printf( "\tmovl %%eax,%d(%%ebx)\n", pos32 );
+            pos16 += 2;
+            break;
+
+        case 'l':  /* long */
+            printf( "\tmovl %d(%%ebp),%%eax\n", pos16 );
+            printf( "\tmovl %%eax,%d(%%ebx)\n", pos32 );
+            pos16 += 4;
+            break;
+
+        case 'p':  /* ptr */
+            /* Get the selector */
+            printf( "\tmovw %d(%%ebp),%%ax\n", pos16 + 2 );
+            /* Get the selector base */
+            printf( "\tandl $0xfff8,%%eax\n" );
+            printf( "\tmovl " PREFIX "ldt_copy(%%eax),%%eax\n" );
+            printf( "\tmovl %%eax,%d(%%ebx)\n", pos32 );
+            /* Add the offset */
+            printf( "\tmovzwl %d(%%ebp),%%eax\n", pos16 );
+            printf( "\taddl %%eax,%d(%%ebx)\n", pos32 );
+            pos16 += 4;
+            break;
+
+        default:
+            fprintf( stderr, "Unknown arg type '%c'\n", args[i-1] );
+        }
+    }
+
+    /* Restore ebx */
+    
+    printf( "\tpopl %%ebx\n" );
+
+    return pos16 - 6;  /* Return the size of the 16-bit args */
+}
+
+
+/*******************************************************************
+ *         BuildContext
+ *
+ * Build the context structure on the 32-bit stack.
+ * The only valid registers in the context structure are:
+ *   eax, ebx, ecx, edx, esi, edi, ds, es, (some of the) flags
+ */
+static void BuildContext(void)
+{
+    /* Save ebx first */
+
+    printf( "\tpushl %%ebx\n" );
+
+    /* Get the 32-bit stack pointer */
+
+    printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%ebx\n" );
+
+    /* Store the registers */
+
+    printf( "\tpopl %d(%%ebx)\n", CONTEXTOFFSET(sc_ebx) ); /* Get ebx from stack */
+    printf( "\tmovl %%eax,%d(%%ebx)\n", CONTEXTOFFSET(sc_eax) );
+    printf( "\tmovl %%ecx,%d(%%ebx)\n", CONTEXTOFFSET(sc_ecx) );
+    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( "\tmovw %%es,%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( "\tpushfl\n" );
+#ifndef __FreeBSD__
+    printf( "\tpopl %d(%%ebx)\n", CONTEXTOFFSET(sc_eflags) );
+#else    
+    printf( "\tpopl %d(%%ebx)\n", CONTEXTOFFSET(sc_efl) );
+#endif
+}
+
+
+/*******************************************************************
+ *         RestoreContext
+ *
+ * Restore the registers from the context structure
+ */
+static void RestoreContext(void)
+{
+    /* Get the 32-bit stack pointer */
+
+    printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%ebx\n" );
+
+    /* Restore the registers */
+
+    printf( "\tmovl %d(%%ebx),%%ecx\n", CONTEXTOFFSET(sc_ecx) );
+    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( "\tmovw %d(%%ebx),%%es\n", CONTEXTOFFSET(sc_es) );
+    printf( "\tpopw %%ax\n" );  /* Remove old ds from the stack */
+    printf( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(sc_ds) ); /* Push new ds */
+#ifndef __FreeBSD__
+    printf( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(sc_eflags) );
+#else    
+    printf( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(sc_efl) );
+#endif
+    printf( "\tpopfl\n" );
+    printf( "\tmovl %d(%%ebx),%%eax\n", CONTEXTOFFSET(sc_eax) );
+    printf( "\tmovl %d(%%ebx),%%ebx\n", CONTEXTOFFSET(sc_ebx) );
+}
+
+
+/*******************************************************************
+ *         BuildCall32Func
+ *
+ * Build a 32-bit callback function. The syntax of the function
+ * profile is: type_xxxxx, where 'type' is one of 'regs', 'word' or
+ * 'long' and each 'x' is an argument ('w'=word, 's'=signed word,
+ * 'l'=long, 'p'=pointer).
+ *
+ * Stack layout upon entry to the callback function:
+ *  ...      ...
+ * (sp+14)  first 16-bit arg
+ * (sp+12)  cs (word)
+ * (sp+10)  ip (word)
+ * (sp+8)   bp (word)
+ * (sp+4)   dll_id+ordinal (long)
+ * (sp)     entrypoint (long)
+ *
+ */
+static void BuildCall32Func( char *profile )
+{
+    int argsize = 0;
+    int short_ret = 0;
+    int reg_func = 0;
+    char *args = profile + 5;
+
+    /* Parse function type */
+
+    if (!strncmp( "word_", profile, 5 )) short_ret = 1;
+    else if (!strncmp( "regs_", profile, 5 )) reg_func = 1;
+    else if (strncmp( "long_", profile, 5 ))
+    {
+        fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
+        return;
+    }
+
+    /* Function header */
+
+    printf( "/**********\n" );
+    printf( " * " PREFIX "CallTo32_%s\n", profile );
+    printf( " **********/\n" );
+    printf( "\t.align 4\n" );
+    printf( "\t.global " PREFIX "CallTo32_%s\n\n", profile );
+    printf( PREFIX "CallTo32_%s:\n", profile );
+
+    /* Setup bp to point to its copy on the stack */
+
+    printf( "\tmovzwl %%sp,%%ebp\n" );
+    printf( "\taddw $8,%%bp\n" );
+
+    /* Save 16-bit ds */
+
+    printf( "\tpushw %%ds\n" );
+
+    /* Restore 32-bit ds */
+
+    printf( "\tpushw $0x%04x\n", WINE_DATA_SELECTOR );
+    printf( "\tpopw %%ds\n" );
+
+    /* Save the 16-bit stack */
+
+    printf( "\tpushw " PREFIX "IF1632_Saved16_bp\n" );
+    printf( "\tpushw " PREFIX "IF1632_Saved16_sp\n" );
+    printf( "\tpushw " PREFIX "IF1632_Saved16_ss\n" );
+    printf( "\tmovw %%ss," PREFIX "IF1632_Saved16_ss\n" );
+    printf( "\tmovw %%sp," PREFIX "IF1632_Saved16_sp\n" );
+    printf( "\tmovw %%bp," PREFIX "IF1632_Saved16_bp\n" );
+
+    /* Transfer the arguments */
+
+    if (reg_func) BuildContext();
+    else if (*args) argsize = TransferArgs16To32( args );
+
+    /* Get the address of the API function */
+
+    printf( "\tmovl -8(%%ebp),%%eax\n" );
+
+    /* Setup es */
+
+    printf( "\tpushw %%ds\n" );
+    printf( "\tpopw %%es\n" );
+
+    /* Switch to the 32-bit stack */
+
+    printf( "\tpushw %%ds\n" );
+    printf( "\tpopw %%ss\n" );
+    printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%esp\n" );
+    printf( "\tmovl " PREFIX "IF1632_Saved32_ebp,%%ebp\n" );
+    if (reg_func)
+        printf( "\tsubl $%d,%%esp\n", sizeof(struct sigcontext_struct) );
+    else if (*args)
+        printf( "\tsubl $%d,%%esp\n", 4 * strlen(args) );
+
+    /* Call the entry point */
+
+    if (debugging)
+    {
+        printf( "\tpushl %%eax\n" );
+        printf( "\tpushl $CALL32_Str_%s\n", profile );
+        printf( "\tcall " PREFIX "RELAY_DebugCall32\n" );
+        printf( "\tpopl %%eax\n" );
+        printf( "\tpopl %%eax\n" );
+    }
+
+    printf( "\tcall %%eax\n" );
+
+    if (debugging)
+    {
+        printf( "\tpushl %%eax\n" );
+        printf( "\tpushl $%d\n", short_ret );
+        printf( "\tcall " PREFIX "RELAY_DebugReturn\n" );
+        printf( "\tpopl %%eax\n" );
+        printf( "\tpopl %%eax\n" );
+    }
+
+    if (reg_func)
+        printf( "\taddl $%d,%%esp\n", sizeof(struct sigcontext_struct) );
+    else if (*args)
+        printf( "\taddl $%d,%%esp\n", 4 * strlen(args) );
+
+    /* Restore the 16-bit stack */
+
+    printf( "\tmovw " PREFIX "IF1632_Saved16_ss,%%ss\n" );
+    printf( "\tmovw " PREFIX "IF1632_Saved16_sp,%%sp\n" );
+    printf( "\tmovw " PREFIX "IF1632_Saved16_bp,%%bp\n" );
+    printf( "\tpopw " PREFIX "IF1632_Saved16_ss\n" );
+    printf( "\tpopw " PREFIX "IF1632_Saved16_sp\n" );
+    printf( "\tpopw " PREFIX "IF1632_Saved16_bp\n" );
+
+    /* Restore registers from the context structure */
+
+    if (reg_func)
+    {
+        printf( "\tandl $0xffff,%%ebp\n" );
+        RestoreContext();
+    }
+    else  /* Store the return value in dx:ax if needed */
+    {
+        if (!short_ret)
+        {
+            printf( "\tpushl %%eax\n" );
+            printf( "\tpopw %%dx\n" );
+            printf( "\tpopw %%dx\n" );
+        }
+    }
+
+    /* Restore ds and bp */
+
+    printf( "\tpopw %%ds\n" );
+    printf( "\tmovw %%bp,%%sp\n" );
+    printf( "\tpopw %%bp\n" );
+
+    /* Remove the arguments and return */
+
+    if (argsize)
+    {
+        printf( "\t.byte 0x66\n" );
+        printf( "\tlret $%d\n", argsize );
+    }
+    else
+    {
+        printf( "\t.byte 0x66\n" );
+        printf( "\tlret\n" );
+    }
+}
+
+
+/*******************************************************************
+ *         BuildCall16Func
+ *
+ * Build a 16-bit callback function.
+ *
+ * Stack frame of the callback function:
+ *  ...      ...
+ * (ebp+22) arg2
+ * (ebp+18) arg1
+ * (ebp+14) 16-bit ds
+ * (ebp+10) func to call
+ * (ebp+8)  code selector
+ * (ebp+4)  return address
+ * (ebp)    previous ebp
+ *
+ * Prototypes for the CallTo16 functions:
+ *   extern WORD CallTo16_word_xxx( FARPROC func, WORD ds, args... );
+ *   extern LONG CallTo16_long_xxx( FARPROC func, WORD ds, args... );
+ *   extern void CallTo16_regs_( FARPROC func, WORD ds, WORD es, WORD ax,
+ *                               WORD bx, WORD cx, WORD dx, WORD si, WORD di );
+ */
+static void BuildCall16Func( char *profile )
+{
+    int short_ret = 0;
+    int reg_func = 0;
+    char *args = profile + 5;
+
+    if (!strncmp( "word_", profile, 5 )) short_ret = 1;
+    else if (!strncmp( "regs_", profile, 5 )) reg_func = short_ret = 1;
+    else if (strncmp( "long_", profile, 5 ))
+    {
+        fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
+        return;
+    }
+
+    /* Function header */
+
+    printf( "/**********\n" );
+    printf( " * " PREFIX "CallTo16_%s\n", profile );
+    printf( " **********/\n" );
+    printf( "\t.align 4\n" );
+    printf( "\t.global " PREFIX "CallTo16_%s\n\n", profile );
+    printf( PREFIX "CallTo16_%s:\n", profile );
+
+    /* Push code selector before return address to simulate a lcall */
+
+    printf( "\tpopl %%eax\n" );
+    printf( "\tpushw $0x%04x\n", WINE_CODE_SELECTOR );
+    printf( "\tpushl %%eax\n" );
+
+    /* Entry code */
+
+    printf( "\tpushl %%ebp\n" );
+    printf( "\tmovl %%esp,%%ebp\n" );
+
+    /* Save the 32-bit registers */
+
+    printf( "\tpushl %%ebx\n" );
+    printf( "\tpushl %%ecx\n" );
+    printf( "\tpushl %%edx\n" );
+    printf( "\tpushl %%esi\n" );
+    printf( "\tpushl %%edi\n" );
+
+    /* Save the 32-bit stack */
+
+    printf( "\tpushl " PREFIX "IF1632_Saved32_esp\n" );
+    printf( "\tpushl " PREFIX "IF1632_Saved32_ebp\n" );
+    printf( "\tmovl %%esp," PREFIX "IF1632_Saved32_esp\n" );
+    printf( "\tmovl %%ebp," PREFIX "IF1632_Saved32_ebp\n" );
+    printf( "\tmovl %%ebp,%%ebx\n" );
+
+    /* Print debugging info */
+
+    if (debugging)
+    {
+        /* Push the address of the first argument */
+        printf( "\tmovl %%ebx,%%eax\n" );
+        printf( "\taddl $10,%%eax\n" );
+        printf( "\tpushl $%d\n", reg_func ? 7 : strlen(args) );
+        printf( "\tpushl %%eax\n" );
+        printf( "\tcall " PREFIX "RELAY_DebugCall16\n" );
+        printf( "\tpopl %%eax\n" );
+        printf( "\tpopl %%eax\n" );
+    }
+
+    /* Switch to the 16-bit stack */
+
+    printf( "\tmovw " PREFIX "IF1632_Saved16_ss,%%ss\n" );
+    printf( "\tmovw " PREFIX "IF1632_Saved16_sp,%%sp\n" );
+    printf( "\tmovzwl " PREFIX "IF1632_Saved16_bp,%%ebp\n" );
+
+    /* Transfer the arguments */
+
+    if (reg_func)
+    {
+        /* Get the registers. ebx is handled later on. */
+        printf( "\tmovl 18(%%ebx),%%es\n" );
+        printf( "\tmovl 22(%%ebx),%%eax\n" );
+        printf( "\tmovl 30(%%ebx),%%ecx\n" );
+        printf( "\tmovl 34(%%ebx),%%edx\n" );
+        printf( "\tmovl 38(%%ebx),%%esi\n" );
+        printf( "\tmovl 42(%%ebx),%%edi\n" );
+    }
+    else  /* not a register function */
+    {
+        int pos = 18;  /* first argument position */
+        while (*args)
+        {
+            switch(*args++)
+            {
+            case 'w': /* word */
+                printf( "\tpushw %d(%%ebx)\n", pos );
+                break;
+            case 'l': /* long */
+                printf( "\tpushl %d(%%ebx)\n", pos );
+                break;
+            }
+            pos += 4;
+        }
+    }
+
+    /* Push the return address */
+
+    printf( "\tpushl " PREFIX "CALL16_RetAddr_%s\n",
+            short_ret ? "word" : "long" );
+
+    /* Push the called routine address */
+
+    printf( "\tpushl 10(%%ebx)\n" );
+
+    /* Get the 16-bit ds */
+    /* FIXME: this shouldn't be necessary if function prologs fixup worked. */
+
+    printf( "\tmovw 14(%%ebx),%%ds\n" );
+
+    if (reg_func)
+    {
+        /* Retrieve ebx from the 32-bit stack */
+        printf( "\tmovl %%fs:26(%%ebx),%%ebx\n" );
+    }
+    else
+    {
+        /* Set ax equal to ds for window procedures */
+        printf( "\tmovw %%ds,%%ax\n" );
+    }
+
+    /* Jump to the called routine */
+
+    printf( "\t.byte 0x66\n" );
+    printf( "\tlret\n" );
+}
+
+
+/*******************************************************************
+ *         BuildRet16Func
+ *
+ * Build the return code for 16-bit callbacks
+ */
+static void BuildRet16Func()
+{
+    printf( "\t.globl " PREFIX "CALL16_Ret_word\n" );
+    printf( "\t.globl " PREFIX "CALL16_Ret_long\n" );
+
+    /* Put return value into eax */
+
+    printf( PREFIX "CALL16_Ret_long:\n" );
+    printf( "\tpushw %%dx\n" );
+    printf( "\tpushw %%ax\n" );
+    printf( "\tpopl %%eax\n" );
+    printf( PREFIX "CALL16_Ret_word:\n" );
+
+    /* Restore 32-bit segment registers */
+
+    printf( "\tmovw $0x%04x,%%bx\n", WINE_DATA_SELECTOR );
+    printf( "\tmovw %%bx,%%ds\n" );
+    printf( "\tmovw %%bx,%%es\n" );
+    printf( "\tmovw %%bx,%%ss\n" );
+
+    /* Restore the 32-bit stack */
+
+    printf( "\tmovl " PREFIX "IF1632_Saved32_esp,%%esp\n" );
+    printf( "\tmovl " PREFIX "IF1632_Saved32_ebp,%%ebp\n" );
+    printf( "\tpopl " PREFIX "IF1632_Saved32_ebp\n" );
+    printf( "\tpopl " PREFIX "IF1632_Saved32_esp\n" );
+
+    /* Restore the 32-bit registers */
+
+    printf( "\tpopl %%edi\n" );
+    printf( "\tpopl %%esi\n" );
+    printf( "\tpopl %%edx\n" );
+    printf( "\tpopl %%ecx\n" );
+    printf( "\tpopl %%ebx\n" );
+
+    /* Return to caller */
+
+    printf( "\tmovl %%ebp,%%esp\n" );
+    printf( "\tpopl %%ebp\n" );
+    printf( "\tlret\n" );
+
+    /* Declare the return address variables */
+
+    printf( "\t.data\n" );
+    printf( "\t.globl " PREFIX "CALL16_RetAddr_word\n" );
+    printf( "\t.globl " PREFIX "CALL16_RetAddr_long\n" );
+    printf( PREFIX "CALL16_RetAddr_word:\t.long 0\n" );
+    printf( PREFIX "CALL16_RetAddr_long:\t.long 0\n" );
+    printf( "\t.text\n" );
+}
+
+
+static void usage(void)
+{
+    fprintf(stderr, "usage: build -spec SPECNAMES\n"
+                    "       build -call32 FUNCTION_PROFILES\n"
+                    "       build -call16 FUNCTION_PROFILES\n" );
+    exit(1);
+}
+
+
+int main(int argc, char **argv)
+{
+    int i;
+
+    if (argc <= 2) usage();
+
+    if (!strcmp( argv[1], "-spec" ))
+    {
+        for (i = 2; i < argc; i++) BuildSpecFiles( argv[i] );
+    }
+    else if (!strcmp( argv[1], "-call32" ))  /* 32-bit callbacks */
+    {
+        /* File header */
+
+        printf( "/* File generated automatically. Do no edit! */\n\n" );
+        printf( "\t.text\n" );
+
+        /* Build the callback functions */
+
+        for (i = 2; i < argc; i++) BuildCall32Func( argv[i] );
+
+        /* Output the argument debugging strings */
+
+        if (debugging)
+        {
+            printf( "/* Argument strings */\n" );
+            for (i = 2; i < argc; i++)
+            {
+                printf( "CALL32_Str_%s:\n", argv[i] );
+                printf( "\t.ascii \"%s\\0\"\n", argv[i] + 5 );
+            }
+        }
+    }
+    else if (!strcmp( argv[1], "-call16" ))  /* 16-bit callbacks */
+    {
+        /* File header */
+
+        printf( "/* File generated automatically. Do no edit! */\n\n" );
+        printf( "\t.text\n" );
+        printf( "\t.globl " PREFIX "CALL16_Start\n" );
+        printf( PREFIX "CALL16_Start:\n" );
+
+        /* Build the callback functions */
+
+        for (i = 2; i < argc; i++) BuildCall16Func( argv[i] );
+
+        /* Output the 16-bit return code */
+
+        BuildRet16Func();
+
+        printf( "\t.globl " PREFIX "CALL16_End\n" );
+        printf( PREFIX "CALL16_End:\n" );
+    }
+    else usage();
+
+    return 0;
+}
diff --git a/tools/newbuild.c b/tools/newbuild.c
deleted file mode 100644
index f9f8e42..0000000
--- a/tools/newbuild.c
+++ /dev/null
@@ -1,958 +0,0 @@
-static char RCSId[] = "$Id: build.c,v 1.3 1993/07/04 04:04:21 root Exp root $";
-static char Copyright[] = "Copyright  Robert J. Amstadt, 1993";
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#ifdef linux
-#ifdef __ELF__
-#define UTEXTSEL 	0x0f
-#else
-#define UTEXTSEL 	0x23
-#endif
-#define UDATASEL	0x2b
-#endif
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#define UTEXTSEL 	0x1f
-#define UDATASEL	0x27
-#endif
-
-#define VARTYPE_BYTE	0
-#define VARTYPE_SIGNEDWORD	0
-#define VARTYPE_WORD	1
-#define VARTYPE_LONG	2
-#define VARTYPE_FARPTR	3
-
-#define FUNCTYPE_PASCAL	16
-#define FUNCTYPE_C	17
-#define FUNCTYPE_REG	19
-
-#define EQUATETYPE_ABS	18
-#define TYPE_RETURN	20
-
-#define MAX_ORDINALS	1024
-
-typedef struct ordinal_definition_s
-{
-    int valid;
-    int type;
-    char export_name[80];
-    void *additional_data;
-} ORDDEF;
-
-typedef struct ordinal_variable_definition_s
-{
-    int n_values;
-    int *values;
-} ORDVARDEF;
-
-typedef struct ordinal_function_definition_s
-{
-    int n_args_16;
-    int arg_types_16[16];
-    int arg_16_offsets[16];
-    int arg_16_size;
-    char internal_name[80];
-    int n_args_32;
-    int arg_indices_32[16];
-} ORDFUNCDEF;
-
-typedef struct ordinal_return_definition_s
-{
-    int arg_size;
-    int ret_value;
-} ORDRETDEF;
-
-ORDDEF OrdinalDefinitions[MAX_ORDINALS];
-
-char LowerDLLName[80];
-char UpperDLLName[80];
-int Limit;
-int DLLId;
-FILE *SpecFp;
-
-char *ParseBuffer = NULL;
-char *ParseNext;
-char ParseSaveChar;
-int Line;
-
-int IsNumberString(char *s)
-{
-    while (*s != '\0')
-	if (!isdigit(*s++))
-	    return 0;
-
-    return 1;
-}
-
-char *strlower(char *s)
-{
-    char *p;
-    
-    for(p = s; *p != '\0'; p++)
-	*p = tolower(*p);
-
-    return s;
-}
-
-char *strupper(char *s)
-{
-    char *p;
-    
-    for(p = s; *p != '\0'; p++)
-	*p = toupper(*p);
-
-    return s;
-}
-
-int stricmp(char *s1, char *s2)
-{
-    if (strlen(s1) != strlen(s2))
-	return -1;
-    
-    while (*s1 != '\0')
-	if (*s1++ != *s2++)
-	    return -1;
-    
-    return 0;
-}
-
-char *
-GetTokenInLine(void)
-{
-    char *p;
-    char *token;
-
-    if (ParseNext != ParseBuffer)
-    {
-	if (ParseSaveChar == '\0')
-	    return NULL;
-	*ParseNext = ParseSaveChar;
-    }
-    
-    /*
-     * Remove initial white space.
-     */
-    for (p = ParseNext; isspace(*p); p++)
-	;
-    
-    if (*p == '\0')
-	return NULL;
-    
-    /*
-     * Find end of token.
-     */
-    token = p++;
-    if (*token != '(' && *token != ')')
-	while (*p != '\0' && *p != '(' && *p != ')' && !isspace(*p))
-	    p++;
-    
-    ParseSaveChar = *p;
-    ParseNext = p;
-    *p = '\0';
-
-    return token;
-}
-
-char *
-GetToken(void)
-{
-    char *token;
-
-    if (ParseBuffer == NULL)
-    {
-	ParseBuffer = malloc(512);
-	ParseNext = ParseBuffer;
-	Line++;
-	while (1)
-	{
-	    if (fgets(ParseBuffer, 511, SpecFp) == NULL)
-		return NULL;
-	    if (ParseBuffer[0] != '#')
-		break;
-	}
-    }
-
-    while ((token = GetTokenInLine()) == NULL)
-    {
-	ParseNext = ParseBuffer;
-	Line++;
-	while (1)
-	{
-	    if (fgets(ParseBuffer, 511, SpecFp) == NULL)
-		return NULL;
-	    if (ParseBuffer[0] != '#')
-		break;
-	}
-    }
-
-    return token;
-}
-
-int
-ParseVariable(int ordinal, int type)
-{
-    ORDDEF *odp;
-    ORDVARDEF *vdp;
-    char export_name[80];
-    char *token;
-    char *endptr;
-    int *value_array;
-    int n_values;
-    int value_array_size;
-    
-    strcpy(export_name, GetToken());
-
-    token = GetToken();
-    if (*token != '(')
-    {
-	fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
-	exit(1);
-    }
-
-    n_values = 0;
-    value_array_size = 25;
-    value_array = malloc(sizeof(*value_array) * value_array_size);
-    
-    while ((token = GetToken()) != NULL)
-    {
-	if (*token == ')')
-	    break;
-
-	value_array[n_values++] = strtol(token, &endptr, 0);
-	if (n_values == value_array_size)
-	{
-	    value_array_size += 25;
-	    value_array = realloc(value_array, 
-				  sizeof(*value_array) * value_array_size);
-	}
-	
-	if (endptr == NULL || *endptr != '\0')
-	{
-	    fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
-		    token);
-	    exit(1);
-	}
-    }
-    
-    if (token == NULL)
-    {
-	fprintf(stderr, "%d: End of file in variable declaration\n", Line);
-	exit(1);
-    }
-
-    if (ordinal >= MAX_ORDINALS)
-    {
-	fprintf(stderr, "%d: Ordinal number too large\n", Line);
-	exit(1);
-    }
-    
-    odp = &OrdinalDefinitions[ordinal];
-    odp->valid = 1;
-    odp->type = type;
-    strcpy(odp->export_name, export_name);
-    
-    vdp = malloc(sizeof(*vdp));
-    odp->additional_data = vdp;
-    
-    vdp->n_values = n_values;
-    vdp->values = realloc(value_array, sizeof(*value_array) * n_values);
-
-    return 0;
-}
-
-int
-ParseExportFunction(int ordinal, int type)
-{
-    char *token;
-    ORDDEF *odp;
-    ORDFUNCDEF *fdp;
-    int arg_types[16];
-    int i;
-    int arg_num;
-    int current_offset;
-    int arg_size;
-	
-    
-    if (ordinal >= MAX_ORDINALS)
-    {
-	fprintf(stderr, "%d: Ordinal number too large\n", Line);
-	exit(1);
-    }
-    
-    odp = &OrdinalDefinitions[ordinal];
-    strcpy(odp->export_name, GetToken());
-    odp->valid = 1;
-    odp->type = type;
-    fdp = malloc(sizeof(*fdp));
-    odp->additional_data = fdp;
-
-    token = GetToken();
-    if (*token != '(')
-    {
-	fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
-	exit(1);
-    }
-
-    fdp->arg_16_size = 0;
-    for (i = 0; i < 16; i++)
-    {
-	token = GetToken();
-	if (*token == ')')
-	    break;
-
-	if (stricmp(token, "byte") == 0 || stricmp(token, "word") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_WORD;
-	    fdp->arg_16_size += 2;
-	    fdp->arg_16_offsets[i] = 2;
-	}
-	else if (stricmp(token, "s_byte") == 0 || 
-		 stricmp(token, "s_word") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_SIGNEDWORD;
-	    fdp->arg_16_size += 2;
-	    fdp->arg_16_offsets[i] = 2;
-	}
-	else if (stricmp(token, "long") == 0 || stricmp(token, "s_long") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_LONG;
-	    fdp->arg_16_size += 4;
-	    fdp->arg_16_offsets[i] = 4;
-	}
-	else if (stricmp(token, "ptr") == 0)
-	{
-	    fdp->arg_types_16[i] = VARTYPE_FARPTR;
-	    fdp->arg_16_size += 4;
-	    fdp->arg_16_offsets[i] = 4;
-	}
-	else
-	{
-	    fprintf(stderr, "%d: Unknown variable type '%s'\n", Line, token);
-	    exit(1);
-	}
-    }
-    fdp->n_args_16 = i;
-
-    if (type == FUNCTYPE_PASCAL || type == FUNCTYPE_REG)
-    {
-	current_offset = 0;
-	for (i--; i >= 0; i--)
-	{
-	    arg_size = fdp->arg_16_offsets[i];
-	    fdp->arg_16_offsets[i] = current_offset;
-	    current_offset += arg_size;
-	}
-    }
-    else
-    {
-	current_offset = 0;
-	for (i = 0; i < fdp->n_args_16; i++)
-	{
-	    arg_size = fdp->arg_16_offsets[i];
-	    fdp->arg_16_offsets[i] = current_offset;
-	    current_offset += arg_size;
-	}
-    }
-
-    strcpy(fdp->internal_name, GetToken());
-    token = GetToken();
-    if (*token != '(')
-    {
-	fprintf(stderr, "%d: Expected '(' got '%s'\n", Line, token);
-	exit(1);
-    }
-    for (i = 0; i < 16; i++)
-    {
-	token = GetToken();
-	if (*token == ')')
-	    break;
-
-	fdp->arg_indices_32[i] = atoi(token);
-	if (fdp->arg_indices_32[i] < 1 || 
-	    fdp->arg_indices_32[i] > fdp->n_args_16)
-	{
-	    fprintf(stderr, "%d: Bad argument index %d\n", Line,
-		    fdp->arg_indices_32[i]);
-	    exit(1);
-	}
-    }
-    fdp->n_args_32 = i;
-
-    return 0;
-}
-
-int
-ParseEquate(int ordinal)
-{
-    ORDDEF *odp;
-    char *token;
-    char *endptr;
-    int value;
-    
-    if (ordinal >= MAX_ORDINALS)
-    {
-	fprintf(stderr, "%d: Ordinal number too large\n", Line);
-	exit(1);
-    }
-    
-    odp = &OrdinalDefinitions[ordinal];
-    strcpy(odp->export_name, GetToken());
-
-    token = GetToken();
-    value = strtol(token, &endptr, 0);
-    if (endptr == NULL || *endptr != '\0')
-    {
-	fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
-		token);
-	exit(1);
-    }
-
-    odp->valid = 1;
-    odp->type = EQUATETYPE_ABS;
-    odp->additional_data = (void *) value;
-
-    return 0;
-}
-
-int
-ParseReturn(int ordinal)
-{
-    ORDDEF *odp;
-    ORDRETDEF *rdp;
-    char *token;
-    char *endptr;
-    int value;
-    
-    if (ordinal >= MAX_ORDINALS)
-    {
-	fprintf(stderr, "%d: Ordinal number too large\n", Line);
-	exit(1);
-    }
-
-    rdp = malloc(sizeof(*rdp));
-    
-    odp = &OrdinalDefinitions[ordinal];
-    strcpy(odp->export_name, GetToken());
-    odp->valid = 1;
-    odp->type = TYPE_RETURN;
-    odp->additional_data = rdp;
-
-    token = GetToken();
-    rdp->arg_size = strtol(token, &endptr, 0);
-    if (endptr == NULL || *endptr != '\0')
-    {
-	fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
-		token);
-	exit(1);
-    }
-
-    token = GetToken();
-    rdp->ret_value = strtol(token, &endptr, 0);
-    if (endptr == NULL || *endptr != '\0')
-    {
-	fprintf(stderr, "%d: Expected number value, got '%s'\n", Line,
-		token);
-	exit(1);
-    }
-
-    return 0;
-}
-
-int
-ParseOrdinal(int ordinal)
-{
-    char *token;
-    
-    token = GetToken();
-    if (token == NULL)
-    {
-	fprintf(stderr, "%d: Expected type after ordinal\n", Line);
-	exit(1);
-    }
-
-    if (stricmp(token, "byte") == 0)
-	return ParseVariable(ordinal, VARTYPE_BYTE);
-    else if (stricmp(token, "word") == 0)
-	return ParseVariable(ordinal, VARTYPE_WORD);
-    else if (stricmp(token, "long") == 0)
-	return ParseVariable(ordinal, VARTYPE_LONG);
-    else if (stricmp(token, "c") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_C);
-    else if (stricmp(token, "p") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
-    else if (stricmp(token, "pascal") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_PASCAL);
-    else if (stricmp(token, "register") == 0)
-	return ParseExportFunction(ordinal, FUNCTYPE_REG);
-    else if (stricmp(token, "equate") == 0)
-	return ParseEquate(ordinal);
-    else if (stricmp(token, "return") == 0)
-	return ParseReturn(ordinal);
-    else
-    {
-	fprintf(stderr, 
-		"%d: Expected type after ordinal, found '%s' instead\n",
-		Line, token);
-	exit(1);
-    }
-}
-
-int
-ParseTopLevel(void)
-{
-    char *token;
-    
-    while ((token = GetToken()) != NULL)
-    {
-	if (stricmp(token, "name") == 0)
-	{
-	    strcpy(LowerDLLName, GetToken());
-	    strlower(LowerDLLName);
-
-	    strcpy(UpperDLLName, LowerDLLName);
-	    strupper(UpperDLLName);
-	}
-	else if (stricmp(token, "id") == 0)
-	{
-	    token = GetToken();
-	    if (!IsNumberString(token))
-	    {
-		fprintf(stderr, "%d: Expected number after id\n", Line);
-		exit(1);
-	    }
-	    
-	    DLLId = atoi(token);
-	}
-	else if (stricmp(token, "length") == 0)
-	{
-	    token = GetToken();
-	    if (!IsNumberString(token))
-	    {
-		fprintf(stderr, "%d: Expected number after length\n", Line);
-		exit(1);
-	    }
-
-	    Limit = atoi(token);
-	}
-	else if (IsNumberString(token))
-	{
-	    int ordinal;
-	    int rv;
-	    
-	    ordinal = atoi(token);
-	    if ((rv = ParseOrdinal(ordinal)) < 0)
-		return rv;
-	}
-	else
-	{
-	    fprintf(stderr, 
-		    "%d: Expected name, id, length or ordinal\n", Line);
-	    exit(1);
-	}
-    }
-
-    return 0;
-}
-
-void
-OutputVariableCode(FILE *fp, char *storage, ORDDEF *odp)
-{
-    ORDVARDEF *vdp;
-    int i;
-
-    fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
-
-    vdp = odp->additional_data;
-    for (i = 0; i < vdp->n_values; i++)
-    {
-	if ((i & 7) == 0)
-	    fprintf(fp, "\t%s\t", storage);
-	    
-	fprintf(fp, "%d", vdp->values[i]);
-	
-	if ((i & 7) == 7 || i == vdp->n_values - 1)
-	    fprintf(fp, "\n");
-	else
-	    fprintf(fp, ", ");
-    }
-    fprintf(fp, "\n");
-}
-
-main(int argc, char **argv)
-{
-    ORDDEF *odp;
-    ORDFUNCDEF *fdp;
-    ORDRETDEF *rdp;
-    FILE *fp;
-    char filename[80];
-    char buffer[80];
-    char *p;
-    int i;
-    
-    if (argc < 2)
-    {
-	fprintf(stderr, "usage: build SPECNAME\n");
-	exit(1);
-    }
-
-    SpecFp = fopen(argv[1], "r");
-    if (SpecFp == NULL)
-    {
-	fprintf(stderr, "Could not open specification file, '%s'\n", argv[1]);
-	exit(1);
-    }
-
-    ParseTopLevel();
-
-    /**********************************************************************
-     *					DLL ENTRY POINTS
-     */
-    sprintf(filename, "dll_%s.S", LowerDLLName);
-    fp = fopen(filename, "w");
-
-    fprintf(fp, "\t.globl _%s_Dispatch\n", UpperDLLName);
-    fprintf(fp, "_%s_Dispatch:\n", UpperDLLName);
-    fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-    fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-    fprintf(fp, "\torl\t$0x%08x,%%eax\n", DLLId << 16);
-    fprintf(fp, "\tjmp\t_CallTo32\n\n");
-
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
-    {
-	fprintf(fp, "\t.globl _%s_Ordinal_%d\n", UpperDLLName, i);
-
-	if (!odp->valid)
-	{
-	    fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
-#ifdef BOB_SAYS_NO
-	    fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-	    fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-#endif
-	    fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
-	    fprintf(fp, "\tpushw\t$0\n");
-	    fprintf(fp, "\tjmp\t_%s_Dispatch\n\n", UpperDLLName);
-	}
-	else
-	{
-	    fdp = odp->additional_data;
-	    rdp = odp->additional_data;
-	    
-	    switch (odp->type)
-	    {
-	      case EQUATETYPE_ABS:
-		fprintf(fp, "_%s_Ordinal_%d = %d\n\n", 
-			UpperDLLName, i, (int) odp->additional_data);
-		break;
-
-	      case VARTYPE_BYTE:
-		OutputVariableCode(fp, ".byte", odp);
-		break;
-
-	      case VARTYPE_WORD:
-		OutputVariableCode(fp, ".word", odp);
-		break;
-
-	      case VARTYPE_LONG:
-		OutputVariableCode(fp, ".long", odp);
-		break;
-
-	      case TYPE_RETURN:
-		fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
-		fprintf(fp, "\tmovw\t$%d,%%ax\n", rdp->ret_value & 0xffff);
-		fprintf(fp, "\tmovw\t$%d,%%dx\n", 
-			(rdp->ret_value >> 16) & 0xffff);
-		fprintf(fp, "\t.byte\t0x66\n");
-		if (rdp->arg_size != 0)
-		    fprintf(fp, "\tlret\t$%d\n", rdp->arg_size);
-		else
-		    fprintf(fp, "\tlret\n");
-		break;
-
-	      case FUNCTYPE_REG:
-		fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
-		fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-		fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-		fprintf(fp, "\tpushl\t$0\n");			/* cr2     */
-		fprintf(fp, "\tpushl\t$0\n");			/* oldmask */
-		fprintf(fp, "\tpushl\t$0\n");			/* i387    */
-		fprintf(fp, "\tpushw\t$0\n");			/* __ssh   */
-		fprintf(fp, "\tpushw\t%%ss\n");			/* ss      */
-		fprintf(fp, "\tpushl\t%%esp\n");		/* esp     */
-		fprintf(fp, "\tpushfl\n");			/* eflags  */
-		fprintf(fp, "\tpushw\t$0\n");			/* __csh   */
-		fprintf(fp, "\tpushw\t%%cs\n");			/* cs      */
-		fprintf(fp, "\tpushl\t$0\n");			/* eip     */
-		fprintf(fp, "\tpushl\t$0\n");			/* err     */
-		fprintf(fp, "\tpushl\t$0\n");			/* trapno  */
-		fprintf(fp, "\tpushal\n");			/* AX, ... */
-		fprintf(fp, "\tpushw\t$0\n");			/* __dsh   */
-		fprintf(fp, "\tpushw\t%%ds\n");			/* ds      */
-		fprintf(fp, "\tpushw\t$0\n");			/* __esh   */
-		fprintf(fp, "\tpushw\t%%es\n");			/* es      */
-		fprintf(fp, "\tpushw\t$0\n");			/* __fsh   */
-		fprintf(fp, "\tpushw\t%%fs\n");			/* fs      */
-		fprintf(fp, "\tpushw\t$0\n");			/* __gsh   */
-		fprintf(fp, "\tpushw\t%%gs\n");			/* gs      */
-		fprintf(fp, "\tmovl\t%%ebp,%%eax\n");
-		fprintf(fp, "\tmovw\t%%esp,%%ebp\n");
-		fprintf(fp, "\tpushl\t88(%%ebp)\n");
-		fprintf(fp, "\tmovl\t%%eax,%%ebp\n");
-		fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
-		fprintf(fp, "\tpushw\t$92\n");
-		fprintf(fp, "\tjmp\t_%s_Relay_%d:\n", UpperDLLName, i);
-		break;
-
-	      case FUNCTYPE_PASCAL:
-		fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
-#ifdef BOB_SAYS_NO
-		fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-		fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-#endif
-		fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
-		fprintf(fp, "\tpushw\t$%d\n", fdp->arg_16_size);
-		fprintf(fp, "\tjmp\t_%s_Relay_%d:\n", UpperDLLName, i);
-		break;
-		
-	      case FUNCTYPE_C:
-	      default:
-		fprintf(fp, "_%s_Ordinal_%d:\n", UpperDLLName, i);
-#ifdef BOB_SAYS_NO
-		fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-		fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-#endif
-		fprintf(fp, "\tmovl\t$%d,%%eax\n", i);
-		fprintf(fp, "\tpushw\t$0\n");
-		fprintf(fp, "\tjmp\t_%s_Relay_%d:\n", UpperDLLName, i);
-		break;
-	    }
-	}
-    }
-
-    fclose(fp);
-
-    /**********************************************************************
-     *					RELAY CODE
-     */
-    sprintf(filename, "rly_%s.S", LowerDLLName);
-    fp = fopen(filename, "w");
-
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
-    {
-	if (!odp->valid)
-	    continue;
-
-	fdp = odp->additional_data;
-	
-	fprintf(fp, "\t.globl _%s_Relay_%d\n", UpperDLLName, i);
-	fprintf(fp, "_%s_Relay_%d:\n", UpperDLLName, i);
-	fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
-	fprintf(fp, "\tandl\t$0x0000ffff,%%ebp\n");
-
-	fprintf(fp, "\tpushl\t%%ebp\n");
-	fprintf(fp, "\tmovl\t%%esp,%%ebp\n");
-
-	/*
- 	 * Save registers.  286 mode does not have fs or gs.
-	 */
-	fprintf(fp, "\tpushw\t%%ds\n");
-	fprintf(fp, "\tpushw\t%%es\n");
-
-	/*
-	 * Restore segment registers.
-	 */
-	fprintf(fp, "\tmovw\t%d,%%ax\n", UDATASEL);
-	fprintf(fp, "\tmovw\t%%ax,%%ds\n");
-	fprintf(fp, "\tmovw\t%%ax,%%es\n");
-
-	/*
-	 * Save old stack save variables, save stack registers, reload
-	 * stack registers.
-	 */
-	fprintf(fp, "\tpushl\t_IF1632_Saved16_esp\n");
-	fprintf(fp, "\tpushl\t_IF1632_Saved16_ebp\n");
-	fprintf(fp, "\tpushw\t_IF1632_Saved16_ss\n");
-
-	fprintf(fp, "\tmovw\t%%ss,_IF1632_Saved16_ss\n");
-	fprintf(fp, "\tmovl\t%%esp,_IF1632_Saved16_esp\n");
-	fprintf(fp, "\tmovl\t%%ebp,_IF1632_Saved16_ebp\n");
-
-	fprintf(fp, "\tmovw\t%%ss,%%ax\n");
-	fprintf(fp, "\tshll\t16,%%eax\n");
-	fprintf(fp, "\torl\t%%esp,%%eax\n");
-
-	fprintf(fp, "\tmovw\t_IF1632_Saved32_ss,%%ss\n");
-	fprintf(fp, "\tmovl\t_IF1632_Saved32_esp,%%esp\n");
-	fprintf(fp, "\tmovl\t_IF1632_Saved32_ebp,%%ebp\n");
-
-	fprintf(fp, "\tpushl\t_Stack16Frame\n");
-	fprintf(fp, "\tmovl\t%%eax,_Stack16Frame\n");
-
-	/*
-	 * Move arguments.
-	 */
-	
-
-	/*
-	 * Call entry point
-	 */
-	fprintf(fp, "\tcall\t%s\n", fdp->internal_name);
-
-	/*
- 	 * Restore registers, but do not destroy return value.
-	 */
-	fprintf(fp, "\tmovw\t_IF1632_Saved16_ss,%%ss\n");
-	fprintf(fp, "\tmovl\t_IF1632_Saved16_esp,%%esp\n");
-	fprintf(fp, "\tmovl\t_IF1632_Saved16_ebp,%%ebp\n");
-
-	fprintf(fp, "\tpopw\t_IF1632_Saved16_ss\n");
-	fprintf(fp, "\tpopl\t_IF1632_Saved16_ebp\n");
-	fprintf(fp, "\tpopl\t_IF1632_Saved16_esp\n");
-
-	fprintf(fp, "\tpopw\t%%es\n");
-	fprintf(fp, "\tpopw\t%%ds\n");
-
-	fprintf(fp, "\t.align\t2,0x90\n");
-	fprintf(fp, "\tleave\n");
-	
-	/*
-	 * Now we need to ditch the parameter bytes that were left on the
-	 * stack. We do this by effectively popping the number of bytes,
-	 * and the return address, removing the parameters and then putting
-	 * the return address back on the stack.
-	 * Normally this field is filled in by the relevant function in
-	 * the emulation library, since it should know how many bytes to
-	 * expect.
-	 */
-	fprintf(fp, "\tpopw\t%%gs:nbytes\n");
-	fprintf(fp, "\tcmpw\t$0,%%gs:nbytes\n");
-	fprintf(fp, "\tje\tnoargs\n");
-	fprintf(fp, "\tpopw\t%%gs:offset\n");
-	fprintf(fp, "\tpopw\t%%gs:selector\n");
-	fprintf(fp, "\taddw\t%%gs:nbytes,%%esp\n");
-	fprintf(fp, "\tpushw\t%%gs:selector\n");
-	fprintf(fp, "\tpushw\t%%gs:offset\n");
-	fprintf(fp, "noargs:\n");
-
-	/*
-	 * Last, but not least we need to move the high word from eax to dx
-	 */
-	fprintf(fp, "\t	pushl\t%%eax\n");
-	fprintf(fp, "\tpopw\t%%dx\n");
-	fprintf(fp, "\tpopw\t%%dx\n");
-
-	fprintf(fp, "\t.byte\t0x66\n");
-	fprintf(fp, "\tlret\n");
-
-    }
-
-    fclose(fp);
-
-    /**********************************************************************
-     *					DLL ENTRY TABLE
-     */
-#ifndef SHORTNAMES
-    sprintf(filename, "dll_%s_tab.c", LowerDLLName);
-#else
-    sprintf(filename, "dtb_%s.c", LowerDLLName);
-#endif
-    fp = fopen(filename, "w");
-
-    fprintf(fp, "#include <stdio.h>\n");
-    fprintf(fp, "#include <stdlib.h>\n");
-    fprintf(fp, "#include \042dlls.h\042\n\n");
-
-    for (i = 0; i <= Limit; i++)
-    {
-	fprintf(fp, "extern void %s_Ordinal_%d();\n", UpperDLLName, i);
-    }
-    
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
-    {
-	if (odp->valid && 
-	    (odp->type == FUNCTYPE_PASCAL || odp->type == FUNCTYPE_C ||
-	     odp->type == FUNCTYPE_REG))
-	{
-	    fdp = odp->additional_data;
-	    fprintf(fp, "extern int %s();\n", fdp->internal_name);
-	}
-    }
-    
-    fprintf(fp, "\nstruct dll_table_entry_s %s_table[%d] =\n", 
-	    UpperDLLName, Limit + 1);
-    fprintf(fp, "{\n");
-    odp = OrdinalDefinitions;
-    for (i = 0; i <= Limit; i++, odp++)
-    {
-	fdp = odp->additional_data;
-
-	if (!odp->valid)
-	    odp->type = -1;
-	
-	switch (odp->type)
-	{
-	  case FUNCTYPE_PASCAL:
-	  case FUNCTYPE_REG:
-	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
-	    fprintf(fp, "\042%s\042, ", odp->export_name);
-	    fprintf(fp, "%s, DLL_HANDLERTYPE_PASCAL, ", fdp->internal_name);
-#ifdef WINESTAT
-	    fprintf(fp, "0, ");
-#endif	    
-	    fprintf(fp, "%d, ", fdp->n_args_32);
-	    if (fdp->n_args_32 > 0)
-	    {
-		int argnum;
-		
-		fprintf(fp, "\n      {\n");
-		for (argnum = 0; argnum < fdp->n_args_32; argnum++)
-		{
-		    fprintf(fp, "        { %d, %d },\n",
-			    fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
-			    fdp->arg_types_16[argnum]);
-		}
-		fprintf(fp, "      }\n    ");
-	    }
-	    fprintf(fp, "}, \n");
-	    break;
-		
-	  case FUNCTYPE_C:
-	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, ", UTEXTSEL, UpperDLLName, i);
-	    fprintf(fp, "\042%s\042, ", odp->export_name);
-	    fprintf(fp, "%s, DLL_HANDLERTYPE_C, ", fdp->internal_name);
-#ifdef WINESTAT
-	    fprintf(fp, "0, ");
-#endif	    
-	    fprintf(fp, "%d, ", fdp->n_args_32);
-	    if (fdp->n_args_32 > 0)
-	    {
-		int argnum;
-		
-		fprintf(fp, "\n      {\n");
-		for (argnum = 0; argnum < fdp->n_args_32; argnum++)
-		{
-		    fprintf(fp, "        { %d, %d },\n",
-			    fdp->arg_16_offsets[fdp->arg_indices_32[argnum]-1],
-			    fdp->arg_types_16[argnum]);
-		}
-		fprintf(fp, "      }\n    ");
-	    }
-	    fprintf(fp, "}, \n");
-	    break;
-	    
-	  default:
-	    fprintf(fp, "    { 0x%x, %s_Ordinal_%d, \042\042, NULL },\n", 
-		    UTEXTSEL, UpperDLLName, i);
-	    break;
-	}
-    }
-    fprintf(fp, "};\n");
-
-    fclose(fp);
-}
-
diff --git a/windows/caret.c b/windows/caret.c
index 5c31d19..8f32990 100644
--- a/windows/caret.c
+++ b/windows/caret.c
@@ -7,6 +7,7 @@
 */
 
 #include "windows.h"
+#include "selectors.h"
 #include "stddebug.h"
 /* #define DEBUG_CARET */
 #include "debug.h"
@@ -30,15 +31,13 @@
 static CARET Caret;
 static BOOL LockCaret;
 
-static WORD CARET_Callback(HWND hwnd, WORD msg, WORD timerid, LONG ctime);
 static void CARET_HideCaret();
 
 
 /*****************************************************************
  *               CARET_Callback
  */
-
-static WORD CARET_Callback(HWND hwnd, WORD msg, WORD timerid, LONG ctime)
+WORD CARET_Callback(HWND hwnd, WORD msg, WORD timerid, LONG ctime)
 {
     HDC hdc;
     HBRUSH hBrush;
@@ -134,7 +133,8 @@
     Caret.timeout = 750;
     LockCaret = FALSE;
 
-    Caret.timerid = SetSystemTimer((HWND)0, 0, Caret.timeout, (FARPROC)CARET_Callback);
+    Caret.timerid = SetSystemTimer( (HWND)0, 0, Caret.timeout,
+                                (FARPROC)GetWndProcEntry16("CARET_Callback"));
 
     dprintf_caret(stddeb,"CreateCaret: hwnd=%d, timerid=%d\n", 
 		  hwnd, Caret.timerid);
@@ -222,7 +222,8 @@
 
     KillSystemTimer( (HWND)0, Caret.timerid);
     Caret.timeout = msecs;
-    Caret.timerid = SetSystemTimer((HWND)0, 0, Caret.timeout, (FARPROC)CARET_Callback);
+    Caret.timerid = SetSystemTimer( (HWND)0, 0, Caret.timeout,
+                                 (FARPROC)GetWndProcEntry16("CARET_Callback"));
 }
 
 
diff --git a/windows/cursor.c b/windows/cursor.c
index 369506d..fb13b6d 100644
--- a/windows/cursor.c
+++ b/windows/cursor.c
@@ -23,6 +23,7 @@
 /* #define DEBUG_CURSOR   */
 /* #define DEBUG_RESOURCE */
 #include "debug.h"
+#include "arch.h"
 
 static int ShowCursCount = 0;
 static HCURSOR hActiveCursor;
@@ -52,16 +53,15 @@
  */
 HCURSOR LoadCursor(HANDLE instance, SEGPTR cursor_name)
 {
-    XColor	bkcolor;
-    XColor	fgcolor;
     HCURSOR 	hCursor;
     HANDLE 	rsc_mem;
     WORD 	*lp;
+    LONG        *lpl,size;
     CURSORDESCRIP *lpcurdesc;
     CURSORALLOC	  *lpcur;
     HDC 	hdc;
-    int i, j, image_size;
-
+    int i, image_size;
+    unsigned char *cp1,*cp2;
     dprintf_resource(stddeb,"LoadCursor: instance = %04x, name = %08lx\n",
 	   instance, cursor_name);
     if (!instance)
@@ -117,27 +117,29 @@
 	    }
 	}
 
-#if 1
+#if 0
+    /* this code replaces all bitmap cursors with the default cursor */
     lpcur->xcursor = XCreateFontCursor(display, XC_top_left_arrow);
     GlobalUnlock(hCursor);
     return hCursor;
 #endif
 
-    if (!(hdc = GetDC(GetDesktopWindow()))) return 0;
+    if (!(hdc = GetDC(0))) return 0;
     rsc_mem = RSC_LoadResource(instance, cursor_name, NE_RSCTYPE_GROUP_CURSOR, 
 			       &image_size);
     if (rsc_mem == (HANDLE)NULL) {
     fprintf(stderr,"LoadCursor / Cursor %08lx not Found !\n", cursor_name);
-	ReleaseDC(GetDesktopWindow(), hdc); 
+	ReleaseDC(0, hdc); 
 	return 0;
 	}
     lp = (WORD *)GlobalLock(rsc_mem);
     if (lp == NULL) {
 	GlobalFree(rsc_mem);
-	ReleaseDC(GetDesktopWindow(), hdc); 
+	ReleaseDC(0, hdc); 
 	return 0;
 	}
     lpcurdesc = (CURSORDESCRIP *)(lp + 3);
+#if 0
     dprintf_cursor(stddeb,"LoadCursor / image_size=%d\n", image_size);
     dprintf_cursor(stddeb,"LoadCursor / curReserved=%X\n", *lp);
     dprintf_cursor(stddeb,"LoadCursor / curResourceType=%X\n", *(lp + 1));
@@ -154,6 +156,7 @@
 		(DWORD)lpcurdesc->curDIBSize);
     dprintf_cursor(stddeb,"LoadCursor / cursor curDIBOffset=%lX\n", 
 		(DWORD)lpcurdesc->curDIBOffset);
+#endif
     lpcur->descriptor = *lpcurdesc;
     GlobalUnlock(rsc_mem);
     GlobalFree(rsc_mem);
@@ -163,63 +166,64 @@
     if (rsc_mem == (HANDLE)NULL) {
     	fprintf(stderr,
 		"LoadCursor / Cursor %08lx Bitmap not Found !\n", cursor_name);
-	ReleaseDC(GetDesktopWindow(), hdc); 
+	ReleaseDC(0, hdc); 
 	return 0;
 	}
-    lp = (WORD *)GlobalLock(rsc_mem);
+    lpl = (LONG *)GlobalLock(rsc_mem);
     if (lp == NULL) {
 	GlobalFree(rsc_mem);
-	ReleaseDC(GetDesktopWindow(), hdc); 
+	ReleaseDC(0, hdc); 
 	return 0;
- 	}
-	lp++;
-    for (j = 0; j < 16; j++)
-        dprintf_cursor(stddeb,"%04X ", *(lp + j));
-/*
-    if (*lp == sizeof(BITMAPINFOHEADER))
-	lpcur->hBitmap = ConvertInfoBitmap(hdc, (BITMAPINFO *)lp);
-    else
-*/
-        lpcur->hBitmap = 0;
-/*     lp += sizeof(BITMAP); */
-    for (i = 0; i < 81; i++) {
-	char temp = *((char *)lp + 162 + i);
-	*((char *)lp + 162 + i) = *((char *)lp + 324 - i);
-	*((char *)lp + 324 - i) = temp;
-	}
-    lpcur->pixshape = XCreatePixmapFromBitmapData(
-    	display, DefaultRootWindow(display), 
-        ((char *)lp + 211), 32, 32,
-/*
-        lpcurdesc->Width / 2, lpcurdesc->Height / 4, 
-*/
-        WhitePixel(display, DefaultScreen(display)), 
-        BlackPixel(display, DefaultScreen(display)), 1);
-    lpcur->pixmask = XCreatePixmapFromBitmapData(
-    	display, DefaultRootWindow(display), 
-        ((char *)lp + 211), 32, 32,
-        WhitePixel(display, DefaultScreen(display)), 
-        BlackPixel(display, DefaultScreen(display)), 1);
-    memset(&bkcolor, 0, sizeof(XColor));
-    memset(&fgcolor, 0, sizeof(XColor));
-    bkcolor.pixel = WhitePixel(display, DefaultScreen(display)); 
-    fgcolor.pixel = BlackPixel(display, DefaultScreen(display));
-    dprintf_cursor(stddeb,"LoadCursor / before XCreatePixmapCursor !\n");
-    lpcur->xcursor = XCreatePixmapCursor(display,
- 	lpcur->pixshape, lpcur->pixmask, 
- 	&fgcolor, &bkcolor, lpcur->descriptor.curXHotspot, 
- 	lpcur->descriptor.curYHotspot);
+    }
+    lpl++;
+    size = CONV_LONG (*lpl);
+    if (size == sizeof(BITMAPCOREHEADER)){
+	CONV_BITMAPCOREHEADER (lpl);
+        ((BITMAPINFOHEADER *)lpl)->biHeight /= 2;
+	lpcur->hBitmap = ConvertCoreBitmap( hdc, (BITMAPCOREHEADER *) lpl );
+    } else if (size == sizeof(BITMAPINFOHEADER)){
+	CONV_BITMAPINFO (lpl);
+        ((BITMAPINFOHEADER *)lpl)->biHeight /= 2;
+	lpcur->hBitmap = ConvertInfoBitmap( hdc, (BITMAPINFO *) lpl );
+    } else  {
+      fprintf(stderr,"No bitmap for cursor?\n");
+      lpcur->hBitmap = 0;
+    }
+    lpl = (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(); */
+    size = lpcur->descriptor.Height/2 * ((lpcur->descriptor.Width+7)/8);
+#if 0
+    dprintf_cursor(stddeb,"Before:\n");
+    for(i=0;i<2*size;i++)  {
+      dprintf_cursor(stddeb,"%02x ",((unsigned char *)lpl)[i]);
+      if ((i & 7) == 7) dprintf_cursor(stddeb,"\n");
+    }
+#endif
+    cp1 = (char *)lpl;
+    cp2 = cp1+2*size;
+    for(i = 0; i < size; i++)  {
+      char tmp=*--cp2;
+      *cp2 = *cp1;
+      *cp1++ = tmp;
+    }
+#if 0
+    dprintf_cursor(stddeb,"After:\n");
+    for(i=0;i<2*size;i++)  {
+      dprintf_cursor(stddeb,"%02x ",((unsigned char *)lpl)[i]);
+      if ((i & 7) == 7) dprintf_cursor(stddeb,"\n");
+    }
+#endif
+    hCursor = CreateCursor(instance, lpcur->descriptor.curXHotspot, 
+ 	lpcur->descriptor.curYHotspot, lpcur->descriptor.Width,
+	lpcur->descriptor.Height/2,
+	(LPSTR)lpl, ((LPSTR)lpl)+size);
+
     GlobalUnlock(rsc_mem);
     GlobalFree(rsc_mem);
-/*
-    hCursor = CreateCursor(instance, lpcur->descriptor.curXHotspot, 
- 	lpcur->descriptor.curYHotspot, 32, 32,
-	(LPSTR)lp + 211, , (LPSTR)lp + 211);
-*/
-    XFreePixmap(display, lpcur->pixshape);
-    XFreePixmap(display, lpcur->pixmask);
-    ReleaseDC(GetDesktopWindow(), hdc); 
     GlobalUnlock(hCursor);
+    ReleaseDC(0,hdc);
     return hCursor;
 }
 
@@ -231,12 +235,16 @@
 HCURSOR CreateCursor(HANDLE instance, short nXhotspot, short nYhotspot, 
 	short nWidth, short nHeight, LPSTR lpANDbitPlane, LPSTR lpXORbitPlane)
 {
-    XColor	bkcolor;
-    XColor	fgcolor;
     HCURSOR 	hCursor;
     CURSORALLOC	  *lpcur;
     HDC 	hdc;
-
+    int         bpllen = (nWidth + 7)/8 * nHeight;
+    char        *tmpbpl = malloc(bpllen);
+    int         i;
+  
+    XColor bkcolor,fgcolor;
+    Colormap cmap = XDefaultColormap(display,XDefaultScreen(display));
+    
     dprintf_resource(stddeb,"CreateCursor: inst=%04x nXhotspot=%d  nYhotspot=%d nWidth=%d nHeight=%d\n",  
        instance, nXhotspot, nYhotspot, nWidth, nHeight);
     dprintf_resource(stddeb,"CreateCursor: inst=%04x lpANDbitPlane=%p lpXORbitPlane=%p\n",
@@ -253,24 +261,21 @@
     memset(lpcur, 0, sizeof(CURSORALLOC));
     lpcur->descriptor.curXHotspot = nXhotspot;
     lpcur->descriptor.curYHotspot = nYhotspot;
-    lpcur->pixshape = XCreatePixmapFromBitmapData(
-    	display, DefaultRootWindow(display), 
-        lpXORbitPlane, nWidth, nHeight,
-        WhitePixel(display, DefaultScreen(display)), 
-        BlackPixel(display, DefaultScreen(display)), 1);
+    for(i=0; i<bpllen; i++) tmpbpl[i] = ~lpANDbitPlane[i];
     lpcur->pixmask = XCreatePixmapFromBitmapData(
     	display, DefaultRootWindow(display), 
-        lpANDbitPlane, nWidth, nHeight,
-        WhitePixel(display, DefaultScreen(display)), 
-        BlackPixel(display, DefaultScreen(display)), 1);
-    memset(&bkcolor, 0, sizeof(XColor));
-    memset(&fgcolor, 0, sizeof(XColor));
-    bkcolor.pixel = WhitePixel(display, DefaultScreen(display)); 
-    fgcolor.pixel = BlackPixel(display, DefaultScreen(display));
+        tmpbpl, nWidth, nHeight, 1, 0, 1);
+    for(i=0; i<bpllen; i++) tmpbpl[i] ^= lpXORbitPlane[i];
+    lpcur->pixshape = XCreatePixmapFromBitmapData(
+    	display, DefaultRootWindow(display),
+        tmpbpl, nWidth, nHeight, 1, 0, 1);
+    XParseColor(display,cmap,"#000000",&fgcolor);
+    XParseColor(display,cmap,"#ffffff",&bkcolor);
     lpcur->xcursor = XCreatePixmapCursor(display,
  	lpcur->pixshape, lpcur->pixmask, 
  	&fgcolor, &bkcolor, lpcur->descriptor.curXHotspot, 
  	lpcur->descriptor.curYHotspot);
+    free(tmpbpl);
     XFreePixmap(display, lpcur->pixshape);
     XFreePixmap(display, lpcur->pixmask);
     ReleaseDC(GetDesktopWindow(), hdc); 
diff --git a/windows/message.c b/windows/message.c
index cf1d2cd..279b320 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -882,10 +882,14 @@
 LONG SendMessage( HWND hwnd, WORD msg, WORD wParam, LONG lParam )
 {
     WND * wndPtr;
+    LONG ret;
 
     wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return 0;
-    return CallWindowProc( wndPtr->lpfnWndProc, hwnd, msg, wParam, lParam );
+    ret = CallWindowProc( wndPtr->lpfnWndProc, hwnd, msg, wParam, lParam );
+    dprintf_msg( stddeb,"SendMessage(%4.4x,%x,%x,%lx) -> %lx\n",
+		 hwnd, msg, wParam, lParam, ret );
+	return ret;
 }
 
 
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 8e43752..9604d35 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -18,6 +18,7 @@
 #include "scroll.h"
 #include "nonclient.h"
 #include "graphics.h"
+#include "selectors.h"
 #include "stddebug.h"
 /* #define DEBUG_NONCLIENT */
 #include "debug.h"
@@ -1321,7 +1322,7 @@
 	if (wParam == SC_ABOUTWINE)
 	{   extern char sysres_DIALOG_2[];
 	    DialogBoxIndirectPtr( wndPtr->hInstance, sysres_DIALOG_2,
-		       hwnd, (WNDPROC)AboutWine_Proc );
+		       hwnd, GetWndProcEntry16("AboutWine_Proc") );
         }
 	break;
     }
diff --git a/windows/utility.c b/windows/utility.c
index 3858487..6bc0ef4 100644
--- a/windows/utility.c
+++ b/windows/utility.c
@@ -14,6 +14,7 @@
 #include <stdlib.h>
 #include "windows.h"
 #include "ldt.h"
+#include "stackframe.h"
 #include "stddebug.h"
 /* #define DEBUG_UTILITY */
 #include "debug.h"
@@ -56,7 +57,7 @@
 int
 DebugPrintString(char *str)
 {
-    fprintf(stderr, "%s", str);
+    fprintf(stderr, "%s\n", str);
     return 0;
 }
 
@@ -268,12 +269,14 @@
 };
 
 #ifndef WINELIB
-INT windows_wsprintf(BYTE *win_stack)
+INT windows_wsprintf(void)
 {
     LPSTR lpOutput, lpFormat, ptr;
     BYTE new_stack[1024], *stack_ptr;
     BOOL fLarge;
 
+    BYTE *win_stack = (BYTE *)CURRENT_STACK16->args;
+
     lpOutput = (LPSTR) PTR_SEG_TO_LIN(*(DWORD*)win_stack);
     win_stack += sizeof(DWORD);
     lpFormat = (LPSTR) PTR_SEG_TO_LIN(*(DWORD*)win_stack);
diff --git a/windows/win.c b/windows/win.c
index 6ed50d8..f17a885 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -21,8 +21,8 @@
 #include "nonclient.h"
 #include "winpos.h"
 #include "color.h"
-#include "stddebug.h"
 #include "callback.h"
+#include "stddebug.h"
 /* #define DEBUG_WIN  */ 
 /* #define DEBUG_MENU */
 #include "debug.h"
@@ -318,9 +318,15 @@
     if (parent)
     {
 	  /* Make sure parent is valid */
-        if (!IsWindow( parent )) return 0;
+        if (!IsWindow( parent )) {
+			dprintf_win(stddeb,"CreateWindowEx: Parent %x is not a windows\n", parent);
+			return 0;
+		}
     }
-    else if (style & WS_CHILD) return 0;  /* WS_CHILD needs a parent */
+    else if (style & WS_CHILD) {
+		dprintf_win(stddeb,"CreateWindowEx: no parent\n");
+		return 0;  /* WS_CHILD needs a parent */
+	}
 
     if (!(class = CLASS_FindClassByName( className, instance, &classPtr ))) {
 	fprintf(stderr,"CreateWindow BAD CLASSNAME '%s' !\n", className);
@@ -336,7 +342,10 @@
       /* Create the window structure */
 
     hwnd = USER_HEAP_ALLOC( sizeof(WND)+classPtr->wc.cbWndExtra );
-    if (!hwnd) return 0;
+    if (!hwnd) {
+		dprintf_win(stddeb,"CreateWindowEx: Out of memory\n");
+		return 0;
+	}
 
       /* Fill the structure */
 
@@ -480,7 +489,10 @@
 
     wmcreate = SendMessage( hwnd, WM_NCCREATE, 0,
                             USER_HEAP_SEG_ADDR(hcreateStruct) );
-    if (!wmcreate) wmcreate = -1;
+    if (!wmcreate) {
+		dprintf_win(stddeb,"CreateWindowEx: WM_NCCREATE return 0\n");
+		wmcreate = -1;
+	}
     else
     {
 	WINPOS_SendNCCalcSize( hwnd, FALSE, &wndPtr->rectWindow,
@@ -496,6 +508,7 @@
     if (wmcreate == -1)
     {
 	  /* Abort window creation */
+	  dprintf_win(stddeb,"CreateWindowEx: wmcreate==-1, aborting\n");
         WIN_DestroyWindow( hwnd );
 	return 0;
     }
@@ -991,8 +1004,6 @@
  *    pointers
  *
  *  o call wndenumprc for every child window the desktop has
- *    (parameters to Callback16 passed backwards so they are
- *    put in in pascal calling order)
  *
  *  o if wndenumprc returns 0 exit
  * 
@@ -1009,13 +1020,7 @@
         if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
               return 0;
       }
-#ifdef WINELIB
-      (*wndenumprc)(hwnd, lParam);
-#else
-      result = CallBack16(wndenumprc, 2,
-		CALLBACK_SIZE_WORD, (int) hwnd,
-		CALLBACK_SIZE_LONG, lParam);
-#endif
+      result = CallEnumWindowsProc( wndenumprc, hwnd, lParam );
       if ( ! result )  {
               return 0;
       }
@@ -1030,7 +1035,7 @@
  *   o hwnd is the first child to use, loop until all next windows
  *     are processed
  * 
- *   o call wdnenumprc with parameters in inverse order (pascal)
+ *   o call wdnenumprc
  *
  *   o call ourselves with the next child window
  * 
@@ -1039,22 +1044,11 @@
 {
     WND *wndPtr;
 
-    while (hwnd) {
-      if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
-            return 0;
-        }
-#ifdef WINELIB
-        if (!(*wndenumprc)( 2, lParam, (int) hwnd)) {
-#else
-        if (!CallBack16(wndenumprc, 2,
-		CALLBACK_SIZE_WORD, (int) hwnd,
-		CALLBACK_SIZE_LONG, lParam)) {
-#endif
-                return 0;
-      }
-      if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) {
-          return 0;
-      }
+    while (hwnd)
+    {
+        if (!(wndPtr=WIN_FindWndPtr(hwnd))) return 0;
+        if (!CallEnumWindowsProc( wndenumprc, hwnd, lParam )) return 0;
+        if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) return 0;
         hwnd=wndPtr->hwndNext;
     } 
     return 1;