Release 960414

Sun Apr 14 12:51:27 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/menu.c] [include/dialog.h] [windows/dialog.c]
	Made the resource loading code always use the correct Windows
	layout for Winelib on other CPUs.

	* [include/module.h] [loader/module.c]
	Added self handle in NE_MODULE structure, so we can use a pointer
	instead of a handle.
	Added function MODULE_GetPtr() to validate a HMODULE.

	* [memory/heap.c]
	Implemented Win32 heap management.

	* [memory/selector.c]
	Fix selector limit for huge blocks.

Sat Apr 13 00:19:12 1996  Huw D. M. Davies <h.davies1@physics.oxford.ac.uk>

	* [objects/metafile.c]
	Fixed memcpy bug to allow memory based metafiles to work.

Fri Apr 12 19:25:41 1996  Frans van Dorsselaer  <dorssel@rulhm1.leidenuniv.nl>

	* [controls/edit.c] [controls/EDIT.TODO]
	Complete rewrite.  Everything changed: new features, new bugs.
	Main addition: WordWrap.

Fri Apr 12 20:29:55 1996  Tristan Tarrant <tst@dcs.ed.ac.uk>

	* [resources/sysres_It.rc]
	Fixed a few mistakes in the file and resized some of the controls.

Fri Apr 12 09:55:13 1996  John Harvey <john@division.co.uk>

	* [misc/winsocket.c]
	Fixed broken #if defined that stopped unixware compiling.

	* [win32/resource.c]
        Added missing return to end of FindResource32.

Thu Apr 11 18:00:00 1996  Alex Korobka <alex@phm30.pharm.sunysb.edu>

	* [windows/keyboard.c] [windows/event.c]
	Fixed GetKeyState for mouse buttons.

	* [windows/message.c]
	WM_MOUSEACTIVATE wasn't sent in some cases.

Wed Apr 10 18:59:53 1996  Niels de Carpentier  <niels@cindy.et.tudelft.nl>

	* [objects/font.c]
	Match slightly bigger font if height negative.

Mon Apr  8 13:46:15 1996  Deano Calver <deano@rattie.demon.co.uk>

	* [multimedia/mmsystem.c]
	Changed read's to FILE_read's in mmsystem to fix mmio bug.

Sun Apr  7 21:40:29 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [misc/commdlg.c] [resources/sysres_En.rc] [resources/sysres_De.rc]
	Introduced ColorDlgProc() for ChooseColor() and replaced fitting
	En-,De- resources. 
	As written in TODO: some national language support is needed here.
diff --git a/ANNOUNCE b/ANNOUNCE
index e2d0c98..7f3bb2f 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,14 +1,14 @@
-This is release 960405 of Wine the MS Windows emulator.  This is still a
+This is release 960414 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 "julliard@lrc.epfl.ch".  Please don't
 forget to include a ChangeLog entry.
 
-WHAT'S NEW with Wine-960405: (see ChangeLog for details)
-	- Faster text display.
-	- Support for SCO OpenServer 5.
-	- Cleaner Win32 module handling.
+WHAT'S NEW with Wine-960414: (see ChangeLog for details)
+	- Complete rewrite of the edit control.
+	- Better color selection dialog.
+	- Win32 heap management.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -17,10 +17,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/development/Wine-960405.tar.gz
-    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960405.tar.gz
-    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960405.tar.gz
-    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960405.tar.gz
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960414.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960414.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960414.tar.gz
+    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960414.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
diff --git a/ChangeLog b/ChangeLog
index f37c6bd..46b0a5b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,71 @@
 ----------------------------------------------------------------------
+Sun Apr 14 12:51:27 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [controls/menu.c] [include/dialog.h] [windows/dialog.c]
+	Made the resource loading code always use the correct Windows
+	layout for Winelib on other CPUs.
+
+	* [include/module.h] [loader/module.c]
+	Added self handle in NE_MODULE structure, so we can use a pointer
+	instead of a handle.
+	Added function MODULE_GetPtr() to validate a HMODULE.
+
+	* [memory/heap.c]
+	Implemented Win32 heap management.
+
+	* [memory/selector.c]
+	Fix selector limit for huge blocks.
+
+Sat Apr 13 00:19:12 1996  Huw D. M. Davies <h.davies1@physics.oxford.ac.uk>
+
+	* [objects/metafile.c]
+	Fixed memcpy bug to allow memory based metafiles to work.
+
+Fri Apr 12 19:25:41 1996  Frans van Dorsselaer  <dorssel@rulhm1.leidenuniv.nl>
+
+	* [controls/edit.c] [controls/EDIT.TODO]
+	Complete rewrite.  Everything changed: new features, new bugs.
+	Main addition: WordWrap.
+
+Fri Apr 12 20:29:55 1996  Tristan Tarrant <tst@dcs.ed.ac.uk>
+
+	* [resources/sysres_It.rc]
+	Fixed a few mistakes in the file and resized some of the controls.
+
+Fri Apr 12 09:55:13 1996  John Harvey <john@division.co.uk>
+
+	* [misc/winsocket.c]
+	Fixed broken #if defined that stopped unixware compiling.
+
+	* [win32/resource.c]
+        Added missing return to end of FindResource32.
+
+Thu Apr 11 18:00:00 1996  Alex Korobka <alex@phm30.pharm.sunysb.edu>
+
+	* [windows/keyboard.c] [windows/event.c]
+	Fixed GetKeyState for mouse buttons.
+
+	* [windows/message.c]
+	WM_MOUSEACTIVATE wasn't sent in some cases.
+
+Wed Apr 10 18:59:53 1996  Niels de Carpentier  <niels@cindy.et.tudelft.nl>
+
+	* [objects/font.c]
+	Match slightly bigger font if height negative.
+
+Mon Apr  8 13:46:15 1996  Deano Calver <deano@rattie.demon.co.uk>
+
+	* [multimedia/mmsystem.c]
+	Changed read's to FILE_read's in mmsystem to fix mmio bug.
+
+Sun Apr  7 21:40:29 1996  Albrecht Kleine  <kleine@ak.sax.de>
+
+	* [misc/commdlg.c] [resources/sysres_En.rc] [resources/sysres_De.rc]
+	Introduced ColorDlgProc() for ChooseColor() and replaced fitting
+	En-,De- resources. 
+	As written in TODO: some national language support is needed here.
+
+----------------------------------------------------------------------
 Fri Apr  5 15:22:55 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
 
 	* [controls/button.c] [controls/static.c]
diff --git a/controls/EDIT.TODO b/controls/EDIT.TODO
index f2d404f..a190874 100644
--- a/controls/EDIT.TODO
+++ b/controls/EDIT.TODO
@@ -1,33 +1,111 @@
--  Find all the remaining bugs!
+This file gives some information about the code in edit.c.  If you want to
+change, add, or fix code, please read this text.  If you're not interested
+in doing actual work on edit.c only C & D will be of interest to you.
 
--  ES_LEFT, ES_RIGHT and ES_CENTER.  ES_RIGHT and ES_CENTER cannot be
-   used with single line edit controls or be combined with ES_AUTOHSCROLL.
+A) basic policy
+B) special functions
+C) not implemented
+D) known bugs
 
--  Hide selection when window loses focus and ES_NOHIDESEL to disable
-   this functionality.
+A) Basic Policy
 
--  ES_LOWERCASE and ES_UPPERCASE.
+The code has been made in such a way, that functions try to call other
+(documented) functions if that is sufficient.  This might sometimes not be
+the most efficient way, but it keeps the code clear.  This way I tried to keep
+the number of functions that rely on the internal EDITSTATE structure as
+low as possible.  For instance EDIT_WM_Cut() simply calls EDIT_WM_Copy() and
+EDIT_WM_Clear().  The latter two are well documented message handlers, so
+as long as they are right EDIT_WM_Cut() will never have to change again.
 
--  ES_OEMCONVERT.  Probably won't do anything very much.
+Example:
+The best thing to do, when you want to know the offset of line 3, is calling
+EDIT_EM_LineIndex().  Again this is a well documented message handler.  Don't
+look at es->LineDefs[2].offset.  It would just be another reference to the
+internal structure, and that would make it more difficult to change things.
+Refer to EDIT_WM_???? and EDIT_EM_????? functions as much as possible.
 
--  ES_WANTRETURN and Ctrl-Enter to move to next line when this
-   functionality is enabled.
+The WND * pointer is used internally whenever possible.  Although it is not
+the real HWND, it improves performance enough to use it.
 
--  Implement undo buffer correctly.  Windows allows the user to undo
-   entered text as well as deleted text.  You can also undo an undo.
+All displaying is done by invalidating regions / rects.  Only
+EDIT_EM_LineScroll() uses direct painting.  This way things become much
+faster.  Although sometimes the response time might appear to be slow, it
+would be much slower even, when everything would be painted instantly.  This
+is especially true for scrollbar tracking and selection changes..
 
--  Add word wrap - this is a very big change!
 
-I'm doing a rewrite on edit.c.  Please e-mail me if you want
-to work on edit.c as well, so we can synchronize.
 
-Bugs in the current version, known to me:
--  An empty document still contains "\r\n"
--  UNDO is unstable (incomplete, and it can cause a segfault)
--  WM_LBUTTONDBLCLK lets you select whole words, but doesn't set
-   the caret at the end of the selection
--  Scrolling (left-right) works, but the scrollbar doesn't
+B) Special functions
 
+The edit control needs to use local heap memory because applications may
+rely on EM_GETHANDLE.  This is bad, but it can't be helped, we have to live
+with that.  For this reason there is a nice EDIT_GetPointer() function,
+which locks the heap buffer *only once*, no matter how often it is called.
+Only at the end of the message handler EDIT_ReleasePointer() is called.  You
+don't have to worry about unlocking the heap.  Calling EDIT_GetPointer() is
+very fast if the buffer is already locked.
+This way, the buffer gets locked / unlock only once every message, although
+EDIT_GetPointer() may actually have been called a hundred times.
+Only when the actual HLOCAL is needed (for example to ReAlloc), a call to
+EDIT_ReleasePointer() is needed.  Look for instance in EDIT_MakeFit().
+
+This brings us to EDIT_MakeFit().  It automatically re-allocates the buffer
+if the size parameter > buffersize.  If everything is successful TRUE is
+returned, otherwise FALSE.  Only when the buffer contents may grow you need
+to call EDIT_MakeFit().  Currently this is only in EDIT_ReplaceSel() and
+EDIT_WM_SetText().
+
+EDIT_BuildLineDefs() is the most important function in edit.c.  It builds
+the internal EDITSTATE structure.  As soon as text *might* have changed, or
+when the appearance of the text on the screen *might* have changed, call
+this function !  This includes changes of screen size, change of the font,
+clipboard actions, etc. etc.  Most other functions that rely on EDITSTATE,
+rely on the stuff this function builds.
+
+
+
+C) Not Implemented
+
+- ES_PASSWORD
+- ES_CENTER
+- ES_RIGHT
+- EM_SETRECT
+- EM_SETRECTNP
+- EM_FMTLINES
+- ES_AUTOVSCROLL (every multi line *is* auto vscroll)
+- ES_AUTOHSCROLL (multi line can be yes or no, but single line only yes)
+- WM_UNDO (=EM_UNDO)
+- EM_CANUNDO
+- EM_SCROLL (scrolling works, but this appears to be an undocumented message)
+- ES_LOWERCASE
+- ES_UPPERCASE
+- ES_OEMCONVERT
+- ES_WANTRETURN
+- probably much, MUCH more
+
+I encountered several undocumented messages, or message parameters.
+EditWndProc() reports any unknown message with an id > WM_USER.
+
+
+
+D) Known bugs.
+
+-	Scrolling is weird, sometimes.  The current code makes the scrollbar
+	of Notepad work, but the scrollbar code itself is broken.  Currently
+	the scroll code of edit.c is *not* according to specs.  Instead, it
+	is according to the broken scrollbar code.  If that gets fixed, this
+	should be fixed, too.
+-	The clipboard is broken.  Whenever things go wrong with
+	cut/copy/paste, it is probably the clipboard that messes up things,
+	not edit.c.
+-	With Notepad, if you select New File a couple of times and enter
+	text, the buffer is sometimes corrupted.
+-	Switching on/off WordWrap with Notepad sometimes corrupts the buffer.
+
+
+I am still very actively changing things.  Especially I am working
+on Undo capabilities.  If you want to do things, other than bug fixes,
+please mail me so we can synchronize.
 
 Frans van Dorsselaer
 dorssel@rulhm1.LeidenUniv.nl
diff --git a/controls/combo.c b/controls/combo.c
index 8ac780f..5a616ce 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -1013,7 +1013,8 @@
     if (idCBox)
     {
         SendDlgItemMessage( hDlg, idCBox, CB_RESETCONTENT, 0, 0 );
-        ret = (SendDlgItemMessage( hDlg, idCBox, CB_DIR, wType, path ) >= 0);
+        ret = (SendDlgItemMessage( hDlg, idCBox, CB_DIR,
+                                   wType, (LPARAM)path ) >= 0);
     }
     if (idStatic)
     {
diff --git a/controls/edit.c b/controls/edit.c
index 37d95ad..d49bd04 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -1,3146 +1,2806 @@
 /*
- * Edit control
+ *	Edit control
  *
- * Copyright  David W. Metcalfe, 1994
- * Copyright  William Magro, 1995, 1996
- * Copyright  Frans van Dorsselaer, 1996
+ *	Copyright  David W. Metcalfe, 1994
+ *	Copyright  William Magro, 1995, 1996
+ *	Copyright  Frans van Dorsselaer, 1996
  *
- * Note: I'm doing a rewrite in order to implement word wrap
- *       Please e-mail me if you want to word on edit.c as well, so
- *       we can synchronize.
- *
- *       Frans van Dorsselaer
- *       dorssel@rulhm1.LeidenUniv.nl
+ */
+
+/*
+ *	UNDER CONSTRUCTION, please read EDIT.TODO
  */
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <windows.h>
-#include "instance.h"
-#include "local.h"
 #include "win.h"
-#include "class.h"
-#include "stackframe.h" /* for MAKE_SEGPTR */
-#include "user.h"
+#include "local.h"
+#include "stackframe.h"
 #include "stddebug.h"
 #include "debug.h"
 #include "xmalloc.h"
 #include "callback.h"
 
-#ifdef WINELIB32
-#define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
-	SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
-		    MAKEWPARAM(GetDlgCtrlID(hWndCntrl),wNotifyCode), \
-		    (LPARAM)hWndCntrl );
-#else
-#define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
-	SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
-		 GetDlgCtrlID(hWndCntrl), MAKELPARAM(hWndCntrl, wNotifyCode));
-#endif
+#define BUFLIMIT_MULTI		65535	/* maximum text buffer length */
+#define BUFLIMIT_SINGLE		32767	/* maximum text buffer length */
+#define BUFSTART_MULTI		1024	/* starting length for multi-line control */
+#define BUFSTART_SINGLE		256	/* starting length for single line control */
+#define GROWLENGTH		64	/* buffers grow by this much */
+#define HSCROLL_FRACTION	3	/* scroll window by 1/3 width */
 
-#define MAXTEXTLEN 30000   /* maximum text buffer length */
-#define EDITLEN     1024   /* starting length for multi-line control */
-#define ENTRYLEN     256   /* starting length for single line control */
-#define GROWLENGTH    64   /* buffers grow by this much */
+typedef enum
+{
+	END_0 = 0,
+	END_DELIMIT,
+	END_NONE,
+	END_HARD,
+	END_SOFT,
+} LINE_END;
+
+typedef struct {
+	int offset;
+	int length;
+	LINE_END ending;
+} LINEDEF;
 
 typedef struct
 {
-    int wlines;              /* number of lines of text */
-    int wtop;                /* top line that is displayed */
-    int wleft;               /* left pixel that is displayed */
-    unsigned int textlen;    /* text buffer length */
-    int textwidth;           /* width of longest line in pixels */
-    RECT fmtrc;              /* rectangle in which to format text */
-    int txtht;               /* height of text line in pixels */
-    HANDLE hText;            /* handle to text buffer */
-    INT *CharWidths;         /* widths of chars in font */
-    unsigned int *textptrs;  /* list of line offsets */
-    int CurrCol;             /* current column */
-    int CurrLine;            /* current line */
-    int WndCol;              /* current window column */
-    int WndRow;              /* current window row */
-    BOOL TextChanged;        /* TRUE if text has changed */
-    BOOL PaintBkgd;          /* paint control background */
-    unsigned int MaxTextLen; /* maximum text buffer length */
-    int SelBegLine;          /* beginning line of selection */
-    int SelBegCol;           /* beginning column of selection */
-    int SelEndLine;          /* ending line of selection */
-    int SelEndCol;           /* ending column of selection */
-    HFONT hFont;             /* handle of current font (if not default) */
-    HANDLE hDeletedText;     /* handle to deleted text buffer for undo */
-    int DeletedLength;       /* length of deleted text */
-    int DeletedCurrLine;     /* starting line from which text was deleted */
-    int DeletedCurrCol;      /* starting col from which text was deleted */
-    int NumTabStops;         /* number of tab stops in buffer hTabStops */
-    unsigned short *TabStops;/* tab stops buffer */
-    BOOL HaveFocus;          /* TRUE if this edit has the focus */
-    int ClientWidth;         /* computed from the window's ClientRect */
-    int ClientHeight;        /* ditto */
-    char PasswordChar;       /* The password character */
-    EDITWORDBREAKPROC WordBreakProc;
-    int CaretPrepareCount;   /* Did we already prepare the caret ? */
-    BOOL CaretHidden;        /* Did we hide the caret during painting ? */
-    int oldWndCol;           /* WndCol before we started painting */
-    int oldWndRow;           /* ditto for WndRow */
+	int TextWidth;		/* width of the widest line in pixels */
+	HLOCAL hBuf;
+	char *text;
+	HFONT hFont;
+	LINEDEF *LineDefs;
+	int XOffset;		/* possitive offset of the viewport in pixels */
+	int FirstVisibleLine;
+	int LineCount;
+	int LineHeight;		/* height of a screen line in pixels */
+	int AveCharWidth;	/* average character width in pixels */
+	unsigned int BufLimit;
+	unsigned int BufSize;
+	BOOL TextChanged;
+	BOOL Redraw;
+	int SelStart;		/* offset of selection start, == SelEnd if no selection */
+	int SelEnd;		/* offset of selection end == current caret position */
+	int NumTabStops;
+	LPINT TabStops;
+	EDITWORDBREAKPROC WordBreakProc;
+	char PasswordChar;
 } EDITSTATE;
 
 
-#define EditBufStartLen(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE \
-			       ? EDITLEN : ENTRYLEN)
-#define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
-#define SelMarked(es) (((es)->SelBegCol != (es)->SelEndCol) || \
-		       ((es)->SelBegLine  != (es)->SelEndLine))
-#define ROUNDUP(numer, denom) (((numer) % (denom)) \
-			       ? ((((numer) + (denom)) / (denom)) * (denom)) \
-			       : (numer) + (denom))
-
-/* "line" dimension for horizontal scroll */
-#define HSCROLLDIM(es) ((es)->ClientWidth / 3)
+#define SWAP_INT(x,y) do { int temp = (x); (x) = (y); (y) = temp; } while(0)
+#define ORDER_INT(x,y) do { if ((y) < (x)) SWAP_INT((x),(y)); } while(0)
 
 /* macros to access window styles */
-#define IsMultiLine(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_MULTILINE)
-#define IsVScrollBar(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & WS_VSCROLL)
-#define IsHScrollBar(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & WS_HSCROLL)
-#define IsReadOnly(hwnd) (GetWindowLong(hwnd,GWL_STYLE) & ES_READONLY)
+#define IsMultiLine(wndPtr) ((wndPtr)->dwStyle & ES_MULTILINE)
+#define IsVScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_VSCROLL)
+#define IsHScrollBar(wndPtr) ((wndPtr)->dwStyle & WS_HSCROLL)
+#define IsReadOnly(wndPtr) ((wndPtr)->dwStyle & ES_READONLY)
+#define IsWordWrap(wndPtr) (((wndPtr)->dwStyle & ES_AUTOHSCROLL) == 0)
 
-/* internal variables */
-static BOOL TextMarking;         /* TRUE if text marking in progress */
-static BOOL ButtonDown;          /* TRUE if left mouse button down */
-static int ButtonRow;              /* row in text buffer when button pressed */
-static int ButtonCol;              /* col in text buffer when button pressed */
+#define EDITSTATEPTR(wndPtr) (*(EDITSTATE **)((wndPtr)->wExtra))
 
-#define SWAP_INT(x,y) do { int temp = (x); (x) = (y); (y) = temp; } while(0)
-
+#ifdef WINELIB32
+#define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
+		SendMessage((wndPtr)->parent->hwndSelf, WM_CTLCOLOREDIT, \
+				(WPARAM)(hdc), (LPARAM)(wndPtr)->hwndSelf)
+#define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
+		SendMessage((wndPtr)->parent->hwndSelf, WM_COMMAND, \
+				MAKEWPARAM((wndPtr)->wIDmenu, wNotifyCode), \
+				(LPARAM)(wndPtr)->hwndSelf )
+#define DPRINTF_EDIT_MSG(str) \
+		dprintf_edit(stddeb, \
+			"edit: " str ": hwnd=%08x, wParam=%08x, lParam=%08lx\n", \
+			(UINT)hwnd, (UINT)wParam, (DWORD)lParam)
+#else
+#define EDIT_SEND_CTLCOLOR(wndPtr,hdc) \
+		SendMessage((wndPtr)->parent->hwndSelf, WM_CTLCOLOR, \
+				(WPARAM)(hdc), MAKELPARAM((wndPtr)->hwndSelf, CTLCOLOR_EDIT))
+#define EDIT_NOTIFY_PARENT(wndPtr, wNotifyCode) \
+		SendMessage((wndPtr)->parent->hwndSelf, WM_COMMAND, \
+				(wndPtr)->wIDmenu, \
+				MAKELPARAM((wndPtr)->hwndSelf, wNotifyCode))
+#define DPRINTF_EDIT_MSG(str) \
+		dprintf_edit(stddeb, \
+			"edit: " str ": hwnd=%04x, wParam=%04x, lParam=%08lx\n", \
+			(UINT)hwnd, (UINT)wParam, (DWORD)lParam)
+#endif
 
 /*********************************************************************
- *  EDIT_HeapAlloc
  *
- *  Allocate the specified number of bytes on the specified local heap.
- */
-static HLOCAL EDIT_HeapAlloc(HWND hwnd, int bytes, WORD flags)
-{
-    HLOCAL ret;
-    
-    ret = LOCAL_Alloc( WIN_GetWindowInstance(hwnd), flags, bytes );
-    if (!ret)
-	fprintf(stderr, "EDIT_HeapAlloc: Out of heap-memory\n");
-    return ret;
-}
-
-/*********************************************************************
- *  EDIT_HeapLock
+ *	Declarations
  *
- *  Return the address of the memory pointed to by the handle.
- */
-static void *EDIT_HeapLock(HWND hwnd, HANDLE handle)
-{
-    return LOCAL_Lock( WIN_GetWindowInstance(hwnd), handle );
-}
-
-/*********************************************************************
- *  EDIT_HeapUnlock
- */
-static void EDIT_HeapUnlock(HWND hwnd, HANDLE handle)
-{
-    if (handle == 0) return;
-    LOCAL_Unlock( WIN_GetWindowInstance( hwnd ), handle );
-}
-
-/*********************************************************************
- *  EDIT_HeapReAlloc
+ *	Files like these should really be kept in alphabetical order.
  *
- *  Reallocate the memory pointed to by the handle.
  */
-static HLOCAL EDIT_HeapReAlloc(HWND hwnd, HANDLE handle, int bytes)
-{
-    return LOCAL_ReAlloc( WIN_GetWindowInstance(hwnd), handle, bytes, 
-			  LMEM_FIXED );
-}
+LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+static void    EDIT_BuildLineDefs(WND *wndPtr);
+static int     EDIT_CallWordBreakProc(WND *wndPtr, char *s, int index, int count, int action);
+static int     EDIT_ColFromWndX(WND *wndPtr, int line, int x);
+static void    EDIT_DelEnd(WND *wndPtr);
+static void    EDIT_DelLeft(WND *wndPtr);
+static void    EDIT_DelRight(WND *wndPtr);
+static int     EDIT_GetAveCharWidth(WND *wndPtr);
+static int     EDIT_GetLineHeight(WND *wndPtr);
+static void    EDIT_GetLineRect(WND *wndPtr, int line, int scol, int ecol, LPRECT rc);
+static char *  EDIT_GetPointer(WND *wndPtr);
+static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static BOOL    EDIT_GetRedraw(WND *wndPtr);
+static int     EDIT_GetTextWidth(WND *wndPtr);
+static int     EDIT_GetVisibleLineCount(WND *wndPtr);
+static int     EDIT_GetWndWidth(WND *wndPtr);
+static int     EDIT_GetXOffset(WND *wndPtr);
+static int     EDIT_LineFromWndY(WND *wndPtr, int y);
+static BOOL    EDIT_MakeFit(WND *wndPtr, int size);
+static void    EDIT_MoveBackward(WND *wndPtr, BOOL extend);
+static void    EDIT_MoveDownward(WND *wndPtr, BOOL extend);
+static void    EDIT_MoveEnd(WND *wndPtr, BOOL extend);
+static void    EDIT_MoveForward(WND *wndPtr, BOOL extend);
+static void    EDIT_MoveHome(WND *wndPtr, BOOL extend);
+static void    EDIT_MovePageDown(WND *wndPtr, BOOL extend);
+static void    EDIT_MovePageUp(WND *wndPtr, BOOL extend);
+static void    EDIT_MoveUpward(WND *wndPtr, BOOL extend);
+static void    EDIT_MoveWordBackward(WND *wndPtr, BOOL extend);
+static void    EDIT_MoveWordForward(WND *wndPtr, BOOL extend);
+static void    EDIT_PaintLine(WND *wndPtr, HDC hdc, int line);
+static int     EDIT_PaintText(WND *wndPtr, HDC hdc, int x, int y, int line, int col, int count, BOOL rev);
+static void    EDIT_ReleasePointer(WND *wndPtr);
+static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static void    EDIT_ScrollIntoView(WND *wndPtr);
+static int     EDIT_WndXFromCol(WND *wndPtr, int line, int col);
+static int     EDIT_WndYFromLine(WND *wndPtr, int line);
+static int     EDIT_WordBreakProc(char *s, int index, int count, int action);
+
+static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+
+static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM wParam, LPARAM lParam);
+static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam);
 
 
 /*********************************************************************
- *  EDIT_HeapFree
  *
- *  Frees the memory pointed to by the handle.
- */
-static void EDIT_HeapFree(HWND hwnd, HANDLE handle)
-{
-    LOCAL_Free( WIN_GetWindowInstance(hwnd), handle );
-}
-
-
-/*********************************************************************
- *  EDIT_HeapSize
+ *	EditWndProc()
  *
- *  Return the size of the given object on the local heap.
  */
-static unsigned int EDIT_HeapSize(HWND hwnd, HANDLE handle)
+LRESULT EditWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
-    return LOCAL_Size( WIN_GetWindowInstance(hwnd), handle );
+	LRESULT lResult = 0L;
+	WND *wndPtr = WIN_FindWndPtr(hwnd);
+
+	switch (msg) {
+	case EM_CANUNDO:
+		DPRINTF_EDIT_MSG("EM_CANUNDO");
+		lResult = EDIT_EM_CanUndo(wndPtr, wParam, lParam);
+		break;
+	case EM_EMPTYUNDOBUFFER:
+		DPRINTF_EDIT_MSG("EM_EMPTYUNDOBUFFER");
+		lResult = EDIT_EM_EmptyUndoBuffer(wndPtr, wParam, lParam);
+		break;
+	case EM_FMTLINES:
+		DPRINTF_EDIT_MSG("EM_FMTLINES");
+		lResult = EDIT_EM_FmtLines(wndPtr, wParam, lParam);
+		break;
+	case EM_GETFIRSTVISIBLELINE:
+		DPRINTF_EDIT_MSG("EM_GETFIRSTVISIBLELINE");
+		lResult = EDIT_EM_GetFirstVisibleLine(wndPtr, wParam, lParam);
+		break;
+	case EM_GETHANDLE:
+		DPRINTF_EDIT_MSG("EM_GETHANDLE");
+		lResult = EDIT_EM_GetHandle(wndPtr, wParam, lParam);
+		break;
+	case EM_GETLINE:
+		DPRINTF_EDIT_MSG("EM_GETLINE");
+		lResult = EDIT_EM_GetLine(wndPtr, wParam, lParam);
+		break;
+	case EM_GETLINECOUNT:
+		DPRINTF_EDIT_MSG("EM_GETLINECOUNT");
+		lResult = EDIT_EM_GetLineCount(wndPtr, wParam, lParam);
+		break;
+	case EM_GETMODIFY:
+		DPRINTF_EDIT_MSG("EM_GETMODIFY");
+		lResult = EDIT_EM_GetModify(wndPtr, wParam, lParam);
+		break;
+	case EM_GETPASSWORDCHAR:
+		DPRINTF_EDIT_MSG("EM_GETPASSWORDCHAR");
+		lResult = EDIT_EM_GetPasswordChar(wndPtr, wParam, lParam);
+		break;
+	case EM_GETRECT:
+		DPRINTF_EDIT_MSG("EM_GETRECT");
+		lResult = EDIT_EM_GetRect(wndPtr, wParam, lParam);
+		break;
+	case EM_GETSEL:
+		DPRINTF_EDIT_MSG("EM_GETSEL");
+		lResult = EDIT_EM_GetSel(wndPtr, wParam, lParam);
+		break;
+	case EM_GETTHUMB:
+		DPRINTF_EDIT_MSG("EM_GETTHUMB");
+		lResult = EDIT_EM_GetThumb(wndPtr, wParam, lParam);
+		break;
+	case EM_GETWORDBREAKPROC:
+		DPRINTF_EDIT_MSG("EM_GETWORDBREAKPROC");
+		lResult = EDIT_EM_GetWordBreakProc(wndPtr, wParam, lParam);
+		break;
+	case EM_LIMITTEXT:
+		DPRINTF_EDIT_MSG("EM_LIMITTEXT");
+		lResult = EDIT_EM_LimitText(wndPtr, wParam, lParam);
+		break;
+	case EM_LINEFROMCHAR:
+		DPRINTF_EDIT_MSG("EM_LINEFROMCHAR");
+		lResult = EDIT_EM_LineFromChar(wndPtr, wParam, lParam);
+		break;
+	case EM_LINEINDEX:
+		DPRINTF_EDIT_MSG("EM_LINEINDEX");
+		lResult = EDIT_EM_LineIndex(wndPtr, wParam, lParam);
+		break;
+	case EM_LINELENGTH:
+		DPRINTF_EDIT_MSG("EM_LINELENGTH");
+		lResult = EDIT_EM_LineLength(wndPtr, wParam, lParam);
+		break;
+	case EM_LINESCROLL:
+		DPRINTF_EDIT_MSG("EM_LINESCROLL");
+		lResult = EDIT_EM_LineScroll(wndPtr, wParam, lParam);
+		break;
+	case EM_REPLACESEL:
+		DPRINTF_EDIT_MSG("EM_REPLACESEL");
+		lResult = EDIT_EM_ReplaceSel(wndPtr, wParam, lParam);
+		break;
+	case EM_SCROLL:
+		DPRINTF_EDIT_MSG("EM_SCROLL");
+		lResult = EDIT_EM_Scroll(wndPtr, wParam, lParam);
+ 		break;
+	case EM_SETHANDLE:
+		DPRINTF_EDIT_MSG("EM_SETHANDLE");
+		lResult = EDIT_EM_SetHandle(wndPtr, wParam, lParam);
+		break;
+	case EM_SETMODIFY:
+		DPRINTF_EDIT_MSG("EM_SETMODIFY");
+		lResult = EDIT_EM_SetModify(wndPtr, wParam, lParam);
+		break;
+	case EM_SETPASSWORDCHAR:
+		DPRINTF_EDIT_MSG("EM_SETPASSWORDCHAR");
+		lResult = EDIT_EM_SetPasswordChar(wndPtr, wParam, lParam);
+		break;
+	case EM_SETREADONLY:
+		DPRINTF_EDIT_MSG("EM_SETREADONLY");
+		lResult = EDIT_EM_SetReadOnly(wndPtr, wParam, lParam);
+ 		break;
+	case EM_SETRECT:
+		DPRINTF_EDIT_MSG("EM_SETRECT");
+		lResult = EDIT_EM_SetRect(wndPtr, wParam, lParam);
+		break;
+	case EM_SETRECTNP:
+		DPRINTF_EDIT_MSG("EM_SETRECTNP");
+		lResult = EDIT_EM_SetRectNP(wndPtr, wParam, lParam);
+		break;
+	case EM_SETSEL:
+		DPRINTF_EDIT_MSG("EM_SETSEL");
+		lResult = EDIT_EM_SetSel(wndPtr, wParam, lParam);
+		break;
+	case EM_SETTABSTOPS:
+		DPRINTF_EDIT_MSG("EM_SETTABSTOPS");
+		lResult = EDIT_EM_SetTabStops(wndPtr, wParam, lParam);
+		break;
+	case EM_SETWORDBREAKPROC:
+		DPRINTF_EDIT_MSG("EM_SETWORDBREAKPROC");
+		lResult = EDIT_EM_SetWordBreakProc(wndPtr, wParam, lParam);
+		break;
+	case EM_UNDO:
+	case WM_UNDO:
+		DPRINTF_EDIT_MSG("EM_UNDO / WM_UNDO");
+		lResult = EDIT_EM_Undo(wndPtr, wParam, lParam);
+		break;
+	case WM_GETDLGCODE:
+		DPRINTF_EDIT_MSG("WM_GETDLGCODE");
+		lResult = EDIT_WM_GetDlgCode(wndPtr, wParam, lParam);
+		break;
+	case WM_CHAR:
+		DPRINTF_EDIT_MSG("WM_CHAR");
+		lResult = EDIT_WM_Char(wndPtr, wParam, lParam);
+		break;
+	case WM_CLEAR:
+		DPRINTF_EDIT_MSG("WM_CLEAR");
+		lResult = EDIT_WM_Clear(wndPtr, wParam, lParam);
+		break;
+	case WM_COPY:
+		DPRINTF_EDIT_MSG("WM_COPY");
+		lResult = EDIT_WM_Copy(wndPtr, wParam, lParam);
+		break;
+	case WM_CREATE:
+		DPRINTF_EDIT_MSG("WM_CREATE");
+		lResult = EDIT_WM_Create(wndPtr, wParam, lParam);
+		break;
+	case WM_CUT:
+		DPRINTF_EDIT_MSG("WM_CUT");
+		lResult = EDIT_WM_Cut(wndPtr, wParam, lParam);
+		break;
+	case WM_DESTROY:
+		DPRINTF_EDIT_MSG("WM_DESTROY");
+		lResult = EDIT_WM_Destroy(wndPtr, wParam, lParam);
+		break;
+	case WM_ENABLE:
+		DPRINTF_EDIT_MSG("WM_ENABLE");
+		lResult = EDIT_WM_Enable(wndPtr, wParam, lParam);
+		break;
+	case WM_ERASEBKGND:
+		DPRINTF_EDIT_MSG("WM_ERASEBKGND");
+		lResult = EDIT_WM_EraseBkGnd(wndPtr, wParam, lParam);
+		break;
+	case WM_GETFONT:
+		DPRINTF_EDIT_MSG("WM_GETFONT");
+		lResult = EDIT_WM_GetFont(wndPtr, wParam, lParam);
+		break;
+	case WM_GETTEXT:
+		DPRINTF_EDIT_MSG("WM_GETTEXT");
+		lResult = EDIT_WM_GetText(wndPtr, wParam, lParam);
+		break;
+	case WM_GETTEXTLENGTH:
+		DPRINTF_EDIT_MSG("WM_GETTEXTLENGTH");
+		lResult = EDIT_WM_GetTextLength(wndPtr, wParam, lParam);
+		break;
+	case WM_HSCROLL:
+		DPRINTF_EDIT_MSG("WM_HSCROLL");
+		lResult = EDIT_WM_HScroll(wndPtr, wParam, lParam);
+		break;
+	case WM_KEYDOWN:
+		DPRINTF_EDIT_MSG("WM_KEYDOWN");
+		lResult = EDIT_WM_KeyDown(wndPtr, wParam, lParam);
+		break;
+	case WM_KILLFOCUS:
+		DPRINTF_EDIT_MSG("WM_KILLFOCUS");
+		lResult = EDIT_WM_KillFocus(wndPtr, wParam, lParam);
+		break;
+	case WM_LBUTTONDBLCLK:
+		DPRINTF_EDIT_MSG("WM_LBUTTONDBLCLK");
+		lResult = EDIT_WM_LButtonDblClk(wndPtr, wParam, lParam);
+		break;
+	case WM_LBUTTONDOWN:
+		DPRINTF_EDIT_MSG("WM_LBUTTONDOWN");
+		lResult = EDIT_WM_LButtonDown(wndPtr, wParam, lParam);
+		break;
+	case WM_LBUTTONUP:
+		DPRINTF_EDIT_MSG("WM_LBUTTONUP");
+		lResult = EDIT_WM_LButtonUp(wndPtr, wParam, lParam);
+		break;
+	case WM_MOUSEMOVE:
+		/*
+		 *	DPRINTF_EDIT_MSG("WM_MOUSEMOVE");
+		 */
+		lResult = EDIT_WM_MouseMove(wndPtr, wParam, lParam);
+		break;
+	case WM_PAINT:
+		DPRINTF_EDIT_MSG("WM_PAINT");
+		lResult = EDIT_WM_Paint(wndPtr, wParam, lParam);
+		break;
+	case WM_PASTE:
+		DPRINTF_EDIT_MSG("WM_PASTE");
+		lResult = EDIT_WM_Paste(wndPtr, wParam, lParam);
+		break;
+	case WM_SETCURSOR:
+		/*
+		 *	DPRINTF_EDIT_MSG("WM_SETCURSOR");
+		 */
+		lResult = EDIT_WM_SetCursor(wndPtr, wParam, lParam);
+		break;
+	case WM_SETFOCUS:
+		DPRINTF_EDIT_MSG("WM_SETFOCUS");
+		lResult = EDIT_WM_SetFocus(wndPtr, wParam, lParam);
+		break;
+	case WM_SETFONT:
+		DPRINTF_EDIT_MSG("WM_SETFONT");
+		lResult = EDIT_WM_SetFont(wndPtr, wParam, lParam);
+		break;
+	case WM_SETREDRAW:
+		DPRINTF_EDIT_MSG("WM_SETREDRAW");
+		lResult = EDIT_WM_SetRedraw(wndPtr, wParam, lParam);
+		break;
+	case WM_SETTEXT:
+		DPRINTF_EDIT_MSG("WM_SETTEXT");
+		lResult = EDIT_WM_SetText(wndPtr, wParam, lParam);
+		break;
+	case WM_SIZE:
+		DPRINTF_EDIT_MSG("WM_SIZE");
+		lResult = EDIT_WM_Size(wndPtr, wParam, lParam);
+		break;
+	case WM_VSCROLL:
+		DPRINTF_EDIT_MSG("WM_VSCROLL");
+		lResult = EDIT_WM_VScroll(wndPtr, wParam, lParam);
+		break;
+	default:
+		if (msg >= WM_USER)
+			fprintf(stdnimp, "edit: undocumented message %d >= WM_USER, please report.\n", msg);
+		lResult = DefWindowProc(hwnd, msg, wParam, lParam);
+		break;
+	}
+	EDIT_ReleasePointer(wndPtr);
+	return lResult;
 }
 
-/********************************************************************
- * EDIT_RecalcSize
- * 
- * Sets the ClientWidth/ClientHeight fields of the EDITSTATE
- * Called on WM_SIZE and WM_SetFont messages
- */
-static void EDIT_RecalcSize(HWND hwnd, EDITSTATE *es)
-{
-    RECT rect;
-    GetClientRect(hwnd,&rect);
-    es->ClientWidth = rect.right > rect.left ? rect.right - rect.left : 0;
-    es->ClientHeight = rect.bottom > rect.top ? (rect.bottom - rect.top) / es->txtht : 0;
-}
 
 /*********************************************************************
- * EDIT_GetEditState
- */
-static EDITSTATE *EDIT_GetEditState(HWND hwnd)
-{
-    return (EDITSTATE *)GetWindowLong(hwnd,0);
-}
-
-/*********************************************************************
- *  EDIT_CaretPrepare
  *
- *  Save the caret state before any painting is done.
+ *	EDIT_BuildLineDefs
+ *
+ *	Build array of pointers to text lines.
+ *	Lines can end with '\0' (last line), nothing (if it is to long),
+ *	a delimiter (usually ' '), a soft return '\r\r\n' or a hard return '\r\n'
+ *
  */
-static void EDIT_CaretPrepare(HWND hwnd)
+static void EDIT_BuildLineDefs(WND *wndPtr)
 {
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	char *text = EDIT_GetPointer(wndPtr);
+	int ww = EDIT_GetWndWidth(wndPtr);
+	HDC hdc;
+	HFONT hFont;
+	HFONT oldFont = 0;
+	char *start, *cp;
+	int prev, next;
+	int width;
+	int length;
+	LINE_END ending;
 
-    if (!es) return;
+	hdc = GetDC(wndPtr->hwndSelf);
+	hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L);
+	if (hFont)
+		oldFont = SelectObject(hdc, hFont);
 
-    if (!es->CaretPrepareCount)
-    {
-	es->CaretHidden = FALSE;
-	es->oldWndCol = es->WndCol;
-	es->oldWndRow = es->WndRow;
-    }
+	if (!IsMultiLine(wndPtr)) {
+		es->LineCount = 1;
+		es->LineDefs = xrealloc(es->LineDefs, sizeof(LINEDEF));
+		es->LineDefs[0].offset = 0;
+		es->LineDefs[0].length = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
+		es->LineDefs[0].ending = END_0;
+		es->TextWidth = LOWORD(GetTabbedTextExtent(hdc, text,
+					es->LineDefs[0].length,
+					es->NumTabStops, es->TabStops));
+	} else {
+		es->LineCount = 0;
+		start = text;
+		do {
+			if (!(cp = strstr(start, "\r\n"))) {
+				ending = END_0;
+				length = strlen(start);
+			} else if ((cp > start) && (*(cp - 1) == '\r')) {
+				ending = END_SOFT;
+				length = cp - start - 1;
+			} else {
+				ending = END_HARD;
+				length = cp - start;
+			}
+			width = LOWORD(GetTabbedTextExtent(hdc, start, length,
+						es->NumTabStops, es->TabStops));
 
-    es->CaretPrepareCount++;
+			if (IsWordWrap(wndPtr) && (width > ww)) {
+				next = 0;
+				do {
+					prev = next;
+					next = EDIT_CallWordBreakProc(wndPtr, start,
+							prev + 1, length, WB_RIGHT);
+					width = LOWORD(GetTabbedTextExtent(hdc, start, next,
+							es->NumTabStops, es->TabStops));
+				} while (width <= ww);
+				if (prev) {
+					length = prev;
+					if (EDIT_CallWordBreakProc(wndPtr, start, length - 1,
+									length, WB_ISDELIMITER)) {
+						length--;
+						ending = END_DELIMIT;
+					} else
+						ending = END_NONE;
+				} else {
+				}
+				width = LOWORD(GetTabbedTextExtent(hdc, start, length,
+							es->NumTabStops, es->TabStops));
+			}
+
+			es->LineDefs = xrealloc(es->LineDefs, (es->LineCount + 1) * sizeof(LINEDEF));
+			es->LineDefs[es->LineCount].offset = start - text;
+			es->LineDefs[es->LineCount].length = length;
+			es->LineDefs[es->LineCount].ending = ending;
+			es->LineCount++;
+			es->TextWidth = MAX(es->TextWidth, width);
+
+			start += length;
+			switch (ending) {
+			case END_SOFT:
+				start += 3;
+				break;
+			case END_HARD:
+				start += 2;
+				break;
+			case END_DELIMIT:
+				start++;
+				break;
+			default:
+				break;
+			}
+		} while (*start || (ending == END_SOFT) || (ending == END_HARD));
+	}
+	if (hFont)
+		SelectObject(hdc, oldFont);
+	ReleaseDC(wndPtr->hwndSelf, hdc);
 }
 
-/*********************************************************************
- *  EDIT_CaretHide
- *
- *  Called before some painting is done.
- */
-static void EDIT_CaretHide(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
 
-    if (!es) return;
-    if (!es->HaveFocus) return;
-    if (!es->CaretPrepareCount) return;
-    
-    if (!es->CaretHidden)
-    {
-    	HideCaret(hwnd);
-    	es->CaretHidden = TRUE;
-    }
+/*********************************************************************
+ *
+ *	EDIT_CallWordBreakProc
+ *
+ *	Call appropriate WordBreakProc (internal or external).
+ *
+ */
+static int EDIT_CallWordBreakProc(WND *wndPtr, char *s, int index, int count, int action)
+{
+	EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0L);
+
+	if (wbp) {
+		return CallWordBreakProc((FARPROC)wbp,
+				(LONG)MAKE_SEGPTR(s), index, count, action);
+	} else
+		return EDIT_WordBreakProc(s, index, count, action);
 }
 
+
 /*********************************************************************
- *  EDIT_CaretUpdate
  *
- *  Called after all painting is done.
+ *	EDIT_ColFromWndX
+ *
+ *	Calculates, for a given line and X-coordinate on the screen, the column.
+ *
  */
-static void EDIT_CaretUpdate(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
+static int EDIT_ColFromWndX(WND *wndPtr, int line, int x)
+{	
+	int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, line, 0L);
+	int linelength = EDIT_EM_LineLength(wndPtr, lineindex, 0L);
+	int i;
 
-    if (!es) return;
-    if (!es->CaretPrepareCount) return;
-    
-    es->CaretPrepareCount--;
-    
-    if (es->CaretPrepareCount) return;
-    if (!es->HaveFocus) return;
-
-    if ((es->WndCol != es->oldWndCol) || (es->WndRow != es->oldWndRow))
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-
-    if (es->CaretHidden)
-    {
-	ShowCaret(hwnd);
-	es->CaretHidden = FALSE;
-    }
+	line = MAX(0, MIN(line, linecount - 1));
+	for (i = 0 ; i < linelength ; i++)
+		if (EDIT_WndXFromCol(wndPtr, line, i) >= x)
+			break;
+	return i;
 }
 
+
 /*********************************************************************
- *  EDIT_WordBreakProc
  *
- *  Find the beginning of words.
- *  Note: unlike the specs for a WordBreakProc, this function only
- *        allows to be called without linebreaks between s[0] upto
- *        s[count - 1].  Remember it is only called
- *        internally, so we can decide this for ourselves.
+ *	EDIT_DelEnd
+ *
+ *	Delete all characters on this line to right of cursor.
+ *
+ */
+static void EDIT_DelEnd(WND *wndPtr)
+{
+	EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(-1, 0));
+	EDIT_MoveEnd(wndPtr, TRUE);
+	EDIT_WM_Clear(wndPtr, 0, 0L);
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_DelLeft
+ *
+ *	Delete character to left of cursor.
+ *
+ */
+static void EDIT_DelLeft(WND *wndPtr)
+{
+	EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(-1, 0));
+	EDIT_MoveBackward(wndPtr, TRUE);
+	EDIT_WM_Clear(wndPtr, 0, 0L);
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_DelRight
+ *
+ *	Delete character to right of cursor.
+ *
+ */
+static void EDIT_DelRight(WND *wndPtr)
+{
+	EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(-1, 0));
+	EDIT_MoveForward(wndPtr, TRUE);
+	EDIT_WM_Clear(wndPtr, 0, 0L);
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_GetAveCharWidth
+ *
+ */
+static int EDIT_GetAveCharWidth(WND *wndPtr)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	
+	return es->AveCharWidth;
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_GetLineHeight
+ *
+ */
+static int EDIT_GetLineHeight(WND *wndPtr)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	
+	return es->LineHeight;
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_GetLineRect
+ *
+ *	Calculates the bounding rectangle for a line from a starting
+ *	column to an ending column.
+ *
+ */
+static void EDIT_GetLineRect(WND *wndPtr, int line, int scol, int ecol, LPRECT rc)
+{
+	rc->top = EDIT_WndYFromLine(wndPtr, line);
+	rc->bottom = rc->top + EDIT_GetLineHeight(wndPtr);
+	rc->left = EDIT_WndXFromCol(wndPtr, line, scol);
+	rc->right = (ecol < 0) ? EDIT_GetWndWidth(wndPtr) : EDIT_WndXFromCol(wndPtr, line, ecol);
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_GetPointer
+ *
+ *	This acts as a LOCAL_Lock(), but it locks only once.  This way
+ *	you can call it whenever you like, without unlocking.
+ *
+ */
+static char *EDIT_GetPointer(WND *wndPtr)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	
+	if (!es->text && es->hBuf)
+		es->text = LOCAL_Lock(wndPtr->hInstance, es->hBuf);
+	return es->text;
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_GetRect
+ *
+ *	Beware: This is not the function called on EM_GETRECT.
+ *	It expects a (LPRECT) in lParam, not a (SEGPTR).
+ *	It is used internally, as if there were no pointer difficulties.
+ *
+ */
+static LRESULT EDIT_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	GetClientRect(wndPtr->hwndSelf, (LPRECT)lParam);
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_GetRedraw
+ *
+ */
+static BOOL EDIT_GetRedraw(WND *wndPtr)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	return es->Redraw;
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_GetTextWidth
+ *
+ */
+static int EDIT_GetTextWidth(WND *wndPtr)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	
+	return es->TextWidth;
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_GetVisibleLineCount
+ *
+ */
+static int EDIT_GetVisibleLineCount(WND *wndPtr)
+{
+	RECT rc;
+	
+	EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
+	return MAX(1, MAX(rc.bottom - rc.top, 0) / EDIT_GetLineHeight(wndPtr));
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_GetWndWidth
+ *
+ */
+static int EDIT_GetWndWidth(WND *wndPtr)
+{
+	RECT rc;
+	
+	EDIT_GetRect(wndPtr, 0, (LPARAM)&rc);
+	return rc.right - rc.left;
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_GetXOffset
+ *
+ */
+static int EDIT_GetXOffset(WND *wndPtr)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	
+	return es->XOffset;
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_LineFromWndY
+ *
+ *	Calculates, for a given Y-coordinate on the screen, the line.
+ *
+ */
+static int EDIT_LineFromWndY(WND *wndPtr, int y)
+{
+	int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	int lineheight = EDIT_GetLineHeight(wndPtr);
+	int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+
+	return MAX(0, MIN(linecount - 1, y / lineheight + firstvis));
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_MakeFit
+ *
+ *	Try to fit size + 1 bytes in the buffer.  Contrain to limits.
+ *
+ */
+static BOOL EDIT_MakeFit(WND *wndPtr, int size)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	if (size <= es->BufSize)
+		return TRUE;
+	if (size > es->BufLimit)
+		return FALSE;
+	es->BufSize = ((size / GROWLENGTH) + 1) * GROWLENGTH;
+	if (es->BufSize > es->BufLimit)
+		es->BufSize = es->BufLimit;
+
+	dprintf_edit(stddeb, "edit: EDIT_MakeFit: ReAlloc to %d+1\n", es->BufSize);
+
+	return LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, es->BufSize + 1, LMEM_MOVEABLE);
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_MoveBackward
+ *
+ */
+static void EDIT_MoveBackward(WND *wndPtr, BOOL extend)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L);
+
+	if (e - lineindex == 0) {
+		if (l) {
+			lineindex = EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
+			e = lineindex + EDIT_EM_LineLength(wndPtr, lineindex, 0L);
+		}
+	} else
+		e--;
+	if (!extend)
+		s = e;
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_MoveDownward
+ *
+ */
+static void EDIT_MoveDownward(WND *wndPtr, BOOL extend)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int linecount = EDIT_EM_GetLineCount(wndPtr, e, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L);
+	int x;
+
+	if (l < linecount - 1) {
+		x = EDIT_WndXFromCol(wndPtr, l, e - lineindex);
+		l++;
+		e = EDIT_EM_LineIndex(wndPtr, l, 0L) +
+				EDIT_ColFromWndX(wndPtr, l, x);
+	}
+	if (!extend)
+		s = e;
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_MoveEnd
+ *
+ */
+static void EDIT_MoveEnd(WND *wndPtr, BOOL extend)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int linelength = EDIT_EM_LineLength(wndPtr, e, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L);
+
+	e = lineindex + linelength;
+	if (!extend)
+		s = e;
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_MoveForward
+ *
+ */
+static void EDIT_MoveForward(WND *wndPtr, BOOL extend)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int linecount = EDIT_EM_GetLineCount(wndPtr, e, 0L);
+	int linelength = EDIT_EM_LineLength(wndPtr, e, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L);
+
+	if (e - lineindex == linelength) {
+		if (l != linecount - 1)
+			e = EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
+	} else
+		e++;
+	if (!extend)
+		s = e;
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_MoveHome
+ *
+ *	Home key: move to beginning of line.
+ *
+ */
+static void EDIT_MoveHome(WND *wndPtr, BOOL extend)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L);
+
+	e = lineindex;
+	if (!extend)
+		s = e;
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_MovePageDown
+ *
+ */
+static void EDIT_MovePageDown(WND *wndPtr, BOOL extend)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int linecount = EDIT_EM_GetLineCount(wndPtr, e, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L);
+	int x;
+
+	if (l < linecount - 1) {
+		x = EDIT_WndXFromCol(wndPtr, l, e - lineindex);
+		l = MIN(linecount - 1, l + EDIT_GetVisibleLineCount(wndPtr));
+		e = EDIT_EM_LineIndex(wndPtr, l, 0L) +
+				EDIT_ColFromWndX(wndPtr, l, x);
+	}
+	if (!extend)
+		s = e;
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_MovePageUp
+ *
+ */
+static void EDIT_MovePageUp(WND *wndPtr, BOOL extend)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L);
+	int x;
+
+	if (l) {
+		x = EDIT_WndXFromCol(wndPtr, l, e - lineindex);
+		l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
+		e = EDIT_EM_LineIndex(wndPtr, l, 0L) +
+				EDIT_ColFromWndX(wndPtr, l, x);
+	}
+	if (!extend)
+		s = e;
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_MoveUpward
+ *
+ */
+static void EDIT_MoveUpward(WND *wndPtr, BOOL extend)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L);
+	int x;
+
+	if (l) {
+		x = EDIT_WndXFromCol(wndPtr, l, e - lineindex);
+		l--;
+		e = EDIT_EM_LineIndex(wndPtr, l, 0L) +
+				EDIT_ColFromWndX(wndPtr, l, x);
+	}
+	if (!extend)
+		s = e;
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_MoveWordBackward
+ *
+ */
+static void EDIT_MoveWordBackward(WND *wndPtr, BOOL extend)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int linelength = EDIT_EM_LineLength(wndPtr, e, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L);
+	char *text;
+
+	if (e - lineindex == 0) {
+		if (l) {
+			lineindex = EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
+			e = lineindex + EDIT_EM_LineLength(wndPtr, lineindex, 0L);
+		}
+	} else {
+		text = EDIT_GetPointer(wndPtr);
+		e = lineindex + EDIT_CallWordBreakProc(wndPtr, text + lineindex,
+				e - lineindex, linelength, WB_LEFT);
+	}
+	if (!extend)
+		s = e;
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_MoveWordForward
+ *
+ */
+static void EDIT_MoveWordForward(WND *wndPtr, BOOL extend)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int linecount = EDIT_EM_GetLineCount(wndPtr, e, 0L);
+	int linelength = EDIT_EM_LineLength(wndPtr, e, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L);
+	char *text;
+
+	if (e - lineindex == linelength) {
+		if (l != linecount - 1)
+			e = EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
+	} else {
+		text = EDIT_GetPointer(wndPtr);
+		e = lineindex + EDIT_CallWordBreakProc(wndPtr, text + lineindex,
+				e - lineindex + 1, linelength, WB_RIGHT);
+	}
+	if (!extend)
+		s = e;
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_PaintLine
+ *
+ */
+static void EDIT_PaintLine(WND *wndPtr, HDC hdc, int line)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	int viscount = EDIT_GetVisibleLineCount(wndPtr);
+	int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	int LineStart;
+	int LineEnd;
+	int ReverseStart;
+	int ReverseEnd;
+	int x;
+	int y;
+
+	if ((line < firstvis) || (line > firstvis + viscount) || (line >= linecount))
+		return;
+
+	dprintf_edit(stddeb, "edit: EDIT_PaintLine: line=%d\n", line);
+
+	x = EDIT_WndXFromCol(wndPtr, line, 0);
+	y = EDIT_WndYFromLine(wndPtr, line);
+	LineStart = EDIT_EM_LineIndex(wndPtr, line, 0L);
+	LineEnd = LineStart + EDIT_EM_LineLength(wndPtr, LineStart, 0L);
+	ReverseStart = MIN(es->SelStart, es->SelEnd);
+	ReverseEnd = MAX(es->SelStart, es->SelEnd);
+	ReverseStart = MIN(LineEnd, MAX(LineStart, ReverseStart));
+	ReverseEnd = MIN(LineEnd, MAX(LineStart, ReverseEnd));
+	if (ReverseStart != ReverseEnd) {
+		x += EDIT_PaintText(wndPtr, hdc, x, y, line,
+				0, ReverseStart - LineStart, FALSE);
+		x += EDIT_PaintText(wndPtr, hdc, x, y, line,
+				ReverseStart - LineStart,
+				ReverseEnd - ReverseStart, TRUE);
+		x += EDIT_PaintText(wndPtr, hdc, x, y, line,
+				ReverseEnd - LineStart,
+				LineEnd - ReverseEnd, FALSE);
+	} else
+		x += EDIT_PaintText(wndPtr, hdc, x, y, line,
+				0, LineEnd - LineStart, FALSE);
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_PaintText
+ *
+ */
+static int EDIT_PaintText(WND *wndPtr, HDC hdc, int x, int y, int line, int col, int count, BOOL rev)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	COLORREF BkColor;
+	COLORREF TextColor;
+	int ret;
+	char *text;
+	int lineindex = EDIT_EM_LineIndex(wndPtr, line, 0L);
+	int xoffset = EDIT_GetXOffset(wndPtr);
+
+	if (count < 1)
+		return 0;
+		
+	BkColor = GetBkColor(hdc);
+	TextColor = GetTextColor(hdc);
+	if (rev) {
+		SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
+		SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
+	}
+	text = EDIT_GetPointer(wndPtr);
+	ret = LOWORD(TabbedTextOut(hdc, x, y, text + lineindex + col, count,
+					es->NumTabStops, es->TabStops, -xoffset));	
+	if (rev) {
+		SetBkColor(hdc, BkColor);
+		SetTextColor(hdc, TextColor);
+	}
+	return ret;
+}	
+
+
+/*********************************************************************
+ *
+ *	EDIT_ReleasePointer
+ *
+ *	This is the only helper function that can be called with es = NULL.
+ *	It is called at the end of EditWndProc() to unlock the buffer.
+ *	
+ */
+static void EDIT_ReleasePointer(WND *wndPtr)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	
+	if (!es)
+		return;
+	if (es->text && es->hBuf)
+		LOCAL_Unlock(wndPtr->hInstance, es->hBuf);
+	es->text = NULL;
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_ReplaceSel
+ *
+ *	Beware: This is not the function called on EM_REPLACESEL.
+ *	It expects a (char *) in lParam, not a (SEGPTR).
+ *	It is used internally, as if there were no pointer difficulties.
+ *
+ */
+static LRESULT EDIT_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	const char *str = (char *)lParam;
+	int strl = strlen(str);
+	int tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int i;
+	char *p;
+	char *text;
+	BOOL redraw;
+
+	ORDER_INT(s,e);
+	if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) {
+		EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
+		return 0L;
+	}
+	redraw = EDIT_GetRedraw(wndPtr);
+	EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
+	EDIT_WM_Clear(wndPtr, 0, 0L);
+	tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
+	e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	text = EDIT_GetPointer(wndPtr);
+	for (p = text + tl ; p >= text + e ; p--)
+		p[strl] = p[0];
+	for (i = 0 , p = text + e ; i < strl ; i++)
+		p[i] = str[i];
+	EDIT_BuildLineDefs(wndPtr);
+	e += strl;
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(e, e));
+	EDIT_EM_SetModify(wndPtr, TRUE, 0L);
+	EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
+	EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
+	if (redraw) {
+		InvalidateRect(wndPtr->hwndSelf, NULL, TRUE);
+		EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
+	}
+	return 0L;
+}
+ 
+
+/*********************************************************************
+ *
+ *	EDIT_ScrollIntoView
+ *
+ *	Makes sure the caret is visible.
+ *
+ */
+static void EDIT_ScrollIntoView(WND *wndPtr)
+{
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L);
+	int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	int vislinecount = EDIT_GetVisibleLineCount(wndPtr);
+	int wndwidth = EDIT_GetWndWidth(wndPtr);
+	int charwidth = EDIT_GetAveCharWidth(wndPtr);
+	int x = EDIT_WndXFromCol(wndPtr, l, e - lineindex);
+	int dy = 0;
+	int dx = 0;
+
+	if (l >= firstvis + vislinecount)
+		dy = l - vislinecount + 1 - firstvis;
+	if (l < firstvis)
+		dy = l - firstvis;
+	if (x < 0)
+		dx = x - wndwidth / HSCROLL_FRACTION / charwidth * charwidth;
+	if (x > wndwidth)
+		dx = x - (HSCROLL_FRACTION - 1) * wndwidth / HSCROLL_FRACTION / charwidth * charwidth;
+	if (dy || dx) {
+		EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, dx));
+		if (dy) 
+			EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
+		if (dx)
+			EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
+	}
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_WndXFromCol
+ *
+ *	Calculates, for a given line and column, the X-coordinate on the screen.
+ *
+ */
+static int EDIT_WndXFromCol(WND *wndPtr, int line, int col)
+{	
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	char *text = EDIT_GetPointer(wndPtr);
+	int ret;
+	HDC hdc;
+	HFONT hFont;
+	HFONT oldFont = 0;
+	int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, line, 0L);
+	int linelength = EDIT_EM_LineLength(wndPtr, lineindex, 0L);
+	int xoffset = EDIT_GetXOffset(wndPtr);
+
+	hdc = GetDC(wndPtr->hwndSelf);
+	hFont = (HFONT)EDIT_WM_GetFont(wndPtr, 0, 0L);
+	if (hFont)
+		oldFont = SelectObject(hdc, hFont);
+	line = MAX(0, MIN(line, linecount - 1));
+	col = MAX(0, MIN(col, linelength));
+	ret = LOWORD(GetTabbedTextExtent(hdc,
+			text + lineindex, col,
+			es->NumTabStops, es->TabStops)) - xoffset;
+	if (hFont)
+		SelectObject(hdc, oldFont);
+	ReleaseDC(wndPtr->hwndSelf, hdc);
+	return ret;
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_WndYFromLine
+ *
+ *	Calculates, for a given line, the Y-coordinate on the screen.
+ *
+ */
+static int EDIT_WndYFromLine(WND *wndPtr, int line)
+{
+	int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	int lineheight = EDIT_GetLineHeight(wndPtr);
+
+	return (line - firstvis) * lineheight;
+}
+
+
+/*********************************************************************
+ *
+ *	EDIT_WordBreakProc
+ *
+ *	Find the beginning of words.
+ *	Note:	unlike the specs for a WordBreakProc, this function only
+ *		allows to be called without linebreaks between s[0] upto
+ *		s[count - 1].  Remember it is only called
+ *		internally, so we can decide this for ourselves.
+ *
  */
 static int EDIT_WordBreakProc(char *s, int index, int count, int action)
 {
-    int ret = 0;
+	int ret = 0;
 
-    dprintf_edit(stddeb, "EDIT_WordBreakProc: s=%p, index=%d"
-	", count=%d, action=%d\n", s, index, count, action);
+	dprintf_edit(stddeb, "edit: EDIT_WordBreakProc: s=%p, index=%d"
+			", count=%d, action=%d\n", s, index, count, action);
 
-    switch (action) {
-    case WB_LEFT:
-	if (!count) break;
-	if (index) index--;
-	if (s[index] == ' ') {
-	    while (index && (s[index] == ' ')) index--;
-	    if (index) {
-		while (index && (s[index] != ' ')) index--;
-		if (s[index] == ' ') index++;
-	    }
-	} else {
-	    while (index && (s[index] != ' ')) index--;
-	    if (s[index] == ' ') index++;
-	}
-	ret = index;
-	break;
-    case WB_RIGHT:
-	if (!count) break;
-	if (index) index--;
-	if (s[index] == ' ')
-	    while ((index < count) && (s[index] == ' ')) index++;
-	else {
-	    while (s[index] && (s[index] != ' ') && (index < count)) index++;
-	    while ((s[index] == ' ') && (index < count)) index++;
-	}
-	ret = index;
-	break;
-    case WB_ISDELIMITER:
-	ret = (s[index] == ' ');
-	break;
-    default:
-	fprintf(stderr, "EDIT_WordBreakProc: unknown action code !\n");
-	break;
-    }
-    return ret;
-}
-
-/*********************************************************************
- *  EDIT_CallWordBreakProc
- *
- *  Call appropriate WordBreakProc (internal or external).
- */
-static int CALLBACK EDIT_CallWordBreakProc(HWND hwnd, char *pch, 
-					int ichCurrent, int cch, int code)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    
-    if (es->WordBreakProc) {
-	/* FIXME: do some stuff to make pch a SEGPTR */
-	return CallWordBreakProc((FARPROC)es->WordBreakProc, (LONG)pch, ichCurrent, cch, code);
-    } else return EDIT_WordBreakProc(pch, ichCurrent, cch, code);
-}
-
-/*********************************************************************
- *  EDIT_GetNextTabStop
- *
- *  Return the next tab stop beyond _pcol_.
- */
-static int EDIT_GetNextTabStop(HWND hwnd, int pcol)
-{
-    int i;
-    int baseUnitWidth = LOWORD(GetDialogBaseUnits());
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (es->NumTabStops == 0)
-	return ROUNDUP(pcol, 8 * baseUnitWidth);
-    if (es->NumTabStops == 1)
-	return ROUNDUP(pcol, es->TabStops[0] * baseUnitWidth / 4);
-    for (i = 0; i < es->NumTabStops; i++)
-    {
-	if (es->TabStops[i] * baseUnitWidth / 4 >= pcol)
-	    return es->TabStops[i] * baseUnitWidth / 4;
-    }
-    return pcol;
-}
-
-/*********************************************************************
- *  EDIT_CharWidth
- *
- *  Return the width of the given character in pixels.
- *  The current column offset in pixels _pcol_ is required to calculate 
- *  the width of a tab.
- */
-static int EDIT_CharWidth(HWND hwnd, short ch, int pcol)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (ch == VK_TAB) return EDIT_GetNextTabStop(hwnd, pcol) - pcol;
-    return es->CharWidths[ch];
-}
-
-/*********************************************************************
- *  EDIT_ClearTextPointers
- *
- *  Clear and initialize text line pointer array.
- */
-static void EDIT_ClearTextPointers(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    
-    dprintf_edit( stddeb, "EDIT_ClearTextPointers\n" );
-    es->textptrs = xrealloc(es->textptrs, sizeof(int));
-    es->textptrs[0] = 0;
-}
-
-/*********************************************************************
- *  EDIT_BuildTextPointers
- *
- *  Build array of pointers to text lines.
- */
-static void EDIT_BuildTextPointers(HWND hwnd)
-{
-    char *text, *cp;
-    unsigned int off, len, line;
-    EDITSTATE *es;
-
-    es = EDIT_GetEditState(hwnd);
-    text = EDIT_HeapLock(hwnd, es->hText);
-
-    es->textwidth = 0;
-    if (IsMultiLine(hwnd)) {
-	es->wlines = 0;
-	cp = text;
-	while ((cp = strchr(cp,'\n')) != NULL) {
-	    es->wlines++; cp++;
-	}
-    } else es->wlines = 1;
-    
-    dprintf_edit( stddeb, "EDIT_BuildTextPointers: realloc\n" );
-    es->textptrs = xrealloc(es->textptrs, (es->wlines + 2) * sizeof(int));
-    
-    cp = text;
-    dprintf_edit(stddeb,"BuildTextPointers: %d lines, pointer %p\n", 
-		 es->wlines, es->textptrs);
-
-    /* advance through text buffer */
-    line = 0;
-    while (*cp)
-    {
-	off = cp - text;     /* offset of beginning of line */
-        dprintf_edit(stddeb,"BuildTextPointers: line %d offs %d\n", line, off);
-	es->textptrs[line] = off;
-	line++;
-	len = 0;
-	
-	/* advance through current line */
-	while (*cp && *cp != '\n')
-	{
-	    len += EDIT_CharWidth(hwnd, (BYTE)*cp, len);
-	                                     /* width of line in pixels */
-	    cp++;
-	}
-	es->textwidth = MAX(es->textwidth, len);
-	if (*cp)
-	    cp++;                            /* skip '\n' */
-    }
-    off = cp - text;
-    es->textptrs[line] = off;
-    EDIT_HeapUnlock(hwnd, es->hText);
-}
-
-/*********************************************************************
- *  EDIT_ModTextPointers
- *
- *  Modify text pointers from a specified position.
- */
-static void EDIT_ModTextPointers(HWND hwnd, int lineno, int var)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    for(;lineno < es->wlines; lineno++) es->textptrs[lineno] += var;
-}
-
-/*********************************************************************
- *  EDIT_TextLine
- *
- *  Return a pointer to the text in the specified line.
- */
-static char *EDIT_TextLine(HWND hwnd, int sel)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    char *text = EDIT_HeapLock(hwnd, es->hText);
-
-    if (sel > es->wlines) return NULL;
-    dprintf_edit(stddeb,"EDIT_TextLine: text %p, line %d offs %d\n", 
-		 text, sel, es->textptrs[sel]);
-    return text + es->textptrs[sel];
-}
-    
-/*********************************************************************
- *  EDIT_GetTextLine
- *
- *  Get a copy of the text in the specified line.
- */
-static char *EDIT_GetTextLine(HWND hwnd, int selection)
-{
-    int len;
-    char *cp, *cp1;
-
-    dprintf_edit(stddeb,"GetTextLine %d\n", selection);
-    cp1 = EDIT_TextLine(hwnd, selection);
-
-    /* Find end of line */
-    cp = strchr( cp1, '\r' );
-    if (cp == NULL) len = strlen(cp1);
-    else len = cp - cp1;
-    
-    /* store selected line and return handle */
-    cp = xmalloc( len + 1 );
-    strncpy( cp, cp1, len);
-    cp[len] = 0;
-    return cp;
-}
-
-/*********************************************************************
- *  EDIT_StrWidth
- *
- *  Return length of string _str_ of length _len_ characters in pixels.
- *  The current column offset in pixels _pcol_ is required to calculate 
- *  the width of a tab.
- */
-static int EDIT_StrWidth(HWND hwnd, unsigned char *str, int len, int pcol)
-{
-    int i, plen = 0;
-
-    for (i = 0; i < len; i++)
-	plen += EDIT_CharWidth(hwnd, (BYTE)(*(str + i)), pcol + plen);
-
-    dprintf_edit(stddeb,"EDIT_StrWidth: returning %d, len=%d\n", plen,len);
-    return plen;
-}
-
-/*********************************************************************
- *  EDIT_LineLength
- *
- *  Return length of line _num_ in characters.
- */
-static int EDIT_LineLength(HWND hwnd, int num)
-{
-    char *cp = EDIT_TextLine(hwnd, num);
-    char *cp1;
-
-    if(!cp)return 0;
-    cp1 = strchr(cp, '\r');
-    return cp1 ? (cp1 - cp) : strlen(cp);
-}
-
-/*********************************************************************
- *  EDIT_GetStr
- *
- *  Return sub-string starting at pixel _off_ of length _len_ pixels.
- *  If _off_ is part way through a character, the negative offset of
- *  the beginning of the character is returned in _diff_, else _diff_ 
- *  will be zero.
- */
-static HANDLE EDIT_GetStr(HWND hwnd, char *lp, int off, int len, int *diff)
-{
-    HANDLE hStr;
-    char *str;
-    int ch = 0, i = 0, j, s_i=0;
-    int ch1;
-
-    dprintf_edit(stddeb,"EDIT_GetStr lp='%s'  off=%d  len=%d\n", lp, off, len);
-
-    if (off < 0) off = 0;
-    while (i < off)
-    {
-	s_i = i;
-	i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
-	ch++;
-    }
-    /* if stepped past _off_, go back a character */
-    if (i > off)
-    {
-	i = s_i;
-	ch--;
-    }
-    *diff = off - i;
-    ch1 = ch;
-    while (i < len + off)
-    {
-	if (*(lp + ch) == '\r' || *(lp + ch) == '\n')
-	    break;
-	i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
-	ch++;
-    }
-    
-    hStr = EDIT_HeapAlloc(hwnd, ch - ch1 + 3, LMEM_FIXED);
-    str = (char *)EDIT_HeapLock(hwnd, hStr);
-    for (i = ch1, j = 0; i < ch; i++, j++)
-	str[j] = lp[i];
-    str[j] = '\0';
-    dprintf_edit(stddeb,"EDIT_GetStr: returning %s\n", str);
-    return hStr;
-}
-
-/*********************************************************************
- *  EDIT_WriteText
- *
- *  Write text to a window
- *     lp  - text line
- *     off - offset in text line (in pixels)
- *     len - length from off (in pixels)
- *     row - line in window
- *     col - column in window
- *     rc  - rectangle in which to display line
- *     blank - blank remainder of line?
- *     reverse - reverse color of line?
- */
-static void EDIT_WriteText(HWND hwnd, char *lp, int off, int len, int row, 
-			   int col, RECT *rc, BOOL blank, BOOL reverse)
-{
-    HDC hdc;
-    HANDLE hStr;
-    char *str, *cp, *cp1;
-    int diff=0, tabwidth, scol;
-    HRGN hrgnClip;
-    COLORREF oldTextColor, oldBkgdColor;
-    HFONT oldfont;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    RECT rc2;
-
-    dprintf_edit(stddeb,"EDIT_WriteText lp=%s, off=%d, len=%d, row=%d, col=%d, reverse=%d\n", lp, off, len, row, col, reverse);
-
-    EDIT_CaretHide(hwnd);
-
-    if( off < 0 ) {
-      len += off;
-      col -= off;
-      off = 0;
-    }
-	
-    hdc = GetDC(hwnd);
-    hStr = EDIT_GetStr(hwnd, lp, off, len, &diff);
-    str = (char *)EDIT_HeapLock(hwnd, hStr);
-    hrgnClip = CreateRectRgnIndirect(rc);
-    SelectClipRgn(hdc, hrgnClip);
-    DeleteObject(hrgnClip);
-
-    if (es->hFont)
-	oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
-    else
-        oldfont = 0;		/* -Wall does not see the use of if */
-
-#ifdef WINELIB32
-    SendMessage(GetParent(hwnd), WM_CTLCOLOREDIT, (WPARAM)hdc, (LPARAM)hwnd);
-#else
-    SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WPARAM)hdc,
-		MAKELPARAM(hwnd, CTLCOLOR_EDIT));
-#endif
-
-    if (reverse)
-    {
-	oldBkgdColor = GetBkColor(hdc);
-	oldTextColor = GetTextColor(hdc);
-	SetBkColor(hdc, GetSysColor(COLOR_HIGHLIGHT));
-	SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
-    }
-    else			/* -Wall does not see the use of if */
-        oldTextColor = oldBkgdColor = 0;
-
-    if ((es->PasswordChar && GetWindowLong( hwnd, GWL_STYLE ) & ES_PASSWORD))
-    {
-        int len = strlen(str);
-        char *buff = xmalloc( len+1 );
-        memset( buff, es->PasswordChar, len );
-        buff[len] = '\0';
-	TextOut( hdc, col - diff, row * es->txtht, buff, len );
-    }
-    else if (!(cp = strchr(str, VK_TAB)))
-	TextOut(hdc, col - diff, row * es->txtht, str, strlen(str));
-    else
-    {
-	TextOut(hdc, col - diff, row * es->txtht, str, (int)(cp - str));
-	scol = EDIT_StrWidth(hwnd, str, (int)(cp - str), 0);
-	tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol);
-	SetRect(&rc2, scol, row * es->txtht, scol+tabwidth, (row + 1) * es->txtht);
-	ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rc2, "", 0, NULL);
-	cp++;
-	scol += tabwidth;
-
-	while ((cp1 = strchr(cp, VK_TAB)))
-	{
-	    TextOut(hdc, scol, row * es->txtht, cp, (int)(cp1 - cp));
-	    scol += EDIT_StrWidth(hwnd, cp, (int)(cp1 - cp), scol);
-	    tabwidth = EDIT_CharWidth(hwnd, VK_TAB, scol);
-	    SetRect(&rc2, scol, row * es->txtht, scol+tabwidth, (row + 1) * es->txtht);
-	    ExtTextOut( hdc, 0, 0, ETO_OPAQUE, &rc2, "", 0, NULL );
-	    cp = ++cp1;
-	    scol += tabwidth;
-	}
-
-	TextOut(hdc, scol, row * es->txtht, cp, strlen(cp));
-    }
-
-    if (reverse)
-    {
-	SetBkColor(hdc, oldBkgdColor);
-	SetTextColor(hdc, oldTextColor);
-    }
-
-    /* blank out remainder of line if appropriate */
-    if (blank && ((rc->right - col) > len))
-    {
-        SetRect( &rc2, col + len, row * es->txtht,
-                 rc->right, (row + 1) * es->txtht );
-        ExtTextOut( hdc, 0, 0, ETO_OPAQUE, &rc2, "", 0, NULL );
-    }
-
-    if (es->hFont)
-	SelectObject(hdc, (HANDLE)oldfont);
-
-    EDIT_HeapFree(hwnd, hStr);
-    ReleaseDC(hwnd, hdc);
-}
-
-/*********************************************************************
- *  EDIT_WriteTextLine
- *
- *  Write the line of text at offset _y_ in text buffer to a window.
- */
-static void EDIT_WriteTextLine(HWND hwnd, RECT *rect, int y)
-{
-    int len = 0;
-    unsigned char *lp;
-    int lnlen, lnlen1;
-    int col, off = 0;
-    int sbl, sel, sbc, sec;
-    RECT rc;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    /* initialize rectangle if NULL, else copy */
-    if (rect)
-	CopyRect(&rc, rect);
-    else
-	GetClientRect(hwnd, &rc);
-
-    dprintf_edit(stddeb,"WriteTextLine %d\n", y);
-
-    /* make sure y is inside the window */
-    if (y < es->wtop || y > (es->wtop + es->ClientHeight))
-    {
-	dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is not a displayed line\n", y);
-	return;
-    }
-
-    /* make sure rectangle is within window */
-    if (rc.left >= es->ClientWidth - 1)
-    {
-	dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.left (%d) is greater than right edge\n",
-	       rc.left);
-	return;
-    }
-    if (rc.right <= 0)
-    {
-	dprintf_edit(stddeb,"EDIT_WriteTextLine: rc.right (%d) is less than left edge\n",
-	       rc.right);
-	return;
-    }
-    if (y - es->wtop < (rc.top / es->txtht) || 
-	y - es->wtop > (rc.bottom / es->txtht))
-    {
-	dprintf_edit(stddeb,"EDIT_WriteTextLine: y (%d) is outside window\n", y);
-	return;
-    }
-
-    /* get the text and length of line */
-    lp = EDIT_GetTextLine( hwnd, y );
-    if (lp == NULL) return;
-    
-    lnlen = EDIT_StrWidth( hwnd, lp, strlen(lp), 0 );
-    lnlen1 = lnlen;
-
-    /* build the line to display */
-    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);
-
-    if (SelMarked(es) && (es->HaveFocus))
-    {
-	sbl = es->SelBegLine;
-	sel = es->SelEndLine;
-	sbc = es->SelBegCol;
-	sec = es->SelEndCol;
-
-	/* put lowest marker first */
-	if (sbl > sel)
-	{
-	    SWAP_INT(sbl, sel);
-	    SWAP_INT(sbc, sec);
-	}
-	if (sbl == sel && sbc > sec)
-	    SWAP_INT(sbc, sec);
-
-	if (y < sbl || y > sel)
-	    EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
-			   TRUE, FALSE);
-	else if (y > sbl && y < sel)
-	    EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
-			   TRUE, TRUE);
-	else if (y == sbl)
-	{
-	    col = EDIT_StrWidth(hwnd, lp, sbc, 0);
-	    if (col > (es->wleft + rc.left))
-	    {
-		len = MIN(col - off, rc.right - off);
-		EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, 
-			       rc.left, &rc, FALSE, FALSE);
-		off = col;
-	    }
-	    if (y == sel)
-	    {
-		col = EDIT_StrWidth(hwnd, lp, sec, 0);
-		if (col < (es->wleft + rc.right))
-		{
-		    len = MIN(col - off, rc.right - off);
-		    EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
-				   off - es->wleft, &rc, FALSE, TRUE);
-		    off = col;
-		    len = MIN(lnlen - off, rc.right - off);
-		    EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
-				   off - es->wleft, &rc, TRUE, FALSE);
+	switch (action) {
+	case WB_LEFT:
+		if (!count) 
+			break;
+		if (index)
+			index--;
+		if (s[index] == ' ') {
+			while (index && (s[index] == ' '))
+				index--;
+			if (index) {
+				while (index && (s[index] != ' '))
+					index--;
+				if (s[index] == ' ')
+					index++;
+			}
+		} else {
+			while (index && (s[index] != ' '))
+				index--;
+			if (s[index] == ' ')
+				index++;
 		}
-		else
-		{
-		    len = MIN(lnlen - off, rc.right - off);
-		    EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
-				   off - es->wleft, &rc, TRUE, TRUE);
-		}
-	    }
-	    else
-	    {
-		len = MIN(lnlen - off, rc.right - off);
-		if (col < (es->wleft + rc.right))
-		    EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
-				   off - es->wleft, &rc, TRUE, TRUE);
-	    }
-	}
-	else if (y == sel)
-	{
-	    col = EDIT_StrWidth(hwnd, lp, sec, 0);
-	    if (col < (es->wleft + rc.right))
-	    {
-		len = MIN(col - off, rc.right - off);
-		EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
-			       off - es->wleft, &rc, FALSE, TRUE);
-		off = col;
-		len = MIN(lnlen - off, rc.right - off);
-		EDIT_WriteText(hwnd, lp, off, len, y - es->wtop,
-			       off - es->wleft, &rc, TRUE, FALSE);
-	    }
-	}
-    }
-    else 
-	EDIT_WriteText(hwnd, lp, off, len, y - es->wtop, rc.left, &rc,
-		       TRUE, FALSE);
-
-    free( lp );
-}
-
-/*********************************************************************
- *  EDIT_ComputeVScrollPos
- *
- *  Compute the vertical scroll bar position from the window
- *  position and text width.
- */
-static int EDIT_ComputeVScrollPos(HWND hwnd)
-{
-    int vscrollpos;
-    INT minpos, maxpos;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    GetScrollRange(hwnd, SB_VERT, &minpos, &maxpos);
-
-    if (es->wlines > es->ClientHeight)
-	vscrollpos = (double)(es->wtop) / (double)(es->wlines - 
-		     es->ClientHeight) * (maxpos - minpos);
-    else
-	vscrollpos = minpos;
-
-    return vscrollpos;
-}
-
-/*********************************************************************
- *  EDIT_ComputeHScrollPos
- *
- *  Compute the horizontal scroll bar position from the window
- *  position and text width.
- */
-static int EDIT_ComputeHScrollPos(HWND hwnd)
-{
-    int hscrollpos;
-    INT minpos, maxpos;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    GetScrollRange(hwnd, SB_HORZ, &minpos, &maxpos);
-
-    if (es->textwidth > es->ClientWidth)
-	hscrollpos = (double)(es->wleft) / (double)(es->textwidth - 
-		     es->ClientWidth) * (maxpos - minpos);
-    else
-	hscrollpos = minpos;
-
-    return hscrollpos;
-}
-
-/*********************************************************************
- *  EDIT_KeyHScroll
- *
- *  Scroll text horizontally using cursor keys.
- */
-static void EDIT_KeyHScroll(HWND hwnd, WORD opt)
-{
-    int hscrollpos;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (opt == SB_LINEDOWN)
-    {
-	es->wleft += HSCROLLDIM(es);
-	es->WndCol -= HSCROLLDIM(es);
-    }
-    else
-    {
-	if (es->wleft == 0)
-	    return;
-	if (es->wleft - HSCROLLDIM(es) < 0)
-	{
-	    es->WndCol += es->wleft;
-	    es->wleft = 0;
-	}	    
-	else
-	{
-	    es->wleft -= HSCROLLDIM(es);
-	    es->WndCol += HSCROLLDIM(es);
-	}
-    }
-
-    InvalidateRect(hwnd, NULL, FALSE);
-    UpdateWindow(hwnd);
-
-    if (IsHScrollBar(hwnd))
-    {
-	hscrollpos = EDIT_ComputeHScrollPos(hwnd);
-	SetScrollPos(hwnd, SB_HORZ, hscrollpos, TRUE);
-    }
-}
-
-/*********************************************************************
- *  EDIT_KeyVScrollLine
- *
- *  Scroll text vertically by one line using keyboard.
- */
-static void EDIT_KeyVScrollLine(HWND hwnd, WORD opt)
-{
-    RECT rc;
-    int y, vscrollpos;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (!IsMultiLine(hwnd))
-	return;
-
-    if (opt == SB_LINEDOWN)
-    {
-	/* move down one line */
-	if (es->wtop + es->ClientHeight >= es->wlines)
-	    return;
-	es->wtop++;
-    }
-    else
-    {
-	/* move up one line */
-	if (es->wtop == 0)
-	    return;
-	--es->wtop;
-    }
-
-    if (IsWindowVisible(hwnd))
-    {
-	EDIT_CaretHide(hwnd);    
-
-	/* adjust client bottom to nearest whole line */
-	GetClientRect(hwnd, &rc);
-	rc.bottom = (rc.bottom / es->txtht) * es->txtht;
-
-	if (opt == SB_LINEUP)
-	{
-	    /* move up one line (scroll window down) */
-	    ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
-	    /* write top line */
-	    EDIT_WriteTextLine(hwnd, NULL, es->wtop);
-	    es->WndRow++;
-	}
-	else
-	{
-	    /* move down one line (scroll window up) */
-	    ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
-	    /* write bottom line */
-	    y = (((rc.bottom - rc.top) / es->txtht) - 1);
-	    EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
-	    --es->WndRow;
-	}
-    }
-
-    /* reset the vertical scroll bar */
-    if (IsVScrollBar(hwnd))
-    {
-	vscrollpos = EDIT_ComputeVScrollPos(hwnd);
-	SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
-    }
-}
-
-/*********************************************************************
- *  EDIT_End
- *
- *  End key: move to end of line.
- */
-static void EDIT_End(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    while (*CurrChar && *CurrChar != '\r')
-    {
-	es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
-	es->CurrCol++;
-    }
-
-    if (es->WndCol >= es->ClientWidth)
-    {
-	es->wleft = es->WndCol - es->ClientWidth + HSCROLLDIM(es);
-	es->WndCol -= es->wleft;
-	InvalidateRect(hwnd, NULL, FALSE);
-	UpdateWindow(hwnd);
-    }
-}
-
-/*********************************************************************
- *  EDIT_Home
- *
- *  Home key: move to beginning of line.
- */
-static void EDIT_Home(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    es->CurrCol = es->WndCol = 0;
-    if (es->wleft != 0)
-    {
-	es->wleft = 0;
-	InvalidateRect(hwnd, NULL, FALSE);
-	UpdateWindow(hwnd);
-    }
-}
-
-/*********************************************************************
- *  EDIT_StickEnd
- *
- *  Stick the cursor to the end of the line.
- */
-static void EDIT_StickEnd(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    int len = EDIT_LineLength(hwnd, es->CurrLine);
-    char *cp = EDIT_TextLine(hwnd, es->CurrLine);
-    int currpel;
-
-    es->CurrCol = MIN(len, es->CurrCol);
-    es->WndCol = MIN(EDIT_StrWidth(hwnd, cp, len, 0) - es->wleft, es->WndCol);
-    currpel = EDIT_StrWidth(hwnd, cp, es->CurrCol, 0);
-
-    if (es->wleft > currpel)
-    {
-	es->wleft = MAX(0, currpel - 20);
-	es->WndCol = currpel - es->wleft;
-	UpdateWindow(hwnd);
-    }
-    else if (currpel - es->wleft >= es->ClientWidth)
-    {
-	es->wleft = currpel - (es->ClientWidth - 5);
-	es->WndCol = currpel - es->wleft;
-	UpdateWindow(hwnd);
-    }
-}
-
-/*********************************************************************
- *  EDIT_Downward
- *
- *  Cursor down key: move down one line.
- */
-static void EDIT_Downward(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    dprintf_edit(stddeb,"EDIT_Downward: WndRow=%d, wtop=%d, wlines=%d\n", 
-	     es->WndRow, es->wtop, es->wlines);
-
-    if (IsMultiLine(hwnd) && (es->WndRow + es->wtop + 1 < es->wlines))
-    {
-	es->CurrLine++;
-	if (es->WndRow == es->ClientHeight - 1)
-	{
-	    es->WndRow++;
-	    EDIT_KeyVScrollLine(hwnd, SB_LINEDOWN);
-	}
-	else
-	    es->WndRow++;
-	EDIT_StickEnd(hwnd);
-    }
-}
-
-/*********************************************************************
- *  EDIT_Upward
- *
- *  Cursor up key: move up one line.
- */
-static void EDIT_Upward(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (IsMultiLine(hwnd) && es->CurrLine != 0)
-    {
-	--es->CurrLine;
-	if (es->WndRow == 0)
-	{
-	    --es->WndRow;
-	    EDIT_KeyVScrollLine(hwnd, SB_LINEUP);
-	}
-	else
-	    --es->WndRow;
-	EDIT_StickEnd(hwnd);
-    }
-}
-
-/*********************************************************************
- *  EDIT_Forward
- *
- *  Cursor right key: move right one character position.
- */
-static void EDIT_Forward(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (*CurrChar == '\0')
-	return;
-
-    if (*CurrChar == '\r')
-    {
-        if (es->CurrLine < (es->wlines - 1))
-        {
-	    EDIT_Home(hwnd);
-	    EDIT_Downward(hwnd);
-        }
-    }
-    else
-    {
-	es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
-	es->CurrCol++;
-	if (es->WndCol >= es->ClientWidth)
-	    EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
-    }
-}
-
-/*********************************************************************
- *  EDIT_Backward
- *
- *  Cursor left key: move left one character position.
- */
-static void EDIT_Backward(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (es->CurrCol)
-    {
-	--es->CurrCol;
-	if (*CurrChar == VK_TAB)
-	    es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), 
-					 EDIT_StrWidth(hwnd, 
-					 EDIT_TextLine(hwnd, es->CurrLine), 
-					 es->CurrCol, 0));
-	else
-	    es->WndCol -= EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), 0);
-	if (es->WndCol < 0)
-	    EDIT_KeyHScroll(hwnd, SB_LINEUP);
-    }
-    else if (IsMultiLine(hwnd) && es->CurrLine != 0)
-    {
-	EDIT_Upward(hwnd);
-	EDIT_End(hwnd);
-    }
-}
-
-/*********************************************************************
- *  EDIT_KeyVScrollPage
- *
- *  Scroll text vertically by one page using keyboard.
- */
-static void EDIT_KeyVScrollPage(HWND hwnd, WORD opt)
-{
-    int vscrollpos;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (IsMultiLine(hwnd))
-    {
-	if (opt == SB_PAGEUP)
-	{
-	    if (es->wtop > es->ClientHeight) es->wtop -= es->ClientHeight;
-	}
-	else
-	{
-	    if (es->wtop + es->ClientHeight < es->wlines)
-	    {
-		es->wtop += es->ClientHeight;
-		if (es->wtop > es->wlines - es->ClientHeight)
-		    es->wtop = es->wlines - es->ClientHeight;
-	    }
-	}
-	if (es->wtop < 0)
-	    es->wtop = 0;
-
-	es->CurrLine = es->wtop + es->WndRow;
-	EDIT_StickEnd(hwnd);
-	InvalidateRect(hwnd, NULL, TRUE);
-	UpdateWindow(hwnd);
-
-	/* reset the vertical scroll bar */
-	if (IsVScrollBar(hwnd))
-	{
-	    vscrollpos = EDIT_ComputeVScrollPos(hwnd);
-	    SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
-	}
-    }
-}
-
-#ifdef SUPERFLUOUS_FUNCTIONS
-/*********************************************************************
- *  EDIT_KeyVScrollDoc
- *
- *  Scroll text to top and bottom of document using keyboard.
- */
-static void EDIT_KeyVScrollDoc(HWND hwnd, WORD opt)
-{
-    int vscrollpos;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (!IsMultiLine(hwnd))
-	return;
-
-    if (opt == SB_TOP)
-	es->wtop = es->wleft = 0;
-    else if (es->wtop + es->ClientHeight < es->wlines)
-    {
-	es->wtop = es->wlines - es->ClientHeight;
-	es->wleft = 0;
-    }
-
-    es->CurrLine = es->wlines;
-    es->WndRow = es->wlines - es->wtop;
-    EDIT_End(hwnd);
-    InvalidateRect(hwnd, NULL, TRUE);
-    UpdateWindow(hwnd);
-
-    /* reset the vertical scroll bar */
-    if (IsVScrollBar(hwnd))
-    {
-	vscrollpos = EDIT_ComputeVScrollPos(hwnd);
-	SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
-    }
-}
-#endif
-
-/*********************************************************************
- *  EDIT_DelKey
- *
- *  Delete character to right of cursor.
- */
-static void EDIT_DelKey(HWND hwnd)
-{
-    RECT rc;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    char *currchar = CurrChar;
-    BOOL repaint;
-
-    if (IsMultiLine(hwnd) && !strncmp(currchar,"\r\n\0",3))
-	return;
-
-    if(*currchar == '\n') {
-        repaint = TRUE;
-        strcpy(currchar, currchar + 1);
-    } else if (*currchar == '\r') {
-        repaint = TRUE;
-        strcpy(currchar, currchar + 2);
-    } else {
-        repaint = FALSE;
-        strcpy(currchar, currchar + 1);
-    }
-    NOTIFY_PARENT(hwnd, EN_UPDATE);
-    
-    if (repaint)
-    {
-	EDIT_BuildTextPointers(hwnd);
-	GetClientRect(hwnd, &rc);
-	rc.top = es->WndRow * es->txtht;
-	InvalidateRect(hwnd, &rc, FALSE);
-	UpdateWindow(hwnd);
-    }
-    else
-    {
-	EDIT_ModTextPointers(hwnd, es->CurrLine + 1, -1);
-	EDIT_WriteTextLine(hwnd, NULL, es->WndRow + es->wtop);
-    }
-
-    es->TextChanged = TRUE;
-    NOTIFY_PARENT(hwnd, EN_CHANGE);
-}
-
-/*********************************************************************
- *  EDIT_VScrollLine
- *
- *  Scroll text vertically by one line using scrollbars.
- */
-static void EDIT_VScrollLine(HWND hwnd, WORD opt)
-{
-    RECT rc;
-    int y;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    dprintf_edit(stddeb,"EDIT_VScrollLine: direction=%d\n", opt);
-
-    if (opt == SB_LINEDOWN)
-    {
-	/* move down one line */
-	if (es->wtop + es->ClientHeight >= es->wlines)
-	    return;
-	es->wtop++;
-    }
-    else
-    {
-	/* move up one line */
-	if (es->wtop == 0)
-	    return;
-	--es->wtop;
-    }
-
-    if (IsWindowVisible(hwnd))
-    {
-	EDIT_CaretHide(hwnd);
-
-	/* adjust client bottom to nearest whole line */
-	GetClientRect(hwnd, &rc);
-	rc.bottom = (rc.bottom / es->txtht) * es->txtht;
-
-	if (opt == SB_LINEUP)
-	{
-	    /* move up one line (scroll window down) */
-	    ScrollWindow(hwnd, 0, es->txtht, &rc, &rc);
-	    /* write top line */
-	    EDIT_WriteTextLine(hwnd, NULL, es->wtop);
-	    es->WndRow++;
-	}
-	else
-	{
-	    /* move down one line (scroll window up) */
-	    ScrollWindow(hwnd, 0, -(es->txtht), &rc, &rc);
-	    /* write bottom line */
-	    y = ((rc.bottom - rc.top / es->txtht) - 1);
-	    EDIT_WriteTextLine(hwnd, NULL, es->wtop + y);
-	    --es->WndRow;
-	}
-    }
-}
-
-
-/*********************************************************************
- *  EDIT_VScrollPage
- *
- *  Scroll text vertically by one page using keyboard.
- */
-static void EDIT_VScrollPage(HWND hwnd, WORD opt)
-{
-    int vscrollpos;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (opt == SB_PAGEUP)
-    {
-	if (es->wtop)
-	    es->wtop -= es->ClientHeight;
-    }
-    else
-    {
-	if (es->wtop + es->ClientHeight < es->wlines)
-	{
-	    es->wtop += es->ClientHeight;
-	    if (es->wtop > es->wlines - es->ClientHeight)
-		es->wtop = es->wlines - es->ClientHeight;
-	}
-    }
-    if (es->wtop < 0)
-	es->wtop = 0;
-    
-    InvalidateRect(hwnd, NULL, TRUE);
-    UpdateWindow(hwnd);
-
-    /* reset the vertical scroll bar */
-    if (IsVScrollBar(hwnd))
-    {
-	vscrollpos = EDIT_ComputeVScrollPos(hwnd);
-	SetScrollPos(hwnd, SB_VERT, vscrollpos, TRUE);
-    }
-}
-
-/*********************************************************************
- *  EDIT_PixelToChar
- *
- *  Convert a pixel offset in the given row to a character offset,
- *  adjusting the pixel offset to the nearest whole character if
- *  necessary.
- */
-static int EDIT_PixelToChar(HWND hwnd, int row, int *pixel)
-{
-    int ch = 0, i = 0, s_i = 0;
-    char *text;
-
-    dprintf_edit(stddeb,"EDIT_PixelToChar: row=%d, pixel=%d\n", row, *pixel);
-
-    text = EDIT_TextLine(hwnd, row);
-    while (i < *pixel)
-    {
-	s_i = i;
-	i += EDIT_CharWidth(hwnd, (BYTE)(*(text + ch)), i);
-	ch++;
-    }
-
-    /* if stepped past _pixel_, go back a character */
-    if (i - *pixel)
-    {
-	i = s_i;
-	--ch;
-    }
-    *pixel = i;
-    return ch;
-}
-
-/*********************************************************************
- *  EDIT_ClearText
- *
- *  Clear text from text buffer.
- */
-static void EDIT_ClearText(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    unsigned int blen = EditBufStartLen(hwnd) + 2;
-    char *text;
-
-    dprintf_edit(stddeb,"EDIT_ClearText %d\n",blen);
-    es->hText = EDIT_HeapReAlloc(hwnd, es->hText, blen);
-    text = EDIT_HeapLock(hwnd, es->hText);
-    memset(text, 0, blen);
-    es->textlen = 0;
-    es->wlines = 0;
-    es->CurrLine = es->CurrCol = 0;
-    es->WndRow = es->WndCol = 0;
-    es->wleft = es->wtop = 0;
-    es->textwidth = 0;
-    es->TextChanged = FALSE;
-    EDIT_ClearTextPointers(hwnd);
-}
-
-/*********************************************************************
- *  EDIT_GetLineCol
- *
- *  Return line and column in text buffer from character offset.
- */
-static void EDIT_GetLineCol(HWND hwnd, int off, int *line, int *col)
-{
-    int lineno;
-    char *cp, *cp1;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    char *text = EDIT_HeapLock(hwnd, es->hText);
-
-    /* check for (0,0) */
-    if (!off || !es->wlines)
-    {
-	*line = 0;
-	*col = 0;
-	return;
-    }
-
-    if (off < 0 || off > strlen(text)) off = strlen(text);
-    cp1 = text;
-    for (lineno = 0; lineno < es->wlines; lineno++)
-    {
-	cp = text + es->textptrs[lineno];
-	if (off == (int)(cp - text))
-	{
-	    *line = lineno;
-	    *col = 0;
-	    return;
-	}
-	if (off < (int)(cp - text))
-	    break;
-	cp1 = cp;
-    }
-    *line = lineno - 1;
-    *col = off - (int)(cp1 - text);
-#if 0
-    if (*(text + *col) == '\0')
-	(*col)--;
-#endif
-}
-
-/*********************************************************************
- *  EDIT_UpdateSel
- *
- *  Redraw the current selection, after losing focus, for example.
- */
-static void EDIT_UpdateSel(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    int y, bbl, bel;
-    RECT rc;
-    
-    /* Note which lines need redrawing. */
-    bbl=MIN(es->SelBegLine,es->SelEndLine);
-    bel=MAX(es->SelBegLine,es->SelEndLine);
-
-    /* Redraw the affected lines */
-    GetClientRect(hwnd, &rc);
-    for (y = bbl; y <= bel; y++)
-    {
-        EDIT_WriteTextLine(hwnd, &rc, y);
-    }
-}
-
-/*********************************************************************
- *  EDIT_ClearSel
- *
- *  Clear the current selection.
- */
-static void EDIT_ClearSel(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    int y, bbl, bel;
-    RECT rc;
-    
-    /* Note which lines need redrawing. */
-    bbl=MIN(es->SelBegLine,es->SelEndLine);
-    bel=MAX(es->SelBegLine,es->SelEndLine);
-
-    /* Clear the selection */
-    es->SelBegLine = es->SelBegCol = 0;
-    es->SelEndLine = es->SelEndCol = 0;
-
-    /* Redraw the affected lines */
-    GetClientRect(hwnd, &rc);
-    for (y = bbl; y <= bel; y++)
-    {
-        EDIT_WriteTextLine(hwnd, &rc, y);
-    }
-}
-
-/*********************************************************************
- *  EDIT_SaveDeletedText
- *
- *  Save deleted text in deleted text buffer.
- */
-static void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len,
-				 int line, int col)
-{
-    char *text;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    dprintf_edit( stddeb, "EDIT_SaveDeletedText\n" );
-    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);
-    GlobalUnlock(es->hDeletedText);
-    es->DeletedLength = len;
-    es->DeletedCurrLine = line;
-    es->DeletedCurrCol = col;
-}
-
-/*********************************************************************
- *  EDIT_DeleteSel
- *
- *  Delete the current selected text (if any)
- */
-static void EDIT_DeleteSel(HWND hwnd)
-{
-    char *selStart, *selEnd;
-    int bl, el, bc, ec;
-    int len;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (SelMarked(es))
-    {
-        /* Get the real beginning and ending lines and columns */
-        bl = es->SelBegLine;
-        el = es->SelEndLine;
-        if ( bl > el ) {
-            bl = el;
-            el = es->SelBegLine;
-            bc = es->SelEndCol;
-            ec = es->SelBegCol;
-        } else if ( bl == el ) {
-            bc = MIN(es->SelBegCol,es->SelEndCol);
-            ec = MAX(es->SelBegCol,es->SelEndCol);
-        } else {
-            bc = es->SelBegCol;
-            ec = es->SelEndCol;
-        }
-            
-	selStart = EDIT_TextLine(hwnd, bl) + bc;
-	selEnd = EDIT_TextLine(hwnd, el) + ec;
-	len = (int)(selEnd - selStart);
-	EDIT_SaveDeletedText(hwnd, selStart, len, bl, bc);
-	es->TextChanged = TRUE;
-        EDIT_ClearSel(hwnd);
-	strcpy(selStart, selEnd);
-
-	es->CurrLine = bl;
-	es->CurrCol = bc;
-	es->WndRow = bl - es->wtop;
-	if (es->WndRow < 0)
-	{
-	    es->wtop = bl;
-	    es->WndRow = 0;
-	}
-	es->WndCol = EDIT_StrWidth(hwnd, selStart - bc, bc, 0) - es->wleft;
-
-	EDIT_BuildTextPointers(hwnd);
-	es->PaintBkgd = TRUE;
-
-        InvalidateRect(hwnd, NULL, TRUE);
-        UpdateWindow(hwnd);
-    }
-}
-
-#ifdef SUPERFLUOUS_FUNCTIONS
-/*********************************************************************
- *  EDIT_TextLineNumber
- *
- *  Return the line number in the text buffer of the supplied
- *  character pointer.
- */
-static int EDIT_TextLineNumber(HWND hwnd, char *lp)
-{
-    int lineno;
-    char *cp;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    char *text = EDIT_HeapLock(hwnd, es->hText);
-
-    for (lineno = 0; lineno < es->wlines; lineno++)
-    {
-	cp = text + es->textptrs[lineno];
-	if (cp == lp)
-	    return lineno;
-	if (cp > lp)
-	    break;
-    }
-    return lineno - 1;
-}
-#endif
-
-/*********************************************************************
- *  EDIT_SetAnchor
- *
- *  Set down anchor for text marking.
- */
-static void EDIT_SetAnchor(HWND hwnd, int row, int col)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (SelMarked(es)) EDIT_ClearSel(hwnd);
-    es->SelBegLine = es->SelEndLine = row;
-    es->SelBegCol = es->SelEndCol = col;
-}
-
-/*********************************************************************
- *  EDIT_ExtendSel
- *
- *  Extend selection to the given screen co-ordinates.
- */
-static void EDIT_ExtendSel(HWND hwnd, INT x, INT y)
-{
-    int bbl, bel, bbc;
-    char *cp;
-    int len, line;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    RECT rc;
-
-    dprintf_edit(stddeb,"EDIT_ExtendSel: x=%d, y=%d\n", x, y);
-
-    bbl = es->SelEndLine;
-    bbc = es->SelEndCol;
-    y = MAX(y,0);
-    if (IsMultiLine(hwnd))
-    {
-        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 (!IsMultiLine(hwnd))
-	    es->WndRow = 0;
-    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 = es->wleft + MAX(x,0);
-    if (es->WndCol > EDIT_StrWidth(hwnd, cp, len, 0))
-	es->WndCol = EDIT_StrWidth(hwnd, cp, len, 0);
-    es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
-    es->WndCol -= es->wleft;
-    es->SelEndCol = es->CurrCol;
-
-    bel = es->SelEndLine;
-
-    /* return if no new characters to mark */
-    if (bbl == bel && bbc == es->SelEndCol) return;
-
-    /* put lowest marker first */
-    if (bbl > bel) SWAP_INT(bbl, bel);
-
-    /* Update lines on which selection has changed */
-    GetClientRect(hwnd, &rc);
-    for (y = bbl; y <= bel; y++)
-    {
-        EDIT_WriteTextLine(hwnd, &rc, y);
-    }
-}
-
-/*********************************************************************
- *  EDIT_InsertText
- *
- *  Insert text at current line and column.
- */
-static void EDIT_InsertText(HWND hwnd, char *str, int len)
-{
-    int plen;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    char *p, *text = EDIT_HeapLock(hwnd, es->hText);
-    
-    plen = strlen(text) + len;
-    if (plen + 1 > es->textlen)
-    {
-      dprintf_edit(stddeb,"InsertText: Realloc\n");
-      es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + len);
-      text = EDIT_HeapLock(hwnd, es->hText);
-      es->textlen = plen + 1;
-    }
-    for (p = CurrChar + strlen(CurrChar); p >= CurrChar; p--) p[len] = *p;
-    memcpy(CurrChar, str, len);
-
-    EDIT_BuildTextPointers(hwnd);
-    es->PaintBkgd = TRUE;
-    es->TextChanged = TRUE;
-
-    EDIT_GetLineCol(hwnd, (int)((CurrChar + len) - text), &(es->CurrLine),
-		                                    &(es->CurrCol));
-    es->WndRow = es->CurrLine - es->wtop;
-    es->WndCol = EDIT_StrWidth(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
-				 es->CurrCol, 0) - es->wleft;
-}
-
-/*********************************************************************
- *  EDIT_ClearDeletedText
- *
- *  Clear deleted text buffer.
- */
-static void EDIT_ClearDeletedText(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    GlobalFree(es->hDeletedText);
-    es->hDeletedText = 0;
-    es->DeletedLength = 0;
-}
-
-/*********************************************************************
- *  EDIT_CopyToClipboard
- *
- *  Copy the specified text to the clipboard.
- */
-static void EDIT_CopyToClipboard(HWND hwnd)
-{
-    HANDLE hMem;
-    char *lpMem;
-    int i, len;
-    char *bbl, *bel;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
-    bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
-    len = (int)(bel - bbl);
-
-    hMem = GlobalAlloc(GHND, (DWORD)(len + 1));
-    lpMem = GlobalLock(hMem);
-
-    for (i = 0; i < len; i++)
-	*lpMem++ = *bbl++;
-
-    GlobalUnlock(hMem);
-    OpenClipboard(hwnd);
-    EmptyClipboard();
-    SetClipboardData(CF_TEXT, hMem);
-    CloseClipboard();
-}
-
-/*********************************************************************
- *  EDIT_KeyTyped
- *
- *  Process keystrokes that produce displayable characters.
- */
-static void EDIT_KeyTyped(HWND hwnd, short ch)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    char *text = EDIT_HeapLock(hwnd, es->hText);
-    char *currchar, *p;
-    RECT rc;
-    BOOL FullPaint = FALSE;
-
-    dprintf_edit(stddeb,"EDIT_KeyTyped: ch=%c\n", (char)ch);
-
-    /* delete selected text (if any) */
-    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)
-    {
-	NOTIFY_PARENT(hwnd, EN_ERRSPACE);
-	return;
-    }
-
-    if (*currchar == '\0' && IsMultiLine(hwnd))
-    {
-	/* insert a newline at end of text */
-	*currchar = '\r';
-	*(currchar + 1) = '\n';
-	*(currchar + 2) = '\0';
-	EDIT_BuildTextPointers(hwnd);
-    }
-
-    /* insert the typed character */
-    if (text[es->textlen - 1] != '\0')
-    {
-	/* current text buffer is full */
-	if (es->textlen == es->MaxTextLen)
-	{
-	    /* text buffer is at maximum size */
-	    NOTIFY_PARENT(hwnd, EN_ERRSPACE);
-	    return;
-	}
-
-	/* increase the text buffer size */
-	es->textlen += GROWLENGTH;
-	/* but not above maximum size */
-	if (es->textlen > es->MaxTextLen)
-	    es->textlen = es->MaxTextLen;
-	dprintf_edit( stddeb, "EDIT_KeyTyped: realloc\n" );
-	es->hText = EDIT_HeapReAlloc(hwnd, es->hText, es->textlen + 2);
-	if (!es->hText)
-	    NOTIFY_PARENT(hwnd, EN_ERRSPACE);
-	text = EDIT_HeapLock(hwnd, es->hText);
-	text[es->textlen - 1] = '\0';
-	currchar = CurrChar;
-    }
-    /* make space for new character and put char in buffer */
-    if (ch == '\n')
-    {
-        for (p = currchar + strlen(currchar); p >= currchar; p--) p[2] = p[0];
-	*currchar = '\r';
-	*(currchar + 1) = '\n';
-	EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 2);
-    }
-    else
-    {
-        for (p = currchar + strlen(currchar); p >= currchar; p--) p[1] = p[0];
-	*currchar = ch;
-	EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 1);
-    }
-    es->TextChanged = TRUE;
-    NOTIFY_PARENT(hwnd, EN_UPDATE);
-
-    /* re-adjust textwidth, if necessary, and redraw line */
-    if (IsMultiLine(hwnd) && es->wlines > 1)
-    {
-	es->textwidth = MAX(es->textwidth,
-		    EDIT_StrWidth(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
-		    (int)(EDIT_TextLine(hwnd, es->CurrLine + 1) -
-			  EDIT_TextLine(hwnd, es->CurrLine)), 0));
-    } else {
-      es->textwidth = MAX(es->textwidth,
-			  EDIT_StrWidth(hwnd, text, strlen(text), 0));
-    }
-
-    if (ch == '\n')
-    {
-	if (es->wleft > 0)
-	    FullPaint = TRUE;
-	es->wleft = 0;
-	EDIT_BuildTextPointers(hwnd);
-	EDIT_End(hwnd);
-	EDIT_Forward(hwnd);
-        EDIT_SetAnchor(hwnd, es->CurrLine, es->CurrCol);
-
-	/* invalidate rest of window */
-	GetClientRect(hwnd, &rc);
-	if (!FullPaint)
-	    rc.top = es->WndRow * es->txtht;
-	InvalidateRect(hwnd, &rc, FALSE);
-
-	UpdateWindow(hwnd);
-	NOTIFY_PARENT(hwnd, EN_CHANGE);
-	return;
-    }
-
-    /* test end of window */
-    if (es->WndCol >= es->ClientWidth - 
-	                    EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft))
-    {
-	/* TODO:- Word wrap to be handled here */
-
-/*	if (!(currchar == text + es->MaxTextLen - 2)) */
-	    EDIT_KeyHScroll(hwnd, SB_LINEDOWN);
-    }
-    es->WndCol += EDIT_CharWidth(hwnd, (BYTE)ch, es->WndCol + es->wleft);
-    es->CurrCol++;
-    EDIT_SetAnchor(hwnd, es->CurrLine, es->CurrCol);
-    EDIT_WriteTextLine(hwnd, NULL, es->wtop + es->WndRow);
-    NOTIFY_PARENT(hwnd, EN_CHANGE);
-    dprintf_edit(stddeb,"KeyTyped O.K.\n");
-}
-
-/*********************************************************************
- *  EM_UNDO message function
- */
-static LRESULT EDIT_UndoMsg(HWND hwnd)
-{
-    char *text;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    
-    if (es->hDeletedText)
-    {
-	text = (char *)GlobalLock(es->hDeletedText);
-	es->CurrLine = es->DeletedCurrLine;
-	es->CurrCol = es->DeletedCurrCol;
-	EDIT_InsertText(hwnd, text, es->DeletedLength);
-	GlobalUnlock(es->hDeletedText);
-	EDIT_ClearDeletedText(hwnd);
-
-	es->SelBegLine = es->CurrLine;
-	es->SelBegCol = es->CurrCol;
-	EDIT_GetLineCol(hwnd, (int)((CurrChar + es->DeletedLength) - text), 
-			&(es->CurrLine), &(es->CurrCol));
-	es->WndRow = es->CurrLine - es->wtop;
-	es->WndCol = EDIT_StrWidth(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
-				     es->CurrCol, 0) - es->wleft;
-	es->SelEndLine = es->CurrLine;
-	es->SelEndCol = es->CurrCol;
-
-	InvalidateRect(hwnd, NULL, TRUE);
-	UpdateWindow(hwnd);
-	return 1;
-    }
-    else
-	return 0;
-}
-
-/*********************************************************************
- *  EM_SETHANDLE message function
- */
-static void EDIT_SetHandleMsg(HWND hwnd, WPARAM wParam)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (IsMultiLine(hwnd))
-    {
-	es->hText = (HANDLE)wParam;
-	es->textlen = EDIT_HeapSize(hwnd, es->hText);
-	es->wlines = 0;
-	es->wtop = es->wleft = 0;
-	es->CurrLine = es->CurrCol = 0;
-	es->WndRow = es->WndCol = 0;
-	es->TextChanged = FALSE;
-	es->textwidth = 0;
-	es->SelBegLine = es->SelBegCol = 0;
-	es->SelEndLine = es->SelEndCol = 0;
-	dprintf_edit(stddeb, "EDIT_SetHandleMsg: handle %04x, textlen=%d\n",
-		     wParam, es->textlen);
-
-	EDIT_BuildTextPointers(hwnd);
-	es->PaintBkgd = TRUE;
-	InvalidateRect(hwnd, NULL, TRUE);
-	UpdateWindow(hwnd);
-    }
-}
-
-/*********************************************************************
- *  EM_SETTABSTOPS message function
- */
-static LRESULT EDIT_SetTabStopsMsg(HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    dprintf_edit( stddeb, "EDIT_SetTabStops\n" );
-    es->NumTabStops = wParam;
-    if (wParam == 0)
-	es->TabStops = xrealloc(es->TabStops, 2);
-    else if (wParam == 1)
-    {
-	es->TabStops = xrealloc(es->TabStops, 2);
-	es->TabStops[0] = LOWORD(lParam);
-    }
-    else
-    {
-	es->TabStops = xrealloc(es->TabStops, wParam * sizeof(*es->TabStops));
-	memcpy(es->TabStops, (unsigned short *)PTR_SEG_TO_LIN(lParam), wParam);
-    }
-    return 0;
-}
-
-/*********************************************************************
- *  EM_GETLINE message function
- */
-static LRESULT EDIT_GetLineMsg(HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    char *cp;
-    int len = 0;
-    unsigned char *buffer = (char *)PTR_SEG_TO_LIN(lParam);
-
-       /* the line wanted */
-    cp  = EDIT_TextLine  (hwnd, wParam);
-    len = EDIT_LineLength(hwnd, wParam);
-    
-       /* if cp==NULL nothing will be copied - I hope */
-    if ((char *) NULL == cp && 0 != len) {
-       fprintf(stdnimp,"edit: EDIT_GetLineMsg cp == NULL && len != 0"); 
-       return 0L;
-    }
-
-    if (0>len)
-       fprintf(stdnimp,"edit: EDIT_GetLineMsg len < 0"); 
-
-       /* suggested reason for the following line:
-          never copy more than the buffer's size ? 
-          I thought that this would make sense only if
-          the lstrcpyn fun was used instead of the gnu strncpy.
-       */
-    len = MIN(len, (WORD)(*buffer));
-
-    if (0>len)
-       fprintf(stdnimp,"edit: EDIT_GetLineMsg len < 0 after MIN"); 
-
-    dprintf_edit( stddeb, "EDIT_GetLineMsg: %d %d, len %d\n", (int)(WORD)(*buffer), (int)(WORD)(*(char *)buffer), len);
-    lstrcpyn(buffer, cp, len);
-
-    return (LRESULT)len;
-}
-
-/*********************************************************************
- *  EM_GETSEL message function
- */
-static LRESULT EDIT_GetSelMsg(HWND hwnd)
-{
-    int so, eo;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    so = es->textptrs[es->SelBegLine] + es->SelBegCol;
-    eo = es->textptrs[es->SelEndLine] + es->SelEndCol;
-
-    return (LRESULT)MAKELONG(so, eo);
-}
-
-/*********************************************************************
- *  EM_REPLACESEL message function
- */
-static void EDIT_ReplaceSel(HWND hwnd, LPARAM lParam)
-{
-    EDIT_DeleteSel(hwnd);
-    EDIT_InsertText(hwnd, (char *)PTR_SEG_TO_LIN(lParam),
-                    strlen((char *)PTR_SEG_TO_LIN(lParam)));
-    InvalidateRect(hwnd, NULL, TRUE);
-    UpdateWindow(hwnd);
-}
-
-/*********************************************************************
- *  EM_LINEFROMCHAR message function
- */
-static LRESULT EDIT_LineFromCharMsg(HWND hwnd, WPARAM wParam)
-{
-    int row, col;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (wParam == (WORD)-1)
-	return (LRESULT)(es->SelBegLine);
-    else
-	EDIT_GetLineCol(hwnd, wParam, &row, &col);
-
-    return (LRESULT)row;
-}
-
-
-/*********************************************************************
- *  EM_LINEINDEX message function
- */
-static LRESULT EDIT_LineIndexMsg(HWND hwnd, WPARAM wParam)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (wParam == (WORD)-1) wParam = es->CurrLine;
-    return es->textptrs[wParam];
-}
-
-
-/*********************************************************************
- *  EM_LINELENGTH message function
- */
-static LRESULT EDIT_LineLengthMsg(HWND hwnd, WPARAM wParam)
-{
-    int row, col, len;
-    int sbl, sbc, sel, sec;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    if (wParam == (WORD)-1)
-    {
-	if (SelMarked(es))
-	{
-	    sbl = es->SelBegLine;
-	    sbc = es->SelBegCol;
-	    sel = es->SelEndLine;
-	    sec = es->SelEndCol;
-
-	    if (sbl > sel)
-	    {
-		SWAP_INT(sbl, sel);
-		SWAP_INT(sbc, sec);
-	    }
-	    if (sbl == sel && sbc > sec)
-		SWAP_INT(sbc, sec);
-
-	    if (sbc == sel)
-	    {
-		len = es->textptrs[sbl + 1] - es->textptrs[sbl] - 1;
-		return len - sec - sbc;
-	    }
-
-	    len = es->textptrs[sel + 1] - es->textptrs[sel] - sec - 1;
-	    return len + sbc;
-	}
-	else    /* no selection marked */
-	{
-	    len = es->textptrs[es->CurrLine + 1] - es->textptrs[es->CurrLine] - 1;
-	    return len;
-	}
-    }
-    else    /* line number specified */
-    {
-	EDIT_GetLineCol(hwnd, wParam, &row, &col);
-	len = es->textptrs[row + 1] - es->textptrs[row];
-	return len;
-    }
-}
-
-/*********************************************************************
- *  EM_SETSEL message function
- */
-static void EDIT_SetSelMsg(HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    INT so, eo;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    so = LOWORD(lParam);
-    eo = HIWORD(lParam);
-
-    if (so == -1)       /* if so == -1, clear selection */
-    {
-	EDIT_ClearSel(hwnd);
-	return;
-    }
-
-    if (so == eo)       /* if so == eo, set caret only */
-    {
-	EDIT_GetLineCol(hwnd, (int) so, &(es->CurrLine), &(es->CurrCol));
-	es->WndRow = es->CurrLine - es->wtop;
-
-	if (!wParam)
-	{
-	    if (es->WndRow < 0 || es->WndRow > es->ClientHeight)
-	    {
-		es->wtop = es->CurrLine;
-		es->WndRow = 0;
-	    }
-	    es->WndCol = EDIT_StrWidth(hwnd, 
-					EDIT_TextLine(hwnd, es->CurrLine), 
-					es->CurrCol, 0) - es->wleft;
-	    if (es->WndCol > es->ClientWidth)
-	    {
-		es->wleft = es->WndCol;
-		es->WndCol = 0;
-	    }
-	    else if (es->WndCol < 0)
-	    {
-		es->wleft += es->WndCol;
-		es->WndCol = 0;
-	    }
-	}
-    }
-    else                /* otherwise set selection */
-    {
-	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, (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;
-
-	if (!wParam)          /* don't suppress scrolling of text */
-	{
-	    if (es->WndRow < 0)
-	    {
-		es->wtop = es->SelEndLine;
-		es->WndRow = 0;
-	    }
-	    else if (es->WndRow > es->ClientHeight)
-	    {
-		es->wtop += es->WndRow - es->ClientHeight;
-		es->WndRow = es->ClientHeight;
-	    }
-	    es->WndCol = EDIT_StrWidth(hwnd, 
-					EDIT_TextLine(hwnd, es->SelEndLine), 
-					es->SelEndCol, 0) - es->wleft;
-	    if (es->WndCol > es->ClientWidth)
-	    {
-		es->wleft += es->WndCol - es->ClientWidth;
-		es->WndCol = es->ClientWidth;
-	    }
-	    else if (es->WndCol < 0)
-	    {
-		es->wleft += es->WndCol;
-		es->WndCol = 0;
-	    }
-	}
-
-	InvalidateRect(hwnd, NULL, TRUE);
-	UpdateWindow(hwnd);
-    }
-}
-
-/*********************************************************************
- *  WM_SETFONT
- */
-static void EDIT_WM_SetFont(HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    HDC hdc;
-    TEXTMETRIC tm;
-    HFONT oldfont;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    es->hFont = (HANDLE)wParam;
-    hdc = GetDC(hwnd);
-    oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
-    GetCharWidth(hdc, 0, 255, es->CharWidths);
-    GetTextMetrics(hdc, &tm);
-    es->txtht = tm.tmHeight + tm.tmExternalLeading;
-    SelectObject(hdc, (HANDLE)oldfont);
-    ReleaseDC(hwnd, hdc);
-
-    es->WndRow = (es->CurrLine - es->wtop) / es->txtht;
-    es->WndCol = EDIT_StrWidth(hwnd, EDIT_TextLine(hwnd, es->CurrLine),
-				 es->CurrCol, 0) - es->wleft;
-
-    InvalidateRect(hwnd, NULL, TRUE);
-    es->PaintBkgd = TRUE;
-    if (lParam) UpdateWindow(hwnd);
-    EDIT_RecalcSize(hwnd,es);
-
-    if (es->HaveFocus)
-    {
-	EDIT_CaretHide(hwnd);
-	DestroyCaret();
-	CreateCaret(hwnd, 0, 2, es->txtht);
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-    }
-}
-
-/*********************************************************************
- *  WM_PASTE
- */
-static void EDIT_WM_Paste(HWND hwnd)
-{
-    HANDLE hClipMem;
-    char *lpClipMem;
-
-    OpenClipboard(hwnd);
-    if (!(hClipMem = GetClipboardData(CF_TEXT)))
-    {
-	/* no text in clipboard */
-	CloseClipboard();
-	return;
-    }
-    lpClipMem = GlobalLock(hClipMem);
-    EDIT_InsertText(hwnd, lpClipMem, strlen(lpClipMem));
-    GlobalUnlock(hClipMem);
-    CloseClipboard();
-    InvalidateRect(hwnd, NULL, TRUE);
-    UpdateWindow(hwnd);
-}
-
-/*********************************************************************
- *  WM_PAINT
- */
-static void EDIT_WM_Paint(HWND hwnd)
-{
-    PAINTSTRUCT ps;
-    HDC hdc;
-    int y;
-    RECT rc;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    EDIT_CaretHide(hwnd);
-
-    hdc = BeginPaint(hwnd, &ps);
-    GetClientRect(hwnd, &rc);
-    IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
-
-    dprintf_edit(stddeb,"WM_PAINT: rc=(%d,%d), (%d,%d)\n",
-                 rc.left, rc.top, rc.right, rc.bottom);
-
-    if (es->PaintBkgd)
-	FillWindow(GetParent(hwnd), hwnd, hdc, (HBRUSH)CTLCOLOR_EDIT);
-
-    for (y = (rc.top / es->txtht); y <= (rc.bottom / es->txtht); y++)
-    {
-	if (y < (IsMultiLine(hwnd) ? es->wlines : 1) - es->wtop)
-	    EDIT_WriteTextLine(hwnd, &rc, y + es->wtop);
-    }
-
-    EndPaint(hwnd, &ps);
-}
-
-static BOOL LOCAL_HeapExists(HANDLE ds)
-{
-/* There is always a local heap in WineLib */
-#ifndef WINELIB
-    INSTANCEDATA *ptr = (INSTANCEDATA *)PTR_SEG_OFF_TO_LIN( ds, 0 );
-    if (!ptr->heap) return 0;
-#endif
-    return 1;
-}
-
-/*********************************************************************
- *  WM_NCCREATE
- */
-static long EDIT_WM_NCCreate(HWND hwnd, LPARAM lParam)
-{
-    CREATESTRUCT *createStruct = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
-    WND *wndPtr = WIN_FindWndPtr(hwnd);
-    EDITSTATE *es;
-    char *text = NULL;
-    HANDLE ds;
-
-    /* store pointer to local or global heap in window structure so that */
-    /* EDITSTATE structure itself can be stored on local heap  */
-    /* allocate space for state variable structure */
-    es = xmalloc( sizeof(EDITSTATE) );
-    SetWindowLong( hwnd, 0, (LONG)es );
-    es->textptrs = xmalloc(sizeof(int));
-    es->CharWidths = xmalloc(256 * sizeof(INT));
-    es->ClientWidth = es->ClientHeight = 1;
-    /* --- text buffer */
-    es->MaxTextLen = MAXTEXTLEN + 1;
-    es->PasswordChar = '*';
-    
-    es->WordBreakProc = NULL;
-    
-    /* Caret stuff */
-    es->CaretPrepareCount = 1;
-    es->CaretHidden = FALSE;
-    es->HaveFocus = FALSE;
-    /*
-     * Hack - If there is no local heap then hwnd should be a globalHeap block
-     * and the local heap needs to be initilised to the same size(minus something)
-     * as the global block
-     */
-    ds = WIN_GetWindowInstance(hwnd);
-    
-    if (!LOCAL_HeapExists(ds))
-    {
-        DWORD globalSize;
-        globalSize = GlobalSize(ds);
-        dprintf_edit(stddeb, "No local heap allocated global size is %ld 0x%lx\n",globalSize, globalSize);
-        /*
-         * I assume the local heap should start at 0 
-         */
-        LocalInit(ds, 0, globalSize);
-        /*
-         * Apparantly we should do an UnlockSegment here but i think this
-         * is because LocalInit is supposed to do a LockSegment. Since
-         * Local Init doesn't do this then it doesn't seem like a good idea to do the
-         * UnlockSegment here yet!
-         * UnlockSegment(hwnd);
-         */
-        
-    }
-    
-
-    if (!(createStruct->lpszName))
-    {
-	dprintf_edit( stddeb, "EDIT_WM_NCCREATE: lpszName == 0\n" );
-	es->textlen = EditBufStartLen(hwnd) + 1;
-	es->hText = EDIT_HeapAlloc(hwnd, es->textlen + 2, LMEM_MOVEABLE);
-	text = EDIT_HeapLock(hwnd, es->hText);
-	memset(text, 0, es->textlen + 2);
-        es->wlines = 0;
-        es->textwidth = 0;
-	EDIT_ClearTextPointers(hwnd);
-	if (IsMultiLine(hwnd)) strcpy(text, "\r\n");
-	EDIT_BuildTextPointers(hwnd);
-    }
-    else
-    {
-        char *windowName = (char *)PTR_SEG_TO_LIN( createStruct->lpszName );
-	dprintf_edit( stddeb, "EDIT_WM_NCCREATE: lpszName != 0\n" );
-        
-	if (strlen(windowName) < EditBufStartLen(hwnd))
-	{
-	    es->textlen = EditBufStartLen(hwnd) + 3;
-	    es->hText = EDIT_HeapAlloc(hwnd, es->textlen + 2, LMEM_MOVEABLE);
-            if (es->hText)
-            {
-                text = EDIT_HeapLock(hwnd, es->hText);
-                if (text)
-                {
-                    strcpy(text, windowName);
-                    if(IsMultiLine(hwnd)) {
-                        strcat(text, "\r\n");
-                    }
-                    *(text + es->textlen) = '\0';
-                }
-            }
-	}
-	else
-	{
-	    es->textlen = strlen(windowName) + 3;
-	    es->hText = EDIT_HeapAlloc(hwnd, es->textlen + 2, LMEM_MOVEABLE);
-	    text = EDIT_HeapLock(hwnd, es->hText);
-	    strcpy(text, windowName);
-	    if(IsMultiLine(hwnd)) strcat(text, "\r\n");
-	    *(text + es->textlen) = '\0';
-	}
-        if (text)
-        {
-            *(text + es->textlen + 1) = '\0';
-            EDIT_BuildTextPointers(hwnd);
-        }
-    }
-
-    /* ES_AUTOVSCROLL and ES_AUTOHSCROLL are automatically applied if */
-    /* the corresponding WS_* style is set                            */
-    if (createStruct->style & WS_VSCROLL)
-	wndPtr->dwStyle |= ES_AUTOVSCROLL;
-    if (createStruct->style & WS_HSCROLL)
-	wndPtr->dwStyle |= ES_AUTOHSCROLL;
-
-    /* remove the WS_CAPTION style if it has been set - this is really a  */
-    /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
-    if (wndPtr->dwStyle & WS_BORDER && wndPtr->dwStyle & WS_DLGFRAME)
-	wndPtr->dwStyle ^= WS_DLGFRAME;
-
-    return 1;
-}
-
-/*********************************************************************
- *  WM_CREATE
- */
-static LRESULT EDIT_WM_Create(HWND hwnd, LPARAM lParam)
-{
-    HDC hdc;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    CLASS *classPtr;
-    TEXTMETRIC tm;
-
-    /* initialize state variable structure */
-    hdc = GetDC(hwnd);
-
-    /* --- char width array                                        */
-    /*     only initialise chars <= 32 as X returns strange widths */
-    /*     for other chars                                         */
-    memset(es->CharWidths, 0, 256 * sizeof(INT));
-    GetCharWidth(hdc, 32, 254, &es->CharWidths[32]);
-
-    /* --- other structure variables */
-    GetTextMetrics(hdc, &tm);
-    es->txtht = tm.tmHeight + tm.tmExternalLeading;
-    EDIT_RecalcSize(hwnd,es);
-    es->wtop = es->wleft = 0;
-    es->CurrCol = es->CurrLine = 0;
-    es->WndCol = es->WndRow = 0;
-    es->TextChanged = FALSE;
-    es->SelBegLine = es->SelBegCol = 0;
-    es->SelEndLine = es->SelEndCol = 0;
-    es->hFont = 0;
-    es->hDeletedText = 0;
-    es->DeletedLength = 0;
-    es->NumTabStops = 0;
-    es->TabStops = xmalloc( sizeof(short) );
-
-    /* set up text cursor for edit class */
-    {
-        char editname[] = "EDIT";
-        CLASS_FindClassByName( MAKE_SEGPTR(editname), 0, &classPtr);
-        classPtr->wc.hCursor = LoadCursor(0, IDC_IBEAM);
-    }
-
-    /* paint background on first WM_PAINT */
-    es->PaintBkgd = TRUE;
-
-    ReleaseDC(hwnd, hdc);
-    return 0L;
-}
-
-/*********************************************************************
- *  WM_VSCROLL
- */
-static void EDIT_WM_VScroll(HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-/*
- *    EDITSTATE *es = EDIT_GetEditState(hwnd);
- */
-    if (IsMultiLine(hwnd))
-    {
-	switch (wParam)
-	{
-	case SB_LINEUP:
-	case SB_LINEDOWN:
-	    EDIT_VScrollLine(hwnd, wParam);
-	    break;
-
-	case SB_PAGEUP:
-	case SB_PAGEDOWN:
-	    EDIT_VScrollPage(hwnd, wParam);
-	    break;
-	}
-    }
-}
-
-/*********************************************************************
- *  WM_HSCROLL
- */
-static void EDIT_WM_HScroll(HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-/*
- *    EDITSTATE *es = EDIT_GetEditState(hwnd);
- */
-    switch (wParam)
-    {
-    case SB_LINEUP:
-    case SB_LINEDOWN:
-	break;
-    }
-}
-
-/*********************************************************************
- *  WM_SIZE
- */
-static void EDIT_WM_Size(HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-  
-    EDIT_RecalcSize(hwnd,es);
-    if (wParam != SIZE_MAXIMIZED && wParam != SIZE_RESTORED) return;
-    InvalidateRect(hwnd, NULL, TRUE);
-    es->PaintBkgd = TRUE;
-    UpdateWindow(hwnd);
-}
-
-/*********************************************************************
- *  WM_LBUTTONDOWN
- */
-static void EDIT_WM_LButtonDown(HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-    char *cp;
-    int len;
-    BOOL end = FALSE;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-
-    ButtonDown = TRUE;
-
-    if ((wParam & MK_SHIFT)) {
-        EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
-        return;
-    }
-
-    es->WndRow = HIWORD(lParam) / es->txtht;
-    dprintf_edit( stddeb, "EDIT_LButtonDown: %04x %08lx, WndRow %d\n", wParam,
-		  lParam, es->WndRow );
-    if (!IsMultiLine(hwnd)) es->WndRow = 0;
-    else if (es->WndRow > es->wlines - es->wtop - 1)
-    {
-        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) + es->wleft;
-    if (end || es->WndCol > EDIT_StrWidth(hwnd, cp, len, 0))
-        es->WndCol = EDIT_StrWidth(hwnd, cp, len, 0);
-    dprintf_edit( stddeb, "EDIT_LButtonDown: CurrLine %d wtop %d wndcol %d\n",
-		  es->CurrLine, es->wtop, es->WndCol);
-    es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
-    es->WndCol -= es->wleft;
-
-    ButtonRow = es->CurrLine;
-    ButtonCol = es->CurrCol;
-    EDIT_SetAnchor(hwnd, ButtonRow, ButtonCol);
-}
-
-/*********************************************************************
- *  WM_MOUSEMOVE
- */
-static void EDIT_WM_MouseMove(HWND hwnd, WPARAM wParam, LPARAM lParam)
-{
-/*
- *    EDITSTATE *es = EDIT_GetEditState(hwnd);
- */
-    if (!(wParam & MK_LBUTTON)) return;
-
-    if (ButtonDown)
-    {
-	TextMarking = TRUE;
-	ButtonDown = FALSE;
-    }
-
-    if (TextMarking)
-	EDIT_ExtendSel(hwnd, LOWORD(lParam), HIWORD(lParam));
-}
-
-/*********************************************************************
- *  WM_CHAR
- */
-static void EDIT_WM_Char(HWND hwnd, WPARAM wParam)
-{
-    dprintf_edit(stddeb,"EDIT_WM_Char: wParam=%c\n", (char)wParam);
-
-    switch (wParam)
-    {
-    case '\r':
-    case '\n':
-	if (!IsMultiLine(hwnd))
-	    break;
-	if (IsReadOnly(hwnd))
-	{
-	    EDIT_Home(hwnd);
-	    EDIT_Downward(hwnd);
-	    break;
-	}
-	wParam = '\n';
-	EDIT_KeyTyped(hwnd, wParam);
-	break;
-
-    case VK_TAB:
-	if (IsReadOnly(hwnd)) break;
-	if (!IsMultiLine(hwnd))
-	    break;
-	EDIT_KeyTyped(hwnd, wParam);
-	break;
-
-    default:
-	if (IsReadOnly(hwnd)) break;
-	if (wParam >= 20 && wParam <= 254 && wParam != 127 )
-	    EDIT_KeyTyped(hwnd, wParam);
-	break;
-    }
-}
-
-/*********************************************************************
- *  WM_KEYDOWN
- */
-static void EDIT_WM_KeyDown(HWND hwnd, WPARAM wParam)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
-    BOOL motionKey = FALSE;
-
-    dprintf_edit(stddeb,"EDIT_WM_KeyDown: key=%x\n", wParam);
-
-    switch (wParam)
-    {
-    case VK_UP:
-	if (IsMultiLine(hwnd))
-	    EDIT_Upward(hwnd);
-	else
-	    EDIT_Backward(hwnd);
-        motionKey = TRUE;
-	break;
-
-    case VK_DOWN:
-	if (IsMultiLine(hwnd))
-	    EDIT_Downward(hwnd);
-	else
-	    EDIT_Forward(hwnd);
-        motionKey = TRUE;
-	break;
-
-    case VK_RIGHT:
-	EDIT_Forward(hwnd);
-        motionKey = TRUE;
-	break;
-
-    case VK_LEFT:
-	EDIT_Backward(hwnd);
-        motionKey = TRUE;
-	break;
-
-    case VK_HOME:
-	EDIT_Home(hwnd);
-        motionKey = TRUE;
-	break;
-
-    case VK_END:
-	EDIT_End(hwnd);
-        motionKey = TRUE;
-	break;
-
-    case VK_PRIOR:
-	if (IsMultiLine(hwnd))
-	{
-	    EDIT_KeyVScrollPage(hwnd, SB_PAGEUP);
-	}
-        motionKey = TRUE;
-	break;
-
-    case VK_NEXT:
-	if (IsMultiLine(hwnd))
-	{
-	    EDIT_KeyVScrollPage(hwnd, SB_PAGEDOWN);
-	}
-        motionKey = TRUE;
-	break;
-
-    case VK_BACK:
-	if (IsReadOnly(hwnd)) break;
-	if (SelMarked(es))
-	    EDIT_DeleteSel(hwnd);
-	else
-	{
-	    if (es->CurrCol == 0 && es->CurrLine == 0)
+		ret = index;
 		break;
-	    EDIT_Backward(hwnd);
-	    EDIT_DelKey(hwnd);
+	case WB_RIGHT:
+		if (!count)
+			break;
+		if (index)
+			index--;
+		if (s[index] == ' ')
+			while ((index < count) && (s[index] == ' ')) index++;
+		else {
+			while (s[index] && (s[index] != ' ') && (index < count))
+				index++;
+			while ((s[index] == ' ') && (index < count)) index++;
+		}
+		ret = index;
+		break;
+	case WB_ISDELIMITER:
+		ret = (s[index] == ' ');
+		break;
+	default:
+		fprintf(stderr, "edit: EDIT_WordBreakProc: unknown action code, please report !\n");
+		break;
 	}
-	break;
-
-    case VK_DELETE:
-	if (IsReadOnly(hwnd)) break;
-	if (SelMarked(es))
-	    EDIT_DeleteSel(hwnd);
-	else
-	    EDIT_DelKey(hwnd);
-	break;
-
-    case VK_SHIFT:
-        motionKey = TRUE;
-        break;
-
-    default:
-        return;
-    }
-
-    if(motionKey && (0x8000 & GetKeyState(VK_SHIFT))) {
-        EDIT_ExtendSel(hwnd, es->WndCol, es->WndRow*es->txtht);
-    } else {
-        EDIT_SetAnchor(hwnd, es->CurrLine, es->CurrCol);
-    }
+	return ret;
 }
 
-/*********************************************************************
- *  WM_SETTEXT
- */
-static LRESULT EDIT_WM_SetText(HWND hwnd, LPARAM lParam)
-{
-    int len;
-    char *text,*settext;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
 
-    settext = PTR_SEG_TO_LIN( lParam );
-    dprintf_edit( stddeb,"WM_SetText, length %d\n",strlen(settext) );
-    if (strlen(settext) <= es->MaxTextLen)
-    {
-	len = settext != NULL ? strlen(settext) : 0;
-	EDIT_ClearText(hwnd);
-	es->textlen = len;
-	dprintf_edit( stddeb, "EDIT_WM_SetText: realloc\n" );
-	es->hText = EDIT_HeapReAlloc(hwnd, es->hText, len + 3);
-	text = EDIT_HeapLock(hwnd, es->hText);
-	if (lParam)
-	    strcpy(text, (char *)PTR_SEG_TO_LIN(lParam));
-	text[len]     = '\0';
-	text[len + 1] = '\0';
-	text[len + 2] = '\0';
-	EDIT_BuildTextPointers(hwnd);
-	InvalidateRect(hwnd, NULL, TRUE);
-	es->PaintBkgd = TRUE;
-	es->TextChanged = TRUE;
-	return 0;
-    }
-    else
-	return EN_ERRSPACE;
+/*********************************************************************
+ *
+ *	EM_CANUNDO
+ *
+ */
+static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	return 0L;
 }
 
-/*********************************************************************
- *  WM_LBUTTONDBLCLK
- */
-static void EDIT_WM_LButtonDblClk(HWND hwnd)
-{
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
 
-    dprintf_edit(stddeb, "WM_LBUTTONDBLCLK: hwnd=%d\n", hwnd);
-    if (SelMarked(es)) EDIT_ClearSel(hwnd);
-    es->SelBegLine = es->SelEndLine = es->CurrLine;
-    es->SelBegCol = EDIT_CallWordBreakProc(hwnd,
-			EDIT_TextLine(hwnd, es->CurrLine),
-			es->CurrCol, 
-			EDIT_LineLength(hwnd, es->CurrLine), 
-			WB_LEFT);
-    es->SelEndCol = EDIT_CallWordBreakProc(hwnd,
-			EDIT_TextLine(hwnd, es->CurrLine),
-			es->CurrCol, 
-			EDIT_LineLength(hwnd, es->CurrLine), 
-			WB_RIGHT);
-    EDIT_WriteTextLine(hwnd, NULL, es->CurrLine);
+/*********************************************************************
+ *
+ *	EM_EMPTYUNDOBUFFER
+ *
+ */
+static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	return 0L;
 }
 
+
 /*********************************************************************
- * EditWndProc()
+ *
+ *	EM_FMTLINES
+ *
  */
-LRESULT EditWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+static LRESULT EDIT_EM_FmtLines(WND *wndPtr, WPARAM wParam, LPARAM lParam)
 {
-    LRESULT lResult = 0;
-    char *textPtr;
-    int len;
-    EDITSTATE *es = EDIT_GetEditState(hwnd);
+	fprintf(stdnimp, "edit: EM_FMTLINES: message not implemented.\n");
+	return wParam ? -1L : 0L;
+}
 
-    EDIT_CaretPrepare(hwnd);
 
-    switch (uMsg) {
-    case EM_CANUNDO:
-	lResult = (LRESULT)es->hDeletedText;
-	break;
+/*********************************************************************
+ *
+ *	EM_GETFIRSTVISIBLELINE
+ *
+ */
+static LRESULT EDIT_EM_GetFirstVisibleLine(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	
-    case EM_EMPTYUNDOBUFFER:
-	EDIT_ClearDeletedText(hwnd);
-	break;
+	return (LRESULT)es->FirstVisibleLine;
+}
 
-    case EM_FMTLINES:
-	fprintf(stdnimp,"edit: EM_FMTLINES message received\n");
-	if (!wParam)
-	    lResult = 1L;
-	else
-	    lResult = 0L;
-	break;
 
-    case EM_GETFIRSTVISIBLELINE:
-	lResult = es->wtop;
-	break;
+/*********************************************************************
+ *
+ *	EM_GETHANDLE
+ *
+ */
+static LRESULT EDIT_EM_GetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-    case EM_GETHANDLE:
-	lResult = (LRESULT)es->hText;
-	break;
+	return (LRESULT)es->hBuf;
+}
+ 
 
-    case EM_GETLINE:
-	if (IsMultiLine(hwnd))
-	    lResult = EDIT_GetLineMsg(hwnd, wParam, lParam);
-	break;
+/*********************************************************************
+ *
+ *	EM_GETLINE
+ *
+ */
+static LRESULT EDIT_EM_GetLine(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	char *text;
+	char *src;
+	char *dst;
+	int len;
+	int i;
+	int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L);
 
-    case EM_GETLINECOUNT:
-	if (IsMultiLine(hwnd))
-	    lResult = es->wlines;
-	break;
+	if (!IsMultiLine(wndPtr))
+		wParam = 0;
+	if ((UINT)wParam >= linecount)
+		return 0L;
+	text = EDIT_GetPointer(wndPtr);
+	src = text + EDIT_EM_LineIndex(wndPtr, wParam, 0L);
+	dst = (char *)PTR_SEG_TO_LIN(lParam);
+	len = MIN(*(WORD *)dst, EDIT_EM_LineLength(wndPtr, wParam, 0L));
+	for (i = 0 ; i < len ; i++) {
+		*dst = *src;
+		src++;
+		dst++;
+	}
+	return (LRESULT)len;
+}
 
-    case EM_GETMODIFY:
-	lResult = es->TextChanged;
-	break;
 
-    case EM_GETPASSWORDCHAR:
-        lResult = es->PasswordChar;
-	break;
+/*********************************************************************
+ *
+ *	EM_GETLINECOUNT
+ *
+ */
+static LRESULT EDIT_EM_GetLineCount(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	
+	return (LRESULT)es->LineCount;
+}
 
-    case EM_GETRECT:
-	GetWindowRect(hwnd, (LPRECT)PTR_SEG_TO_LIN(lParam));
-	break;
 
-    case EM_GETSEL:
-	lResult = EDIT_GetSelMsg(hwnd);
-	break;
+/*********************************************************************
+ *
+ *	EM_GETMODIFY
+ *
+ */
+static LRESULT EDIT_EM_GetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-    case EM_GETWORDBREAKPROC:
-	dprintf_edit(stddeb, "EM_GETWORDBREAKPROC\n");
-	lResult = (LRESULT)es->WordBreakProc;
-	break;
+	return (LRESULT)es->TextChanged;
+}
 
-    case EM_LIMITTEXT:
-	if (wParam)
-	    es->MaxTextLen = wParam;
-	else if (IsMultiLine(hwnd))
-	    es->MaxTextLen = 65535;
-	else
-	    es->MaxTextLen = 32767;
-	break;
 
-    case EM_LINEFROMCHAR:
-	lResult = EDIT_LineFromCharMsg(hwnd, wParam);
-	break;
+/*********************************************************************
+ *
+ *	EM_GETPASSWORDCHAR
+ *
+ */
+static LRESULT EDIT_EM_GetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-    case EM_LINEINDEX:
-	if (IsMultiLine(hwnd))
-	    lResult = EDIT_LineIndexMsg(hwnd, wParam);
-	break;
+	return (LRESULT)es->PasswordChar;
+}
 
-    case EM_LINELENGTH:
-	lResult = EDIT_LineLengthMsg(hwnd, wParam);
-	break;
 
-    case EM_LINESCROLL:
-	fprintf(stdnimp,"edit: cannot process EM_LINESCROLL message\n");
-	break;
+/*********************************************************************
+ *
+ *	EM_GETRECT
+ *
+ */
+static LRESULT EDIT_EM_GetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	return EDIT_GetRect(wndPtr, wParam, (LPARAM)PTR_SEG_TO_LIN(lParam));
+}
 
-    case EM_REPLACESEL:
-	EDIT_ReplaceSel(hwnd, lParam);
-	break;
 
-    case EM_SETHANDLE:
-	EDIT_ClearDeletedText(hwnd);
-	EDIT_SetHandleMsg(hwnd, wParam);
-	break;
+/*********************************************************************
+ *
+ *	EM_GETSEL
+ *
+ */
+static LRESULT EDIT_EM_GetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-    case EM_SETMODIFY:
+	return MAKELONG(es->SelStart, es->SelEnd);
+}
+
+
+/*********************************************************************
+ *
+ *	EM_GETTHUMB
+ *
+ *	undocumented: is this right ?
+ *
+ */
+static LRESULT EDIT_EM_GetThumb(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	return MAKELONG(EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L),
+		EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L));
+}
+
+
+/*********************************************************************
+ *
+ *	EM_GETWORDBREAKPROC
+ *
+ */
+static LRESULT EDIT_EM_GetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	return (LRESULT)es->WordBreakProc;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_LIMITTEXT
+ *
+ */
+static LRESULT EDIT_EM_LimitText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	if (IsMultiLine(wndPtr)) {
+		if (wParam)
+			es->BufLimit = MIN((UINT)wParam, BUFLIMIT_MULTI);
+		else
+			es->BufLimit = BUFLIMIT_MULTI;
+	} else {
+		if (wParam)
+			es->BufLimit = MIN((UINT)wParam, BUFLIMIT_SINGLE);
+		else
+			es->BufLimit = BUFLIMIT_SINGLE;
+	}
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_LINEFROMCHAR
+ *
+ */
+static LRESULT EDIT_EM_LineFromChar(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	int l;
+
+	if (!IsMultiLine(wndPtr))
+		return 0L;
+	if ((INT)wParam == -1)
+		wParam = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	l = EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1;
+	while (EDIT_EM_LineIndex(wndPtr, l, 0L) > (UINT)wParam)
+		l--;
+	return (LRESULT)l;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_LINEINDEX
+ *
+ */
+static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	int e;
+	int l;
+
+	if ((INT)wParam < 0) {
+		e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+		l = EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1;
+		while (es->LineDefs[l].offset > (UINT)wParam)
+			l--;
+		return (LRESULT)es->LineDefs[l].offset;
+	}
+	if (wParam >= es->LineCount)
+		return -1L;
+	return (LRESULT)es->LineDefs[wParam].offset;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_LINELENGTH
+ *
+ */
+static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	int SelStartLine;
+	int SelEndLine;
+
+	if (!IsMultiLine(wndPtr))
+		return (LRESULT)es->LineDefs[0].length;
+	if ((INT)wParam >= 0)
+		return (LRESULT)es->LineDefs[EDIT_EM_LineFromChar(wndPtr, wParam, 0L)].length;
+	SelStartLine = EDIT_EM_LineFromChar(wndPtr, es->SelStart, 0L);
+	SelEndLine = EDIT_EM_LineFromChar(wndPtr, es->SelEnd, 0L);
+	return (LRESULT)(es->SelStart - es->LineDefs[SelStartLine].offset +
+			es->LineDefs[SelEndLine].offset +
+			es->LineDefs[SelEndLine].length - es->SelEnd);
+}
+ 
+
+/*********************************************************************
+ *
+ *	EM_LINESCROLL
+ *
+ */
+static LRESULT EDIT_EM_LineScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	int newfirstvis = firstvis + (INT)LOWORD(lParam);
+	int xoffset = EDIT_GetXOffset(wndPtr);
+	int newxoffset = xoffset + (INT)HIWORD(lParam);
+	int textwidth = EDIT_GetTextWidth(wndPtr);
+	int dx;
+	int dy;
+	POINT pos;
+	HRGN hRgn;
+
+	if (newfirstvis < 0)
+		newfirstvis = 0;
+	if (newfirstvis >= linecount)
+		newfirstvis = linecount - 1;
+
+	if (newxoffset < 0)
+		newxoffset = 0;
+	if (newxoffset >= textwidth)
+		newxoffset = textwidth;
+	dx = xoffset - newxoffset;
+	dy = EDIT_WndYFromLine(wndPtr, firstvis) - EDIT_WndYFromLine(wndPtr, newfirstvis);
+	if (dx || dy) {
+		if (wndPtr->hwndSelf == GetFocus())
+			HideCaret(wndPtr->hwndSelf);
+		if (EDIT_GetRedraw(wndPtr)) {
+			hRgn = CreateRectRgn(0, 0, 0, 0);
+			GetUpdateRgn(wndPtr->hwndSelf, hRgn, FALSE);
+			ValidateRgn(wndPtr->hwndSelf, 0);
+			OffsetRgn(hRgn, dx, dy);
+			InvalidateRgn(wndPtr->hwndSelf, hRgn, TRUE);
+			DeleteObject(hRgn);
+			ScrollWindow(wndPtr->hwndSelf, dx, dy, NULL, NULL);
+		}
+		es->FirstVisibleLine = newfirstvis;
+		es->XOffset = newxoffset;
+		if (IsVScrollBar(wndPtr))
+			SetScrollPos(wndPtr->hwndSelf, SB_VERT,
+				EDIT_WM_VScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
+		if (IsHScrollBar(wndPtr))
+			SetScrollPos(wndPtr->hwndSelf, SB_HORZ,
+				EDIT_WM_HScroll(wndPtr, EM_GETTHUMB, 0L), TRUE);
+		if (wndPtr->hwndSelf == GetFocus()) {
+			GetCaretPos(&pos);
+			SetCaretPos(pos.x + dx, pos.y + dy);
+			ShowCaret(wndPtr->hwndSelf);
+		}
+	}
+	return -1L;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_REPLACESEL
+ *
+ */
+static LRESULT EDIT_EM_ReplaceSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	return (LRESULT)EDIT_ReplaceSel(wndPtr, wParam,
+				(LPARAM)(char *)PTR_SEG_TO_LIN(lParam));
+}
+ 
+
+/*********************************************************************
+ *
+ *	EM_SCROLL
+ *
+ *	FIXME: undocumented message.
+ */
+static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	fprintf(stdnimp, "edit: EM_SCROLL: message not implemented (undocumented), please report.\n");
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETHANDLE
+ *
+ */
+static LRESULT EDIT_EM_SetHandle(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	if (IsMultiLine(wndPtr)) {
+		EDIT_ReleasePointer(wndPtr);
+		/*
+		 *	FIXME:	specs say: old buffer should be freed 
+		 *		by the aplication, but e.g. Notepad doesn't.
+		 *		Should we LOCAL_Free() the old hBuf ?
+		 */
+		LOCAL_Free(wndPtr->hInstance, es->hBuf);
+		es->hBuf = (HLOCAL)wParam;
+		es->BufSize = MIN(1, LOCAL_Size(wndPtr->hInstance, es->hBuf)) - 1;
+		es->hBuf = LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, es->BufSize + 1, LMEM_MOVEABLE);
+		es->LineCount = 0;
+		es->FirstVisibleLine = 0;
+		es->SelStart = es->SelEnd = 0;
+		EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
+		EDIT_EM_SetModify(wndPtr, FALSE, 0L);
+		EDIT_BuildLineDefs(wndPtr);
+		if (EDIT_GetRedraw(wndPtr))
+			InvalidateRect(wndPtr->hwndSelf, NULL, TRUE);
+	}
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETMODIFY
+ *
+ */
+static LRESULT EDIT_EM_SetModify(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
 	es->TextChanged = wParam;
-	break;
-
-    case EM_SETPASSWORDCHAR:
-        es->PasswordChar = (char) wParam;
-	break;
-
-    case EM_SETREADONLY:
-	dprintf_edit(stddeb, "EM_SETREADONLY, wParam=%d\n", wParam);
-	SetWindowLong(hwnd, GWL_STYLE,
-	    (BOOL)wParam ? (GetWindowLong(hwnd, GWL_STYLE) | ES_READONLY)
-		: (GetWindowLong(hwnd, GWL_STYLE) & ~(DWORD)ES_READONLY));
-	break;
-
-    case EM_SETRECT:
-    case EM_SETRECTNP:
-	fprintf(stdnimp,"edit: cannot process EM_SETRECT(NP) message\n");
-	break;
-
-    case EM_SETSEL:
-	EDIT_SetSelMsg(hwnd, wParam, lParam);
-	break;
-
-    case EM_SETTABSTOPS:
-	lResult = EDIT_SetTabStopsMsg(hwnd, wParam, lParam);
-	break;
-
-    case EM_SETWORDBREAKPROC:
-	dprintf_edit(stddeb, "EM_SETWORDBREAKPROC, lParam=%08lx\n",
-			(DWORD)lParam);
-	es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
-	break;
-
-    case EM_UNDO:
-	lResult = EDIT_UndoMsg(hwnd);
-	break;
-
-    case WM_GETDLGCODE:
-        lResult = DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
-	break;
-
-    case WM_CHAR:
-	EDIT_WM_Char(hwnd, wParam);
-	break;
-
-    case WM_COPY:
-	EDIT_CopyToClipboard(hwnd);
-	EDIT_ClearSel(hwnd);
-	break;
-
-    case WM_CREATE:
-	lResult = EDIT_WM_Create(hwnd, lParam);
-	break;
-
-    case WM_CUT:
-	EDIT_CopyToClipboard(hwnd);
-	EDIT_DeleteSel(hwnd);
-	break;
-
-    case WM_DESTROY:
-	free(es->textptrs);
-	free(es->CharWidths);
-	free(es->TabStops);
-	EDIT_HeapFree(hwnd, es->hText);
-	free( EDIT_GetEditState(hwnd) );
-	break;
-
-    case WM_ENABLE:
-	InvalidateRect(hwnd, NULL, FALSE);
-	break;
-
-    case WM_GETTEXT:
-	textPtr = EDIT_HeapLock(hwnd, es->hText);
-	len = strlen( textPtr );
-	if ((int)wParam > len)
-	{
-	    strcpy((char *)PTR_SEG_TO_LIN(lParam), textPtr);
-	    lResult = (LRESULT)len ;
-	}
-	EDIT_HeapUnlock(hwnd, es->hText);
-	break;
-
-    case WM_GETTEXTLENGTH:
-	textPtr = EDIT_HeapLock(hwnd, es->hText);
-	lResult = (LRESULT)strlen(textPtr);
-	EDIT_HeapUnlock(hwnd, es->hText);
-	break;
-
-    case WM_HSCROLL:
-	EDIT_WM_HScroll(hwnd, wParam, lParam);
-	break;
-
-    case WM_KEYDOWN:
-	EDIT_WM_KeyDown(hwnd, wParam);
-	break;
-
-    case WM_KILLFOCUS:
-	dprintf_edit(stddeb, "WM_KILLFOCUS\n");
-	es->HaveFocus = FALSE;
-	DestroyCaret();
-	if (SelMarked(es))
-            if(GetWindowLong(hwnd,GWL_STYLE) & ES_NOHIDESEL)
-	        EDIT_UpdateSel(hwnd);
-            else
-	        EDIT_ClearSel(hwnd);
-	NOTIFY_PARENT(hwnd, EN_KILLFOCUS);
-	break;
-
-    case WM_LBUTTONDOWN:
-	SetFocus(hwnd);
-	SetCapture(hwnd);
-	EDIT_WM_LButtonDown(hwnd, wParam, lParam);
-	break;
-
-    case WM_LBUTTONUP:
-	if (GetCapture() != hwnd) break;
-	ReleaseCapture();
-	ButtonDown = FALSE;
-        TextMarking = FALSE;
-	break;
-
-    case WM_MOUSEMOVE:
-	if (es->HaveFocus)
-	    EDIT_WM_MouseMove(hwnd, wParam, lParam);
-	break;
-
-    case WM_MOVE:
-	break;
-
-    case WM_NCCREATE:
-	lResult = EDIT_WM_NCCreate(hwnd, lParam);
-	break;
-	
-    case WM_PAINT:
-	EDIT_WM_Paint(hwnd);
-	break;
-
-    case WM_PASTE:
-	EDIT_WM_Paste(hwnd);
-	break;
-
-    case WM_SETFOCUS:
-	dprintf_edit(stddeb, "WM_SETFOCUS\n");
-	es->HaveFocus = TRUE;
-	if (SelMarked(es)) EDIT_UpdateSel(hwnd);
-	CreateCaret(hwnd, 0, 2, es->txtht);
-	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
-	es->CaretHidden = TRUE;
-	NOTIFY_PARENT(hwnd, EN_SETFOCUS);
-	break;
-
-    case WM_SETFONT:
-	EDIT_WM_SetFont(hwnd, wParam, lParam);
-	break;
-#if 0
-    case WM_SETREDRAW:
-	dprintf_edit(stddeb, "WM_SETREDRAW: hwnd=%d, wParam=%x\n",
-		     hwnd, wParam);
-	break;
-#endif
-    case WM_SETTEXT:
-	EDIT_ClearDeletedText(hwnd);
-	EDIT_WM_SetText(hwnd, lParam);
-	break;
-
-    case WM_SIZE:
-	EDIT_WM_Size(hwnd, wParam, lParam);
-	break;
-
-    case WM_VSCROLL:
-	EDIT_WM_VScroll(hwnd, wParam, lParam);
-	break;
-
-    case WM_LBUTTONDBLCLK:
-	EDIT_WM_LButtonDblClk(hwnd);
-	break;
-
-    default:
-	lResult = DefWindowProc(hwnd, uMsg, wParam, lParam);
-	break;
-    }
-
-    EDIT_CaretUpdate(hwnd);
-
-    return lResult;
+	return 0L;
 }
 
+
+/*********************************************************************
+ *
+ *	EM_SETPASSWORDCHAR
+ *
+ */
+static LRESULT EDIT_EM_SetPasswordChar(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	es->PasswordChar = (char)wParam;
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETREADONLY
+ *
+ */
+static LRESULT EDIT_EM_SetReadOnly(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	if ((BOOL)wParam)
+		wndPtr->dwStyle |= ES_READONLY;
+	else
+		wndPtr->dwStyle &= ~(DWORD)ES_READONLY;
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETRECT
+ *
+ */
+static LRESULT EDIT_EM_SetRect(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	fprintf(stdnimp,"edit: EM_SETRECT: message not implemented, please report.\n");
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETRECTNP
+ *
+ */
+static LRESULT EDIT_EM_SetRectNP(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	fprintf(stdnimp,"edit: EM_SETRECTNP: message not implemented, please report.\n");
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETSEL
+ *
+ */
+static LRESULT EDIT_EM_SetSel(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	int ns = (INT)LOWORD(lParam);
+	int ne = (INT)HIWORD(lParam);
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int sl;
+	int el;
+	int sc;
+	int ec;
+	int elineindex;
+	int tl = EDIT_WM_GetTextLength(wndPtr, 0, 0L);
+	RECT rc;
+	HRGN hRgn1, hRgn2;
+	HRGN oldRgn, newRgn;
+
+	if (ns < 0) {
+		ne = e;
+		ns = e;
+	} else {
+		ns = MIN(ns, tl);
+		if (ne < 0)
+			ne = tl;
+		ne = MIN(ne, tl);
+	}
+	es->SelStart = ns;
+	es->SelEnd = ne;
+	if (wndPtr->hwndSelf == GetFocus()) {
+		el = EDIT_EM_LineFromChar(wndPtr, ne, 0L);
+		elineindex = EDIT_EM_LineIndex(wndPtr, el, 0L);
+		SetCaretPos(EDIT_WndXFromCol(wndPtr, el, ne - elineindex),
+				EDIT_WndYFromLine(wndPtr, el));
+	}
+	if (wParam)
+		EDIT_ScrollIntoView(wndPtr);
+
+	/*
+	 *	Let's do some repainting
+	 */
+	ORDER_INT(s, e);
+	ORDER_INT(ns, ne);
+	if (EDIT_GetRedraw(wndPtr) && 
+			!(((s == e) && (ns == ne)) ||
+				((ns == s) && (ne == e)))) {
+		/* Yes, there is something to paint */
+		hRgn1 = CreateRectRgn(0, 0, 0, 0);
+		hRgn2 = CreateRectRgn(0, 0, 0, 0);
+		oldRgn = CreateRectRgn(0, 0, 0, 0);
+		newRgn = CreateRectRgn(0, 0, 0, 0);
+		/* Build the old selection region */
+		sl = EDIT_EM_LineFromChar(wndPtr, s, 0L);
+		el = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+		sc = s - EDIT_EM_LineIndex(wndPtr, sl, 0L);
+		ec = e - EDIT_EM_LineIndex(wndPtr, el, 0L);
+		if (sl == el) {
+			EDIT_GetLineRect(wndPtr, sl, sc, ec, &rc);
+			SetRectRgn(oldRgn, rc.left, rc.top, rc.right, rc.bottom);
+		} else {
+			EDIT_GetLineRect(wndPtr, sl, sc, -1, &rc);
+			SetRectRgn(hRgn1, rc.left, rc.top, rc.right, rc.bottom);
+			EDIT_GetLineRect(wndPtr, el, 0, ec, &rc);
+			SetRectRgn(hRgn2, rc.left, rc.top, rc.right, rc.bottom);
+			CombineRgn(oldRgn, hRgn1, hRgn2, RGN_OR);
+			if (el > sl + 1) {
+				EDIT_GetLineRect(wndPtr, sl + 1, 0, -1, &rc);
+				rc.bottom = rc.top + (rc.bottom - rc.top) * (el - sl - 1);
+				CombineRgn(hRgn1, oldRgn, 0, RGN_COPY);
+				SetRectRgn(hRgn2, rc.left, rc.top, rc.right, rc.bottom);
+				CombineRgn(oldRgn, hRgn1, hRgn2, RGN_OR);
+			}
+		}
+		/* Build the new selection region */
+		sl = EDIT_EM_LineFromChar(wndPtr, ns, 0L);
+		el = EDIT_EM_LineFromChar(wndPtr, ne, 0L);
+		sc = ns - EDIT_EM_LineIndex(wndPtr, sl, 0L);
+		ec = ne - EDIT_EM_LineIndex(wndPtr, el, 0L);
+		if (sl == el) {
+			EDIT_GetLineRect(wndPtr, sl, sc, ec, &rc);
+			SetRectRgn(newRgn, rc.left, rc.top, rc.right, rc.bottom);
+		} else {
+			EDIT_GetLineRect(wndPtr, sl, sc, -1, &rc);
+			SetRectRgn(hRgn1, rc.left, rc.top, rc.right, rc.bottom);
+			EDIT_GetLineRect(wndPtr, el, 0, ec, &rc);
+			SetRectRgn(hRgn2, rc.left, rc.top, rc.right, rc.bottom);
+			CombineRgn(newRgn, hRgn1, hRgn2, RGN_OR);
+			if (el > sl + 1) {
+				EDIT_GetLineRect(wndPtr, sl + 1, 0, -1, &rc);
+				rc.bottom = rc.top + (rc.bottom - rc.top) * (el - sl - 1);
+				CombineRgn(hRgn1, newRgn, 0, RGN_COPY);
+				SetRectRgn(hRgn2, rc.left, rc.top, rc.right, rc.bottom);
+				CombineRgn(newRgn, hRgn1, hRgn2, RGN_OR);
+			}
+		}
+		/* Only difference needs painting */
+		CombineRgn(hRgn1, oldRgn, newRgn, RGN_XOR);
+		/* Only part in formatting RECT needs painting */
+		
+		InvalidateRgn(wndPtr->hwndSelf, hRgn1, FALSE);
+		DeleteObject(hRgn1);
+		DeleteObject(hRgn2);
+		DeleteObject(oldRgn);
+		DeleteObject(newRgn);		
+	}
+	return -1L;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETTABSTOPS
+ *
+ */
+static LRESULT EDIT_EM_SetTabStops(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	if (!IsMultiLine(wndPtr))
+		return 0L;
+	if (es->TabStops)
+		free(es->TabStops);
+	es->NumTabStops = wParam;
+	if (wParam == 0)
+		es->TabStops = NULL;
+	else {
+		es->TabStops = (unsigned short *)xmalloc(wParam * sizeof(unsigned short));
+		memcpy(es->TabStops, (unsigned short *)PTR_SEG_TO_LIN(lParam),
+				wParam * sizeof(unsigned short));
+	}
+	return 1L;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_SETWORDBREAKPROC
+ *
+ */
+static LRESULT EDIT_EM_SetWordBreakProc(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	es->WordBreakProc = (EDITWORDBREAKPROC)lParam;
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	EM_UNDO
+ *
+ */
+static LRESULT EDIT_EM_Undo(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_CHAR
+ *
+ */
+static LRESULT EDIT_WM_Char(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	char str[2];
+	char c = (char)wParam;
+
+	switch (c) {
+	case '\r':
+	case '\n':
+		if (IsMultiLine(wndPtr)) {
+			if (IsReadOnly(wndPtr)) {
+				EDIT_MoveHome(wndPtr, FALSE);
+				EDIT_MoveDownward(wndPtr, FALSE);
+			} else
+				EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\r\n");
+		}
+		break;
+	case '\t':
+		if (IsMultiLine(wndPtr) && !IsReadOnly(wndPtr))
+			EDIT_ReplaceSel(wndPtr, 0, (LPARAM)"\t");
+		break;
+	default:
+		if (!IsReadOnly(wndPtr) && (c >= ' ') && (c != 127)) {
+ 			str[0] = c;
+ 			str[1] = '\0';
+ 			EDIT_ReplaceSel(wndPtr, 0, (LPARAM)str);
+ 		}
+		break;
+	}
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_CLEAR
+ *
+ */
+static LRESULT EDIT_WM_Clear(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	char *text;
+	BOOL redraw;
+	
+	if (s != e) {
+		redraw = EDIT_GetRedraw(wndPtr);
+		EDIT_WM_SetRedraw(wndPtr, FALSE, 0L);
+		ORDER_INT(s, e);
+		text = EDIT_GetPointer(wndPtr);
+		strcpy(text + s, text + e);
+		EDIT_BuildLineDefs(wndPtr);
+		EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, s));
+		EDIT_EM_SetModify(wndPtr, TRUE, 0L);
+		EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
+		EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
+		if (redraw) {
+			InvalidateRect(wndPtr->hwndSelf, NULL, TRUE);
+			EDIT_NOTIFY_PARENT(wndPtr, EN_CHANGE);
+		}
+	}
+	return -1L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_COPY
+ *
+ */
+static LRESULT EDIT_WM_Copy(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	HGLOBAL hdst;
+	char *text;
+	char *dst;
+	char *src;
+	int i;
+
+	if (e == s)
+		return -1L;
+	ORDER_INT(s, e);
+	hdst = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(e - s + 1));
+	dst = GlobalLock(hdst);
+	text = EDIT_GetPointer(wndPtr);
+	src = text + s;
+	for (i = 0 ; i < e - s ; i++)
+		*dst++ = *src++;
+	*dst = '\0';
+	GlobalUnlock(hdst);
+	OpenClipboard(wndPtr->hwndSelf);
+	EmptyClipboard();
+	SetClipboardData(CF_TEXT, hdst);
+	CloseClipboard();
+	return -1L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_CREATE
+ *
+ */
+static LRESULT EDIT_WM_Create(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	CREATESTRUCT *cs = (CREATESTRUCT *)PTR_SEG_TO_LIN(lParam);
+	EDITSTATE *es;
+	char *windowName = NULL;
+	char *text;
+
+	es = xmalloc(sizeof(EDITSTATE));
+	memset(es, 0, sizeof(EDITSTATE));
+	*(EDITSTATE **)wndPtr->wExtra = es;
+
+	if (IsMultiLine(wndPtr)) {
+		es->BufLimit = BUFLIMIT_MULTI;
+		es->PasswordChar = '\0';
+	} else {
+		es->BufLimit = BUFLIMIT_SINGLE;
+		es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0';
+	}
+
+	es->BufSize = IsMultiLine(wndPtr) ? BUFSTART_MULTI : BUFSTART_SINGLE;
+	if (cs->lpszName)
+		windowName = (char *)PTR_SEG_TO_LIN(cs->lpszName);
+	if (windowName)
+		es->BufSize = MAX(es->BufSize, strlen(windowName));
+	es->hBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE, es->BufSize + 1);
+	text = EDIT_GetPointer(wndPtr);
+	if (!text) {
+		fprintf(stderr, "edit: WM_CREATE: unable to heap buffer, please report !\n");
+		return -1L;
+	}
+	if (windowName)
+		strcpy(text, windowName);
+	else
+		text[0] = '\0';
+
+	if (cs->style & WS_VSCROLL)
+		cs->style |= ES_AUTOVSCROLL;
+	if (cs->style & WS_HSCROLL)
+		cs->style |= ES_AUTOHSCROLL;
+
+	/* remove the WS_CAPTION style if it has been set - this is really a  */
+	/* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
+	if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME))
+		cs->style ^= WS_DLGFRAME;
+
+	EDIT_WM_SetFont(wndPtr, 0, 0L);
+	EDIT_WM_SetRedraw(wndPtr, TRUE, 0L);
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_CUT
+ *
+ */
+static LRESULT EDIT_WM_Cut(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDIT_WM_Copy(wndPtr, 0, 0L);
+	EDIT_WM_Clear(wndPtr, 0, 0L);
+	return -1L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_DESTROY
+ *
+ */
+static LRESULT EDIT_WM_Destroy(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	free(es->LineDefs);
+	if (es->TabStops)
+		free(es->TabStops);
+	EDIT_ReleasePointer(wndPtr);
+	LOCAL_Free(wndPtr->hInstance, es->hBuf);
+	free(es);
+	*(EDITSTATE **)&wndPtr->wExtra = NULL;
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_ENABLE
+ *
+ */
+static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_ERASEBKGND
+ *
+ */
+static LRESULT EDIT_WM_EraseBkGnd(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	HBRUSH hBrush;
+	RECT rc;
+
+	hBrush = (HBRUSH)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
+
+	GetClientRect(wndPtr->hwndSelf, &rc);
+	IntersectClipRect((HDC)wParam, rc.left, rc.top, rc.right, rc.bottom);
+	GetClipBox((HDC)wParam, &rc);
+	/*
+	 *	FIXME:	specs say that we should UnrealizeObject() the brush,
+	 *		but the specs of UnrealizeObject() say that we shouldn't
+	 *		unrealize a stock object.  The default brush that
+	 *		DefWndProc() returns is ... a stock object.
+	 */
+	FillRect((HDC)wParam, &rc, hBrush);
+	return -1L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_GETDLGCODE
+ *
+ */
+static LRESULT EDIT_WM_GetDlgCode(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	return DLGC_HASSETSEL | DLGC_WANTCHARS | DLGC_WANTARROWS;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_GETFONT
+ *
+ */
+static LRESULT EDIT_WM_GetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	return (LRESULT)es->hFont;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_GETTEXT
+ *
+ */
+static LRESULT EDIT_WM_GetText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	char *text = EDIT_GetPointer(wndPtr);
+	int len;
+	LRESULT lResult = 0L;
+
+	len = strlen(text);
+	if ((int)wParam > len) {
+		strcpy((char *)PTR_SEG_TO_LIN(lParam), text);
+		lResult = (LRESULT)len ;
+	}
+	return lResult;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_GETTEXTLENGTH
+ *
+ */
+static LRESULT EDIT_WM_GetTextLength(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	LRESULT ret;
+	char *text = EDIT_GetPointer(wndPtr);
+
+	ret = (LRESULT)strlen(text);
+	return ret;
+}
+ 
+
+/*********************************************************************
+ *
+ *	WM_HSCROLL
+ *
+ *	FIXME: scrollbar code itself is broken, so this one is a hack.
+ *
+ */
+static LRESULT EDIT_WM_HScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	int wndwidth = EDIT_GetWndWidth(wndPtr);
+	int textwidth = EDIT_GetTextWidth(wndPtr);
+	int charwidth = EDIT_GetAveCharWidth(wndPtr);
+	int xoffset = EDIT_GetXOffset(wndPtr);
+	int dx = 0;
+	BOOL not = TRUE;
+	LRESULT ret = 0L;
+
+	switch (wParam) {
+	case SB_LINELEFT:
+		dx = -charwidth;
+		break;
+	case SB_LINERIGHT:
+		dx = charwidth;
+		break;
+	case SB_PAGELEFT:
+		dx = -wndwidth / HSCROLL_FRACTION / charwidth * charwidth;
+		break;
+	case SB_PAGERIGHT:
+		dx = wndwidth / HSCROLL_FRACTION / charwidth * charwidth;
+		break;
+	case SB_LEFT:
+		dx = -xoffset;
+		break;
+	case SB_RIGHT:
+		dx = textwidth - xoffset;
+		break;
+	case SB_THUMBTRACK:
+/*
+ *		not = FALSE;
+ */
+	case SB_THUMBPOSITION:
+		dx = LOWORD(lParam) * textwidth / 100 - xoffset;
+		break;
+	/* The next two are undocumented ! */
+	case EM_GETTHUMB:
+		ret = textwidth ? MAKELONG(xoffset * 100 / textwidth, 0) : 0;
+		break;
+	case EM_LINESCROLL:
+		dx = LOWORD(lParam);
+		break;
+	case SB_ENDSCROLL:
+	default:
+		break;
+	}
+	if (dx) {
+		EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(0, dx));
+		if (not)
+			EDIT_NOTIFY_PARENT(wndPtr, EN_HSCROLL);
+	}
+	return ret;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_KEYDOWN
+ *
+ *	Handling of special keys that don't produce a WM_CHAR
+ *	(i.e. non-printable keys) & Backspace & Delete
+ *
+ */
+static LRESULT EDIT_WM_KeyDown(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	int s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	BOOL shift;
+	BOOL control;
+
+	if (GetKeyState(VK_MENU) & 0x8000)
+		return 0L;
+
+	shift = GetKeyState(VK_SHIFT) & 0x8000;
+	control = GetKeyState(VK_CONTROL) & 0x8000;
+
+	switch (wParam) {
+	case VK_LEFT:
+	case VK_UP:
+		if (IsMultiLine(wndPtr) && (wParam == VK_UP))
+			EDIT_MoveUpward(wndPtr, shift);
+		else
+			if (control)
+				EDIT_MoveWordBackward(wndPtr, shift);
+			else
+				EDIT_MoveBackward(wndPtr, shift);
+		break;
+	case VK_RIGHT:
+	case VK_DOWN:
+		if (IsMultiLine(wndPtr) && (wParam == VK_DOWN))
+			EDIT_MoveDownward(wndPtr, shift);
+		else if (control)
+			EDIT_MoveWordForward(wndPtr, shift);
+		else
+			EDIT_MoveForward(wndPtr, shift);
+		break;
+	case VK_HOME:
+		EDIT_MoveHome(wndPtr, shift);
+		break;
+	case VK_END:
+		EDIT_MoveEnd(wndPtr, shift);
+		break;
+	case VK_PRIOR:
+		if (IsMultiLine(wndPtr))
+			EDIT_MovePageUp(wndPtr, shift);
+		break;
+	case VK_NEXT:
+		if (IsMultiLine(wndPtr))
+			EDIT_MovePageDown(wndPtr, shift);
+		break;
+	case VK_BACK:
+		if (!IsReadOnly(wndPtr) && !control)
+			if (e != s)
+				EDIT_WM_Clear(wndPtr, 0, 0L);
+			else
+				EDIT_DelLeft(wndPtr);
+		break;
+	case VK_DELETE:
+		if (!IsReadOnly(wndPtr) && !(shift && control))
+			if (e != s) {
+				if (shift)
+					EDIT_WM_Cut(wndPtr, 0, 0L);
+				else
+					EDIT_WM_Clear(wndPtr, 0, 0L);
+			} else {
+				if (shift)
+					EDIT_DelLeft(wndPtr);
+				else if (control)
+					EDIT_DelEnd(wndPtr);
+				else
+					EDIT_DelRight(wndPtr);
+			}
+		break;
+	case VK_INSERT:
+		if (shift) {
+			if (!IsReadOnly(wndPtr))
+				EDIT_WM_Paste(wndPtr, 0, 0L);
+		} else if (control)
+			EDIT_WM_Copy(wndPtr, 0, 0L);
+		break;
+	}
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_KILLFOCUS
+ *
+ */
+static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	DestroyCaret();
+	if(!(wndPtr->dwStyle & ES_NOHIDESEL))
+		EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(-1, 0));
+	EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS);
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_LBUTTONDBLCLK
+ *
+ */
+static LRESULT EDIT_WM_LButtonDblClk(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	int s;
+	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	int l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int lineindex = EDIT_EM_LineIndex(wndPtr, l, 0L);
+	int linelength = EDIT_EM_LineLength(wndPtr, e, 0L);
+	char *text = EDIT_GetPointer(wndPtr);
+
+	s = lineindex + EDIT_CallWordBreakProc(wndPtr, text + lineindex, e - lineindex, linelength, WB_LEFT);
+	e = lineindex + EDIT_CallWordBreakProc(wndPtr, text + lineindex, e - lineindex, linelength, WB_RIGHT);
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_LBUTTONDOWN
+ *
+ */
+static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	int l;
+	int s;
+	int e;
+
+	SetFocus(wndPtr->hwndSelf);
+	SetCapture(wndPtr->hwndSelf);
+	l = EDIT_LineFromWndY(wndPtr, (INT)HIWORD(lParam));
+	e = EDIT_EM_LineIndex(wndPtr, l ,0L) +
+			EDIT_ColFromWndX(wndPtr, l, (INT)LOWORD(lParam));
+	if (GetKeyState(VK_SHIFT) & 0x8000)
+		s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	else 
+		s = e;
+	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_LBUTTONUP
+ *
+ */
+static LRESULT EDIT_WM_LButtonUp(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	if (GetCapture() == wndPtr->hwndSelf)
+		ReleaseCapture();
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_MOUSEMOVE
+ *
+ */
+static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	int Line;
+	int Col;
+	int x = (INT)LOWORD(lParam);
+
+	if (GetCapture() == wndPtr->hwndSelf) {
+		Line = EDIT_LineFromWndY(wndPtr, (INT)HIWORD(lParam));
+		Line = MAX(Line, EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L));
+		Line = MIN(Line, EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L) + EDIT_GetVisibleLineCount(wndPtr) - 1);
+		x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
+		Col = EDIT_ColFromWndX(wndPtr, Line, x);
+		EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(es->SelStart,
+				EDIT_EM_LineIndex(wndPtr, Line, 0L) + Col));
+	}
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_PAINT
+ *
+ */
+static LRESULT EDIT_WM_Paint(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	PAINTSTRUCT ps;
+	int i;
+	int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	HDC hdc;
+	HFONT hFont;
+	HFONT oldFont = 0;
+	RECT rc;
+	RECT rcLine;
+	RECT rcRgn;
+
+	hdc = BeginPaint(wndPtr->hwndSelf, &ps);
+	GetClientRect(wndPtr->hwndSelf, &rc);
+	IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
+	hFont = EDIT_WM_GetFont(wndPtr, 0, 0L);
+	if (hFont)
+		oldFont = SelectObject(hdc, hFont);
+	EDIT_SEND_CTLCOLOR(wndPtr, hdc);
+	GetClipBox(hdc, &rcRgn);
+	for (i = firstvis ; i <= MIN(firstvis + EDIT_GetVisibleLineCount(wndPtr), firstvis + es->LineCount - 1) ; i++ ) {
+		EDIT_GetLineRect(wndPtr, i, 0, -1, &rcLine);
+		if (IntersectRect(&rc, &rcRgn, &rcLine))
+			EDIT_PaintLine(wndPtr, hdc, i);
+	}
+	if (hFont)
+		SelectObject(hdc, oldFont);
+	EndPaint(wndPtr->hwndSelf, &ps);
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_PASTE
+ *
+ */
+static LRESULT EDIT_WM_Paste(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	HGLOBAL hsrc;
+	char *src;
+
+	OpenClipboard(wndPtr->hwndSelf);
+	if ((hsrc = GetClipboardData(CF_TEXT))) {
+		src = (char *)GlobalLock(hsrc);
+		EDIT_ReplaceSel(wndPtr, 0, (LPARAM)src);
+		GlobalUnlock(hsrc);
+	}
+	CloseClipboard();
+	return -1L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_SETCURSOR
+ *
+ */
+static LRESULT EDIT_WM_SetCursor(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	if (LOWORD(lParam) == HTCLIENT) {
+		SetCursor(LoadCursor(0, IDC_IBEAM));
+		return -1L;
+	} else
+		return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_SETFOCUS
+ *
+ */
+static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	LPARAM sel = EDIT_EM_GetSel(wndPtr, 0, 0L);
+
+	CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
+	EDIT_EM_SetSel(wndPtr, FALSE, sel);
+	ShowCaret(wndPtr->hwndSelf);
+	EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS);
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_SETFONT
+ *
+ */
+static LRESULT EDIT_WM_SetFont(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	TEXTMETRIC tm;
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+	LPARAM sel = EDIT_EM_GetSel(wndPtr, 0, 0L);
+	HDC hdc;
+	HFONT oldFont = 0;
+
+	es->hFont = (HFONT)wParam;
+	hdc = GetDC(wndPtr->hwndSelf);
+	if (es->hFont)
+		oldFont = SelectObject(hdc, es->hFont);
+	GetTextMetrics(hdc, &tm);
+	es->LineHeight = HIWORD(GetTextExtent(hdc, "", 0));
+	es->AveCharWidth = tm.tmAveCharWidth;
+	if (es->hFont)
+		SelectObject(hdc, oldFont);
+	ReleaseDC(wndPtr->hwndSelf, hdc);
+	EDIT_BuildLineDefs(wndPtr);
+	if (lParam && EDIT_GetRedraw(wndPtr))
+		InvalidateRect(wndPtr->hwndSelf, NULL, TRUE);
+	if (wndPtr->hwndSelf == GetFocus()) {
+		DestroyCaret();
+		CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
+		EDIT_EM_SetSel(wndPtr, FALSE, sel);
+		ShowCaret(wndPtr->hwndSelf);
+	}
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_SETREDRAW
+ *
+ */
+static LRESULT EDIT_WM_SetRedraw(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDITSTATE *es = EDITSTATEPTR(wndPtr);
+
+	es->Redraw = wParam ? TRUE : FALSE;
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_SETTEXT
+ *
+ */
+static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(0, -1));
+	EDIT_WM_Clear(wndPtr, 0, 0L);
+	if (lParam)
+		EDIT_EM_ReplaceSel(wndPtr, 0, lParam);
+	EDIT_EM_EmptyUndoBuffer(wndPtr, 0, 0L);
+	EDIT_EM_SetModify(wndPtr, TRUE, 0L);
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_SIZE
+ *
+ */
+static LRESULT EDIT_WM_Size(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	if (EDIT_GetRedraw(wndPtr) &&
+			((wParam == SIZE_MAXIMIZED) ||
+				(wParam == SIZE_RESTORED)))
+		InvalidateRect(wndPtr->hwndSelf, NULL, TRUE);
+	return 0L;
+}
+
+
+/*********************************************************************
+ *
+ *	WM_VSCROLL
+ *
+ *	FIXME: scrollbar code itself is broken, so this one is a hack.
+ *
+ */
+static LRESULT EDIT_WM_VScroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
+{
+	int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	int vislinecount = EDIT_GetVisibleLineCount(wndPtr);
+	int dy = 0;
+	BOOL not = TRUE;
+	LRESULT ret = 0L;
+
+	switch (wParam) {
+	case SB_LINEUP:
+		dy = -1;
+		break;
+	case SB_LINEDOWN:
+		dy = 1;
+		break;
+	case SB_PAGEUP:
+		dy = -vislinecount;
+		break;
+	case SB_PAGEDOWN:
+		dy = vislinecount;
+		break;
+	case SB_TOP:
+		dy = -firstvis;
+		break;
+	case SB_BOTTOM:
+		dy = linecount - 1 - firstvis;
+		break;
+	case SB_THUMBTRACK:
+/*
+ *		not = FALSE;
+ */
+	case SB_THUMBPOSITION:
+		dy = LOWORD(lParam) * (linecount - 1) / 100 - firstvis;
+		break;
+	/* The next two are undocumented ! */
+	case EM_GETTHUMB:
+		ret = (linecount > 1) ? MAKELONG(firstvis * 100 / (linecount - 1), 0) : 0L;
+		break;
+	case EM_LINESCROLL:
+		dy = LOWORD(lParam);
+		break;
+	case SB_ENDSCROLL:
+	default:
+		break;
+	}
+	if (dy) {
+		EDIT_EM_LineScroll(wndPtr, 0, MAKELPARAM(dy, 0));
+		if (not)
+			EDIT_NOTIFY_PARENT(wndPtr, EN_VSCROLL);
+	}
+	return ret;
+}
diff --git a/controls/listbox.c b/controls/listbox.c
index 21f66b4..dbec947 100644
--- a/controls/listbox.c
+++ b/controls/listbox.c
@@ -2050,7 +2050,7 @@
     dprintf_listbox( stddeb, "DlgDirSelect: %04x '%s' %d\n", hDlg, lpStr, id );
     if ((i = SendDlgItemMessage( hDlg, id, LB_GETCURSEL, 0, 0 )) == LB_ERR)
         return FALSE;
-    SendDlgItemMessage( hDlg, id, LB_GETTEXT, i, MAKE_SEGPTR(buffer) );
+    SendDlgItemMessage( hDlg, id, LB_GETTEXT, i, (LPARAM)MAKE_SEGPTR(buffer) );
     if (buffer[0] == '[')  /* drive or directory */
     {
         if (buffer[1] == '-')  /* drive */
diff --git a/controls/menu.c b/controls/menu.c
index 33e58b3..7f09a8ea 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -1017,11 +1017,11 @@
 
     do
     {
-        flags = *(WORD *)PTR_SEG_TO_LIN( res );
+        flags = GET_WORD( PTR_SEG_TO_LIN( res ) );
         res += sizeof(WORD);
         if (!(flags & MF_POPUP))
         {
-            id = *(WORD *)PTR_SEG_TO_LIN( res );
+            id = GET_WORD( PTR_SEG_TO_LIN( res ) );
             res += sizeof(WORD);
         }
         data = res;
@@ -2315,7 +2315,7 @@
     
     /* check for Win32 module */
     instance = GetExePtr( instance );
-    if(((NE_MODULE*)GlobalLock(instance))->flags & NE_FFLAGS_WIN32)
+    if (MODULE_GetPtr(instance)->flags & NE_FFLAGS_WIN32)
         return WIN32_LoadMenuA(instance,PTR_SEG_TO_LIN(name));
 
     if (!(hRsrc = FindResource( instance, name, RT_MENU ))) return 0;
diff --git a/debugger/dbg.y b/debugger/dbg.y
index b1ae0e4..e809a37 100644
--- a/debugger/dbg.y
+++ b/debugger/dbg.y
@@ -217,6 +217,18 @@
 }
 
 
+
+/***********************************************************************
+ *           DEBUG_EnterDebugger
+ *
+ * Force an entry into the debugger.
+ */
+void DEBUG_EnterDebugger(void)
+{
+    kill( getpid(), SIGHUP );
+}
+
+
 void wine_debug( int signal, struct sigcontext_struct *regs )
 {
     static int loaded_symbols = 0;
@@ -248,6 +260,12 @@
         addr.off = EIP_reg(DEBUG_context);
         DBG_FIX_ADDR_SEG( &addr, 0 );
 
+        /* Put the display in a correct state */
+
+        XUngrabPointer( display, CurrentTime );
+        XUngrabServer( display );
+        XFlush( display );
+
         if (!addr.seg) newmode = 32;
         else newmode = (GET_SEL_FLAGS(addr.seg) & LDT_FLAGS_32BIT) ? 32 : 16;
 
diff --git a/debugger/hash.c b/debugger/hash.c
index c21c0d0..daeda4a 100644
--- a/debugger/hash.c
+++ b/debugger/hash.c
@@ -217,7 +217,7 @@
 
     for (ok = ModuleFirst(&entry); ok; ok = ModuleNext(&entry))
     {
-        if (!(pModule = (NE_MODULE *)GlobalLock( entry.hModule ))) continue;
+        if (!(pModule = MODULE_GetPtr( entry.hModule ))) continue;
 
         name = (unsigned char *)pModule + pModule->name_table;
 
diff --git a/if1632/kernel32.spec b/if1632/kernel32.spec
index f205374..e58e0cf 100644
--- a/if1632/kernel32.spec
+++ b/if1632/kernel32.spec
@@ -261,7 +261,7 @@
 0256 stub GetPrivateProfileStringW
 0257	stdcall GetProcAddress(long long)	WIN32_GetProcAddress
 0258 stub GetProcessAffinityMask
-0259	return GetProcessHeap 0 0
+0259 stdcall GetProcessHeap() GetProcessHeap
 0260 stub GetProcessHeaps
 0261 stub GetProcessShutdownParameters
 0262 stub GetProcessTimes
@@ -338,18 +338,18 @@
 0332 stub GlobalUnlock
 0333 stub GlobalWire
 0334 stdcall HeapAlloc(long long long) HeapAlloc
-0335 stub HeapCompact
+0335 stdcall HeapCompact(long long) HeapCompact
 0336 stdcall HeapCreate(long long long)	HeapCreate
-0337 stub HeapDestroy
-0338 stub HeapFree
-0339 stub HeapLock
-0340 stub HeapReAlloc
-0341 stub HeapSize
-0342 stub HeapUnlock
-0343 stub HeapValidate
-0344 stub HeapWalk
+0337 stdcall HeapDestroy(long) HeapDestroy
+0338 stdcall HeapFree(long long ptr) HeapFree
+0339 stdcall HeapLock(long) HeapLock
+0340 stdcall HeapReAlloc(long long ptr long) HeapReAlloc
+0341 stdcall HeapSize(long long ptr) HeapSize
+0342 stdcall HeapUnlock(long) HeapUnlock
+0343 stdcall HeapValidate(long long ptr) HeapValidate
+0344 stdcall HeapWalk(long ptr) HeapWalk
 0345 stub InitAtomTable
-0346 stdcall InitializeCriticalSection(ptr)	InitializeCriticalSection
+0346 stdcall InitializeCriticalSection(ptr) InitializeCriticalSection
 0347 stub InterlockedDecrement
 0348 stub InterlockedExchange
 0349 stub InterlockedIncrement
diff --git a/include/debug.h b/include/debug.h
index 1d72191..0fe2002 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -47,6 +47,7 @@
 #undef DEBUG_GDI
 #undef DEBUG_GLOBAL
 #undef DEBUG_GRAPHICS
+#undef DEBUG_HEAP
 #undef DEBUG_HOOK
 #undef DEBUG_ICON
 #undef DEBUG_INT
@@ -126,6 +127,7 @@
 #define DEBUG_GDI
 #define DEBUG_GLOBAL
 #define DEBUG_GRAPHICS
+#define DEBUG_HEAP
 #define DEBUG_HOOK
 #define DEBUG_ICON
 #define DEBUG_INT
@@ -331,6 +333,11 @@
 #else
     0,
 #endif
+#ifdef DEBUG_HEAP
+    1,
+#else
+    0,
+#endif
 #ifdef DEBUG_HOOK
     1,
 #else
@@ -967,8 +974,21 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_hook if(!debug_msg_enabled[31]) ; else fprintf
-#define debugging_hook debug_msg_enabled[31]
+#define dprintf_heap if(!debug_msg_enabled[31]) ; else fprintf
+#define debugging_heap debug_msg_enabled[31]
+#else
+#ifdef DEBUG_HEAP
+#define dprintf_heap fprintf
+#define debugging_heap 1
+#else
+#define dprintf_heap while(0) fprintf
+#define debugging_heap 0
+#endif
+#endif
+
+#ifdef DEBUG_RUNTIME
+#define dprintf_hook if(!debug_msg_enabled[32]) ; else fprintf
+#define debugging_hook debug_msg_enabled[32]
 #else
 #ifdef DEBUG_HOOK
 #define dprintf_hook fprintf
@@ -980,8 +1000,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_icon if(!debug_msg_enabled[32]) ; else fprintf
-#define debugging_icon debug_msg_enabled[32]
+#define dprintf_icon if(!debug_msg_enabled[33]) ; else fprintf
+#define debugging_icon debug_msg_enabled[33]
 #else
 #ifdef DEBUG_ICON
 #define dprintf_icon fprintf
@@ -993,8 +1013,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_int if(!debug_msg_enabled[33]) ; else fprintf
-#define debugging_int debug_msg_enabled[33]
+#define dprintf_int if(!debug_msg_enabled[34]) ; else fprintf
+#define debugging_int debug_msg_enabled[34]
 #else
 #ifdef DEBUG_INT
 #define dprintf_int fprintf
@@ -1006,8 +1026,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_key if(!debug_msg_enabled[34]) ; else fprintf
-#define debugging_key debug_msg_enabled[34]
+#define dprintf_key if(!debug_msg_enabled[35]) ; else fprintf
+#define debugging_key debug_msg_enabled[35]
 #else
 #ifdef DEBUG_KEY
 #define dprintf_key fprintf
@@ -1019,8 +1039,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_keyboard if(!debug_msg_enabled[35]) ; else fprintf
-#define debugging_keyboard debug_msg_enabled[35]
+#define dprintf_keyboard if(!debug_msg_enabled[36]) ; else fprintf
+#define debugging_keyboard debug_msg_enabled[36]
 #else
 #ifdef DEBUG_KEYBOARD
 #define dprintf_keyboard fprintf
@@ -1032,8 +1052,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_ldt if(!debug_msg_enabled[36]) ; else fprintf
-#define debugging_ldt debug_msg_enabled[36]
+#define dprintf_ldt if(!debug_msg_enabled[37]) ; else fprintf
+#define debugging_ldt debug_msg_enabled[37]
 #else
 #ifdef DEBUG_LDT
 #define dprintf_ldt fprintf
@@ -1045,8 +1065,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_listbox if(!debug_msg_enabled[37]) ; else fprintf
-#define debugging_listbox debug_msg_enabled[37]
+#define dprintf_listbox if(!debug_msg_enabled[38]) ; else fprintf
+#define debugging_listbox debug_msg_enabled[38]
 #else
 #ifdef DEBUG_LISTBOX
 #define dprintf_listbox fprintf
@@ -1058,8 +1078,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_local if(!debug_msg_enabled[38]) ; else fprintf
-#define debugging_local debug_msg_enabled[38]
+#define dprintf_local if(!debug_msg_enabled[39]) ; else fprintf
+#define debugging_local debug_msg_enabled[39]
 #else
 #ifdef DEBUG_LOCAL
 #define dprintf_local fprintf
@@ -1071,8 +1091,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mci if(!debug_msg_enabled[39]) ; else fprintf
-#define debugging_mci debug_msg_enabled[39]
+#define dprintf_mci if(!debug_msg_enabled[40]) ; else fprintf
+#define debugging_mci debug_msg_enabled[40]
 #else
 #ifdef DEBUG_MCI
 #define dprintf_mci fprintf
@@ -1084,8 +1104,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mcianim if(!debug_msg_enabled[40]) ; else fprintf
-#define debugging_mcianim debug_msg_enabled[40]
+#define dprintf_mcianim if(!debug_msg_enabled[41]) ; else fprintf
+#define debugging_mcianim debug_msg_enabled[41]
 #else
 #ifdef DEBUG_MCIANIM
 #define dprintf_mcianim fprintf
@@ -1097,8 +1117,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mciwave if(!debug_msg_enabled[41]) ; else fprintf
-#define debugging_mciwave debug_msg_enabled[41]
+#define dprintf_mciwave if(!debug_msg_enabled[42]) ; else fprintf
+#define debugging_mciwave debug_msg_enabled[42]
 #else
 #ifdef DEBUG_MCIWAVE
 #define dprintf_mciwave fprintf
@@ -1110,8 +1130,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mdi if(!debug_msg_enabled[42]) ; else fprintf
-#define debugging_mdi debug_msg_enabled[42]
+#define dprintf_mdi if(!debug_msg_enabled[43]) ; else fprintf
+#define debugging_mdi debug_msg_enabled[43]
 #else
 #ifdef DEBUG_MDI
 #define dprintf_mdi fprintf
@@ -1123,8 +1143,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_menu if(!debug_msg_enabled[43]) ; else fprintf
-#define debugging_menu debug_msg_enabled[43]
+#define dprintf_menu if(!debug_msg_enabled[44]) ; else fprintf
+#define debugging_menu debug_msg_enabled[44]
 #else
 #ifdef DEBUG_MENU
 #define dprintf_menu fprintf
@@ -1136,8 +1156,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_message if(!debug_msg_enabled[44]) ; else fprintf
-#define debugging_message debug_msg_enabled[44]
+#define dprintf_message if(!debug_msg_enabled[45]) ; else fprintf
+#define debugging_message debug_msg_enabled[45]
 #else
 #ifdef DEBUG_MESSAGE
 #define dprintf_message fprintf
@@ -1149,8 +1169,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_metafile if(!debug_msg_enabled[45]) ; else fprintf
-#define debugging_metafile debug_msg_enabled[45]
+#define dprintf_metafile if(!debug_msg_enabled[46]) ; else fprintf
+#define debugging_metafile debug_msg_enabled[46]
 #else
 #ifdef DEBUG_METAFILE
 #define dprintf_metafile fprintf
@@ -1162,8 +1182,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_midi if(!debug_msg_enabled[46]) ; else fprintf
-#define debugging_midi debug_msg_enabled[46]
+#define dprintf_midi if(!debug_msg_enabled[47]) ; else fprintf
+#define debugging_midi debug_msg_enabled[47]
 #else
 #ifdef DEBUG_MIDI
 #define dprintf_midi fprintf
@@ -1175,8 +1195,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mmio if(!debug_msg_enabled[47]) ; else fprintf
-#define debugging_mmio debug_msg_enabled[47]
+#define dprintf_mmio if(!debug_msg_enabled[48]) ; else fprintf
+#define debugging_mmio debug_msg_enabled[48]
 #else
 #ifdef DEBUG_MMIO
 #define dprintf_mmio fprintf
@@ -1188,8 +1208,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mmsys if(!debug_msg_enabled[48]) ; else fprintf
-#define debugging_mmsys debug_msg_enabled[48]
+#define dprintf_mmsys if(!debug_msg_enabled[49]) ; else fprintf
+#define debugging_mmsys debug_msg_enabled[49]
 #else
 #ifdef DEBUG_MMSYS
 #define dprintf_mmsys fprintf
@@ -1201,8 +1221,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_mmtime if(!debug_msg_enabled[49]) ; else fprintf
-#define debugging_mmtime debug_msg_enabled[49]
+#define dprintf_mmtime if(!debug_msg_enabled[50]) ; else fprintf
+#define debugging_mmtime debug_msg_enabled[50]
 #else
 #ifdef DEBUG_MMTIME
 #define dprintf_mmtime fprintf
@@ -1214,8 +1234,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_module if(!debug_msg_enabled[50]) ; else fprintf
-#define debugging_module debug_msg_enabled[50]
+#define dprintf_module if(!debug_msg_enabled[51]) ; else fprintf
+#define debugging_module debug_msg_enabled[51]
 #else
 #ifdef DEBUG_MODULE
 #define dprintf_module fprintf
@@ -1227,8 +1247,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_msg if(!debug_msg_enabled[51]) ; else fprintf
-#define debugging_msg debug_msg_enabled[51]
+#define dprintf_msg if(!debug_msg_enabled[52]) ; else fprintf
+#define debugging_msg debug_msg_enabled[52]
 #else
 #ifdef DEBUG_MSG
 #define dprintf_msg fprintf
@@ -1240,8 +1260,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_nonclient if(!debug_msg_enabled[52]) ; else fprintf
-#define debugging_nonclient debug_msg_enabled[52]
+#define dprintf_nonclient if(!debug_msg_enabled[53]) ; else fprintf
+#define debugging_nonclient debug_msg_enabled[53]
 #else
 #ifdef DEBUG_NONCLIENT
 #define dprintf_nonclient fprintf
@@ -1253,8 +1273,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_ole if(!debug_msg_enabled[53]) ; else fprintf
-#define debugging_ole debug_msg_enabled[53]
+#define dprintf_ole if(!debug_msg_enabled[54]) ; else fprintf
+#define debugging_ole debug_msg_enabled[54]
 #else
 #ifdef DEBUG_OLE
 #define dprintf_ole fprintf
@@ -1266,8 +1286,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_palette if(!debug_msg_enabled[54]) ; else fprintf
-#define debugging_palette debug_msg_enabled[54]
+#define dprintf_palette if(!debug_msg_enabled[55]) ; else fprintf
+#define debugging_palette debug_msg_enabled[55]
 #else
 #ifdef DEBUG_PALETTE
 #define dprintf_palette fprintf
@@ -1279,8 +1299,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_profile if(!debug_msg_enabled[55]) ; else fprintf
-#define debugging_profile debug_msg_enabled[55]
+#define dprintf_profile if(!debug_msg_enabled[56]) ; else fprintf
+#define debugging_profile debug_msg_enabled[56]
 #else
 #ifdef DEBUG_PROFILE
 #define dprintf_profile fprintf
@@ -1292,8 +1312,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_prop if(!debug_msg_enabled[56]) ; else fprintf
-#define debugging_prop debug_msg_enabled[56]
+#define dprintf_prop if(!debug_msg_enabled[57]) ; else fprintf
+#define debugging_prop debug_msg_enabled[57]
 #else
 #ifdef DEBUG_PROP
 #define dprintf_prop fprintf
@@ -1305,8 +1325,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_reg if(!debug_msg_enabled[57]) ; else fprintf
-#define debugging_reg debug_msg_enabled[57]
+#define dprintf_reg if(!debug_msg_enabled[58]) ; else fprintf
+#define debugging_reg debug_msg_enabled[58]
 #else
 #ifdef DEBUG_REG
 #define dprintf_reg fprintf
@@ -1318,8 +1338,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_region if(!debug_msg_enabled[58]) ; else fprintf
-#define debugging_region debug_msg_enabled[58]
+#define dprintf_region if(!debug_msg_enabled[59]) ; else fprintf
+#define debugging_region debug_msg_enabled[59]
 #else
 #ifdef DEBUG_REGION
 #define dprintf_region fprintf
@@ -1331,8 +1351,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_relay if(!debug_msg_enabled[59]) ; else fprintf
-#define debugging_relay debug_msg_enabled[59]
+#define dprintf_relay if(!debug_msg_enabled[60]) ; else fprintf
+#define debugging_relay debug_msg_enabled[60]
 #else
 #ifdef DEBUG_RELAY
 #define dprintf_relay fprintf
@@ -1344,8 +1364,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_resource if(!debug_msg_enabled[60]) ; else fprintf
-#define debugging_resource debug_msg_enabled[60]
+#define dprintf_resource if(!debug_msg_enabled[61]) ; else fprintf
+#define debugging_resource debug_msg_enabled[61]
 #else
 #ifdef DEBUG_RESOURCE
 #define dprintf_resource fprintf
@@ -1357,8 +1377,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_scroll if(!debug_msg_enabled[61]) ; else fprintf
-#define debugging_scroll debug_msg_enabled[61]
+#define dprintf_scroll if(!debug_msg_enabled[62]) ; else fprintf
+#define debugging_scroll debug_msg_enabled[62]
 #else
 #ifdef DEBUG_SCROLL
 #define dprintf_scroll fprintf
@@ -1370,8 +1390,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_selector if(!debug_msg_enabled[62]) ; else fprintf
-#define debugging_selector debug_msg_enabled[62]
+#define dprintf_selector if(!debug_msg_enabled[63]) ; else fprintf
+#define debugging_selector debug_msg_enabled[63]
 #else
 #ifdef DEBUG_SELECTOR
 #define dprintf_selector fprintf
@@ -1383,8 +1403,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_sem if(!debug_msg_enabled[63]) ; else fprintf
-#define debugging_sem debug_msg_enabled[63]
+#define dprintf_sem if(!debug_msg_enabled[64]) ; else fprintf
+#define debugging_sem debug_msg_enabled[64]
 #else
 #ifdef DEBUG_SEM
 #define dprintf_sem fprintf
@@ -1396,8 +1416,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_shm if(!debug_msg_enabled[64]) ; else fprintf
-#define debugging_shm debug_msg_enabled[64]
+#define dprintf_shm if(!debug_msg_enabled[65]) ; else fprintf
+#define debugging_shm debug_msg_enabled[65]
 #else
 #ifdef DEBUG_SHM
 #define dprintf_shm fprintf
@@ -1409,8 +1429,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_stress if(!debug_msg_enabled[65]) ; else fprintf
-#define debugging_stress debug_msg_enabled[65]
+#define dprintf_stress if(!debug_msg_enabled[66]) ; else fprintf
+#define debugging_stress debug_msg_enabled[66]
 #else
 #ifdef DEBUG_STRESS
 #define dprintf_stress fprintf
@@ -1422,8 +1442,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_syscolor if(!debug_msg_enabled[66]) ; else fprintf
-#define debugging_syscolor debug_msg_enabled[66]
+#define dprintf_syscolor if(!debug_msg_enabled[67]) ; else fprintf
+#define debugging_syscolor debug_msg_enabled[67]
 #else
 #ifdef DEBUG_SYSCOLOR
 #define dprintf_syscolor fprintf
@@ -1435,8 +1455,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_task if(!debug_msg_enabled[67]) ; else fprintf
-#define debugging_task debug_msg_enabled[67]
+#define dprintf_task if(!debug_msg_enabled[68]) ; else fprintf
+#define debugging_task debug_msg_enabled[68]
 #else
 #ifdef DEBUG_TASK
 #define dprintf_task fprintf
@@ -1448,8 +1468,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_text if(!debug_msg_enabled[68]) ; else fprintf
-#define debugging_text debug_msg_enabled[68]
+#define dprintf_text if(!debug_msg_enabled[69]) ; else fprintf
+#define debugging_text debug_msg_enabled[69]
 #else
 #ifdef DEBUG_TEXT
 #define dprintf_text fprintf
@@ -1461,8 +1481,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_timer if(!debug_msg_enabled[69]) ; else fprintf
-#define debugging_timer debug_msg_enabled[69]
+#define dprintf_timer if(!debug_msg_enabled[70]) ; else fprintf
+#define debugging_timer debug_msg_enabled[70]
 #else
 #ifdef DEBUG_TIMER
 #define dprintf_timer fprintf
@@ -1474,8 +1494,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_toolhelp if(!debug_msg_enabled[70]) ; else fprintf
-#define debugging_toolhelp debug_msg_enabled[70]
+#define dprintf_toolhelp if(!debug_msg_enabled[71]) ; else fprintf
+#define debugging_toolhelp debug_msg_enabled[71]
 #else
 #ifdef DEBUG_TOOLHELP
 #define dprintf_toolhelp fprintf
@@ -1487,8 +1507,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_utility if(!debug_msg_enabled[71]) ; else fprintf
-#define debugging_utility debug_msg_enabled[71]
+#define dprintf_utility if(!debug_msg_enabled[72]) ; else fprintf
+#define debugging_utility debug_msg_enabled[72]
 #else
 #ifdef DEBUG_UTILITY
 #define dprintf_utility fprintf
@@ -1500,8 +1520,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_vxd if(!debug_msg_enabled[72]) ; else fprintf
-#define debugging_vxd debug_msg_enabled[72]
+#define dprintf_vxd if(!debug_msg_enabled[73]) ; else fprintf
+#define debugging_vxd debug_msg_enabled[73]
 #else
 #ifdef DEBUG_VXD
 #define dprintf_vxd fprintf
@@ -1513,8 +1533,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_win if(!debug_msg_enabled[73]) ; else fprintf
-#define debugging_win debug_msg_enabled[73]
+#define dprintf_win if(!debug_msg_enabled[74]) ; else fprintf
+#define debugging_win debug_msg_enabled[74]
 #else
 #ifdef DEBUG_WIN
 #define dprintf_win fprintf
@@ -1526,8 +1546,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_win32 if(!debug_msg_enabled[74]) ; else fprintf
-#define debugging_win32 debug_msg_enabled[74]
+#define dprintf_win32 if(!debug_msg_enabled[75]) ; else fprintf
+#define debugging_win32 debug_msg_enabled[75]
 #else
 #ifdef DEBUG_WIN32
 #define dprintf_win32 fprintf
@@ -1539,8 +1559,8 @@
 #endif
 
 #ifdef DEBUG_RUNTIME
-#define dprintf_winsock if(!debug_msg_enabled[75]) ; else fprintf
-#define debugging_winsock debug_msg_enabled[75]
+#define dprintf_winsock if(!debug_msg_enabled[76]) ; else fprintf
+#define debugging_winsock debug_msg_enabled[76]
 #else
 #ifdef DEBUG_WINSOCK
 #define dprintf_winsock fprintf
@@ -1586,6 +1606,7 @@
     "gdi",
     "global",
     "graphics",
+    "heap",
     "hook",
     "icon",
     "int",
diff --git a/include/debugger.h b/include/debugger.h
index 1f1a7af..866e202 100644
--- a/include/debugger.h
+++ b/include/debugger.h
@@ -111,6 +111,7 @@
 extern void DEBUG_BackTrace(void);
 
   /* debugger/dbg.y */
+extern void DEBUG_EnterDebugger(void);
 extern void wine_debug( int signal, struct sigcontext_struct * regs );
 
 #endif  /* DEBUGGER_H */
diff --git a/include/dialog.h b/include/dialog.h
index 2eb2d8f..e835b5b 100644
--- a/include/dialog.h
+++ b/include/dialog.h
@@ -33,34 +33,27 @@
 } DIALOGINFO;
 
 
-  /* Dialog template header */
-typedef struct
-{
-    DWORD     style;    
-    BYTE      nbItems WINE_PACKED;
-    WORD      x WINE_PACKED;
-    WORD      y WINE_PACKED;
-    WORD      cx WINE_PACKED;
-    WORD      cy WINE_PACKED;
-} DLGTEMPLATEHEADER;
-
-
   /* Dialog control header */
 typedef struct
 {
+    DWORD      style;
     WORD       x;
     WORD       y;
     WORD       cx;
     WORD       cy;
     WORD       id;
-    DWORD      style WINE_PACKED;
 } DLGCONTROLHEADER;
 
 
   /* Dialog template */
 typedef struct
 {
-    DLGTEMPLATEHEADER  header;
+    DWORD              style;
+    WORD               nbItems;
+    WORD               x;
+    WORD               y;
+    WORD               cx;
+    WORD               cy;
     SEGPTR             menuName;
     SEGPTR             className;
     SEGPTR             caption;
diff --git a/include/handle32.h b/include/handle32.h
index 08ab132..6ebbaa2 100644
--- a/include/handle32.h
+++ b/include/handle32.h
@@ -15,7 +15,7 @@
 
 typedef struct {
     unsigned long       magic;
-} KERNEL_OBJECT, *HANDLE32;
+} KERNEL_OBJECT;
 
 typedef struct {
     KERNEL_OBJECT       common;
diff --git a/include/module.h b/include/module.h
index 01561f1..01c7840 100644
--- a/include/module.h
+++ b/include/module.h
@@ -8,6 +8,7 @@
 #define _WINE_MODULE_H
 
 #include "wintypes.h"
+#include "pe_image.h"
 
 #ifndef WINELIB
 #pragma pack(1)
@@ -16,49 +17,45 @@
   /* In-memory module structure. See 'Windows Internals' p. 219 */
 typedef struct
 {
-    WORD    magic;            /* 'NE' signature */
-    WORD    count;            /* Usage count */
-    WORD    entry_table;      /* Near ptr to entry table */
-    HMODULE next;             /* Selector to next module */
-    WORD    dgroup_entry;     /* Near ptr to segment entry for DGROUP */
-    WORD    fileinfo;         /* Near ptr to file info (OFSTRUCT) */
-    WORD    flags;            /* Module flags */
-    WORD    dgroup;           /* Logical segment for DGROUP */
-    WORD    heap_size;        /* Initial heap size */
-    WORD    stack_size;       /* Initial stack size */
-    WORD    ip;               /* Initial ip */
-    WORD    cs;               /* Initial cs (logical segment) */
-    WORD    sp;               /* Initial stack pointer */
-    WORD    ss;               /* Initial ss (logical segment) */
-    WORD    seg_count;        /* Number of segments in segment table */
-    WORD    modref_count;     /* Number of module references */
-    WORD    nrname_size;      /* Size of non-resident names table */
-    WORD    seg_table;        /* Near ptr to segment table */
-    WORD    res_table;        /* Near ptr to resource table */
-    WORD    name_table;       /* Near ptr to resident names table */
-    WORD    modref_table;     /* Near ptr to module reference table */
-    WORD    import_table;     /* Near ptr to imported names table */
-    DWORD   nrname_fpos;      /* File offset of non-resident names table */
-    WORD    moveable_entries; /* Number of moveable entries in entry table */
-    WORD    alignment;        /* Alignment shift count */
-    WORD    truetype;         /* Set to 2 if TrueType font */
-    BYTE    os_flags;         /* Operating system flags */
-    BYTE    misc_flags;       /* Misc. flags */
-    HANDLE  dlls_to_init;     /* List of DLLs to initialize */
-    HANDLE  nrname_handle;    /* Handle to non-resident name table in memory */
-    WORD    min_swap_area;    /* Min. swap area size */
-    WORD    expected_version; /* Expected Windows version */
-    WORD    self_loading_sel; /* Selector used for self-loading apps. procs */
+    WORD    magic;            /* 00 'NE' signature */
+    WORD    count;            /* 02 Usage count */
+    WORD    entry_table;      /* 04 Near ptr to entry table */
+    HMODULE next;             /* 06 Selector to next module */
+    WORD    dgroup_entry;     /* 08 Near ptr to segment entry for DGROUP */
+    WORD    fileinfo;         /* 0a Near ptr to file info (OFSTRUCT) */
+    WORD    flags;            /* 0c Module flags */
+    WORD    dgroup;           /* 0e Logical segment for DGROUP */
+    WORD    heap_size;        /* 10 Initial heap size */
+    WORD    stack_size;       /* 12 Initial stack size */
+    WORD    ip;               /* 14 Initial ip */
+    WORD    cs;               /* 16 Initial cs (logical segment) */
+    WORD    sp;               /* 18 Initial stack pointer */
+    WORD    ss;               /* 1a Initial ss (logical segment) */
+    WORD    seg_count;        /* 1c Number of segments in segment table */
+    WORD    modref_count;     /* 1e Number of module references */
+    WORD    nrname_size;      /* 20 Size of non-resident names table */
+    WORD    seg_table;        /* 22 Near ptr to segment table */
+    WORD    res_table;        /* 24 Near ptr to resource table */
+    WORD    name_table;       /* 26 Near ptr to resident names table */
+    WORD    modref_table;     /* 28 Near ptr to module reference table */
+    WORD    import_table;     /* 2a Near ptr to imported names table */
+    DWORD   nrname_fpos;      /* 2c File offset of non-resident names table */
+    WORD    moveable_entries; /* 30 Number of moveable entries in entry table*/
+    WORD    alignment;        /* 32 Alignment shift count */
+    WORD    truetype;         /* 34 Set to 2 if TrueType font */
+    BYTE    os_flags;         /* 36 Operating system flags */
+    BYTE    misc_flags;       /* 37 Misc. flags */
+    HANDLE  dlls_to_init;     /* 38 List of DLLs to initialize */
+    HANDLE  nrname_handle;    /* 3a Handle to non-resident name table */
+    WORD    min_swap_area;    /* 3c Min. swap area size */
+    WORD    expected_version; /* 3e Expected Windows version */
+    /* From here, these are extra fields not present in normal Windows */
+    PE_MODULE *pe_module;     /* 40 PE module handle for Win32 modules */
+    HMODULE self;             /* 44 Handle for this module */
+    WORD    self_loading_sel; /* 46 Selector used for self-loading apps. */
 } NE_MODULE;
 
 
-  /* Extra module info appended to NE_MODULE for Win32 modules */
-typedef struct
-{
-    DWORD   pe_module;
-} NE_WIN32_EXTRAINFO;
-
-
   /* In-memory segment table */
 typedef struct
 {
@@ -115,6 +112,7 @@
 #endif
 
 extern BOOL MODULE_Init(void);
+extern NE_MODULE *MODULE_GetPtr( HMODULE hModule );
 extern void MODULE_DumpModule( HMODULE hmodule );
 extern void MODULE_WalkModules(void);
 extern int MODULE_OpenFile( HMODULE hModule );
@@ -128,7 +126,7 @@
 extern FARPROC MODULE_GetWndProcEntry32( const char *name );
 
 extern BOOL NE_LoadSegment( HMODULE hModule, WORD segnum );
-extern void NE_FixupPrologs( HMODULE hModule );
+extern void NE_FixupPrologs( NE_MODULE *pModule );
 extern void NE_InitializeDLLs( HMODULE hModule );
 
 #endif  /* _WINE_MODULE_H */
diff --git a/include/pe_image.h b/include/pe_image.h
index e97d418..f527481 100644
--- a/include/pe_image.h
+++ b/include/pe_image.h
@@ -18,6 +18,8 @@
 	int resource_offset; /* offset to resource typedirectory in file */
 };
 
+typedef struct pe_data PE_MODULE;
+
 extern int PE_unloadImage(HMODULE hModule);
 extern void my_wcstombs(char * result, u_short * source, int len);
 
diff --git a/include/stddebug.h b/include/stddebug.h
index 452812a..7852551 100644
--- a/include/stddebug.h
+++ b/include/stddebug.h
@@ -107,6 +107,7 @@
 #undef DEBUG_GDI
 #undef DEBUG_GLOBAL
 #undef DEBUG_GRAPHICS
+#undef DEBUG_HEAP
 #undef DEBUG_HOOK
 #undef DEBUG_ICON
 #undef DEBUG_INT
@@ -186,6 +187,7 @@
 #define DEBUG_GDI
 #define DEBUG_GLOBAL
 #define DEBUG_GRAPHICS
+#define DEBUG_HEAP
 #define DEBUG_HOOK
 #define DEBUG_ICON
 #define DEBUG_INT
diff --git a/include/winbase.h b/include/winbase.h
index 38f5e3c..66d8e1a 100644
--- a/include/winbase.h
+++ b/include/winbase.h
@@ -1,5 +1,5 @@
-#ifndef _WINBASE_H
-#define _WINBASE_H
+#ifndef __WINE_WINBASE_H
+#define __WINE_WINBASE_H
 
 
 
@@ -19,12 +19,6 @@
 #define WAIT_ABANDONED_0	STATUS_ABANDONED_WAIT_0
 #define WAIT_TIMEOUT		STATUS_TIMEOUT
 
-#define MEM_COMMIT      0x1000
-#define MEM_RESERVE	0x2000
-#define MEM_TOPDOWN	0x100000
-
-#define MEM_RELEASE	0x8000
-
 #define	PAGE_NOACCESS		0x01
 #define	PAGE_READONLY		0x02
 #define	PAGE_READWRITE		0x04
@@ -36,11 +30,14 @@
 #define	PAGE_GUARD		0x100
 #define	PAGE_NOCACHE		0x200
 
-HANDLE WINAPI OpenProcess(DWORD access, BOOL inherit, DWORD id);
-int WINAPI GetCurrentProcessId(void);
-int WINAPI TerminateProcess(HANDLE h, int ret);
-
-WINAPI void *  VirtualAlloc (void *addr,DWORD size,DWORD type,DWORD protect);
+#define MEM_COMMIT              0x00001000
+#define MEM_RESERVE             0x00002000
+#define MEM_DECOMMIT            0x00004000
+#define MEM_RELEASE             0x00008000
+#define MEM_FREE                0x00010000
+#define MEM_PRIVATE             0x00020000
+#define MEM_MAPPED              0x00040000
+#define MEM_TOP_DOWN            0x00100000
 
 struct _EXCEPTION_POINTERS;
 
@@ -105,8 +102,6 @@
   int ss;
 } exception_info;
 
-#endif
-
 
 /*DWORD WINAPI GetVersion( void );*/
 
@@ -122,3 +117,27 @@
 #define FreeModule(hLibModule) FreeLibrary((hLibModule))
 #define MakeProcInstance(lpProc,hInstance) (lpProc)
 #define FreeProcInstance(lpProc) (lpProc)
+
+
+WINAPI void     DeleteCriticalSection(CRITICAL_SECTION *lpCrit);
+WINAPI void     EnterCriticalSection(CRITICAL_SECTION *lpCrit);
+WINAPI int      GetCurrentProcessId(void);
+WINAPI HANDLE32 GetProcessHeap(void);
+WINAPI LPVOID   HeapAlloc(HANDLE32,DWORD,DWORD);
+WINAPI DWORD    HeapCompact(HANDLE32,DWORD);
+WINAPI HANDLE32 HeapCreate(DWORD,DWORD,DWORD);
+WINAPI BOOL     HeapDestroy(HANDLE32);
+WINAPI BOOL     HeapFree(HANDLE32,DWORD,LPVOID);
+WINAPI BOOL     HeapLock(HANDLE32);
+WINAPI LPVOID   HeapReAlloc(HANDLE32,DWORD,LPVOID,DWORD);
+WINAPI DWORD    HeapSize(HANDLE32,DWORD,LPVOID);
+WINAPI BOOL     HeapUnlock(HANDLE32);
+WINAPI BOOL     HeapValidate(HANDLE32,DWORD,LPVOID);
+WINAPI void     InitializeCriticalSection(CRITICAL_SECTION *lpCrit);
+WINAPI void     LeaveCriticalSection(CRITICAL_SECTION *lpCrit);
+WINAPI HANDLE   OpenProcess(DWORD access, BOOL inherit, DWORD id);
+WINAPI int      TerminateProcess(HANDLE h, int ret);
+WINAPI LPVOID   VirtualAlloc(LPVOID addr,DWORD size,DWORD type,DWORD protect);
+WINAPI BOOL     VirtualFree( LPVOID addr, DWORD size, DWORD type );
+
+#endif  /* __WINE_WINBASE_H */
diff --git a/include/winnt.h b/include/winnt.h
new file mode 100644
index 0000000..b72a44d
--- /dev/null
+++ b/include/winnt.h
@@ -0,0 +1,23 @@
+/*
+ * Win32 definitions for Windows NT
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#ifndef __WINE_WINNT_H
+#define __WINE_WINNT_H
+
+/* Heap flags */
+#define HEAP_NO_SERIALIZE               0x00000001
+#define HEAP_GROWABLE                   0x00000002
+#define HEAP_GENERATE_EXCEPTIONS        0x00000004
+#define HEAP_ZERO_MEMORY                0x00000008
+#define HEAP_REALLOC_IN_PLACE_ONLY      0x00000010
+#define HEAP_TAIL_CHECKING_ENABLED      0x00000020
+#define HEAP_FREE_CHECKING_ENABLED      0x00000040
+#define HEAP_DISABLE_COALESCE_ON_FREE   0x00000080
+#define HEAP_CREATE_ALIGN_16            0x00010000
+#define HEAP_CREATE_ENABLE_TRACING      0x00020000
+
+
+#endif  /* __WINE_WINNT_H */
diff --git a/include/wintypes.h b/include/wintypes.h
index 8f53926..9430f56 100644
--- a/include/wintypes.h
+++ b/include/wintypes.h
@@ -43,6 +43,7 @@
 #endif  /* WINELIB32 */
 
 typedef UINT HANDLE;
+typedef DWORD HANDLE32;
 typedef UINT WPARAM;
 typedef LONG LPARAM;
 typedef LONG LRESULT;
@@ -163,6 +164,23 @@
 #define SELECTOROF(ptr)     (HIWORD(ptr))
 #define OFFSETOF(ptr)       (LOWORD(ptr))
 
+#if !defined(WINELIB) || defined(__i386__)
+#define PUT_WORD(ptr,w)   (*(WORD *)(ptr) = (w))
+#define GET_WORD(ptr)     (*(WORD *)(ptr))
+#define PUT_DWORD(ptr,dw) (*(DWORD *)(ptr) = (dw))
+#define GET_DWORD(ptr)    (*(DWORD *)(ptr))
+#else
+#define PUT_WORD(ptr,w)   (*(BYTE *)(ptr) = LOBYTE(w), \
+                           *((BYTE *)(ptr) + 1) = HIBYTE(w))
+#define GET_WORD(ptr)     ((WORD)(*(BYTE *)(ptr) | \
+                                  (WORD)(*((BYTE *)(ptr)+1) << 8)))
+#define PUT_DWORD(ptr,dw) (PUT_WORD((ptr),LOWORD(dw)), \
+                           PUT_WORD((WORD *)(ptr)+1,HIWORD(dw)))
+#define GET_DWORD(ptr)    ((DWORD)(GET_WORD(ptr) | \
+                                   ((DWORD)GET_WORD((WORD *)(ptr)+1) << 16)))
+#endif  /* !WINELIB || __i386__ */
+
+
 #ifndef MAX
 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
 #endif
@@ -171,13 +189,4 @@
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
 #endif
 
-#ifndef DONT_DEFINE_min_AND_max
-#ifndef min
-#define min(a,b) MIN(a,b)
-#endif
-#ifndef max
-#define max(a,b) MAX(a,b)
-#endif
-#endif
-
 #endif /* __WINE_WINTYPES_H */
diff --git a/library/miscstubs.c b/library/miscstubs.c
index 8ed3f24..846f702 100644
--- a/library/miscstubs.c
+++ b/library/miscstubs.c
@@ -207,3 +207,8 @@
 {
     return MODULE_GetWndProcEntry16( name );
 }
+
+void DEBUG_EnterDebugger(void)
+{
+}
+
diff --git a/loader/module.c b/loader/module.c
index 060c286..128c05a 100644
--- a/loader/module.c
+++ b/loader/module.c
@@ -72,10 +72,11 @@
     dprintf_module( stddeb, "Built-in %s: hmodule=%04x\n",
                     table->name, hModule );
     pModule = (NE_MODULE *)GlobalLock( hModule );
+    pModule->self = hModule;
 
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
-        ((NE_WIN32_EXTRAINFO*)(pModule+1))->pe_module = (DWORD)table;
+        pModule->pe_module = (PE_MODULE *)table;
     }
     else  /* Win16 module */
     {
@@ -127,6 +128,18 @@
 
 
 /***********************************************************************
+ *           MODULE_GetPtr
+ */
+NE_MODULE *MODULE_GetPtr( HMODULE hModule )
+{
+    NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
+    if (!pModule || (pModule->magic != NE_SIGNATURE) ||
+        (pModule->self != hModule)) return NULL;
+    return pModule;
+}
+
+
+/***********************************************************************
  *           MODULE_DumpModule
  */
 void MODULE_DumpModule( HMODULE hmodule )
@@ -135,9 +148,9 @@
     SEGTABLEENTRY *pSeg;
     BYTE *pstr;
     WORD *pword;
-    NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hmodule );
+    NE_MODULE *pModule;
 
-    if (!pModule || (pModule->magic != NE_SIGNATURE))
+    if (!(pModule = MODULE_GetPtr( hmodule )))
     {
         fprintf( stderr, "**** %04x is not a module handle\n", hmodule );
         return;
@@ -156,7 +169,7 @@
             pModule->os_flags, pModule->min_swap_area,
             pModule->expected_version );
     if (pModule->flags & NE_FFLAGS_WIN32)
-        printf( "PE module=%08x\n", (unsigned int)NE_WIN32_MODULE(pModule) );
+        printf( "PE module=%08x\n", (unsigned int)pModule->pe_module );
 
       /* Dump the file info */
 
@@ -276,8 +289,8 @@
     fprintf( stderr, "Module Flags Name\n" );
     while (hModule)
     {
-        NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
-        if (!pModule || (pModule->magic != NE_SIGNATURE))
+        NE_MODULE *pModule = MODULE_GetPtr( hModule );
+        if (!pModule)
         {
             fprintf( stderr, "**** Bad module %04x in list\n", hModule );
             return;
@@ -304,7 +317,7 @@
     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
     dprintf_module( stddeb, "MODULE_OpenFile(%04x) cache: mod=%04x fd=%d\n",
                     hModule, hCachedModule, cachedfd );
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return -1;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return -1;
     if (hCachedModule == hModule) return cachedfd;
     close( cachedfd );
     hCachedModule = hModule;
@@ -370,7 +383,7 @@
     NE_MODULE *pModule;
     int i, minsize;
 
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
     pSegment = NE_SEG_TABLE( pModule );
     for (i = 1; i <= pModule->seg_count; i++, pSegment++)
     {
@@ -402,7 +415,7 @@
     SEGTABLEENTRY *pSegment;
     NE_MODULE *pModule;
     
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     if (pModule->dgroup == 0) return hModule;
 
     pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
@@ -422,7 +435,7 @@
     int minsize;
     HINSTANCE hNewInstance, hPrevInstance;
 
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     if (pModule->dgroup == 0) return hModule;
 
     pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
@@ -501,10 +514,17 @@
     if (!hModule) return (HMODULE)11;  /* invalid exe */
     FarSetOwner( hModule, hModule );
     pModule = (NE_MODULE *)GlobalLock( hModule );
-    memcpy( pModule, &ne_header, sizeof(NE_MODULE) );
+    memcpy( pModule, &ne_header, sizeof(ne_header) );
     pModule->count = 0;
+    pModule->pe_module = NULL;
+    pModule->self = hModule;
+    pModule->self_loading_sel = 0;
     pData = (BYTE *)(pModule + 1);
 
+    /* Clear internal Wine flags in case they are set in the EXE file */
+
+    pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
+
     /* Read the fast-load area */
 
     if (ne_header.additional_flags & NE_AFLAGS_FASTLOAD)
@@ -524,10 +544,6 @@
         }
     }
 
-    /* Clear internal Wine flags in case they are set in the EXE file */
-
-    pModule->flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32);
-
     /* Store the filename information */
 
     pModule->fileinfo = (int)pData - (int)pModule;
@@ -556,7 +572,11 @@
         }
         free( buffer );
     }
-    else return (HMODULE)11;  /* invalid exe */
+    else
+    {
+        GlobalFree( hModule );
+        return (HMODULE)11;  /* invalid exe */
+    }
 
     /* Get the resource table */
 
@@ -575,7 +595,11 @@
     pModule->name_table = (int)pData - (int)pModule;
     if (!READ( ne_header.rname_tab_offset,
                ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
-               pData )) return (HMODULE)11;  /* invalid exe */
+               pData ))
+    {
+        GlobalFree( hModule );
+        return (HMODULE)11;  /* invalid exe */
+    }
     pData += ne_header.moduleref_tab_offset - ne_header.rname_tab_offset;
 
     /* Get the module references table */
@@ -595,7 +619,11 @@
     pModule->import_table = (int)pData - (int)pModule;
     if (!READ( ne_header.iname_tab_offset, 
                ne_header.entry_tab_offset - ne_header.iname_tab_offset,
-               pData )) return (HMODULE)11;  /* invalid exe */
+               pData ))
+    {
+        GlobalFree( hModule );
+        return (HMODULE)11;  /* invalid exe */
+    }
     pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
 
     /* Get the entry table */
@@ -603,7 +631,11 @@
     pModule->entry_table = (int)pData - (int)pModule;
     if (!READ( ne_header.entry_tab_offset,
                ne_header.entry_tab_length,
-               pData )) return (HMODULE)11;  /* invalid exe */
+               pData ))
+    {
+        GlobalFree( hModule );
+        return (HMODULE)11;  /* invalid exe */
+    }
     pData += ne_header.entry_tab_length;
 
     /* Get the non-resident names table */
@@ -612,11 +644,20 @@
     {
         pModule->nrname_handle = GLOBAL_Alloc( 0, ne_header.nrname_tab_length,
                                                hModule, FALSE, FALSE, FALSE );
-        if (!pModule->nrname_handle) return (HMODULE)11;  /* invalid exe */
+        if (!pModule->nrname_handle)
+        {
+            GlobalFree( hModule );
+            return (HMODULE)11;  /* invalid exe */
+        }
         buffer = GlobalLock( pModule->nrname_handle );
         _llseek( hFile, ne_header.nrname_tab_offset, SEEK_SET );
         if (FILE_Read( hFile, buffer, ne_header.nrname_tab_length )
-              != ne_header.nrname_tab_length) return (HMODULE)11;  /* invalid exe */
+              != ne_header.nrname_tab_length)
+        {
+            GlobalFree( pModule->nrname_handle );
+            GlobalFree( hModule );
+            return (HMODULE)11;  /* invalid exe */
+        }
     }
     else pModule->nrname_handle = 0;
 
@@ -627,14 +668,19 @@
         pModule->dlls_to_init = GLOBAL_Alloc(GMEM_ZEROINIT,
                                     (pModule->modref_count+1)*sizeof(HMODULE),
                                     hModule, FALSE, FALSE, FALSE );
-        if (!pModule->dlls_to_init) return (HMODULE)11;  /* invalid exe */
+        if (!pModule->dlls_to_init)
+        {
+            if (pModule->nrname_handle) GlobalFree( pModule->nrname_handle );
+            GlobalFree( hModule );
+            return (HMODULE)11;  /* invalid exe */
+        }
     }
     else pModule->dlls_to_init = 0;
 
-    if (debugging_module) MODULE_DumpModule( hModule );
     pModule->next = hFirstModule;
     hFirstModule = hModule;
     return hModule;
+#undef READ
 }
 
 
@@ -649,7 +695,7 @@
     BYTE len;
     NE_MODULE *pModule;
 
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
 
     dprintf_module( stddeb, "MODULE_GetOrdinal(%04x,'%s')\n",
                     hModule, name );
@@ -714,7 +760,7 @@
     BYTE *p;
     WORD sel, offset;
 
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
 
     p = (BYTE *)pModule + pModule->entry_table;
     while (*p && (curOrdinal + *p <= ordinal))
@@ -764,7 +810,7 @@
     WORD curOrdinal = 1;
     BYTE *p;
 
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
 
     p = (BYTE *)pModule + pModule->entry_table;
     while (*p && (curOrdinal + *p <= ordinal))
@@ -809,7 +855,7 @@
     register char *cpnt;
     NE_MODULE *pModule;
 
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
 
       /* First search the resident names */
 
@@ -876,7 +922,7 @@
     BYTE *p, len;
     static char buffer[10];
 
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return NULL;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return NULL;
     p = (BYTE *)pModule + pModule->name_table;
     len = MIN( *p, 8 );
     memcpy( buffer, p + 1, len );
@@ -890,10 +936,9 @@
  */
 void MODULE_RegisterModule( HMODULE hModule )
 {
-	NE_MODULE *pModule;
-	pModule = (NE_MODULE *)GlobalLock( hModule );
-	pModule->next = hFirstModule;
-	hFirstModule = hModule;
+    NE_MODULE *pModule = MODULE_GetPtr( hModule );
+    pModule->next = hFirstModule;
+    hFirstModule = hModule;
 }
 
 /**********************************************************************
@@ -915,7 +960,7 @@
 
     while(hModule)
     {
-        NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
+        NE_MODULE *pModule = MODULE_GetPtr( hModule );
         if (!pModule) break;
         modulepath = NE_MODULE_NAME(pModule);
         if (!(modulename = strrchr( modulepath, '\\' )))
@@ -945,18 +990,22 @@
     HMODULE *pModRef;
     int i;
 
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return;
     if (pModule->flags & NE_FFLAGS_BUILTIN)
         return;  /* Can't free built-in module */
 
     /* FIXME: should call the exit code for the library here */
 
+    /* Clear magic number just in case */
+
+    pModule->magic = pModule->self = 0;
+
       /* Remove it from the linked list */
 
     hPrevModule = &hFirstModule;
     while (*hPrevModule && (*hPrevModule != hModule))
     {
-        hPrevModule = &((NE_MODULE *)GlobalLock( *hPrevModule ))->next;
+        hPrevModule = &(MODULE_GetPtr( *hPrevModule ))->next;
     }
     if (*hPrevModule) *hPrevModule = pModule->next;
 
@@ -1038,7 +1087,7 @@
             return hModule;
         }
         _lclose( hFile );
-        pModule = (NE_MODULE *)GlobalLock( hModule );
+        pModule = MODULE_GetPtr( hModule );
 
           /* Allocate the segments for this module */
 
@@ -1086,7 +1135,7 @@
             }
             else  /* Increment the reference count of the DLL */
             {
-                NE_MODULE *pOldDLL = (NE_MODULE *)GlobalLock( *pModRef );
+                NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
                 if (pOldDLL) pOldDLL->count++;
             }
         }
@@ -1171,7 +1220,7 @@
 
           /* Fixup the functions prologs */
 
-        NE_FixupPrologs( hModule );
+        NE_FixupPrologs( pModule );
 
           /* Make sure the usage count is 1 on the first loading of  */
           /* the module, even if it contains circular DLL references */
@@ -1180,7 +1229,7 @@
     }
     else
     {
-        pModule = (NE_MODULE *)GlobalLock( hModule );
+        pModule = MODULE_GetPtr( hModule );
         hPrevInstance = MODULE_GetInstance( hModule );
         hInstance = MODULE_CreateInstance( hModule, params );
         if (hInstance != hPrevInstance)  /* not a library */
@@ -1191,7 +1240,8 @@
     hModule = GlobalAlloc( GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(NE_MODULE) );
     pModule = (NE_MODULE *)GlobalLock( hModule );
     pModule->count = 1;
-    pModule->magic = 0x454e;
+    pModule->magic = NE_SIGNATURE;
+    pModule->self = hModule;
     hPrevInstance = 0;
     hInstance = MODULE_CreateInstance( hModule, (LOADPARAMS*)paramBlock );
 #endif /* WINELIB */
@@ -1218,7 +1268,7 @@
     NE_MODULE *pModule;
 
     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
 
     dprintf_module( stddeb, "FreeModule: %s count %d\n", 
 		    MODULE_GetModuleName(hModule), pModule->count );
@@ -1250,7 +1300,7 @@
     NE_MODULE *pModule;
 
     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     dprintf_module( stddeb, "GetModuleUsage(%04x): returning %d\n",
                     hModule, pModule->count );
     return pModule->count;
@@ -1265,7 +1315,7 @@
     NE_MODULE *pModule;
 
     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     lstrcpyn( lpFileName, NE_MODULE_NAME(pModule), nSize );
     dprintf_module( stddeb, "GetModuleFilename: %s\n", lpFileName );
     return strlen(lpFileName);
@@ -1486,9 +1536,8 @@
  */
 WORD GetExpWinVer( HMODULE hModule )
 {
-    NE_MODULE *pModule = (NE_MODULE *)GlobalLock( hModule );
-
-    return pModule->expected_version;
+    NE_MODULE *pModule = MODULE_GetPtr( hModule );
+    return pModule ? pModule->expected_version : 0;
 }
 
 
@@ -1510,7 +1559,7 @@
     NE_MODULE *pModule;
 
     if (!lpme->wNext) return FALSE;
-    if (!(pModule = (NE_MODULE *)GlobalLock( lpme->wNext ))) return FALSE;
+    if (!(pModule = MODULE_GetPtr( lpme->wNext ))) return FALSE;
     strncpy( lpme->szModule, (char *)pModule + pModule->name_table,
              MAX_MODULE_NAME );
     lpme->szModule[MAX_MODULE_NAME] = '\0';
diff --git a/loader/ne_image.c b/loader/ne_image.c
index 8ae9004..2fcd8f9 100644
--- a/loader/ne_image.c
+++ b/loader/ne_image.c
@@ -49,7 +49,7 @@
     int ordinal, additive;
     unsigned short *sp;
 
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return FALSE;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
     pSegTable = NE_SEG_TABLE( pModule );
     pSeg = pSegTable + segnum - 1;
     pModuleTable = NE_MODULE_TABLE( pModule );
@@ -171,7 +171,7 @@
             address = MODULE_GetEntryPoint( module, ordinal );
             if (!address)
             {
-                NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
+                NE_MODULE *pTarget = MODULE_GetPtr( module );
                 if (!pTarget)
                     fprintf( stderr, "Module not found: %04x, reference %d of module %*.*s\n",
                              module, rep->target1, 
@@ -187,7 +187,7 @@
             }
             if (debugging_fixup)
             {
-                NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
+                NE_MODULE *pTarget = MODULE_GetPtr( module );
                 fprintf( stddeb,"%d: %*.*s.%d=%04x:%04x\n", i + 1, 
                          *((BYTE *)pTarget + pTarget->name_table),
                          *((BYTE *)pTarget + pTarget->name_table),
@@ -208,7 +208,7 @@
 
             if (!address)
             {
-                NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
+                NE_MODULE *pTarget = MODULE_GetPtr( module );
                 fprintf( stderr, "Warning: no handler for %*.*s.%s, setting to 0:0\n",
                         *((BYTE *)pTarget + pTarget->name_table),
                         *((BYTE *)pTarget + pTarget->name_table),
@@ -216,7 +216,7 @@
             }
             if (debugging_fixup)
             {
-                NE_MODULE *pTarget = (NE_MODULE *)GlobalLock( module );
+                NE_MODULE *pTarget = MODULE_GetPtr( module );
                 fprintf( stddeb,"%d: %*.*s.%s=%04x:%04x\n", i + 1, 
                          *((BYTE *)pTarget + pTarget->name_table),
                          *((BYTE *)pTarget + pTarget->name_table),
@@ -347,23 +347,21 @@
  *
  * Fixup the exported functions prologs.
  */
-void NE_FixupPrologs( HMODULE hModule )
+void NE_FixupPrologs( NE_MODULE *pModule )
 {
 #ifdef WINELIB
 	fprintf(stderr,"NE_FixupPrologs should not be called for libwine\n");
 #else
-    NE_MODULE *pModule;
     SEGTABLEENTRY *pSegTable;
     WORD dgroup = 0;
     WORD sel;
     BYTE *p, *fixup_ptr, count;
 
-    pModule = (NE_MODULE *)GlobalLock( hModule );
     pSegTable = NE_SEG_TABLE(pModule);
     if (pModule->flags & NE_FFLAGS_SINGLEDATA)
         dgroup = pSegTable[pModule->dgroup-1].selector;
 
-    dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", hModule );
+    dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", pModule->self );
     p = (BYTE *)pModule + pModule->entry_table;
     while (*p)
     {
@@ -455,10 +453,11 @@
      * es:si  command line (always 0)
      */
 
-    pModule = (NE_MODULE *)GlobalLock( hModule );
+    if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
     pSegTable = NE_SEG_TABLE( pModule );
 
-    if (!(pModule->flags & NE_FFLAGS_LIBMODULE)) return TRUE; /*not a library*/
+    if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
+        (pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
     if (!pModule->cs) return TRUE;  /* no initialization code */
 
     if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
@@ -509,7 +508,7 @@
     NE_MODULE *pModule;
     HMODULE *pDLL;
 
-    pModule = (NE_MODULE *)GlobalLock( hModule );
+    if (!(pModule = MODULE_GetPtr( hModule ))) return;
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
         PE_InitializeDLLs(hModule);
diff --git a/loader/ne_resource.c b/loader/ne_resource.c
index e7e1a6e..7e45089 100644
--- a/loader/ne_resource.c
+++ b/loader/ne_resource.c
@@ -43,7 +43,7 @@
     DWORD ret = 0;
     int count;
 
-    pModule = (NE_MODULE *)GlobalLock( hModule );
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
     for (; pTypeInfo->type_id != 0;
              pTypeInfo = (NE_TYPEINFO *)((char*)(pTypeInfo+1) +
@@ -139,11 +139,10 @@
  */
 HRSRC NE_FindResource( HMODULE hModule, SEGPTR typeId, SEGPTR resId )
 {
-    NE_MODULE *pModule;
     NE_TYPEINFO *pTypeInfo;
     HRSRC hRsrc;
 
-    pModule = (NE_MODULE *)GlobalLock( hModule );
+    NE_MODULE *pModule = MODULE_GetPtr( hModule );
     if (!pModule || !pModule->res_table) return 0;
     pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
 
@@ -217,11 +216,10 @@
  */
 HGLOBAL NE_AllocResource( HMODULE hModule, HRSRC hRsrc, DWORD size )
 {
-    NE_MODULE *pModule;
     NE_NAMEINFO *pNameInfo=NULL;
     WORD sizeShift;
 
-    pModule = (NE_MODULE *)GlobalLock( hModule );
+    NE_MODULE *pModule = MODULE_GetPtr( hModule );
     if (!pModule || !pModule->res_table) return 0;
     sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
 #ifndef WINELIB
@@ -238,11 +236,10 @@
  */
 int NE_AccessResource( HMODULE hModule, HRSRC hRsrc )
 {
-    NE_MODULE *pModule;
     NE_NAMEINFO *pNameInfo=NULL;
     int fd;
 
-    pModule = (NE_MODULE *)GlobalLock( hModule );
+    NE_MODULE *pModule = MODULE_GetPtr( hModule );
     if (!pModule || !pModule->res_table) return -1;
 #ifndef WINELIB
     pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
@@ -262,11 +259,10 @@
  */
 DWORD NE_SizeofResource( HMODULE hModule, HRSRC hRsrc )
 {
-    NE_MODULE *pModule;
     NE_NAMEINFO *pNameInfo=NULL;
     WORD sizeShift;
 
-    pModule = (NE_MODULE *)GlobalLock( hModule );
+    NE_MODULE *pModule = MODULE_GetPtr( hModule );
     if (!pModule || !pModule->res_table) return 0;
     sizeShift = *(WORD *)((char *)pModule + pModule->res_table);
 #ifndef WINELIB
@@ -281,12 +277,11 @@
  */
 HGLOBAL NE_LoadResource( HMODULE hModule,  HRSRC hRsrc )
 {
-    NE_MODULE *pModule;
     NE_NAMEINFO *pNameInfo=NULL;
     WORD sizeShift;
     int fd;
 
-    pModule = (NE_MODULE *)GlobalLock( hModule );
+    NE_MODULE *pModule = MODULE_GetPtr( hModule );
     if (!pModule || !pModule->res_table) return 0;
 #ifndef WINELIB
     pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc);
@@ -328,12 +323,11 @@
  */
 BOOL NE_FreeResource( HMODULE hModule, HGLOBAL handle )
 {
-    NE_MODULE *pModule;
     NE_TYPEINFO *pTypeInfo;
     NE_NAMEINFO *pNameInfo;
     WORD count;
 
-    pModule = (NE_MODULE *)GlobalLock( hModule );
+    NE_MODULE *pModule = MODULE_GetPtr( hModule );
     if (!pModule || !pModule->res_table) return FALSE;
     pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->res_table + 2);
     while (pTypeInfo->type_id)
diff --git a/loader/pe_image.c b/loader/pe_image.c
index ad82288..79789b7 100644
--- a/loader/pe_image.c
+++ b/loader/pe_image.c
@@ -34,6 +34,8 @@
 #include "debug.h"
 #include "xmalloc.h"
 
+static HANDLE32 ProcessHeap;  /* FIXME: should be in process database */
+
 void my_wcstombs(char * result, u_short * source, int len)
 {
   while(len--) {
@@ -136,20 +138,19 @@
 DWORD PE_GetProcAddress(HMODULE hModule, char* function)
 {
     NE_MODULE *pModule;
-    struct pe_data *pe;
 
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0;
     if (pModule->flags & NE_FFLAGS_BUILTIN)
     {
-        BUILTIN_DLL *dll = (BUILTIN_DLL *)NE_WIN32_MODULE(pModule);
+        BUILTIN_DLL *dll = (BUILTIN_DLL *)pModule->pe_module;
         if(HIWORD(function))
             return RELAY32_GetEntryPoint(dll,function,0);
         else
             return RELAY32_GetEntryPoint(dll,0,(int)function);
     }
-    if (!(pe = NE_WIN32_MODULE(pModule))) return 0;
-    return PE_FindExportedFunction( pe, function );
+    if (!pModule->pe_module) return 0;
+    return PE_FindExportedFunction( pModule->pe_module, function );
 }
 
 void fixup_imports(struct pe_data *pe, HMODULE hModule)
@@ -286,7 +287,7 @@
 	     pe->pe_seg[i].NumberOfRelocations,
 	     pe->pe_seg[i].NumberOfLinenumbers,
 	     pe->pe_seg[i].Characteristics);
-	  pe->vma_size = max(pe->vma_size,
+	  pe->vma_size = MAX(pe->vma_size,
 	  		pe->pe_seg[i].Virtual_Address + 
 			pe->pe_seg[i].Size_Of_Raw_Data);
     }
@@ -535,10 +536,9 @@
 
 HINSTANCE PE_LoadModule( int fd, OFSTRUCT *ofs, LOADPARAMS* params )
 {
-        struct pe_data *pe;
+        PE_MODULE *pe;
 	int size, of_size;
 	NE_MODULE *pModule;
-        NE_WIN32_EXTRAINFO *pExtraInfo;
 	SEGTABLEENTRY *pSegment;
 	char *pStr;
 	DWORD cts;
@@ -554,8 +554,6 @@
         of_size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName)
                   + strlen(ofs->szPathName) + 1;
 	size = sizeof(NE_MODULE) +
-               /* extra module info */
-               sizeof(NE_WIN32_EXTRAINFO) +
                /* loaded file info */
                of_size +
                /* segment table: DS,CS */
@@ -586,18 +584,16 @@
 	pModule->seg_count=1;
 	pModule->modref_count=0;
 	pModule->nrname_size=0;
-	pModule->fileinfo=sizeof(NE_MODULE) + sizeof(NE_WIN32_EXTRAINFO);
+	pModule->fileinfo=sizeof(NE_MODULE);
 	pModule->os_flags=NE_OSFLAGS_WINDOWS;
 	pModule->expected_version=0x30A;
-
-        /* Set extra info */
-        pExtraInfo = (NE_WIN32_EXTRAINFO *)(pModule + 1);
+        pModule->self = hModule;
 
         /* Set loaded file information */
-        memcpy( pExtraInfo + 1, ofs, of_size );
-        ((OFSTRUCT *)(pExtraInfo+1))->cBytes = of_size - 1;
+        memcpy( pModule + 1, ofs, of_size );
+        ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
 
-	pSegment=(SEGTABLEENTRY*)((char*)(pExtraInfo + 1) + of_size);
+	pSegment=(SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
 	pModule->seg_table=pModule->dgroup_entry=(int)pSegment-(int)pModule;
 	pSegment->size=0;
 	pSegment->flags=NE_SEGFLAGS_DATA;
@@ -627,7 +623,7 @@
 
 	pe = PE_LoadImage( fd, hModule, mz_header.ne_offset );
 
-        pExtraInfo->pe_module = (DWORD)pe;
+        pModule->pe_module = pe;
 	pModule->heap_size=0x1000;
 	pModule->stack_size=0xE000;
 
@@ -638,6 +634,7 @@
 	if ((pe->pe_header->coff.Characteristics & IMAGE_FILE_DLL)) {
 /*            PE_InitDLL(hModule); */
         } else {
+            ProcessHeap = HeapCreate( 0, 0x10000, 0 );
             TASK_CreateTask(hModule,hInstance,0,
 		params->hEnvironment,(LPSTR)PTR_SEG_TO_LIN(params->cmdLine),
 		*((WORD*)PTR_SEG_TO_LIN(params->showCmd)+1));
@@ -646,6 +643,11 @@
 	return hInstance;
 }
 
+HANDLE32 GetProcessHeap(void)
+{
+    return ProcessHeap;
+}
+
 int USER_InitApp(HINSTANCE hInstance);
 void PE_InitTEB(int hTEB);
 
@@ -653,19 +655,19 @@
 {
     int fs;
     HMODULE hModule;
+    NE_MODULE *pModule;
     struct pe_data *pe;
 
     dprintf_win32(stddeb,"Going to start Win32 program\n");	
     InitTask(context);
     hModule = GetExePtr( GetCurrentTask() );
+    pModule = MODULE_GetPtr( hModule );
     USER_InitApp( hModule );
     fs=(int)GlobalAlloc(GHND,0x10000);
     PE_InitTEB(fs);
-    pe = NE_WIN32_MODULE( (NE_MODULE *)GlobalLock(hModule) );
     __asm__ __volatile__("movw %w0,%%fs"::"r" (fs));
-/*    ((void(*)())(pe->load_addr+pe->pe_header->opt_coff.AddressOfEntryPoint))(); */
-    CallTaskStart32( (FARPROC)(pe->load_addr + 
-                               pe->pe_header->opt_coff.AddressOfEntryPoint) );
+    CallTaskStart32( (FARPROC)(pModule->pe_module->load_addr + 
+                               pModule->pe_module->pe_header->opt_coff.AddressOfEntryPoint) );
 }
 
 int PE_UnloadImage( HMODULE hModule )
@@ -678,11 +680,13 @@
 static void PE_InitDLL(HMODULE hModule)
 {
     NE_MODULE *pModule;
-    struct pe_data *pe;
+    PE_MODULE *pe;
+
     hModule = GetExePtr(hModule);
-    if (!(pModule = (NE_MODULE *)GlobalLock(hModule))) return;
-    if (!(pModule->flags & NE_FFLAGS_WIN32)) return;
-    if (!(pe = NE_WIN32_MODULE(pModule))) return;
+    if (!(pModule = MODULE_GetPtr(hModule))) return;
+    if (!(pModule->flags & NE_FFLAGS_WIN32) || !(pe = pModule->pe_module))
+        return;
+
     /* FIXME: What are the correct values for parameters 2 and 3? */
         
     /* Is this a library? */
@@ -726,7 +730,7 @@
 {
 	NE_MODULE *pModule;
 	HMODULE *pDLL;
-	pModule = (NE_MODULE *)GlobalLock( GetExePtr(hModule) );
+	pModule = MODULE_GetPtr( GetExePtr(hModule) );
 	if (pModule->dlls_to_init)
 	{
 		HANDLE to_init = pModule->dlls_to_init;
diff --git a/loader/resource.c b/loader/resource.c
index 0de3993..b6a4549 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -52,7 +52,7 @@
     dprintf_resource( stddeb, " name=" );
     PrintId( name );
     dprintf_resource( stddeb, "\n" );
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
 #ifndef WINELIB
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
@@ -77,7 +77,7 @@
     dprintf_resource(stddeb, "LoadResource: module=%04x res=%04x\n",
                      hModule, hRsrc );
     if (!hRsrc) return 0;
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
 #ifndef WINELIB
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
@@ -104,7 +104,7 @@
     dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
     if (!handle) return (SEGPTR)0;
     hModule = GetExePtr( handle );
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
         fprintf(stderr,"Don't know how to LockResource() for Win32 module\n");
@@ -126,7 +126,7 @@
     dprintf_resource(stddeb, "LockResource: handle=%04x\n", handle );
     if (!handle) return NULL;
     hModule = GetExePtr( handle );
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
         fprintf(stderr,"Don't know how to LockResource() for Win32 module\n");
@@ -151,7 +151,7 @@
     dprintf_resource(stddeb, "FreeResource: handle=%04x\n", handle );
     if (!handle) return FALSE;
     hModule = GetExePtr( handle );
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
         fprintf(stderr,"Don't know how to FreeResource() for Win32 module\n");
@@ -175,7 +175,7 @@
     dprintf_resource(stddeb, "AccessResource: module=%04x res=%04x\n",
                      hModule, hRsrc );
     if (!hRsrc) return 0;
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
 #ifndef WINELIB
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
@@ -199,7 +199,7 @@
     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
     dprintf_resource(stddeb, "SizeofResource: module=%04x res=%04x\n",
                      hModule, hRsrc );
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
 #ifndef WINELIB
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
@@ -224,7 +224,7 @@
     dprintf_resource(stddeb, "AllocResource: module=%04x res=%04x size=%ld\n",
                      hModule, hRsrc, size );
     if (!hRsrc) return 0;
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
 #ifndef WINELIB
     if (pModule->flags & NE_FFLAGS_WIN32)
     {
diff --git a/loader/signal.c b/loader/signal.c
index d9b72ab..e7f9ea2 100644
--- a/loader/signal.c
+++ b/loader/signal.c
@@ -113,9 +113,6 @@
         }
     }
 
-    XUngrabPointer(display, CurrentTime);
-    XUngrabServer(display);
-    XFlush(display);
     wine_debug( signal, context );  /* Enter our debugger */
 }
 
diff --git a/loader/task.c b/loader/task.c
index 0a2a3b8..7ddac31 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -162,7 +162,7 @@
     /* Now add the program name */
 
     *p++ = '\0';
-    *(WORD *)p = 1;
+    PUT_WORD( p, 1 );
     p += sizeof(WORD);
     GetSystemDirectory( p, sysdirlen );
     strcat( p, "\\" );
@@ -329,7 +329,7 @@
 {
     int cs_reg, ds_reg, ip_reg;
     TDB *pTask = (TDB *)GlobalLock( hCurrentTask );
-    NE_MODULE *pModule = (NE_MODULE *)GlobalLock( pTask->hModule );
+    NE_MODULE *pModule = MODULE_GetPtr( pTask->hModule );
     SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
 
     /* Registers at initialization must be:
@@ -387,7 +387,7 @@
     extern DWORD CALLTO16_RetAddr_word;
 #endif
     
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     pSegTable = NE_SEG_TABLE( pModule );
 
       /* Allocate the task structure */
@@ -759,7 +759,7 @@
     EAX_reg(&context) = 0;
 #endif
     if (!(pTask = (TDB *)GlobalLock( hCurrentTask ))) return;
-    if (!(pModule = (NE_MODULE *)GlobalLock( pTask->hModule ))) return;
+    if (!(pModule = MODULE_GetPtr( pTask->hModule ))) return;
 
     if (firstTask)
     {
diff --git a/memory/Makefile.in b/memory/Makefile.in
index 357ded9..4287234 100644
--- a/memory/Makefile.in
+++ b/memory/Makefile.in
@@ -4,6 +4,7 @@
 C_SRCS = \
 	atom.c \
 	global.c \
+	heap.c \
 	ldt.c \
 	local.c \
 	selector.c
diff --git a/memory/global.c b/memory/global.c
index 78e0081..98d7bd0 100644
--- a/memory/global.c
+++ b/memory/global.c
@@ -198,7 +198,9 @@
         ptr = DDE_malloc(flags, size, &shmdata);
     else 
 #endif  /* CONFIG_IPC */
+    {
 	ptr = malloc( size );
+    }
     if (!ptr) return 0;
 
       /* Allocate the selector(s) */
diff --git a/memory/heap.c b/memory/heap.c
new file mode 100644
index 0000000..945c844
--- /dev/null
+++ b/memory/heap.c
@@ -0,0 +1,1091 @@
+/*
+ * Win32 heap functions
+ *
+ * Copyright 1996 Alexandre Julliard
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "windows.h"
+#include "debugger.h"
+#include "kernel32.h"  /* for CRITICAL_SECTION */
+#include "winbase.h"
+#include "winerror.h"
+#include "winnt.h"
+#include "stddebug.h"
+#include "debug.h"
+
+/* Note: the heap data structures are based on what Pietrek describes in his
+ * book 'Windows 95 System Programming Secrets'. The layout is not exactly
+ * the same, but could be easily adapted if it turns out some programs
+ * require it.
+ */
+
+typedef struct tagARENA_INUSE
+{
+    DWORD  size;                    /* Block size; must be the first field */
+    WORD   threadId;                /* Allocating thread id */
+    WORD   magic;                   /* Magic number */
+    DWORD  callerEIP;               /* EIP of caller upon allocation */
+} ARENA_INUSE;
+
+typedef struct tagARENA_FREE
+{
+    DWORD                 size;     /* Block size; must be the first field */
+    WORD                  threadId; /* Freeing thread id */
+    WORD                  magic;    /* Magic number */
+    struct tagARENA_FREE *next;     /* Next free arena */
+    struct tagARENA_FREE *prev;     /* Prev free arena */
+} ARENA_FREE;
+
+#define ARENA_FLAG_FREE        0x00000001  /* flags OR'ed with arena size */
+#define ARENA_FLAG_PREV_FREE   0x00000002
+#define ARENA_SIZE_MASK        0xfffffffc
+#define ARENA_INUSE_MAGIC      0x4842      /* Value for arena 'magic' field */
+#define ARENA_FREE_MAGIC       0x4846      /* Value for arena 'magic' field */
+
+#define ARENA_INUSE_FILLER     0x55
+#define ARENA_FREE_FILLER      0xaa
+
+#define HEAP_NB_FREE_LISTS   4   /* Number of free lists */
+
+/* Max size of the blocks on the free lists */
+static const DWORD HEAP_freeListSizes[HEAP_NB_FREE_LISTS] =
+{
+    0x20, 0x80, 0x200, 0xffffffff
+};
+
+typedef struct
+{
+    DWORD       size;
+    ARENA_FREE  arena;
+} FREE_LIST_ENTRY;
+
+struct tagHEAP;
+
+typedef struct tagSUBHEAP
+{
+    DWORD               size;       /* Size of the whole sub-heap */
+    DWORD               commitSize; /* Committed size of the sub-heap */
+    DWORD               headerSize; /* Size of the heap header */
+    struct tagSUBHEAP  *next;       /* Next sub-heap */
+    struct tagHEAP     *heap;       /* Main heap structure */
+    DWORD               magic;      /* Magic number */
+} SUBHEAP;
+
+#define SUBHEAP_MAGIC    ((DWORD)('S' | ('U'<<8) | ('B'<<16) | ('H'<<24)))
+
+typedef struct tagHEAP
+{
+    SUBHEAP          subheap;       /* First sub-heap */
+    struct tagHEAP  *next;          /* Next heap for this process */
+    FREE_LIST_ENTRY  freeList[HEAP_NB_FREE_LISTS];  /* Free lists */
+    CRITICAL_SECTION critSection;   /* Critical section for serialization */
+    DWORD            flags;         /* Heap flags */
+    DWORD            magic;         /* Magic number */
+} HEAP;
+
+#define HEAP_MAGIC       ((DWORD)('H' | ('E'<<8) | ('A'<<16) | ('P'<<24)))
+
+#define HEAP_DEF_SIZE        0x110000   /* Default heap size = 1Mb + 64Kb */
+#define HEAP_MIN_BLOCK_SIZE  (8+sizeof(ARENA_FREE))  /* Min. heap block size */
+
+
+/***********************************************************************
+ *           HEAP_Dump
+ */
+void HEAP_Dump( HEAP *heap )
+{
+    int i;
+    SUBHEAP *subheap;
+    char *ptr;
+
+    printf( "Heap: %08lx\n", (DWORD)heap );
+    printf( "Next: %08lx  Sub-heaps: %08lx",
+            (DWORD)heap->next, (DWORD)&heap->subheap );
+    subheap = &heap->subheap;
+    while (subheap->next)
+    {
+        printf( " -> %08lx", (DWORD)subheap->next );
+        subheap = subheap->next;
+    }
+
+    printf( "\nFree lists:\n Block   Stat   Size    Id\n" );
+    for (i = 0; i < HEAP_NB_FREE_LISTS; i++)
+        printf( "%08lx free %08lx %04x prev=%08lx next=%08lx\n",
+                (DWORD)&heap->freeList[i].arena, heap->freeList[i].arena.size,
+                heap->freeList[i].arena.threadId,
+                (DWORD)heap->freeList[i].arena.prev,
+                (DWORD)heap->freeList[i].arena.next );
+
+    subheap = &heap->subheap;
+    while (subheap)
+    {
+        DWORD freeSize = 0, usedSize = 0, arenaSize = subheap->headerSize;
+        printf( "\n\nSub-heap %08lx: size=%08lx committed=%08lx\n",
+                (DWORD)subheap, subheap->size, subheap->commitSize );
+
+        printf( "\n Block   Stat   Size    Id\n" );
+        ptr = (char*)subheap + subheap->headerSize;
+        while (ptr < (char *)subheap + subheap->size)
+        {
+            if (*(DWORD *)ptr & ARENA_FLAG_FREE)
+            {
+                ARENA_FREE *pArena = (ARENA_FREE *)ptr;
+                printf( "%08lx free %08lx %04x prev=%08lx next=%08lx\n",
+                        (DWORD)pArena, pArena->size & ARENA_SIZE_MASK,
+                        pArena->threadId, (DWORD)pArena->prev,
+                        (DWORD)pArena->next);
+                ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK);
+                arenaSize += sizeof(ARENA_FREE);
+                freeSize += pArena->size & ARENA_SIZE_MASK;
+            }
+            else if (*(DWORD *)ptr & ARENA_FLAG_PREV_FREE)
+            {
+                ARENA_INUSE *pArena = (ARENA_INUSE *)ptr;
+                printf( "%08lx Used %08lx %04x back=%08lx EIP=%08lx\n",
+                        (DWORD)pArena, pArena->size & ARENA_SIZE_MASK,
+                        pArena->threadId, *((DWORD *)pArena - 1),
+                        pArena->callerEIP );
+                ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK);
+                arenaSize += sizeof(ARENA_INUSE);
+                usedSize += pArena->size & ARENA_SIZE_MASK;
+            }
+            else
+            {
+                ARENA_INUSE *pArena = (ARENA_INUSE *)ptr;
+                printf( "%08lx used %08lx %04x EIP=%08lx\n",
+                        (DWORD)pArena, pArena->size & ARENA_SIZE_MASK,
+                        pArena->threadId, pArena->callerEIP );
+                ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK);
+                arenaSize += sizeof(ARENA_INUSE);
+                usedSize += pArena->size & ARENA_SIZE_MASK;
+            }
+        }
+        printf( "\nTotal: Size=%08lx Committed=%08lx Free=%08lx Used=%08lx Arenas=%08lx (%ld%%)\n\n",
+                subheap->size, subheap->commitSize, freeSize, usedSize,
+                arenaSize, (arenaSize * 100) / subheap->size );
+        subheap = subheap->next;
+    }
+}
+
+
+/***********************************************************************
+ *           HEAP_GetPtr
+ */
+static HEAP *HEAP_GetPtr( HANDLE32 heap )
+{
+    HEAP *heapPtr = (HEAP *)heap;
+    if (!heapPtr || (heapPtr->magic != HEAP_MAGIC))
+    {
+        fprintf( stderr, "Invalid heap %08lx!\n", heap );
+        SetLastError( ERROR_INVALID_HANDLE );
+        return NULL;
+    }
+    if (debugging_heap && !HeapValidate( heap, 0, NULL ))
+    {
+        HEAP_Dump( heapPtr );
+        DEBUG_EnterDebugger();
+        SetLastError( ERROR_INVALID_HANDLE );
+        return NULL;
+    }
+    return heapPtr;
+}
+
+
+/***********************************************************************
+ *           HEAP_InsertFreeBlock
+ *
+ * Insert a free block into the free list.
+ */
+static void HEAP_InsertFreeBlock( HEAP *heap, ARENA_FREE *pArena )
+{
+    FREE_LIST_ENTRY *pEntry = heap->freeList;
+    while (pEntry->size < pArena->size) pEntry++;
+    pArena->size      |= ARENA_FLAG_FREE;
+    pArena->next       = pEntry->arena.next;
+    pArena->next->prev = pArena;
+    pArena->prev       = &pEntry->arena;
+    pEntry->arena.next = pArena;
+}
+
+
+/***********************************************************************
+ *           HEAP_FindSubHeap
+ *
+ * Find the sub-heap containing a given address.
+ */
+static SUBHEAP *HEAP_FindSubHeap( HEAP *heap, void *ptr )
+{
+    SUBHEAP *sub = &heap->subheap;
+    while (sub)
+    {
+        if (((char *)ptr >= (char *)sub) &&
+            ((char *)ptr < (char *)sub + sub->size)) return sub;
+        sub = sub->next;
+    }
+    return NULL;
+}
+
+
+/***********************************************************************
+ *           HEAP_Commit
+ *
+ * Make sure the heap storage is committed up to (not including) ptr.
+ */
+static BOOL HEAP_Commit( SUBHEAP *subheap, void *ptr )
+{
+    DWORD size = (DWORD)((char *)ptr - (char *)subheap);
+    size = (size + 0xfff) & 0xfffff000;  /* Align size on a page boundary */
+    if (size > subheap->size) size = subheap->size;
+    if (size <= subheap->commitSize) return TRUE;
+    if (!VirtualAlloc( (char *)subheap + subheap->commitSize,
+                       size - subheap->commitSize, MEM_COMMIT,
+                       PAGE_EXECUTE_READWRITE))
+    {
+        fprintf( stderr, "HEAP_Commit: could not commit %08lx bytes at %08lx for heap %08lx\n",
+                 size - subheap->commitSize,
+                 (DWORD)((char *)subheap + subheap->commitSize),
+                 (DWORD)subheap->heap );
+        return FALSE;
+    }
+    subheap->commitSize = size;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           HEAP_Decommit
+ *
+ * If possible, decommit the heap storage from (including) 'ptr'.
+ */
+static BOOL HEAP_Decommit( SUBHEAP *subheap, void *ptr )
+{
+    DWORD size = (DWORD)((char *)ptr - (char *)subheap);
+    size = (size + 0xfff) & 0xfffff000;  /* Align size on a page boundary */
+    if (size >= subheap->commitSize) return TRUE;
+    if (!VirtualFree( (char *)subheap + subheap->commitSize,
+                      size - subheap->commitSize, MEM_DECOMMIT ))
+    {
+        fprintf( stderr, "HEAP_Decommit: could not decommit %08lx bytes at %08lx for heap %08lx\n",
+                 size - subheap->commitSize,
+                 (DWORD)((char *)subheap + subheap->commitSize),
+                 (DWORD)subheap->heap );
+        return FALSE;
+    }
+    subheap->commitSize = size;
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           HEAP_CreateFreeBlock
+ *
+ * Create a free block at a specified address. 'size' is the size of the
+ * whole block, including the new arena.
+ */
+static void HEAP_CreateFreeBlock( SUBHEAP *subheap, void *ptr, DWORD size )
+{
+    ARENA_FREE *pFree;
+
+    /* Create a free arena */
+
+    pFree = (ARENA_FREE *)ptr;
+    pFree->threadId = GetCurrentTask();
+    pFree->magic = ARENA_FREE_MAGIC;
+
+    /* If debugging, erase the freed block content */
+
+    if (debugging_heap)
+    {
+        char *pEnd = (char *)ptr + size;
+        if (pEnd > (char *)subheap + subheap->commitSize)
+            pEnd = (char *)subheap + subheap->commitSize;
+        if (pEnd > (char *)(pFree + 1))
+            memset( pFree + 1, ARENA_FREE_FILLER, pEnd - (char *)(pFree + 1) );
+    }
+
+    /* Check if next block is free also */
+
+    if (((char *)ptr + size < (char *)subheap + subheap->size) &&
+        (*(DWORD *)((char *)ptr + size) & ARENA_FLAG_FREE))
+    {
+        /* Remove the next arena from the free list */
+        ARENA_FREE *pNext = (ARENA_FREE *)((char *)ptr + size);
+        pNext->next->prev = pNext->prev;
+        pNext->prev->next = pNext->next;
+        size += (pNext->size & ARENA_SIZE_MASK) + sizeof(*pNext);
+        if (debugging_heap)
+            memset( pNext, ARENA_FREE_FILLER, sizeof(ARENA_FREE) );
+    }
+
+    /* Set the next block PREV_FREE flag and pointer */
+
+    if ((char *)ptr + size < (char *)subheap + subheap->size)
+    {
+        DWORD *pNext = (DWORD *)((char *)ptr + size);
+        *pNext |= ARENA_FLAG_PREV_FREE;
+        *(ARENA_FREE **)(pNext - 1) = pFree;
+    }
+
+    /* Last, insert the new block into the free list */
+
+    pFree->size = size - sizeof(*pFree);
+    HEAP_InsertFreeBlock( subheap->heap, pFree );
+}
+
+
+/***********************************************************************
+ *           HEAP_MakeInUseBlockFree
+ *
+ * Turn an in-use block into a free block. Can also decommit the end of
+ * the heap, and possibly even free the sub-heap altogether.
+ */
+static void HEAP_MakeInUseBlockFree( SUBHEAP *subheap, ARENA_INUSE *pArena )
+{
+    ARENA_FREE *pFree;
+    DWORD size = (pArena->size & ARENA_SIZE_MASK) + sizeof(*pArena);
+
+    /* Check if we can merge with previous block */
+
+    if (pArena->size & ARENA_FLAG_PREV_FREE)
+    {
+        pFree = *((ARENA_FREE **)pArena - 1);
+        size += (pFree->size & ARENA_SIZE_MASK) + sizeof(ARENA_FREE);
+        /* Remove it from the free list */
+        pFree->next->prev = pFree->prev;
+        pFree->prev->next = pFree->next;
+    }
+    else pFree = (ARENA_FREE *)pArena;
+
+    /* Create a free block */
+
+    HEAP_CreateFreeBlock( subheap, pFree, size );
+    size = (pFree->size & ARENA_SIZE_MASK) + sizeof(ARENA_FREE);
+    if ((char *)pFree + size < (char *)subheap + subheap->size)
+        return;  /* Not the last block, so nothing more to do */
+
+    /* Free the whole sub-heap if it's empty and not the original one */
+
+    if (((char *)pFree == (char *)subheap + subheap->headerSize) &&
+        (subheap != &subheap->heap->subheap))
+    {
+        /* FIXME: free the sub-heap here */
+        return;
+    }
+    
+    /* Decommit the end of the heap */
+
+    HEAP_Decommit( subheap, pFree + 1 );
+}
+
+
+/***********************************************************************
+ *           HEAP_ShrinkBlock
+ *
+ * Shrink an in-use block.
+ */
+static void HEAP_ShrinkBlock(SUBHEAP *subheap, ARENA_INUSE *pArena, DWORD size)
+{
+    if ((pArena->size & ARENA_SIZE_MASK) >= size + HEAP_MIN_BLOCK_SIZE)
+    {
+        HEAP_CreateFreeBlock( subheap, (char *)(pArena + 1) + size,
+                              (pArena->size & ARENA_SIZE_MASK) - size );
+        pArena->size = (pArena->size & ~ARENA_SIZE_MASK) | size;
+    }
+    else
+    {
+        /* Turn off PREV_FREE flag in next block */
+        char *pNext = (char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK);
+        if (pNext < (char *)subheap + subheap->size)
+            *(DWORD *)pNext &= ~ARENA_FLAG_PREV_FREE;
+    }
+}
+
+
+/***********************************************************************
+ *           HEAP_CreateSubHeap
+ *
+ * Create a sub-heap of the given size.
+ */
+static SUBHEAP *HEAP_CreateSubHeap( DWORD commitSize, DWORD totalSize )
+{
+    SUBHEAP *subheap;
+
+    /* Round-up sizes on a 64K boundary */
+
+    totalSize  = (totalSize + 0xffff) & 0xffff0000;
+    commitSize = (commitSize + 0xffff) & 0xffff0000;
+    if (!commitSize) commitSize = 0x10000;
+    if (totalSize < commitSize) totalSize = commitSize;
+
+    /* Allocate the memory block */
+
+    if (!(subheap = VirtualAlloc( NULL, totalSize,
+                                  MEM_RESERVE, PAGE_EXECUTE_READWRITE )))
+    {
+        fprintf( stderr, "HEAP_CreateSubHeap: could not VirtualAlloc %08lx bytes\n",
+                 totalSize );
+        return NULL;
+    }
+    if (!VirtualAlloc(subheap, commitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
+    {
+        fprintf( stderr, "HEAP_CreateSubHeap: could not commit %08lx bytes for sub-heap %08lx\n",
+                 commitSize, (DWORD)subheap );
+        VirtualFree( subheap, 0, MEM_RELEASE );
+        return NULL;
+    }
+
+    /* Fill the sub-heap structure */
+
+    subheap->size       = totalSize;
+    subheap->commitSize = commitSize;
+    subheap->headerSize = sizeof(*subheap);
+    subheap->next       = NULL;
+    subheap->heap       = NULL;
+    subheap->magic      = SUBHEAP_MAGIC;
+    return subheap;
+}
+
+
+/***********************************************************************
+ *           HEAP_FindFreeBlock
+ *
+ * Find a free block at least as large as the requested size, and make sure
+ * the requested size is committed.
+ */
+static ARENA_FREE *HEAP_FindFreeBlock( HEAP *heap, DWORD size,
+                                       SUBHEAP **ppSubHeap )
+{
+    SUBHEAP *subheap;
+    ARENA_FREE *pArena;
+    FREE_LIST_ENTRY *pEntry = heap->freeList;
+
+    /* Find a suitable free list, and in it find a block large enough */
+
+    while (pEntry->size < size) pEntry++;
+    pArena = pEntry->arena.next;
+    while (pArena != &heap->freeList[0].arena)
+    {
+        if (pArena->size > size)
+        {
+            subheap = HEAP_FindSubHeap( heap, pArena );
+            if (!HEAP_Commit( subheap, (char *)pArena + sizeof(ARENA_INUSE)
+                                               + size + HEAP_MIN_BLOCK_SIZE))
+                return NULL;
+            *ppSubHeap = subheap;
+            return pArena;
+        }
+
+        pArena = pArena->next;
+    }
+
+    /* If no block was found, attempt to grow the heap */
+
+    if (!(heap->flags & HEAP_GROWABLE))
+    {
+        fprintf( stderr, "HEAP_FindFreeBlock: Not enough space in heap %08lx for %08lx bytes\n",
+                 (DWORD)heap, size );
+        return NULL;
+    }
+    size += sizeof(SUBHEAP) + sizeof(ARENA_FREE);
+    if (!(subheap = HEAP_CreateSubHeap( size, MAX( HEAP_DEF_SIZE, size ) )))
+        return NULL;
+
+    /* Insert the new sub-heap in the list */
+
+    subheap->heap = heap;
+    subheap->next = heap->subheap.next;
+    heap->subheap.next = subheap;
+    size = subheap->size;
+    dprintf_heap( stddeb, "HEAP_FindFreeBlock: created new sub-heap %08lx of %08lx bytes for heap %08lx\n",
+                  (DWORD)subheap, size, (DWORD)heap );
+
+    HEAP_CreateFreeBlock( subheap, subheap + 1, size - sizeof(*subheap) );
+    *ppSubHeap = subheap;
+    return (ARENA_FREE *)(subheap + 1);
+}
+
+
+/***********************************************************************
+ *           HEAP_IsValidArenaPtr
+ *
+ * Check that the pointer is inside the range possible for arenas.
+ */
+static BOOL HEAP_IsValidArenaPtr( HEAP *heap, void *ptr )
+{
+    int i;
+    SUBHEAP *subheap = HEAP_FindSubHeap( heap, ptr );
+    if (!subheap) return FALSE;
+    if ((char *)ptr >= (char *)subheap + subheap->headerSize) return TRUE;
+    if (subheap != &heap->subheap) return FALSE;
+    for (i = 0; i < HEAP_NB_FREE_LISTS; i++)
+        if (ptr == (void *)&heap->freeList[i].arena) return TRUE;
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           HEAP_ValidateFreeArena
+ */
+static BOOL HEAP_ValidateFreeArena( SUBHEAP *subheap, ARENA_FREE *pArena )
+{
+    char *heapEnd = (char *)subheap + subheap->size;
+
+    /* Check magic number */
+    if (pArena->magic != ARENA_FREE_MAGIC)
+    {
+        fprintf( stderr, "Heap %08lx: invalid free arena magic for %08lx\n",
+                 (DWORD)subheap->heap, (DWORD)pArena );
+        return FALSE;
+    }
+    /* Check size flags */
+    if (!(pArena->size & ARENA_FLAG_FREE) ||
+        (pArena->size & ARENA_FLAG_PREV_FREE))
+    {
+        fprintf( stderr, "Heap %08lx: bad flags %lx for free arena %08lx\n",
+                 (DWORD)subheap->heap, pArena->size & ~ARENA_SIZE_MASK, (DWORD)pArena );
+    }
+    /* Check arena size */
+    if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) > heapEnd)
+    {
+        fprintf( stderr, "Heap %08lx: bad size %08lx for free arena %08lx\n",
+                 (DWORD)subheap->heap, (DWORD)pArena->size & ARENA_SIZE_MASK, (DWORD)pArena );
+        return FALSE;
+    }
+    /* Check that next pointer is valid */
+    if (!HEAP_IsValidArenaPtr( subheap->heap, pArena->next ))
+    {
+        fprintf( stderr, "Heap %08lx: bad next ptr %08lx for arena %08lx\n",
+                 (DWORD)subheap->heap, (DWORD)pArena->next, (DWORD)pArena );
+        return FALSE;
+    }
+    /* Check that next arena is free */
+    if (!(pArena->next->size & ARENA_FLAG_FREE) ||
+        (pArena->next->magic != ARENA_FREE_MAGIC))
+    { 
+        fprintf( stderr, "Heap %08lx: next arena %08lx invalid for %08lx\n", 
+                 (DWORD)subheap->heap, (DWORD)pArena->next, (DWORD)pArena );
+        return FALSE;
+    }
+    /* Check that prev pointer is valid */
+    if (!HEAP_IsValidArenaPtr( subheap->heap, pArena->prev ))
+    {
+        fprintf( stderr, "Heap %08lx: bad prev ptr %08lx for arena %08lx\n",
+                 (DWORD)subheap->heap, (DWORD)pArena->prev, (DWORD)pArena );
+        return FALSE;
+    }
+    /* Check that prev arena is free */
+    if (!(pArena->prev->size & ARENA_FLAG_FREE) ||
+        (pArena->prev->magic != ARENA_FREE_MAGIC))
+    { 
+        fprintf( stderr, "Heap %08lx: prev arena %08lx invalid for %08lx\n", 
+                 (DWORD)subheap->heap, (DWORD)pArena->prev, (DWORD)pArena );
+        return FALSE;
+    }
+    /* Check that next block has PREV_FREE flag */
+    if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) < heapEnd)
+    {
+        if (!(*(DWORD *)((char *)(pArena + 1) +
+            (pArena->size & ARENA_SIZE_MASK)) & ARENA_FLAG_PREV_FREE))
+        {
+            fprintf( stderr, "Heap %08lx: free arena %08lx next block has no PREV_FREE flag\n",
+                     (DWORD)subheap->heap, (DWORD)pArena );
+            return FALSE;
+        }
+        /* Check next block back pointer */
+        if (*((ARENA_FREE **)((char *)(pArena + 1) +
+            (pArena->size & ARENA_SIZE_MASK)) - 1) != pArena)
+        {
+            fprintf( stderr, "Heap %08lx: arena %08lx has wrong back ptr %08lx\n",
+                     (DWORD)subheap->heap, (DWORD)pArena,
+                     *((DWORD *)((char *)(pArena+1)+ (pArena->size & ARENA_SIZE_MASK)) - 1));
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           HEAP_ValidateInUseArena
+ */
+static BOOL HEAP_ValidateInUseArena( SUBHEAP *subheap, ARENA_INUSE *pArena )
+{
+    char *heapEnd = (char *)subheap + subheap->size;
+
+    /* Check magic number */
+    if (pArena->magic != ARENA_INUSE_MAGIC)
+    {
+        fprintf( stderr, "Heap %08lx: invalid in-use arena magic for %08lx\n",
+                 (DWORD)subheap->heap, (DWORD)pArena );
+        return FALSE;
+    }
+    /* Check size flags */
+    if (pArena->size & ARENA_FLAG_FREE) 
+    {
+        fprintf( stderr, "Heap %08lx: bad flags %lx for in-use arena %08lx\n",
+                 (DWORD)subheap->heap, pArena->size & ~ARENA_SIZE_MASK, (DWORD)pArena );
+    }
+    /* Check arena size */
+    if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) > heapEnd)
+    {
+        fprintf( stderr, "Heap %08lx: bad size %08lx for in-use arena %08lx\n",
+                 (DWORD)subheap->heap, (DWORD)pArena->size & ARENA_SIZE_MASK, (DWORD)pArena );
+        return FALSE;
+    }
+    /* Check next arena PREV_FREE flag */
+    if (((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) < heapEnd) &&
+        (*(DWORD *)((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK)) & ARENA_FLAG_PREV_FREE))
+    {
+        fprintf( stderr, "Heap %08lx: in-use arena %08lx next block has PREV_FREE flag\n",
+                 (DWORD)subheap->heap, (DWORD)pArena );
+        return FALSE;
+    }
+    /* Check prev free arena */
+    if (pArena->size & ARENA_FLAG_PREV_FREE)
+    {
+        ARENA_FREE *pPrev = *((ARENA_FREE **)pArena - 1);
+        /* Check prev pointer */
+        if (!HEAP_IsValidArenaPtr( subheap->heap, pPrev ))
+        {
+            fprintf(stderr, "Heap %08lx: bad back ptr %08lx for arena %08lx\n",
+                    (DWORD)subheap->heap, (DWORD)pPrev, (DWORD)pArena );
+            return FALSE;
+        }
+        /* Check that prev arena is free */
+        if (!(pPrev->size & ARENA_FLAG_FREE) ||
+            (pPrev->magic != ARENA_FREE_MAGIC))
+        { 
+            fprintf( stderr, "Heap %08lx: prev arena %08lx invalid for in-use %08lx\n", 
+                     (DWORD)subheap->heap, (DWORD)pPrev, (DWORD)pArena );
+            return FALSE;
+        }
+        /* Check that prev arena is really the previous block */
+        if ((char *)(pPrev + 1) + (pPrev->size & ARENA_SIZE_MASK) != (char *)pArena)
+        {
+            fprintf( stderr, "Heap %08lx: prev arena %08lx is not prev for in-use %08lx\n",
+                     (DWORD)subheap->heap, (DWORD)pPrev, (DWORD)pArena );
+            return FALSE;
+        }
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           HeapCreate   (KERNEL32.336)
+ */
+HANDLE32 HeapCreate( DWORD flags, DWORD initialSize, DWORD maxSize )
+{
+    int i;
+    HEAP *heap;
+    SUBHEAP *subheap;
+    FREE_LIST_ENTRY *pEntry;
+
+    /* Allocate the heap block */
+
+    if (!maxSize)
+    {
+        maxSize = HEAP_DEF_SIZE;
+        flags |= HEAP_GROWABLE;
+    }
+    if (!(subheap = HEAP_CreateSubHeap( initialSize, maxSize )))
+    {
+        SetLastError( ERROR_OUTOFMEMORY );
+        return 0;
+    }
+
+    /* Fill the heap structure */
+
+    heap = (HEAP *)subheap;
+    subheap->heap       = heap;
+    subheap->headerSize = sizeof(HEAP);
+    heap->next          = NULL;
+    heap->flags         = flags;
+    heap->magic         = HEAP_MAGIC;
+    InitializeCriticalSection( &heap->critSection );
+
+    /* Build the free lists */
+
+    for (i = 0, pEntry = heap->freeList; i < HEAP_NB_FREE_LISTS; i++, pEntry++)
+    {
+        pEntry->size           = HEAP_freeListSizes[i];
+        pEntry->arena.size     = 0 | ARENA_FLAG_FREE;
+        pEntry->arena.next     = i < HEAP_NB_FREE_LISTS-1 ?
+                         &heap->freeList[i+1].arena : &heap->freeList[0].arena;
+        pEntry->arena.prev     = i ? &heap->freeList[i-1].arena : 
+                                   &heap->freeList[HEAP_NB_FREE_LISTS-1].arena;
+        pEntry->arena.threadId = 0;
+        pEntry->arena.magic    = ARENA_FREE_MAGIC;
+    }
+
+    /* Create the first free block */
+
+    HEAP_CreateFreeBlock( subheap, heap + 1, subheap->size - sizeof(*heap) );
+
+    /* We are done */
+
+    SetLastError( 0 );
+    return (HANDLE32)heap;
+}
+
+
+/***********************************************************************
+ *           HeapDestroy   (KERNEL32.337)
+ */
+BOOL HeapDestroy( HANDLE32 heap )
+{
+    HEAP *heapPtr = HEAP_GetPtr( heap );
+    SUBHEAP *subheap;
+
+    dprintf_heap( stddeb, "HeapDestroy: %08lx\n", heap );
+    if (!heapPtr) return FALSE;
+
+    DeleteCriticalSection( &heapPtr->critSection );
+    subheap = &heapPtr->subheap;
+    while (subheap)
+    {
+        SUBHEAP *next = subheap->next;
+        VirtualFree( subheap, subheap->commitSize, MEM_DECOMMIT );
+        VirtualFree( subheap, 0, MEM_RELEASE );
+        subheap = next;
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           HeapAlloc   (KERNEL32.334)
+ */
+LPVOID HeapAlloc( HANDLE32 heap, DWORD flags, DWORD size )
+{
+    ARENA_FREE *pArena;
+    ARENA_INUSE *pInUse;
+    SUBHEAP *subheap;
+    HEAP *heapPtr = HEAP_GetPtr( heap );
+
+    /* Validate the parameters */
+
+    if (!heapPtr) return NULL;
+    flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY;
+    flags |= heapPtr->flags;
+    if (!(flags & HEAP_NO_SERIALIZE)) HeapLock( heap );
+    size = (size + 3) & ~3;
+    if (size < HEAP_MIN_BLOCK_SIZE) size = HEAP_MIN_BLOCK_SIZE;
+
+    /* Locate a suitable free block */
+
+    if (!(pArena = HEAP_FindFreeBlock( heapPtr, size, &subheap )))
+    {
+        dprintf_heap( stddeb, "HeapAlloc(%08lx,%08lx,%08lx): returning NULL\n",
+                  heap, flags, size  );
+        if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap );
+        SetLastError( ERROR_OUTOFMEMORY );
+        return NULL;
+    }
+
+    /* Remove the arena from the free list */
+
+    pArena->next->prev = pArena->prev;
+    pArena->prev->next = pArena->next;
+
+    /* Build the in-use arena */
+
+    pInUse = (ARENA_INUSE *)pArena;
+    pInUse->size      = (pInUse->size & ~ARENA_FLAG_FREE)
+                        + sizeof(ARENA_FREE) - sizeof(ARENA_INUSE);
+    pInUse->callerEIP = *((DWORD *)&heap - 1);  /* hack hack */
+    pInUse->threadId  = GetCurrentTask();
+    pInUse->magic     = ARENA_INUSE_MAGIC;
+
+    /* Shrink the block */
+
+    HEAP_ShrinkBlock( subheap, pInUse, size );
+
+    if (flags & HEAP_ZERO_MEMORY) memset( pInUse + 1, 0, size );
+    else if (debugging_heap) memset( pInUse + 1, ARENA_INUSE_FILLER, size );
+
+    if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap );
+    SetLastError( 0 );
+
+    dprintf_heap( stddeb, "HeapAlloc(%08lx,%08lx,%08lx): returning %08lx\n",
+                  heap, flags, size, (DWORD)(pInUse + 1) );
+    return (LPVOID)(pInUse + 1);
+}
+
+
+/***********************************************************************
+ *           HeapFree   (KERNEL32.338)
+ */
+BOOL HeapFree( HANDLE32 heap, DWORD flags, LPVOID ptr )
+{
+    ARENA_INUSE *pInUse;
+    SUBHEAP *subheap;
+    HEAP *heapPtr = HEAP_GetPtr( heap );
+
+    /* Validate the parameters */
+
+    if (!heapPtr) return FALSE;
+    flags &= HEAP_NO_SERIALIZE;
+    flags |= heapPtr->flags;
+    if (!(flags & HEAP_NO_SERIALIZE)) HeapLock( heap );
+    if (!HeapValidate( heap, HEAP_NO_SERIALIZE, ptr ))
+    {
+        if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap );
+        SetLastError( ERROR_INVALID_PARAMETER );
+        dprintf_heap( stddeb, "HeapFree(%08lx,%08lx,%08lx): returning FALSE\n",
+                      heap, flags, (DWORD)ptr );
+        return FALSE;
+    }
+
+    /* Turn the block into a free block */
+
+    pInUse  = (ARENA_INUSE *)ptr - 1;
+    subheap = HEAP_FindSubHeap( heapPtr, pInUse );
+    HEAP_MakeInUseBlockFree( subheap, pInUse );
+
+    if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap );
+    SetLastError( 0 );
+
+    dprintf_heap( stddeb, "HeapFree(%08lx,%08lx,%08lx): returning TRUE\n",
+                  heap, flags, (DWORD)ptr );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           HeapReAlloc   (KERNEL32.340)
+ */
+LPVOID HeapReAlloc( HANDLE32 heap, DWORD flags, LPVOID ptr, DWORD size )
+{
+    ARENA_INUSE *pArena;
+    DWORD oldSize;
+    HEAP *heapPtr;
+    SUBHEAP *subheap;
+
+    if (!ptr) return HeapAlloc( heap, flags, size );  /* FIXME: correct? */
+    if (!(heapPtr = HEAP_GetPtr( heap ))) return FALSE;
+
+    /* Validate the parameters */
+
+    flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY |
+             HEAP_REALLOC_IN_PLACE_ONLY;
+    flags |= heapPtr->flags;
+    size = (size + 3) & ~3;
+    if (size < HEAP_MIN_BLOCK_SIZE) size = HEAP_MIN_BLOCK_SIZE;
+
+    if (!(flags & HEAP_NO_SERIALIZE)) HeapLock( heap );
+    if (!HeapValidate( heap, HEAP_NO_SERIALIZE, ptr ))
+    {
+        if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap );
+        SetLastError( ERROR_INVALID_PARAMETER );
+        dprintf_heap( stddeb, "HeapReAlloc(%08lx,%08lx,%08lx,%08lx): returning NULL\n",
+                      heap, flags, (DWORD)ptr, size );
+        return NULL;
+    }
+
+    /* Check if we need to grow the block */
+
+    pArena = (ARENA_INUSE *)ptr - 1;
+    pArena->threadId = GetCurrentTask();
+    subheap = HEAP_FindSubHeap( heapPtr, pArena );
+    oldSize = (pArena->size & ARENA_SIZE_MASK);
+    if (size > oldSize)
+    {
+        char *pNext = (char *)(pArena + 1) + oldSize;
+        if ((pNext < (char *)subheap + subheap->size) &&
+            (*(DWORD *)pNext & ARENA_FLAG_FREE) &&
+            (oldSize + (*(DWORD *)pNext & ARENA_SIZE_MASK) + sizeof(ARENA_FREE) >= size))
+        {
+            /* The next block is free and large enough */
+            ARENA_FREE *pFree = (ARENA_FREE *)pNext;
+            pFree->next->prev = pFree->prev;
+            pFree->prev->next = pFree->next;
+            pArena->size += (pFree->size & ARENA_SIZE_MASK) + sizeof(*pFree);
+        }
+        else  /* Do it the hard way */
+        {
+            ARENA_FREE *pNew;
+            ARENA_INUSE *pInUse;
+            SUBHEAP *newsubheap;
+
+            if ((flags & HEAP_REALLOC_IN_PLACE_ONLY) ||
+                !(pNew = HEAP_FindFreeBlock( heapPtr, size, &newsubheap )))
+            {
+                if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap );
+                return NULL;
+            }
+
+            /* Build the in-use arena */
+
+            pNew->next->prev = pNew->prev;
+            pNew->prev->next = pNew->next;
+            pInUse = (ARENA_INUSE *)pNew;
+            pInUse->size     = (pInUse->size & ~ARENA_FLAG_FREE)
+                               + sizeof(ARENA_FREE) - sizeof(ARENA_INUSE);
+            pInUse->threadId = GetCurrentTask();
+            pInUse->magic    = ARENA_INUSE_MAGIC;
+            memcpy( pInUse + 1, pArena + 1, oldSize );
+
+            /* Free the previous block */
+
+            HEAP_MakeInUseBlockFree( subheap, pArena );
+            subheap = newsubheap;
+            pArena  = pInUse;
+        }
+    }
+
+
+    /* Shrink the block */
+
+    HEAP_ShrinkBlock( subheap, pArena, size );
+
+    /* Clear the extra bytes if needed */
+
+    if (size > oldSize)
+    {
+        if (flags & HEAP_ZERO_MEMORY)
+            memset( (char *)(pArena + 1) + oldSize, 0,
+                    (pArena->size & ARENA_SIZE_MASK) - oldSize );
+        else if (debugging_heap)
+            memset( (char *)(pArena + 1) + oldSize, ARENA_INUSE_FILLER,
+                    (pArena->size & ARENA_SIZE_MASK) - oldSize );
+    }
+
+    /* Return the new arena */
+
+    pArena->callerEIP = *((DWORD *)&heap - 1);  /* hack hack */
+    if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap );
+
+    dprintf_heap( stddeb, "HeapReAlloc(%08lx,%08lx,%08lx,%08lx): returning %08lx\n",
+                  heap, flags, (DWORD)ptr, size, (DWORD)(pArena + 1) );
+    return (LPVOID)(pArena + 1);
+}
+
+
+/***********************************************************************
+ *           HeapCompact   (KERNEL32.335)
+ */
+DWORD HeapCompact( HANDLE32 heap, DWORD flags )
+{
+    return 0;
+}
+
+
+/***********************************************************************
+ *           HeapLock   (KERNEL32.339)
+ */
+BOOL HeapLock( HANDLE32 heap )
+{
+    HEAP *heapPtr = HEAP_GetPtr( heap );
+
+    if (!heapPtr) return FALSE;
+    EnterCriticalSection( &heapPtr->critSection );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           HeapUnlock   (KERNEL32.342)
+ */
+BOOL HeapUnlock( HANDLE32 heap )
+{
+    HEAP *heapPtr = HEAP_GetPtr( heap );
+
+    if (!heapPtr) return FALSE;
+    LeaveCriticalSection( &heapPtr->critSection );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           HeapSize   (KERNEL32.341)
+ */
+DWORD HeapSize( HANDLE32 heap, DWORD flags, LPVOID ptr )
+{
+    DWORD ret;
+    HEAP *heapPtr = HEAP_GetPtr( heap );
+
+    if (!heapPtr) return FALSE;
+    flags &= HEAP_NO_SERIALIZE;
+    flags |= heapPtr->flags;
+    if (!(flags & HEAP_NO_SERIALIZE)) HeapLock( heap );
+    if (!HeapValidate( heap, HEAP_NO_SERIALIZE, ptr ))
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        ret = 0xffffffff;
+    }
+    else
+    {
+        ARENA_INUSE *pArena = (ARENA_INUSE *)ptr - 1;
+        ret = pArena->size & ARENA_SIZE_MASK;
+    }
+    if (!(flags & HEAP_NO_SERIALIZE)) HeapUnlock( heap );
+
+    dprintf_heap( stddeb, "HeapSize(%08lx,%08lx,%08lx): returning %08lx\n",
+                  heap, flags, (DWORD)ptr, ret );
+    return ret;
+}
+
+
+/***********************************************************************
+ *           HeapValidate   (KERNEL32.343)
+ */
+BOOL HeapValidate( HANDLE32 heap, DWORD flags, LPVOID block )
+{
+    SUBHEAP *subheap;
+    HEAP *heapPtr = (HEAP *)heap;
+
+    if (!heapPtr || (heapPtr->magic != HEAP_MAGIC))
+    {
+        fprintf( stderr, "Invalid heap %08lx!\n", heap );
+        return FALSE;
+    }
+
+    if (block)
+    {
+        if (!(subheap = HEAP_FindSubHeap( heapPtr, block )) ||
+            ((char *)block < (char *)subheap + subheap->headerSize
+                              + sizeof(ARENA_INUSE)))
+        {
+            fprintf( stderr, "Heap %08lx: block %08lx is not inside heap\n",
+                     (DWORD)heap, (DWORD)block );
+            return FALSE;
+        }
+        return HEAP_ValidateInUseArena( subheap, (ARENA_INUSE *)block - 1 );
+    }
+
+    subheap = &heapPtr->subheap;
+    while (subheap)
+    {
+        char *ptr = (char *)subheap + subheap->headerSize;
+        while (ptr < (char *)subheap + subheap->size)
+        {
+            if (*(DWORD *)ptr & ARENA_FLAG_FREE)
+            {
+                if (!HEAP_ValidateFreeArena( subheap, (ARENA_FREE *)ptr ))
+                    return FALSE;
+                ptr += sizeof(ARENA_FREE) + (*(DWORD *)ptr & ARENA_SIZE_MASK);
+            }
+            else
+            {
+                if (!HEAP_ValidateInUseArena( subheap, (ARENA_INUSE *)ptr ))
+                    return FALSE;
+                ptr += sizeof(ARENA_INUSE) + (*(DWORD *)ptr & ARENA_SIZE_MASK);
+            }
+        }
+        subheap = subheap->next;
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           HeapWalk   (KERNEL32.344)
+ */
+BOOL HeapWalk( HANDLE32 heap, void *entry )
+{
+    return FALSE;
+}
diff --git a/memory/local.c b/memory/local.c
index f249a80..96fa999 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -313,7 +313,7 @@
     if (start == 0) {
       /* Check if the segment is the DGROUP of a module */
 
-	if ((pModule = (NE_MODULE *)GlobalLock( GetExePtr( selector ) )))
+	if ((pModule = MODULE_GetPtr( GetExePtr( selector ) )))
 	{
 	    SEGTABLEENTRY *pSeg = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
 	    if (pModule->dgroup && (pSeg->selector == selector)) {
diff --git a/memory/selector.c b/memory/selector.c
index 26afe79..b3b117f 100644
--- a/memory/selector.c
+++ b/memory/selector.c
@@ -121,9 +121,9 @@
     {
         LDT_SetEntry( SELECTOR_TO_ENTRY(sel) + i, &entry );
         entry.base += 0x10000;
-        size -= 0x10000;
-        entry.limit = (size > 0x10000) ? 0xffff : size-1;
-        entry.limit_in_pages = 0;
+        /* Apparently the next selectors should *not* get a 64k limit. */
+        /* Can't remember where I read they should... --AJ */
+        entry.limit -= entry.limit_in_pages ? 0x10 : 0x10000;
     }
 }
 
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 66beced..089019b 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -2,6 +2,7 @@
  * COMMDLG functions
  *
  * Copyright 1994 Martin Ayotte
+ * Copyright 1996 Albrecht Kleine
  */
 
 #include <stdio.h>
@@ -694,33 +695,6 @@
 
 
 /***********************************************************************
- *           ColorDlgProc   (COMMDLG.8)
- */
-LRESULT ColorDlgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)
-{
-  switch (wMsg) 
-    {
-    case WM_INITDIALOG:
-      dprintf_commdlg(stddeb,"ColorDlgProc // WM_INITDIALOG lParam=%08lX\n", lParam);
-      ShowWindow(hWnd, SW_SHOWNORMAL);
-      return (TRUE);
-    case WM_COMMAND:
-      switch (wParam)
-	{
-	case IDOK:
-	  EndDialog(hWnd, TRUE);
-	  return(TRUE);
-	case IDCANCEL:
-	  EndDialog(hWnd, FALSE);
-	  return(TRUE);
-	}
-      return(FALSE);
-    }
-  return FALSE;
-}
-
-
-/***********************************************************************
  *           FindTextDlg   (COMMDLG.11)
  */
 BOOL FindText(LPFINDREPLACE lpFind)
@@ -1119,3 +1093,1068 @@
     strncpy(lpTitle, &lpFile[i], len);
     return 0;
 }
+
+
+/* --------------------------- Choose Color Dialog ------------------------------ */
+
+static const COLORREF predefcolors[6][8]=
+{
+ { 0x008080FFL, 0x0080FFFFL, 0x0080FF80L, 0x0080FF00L,
+   0x00FFFF80L, 0x00FF8000L, 0x00C080FFL, 0x00FF80FFL },
+ { 0x000000FFL, 0x0000FFFFL, 0x0000FF80L, 0x0040FF00L,
+   0x00FFFF00L, 0x00C08000L, 0x00C08080L, 0x00FF00FFL },
+
+ { 0x00404080L, 0x004080FFL, 0x0000FF00L, 0x00808000L,
+   0x00804000L, 0x00FF8080L, 0x00400080L, 0x008000FFL },
+ { 0x00000080L, 0x000080FFL, 0x00008000L, 0x00408000L,
+   0x00FF0000L, 0x00A00000L, 0x00800080L, 0x00FF0080L },
+
+ { 0x00000040L, 0x00004080L, 0x00004000L, 0x00404000L,
+   0x00800000L, 0x00400000L, 0x00400040L, 0x00800040L },
+ { 0x00000000L, 0x00008080L, 0x00408080L, 0x00808080L,
+   0x00808040L, 0x00C0C0C0L, 0x00400040L, 0x00FFFFFFL },
+};
+
+struct CCPRIVATE
+{
+ LPCHOOSECOLOR lpcc;  /* points to public known data structure */
+ int nextuserdef;     /* next free place in user defined color array */
+ HDC hdcMem;          /* color graph used for BitBlt() */
+ RECT fullsize;       /* original dialog window size */
+ UINT msetrgb;        /* # of SETRGBSTRING message (today not used)  */
+ RECT old3angle;      /* last position of l-marker */
+ RECT oldcross;       /* last position of color/satuation marker */
+ int h;
+ int s;
+ int l;               /* for temporary storing of hue,sat,lum */
+};
+
+/***********************************************************************
+ *                             CC_HSLtoRGB                    [internal]
+ */
+static int CC_HSLtoRGB(char c,int hue,int sat,int lum)
+{
+ int res=0,maxrgb;
+
+ /* hue */
+ switch(c)
+ {
+  case 'R':if (hue>80)  hue-=80;  else hue+=160; break;
+  case 'G':if (hue>160) hue-=160; else hue+=80;  break;
+  case 'B':break;
+ }
+
+ /* l below 120 */
+ maxrgb=(256*MIN(120,lum))/120;  /* 0 .. 256 */
+ if (hue< 80)
+  res=0;
+ else
+  if (hue< 120)
+  {
+   res=(hue-80)* maxrgb;           /* 0...10240 */
+   res/=40;                        /* 0...256 */
+  }
+  else
+   if (hue< 200)
+    res=maxrgb;
+   else
+    {
+     res=(240-hue)* maxrgb;
+     res/=40;
+    }
+ res=res-maxrgb/2;                 /* -128...128 */
+
+ /* saturation */
+ res=maxrgb/2 + (sat*res) /240;    /* 0..256 */
+
+ /* lum above 120 */
+ if (lum>120 && res<256)
+  res+=((lum-120) * (256-res))/120;
+
+ return MIN(res,255);
+}
+
+/***********************************************************************
+ *                             CC_RGBtoHSL                    [internal]
+ */
+static int CC_RGBtoHSL(char c,int r,int g,int b)
+{
+ WORD maxi,mini,mmsum,mmdif,result=0;
+ int iresult=0;
+
+ maxi=MAX(r,b);
+ maxi=MAX(maxi,g);
+ mini=MIN(r,b);
+ mini=MIN(mini,g);
+
+ mmsum=maxi+mini;
+ mmdif=maxi-mini;
+
+ switch(c)
+ {
+  /* lum */
+  case 'L':mmsum*=120;              /* 0...61200=(255+255)*120 */
+	   result=mmsum/255;        /* 0...240 */
+	   break;
+  /* saturation */
+  case 'S':if (!mmsum)
+	    result=0;
+	   else
+	    if (!mini || maxi==255)
+	     result=240;
+	   else
+	   {
+	    result=mmdif*240;       /* 0...61200=255*240 */
+	    result/= (mmsum>255 ? mmsum=510-mmsum : mmsum); /* 0..255 */
+	   }
+	   break;
+  /* hue */
+  case 'H':if (!mmdif)
+	    result=160;
+	   else
+	   {
+	    if (maxi==r)
+	    {
+	     iresult=40*(g-b);       /* -10200 ... 10200 */
+	     iresult/=(int)mmdif;    /* -40 .. 40 */
+	     if (iresult<0)
+	      iresult+=240;          /* 0..40 and 200..240 */
+	    }
+	    else
+	     if (maxi==g)
+	     {
+	      iresult=40*(b-r);
+	      iresult/=(int)mmdif;
+	      iresult+=80;           /* 40 .. 120 */
+	     }
+	     else
+	      if (maxi==b)
+	      {
+	       iresult=40*(r-g);
+	       iresult/=(int)mmdif;
+	       iresult+=160;         /* 120 .. 200 */
+	      }
+	    result=iresult;
+	   }
+	   break;
+ }
+ return result;    /* is this integer arithmetic precise enough ? */
+}
+
+#define DISTANCE 4
+
+/***********************************************************************
+ *                CC_MouseCheckPredefColorArray               [internal]
+ */
+static int CC_MouseCheckPredefColorArray(HWND hDlg,int dlgitem,int rows,int cols,
+	    LPARAM lParam,COLORREF *cr)
+{
+ HWND hwnd;
+ POINT point;
+ RECT rect;
+ int dx,dy,x,y;
+
+ point.x=LOWORD(lParam);
+ point.y=HIWORD(lParam);
+ ClientToScreen(hDlg,&point);
+
+ hwnd=GetDlgItem(hDlg,dlgitem);
+ GetWindowRect(hwnd,&rect);
+ if (PtInRect(&rect,point))
+ {
+  dx=(rect.right-rect.left)/cols;
+  dy=(rect.bottom-rect.top)/rows;
+  ScreenToClient(hwnd,&point);
+
+  if (point.x % dx < (dx-DISTANCE) && point.y % dy < (dy-DISTANCE))
+  {
+   x=point.x/dx;
+   y=point.y/dy;
+   *cr=predefcolors[y][x];
+   /* FIXME: Draw_a_Focus_Rect() */
+   return 1;
+  }
+ }
+ return 0;
+}
+
+/***********************************************************************
+ *                  CC_MouseCheckUserColorArray               [internal]
+ */
+static int CC_MouseCheckUserColorArray(HWND hDlg,int dlgitem,int rows,int cols,
+	    LPARAM lParam,COLORREF *cr,COLORREF*crarr)
+{
+ HWND hwnd;
+ POINT point;
+ RECT rect;
+ int dx,dy,x,y;
+
+ point.x=LOWORD(lParam);
+ point.y=HIWORD(lParam);
+ ClientToScreen(hDlg,&point);
+
+ hwnd=GetDlgItem(hDlg,dlgitem);
+ GetWindowRect(hwnd,&rect);
+ if (PtInRect(&rect,point))
+ {
+  dx=(rect.right-rect.left)/cols;
+  dy=(rect.bottom-rect.top)/rows;
+  ScreenToClient(hwnd,&point);
+
+  if (point.x % dx < (dx-DISTANCE) && point.y % dy < (dy-DISTANCE))
+  {
+   x=point.x/dx;
+   y=point.y/dy;
+   *cr=crarr[x+cols*y];
+   /* FIXME: Draw_a_Focus_Rect() */
+   return 1;
+  }
+ }
+ return 0;
+}
+
+#define MAXVERT  240
+#define MAXHORI  239
+
+/*  240  ^......        ^^ 240
+	 |     .        ||
+    SAT  |     .        || LUM
+	 |     .        ||
+	 +-----> 239   ----
+	   HUE
+*/
+/***********************************************************************
+ *                  CC_MouseCheckColorGraph                   [internal]
+ */
+static int CC_MouseCheckColorGraph(HWND hDlg,int dlgitem,int *hori,int *vert,LPARAM lParam)
+{
+ HWND hwnd;
+ POINT point;
+ RECT rect;
+ long x,y;
+
+ point.x=LOWORD(lParam);
+ point.y=HIWORD(lParam);
+ ClientToScreen(hDlg,&point);
+ hwnd=GetDlgItem(hDlg,dlgitem);
+ GetWindowRect(hwnd,&rect);
+ if (PtInRect(&rect,point))
+ {
+  GetClientRect(hwnd,&rect);
+  ScreenToClient(hwnd,&point);
+
+  x=(long)point.x*MAXHORI;
+  x/=rect.right;
+  y=(long)(rect.bottom-point.y)*MAXVERT;
+  y/=rect.bottom;
+
+  if (hori)
+   *hori=x;
+  if (vert)
+   *vert=y;
+  return 1;
+ }
+ else
+  return 0;
+}
+/***********************************************************************
+ *                  CC_MouseCheckResultWindow                 [internal]
+ */
+static int CC_MouseCheckResultWindow(HWND hDlg,LPARAM lParam)
+{
+ HWND hwnd;
+ POINT point;
+ RECT rect;
+ point.x=LOWORD(lParam);
+ point.y=HIWORD(lParam);
+ ClientToScreen(hDlg,&point);
+ hwnd=GetDlgItem(hDlg,0x2c5);
+ GetWindowRect(hwnd,&rect);
+ if (PtInRect(&rect,point))
+ {
+  PostMessage(hDlg,WM_COMMAND,0x2c9,0);
+  return 1;
+ }
+ return 0;
+}
+
+/***********************************************************************
+ *                       CC_CheckDigitsInEdit                 [internal]
+ */
+static int CC_CheckDigitsInEdit(HWND hwnd,int maxval)
+{
+ int i,k,m,result,value;
+ long editpos;
+ char buffer[30];
+ GetWindowText(hwnd,buffer,30-1);
+ m=lstrlen(buffer);
+ result=0;
+
+ for (i=0;i<m;i++)
+  if (buffer[i]<'0' || buffer[i]>'9')
+  {
+   for (k=i+1;k<=m;k++)   /* delete bad character */
+   {
+    buffer[i]=buffer[k];
+    m--;
+   }
+   buffer[m]=0;
+   result=1;
+  }
+
+ value=atoi(buffer);
+ if (value>maxval)       /* build a new string */
+ {
+  sprintf(buffer,"%d",maxval);
+  result=2;
+ }
+ if (result)
+ {
+  editpos=SendMessage(hwnd,EM_GETSEL,0,0);
+  SetWindowText(hwnd,buffer);
+  SendMessage(hwnd,EM_SETSEL,0,editpos);
+ }
+ return value;
+}
+
+
+
+/***********************************************************************
+ *                    CC_PaintSelectedColor                   [internal]
+ */
+static void CC_PaintSelectedColor(HWND hDlg,COLORREF cr)
+{
+ RECT rect;
+ HDC  hdc;
+ HBRUSH hBrush;
+ HWND hwnd=GetDlgItem(hDlg,0x2c5);
+ if (IsWindowVisible(GetDlgItem(hDlg,0x2c6)))   /* if full size */
+ {
+  hdc=GetDC(hwnd);
+  GetClientRect (hwnd, &rect) ;
+  hBrush = CreateSolidBrush(cr);
+  if (hBrush)
+  {
+   hBrush = SelectObject (hdc, hBrush) ;
+   Rectangle (hdc, rect.left,rect.top,rect.right/2,rect.bottom);
+   DeleteObject (SelectObject (hdc,hBrush)) ;
+   hBrush=CreateSolidBrush(GetNearestColor(hdc,cr));
+   if (hBrush)
+   {
+    hBrush= SelectObject (hdc, hBrush) ;
+    Rectangle (hdc, rect.right/2-1,rect.top,rect.right,rect.bottom);
+    DeleteObject (SelectObject (hdc, hBrush)) ;
+   }
+  }
+  ReleaseDC(hwnd,hdc);
+ }
+}
+
+/***********************************************************************
+ *                    CC_PaintTriangle                        [internal]
+ */
+static void CC_PaintTriangle(HWND hDlg,int y)
+{
+ HDC hDC;
+ long temp;
+ int w=GetDialogBaseUnits();
+ POINT points[3];
+ int height;
+ int oben;
+ RECT rect;
+ HWND hwnd=GetDlgItem(hDlg,0x2be);
+ struct CCPRIVATE *lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); 
+
+ if (IsWindowVisible(GetDlgItem(hDlg,0x2c6)))   /* if full size */
+ {
+   GetClientRect(hwnd,&rect);
+   height=rect.bottom;
+   hDC=GetDC(hDlg);
+
+   points[0].y=rect.top;
+   points[0].x=rect.right;         /*  |  /|  */
+   ClientToScreen(hwnd,points);    /*  | / |  */
+   ScreenToClient(hDlg,points);    /*  |<  |  */
+   oben=points[0].y;               /*  | \ |  */
+				   /*  |  \|  */
+   temp=(long)height*(long)y;
+   points[0].y=oben+height -temp/(long)MAXVERT;
+   points[1].y=points[0].y+w;
+   points[2].y=points[0].y-w;
+   points[2].x=points[1].x=points[0].x + w;
+
+   if (lpp->old3angle.left)
+    FillRect(hDC,&lpp->old3angle,GetStockObject(WHITE_BRUSH));
+   lpp->old3angle.left  =points[0].x;
+   lpp->old3angle.right =points[1].x+1;
+   lpp->old3angle.top   =points[2].y-1;
+   lpp->old3angle.bottom=points[1].y+1;
+   Polygon(hDC,points,3);
+   ReleaseDC(hDlg,hDC);
+ }
+}
+
+
+/***********************************************************************
+ *                    CC_PaintCross                           [internal]
+ */
+static void CC_PaintCross(HWND hDlg,int x,int y)
+{
+ HDC hDC;
+ long temp;
+ int w=GetDialogBaseUnits();
+ HWND hwnd=GetDlgItem(hDlg,0x2c6);
+ struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); 
+ RECT rect;
+ POINT point;
+ HPEN hPen;
+
+ if (IsWindowVisible(GetDlgItem(hDlg,0x2c6)))   /* if full size */
+ {
+   GetClientRect(hwnd,&rect);
+
+   hDC=GetDC(hwnd);
+   hPen=CreatePen(PS_SOLID,2,0);
+   hPen=SelectObject(hDC,hPen);
+
+   temp=(long)rect.right*(long)x;
+   point.x=temp/(long)MAXHORI;
+   temp=(long)rect.bottom*(long)y;
+   point.y=rect.bottom-temp/(long)MAXVERT;
+
+   if (lpp->oldcross.left!=lpp->oldcross.right)
+     BitBlt(hDC,lpp->oldcross.left,lpp->oldcross.top,
+	     lpp->oldcross.right-lpp->oldcross.left,
+	     lpp->oldcross.bottom-lpp->oldcross.top,
+	     lpp->hdcMem,lpp->oldcross.left,lpp->oldcross.top,SRCCOPY);
+
+   lpp->oldcross.left  =point.x-w-1;
+   lpp->oldcross.right =point.x+w+1;
+   lpp->oldcross.top   =point.y-w-1;
+   lpp->oldcross.bottom=point.y+w+1;
+
+   if (point.y+w/2<rect.bottom-3) /* perhaps better via SelectClipRgn() */
+   {
+    MoveTo(hDC,point.x,MIN(point.y+w/2,rect.bottom));
+    LineTo(hDC,point.x,MIN(point.y+w,rect.bottom-2));
+   }
+   if (point.y-w/2>3)
+   {
+    MoveTo(hDC,point.x,point.y-w/2);
+    LineTo(hDC,point.x,MAX(2,point.y-w  ));
+   }
+   if (point.x+w/2<rect.right-3)
+   {
+    MoveTo(hDC,point.x+w/2,point.y);
+    LineTo(hDC,MIN(rect.right,point.x+w),  point.y);
+   }
+   if ((point.x-w/2)>3)
+   {
+    MoveTo(hDC,point.x-w/2,point.y);
+    LineTo(hDC,MAX(2,point.x-w),  point.y);
+   }
+
+   DeleteObject(SelectObject(hDC,hPen));
+   ReleaseDC(hwnd,hDC);
+ }
+}
+
+
+#define XSTEPS 36
+#define YSTEPS 48
+
+
+/***********************************************************************
+ *                    CC_PrepareColorGraph                    [internal]
+ */
+static void CC_PrepareColorGraph(HWND hDlg)    
+{
+ int sdif,hdif,xdif,ydif,r,g,b,hue,sat;
+ HWND hwnd=GetDlgItem(hDlg,0x2c6);
+ struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER);  
+ HBRUSH hbrush;
+ HDC hdc ;
+ RECT rect,client;
+ HBITMAP hbmMem;
+ HCURSOR hcursor=SetCursor(LoadCursor(0,IDC_WAIT));
+
+ GetClientRect(hwnd,&client);
+ hdc=GetDC(hwnd);
+ lpp->hdcMem = CreateCompatibleDC(hdc);
+ hbmMem = CreateCompatibleBitmap(hdc,client.right,client.bottom);
+ SelectObject(lpp->hdcMem,hbmMem);
+
+ xdif=client.right /XSTEPS;
+ ydif=client.bottom/YSTEPS+1;
+ hdif=239/XSTEPS;
+ sdif=240/YSTEPS;
+ for(rect.left=hue=0;hue<239+hdif;hue+=hdif)
+ {
+  rect.right=rect.left+xdif;
+  rect.bottom=client.bottom;
+  for(sat=0;sat<240+sdif;sat+=sdif)
+  {
+   rect.top=rect.bottom-ydif;
+   r=CC_HSLtoRGB('R',hue,sat,120);
+   g=CC_HSLtoRGB('G',hue,sat,120);
+   b=CC_HSLtoRGB('B',hue,sat,120);
+   hbrush=CreateSolidBrush(RGB(r,g,b));
+   FillRect(lpp->hdcMem,&rect,hbrush);
+   DeleteObject(hbrush);
+   rect.bottom=rect.top;
+  }
+  rect.left=rect.right;
+ }
+ ReleaseDC(hwnd,hdc);
+ SetCursor(hcursor);
+ /* FIXME perhaps we should do it only ONCE for all, like hCDRom,.... ? */
+}
+
+/***********************************************************************
+ *                          CC_PaintColorGraph                [internal]
+ */
+static void CC_PaintColorGraph(HWND hDlg)
+{
+ HWND hwnd=GetDlgItem(hDlg,0x2c6);
+ struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); 
+ HDC  hDC;
+ RECT rect;
+ if (IsWindowVisible(hwnd))   /* if full size */
+ {
+  if (!lpp->hdcMem)
+   CC_PrepareColorGraph(hDlg);   /* should not be necessary */
+
+  hDC=GetDC(hwnd);
+  GetClientRect(hwnd,&rect);
+  if (lpp->hdcMem)
+    BitBlt(hDC,0,0,rect.right,rect.bottom,lpp->hdcMem,0,0,SRCCOPY);
+  else
+    fprintf(stderr,"choose color: hdcMem is not defined\n");
+  ReleaseDC(hwnd,hDC);
+ }
+}
+/***********************************************************************
+ *                           CC_PaintLumBar                   [internal]
+ */
+static void CC_PaintLumBar(HWND hDlg,int hue,int sat)
+{
+ HWND hwnd=GetDlgItem(hDlg,0x2be);
+ RECT rect,client;
+ int lum,ldif,ydif,r,g,b;
+ HBRUSH hbrush;
+ HDC hDC;
+
+ if (IsWindowVisible(hwnd))
+ {
+  hDC=GetDC(hwnd);
+  GetClientRect(hwnd,&client);
+  rect=client;
+
+  ldif=240/YSTEPS;
+  ydif=client.bottom/YSTEPS+1;
+  for(lum=0;lum<240+ldif;lum+=ldif)
+  {
+   rect.top=MAX(0,rect.bottom-ydif);
+   r=CC_HSLtoRGB('R',hue,sat,lum);
+   g=CC_HSLtoRGB('G',hue,sat,lum);
+   b=CC_HSLtoRGB('B',hue,sat,lum);
+   hbrush=CreateSolidBrush(RGB(r,g,b));
+   FillRect(hDC,&rect,hbrush);
+   DeleteObject(hbrush);
+   rect.bottom=rect.top;
+  }
+  GetClientRect(hwnd,&rect);
+  FrameRect(hDC,&rect,GetStockObject(BLACK_BRUSH));
+  ReleaseDC(hwnd,hDC);
+ }
+}
+
+/***********************************************************************
+ *                             CC_EditSetRGB                  [internal]
+ */
+static void CC_EditSetRGB(HWND hDlg,COLORREF cr)
+{
+ char buffer[10];
+ int r=GetRValue(cr);
+ int g=GetGValue(cr);
+ int b=GetBValue(cr);
+ if (IsWindowVisible(GetDlgItem(hDlg,0x2c6)))   /* if full size */
+ {
+   sprintf(buffer,"%d",r);
+   SetWindowText(GetDlgItem(hDlg,0x2c2),buffer);
+   sprintf(buffer,"%d",g);
+   SetWindowText(GetDlgItem(hDlg,0x2c3),buffer);
+   sprintf(buffer,"%d",b);
+   SetWindowText(GetDlgItem(hDlg,0x2c4),buffer);
+ }
+}
+
+/***********************************************************************
+ *                             CC_EditSetHSL                  [internal]
+ */
+static void CC_EditSetHSL(HWND hDlg,int h,int s,int l)
+{
+ char buffer[10];
+ if (IsWindowVisible(GetDlgItem(hDlg,0x2c6)))   /* if full size */
+ {
+   sprintf(buffer,"%d",h);
+   SetWindowText(GetDlgItem(hDlg,0x2bf),buffer);
+   sprintf(buffer,"%d",s);
+   SetWindowText(GetDlgItem(hDlg,0x2c0),buffer);
+   sprintf(buffer,"%d",l);
+   SetWindowText(GetDlgItem(hDlg,0x2c1),buffer);
+ }
+ CC_PaintLumBar(hDlg,h,s);
+}
+
+/***********************************************************************
+ *                       CC_SwitchToFullSize                  [internal]
+ */
+static void CC_SwitchToFullSize(HWND hDlg,COLORREF result,LPRECT lprect)
+{
+ int i;
+ struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); 
+ 
+ EnableWindow(GetDlgItem(hDlg,0x2cf),FALSE);
+ CC_PrepareColorGraph(hDlg);
+ for (i=0x2bf;i<0x2c5;i++)
+   EnableWindow(GetDlgItem(hDlg,i),TRUE);
+ for (i=0x2d3;i<0x2d9;i++)
+   EnableWindow(GetDlgItem(hDlg,i),TRUE);
+ EnableWindow(GetDlgItem(hDlg,0x2c9),TRUE);
+ EnableWindow(GetDlgItem(hDlg,0x2c8),TRUE);
+
+ if (lprect)
+  SetWindowPos(hDlg,NULL,0,0,lprect->right-lprect->left,
+   lprect->bottom-lprect->top, SWP_NOMOVE|SWP_NOZORDER);
+
+ ShowWindow(GetDlgItem(hDlg,0x2c6),SW_SHOW);
+ ShowWindow(GetDlgItem(hDlg,0x2be),SW_SHOW);
+ ShowWindow(GetDlgItem(hDlg,0x2c5),SW_SHOW);
+
+ CC_EditSetRGB(hDlg,result);
+ CC_EditSetHSL(hDlg,lpp->h,lpp->s,lpp->l);
+}
+
+/***********************************************************************
+ *                           CC_PaintPredefColorArray         [internal]
+ */
+static void CC_PaintPredefColorArray(HWND hDlg,int rows,int cols)
+{
+ HWND hwnd=GetDlgItem(hDlg,0x2d0);
+ RECT rect;
+ HDC  hdc;
+ HBRUSH hBrush;
+ int dx,dy,i,j,k;
+
+ GetClientRect(hwnd,&rect);
+ dx=rect.right/cols;
+ dy=rect.bottom/rows;
+ k=rect.left;
+
+ hdc=GetDC(hwnd);
+ GetClientRect (hwnd, &rect) ;
+
+ for (j=0;j<rows;j++)
+ {
+  for (i=0;i<cols;i++)
+  {
+   hBrush = CreateSolidBrush(predefcolors[j][i]);
+   if (hBrush)
+   {
+    hBrush = SelectObject (hdc, hBrush) ;
+    Rectangle (hdc, rect.left,     rect.top,
+		    rect.left+dx-DISTANCE,rect.top+dy-DISTANCE);
+    rect.left=rect.left+dx;
+    DeleteObject (SelectObject (hdc, hBrush)) ;
+   }
+  }
+  rect.top=rect.top+dy;
+  rect.left=k;
+ }
+ ReleaseDC(hwnd,hdc);
+ /* FIXME: draw_a_focus_rect */
+}
+/***********************************************************************
+ *                             CC_PaintUserColorArray         [internal]
+ */
+static void CC_PaintUserColorArray(HWND hDlg,int rows,int cols,COLORREF* lpcr)
+{
+ HWND hwnd=GetDlgItem(hDlg,0x2d1);
+ RECT rect;
+ HDC  hdc;
+ HBRUSH hBrush;
+ int dx,dy,i,j,k;
+
+ GetClientRect(hwnd,&rect);
+
+ dx=rect.right/cols;
+ dy=rect.bottom/rows;
+ k=rect.left;
+
+ hdc=GetDC(hwnd);
+ if (hdc)
+ {
+  for (j=0;j<rows;j++)
+  {
+   for (i=0;i<cols;i++)
+   {
+    hBrush = CreateSolidBrush(lpcr[i+j*cols]);
+    if (hBrush)
+    {
+     hBrush = SelectObject (hdc, hBrush) ;
+     Rectangle (hdc, rect.left,     rect.top,
+		    rect.left+dx-DISTANCE,rect.top+dy-DISTANCE);
+     rect.left=rect.left+dx;
+     DeleteObject (SelectObject (hdc, hBrush)) ;
+    }
+   }
+   rect.top=rect.top+dy;
+   rect.left=k;
+  }
+  ReleaseDC(hwnd,hdc);
+ }
+ /* FIXME: draw_a_focus_rect */
+}
+
+
+
+/***********************************************************************
+ *                             CC_HookCallChk                 [internal]
+ */
+static BOOL CC_HookCallChk(LPCHOOSECOLOR lpcc)
+{
+ if (lpcc)
+  if(lpcc->Flags & CC_ENABLEHOOK)
+   if (lpcc->lpfnHook)
+    return TRUE;
+ return FALSE;
+}
+
+/***********************************************************************
+ *                            CC_WMInitDialog                 [internal]
+ */
+static LONG CC_WMInitDialog(HWND hDlg, WPARAM wParam, LPARAM lParam) 
+{
+   int i,res;
+   HWND hwnd;
+   RECT rect;
+   POINT point;
+   struct CCPRIVATE * lpp; 
+   
+   dprintf_commdlg(stddeb,"ColorDlgProc // WM_INITDIALOG lParam=%08lX\n", lParam);
+   lpp=calloc(1,sizeof(struct CCPRIVATE));
+   lpp->lpcc=(LPCHOOSECOLOR)lParam;
+   if (lpp->lpcc->lStructSize != sizeof(CHOOSECOLOR))
+   {
+      EndDialog (hDlg, 0) ;
+      return FALSE;
+   }
+   SetWindowLong(hDlg, DWL_USER, (LONG)lpp); 
+
+   if (!(lpp->lpcc->Flags & CC_SHOWHELP))
+      ShowWindow(GetDlgItem(hDlg,0x40e),SW_HIDE);
+   lpp->msetrgb=RegisterWindowMessage(MAKE_SEGPTR(SETRGBSTRING));
+#if 0
+   cpos=MAKELONG(5,7); /* init */
+   if (lpp->lpcc->Flags & CC_RGBINIT)
+   {
+     for (i=0;i<6;i++)
+       for (j=0;j<8;j++)
+        if (predefcolors[i][j]==lpp->lpcc->rgbResult)
+        {
+          cpos=MAKELONG(i,j);
+          goto found;
+        }
+   }
+   found:
+   /* FIXME: Draw_a_focus_rect & set_init_values */
+#endif
+   GetWindowRect(hDlg,&lpp->fullsize);
+   if (lpp->lpcc->Flags & CC_FULLOPEN || lpp->lpcc->Flags & CC_PREVENTFULLOPEN)
+   {
+      hwnd=GetDlgItem(hDlg,0x2cf);
+      EnableWindow(hwnd,FALSE);
+   }
+   if (!(lpp->lpcc->Flags & CC_FULLOPEN) || lpp->lpcc->Flags & CC_PREVENTFULLOPEN)
+   {
+      rect=lpp->fullsize;
+      res=rect.bottom-rect.top;
+      hwnd=GetDlgItem(hDlg,0x2c6); /* cut at left border */
+      point.x=point.y=0;
+      ClientToScreen(hwnd,&point);
+      ScreenToClient(hDlg,&point);
+      GetClientRect(hDlg,&rect);
+      point.x+=GetSystemMetrics(SM_CXDLGFRAME);
+      SetWindowPos(hDlg,NULL,0,0,point.x,res,SWP_NOMOVE|SWP_NOZORDER);
+
+      ShowWindow(GetDlgItem(hDlg,0x2c6),SW_HIDE);
+      ShowWindow(GetDlgItem(hDlg,0x2c5),SW_HIDE);
+   }
+   else
+      CC_SwitchToFullSize(hDlg,lpp->lpcc->rgbResult,NULL);
+   res=TRUE;
+   for (i=0x2bf;i<0x2c5;i++)
+     SendMessage(GetDlgItem(hDlg,i),EM_LIMITTEXT,3,0);      /* max 3 digits:  xyz  */
+   if (CC_HookCallChk(lpp->lpcc))
+      res=CallWindowProc((FARPROC)lpp->lpcc->lpfnHook,hDlg,WM_INITDIALOG,wParam,lParam);
+   return res;
+}
+
+/***********************************************************************
+ *                              CC_WMCommand                  [internal]
+ */
+static LRESULT CC_WMCommand(HWND hDlg, WPARAM wParam, LPARAM lParam) 
+{
+    int r,g,b,i,xx;
+    UINT cokmsg;
+    HDC hdc;
+    COLORREF *cr;
+    struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); 
+    switch (wParam)
+    {
+          case 0x2c2:  /* edit notify RGB */
+	  case 0x2c3:
+	  case 0x2c4:
+	       if (HIWORD(lParam)==EN_UPDATE)
+			 {
+			   i=CC_CheckDigitsInEdit(LOWORD(lParam),255);
+			   r=GetRValue(lpp->lpcc->rgbResult);
+			   g=GetGValue(lpp->lpcc->rgbResult);
+			   b=GetBValue(lpp->lpcc->rgbResult);
+			   xx=0;
+			   switch (wParam)
+			   {
+			    case 0x2c2:if ((xx=(i!=r))) r=i;break;
+			    case 0x2c3:if ((xx=(i!=g))) g=i;break;
+			    case 0x2c4:if ((xx=(i!=b))) b=i;break;
+			   }
+			   if (xx) /* something has changed */
+			   {
+			    lpp->lpcc->rgbResult=RGB(r,g,b);
+			    CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult);
+			    lpp->h=CC_RGBtoHSL('H',r,g,b);
+			    lpp->s=CC_RGBtoHSL('S',r,g,b);
+			    lpp->l=CC_RGBtoHSL('L',r,g,b);
+			    CC_EditSetHSL(hDlg,lpp->h,lpp->s,lpp->l);
+			    CC_PaintCross(hDlg,lpp->h,lpp->s);
+			    CC_PaintTriangle(hDlg,lpp->l);
+			   }
+			 }
+		 break;
+		 
+	  case 0x2bf:  /* edit notify HSL */
+	  case 0x2c0:
+	  case 0x2c1:
+	       if (HIWORD(lParam)==EN_UPDATE)
+			 {
+			   i=CC_CheckDigitsInEdit(LOWORD(lParam),wParam==0x2bf?239:240);
+			   xx=0;
+			   switch (wParam)
+			   {
+			    case 0x2bf:if ((xx=(i!=lpp->h))) lpp->h=i;break;
+			    case 0x2c0:if ((xx=(i!=lpp->s))) lpp->s=i;break;
+			    case 0x2c1:if ((xx=(i!=lpp->l))) lpp->l=i;break;
+			   }
+			   if (xx) /* something has changed */
+			   {
+			    r=CC_HSLtoRGB('R',lpp->h,lpp->s,lpp->l);
+			    g=CC_HSLtoRGB('G',lpp->h,lpp->s,lpp->l);
+			    b=CC_HSLtoRGB('B',lpp->h,lpp->s,lpp->l);
+			    lpp->lpcc->rgbResult=RGB(r,g,b);
+			    CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult);
+			    CC_EditSetRGB(hDlg,lpp->lpcc->rgbResult);
+			    CC_PaintCross(hDlg,lpp->h,lpp->s);
+			    CC_PaintTriangle(hDlg,lpp->l);
+			   }
+			 }
+	       break;
+	       
+          case 0x2cf:
+               CC_SwitchToFullSize(hDlg,lpp->lpcc->rgbResult,&lpp->fullsize);
+	       InvalidateRect(hDlg,NULL,NULL);
+	       SetFocus(GetDlgItem(hDlg,0x2bf));
+	       break;
+
+          case 0x2c8:    /* add colors ... column by column */
+               cr=PTR_SEG_TO_LIN(lpp->lpcc->lpCustColors);
+               cr[(lpp->nextuserdef%2)*8 + lpp->nextuserdef/2]=lpp->lpcc->rgbResult;
+               if (++lpp->nextuserdef==16)
+		   lpp->nextuserdef=0;
+	       CC_PaintUserColorArray(hDlg,2,8,PTR_SEG_TO_LIN(lpp->lpcc->lpCustColors));
+	       break;
+
+          case 0x2c9:              /* resulting color */
+	       hdc=GetDC(hDlg);
+	       lpp->lpcc->rgbResult=GetNearestColor(hdc,lpp->lpcc->rgbResult);
+	       ReleaseDC(hDlg,hdc);
+	       CC_EditSetRGB(hDlg,lpp->lpcc->rgbResult);
+	       CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult);
+	       r=GetRValue(lpp->lpcc->rgbResult);
+	       g=GetGValue(lpp->lpcc->rgbResult);
+	       b=GetBValue(lpp->lpcc->rgbResult);
+	       lpp->h=CC_RGBtoHSL('H',r,g,b);
+	       lpp->s=CC_RGBtoHSL('S',r,g,b);
+	       lpp->l=CC_RGBtoHSL('L',r,g,b);
+	       CC_EditSetHSL(hDlg,lpp->h,lpp->s,lpp->l);
+	       CC_PaintCross(hDlg,lpp->h,lpp->s);
+	       CC_PaintTriangle(hDlg,lpp->l);
+	       break;
+
+	  case 0x40e:           /* Help! */ /* The Beatles, 1965  ;-) */
+	       i=RegisterWindowMessage(MAKE_SEGPTR(HELPMSGSTRING));
+	       if (lpp->lpcc->hwndOwner)
+		   SendMessage(lpp->lpcc->hwndOwner,i,0,(LPARAM)lpp->lpcc);
+	       if (CC_HookCallChk(lpp->lpcc))
+		   CallWindowProc((FARPROC)lpp->lpcc->lpfnHook,hDlg,
+		      WM_COMMAND,psh15,(LPARAM)lpp->lpcc);
+	       break;
+
+          case IDOK :
+		cokmsg=RegisterWindowMessage(MAKE_SEGPTR(COLOROKSTRING));
+		if (lpp->lpcc->hwndOwner)
+			if (SendMessage(lpp->lpcc->hwndOwner,cokmsg,0,(LPARAM)lpp->lpcc))
+			   break;    /* do NOT close */
+
+		EndDialog (hDlg, 1) ;
+		return TRUE ;
+	
+	  case IDCANCEL :
+		EndDialog (hDlg, 0) ;
+		return TRUE ;
+
+       }
+       return FALSE;
+}
+
+/***********************************************************************
+ *                              CC_WMPaint                    [internal]
+ */
+static LRESULT CC_WMPaint(HWND hDlg, WPARAM wParam, LPARAM lParam) 
+{
+    struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); 
+    /* we have to paint dialog children except text and buttons */
+ 
+    CC_PaintPredefColorArray(hDlg,6,8);
+    CC_PaintUserColorArray(hDlg,2,8,PTR_SEG_TO_LIN(lpp->lpcc->lpCustColors));
+    CC_PaintColorGraph(hDlg);
+    CC_PaintLumBar(hDlg,lpp->h,lpp->s);
+    CC_PaintCross(hDlg,lpp->h,lpp->s);
+    CC_PaintTriangle(hDlg,lpp->l);
+    CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult);
+
+    /* special necessary for Wine */
+    ValidateRect(GetDlgItem(hDlg,0x2d0),NULL);
+    ValidateRect(GetDlgItem(hDlg,0x2d1),NULL);
+    ValidateRect(GetDlgItem(hDlg,0x2c6),NULL);
+    ValidateRect(GetDlgItem(hDlg,0x2be),NULL);
+    ValidateRect(GetDlgItem(hDlg,0x2c5),NULL);
+    /* hope we can remove it later -->FIXME */
+ return 0;
+}
+
+
+/***********************************************************************
+ *                              CC_WMLButtonDown              [internal]
+ */
+static LRESULT CC_WMLButtonDown(HWND hDlg, WPARAM wParam, LPARAM lParam) 
+{
+   struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); 
+   int r,g,b,i;
+   i=0;
+   if (CC_MouseCheckPredefColorArray(hDlg,0x2d0,6,8,lParam,&lpp->lpcc->rgbResult))
+      i=1;
+   else
+      if (CC_MouseCheckUserColorArray(hDlg,0x2d1,2,8,lParam,&lpp->lpcc->rgbResult,
+	      PTR_SEG_TO_LIN(lpp->lpcc->lpCustColors)))
+         i=1;
+      else
+	 if (CC_MouseCheckColorGraph(hDlg,0x2c6,&lpp->h,&lpp->s,lParam))
+	    i=2;
+	 else
+	    if (CC_MouseCheckColorGraph(hDlg,0x2be,NULL,&lpp->l,lParam))
+	       i=2;
+   if (i==2)
+   {
+      r=CC_HSLtoRGB('R',lpp->h,lpp->s,lpp->l);
+      g=CC_HSLtoRGB('G',lpp->h,lpp->s,lpp->l);
+      b=CC_HSLtoRGB('B',lpp->h,lpp->s,lpp->l);
+      lpp->lpcc->rgbResult=RGB(r,g,b);
+   }
+   if (i==1)
+   {
+      r=GetRValue(lpp->lpcc->rgbResult);
+      g=GetGValue(lpp->lpcc->rgbResult);
+      b=GetBValue(lpp->lpcc->rgbResult);
+      lpp->h=CC_RGBtoHSL('H',r,g,b);
+      lpp->s=CC_RGBtoHSL('S',r,g,b);
+      lpp->l=CC_RGBtoHSL('L',r,g,b);
+   }
+   if (i)
+   {
+      CC_EditSetRGB(hDlg,lpp->lpcc->rgbResult);
+      CC_EditSetHSL(hDlg,lpp->h,lpp->s,lpp->l);
+      CC_PaintCross(hDlg,lpp->h,lpp->s);
+      CC_PaintTriangle(hDlg,lpp->l);
+      CC_PaintSelectedColor(hDlg,lpp->lpcc->rgbResult);
+      return TRUE;
+   }
+   return FALSE;
+}
+
+/***********************************************************************
+ *           ColorDlgProc   (COMMDLG.8)
+ */
+LRESULT ColorDlgProc(HWND hDlg, UINT message,
+			 UINT wParam, LONG lParam)
+{
+ int res;
+ struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); 
+ if (message!=WM_INITDIALOG)
+ {
+  if (!lpp)
+     return FALSE;
+  res=0;
+  if (CC_HookCallChk(lpp->lpcc))
+     res=CallWindowProc((FARPROC)lpp->lpcc->lpfnHook,hDlg,message,wParam,lParam);
+  if (res)
+     return res;
+ }
+
+ /* FIXME: SetRGB message
+ if (message && message==msetrgb)
+    return HandleSetRGB(hDlg,lParam);
+ */
+
+ switch (message)
+	{
+	  case WM_INITDIALOG:
+	                return CC_WMInitDialog(hDlg,wParam,lParam);
+	  case WM_NCDESTROY:
+	                /* FIXME: what about lpp->hdcMem ? */
+	                free(lpp);
+	                SetWindowLong(hDlg, DWL_USER, 0L); /* we don't need it anymore */
+	                break;
+	  case WM_COMMAND:
+	                if (CC_WMCommand(hDlg, wParam, lParam))
+	                   return TRUE;
+	                break;     
+	  case WM_PAINT:
+	                CC_WMPaint(hDlg, wParam, lParam);
+	                break;
+	  case WM_LBUTTONDBLCLK:
+	                if (CC_MouseCheckResultWindow(hDlg,lParam))
+			  return TRUE;
+			break;
+	  case WM_MOUSEMOVE:  /* FIXME: calculate new hue,sat,lum (if in color graph) */
+			break;
+	  case WM_LBUTTONUP:  /* FIXME: ClipCursor off (if in color graph)*/
+			break;
+	  case WM_LBUTTONDOWN:/* FIXME: ClipCursor on  (if in color graph)*/
+	                if (CC_WMLButtonDown(hDlg, wParam, lParam))
+	                   return TRUE;
+	                break;     
+	}
+     return FALSE ;
+}
+
diff --git a/misc/winsocket.c b/misc/winsocket.c
index 91652e8..f52c588 100644
--- a/misc/winsocket.c
+++ b/misc/winsocket.c
@@ -11,7 +11,7 @@
 #include <sys/types.h>
 #include <sys/ipc.h>
 #include <sys/ioctl.h>
-#if defined__svr4__
+#if defined(__svr4__)
 #include <sys/filio.h>
 #include <sys/ioccom.h>
 #endif
diff --git a/multimedia/mmsystem.c b/multimedia/mmsystem.c
index 152ee9a..f678ee4 100644
--- a/multimedia/mmsystem.c
+++ b/multimedia/mmsystem.c
@@ -1900,7 +1900,7 @@
 	dprintf_mmio(stddeb, "mmioRead(%04X, %p, %ld);\n", hmmio, pch, cch);
 	lpmminfo = (LPMMIOINFO)GlobalLock(hmmio);
 	if (lpmminfo == NULL) return 0;
-	count = read(LOWORD(lpmminfo->dwReserved2), pch, cch);
+	count = FILE_Read(LOWORD(lpmminfo->dwReserved2), pch, cch);
 	GlobalUnlock(hmmio);
 	dprintf_mmio(stddeb, "mmioRead // count=%ld\n", count);
 	return count;
@@ -2002,7 +2002,7 @@
 	lpmminfo = (LPMMIOINFO)GlobalLock(hmmio);
 	if (lpmminfo == NULL) return 0;
 	if (uFlags == MMIO_READ) {
-		count = read(LOWORD(lpmminfo->dwReserved2), 
+		count = FILE_Read(LOWORD(lpmminfo->dwReserved2), 
 			lpmmioinfo->pchBuffer, lpmmioinfo->cchBuffer);
 		}
 	if (uFlags == MMIO_WRITE) {
@@ -2070,7 +2070,7 @@
 		(uFlags & MMIO_FINDLIST)) {
 		dprintf_mmio(stddeb, "mmioDescend // MMIO_FINDxxxx dwfcc=%08lX !\n", dwfcc);
 		while (TRUE) {
-			if (read(LOWORD(lpmminfo->dwReserved2), (LPSTR)lpck, 
+			if (FILE_Read(LOWORD(lpmminfo->dwReserved2), (LPSTR)lpck, 
 					sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
 				_llseek(LOWORD(lpmminfo->dwReserved2), dwOldPos, SEEK_SET);
 				GlobalUnlock(hmmio);
@@ -2086,7 +2086,7 @@
 			}
 		}
 	else {
-		if (read(LOWORD(lpmminfo->dwReserved2), (LPSTR)lpck, 
+		if (FILE_Read(LOWORD(lpmminfo->dwReserved2), (LPSTR)lpck, 
 				sizeof(MMCKINFO)) < sizeof(MMCKINFO)) {
 			_llseek(LOWORD(lpmminfo->dwReserved2), dwOldPos, SEEK_SET);
 			GlobalUnlock(hmmio);
diff --git a/objects/font.c b/objects/font.c
index 41c8d38..f9cfc8b 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -152,7 +152,9 @@
         height = 10 * (-height * 9 / 8);
 	 * may be we have to use an non linear function
 	*/
-        height *= -10;
+	/* assume internal leading is 2 pixels. Else small fonts will become
+         * very small. */
+        height = (height-2) * -10; 
     }
     else height *= 10;
     width  = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
diff --git a/objects/metafile.c b/objects/metafile.c
index f66465c..b68373a 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -648,7 +648,7 @@
 	GlobalUnlock(mf->hMetaHdr);
 	mf->hMetaHdr = GlobalReAlloc(mf->hMetaHdr, len, GMEM_MOVEABLE);
 	mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
-	memcpy(mh + mh->mtSize * 2, mr, rlen);
+	memcpy((WORD *)mh + mh->mtSize, mr, rlen);
     }
     else if (mh->mtType == 1)     /* disk based metafile */
     {
diff --git a/programs/progman/main.c b/programs/progman/main.c
index e9906ff..561fc27 100644
--- a/programs/progman/main.c
+++ b/programs/progman/main.c
@@ -62,8 +62,8 @@
   }
 #endif
 
-  /* Select Language */
-#ifdef WINELIB
+  /* Select Language (FIXME) */
+#ifndef WINELIB
   Globals.lpszLanguage = langNames[Options.language];
 #else
   Globals.lpszLanguage = "En";
diff --git a/programs/progman/string.c b/programs/progman/string.c
index f33941b..cb6e160 100644
--- a/programs/progman/string.c
+++ b/programs/progman/string.c
@@ -120,8 +120,8 @@
   if (Globals.hMainMenu) DestroyMenu(Globals.hMainMenu);
   Globals.hMainMenu = hMainMenu;
 
-#ifdef WINELIB
-  /* Update system menus */
+#ifndef WINELIB
+  /* Update system menus (FIXME) */
   for (i = 0; langNames[i] && lstrcmp(lang, langNames[i]);) i++;
   if (langNames[i]) Options.language = i;
 
diff --git a/rc/parser.h b/rc/parser.h
index 38e5028..c0d2d27 100644
--- a/rc/parser.h
+++ b/rc/parser.h
@@ -105,7 +105,3 @@
 
 extern int verbose;
 
-#ifdef __sun__
-#define strtoul strtol
-#endif
-
diff --git a/resources/TODO b/resources/TODO
index e391bd3..31be6f5 100644
--- a/resources/TODO
+++ b/resources/TODO
@@ -27,3 +27,27 @@
 
 Frans van Dorsselaer
 dorssel@rulhm1.LeidenUniv.nl
+***************************************************************
+1996, April, 7th
+
+Subject: ChooseColor
+         ===========
+
+Today I introduced ChooseColor() to commdlg.c.
+Because this old resource was insufficient I wrote a new one
+(including some new static contols).
+
+Please delete the old CHOOSECOLOR in YOUR sysres_??.rc   
+and insert the new CHOOSECOLOR from sysres_En.rc to YOUR 
+language file and translate this as you like it - 
+otherwise you'll get an undefined behavour. 
+
+Today it works well for:
+* English 
+* German
+...to be continued......
+
+Thank you.
+
+Albrecht Kleine
+kleine@ak.sax.de
diff --git a/resources/sysres_De.rc b/resources/sysres_De.rc
index abb8f60..b20f6b8 100644
--- a/resources/sysres_De.rc
+++ b/resources/sysres_De.rc
@@ -144,24 +144,37 @@
 }
 
 
-CHOOSE_COLOR DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 264, 200
+CHOOSE_COLOR DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 300, 200
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Farbe"
 FONT 8, "Helv"
 {
- LTEXT "&Standardfarben:", 1088, 6, 6, 40, 9
- LTEXT "S&elbstdefinierte Farben:", 1089, 6, 126, 40, 9
- LTEXT "Farbe|Re&in", 1090, 100, 146, 40, 9
- LTEXT "&Ton:", 1091, 150, 126, 40, 9
- LTEXT "&Sättigung:", 1092, 150, 146, 40, 9
- LTEXT "&Helligkeit:", 1093, 150, 166, 40, 9
- LTEXT "&Rot:", 1094, 150, 126, 40, 9
- LTEXT "&Grün:", 1095, 150, 146, 40, 9
- LTEXT "Bl&au:", 1096, 150, 166, 40, 9
- DEFPUSHBUTTON "Ok", 1, 6, 182, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
- PUSHBUTTON "Selbstdefinierte Farbe &hinzufügen", 1024, 120, 182, 100, 14, WS_GROUP | WS_TABSTOP
- PUSHBUTTON "Selbstdefinierte Farbe &entfernen", 1025, 6, 164, 56, 14, WS_GROUP | WS_TABSTOP
- PUSHBUTTON "Abbrechen", 2, 76, 182, 56, 14, WS_GROUP | WS_TABSTOP
+ LTEXT "Gr&undfarben:",   1088, 4,    4,  140, 10
+ LTEXT "Selbs&tdefinierte Farben:",  1089, 4,   106, 140, 10
+ LTEXT "Farbe |  B&asis",  1090, 150, 151,  48, 10
+ LTEXT   "&Rot:", 726 ,249,126,24,10
+ EDITTEXT 706, 275,124,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT   "&Grün:",727/*1095*/,249,140,24,10
+ EDITTEXT 707, 275,138,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT   "&Blau:",728 /*1096*/,249,154,24,10
+ EDITTEXT 708, 275,152,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT  "&Farbe:" ,723 /*1091*/,202,126,22,10
+ EDITTEXT 703, 226,124,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT  "&Sätt:" ,724 /*1092*/,202,140,22,10
+ EDITTEXT 704, 226,138,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT  "H&ell:" ,725 /*1093*/,202,154,22,10
+ EDITTEXT 705, 226,152,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ CONTROL "" ,720,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP,4,14,140,86
+ CONTROL "" ,721,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP,4,116,140,28
+ CONTROL "" ,710,"STATIC",WS_BORDER|SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,4,118,116
+ CONTROL "" ,702,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP, 278,4,8,116
+ CONTROL "" ,709,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,124,40,26
+ DEFPUSHBUTTON "Ok",  1,  4, 166, 44, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Abbrechen", 2, 52, 166, 44, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "&Hilfe", 1038,100,166, 44, 14
+ PUSHBUTTON "Farbe hin&zufügen",    712/*1024*/, 152, 166, 142, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Farben &definieren >>", 719/*1025*/,   4, 150, 142, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON  "&a",713,300,200,4,14   /* just a dummy:  'a' is  like  &a  in "B&asis"  */
 }
 
 
diff --git a/resources/sysres_En.rc b/resources/sysres_En.rc
index b918771..aba679a 100644
--- a/resources/sysres_En.rc
+++ b/resources/sysres_En.rc
@@ -144,24 +144,37 @@
 }
 
 
-CHOOSE_COLOR DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 264, 200
+CHOOSE_COLOR DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 300, 200
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Color"
 FONT 8, "Helv"
 {
- LTEXT "&Basic Colors:", 1088, 6, 6, 40, 9
- LTEXT "&Custom Colors:", 1089, 6, 126, 40, 9
- LTEXT "Color|Sol&id", 1090, 100, 146, 40, 9
- LTEXT "&Hue:", 1091, 150, 126, 40, 9
- LTEXT "&Sat:", 1092, 150, 146, 40, 9
- LTEXT "&Lum:", 1093, 150, 166, 40, 9
- LTEXT "&Red:", 1094, 150, 126, 40, 9
- LTEXT "&Green:", 1095, 150, 146, 40, 9
- LTEXT "Bl&ue:", 1096, 150, 166, 40, 9
- DEFPUSHBUTTON "Ok", 1, 6, 182, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
- PUSHBUTTON "&Add to Custom Colors", 1024, 120, 182, 100, 14, WS_GROUP | WS_TABSTOP
- PUSHBUTTON "&Delete Custom Colors", 1025, 6, 164, 56, 14, WS_GROUP | WS_TABSTOP
- PUSHBUTTON "Cancel", 2, 76, 182, 56, 14, WS_GROUP | WS_TABSTOP
+ LTEXT "&Basic Colors:",   1088, 4,    4,  140, 10
+ LTEXT "&Custom Colors:",  1089, 4,   106, 140, 10
+ LTEXT "Color |  Sol&id",  1090, 150, 151,  48, 10
+ LTEXT   "&Red:", 726 /*1094*/,249,126,24,10
+ EDITTEXT 706, 275,124,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT   "&Green:",727/*1095*/,249,140,24,10
+ EDITTEXT 707, 275,138,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT   "&Blue:",728 /*1096*/,249,154,24,10
+ EDITTEXT 708, 275,152,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT  "&Hue:" ,723 /*1091*/,202,126,22,10
+ EDITTEXT 703, 226,124,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT  "&Sat:" ,724 /*1092*/,202,140,22,10
+ EDITTEXT 704, 226,138,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT  "&Lum:" ,725 /*1093*/,202,154,22,10
+ EDITTEXT 705, 226,152,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ CONTROL "" ,720,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP,4,14,140,86
+ CONTROL "" ,721,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP,4,116,140,28
+ CONTROL "" ,710,"STATIC",WS_BORDER|SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,4,118,116
+ CONTROL "" ,702,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP, 278,4,8,116
+ CONTROL "" ,709,"STATIC",SS_SIMPLE|WS_TABSTOP|WS_GROUP, 152,124,40,26
+ DEFPUSHBUTTON "Ok",  1,  4, 166, 44, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Cancel", 2, 52, 166, 44, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Help", 1038,100,166, 44, 14
+ PUSHBUTTON "&Add to Custom Colors",    712/*1024*/, 152, 166, 142, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "&Define Custom Colors >>", 719/*1025*/,   4, 150, 142, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON  "&i",713,300,200,4,14   /* just a dummy:  'i' is  like  &i  in "sol&id"  */
 }
 
 
diff --git a/resources/sysres_It.rc b/resources/sysres_It.rc
index 15a0136..91ba456 100644
--- a/resources/sysres_It.rc
+++ b/resources/sysres_It.rc
@@ -30,7 +30,7 @@
 SHELL_ABOUT_MSGBOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 50, 44, 223, 200
 STYLE DS_LOCALEDIT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
 CAPTION "Informazioni su %s"
-FONT 10, "Sistema"
+FONT 10, "System"
 {
  DEFPUSHBUTTON "OK", 1, 91, 180, 40, 14
  CONTROL "", -1, "STATIC", SS_BLACKFRAME | WS_CHILD | WS_VISIBLE | WS_DISABLED, 4, 35, 215, 140
@@ -44,10 +44,10 @@
 CAPTION "Apri"
 FONT 8, "Helv"
 {
- LTEXT "File &Nome:", 1090, 6, 6, 76, 9
+ LTEXT "&Nome file:", 1090, 6, 6, 76, 9
  EDITTEXT 1152, 6, 16, 90, 12, ES_AUTOHSCROLL | ES_OEMCONVERT | WS_BORDER | WS_TABSTOP
  LISTBOX 1120, 6, 32, 90, 68, LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_TABSTOP
- LTEXT "&Directories:", -1, 110, 6, 92, 9
+ LTEXT "&Percorso:", -1, 110, 6, 92, 9
  LTEXT "", 1088, 110, 18, 92, 9, SS_NOPREFIX | WS_GROUP
  LISTBOX 1121, 110, 32, 92, 68, LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_TABSTOP
  LTEXT "Files di &Tipo:", 1089, 6, 104, 90, 9
@@ -57,7 +57,7 @@
  DEFPUSHBUTTON "Apri", 1, 208, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
  PUSHBUTTON "Annulla", 2, 208, 24, 56, 14, WS_GROUP | WS_TABSTOP
  PUSHBUTTON "&Aiuto", 1038, 208, 46, 56, 14, WS_GROUP | WS_TABSTOP
- CHECKBOX "Solo &Lettura", 1040, 208, 68, 50, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
+ CHECKBOX "Solo &Lettura", 1040, 208, 68, 52, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
 }
 
 
@@ -66,17 +66,17 @@
 CAPTION "Salva con nome ..."
 FONT 8, "Helv"
 {
- LTEXT "File &Nome:", 1090, 6, 6, 76, 9
+ LTEXT "&Nome file:", 1090, 6, 6, 76, 9
  EDITTEXT 1152, 6, 16, 90, 12, ES_AUTOHSCROLL | ES_OEMCONVERT | WS_BORDER | WS_TABSTOP
  LISTBOX 1120, 6, 32, 90, 68, LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_TABSTOP
- LTEXT "&Directories:", -1, 110, 6, 92, 9
+ LTEXT "&Percorso:", -1, 110, 6, 92, 9
  LTEXT "", 1088, 110, 18, 92, 9, SS_NOPREFIX | WS_GROUP
  LISTBOX 1121, 110, 32, 92, 68, LBS_STANDARD | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_DISABLENOSCROLL | WS_TABSTOP
  LTEXT "Files di &Tipo:", 1089, 6, 104, 90, 9
  COMBOBOX 1136, 6, 114, 90, 36, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_BORDER | WS_VSCROLL | WS_TABSTOP
  LTEXT "&Unita':", 1091, 110, 104, 92, 9
  COMBOBOX 1137, 110, 114, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
- DEFPUSHBUTTON "Save As", 1, 208, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
+ DEFPUSHBUTTON "Salva come", 1, 208, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
  PUSHBUTTON "Cancel", 2, 208, 24, 56, 14, WS_GROUP | WS_TABSTOP
  PUSHBUTTON "&Help", 1038, 208, 46, 56, 14, WS_GROUP | WS_TABSTOP
  CHECKBOX "&Read Only", 1040, 208, 68, 50, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
@@ -106,29 +106,29 @@
 }
 
 
-PRINT_SETUP DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 264, 134
+PRINT_SETUP DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 274, 154
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Configurazione Stampante"
 FONT 8, "Helv"
 {
- GROUPBOX "Stampante", 1072, 6, 10, 180, 65, BS_GROUPBOX
- RADIOBUTTON "Stampante &Preferita", 1056, 16, 20, 80, 12
+ GROUPBOX "Stampante", 1072, 6, 10, 180, 72, BS_GROUPBOX
+ RADIOBUTTON "Stampante &Preferita", 1056, 16, 20, 78, 12
  LTEXT "[none]", 1088, 35, 35, 120, 9
- RADIOBUTTON "Stampante &Specifica", 1057, 16, 50, 80, 12
+ RADIOBUTTON "Stampante &Specifica", 1057, 16, 50, 78, 12
  COMBOBOX 1136, 35, 65, 149, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
  DEFPUSHBUTTON "Ok", 1, 206, 6, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
  PUSHBUTTON "Annulla", 2, 206, 24, 56, 14, WS_GROUP | WS_TABSTOP
  PUSHBUTTON "&Installa", 1024, 206, 46, 56, 14, WS_GROUP | WS_TABSTOP
  GROUPBOX "Orientamento", 1073, 6, 85, 100, 50, BS_GROUPBOX
- RADIOBUTTON "&Verticale", 1058, 50, 100, 40, 12
- RADIOBUTTON "&Orizzontale", 1059, 50, 115, 40, 12
+ RADIOBUTTON "&Verticale", 1058, 50, 100, 42, 12
+ RADIOBUTTON "&Orizzontale", 1059, 50, 115, 50, 12
  ICON "LANDSCAP", 1097, 10, 95, 32, 32
  ICON "PORTRAIT", 1098, 10, 95, 32, 32
- GROUPBOX "Carta", 1074, 120, 85, 180, 50, BS_GROUPBOX
- LTEXT "&Dimensione", 1089, 130, 95, 30, 9
- LTEXT "&Sorgente", 1090, 130, 110, 30, 9
- COMBOBOX 1137, 155, 95, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
- COMBOBOX 1138, 155, 110, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "Carta", 1074, 120, 85, 150, 50, BS_GROUPBOX
+ LTEXT "&Dimensione", 1089, 130, 100, 30, 9
+ LTEXT "&Sorgente", 1090, 130, 115, 30, 9
+ COMBOBOX 1137, 168, 95, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
+ COMBOBOX 1138, 168, 110, 92, 68, CBS_DROPDOWNLIST | CBS_OWNERDRAWFIXED | CBS_AUTOHSCROLL | CBS_SORT | CBS_HASSTRINGS | WS_BORDER | WS_VSCROLL | WS_TABSTOP
 }
 
 
@@ -159,7 +159,7 @@
  LTEXT "&Verde:", 1095, 150, 146, 40, 9
  LTEXT "Bl&u:", 1096, 150, 166, 40, 9
  DEFPUSHBUTTON "Ok", 1, 6, 182, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
- PUSHBUTTON "&Aggiugni ai Colori Utente", 1024, 120, 182, 100, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "&Aggiungi ai Colori Utente", 1024, 120, 182, 100, 14, WS_GROUP | WS_TABSTOP
  PUSHBUTTON "&Cancella Colori Utente", 1025, 6, 164, 56, 14, WS_GROUP | WS_TABSTOP
  PUSHBUTTON "Annulla", 2, 76, 182, 56, 14, WS_GROUP | WS_TABSTOP
 }
@@ -170,14 +170,14 @@
 CAPTION "Trova"
 FONT 8, "Helv"
 {
- LTEXT "Tro&va cosa:", -1, 4, 8, 42, 8
+ LTEXT "Tro&va:", -1, 4, 8, 42, 8
  EDITTEXT 1152, 47, 7, 128, 12, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP
  CHECKBOX "&Parola Intera", 1040, 4, 26, 100, 12, BS_AUTOCHECKBOX | WS_GROUP | WS_TABSTOP
- CHECKBOX "&Maiuscole/Minuscole", 1041, 4, 42, 64, 12, BS_AUTOCHECKBOX | WS_TABSTOP
+ CHECKBOX "&Maiuscole/Minuscole", 1041, 4, 42, 74, 12, BS_AUTOCHECKBOX | WS_TABSTOP
  GROUPBOX "Direzione", 1072, 107, 26, 68, 28
- CONTROL "&Su", 1056, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 111, 38, 20, 12
- CONTROL "&Giu'", 1057, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 138, 38, 30, 12
- DEFPUSHBUTTON "&Trova Prossimo", 1, 182, 5, 50, 14, WS_GROUP | WS_TABSTOP
+ CONTROL "&Su", 1056, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 111, 38, 24, 12
+ CONTROL "&Giu'", 1057, "BUTTON", BS_AUTORADIOBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 142, 38, 28, 12
+ DEFPUSHBUTTON "&Trova Prossimo", 1, 180, 5, 54, 14, WS_GROUP | WS_TABSTOP
  PUSHBUTTON "Annulla", 2, 182, 23, 50, 14, WS_GROUP | WS_TABSTOP
  PUSHBUTTON "&Aiuto", 1038, 182, 45, 50, 14, WS_GROUP | WS_TABSTOP
 }
@@ -188,7 +188,7 @@
 CAPTION "Cambia"
 FONT 8, "Helv"
 {
- LTEXT "Tro&va cosa:", -1, 4, 9, 48, 8
+ LTEXT "Tro&va:", -1, 4, 9, 48, 8
  EDITTEXT 1152, 54, 7, 114, 12, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP
  LTEXT "Ca&mbia con:", -1, 4, 26, 48, 8
  EDITTEXT 1153, 54, 24, 114, 12, ES_AUTOHSCROLL | WS_BORDER | WS_GROUP | WS_TABSTOP
diff --git a/tools/build.c b/tools/build.c
index 9e994f0..dfa2d40 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -635,6 +635,9 @@
     pModule->nrname_handle = 0;
     pModule->min_swap_area = 0;
     pModule->expected_version = 0x030a;
+    pModule->pe_module = NULL;
+    pModule->self = 0;
+    pModule->self_loading_sel = 0;
 
       /* File information */
 
@@ -772,14 +775,12 @@
 {
     char *buffer;
     NE_MODULE *pModule;
-    NE_WIN32_EXTRAINFO *pExtraInfo;
     OFSTRUCT *pFileInfo;
     BYTE *pstr;
     WORD *pword;
 
     /*   Module layout:
      * NE_MODULE            Module
-     * NE_WIN32_EXTRAINFO   Win32 module extra info
      * OFSTRUCT             File information
      * SEGTABLEENTRY        Segment table (empty)
      * WORD[2]              Resource table (empty)
@@ -817,15 +818,13 @@
     pModule->nrname_handle = 0;
     pModule->min_swap_area = 0;
     pModule->expected_version = 0x030a;
-
-    /* Win32 extra info */
-
-    pExtraInfo = (NE_WIN32_EXTRAINFO *)(pModule + 1);
-    pExtraInfo->pe_module = 0;
+    pModule->pe_module = NULL;
+    pModule->self = 0;
+    pModule->self_loading_sel = 0;
 
       /* File information */
 
-    pFileInfo = (OFSTRUCT *)(pExtraInfo + 1);
+    pFileInfo = (OFSTRUCT *)(pModule + 1);
     pModule->fileinfo = (int)pFileInfo - (int)pModule;
     memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) );
     pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName)
diff --git a/win32/Makefile.in b/win32/Makefile.in
index 2ff2ccf..b563e7e 100644
--- a/win32/Makefile.in
+++ b/win32/Makefile.in
@@ -11,7 +11,6 @@
 	except.c \
 	file.c \
 	gdi32.c \
-	heap.c \
 	init.c \
 	memory.c \
 	newfns.c \
diff --git a/win32/heap.c b/win32/heap.c
deleted file mode 100644
index 33e9dbb..0000000
--- a/win32/heap.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Win32 kernel functions
- *
- * Copyright 1995 Thomas Sandford <t.d.g.sandford@prds-grn.demon.co.uk>
- * Copyright 1995 Martin von Löwis
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/time.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include "windows.h"
-#include "winerror.h"
-#include "kernel32.h"
-#include "handle32.h"
-#include "winbase.h"
-#include "stddebug.h"
-#include "debug.h"
-
-#define HEAP_ZERO_MEMORY	0x8
-
-/* FIXME: these functions do *not* implement the win32 API properly. They
-are here merely as "get you going" aids */
-/***********************************************************************
- *           HeapAlloc			(KERNEL32.222)
- *
- */
-LPVOID SIMPLE_HeapAlloc(HANDLE hHeap, DWORD dwFlags, DWORD dwBytes)
-
-{
-	void *result;
-
-	result = malloc(dwBytes);
-	if(result && (dwFlags & HEAP_ZERO_MEMORY))
-		memset(result, 0, dwBytes);
-	return result;
-}
-
-HANDLE32 HeapCreate(DWORD flOptions, DWORD dwInitialSize, DWORD dwMaximumSize)
-{
-	LPVOID start;
-	HEAP_OBJECT *ret;
-	HEAPITEM_OBJECT *item;
-	if(dwInitialSize<4096)
-		return 0;
-	start = VirtualAlloc(0,dwMaximumSize, MEM_RESERVE, PAGE_READWRITE);
-	if(!start)
-		return 0;
-	if(!VirtualAlloc(start,dwInitialSize, MEM_COMMIT, PAGE_READWRITE))
-	{
-		VirtualFree(start,dwMaximumSize,MEM_RELEASE);
-		return 0;
-	}
-	ret=CreateKernelObject(sizeof(HEAP_OBJECT));
-	ret->common.magic=KERNEL_OBJECT_HEAP;
-	ret->start=start;
-	ret->size=dwInitialSize;
-	ret->maximum=dwMaximumSize;
-	ret->flags=flOptions;
-	item=start;
-	item->common.magic=KERNEL_OBJECT_HEAPITEM;
-	item->next=item->prev=0;
-	item->heap=ret;
-
-	ret->first=ret->last=item;
-
-	return (HANDLE32)ret;
-}
-
-BOOL HeapDestroy(HEAP_OBJECT *h)
-{
-	/* FIXME: last error */
-	if(h->common.magic!=KERNEL_OBJECT_HEAP)
-		return 0;
-	h->common.magic=0;
-	VirtualFree(h->start,h->size,MEM_RELEASE);
-	ReleaseKernelObject(h);
-	return 1;
-}
-
-
-static BOOL HEAP_GrowHeap(HEAP_OBJECT *h,DWORD size)
-{
-	HEAPITEM_OBJECT *last;
-	/* FIXME: last error */
-	if(size > h->maximum-h->size)
-		return 0;
-	if(!VirtualAlloc(h->start+h->size,size,MEM_COMMIT,PAGE_READWRITE))
-		return 0;
-	/* FIXME: consolidate with previous item */
-	last=h->start+size;
-	h->size+=size;
-	h->last->next=last;
-	last->prev=h->last;
-	last->next=0;
-	h->last=last;
-	last->common.magic=KERNEL_OBJECT_HEAPITEM;
-	last->heap=h;
-	return 1;
-}
-
-
-LPVOID HeapAlloc(HEAP_OBJECT *h,DWORD dwFlags,DWORD dwBytes)
-{
-	HEAPITEM_OBJECT *it,*next,*prev;
-	/* FIXME: last error */
-	if(!h)
-		return SIMPLE_HeapAlloc(h,dwFlags,dwBytes);
-	if(h->common.magic!=KERNEL_OBJECT_HEAP)
-		return 0;
-	/* align to DWORD */
-	dwBytes = (dwBytes + 3) & ~3;
-	for(it=h->first;it;it=it->next)
-	{
-		if(it->size>dwBytes+sizeof(HEAPITEM_OBJECT))
-			break;
-	}
-	if(!it)
-	{
-		if(!HEAP_GrowHeap(h,dwBytes))
-			return 0;
-		it=h->last;
-	}
-	next = it->next;
-	prev = it->prev;
-	if(it->size > dwBytes+2*sizeof(HEAPITEM_OBJECT))
-	{	/* split item */
-		HEAPITEM_OBJECT *next=(HEAPITEM_OBJECT*)((char*)(it+1)+dwBytes);
-		next->common.magic=KERNEL_OBJECT_HEAPITEM;
-		next->size=it->size-sizeof(HEAPITEM_OBJECT)-dwBytes;
-		next->next = it->next;
-	}
-	if(next)
-		next->prev=prev;
-	else
-		h->last=prev;
-	if(prev)
-		prev->next=next;
-	else
-		h->first=next;
-	/* Allocated item is denoted by self-referencing */
-	it->next=it->prev=it;
-	return (LPVOID)(it+1);
-}
-
-BOOL HeapFree(HEAP_OBJECT *h,DWORD dwFlags,LPVOID lpMem)
-{
-	HEAPITEM_OBJECT *item,*prev,*next;
-	item = (HEAPITEM_OBJECT*)lpMem - 1;
-	if(item->common.magic != KERNEL_OBJECT_HEAP)
-		return 0;
-	for(next=item;(caddr_t)next<(caddr_t)h->start+h->size;
-		next=(HEAPITEM_OBJECT*)((char*)next+next->size))
-		if(next!=next->next)
-			break;
-	if((caddr_t)next>=(caddr_t)h->start+h->size)
-		next=0;
-	if(next)
-		prev=next->prev;
-	else
-		prev=h->last;
-	/* consolidate with previous */
-	if(prev && (char*)prev+prev->size==(char*)item)
-	{
-		prev->size+=item->size;
-		item=prev;
-		prev=item->prev;
-	}
-	/* consolidate with next */
-	if(next && (char*)item+item->size==(char*)next)
-	{
-		item->size+=next->size;
-		next=next->next;
-	}
-	if(prev)
-	{
-		item->prev=prev;
-		prev->next=item;
-	} else 
-		h->first=item;
-	if(next)
-	{
-		item->next=next;
-		next->prev=item;
-	}else
-		h->last=item;
-	return 1;
-}
-
diff --git a/win32/init.c b/win32/init.c
index 0d53749..bf38b1d 100644
--- a/win32/init.c
+++ b/win32/init.c
@@ -30,7 +30,7 @@
 /*********************************************************************
  *              CloseHandle             (KERNEL32.23)
  */
-BOOL CloseHandle(HANDLE32 handle)
+BOOL CloseHandle(KERNEL_OBJECT *handle)
 {
     int rc;
 
diff --git a/win32/resource.c b/win32/resource.c
index 7d55ec9..dfe5537 100644
--- a/win32/resource.c
+++ b/win32/resource.c
@@ -93,7 +93,7 @@
 HANDLE32 FindResource32( HINSTANCE hModule, LPCWSTR name, LPCWSTR type )
 {
 #ifndef WINELIB
-    struct pe_data *pe;
+    PE_MODULE *pe;
     NE_MODULE *pModule;
     PIMAGE_RESOURCE_DIRECTORY resdirptr;
     DWORD root;
@@ -105,9 +105,9 @@
     dprintf_resource( stddeb, " name=" );
     PrintId( name );
     dprintf_resource( stddeb, "\n" );
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0;  /* FIXME? */
-    if (!(pe = NE_WIN32_MODULE(pModule)) || !pe->pe_resource) return 0;
+    if (!(pe = pModule->pe_module) || !pe->pe_resource) return 0;
 
     resdirptr = (PIMAGE_RESOURCE_DIRECTORY) pe->pe_resource;
     root = (DWORD) resdirptr;
@@ -117,8 +117,10 @@
 	return 0;
     result = GetResDirEntry(resdirptr, (LPCWSTR)language, root);
 	/* Try LANG_NEUTRAL, too */
-	if(!result)
-		return GetResDirEntry(resdirptr, (LPCWSTR)0, root);
+    if(!result)
+        return GetResDirEntry(resdirptr, (LPCWSTR)0, root);
+    return result;
+    
 #else
     return LIBRES_FindResource( hModule, name, type );
 #endif
@@ -131,17 +133,17 @@
 HANDLE32 LoadResource32( HINSTANCE hModule, HANDLE32 hRsrc )
 {
 #ifndef WINELIB
-    struct pe_data *pe;
     NE_MODULE *pModule;
+    PE_MODULE *pe;
 
     hModule = GetExePtr( hModule );  /* In case we were passed an hInstance */
     dprintf_resource(stddeb, "LoadResource: module=%04x res=%04x\n",
                      hModule, hRsrc );
     if (!hRsrc) return 0;
 
-    if (!(pModule = (NE_MODULE *)GlobalLock( hModule ))) return 0;
+    if (!(pModule = MODULE_GetPtr( hModule ))) return 0;
     if (!(pModule->flags & NE_FFLAGS_WIN32)) return 0;  /* FIXME? */
-    if (!(pe = NE_WIN32_MODULE(pModule)) || !pe->pe_resource) return 0;
+    if (!(pe = pModule->pe_module) || !pe->pe_resource) return 0;
     return (HANDLE32) (pe->load_addr+((PIMAGE_RESOURCE_DATA_ENTRY)hRsrc)->OffsetToData);
 #else
     return LIBRES_LoadResource( hModule, hRsrc );
diff --git a/win32/thread.c b/win32/thread.c
index 5e203c1..3d958d0 100644
--- a/win32/thread.c
+++ b/win32/thread.c
@@ -48,12 +48,18 @@
 
 void WINAPI EnterCriticalSection(CRITICAL_SECTION* lpCrit)
 {
-	return;
+    if (lpCrit->LockCount)
+        fprintf( stderr, "Error: re-entering critical section %08lx\n",
+                 (DWORD)lpCrit );
+    lpCrit->LockCount++;
 }
 
 void WINAPI LeaveCriticalSection(CRITICAL_SECTION* lpCrit)
 {
-	return;
+    if (!lpCrit->LockCount)
+        fprintf( stderr, "Error: leaving critical section %08lx again\n",
+                 (DWORD)lpCrit );
+    lpCrit->LockCount--;
 }
 
 void WINAPI DeleteCriticalSection(CRITICAL_SECTION* lpCrit)
diff --git a/win32/time.c b/win32/time.c
index 8dd88fc..610d4a6 100644
--- a/win32/time.c
+++ b/win32/time.c
@@ -84,6 +84,6 @@
 VOID Sleep(DWORD cMilliseconds)
 {
     if(cMilliseconds == INFINITE)
-        while(1) { /* Spin forever */ }
+        while(1) sleep(1000); /* Spin forever */
     usleep(cMilliseconds*1000);
 }
diff --git a/windows/dialog.c b/windows/dialog.c
index a3fc33d..ee3f402 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -69,14 +69,20 @@
  *           DIALOG_GetControl
  *
  * Return the class and text of the control pointed to by ptr,
- * and return a pointer to the next control.
+ * fill the header structure and return a pointer to the next control.
  */
-static SEGPTR DIALOG_GetControl( SEGPTR ptr, SEGPTR *class, SEGPTR *text )
+static SEGPTR DIALOG_GetControl( SEGPTR ptr, DLGCONTROLHEADER *header,
+                                 SEGPTR *class, SEGPTR *text )
 {
     unsigned char *base = (unsigned char *)PTR_SEG_TO_LIN( ptr );
     unsigned char *p = base;
 
-    p += 14;  /* size of control header */
+    header->x  = GET_WORD(p); p += sizeof(WORD);
+    header->y  = GET_WORD(p); p += sizeof(WORD);
+    header->cx = GET_WORD(p); p += sizeof(WORD);
+    header->cy = GET_WORD(p); p += sizeof(WORD);
+    header->id = GET_WORD(p); p += sizeof(WORD);
+    header->style = GET_DWORD(p); p += sizeof(DWORD);
 
     if (*p & 0x80)
     {
@@ -92,7 +98,7 @@
     if (*p == 0xff)
     {
 	  /* Integer id, not documented (?). Only works for SS_ICON controls */
-	*text = MAKEINTRESOURCE( p[1] + 256 * p[2] );
+	*text = MAKEINTRESOURCE( GET_WORD(p+1) );
 	p += 4;
     }
     else
@@ -115,14 +121,18 @@
     unsigned char *base = (unsigned char *)PTR_SEG_TO_LIN(template);
     unsigned char * p = base;
  
-    result->header = *(DLGTEMPLATEHEADER *)p;
-    p += 13;
+    result->style = GET_DWORD(p); p += sizeof(DWORD);
+    result->nbItems = *p++;
+    result->x  = GET_WORD(p); p += sizeof(WORD);
+    result->y  = GET_WORD(p); p += sizeof(WORD);
+    result->cx = GET_WORD(p); p += sizeof(WORD);
+    result->cy = GET_WORD(p); p += sizeof(WORD);
 
     /* Get the menu name */
 
     if (*p == 0xff)
     {
-        result->menuName = MAKEINTRESOURCE( p[1] + 256 * p[2] );
+        result->menuName = MAKEINTRESOURCE( GET_WORD(p+1) );
         p += 3;
     }
     else if (*p)
@@ -149,9 +159,9 @@
 
     /* Get the font name */
 
-    if (result->header.style & DS_SETFONT)
+    if (result->style & DS_SETFONT)
     {
-	result->pointSize = *(WORD *)p;
+	result->pointSize = GET_WORD(p);
         p += sizeof(WORD);
 	result->faceName = template + (WORD)(p - base);
         p += strlen(p) + 1;
@@ -166,9 +176,9 @@
  */
 static void DIALOG_DisplayTemplate( DLGTEMPLATE * result )
 {
-    dprintf_dialog(stddeb, "DIALOG %d, %d, %d, %d\n", result->header.x, result->header.y,
-	    result->header.cx, result->header.cy );
-    dprintf_dialog(stddeb, " STYLE %08lx\n", result->header.style );
+    dprintf_dialog(stddeb, "DIALOG %d, %d, %d, %d\n", result->x, result->y,
+                   result->cx, result->cy );
+    dprintf_dialog(stddeb, " STYLE %08lx\n", result->style );
     dprintf_dialog( stddeb, " CAPTION '%s'\n",
                     (char *)PTR_SEG_TO_LIN(result->caption) );
 
@@ -184,7 +194,7 @@
     else if (LOWORD(result->menuName))
 	dprintf_dialog(stddeb, " MENU %04x\n", LOWORD(result->menuName) );
 
-    if (result->header.style & DS_SETFONT)
+    if (result->style & DS_SETFONT)
 	dprintf_dialog( stddeb, " FONT %d,'%s'\n", result->pointSize,
                         (char *)PTR_SEG_TO_LIN(result->faceName) );
 }
@@ -264,7 +274,7 @@
 
       /* Create custom font if needed */
 
-    if (template.header.style & DS_SETFONT)
+    if (template.style & DS_SETFONT)
     {
           /* The font height must be negative as it is a point size */
           /* (see CreateFont() documentation in the Windows SDK).   */
@@ -293,26 +303,26 @@
       /* Create dialog main window */
 
     rect.left = rect.top = 0;
-    rect.right = template.header.cx * xUnit / 4;
-    rect.bottom = template.header.cy * yUnit / 8;
-    if (template.header.style & DS_MODALFRAME) exStyle |= WS_EX_DLGMODALFRAME;
-    AdjustWindowRectEx( &rect, template.header.style, 
+    rect.right = template.cx * xUnit / 4;
+    rect.bottom = template.cy * yUnit / 8;
+    if (template.style & DS_MODALFRAME) exStyle |= WS_EX_DLGMODALFRAME;
+    AdjustWindowRectEx( &rect, template.style, 
 			hMenu ? TRUE : FALSE , exStyle );
     rect.right -= rect.left;
     rect.bottom -= rect.top;
 
-    if ((INT)template.header.x == CW_USEDEFAULT)
+    if ((INT)template.x == CW_USEDEFAULT)
         rect.left = rect.top = CW_USEDEFAULT;
     else
     {
-        rect.left += template.header.x * xUnit / 4;
-        rect.top += template.header.y * yUnit / 8;
-        if (!(template.header.style & DS_ABSALIGN))
+        rect.left += template.x * xUnit / 4;
+        rect.top += template.y * yUnit / 8;
+        if (!(template.style & DS_ABSALIGN))
             ClientToScreen( owner, (POINT *)&rect );
     }
 
     hwnd = CreateWindowEx( exStyle, template.className, template.caption, 
-			   template.header.style & ~WS_VISIBLE,
+			   template.style & ~WS_VISIBLE,
 			   rect.left, rect.top, rect.right, rect.bottom,
 			   owner, hMenu, hInst, (SEGPTR)0 );
     if (!hwnd)
@@ -348,15 +358,15 @@
     dlgInfo->msgResult = 0;  /* This is used to store the default button id */
     dlgInfo->hDialogHeap = 0;
 
-    for (i = 0; i < template.header.nbItems; i++)
+    for (i = 0; i < template.nbItems; i++)
     {
-	DLGCONTROLHEADER *header;
+	DLGCONTROLHEADER header;
 	SEGPTR className, winName;
         HWND hwndDefButton = 0;
         char buffer[10];
 
-        header = (DLGCONTROLHEADER *)PTR_SEG_TO_LIN( headerPtr );
-	headerPtr = DIALOG_GetControl( headerPtr, &className, &winName );
+	headerPtr = DIALOG_GetControl( headerPtr, &header,
+                                       &className, &winName );
 
         if (!HIWORD(className))
         {
@@ -381,12 +391,12 @@
 	else dprintf_dialog(stddeb,"%04x", LOWORD(winName) );
 
 	dprintf_dialog(stddeb," %d, %d, %d, %d, %d, %08lx\n", 
-                       header->id, header->x, header->y, 
-                       header->cx, header->cy, header->style );
+                       header.id, header.x, header.y, 
+                       header.cx, header.cy, header.style );
 
 	if (HIWORD(className) &&
             !strcmp( (char *)PTR_SEG_TO_LIN(className), "EDIT") &&
-            ((header->style & DS_LOCALEDIT) != DS_LOCALEDIT))
+            ((header.style & DS_LOCALEDIT) != DS_LOCALEDIT))
         {
 	    if (!dlgInfo->hDialogHeap)
             {
@@ -399,23 +409,23 @@
 		LocalInit(dlgInfo->hDialogHeap, 0, 0xffff);
 	    }
 	    hwndCtrl = CreateWindowEx(WS_EX_NOPARENTNOTIFY, className, winName,
-                                      header->style | WS_CHILD,
-                                      header->x * xUnit / 4,
-                                      header->y * yUnit / 8,
-                                      header->cx * xUnit / 4,
-                                      header->cy * yUnit / 8,
-                                      hwnd, (HMENU)header->id,
+                                      header.style | WS_CHILD,
+                                      header.x * xUnit / 4,
+                                      header.y * yUnit / 8,
+                                      header.cx * xUnit / 4,
+                                      header.cy * yUnit / 8,
+                                      hwnd, (HMENU)header.id,
                                       dlgInfo->hDialogHeap, (SEGPTR)0 );
 	}
 	else
         {
 	    hwndCtrl = CreateWindowEx(WS_EX_NOPARENTNOTIFY, className, winName,
-                                      header->style | WS_CHILD,
-                                      header->x * xUnit / 4,
-                                      header->y * yUnit / 8,
-                                      header->cx * xUnit / 4,
-                                      header->cy * yUnit / 8,
-                                      hwnd, (HMENU)header->id,
+                                      header.style | WS_CHILD,
+                                      header.x * xUnit / 4,
+                                      header.y * yUnit / 8,
+                                      header.cx * xUnit / 4,
+                                      header.cy * yUnit / 8,
+                                      hwnd, (HMENU)header.id,
                                       hInst, (SEGPTR)0 );
 	}
 
@@ -454,7 +464,7 @@
 	SendMessage( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
     if (SendMessage( hwnd, WM_INITDIALOG, (WPARAM)dlgInfo->hwndFocus, param ))
 	SetFocus( dlgInfo->hwndFocus );
-    if (template.header.style & WS_VISIBLE) ShowWindow(hwnd, SW_SHOW);
+    if (template.style & WS_VISIBLE) ShowWindow(hwnd, SW_SHOW);
     return hwnd;
 }
 
diff --git a/windows/event.c b/windows/event.c
index 19fa10a..098d876 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -6,7 +6,6 @@
  */
 
 #include <ctype.h>
-#include <signal.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
@@ -20,6 +19,7 @@
 #include "win.h"
 #include "class.h"
 #include "clipboard.h"
+#include "debugger.h"
 #include "options.h"
 #include "queue.h"
 #include "winpos.h"
@@ -317,7 +317,7 @@
     /* Ctrl-Alt-Return enters the debugger */
     if ((keysym == XK_Return) && (event->type == KeyPress) &&
         (event->state & ControlMask) && (event->state & Mod1Mask))
-        kill( getpid(), SIGHUP );
+        DEBUG_EnterDebugger();
 
     xkey = LOWORD(keysym);
     key_type = HIBYTE(xkey);
@@ -451,8 +451,8 @@
     int buttonNum = event->button - 1;
 
     if (buttonNum >= NB_BUTTONS) return;
-    MouseButtonsStates[buttonNum] = TRUE;
-    AsyncMouseButtonsStates[buttonNum] = TRUE;
+    MouseButtonsStates[buttonNum] = 0x8000;
+    AsyncMouseButtonsStates[buttonNum] = 0x8000;
     hardware_event( messages[buttonNum],
 		    EVENT_XStateToKeyState( event->state ), 0L,
 		    event->x_root - desktopX, event->y_root - desktopY,
diff --git a/windows/keyboard.c b/windows/keyboard.c
index bdf8030..7dae630 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -40,9 +40,9 @@
 void GetKeyboardState(BYTE FAR *lpKeyState)
 {
     if (lpKeyState != NULL) {
-	KeyStateTable[VK_LBUTTON] = MouseButtonsStates[0];
-	KeyStateTable[VK_MBUTTON] = MouseButtonsStates[1];
-	KeyStateTable[VK_RBUTTON] = MouseButtonsStates[2];
+	KeyStateTable[VK_LBUTTON] = MouseButtonsStates[0] >> 8;
+	KeyStateTable[VK_MBUTTON] = MouseButtonsStates[1] >> 8;
+	KeyStateTable[VK_RBUTTON] = MouseButtonsStates[2] >> 8;
 	memcpy(lpKeyState, KeyStateTable, 256);
     }
 }
@@ -54,9 +54,9 @@
 {
     if (lpKeyState != NULL) {
 	memcpy(KeyStateTable, lpKeyState, 256);
-	MouseButtonsStates[0] = KeyStateTable[VK_LBUTTON];
-	MouseButtonsStates[1] = KeyStateTable[VK_MBUTTON];
-	MouseButtonsStates[2] = KeyStateTable[VK_RBUTTON];
+	MouseButtonsStates[0] = KeyStateTable[VK_LBUTTON]? 0x8000: 0;
+	MouseButtonsStates[1] = KeyStateTable[VK_MBUTTON]? 0x8000: 0;
+	MouseButtonsStates[2] = KeyStateTable[VK_RBUTTON]? 0x8000: 0;
     }
 }
 
@@ -80,15 +80,15 @@
     switch (nKey) {
      case VK_LBUTTON:
 	retval = AsyncMouseButtonsStates[0] | 
-	(MouseButtonsStates[0] << 8);
+	MouseButtonsStates[0]? 0x0001: 0;
 	break;
      case VK_MBUTTON:
 	retval = AsyncMouseButtonsStates[1] |
-	(MouseButtonsStates[1] << 8);
+	MouseButtonsStates[1]? 0x0001: 0;
 	break;
      case VK_RBUTTON:
 	retval = AsyncMouseButtonsStates[2] |
-	(MouseButtonsStates[2] << 8);
+	MouseButtonsStates[2]? 0x0001: 0;
 	break;
      default:
 	retval = AsyncKeyStateTable[nKey] | 
diff --git a/windows/message.c b/windows/message.c
index 6a88fc6..d1ac195 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -81,32 +81,28 @@
    
     hittest = WINPOS_WindowFromPoint( msg->pt, &pWnd );
     msg->hwnd = pWnd->hwndSelf;
-    if (hittest != HTERROR)
+    if ((hittest != HTERROR) && mouseClick)
     {
+        HWND hwndTop = WIN_GetTopParent( msg->hwnd );
+
         /* Send the WM_PARENTNOTIFY message */
 
-        if (mouseClick) WIN_SendParentNotify( msg->hwnd, msg->message, 0,
-                                            MAKELONG( msg->pt.x, msg->pt.y ) );
+        WIN_SendParentNotify( msg->hwnd, msg->message, 0,
+                              MAKELONG( msg->pt.x, msg->pt.y ) );
 
         /* Activate the window if needed */
 
-        if (mouseClick)
+        if (msg->hwnd != GetActiveWindow() && msg->hwnd != GetDesktopWindow())
         {
-            HWND hwndTop = WIN_GetTopParent( msg->hwnd );
-            if (hwndTop != GetActiveWindow())
-            {
-                LONG ret = SendMessage( msg->hwnd, WM_MOUSEACTIVATE,
-					(WPARAM)hwndTop,
-                                        MAKELONG( hittest, msg->message ) );
-                if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
-                    eatMsg = TRUE;
-                if ((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT))
-                {
-                    SetWindowPos( hwndTop, HWND_TOP, 0, 0, 0, 0,
-                                 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
-                    WINPOS_ChangeActiveWindow( hwndTop, TRUE );
-                }
-            }
+            LONG ret = SendMessage( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
+                                    MAKELONG( hittest, msg->message ) );
+
+            if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
+                eatMsg = TRUE;
+
+            if (((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT)) 
+                && hwndTop != GetActiveWindow() )
+                WINPOS_ChangeActiveWindow( hwndTop, TRUE );
         }
     }