Release 960421

Sat Apr 20 23:23:16 1996  Robert Pouliot <krynos@qbc.clic.net>

	* [resources/sysres_Fr.rc] [resources/TODO]
	Made changes for Choose_Color dialog.

Sat Apr 20 15:43:49 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [controls/button.c]
	Fixed test that got miscompiled by some old gcc versions.

	* [memory/local.c]
	Fixed the layout of handle tables so that moveable handle entries
	can be freed on LocalFree().
	Implemented LocalFlags(), LocalCountFree(), LocalHandleDelta() and
	GetHeapSpaces().

	* [misc/main.c] [ANNOUNCE]
	Update the list of contributors. Please let me know if I forgot
	someone.

Fri Apr 19 20:07:20 1996  Frans van Dorsselaer  <dorssel@rulhm1.leidenuniv.nl>

	* [controls/edit.c] [controls/EDIT.TODO]
	Fixed EM_SETHANDLE / WM_CREATE / EDIT_MakeFir() buffer allocation.
	Fixed ES_NOHIDESEL / WM_MOUSEMOVE / WM_LBUTTONDOWN implementation.
	Added WM_ENABLE implementation (gray text).
	Fixed buffer > 32767 bug.
	Fixed argument types / typecasting.
	Faster selection (re)drawing.

Thu Apr 18 13:38:26 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [misc/registry.c] [include/winreg.h]
	Changed savefile format again to human readable/editable
	(UNICODE chars >0xff are specified by \uXXXX, data by XX).
	Has now global / local registry databases (including merging them).
	HKEY_CLASSES_ROOT == HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes.
	HKEY_CURRENT_USER == HKEY_USERS\\<loginname>.

	* [misc/comm.c]
	Allow " " as COMx: ... spec delimiter too.
	(AOL-CD setup.exe tries to initialize modem2 as "9600,x,x x" (can't 
	remember the x).

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

	* [windows/mdi.c]
	Miscellaneous changes.

	* [windows/winpos.c] 
	Use BitBlt whenever possible in SetWindowPos.

	* [windows/painting.c]
	Fix incompatibilities with hrgnUpdate being 1.

Wed Apr 17 19:19:22 1996  Albrecht Kleine  <kleine@ak.sax.de>

	* [misc/commdlg.c]
	Many bugfixes in ChooseColor dialog.
	Added a user defined dialog title in FileOpen-/FileSave- dialog.

	* [misc/commdlg.c][include/commdlg.h]
	  [if1632/commdlg.spec][if1632/winprocs.spec]
	Introduced dialog-, callback- and enum- stub functions
	for ChooseFont dialog

Wed Apr 17 19:08:38 1996  Niels de Carpentier  <niels@cindy.et.tudelft.nl>

	* [objects/metafile.c] [include/metafile.h] [if1632/gdi.spec]
	Implemented EnumMetaFile and CopyMetaFile. Removed METAFILE struct.
	Implemented META_STRETCHDIB in PlayMetaFileRecord, several bug 
	fixes.

	* [windows/winpos.c]
	Don't try to hide the window if it's already hidden.

	* [windows/message.c]
	Let MSG_PeekHardwareMsg fill the message queue with events if
	it's empty.

Wed Apr 17 17:54:04 1996  Tristan Tarrant <tst@sthinc.demon.co.uk>

	* [resources/sysres_It.rc]
	Updated to support the new CHOOSE_COLOR_DIALOG.

Tue Apr 16 11:50:00 1996  Anand Kumria <akumria@ozemail.com.au>

	* [if1632/Makefile] [if1632/relay.c] [if1631/w32sys.spec]
	  [include/w32sys.h] [include/dlls.h]
	  [misc/Makefile] [misc/w32sys.c]
	W32SYS.DLL partially implemented.
diff --git a/ANNOUNCE b/ANNOUNCE
index 7f3bb2f..23bded41 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,14 +1,15 @@
-This is release 960414 of Wine the MS Windows emulator.  This is still a
+This is release 960421 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-960414: (see ChangeLog for details)
-	- Complete rewrite of the edit control.
-	- Better color selection dialog.
-	- Win32 heap management.
+WHAT'S NEW with Wine-960421: (see ChangeLog for details)
+	- Preliminary support for W32SYS.DLL.
+	- Built-in COMMDLG improvements.
+	- New format and location for registry files.
+	- Window refresh optimized.
 	- Lots of bug fixes.
 
 See the README file in the distribution for installation instructions.
@@ -17,10 +18,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-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
+    sunsite.unc.edu:/pub/Linux/ALPHA/wine/development/Wine-960421.tar.gz
+    tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-960421.tar.gz
+    ftp.infomagic.com:/pub/mirrors/linux/wine/development/Wine-960421.tar.gz
+    aris.com:/pub/linux/ALPHA/Wine/development/Wine-960421.tar.gz
 
 It should also be available from any site that mirrors tsx-11 or sunsite.
 
@@ -34,19 +35,25 @@
 really intend to test the new releases as soon as they're out.
 
 Wine is available thanks to the work of Bob Amstadt, Dag Asheim,
-Martin Ayotte, Ross Biro, Erik Bos, Fons Botman, John Brezak,
-Andrew Bulhak, John Burton, Paul Falstad, Olaf Flebbe, Peter Galbavy,
-Ramon Garcia, Hans de Graaff, Charles M. Hannum, Cameron Heide,
-Jochen Hoenicke, Jeffrey Hsu, Miguel de Icaza, Alexandre Julliard,
-Jon Konrath, Scott A. Laird, Martin von Loewis, Kenneth MacDonald,
-Peter MacDonald, William Magro, Marcus Meissner, Graham Menhennitt,
-David Metcalfe, Michael Patra, John Richardson, Johannes Ruscheinski,
-Thomas Sandford, Constantine Sapuntzakis, Daniel Schepler,
+Martin Ayotte, Ross Biro, Uwe Bonnes, Erik Bos, Fons Botman, John Brezak,
+Andrew Bulhak, John Burton, Niels de Carpentier, Roman Dolejsi,
+Frans van Dorsselaer, Paul Falstad, Olaf Flebbe, Peter Galbavy,
+Ramon Garcia, Hans de Graaff, Charles M. Hannum, John Harvey,
+Cameron Heide, Jochen Hoenicke, Onno Hovers, Jeffrey Hsu,
+Miguel de Icaza, Jukka Iivonen, Alexandre Julliard, Jochen Karrer,
+Andreas Kirschbaum, Albrecht Kleine, Jon Konrath, Alex Korobka,
+Greg Kreider, Anand Kumria, Scott A. Laird, Martin von Loewis,
+Kenneth MacDonald, Peter MacDonald, William Magro, Juergen Marquardt,
+Marcus Meissner, Graham Menhennitt, David Metcalfe, Steffen Moeller,
+Philippe De Muyter, Itai Nahshon, Michael Patra, Jim Peterson,
+Robert Pouliot, Keith Reynolds, John Richardson, Johannes Ruscheinski,
+Thomas Sandford, Constantine Sapuntzakis, Daniel Schepler, Ulrich Schmid,
 Bernd Schmidt, Yngvi Sigurjonsson, Rick Sladkey, William Smith,
-Erik Svendsen, Goran Thyni, Jimmy Tirtawangsa, Jon Tombs,
-Linus Torvalds, Gregory Trubetskoy, Michael Veksler, Morten Welinder,
-Jan Willamowius, Carl Williams, Karl Guenter Wuensch, Eric Youngdale,
-and James Youngman.
+Erik Svendsen, Tristan Tarrant, Andrew Taylor, Duncan C Thomson,
+Goran Thyni, Jimmy Tirtawangsa, Jon Tombs, Linus Torvalds,
+Gregory Trubetskoy, Michael Veksler, Sven Verdoolaege, Eric Warnke,
+Manfred Weichel, Morten Welinder, Jan Willamowius, Carl Williams,
+Karl Guenter Wuensch, Eric Youngdale, and James Youngman.
 
 --
 Alexandre Julliard
diff --git a/ChangeLog b/ChangeLog
index 46b0a5b..f8d4c3d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,97 @@
 ----------------------------------------------------------------------
+Sat Apr 20 23:23:16 1996  Robert Pouliot <krynos@qbc.clic.net>
+
+	* [resources/sysres_Fr.rc] [resources/TODO]
+	Made changes for Choose_Color dialog.
+
+Sat Apr 20 15:43:49 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
+
+	* [controls/button.c]
+	Fixed test that got miscompiled by some old gcc versions.
+
+	* [memory/local.c]
+	Fixed the layout of handle tables so that moveable handle entries
+	can be freed on LocalFree().
+	Implemented LocalFlags(), LocalCountFree(), LocalHandleDelta() and
+	GetHeapSpaces().
+
+	* [misc/main.c] [ANNOUNCE]
+	Update the list of contributors. Please let me know if I forgot
+	someone.
+
+Fri Apr 19 20:07:20 1996  Frans van Dorsselaer  <dorssel@rulhm1.leidenuniv.nl>
+
+	* [controls/edit.c] [controls/EDIT.TODO]
+	Fixed EM_SETHANDLE / WM_CREATE / EDIT_MakeFir() buffer allocation.
+	Fixed ES_NOHIDESEL / WM_MOUSEMOVE / WM_LBUTTONDOWN implementation.
+	Added WM_ENABLE implementation (gray text).
+	Fixed buffer > 32767 bug.
+	Fixed argument types / typecasting.
+	Faster selection (re)drawing.
+
+Thu Apr 18 13:38:26 1996  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>
+
+	* [misc/registry.c] [include/winreg.h]
+	Changed savefile format again to human readable/editable
+	(UNICODE chars >0xff are specified by \uXXXX, data by XX).
+	Has now global / local registry databases (including merging them).
+	HKEY_CLASSES_ROOT == HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes.
+	HKEY_CURRENT_USER == HKEY_USERS\\<loginname>.
+
+	* [misc/comm.c]
+	Allow " " as COMx: ... spec delimiter too.
+	(AOL-CD setup.exe tries to initialize modem2 as "9600,x,x x" (can't 
+	remember the x).
+
+Thu Apr 18 09:00:00 1996  Alex Korobka <alex@phm30.pharm.sunysb.edu>
+
+	* [windows/mdi.c]
+	Miscellaneous changes.
+
+	* [windows/winpos.c] 
+	Use BitBlt whenever possible in SetWindowPos.
+
+	* [windows/painting.c]
+	Fix incompatibilities with hrgnUpdate being 1.
+
+Wed Apr 17 19:19:22 1996  Albrecht Kleine  <kleine@ak.sax.de>
+
+	* [misc/commdlg.c]
+	Many bugfixes in ChooseColor dialog.
+	Added a user defined dialog title in FileOpen-/FileSave- dialog.
+
+	* [misc/commdlg.c][include/commdlg.h]
+	  [if1632/commdlg.spec][if1632/winprocs.spec]
+	Introduced dialog-, callback- and enum- stub functions
+	for ChooseFont dialog
+
+Wed Apr 17 19:08:38 1996  Niels de Carpentier  <niels@cindy.et.tudelft.nl>
+
+	* [objects/metafile.c] [include/metafile.h] [if1632/gdi.spec]
+	Implemented EnumMetaFile and CopyMetaFile. Removed METAFILE struct.
+	Implemented META_STRETCHDIB in PlayMetaFileRecord, several bug 
+	fixes.
+
+	* [windows/winpos.c]
+	Don't try to hide the window if it's already hidden.
+
+	* [windows/message.c]
+	Let MSG_PeekHardwareMsg fill the message queue with events if
+	it's empty.
+
+Wed Apr 17 17:54:04 1996  Tristan Tarrant <tst@sthinc.demon.co.uk>
+
+	* [resources/sysres_It.rc]
+	Updated to support the new CHOOSE_COLOR_DIALOG.
+
+Tue Apr 16 11:50:00 1996  Anand Kumria <akumria@ozemail.com.au>
+
+	* [if1632/Makefile] [if1632/relay.c] [if1631/w32sys.spec]
+	  [include/w32sys.h] [include/dlls.h]
+	  [misc/Makefile] [misc/w32sys.c]
+	W32SYS.DLL partially implemented.
+
+----------------------------------------------------------------------
 Sun Apr 14 12:51:27 1996  Alexandre Julliard  <julliard@lrc.epfl.ch>
 
 	* [controls/menu.c] [include/dialog.h] [windows/dialog.c]
diff --git a/controls/EDIT.TODO b/controls/EDIT.TODO
index a190874..99b4270 100644
--- a/controls/EDIT.TODO
+++ b/controls/EDIT.TODO
@@ -98,9 +98,6 @@
 -	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
diff --git a/controls/button.c b/controls/button.c
index 68515db..f5e7eff 100644
--- a/controls/button.c
+++ b/controls/button.c
@@ -253,12 +253,17 @@
 		break;
 
 	case BM_SETSTATE:
-                if (!wParam != !(infoPtr->state & BUTTON_HIGHLIGHTED))
+                if (wParam)
                 {
-                    if (wParam) infoPtr->state |= BUTTON_HIGHLIGHTED;
-                    else infoPtr->state &= ~BUTTON_HIGHLIGHTED;
-                    PAINT_BUTTON( wndPtr, style, ODA_SELECT );
+                    if (infoPtr->state & BUTTON_HIGHLIGHTED) break;
+                    infoPtr->state |= BUTTON_HIGHLIGHTED;
                 }
+                else
+                {
+                    if (!(infoPtr->state & BUTTON_HIGHLIGHTED)) break;
+                    infoPtr->state &= ~BUTTON_HIGHLIGHTED;
+                }
+                PAINT_BUTTON( wndPtr, style, ODA_SELECT );
                 break;
 
 	default:
diff --git a/controls/edit.c b/controls/edit.c
index d49bd04..296365c 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -23,8 +23,8 @@
 #include "xmalloc.h"
 #include "callback.h"
 
-#define BUFLIMIT_MULTI		65535	/* maximum text buffer length */
-#define BUFLIMIT_SINGLE		32767	/* maximum text buffer length */
+#define BUFLIMIT_MULTI		65534	/* maximum text buffer length (not including '\0') */
+#define BUFLIMIT_SINGLE		32766
 #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 */
@@ -40,38 +40,38 @@
 } LINE_END;
 
 typedef struct {
-	int offset;
-	int length;
+	UINT offset;
+	UINT length;
 	LINE_END ending;
 } LINEDEF;
 
 typedef struct
 {
-	int TextWidth;		/* width of the widest line in pixels */
+	UINT 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;
+	UINT XOffset;		/* offset of the viewport in pixels */
+	UINT FirstVisibleLine;
+	UINT LineCount;
+	UINT LineHeight;	/* height of a screen line in pixels */
+	UINT AveCharWidth;	/* average character width in pixels */
+	UINT BufLimit;
+	UINT BufSize;
 	BOOL TextChanged;
 	BOOL Redraw;
-	int SelStart;		/* offset of selection start, == SelEnd if no selection */
-	int SelEnd;		/* offset of selection end == current caret position */
-	int NumTabStops;
+	UINT SelStart;		/* offset of selection start, == SelEnd if no selection */
+	UINT SelEnd;		/* offset of selection end == current caret position */
+	UINT NumTabStops;
 	LPINT TabStops;
 	EDITWORDBREAKPROC WordBreakProc;
 	char PasswordChar;
 } EDITSTATE;
 
 
-#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)
+#define SWAP_UINT(x,y) do { UINT temp = (UINT)(x); (x) = (UINT)(y); (y) = temp; } while(0)
+#define ORDER_UINT(x,y) do { if ((UINT)(y) < (UINT)(x)) SWAP_UINT((x),(y)); } while(0)
 
 /* macros to access window styles */
 #define IsMultiLine(wndPtr) ((wndPtr)->dwStyle & ES_MULTILINE)
@@ -118,23 +118,24 @@
 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 INT     EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action);
+static UINT    EDIT_ColFromWndX(WND *wndPtr, UINT 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 UINT    EDIT_GetAveCharWidth(WND *wndPtr);
+static UINT    EDIT_GetLineHeight(WND *wndPtr);
+static void    EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT 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 UINT    EDIT_GetTextWidth(WND *wndPtr);
+static UINT    EDIT_GetVisibleLineCount(WND *wndPtr);
+static UINT    EDIT_GetWndWidth(WND *wndPtr);
+static UINT    EDIT_GetXOffset(WND *wndPtr);
+static void    EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end);
+static UINT    EDIT_LineFromWndY(WND *wndPtr, INT y);
+static BOOL    EDIT_MakeFit(WND *wndPtr, UINT size);
 static void    EDIT_MoveBackward(WND *wndPtr, BOOL extend);
 static void    EDIT_MoveDownward(WND *wndPtr, BOOL extend);
 static void    EDIT_MoveEnd(WND *wndPtr, BOOL extend);
@@ -145,14 +146,14 @@
 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_PaintLine(WND *wndPtr, HDC hdc, UINT line, BOOL rev);
+static UINT    EDIT_PaintText(WND *wndPtr, HDC hdc, INT x, INT y, UINT line, UINT col, UINT 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 INT     EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col);
+static INT     EDIT_WndYFromLine(WND *wndPtr, UINT line);
+static INT     EDIT_WordBreakProc(char *s, INT index, INT count, INT action);
 
 static LRESULT EDIT_EM_CanUndo(WND *wndPtr, WPARAM wParam, LPARAM lParam);
 static LRESULT EDIT_EM_EmptyUndoBuffer(WND *wndPtr, WPARAM wParam, LPARAM lParam);
@@ -217,6 +218,30 @@
 
 /*********************************************************************
  *
+ *	General shortcuts for variable names:
+ *
+ *	UINT l;		line
+ *	UINT c;		column
+ *	UINT s;		offset of selection start
+ *	UINT e;		offset of selection end
+ *	UINT sl;	line on which the selection starts
+ *	UINT el;	line on which the selection ends
+ *	UINT sc;	column on which the selection starts
+ *	UINT ec;	column on which the selection ends
+ *	UINT li;	line index (offset)
+ *	UINT fv;	first visible line
+ *	UINT vlc;	vissible line count
+ *	UINT lc;	line count
+ *	UINT lh;	line height (in pixels)
+ *	UINT tw;	text width (in pixels)
+ *	UINT ww;	window width (in pixels)
+ *	UINT cw;	character width (average, in pixels)
+ *
+ */
+
+
+/*********************************************************************
+ *
  *	EditWndProc()
  *
  */
@@ -587,7 +612,7 @@
  *	Call appropriate WordBreakProc (internal or external).
  *
  */
-static int EDIT_CallWordBreakProc(WND *wndPtr, char *s, int index, int count, int action)
+static INT EDIT_CallWordBreakProc(WND *wndPtr, char *s, INT index, INT count, INT action)
 {
 	EDITWORDBREAKPROC wbp = (EDITWORDBREAKPROC)EDIT_EM_GetWordBreakProc(wndPtr, 0, 0L);
 
@@ -606,15 +631,15 @@
  *	Calculates, for a given line and X-coordinate on the screen, the column.
  *
  */
-static int EDIT_ColFromWndX(WND *wndPtr, int line, int x)
+static UINT EDIT_ColFromWndX(WND *wndPtr, UINT 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;
+	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
+	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
+	UINT i;
 
-	line = MAX(0, MIN(line, linecount - 1));
-	for (i = 0 ; i < linelength ; i++)
+	line = MAX(0, MIN(line, lc - 1));
+	for (i = 0 ; i < ll ; i++)
 		if (EDIT_WndXFromCol(wndPtr, line, i) >= x)
 			break;
 	return i;
@@ -630,7 +655,7 @@
  */
 static void EDIT_DelEnd(WND *wndPtr)
 {
-	EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(-1, 0));
+	EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
 	EDIT_MoveEnd(wndPtr, TRUE);
 	EDIT_WM_Clear(wndPtr, 0, 0L);
 }
@@ -645,7 +670,7 @@
  */
 static void EDIT_DelLeft(WND *wndPtr)
 {
-	EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(-1, 0));
+	EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
 	EDIT_MoveBackward(wndPtr, TRUE);
 	EDIT_WM_Clear(wndPtr, 0, 0L);
 }
@@ -660,7 +685,7 @@
  */
 static void EDIT_DelRight(WND *wndPtr)
 {
-	EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(-1, 0));
+	EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(-1, 0));
 	EDIT_MoveForward(wndPtr, TRUE);
 	EDIT_WM_Clear(wndPtr, 0, 0L);
 }
@@ -671,7 +696,7 @@
  *	EDIT_GetAveCharWidth
  *
  */
-static int EDIT_GetAveCharWidth(WND *wndPtr)
+static UINT EDIT_GetAveCharWidth(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	
@@ -684,7 +709,7 @@
  *	EDIT_GetLineHeight
  *
  */
-static int EDIT_GetLineHeight(WND *wndPtr)
+static UINT EDIT_GetLineHeight(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	
@@ -700,12 +725,13 @@
  *	column to an ending column.
  *
  */
-static void EDIT_GetLineRect(WND *wndPtr, int line, int scol, int ecol, LPRECT rc)
+static void EDIT_GetLineRect(WND *wndPtr, UINT line, UINT scol, UINT 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);
+	rc->right = ((INT)ecol == -1) ? EDIT_GetWndWidth(wndPtr) :
+				EDIT_WndXFromCol(wndPtr, line, ecol);
 }
 
 
@@ -761,7 +787,7 @@
  *	EDIT_GetTextWidth
  *
  */
-static int EDIT_GetTextWidth(WND *wndPtr)
+static UINT EDIT_GetTextWidth(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	
@@ -774,7 +800,7 @@
  *	EDIT_GetVisibleLineCount
  *
  */
-static int EDIT_GetVisibleLineCount(WND *wndPtr)
+static UINT EDIT_GetVisibleLineCount(WND *wndPtr)
 {
 	RECT rc;
 	
@@ -788,7 +814,7 @@
  *	EDIT_GetWndWidth
  *
  */
-static int EDIT_GetWndWidth(WND *wndPtr)
+static UINT EDIT_GetWndWidth(WND *wndPtr)
 {
 	RECT rc;
 	
@@ -802,7 +828,7 @@
  *	EDIT_GetXOffset
  *
  */
-static int EDIT_GetXOffset(WND *wndPtr)
+static UINT EDIT_GetXOffset(WND *wndPtr)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	
@@ -812,18 +838,91 @@
 
 /*********************************************************************
  *
+ *	EDIT_InvalidateText
+ *
+ *	Invalidate the text from offset start upto, but not including,
+ *	offset end.  Useful for (re)painting the selection.
+ *	Regions outside the linewidth are not invalidated.
+ *	end == -1 means end == TextLength.
+ *	start and end need not be ordered.
+ *
+ */
+static void EDIT_InvalidateText(WND *wndPtr, UINT start, UINT end)
+{
+	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
+	UINT sl;
+	UINT el;
+	UINT sc;
+	UINT ec;
+	RECT rcWnd;
+	RECT rcLine;
+	RECT rcUpdate;
+	UINT line;
+
+	if (end == start )
+		return;
+
+	if ((INT)end == -1)
+		end = (UINT)EDIT_WM_GetTextLength(wndPtr, 0, 0L);
+	ORDER_UINT(start, end);
+	sl = (UINT)EDIT_EM_LineFromChar(wndPtr, start, 0L);
+	el = (UINT)EDIT_EM_LineFromChar(wndPtr, end, 0L);
+	if ((el < fv) || (sl > fv + vlc))
+		return;
+
+	sc = start - (UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L);
+	ec = end - (UINT)EDIT_EM_LineIndex(wndPtr, el, 0L);
+	if (sl < fv) {
+		sl = fv;
+		sc = 0;
+	}
+	if (el > fv + vlc) {
+		el = fv + vlc;
+		ec = (UINT)EDIT_EM_LineLength(wndPtr,
+				(UINT)EDIT_EM_LineIndex(wndPtr, el, 0L), 0L);
+	}
+	EDIT_GetRect(wndPtr, 0, (LPARAM)&rcWnd);
+	if (sl == el) {
+		EDIT_GetLineRect(wndPtr, sl, sc, ec, &rcLine);
+		if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
+			InvalidateRect(wndPtr->hwndSelf, &rcUpdate, FALSE);
+	} else {
+		EDIT_GetLineRect(wndPtr, sl, sc,
+				(UINT)EDIT_EM_LineLength(wndPtr,
+					(UINT)EDIT_EM_LineIndex(wndPtr, sl, 0L), 0L),
+				&rcLine);
+		if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
+			InvalidateRect(wndPtr->hwndSelf, &rcUpdate, FALSE);
+		for (line = sl + 1 ; line < el ; line++) {
+			EDIT_GetLineRect(wndPtr, line, 0,
+				(UINT)EDIT_EM_LineLength(wndPtr,
+					(UINT)EDIT_EM_LineIndex(wndPtr, line, 0L), 0L),
+				&rcLine);
+			if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
+				InvalidateRect(wndPtr->hwndSelf, &rcUpdate, FALSE);
+		}
+		EDIT_GetLineRect(wndPtr, el, 0, ec, &rcLine);
+		if (IntersectRect(&rcUpdate, &rcWnd, &rcLine))
+			InvalidateRect(wndPtr->hwndSelf, &rcUpdate, FALSE);
+	}
+}
+
+
+/*********************************************************************
+ *
  *	EDIT_LineFromWndY
  *
  *	Calculates, for a given Y-coordinate on the screen, the line.
  *
  */
-static int EDIT_LineFromWndY(WND *wndPtr, int y)
+static UINT 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);
+	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	UINT lh = EDIT_GetLineHeight(wndPtr);
+	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
 
-	return MAX(0, MIN(linecount - 1, y / lineheight + firstvis));
+	return MAX(0, MIN(lc - 1, y / lh + fv));
 }
 
 
@@ -831,10 +930,10 @@
  *
  *	EDIT_MakeFit
  *
- *	Try to fit size + 1 bytes in the buffer.  Contrain to limits.
+ *	Try to fit size + 1 bytes in the buffer.  Constrain to limits.
  *
  */
-static BOOL EDIT_MakeFit(WND *wndPtr, int size)
+static BOOL EDIT_MakeFit(WND *wndPtr, UINT size)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
@@ -842,13 +941,17 @@
 		return TRUE;
 	if (size > es->BufLimit)
 		return FALSE;
-	es->BufSize = ((size / GROWLENGTH) + 1) * GROWLENGTH;
-	if (es->BufSize > es->BufLimit)
-		es->BufSize = es->BufLimit;
+	size = ((size / GROWLENGTH) + 1) * GROWLENGTH;
+	if (size > es->BufLimit)
+		size = es->BufLimit;
 
-	dprintf_edit(stddeb, "edit: EDIT_MakeFit: ReAlloc to %d+1\n", es->BufSize);
+	dprintf_edit(stddeb, "edit: EDIT_MakeFit: trying to ReAlloc to %d+1\n", size);
 
-	return LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, es->BufSize + 1, LMEM_MOVEABLE);
+	if (LOCAL_ReAlloc(wndPtr->hInstance, es->hBuf, size + 1, LMEM_MOVEABLE)) {
+		es->BufSize = MIN(LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1, es->BufLimit);
+		return TRUE;
+	} else
+		return FALSE;
 }
 
 
@@ -859,21 +962,21 @@
  */
 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);
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
 
-	if (e - lineindex == 0) {
+	if (e - li == 0) {
 		if (l) {
-			lineindex = EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
-			e = lineindex + EDIT_EM_LineLength(wndPtr, lineindex, 0L);
+			li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
+			e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
 		}
 	} else
 		e--;
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
 }
 
 
@@ -884,22 +987,22 @@
  */
 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;
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
+	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
+	INT x;
 
-	if (l < linecount - 1) {
-		x = EDIT_WndXFromCol(wndPtr, l, e - lineindex);
+	if (l < lc - 1) {
+		x = EDIT_WndXFromCol(wndPtr, l, e - li);
 		l++;
-		e = EDIT_EM_LineIndex(wndPtr, l, 0L) +
+		e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
 				EDIT_ColFromWndX(wndPtr, l, x);
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
 }
 
 
@@ -910,16 +1013,16 @@
  */
 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);
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
+	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
 
-	e = lineindex + linelength;
+	e = li + ll;
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
 }
 
 
@@ -930,21 +1033,21 @@
  */
 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);
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
+	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
+	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
 
-	if (e - lineindex == linelength) {
-		if (l != linecount - 1)
-			e = EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
+	if (e - li == ll) {
+		if (l != lc - 1)
+			e = (UINT)EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
 	} else
 		e++;
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
 }
 
 
@@ -957,15 +1060,15 @@
  */
 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);
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
 
-	e = lineindex;
+	e = li;
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
 }
 
 
@@ -976,22 +1079,22 @@
  */
 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;
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
+	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
+	INT x;
 
-	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) +
+	if (l < lc - 1) {
+		x = EDIT_WndXFromCol(wndPtr, l, e - li);
+		l = MIN(lc - 1, l + EDIT_GetVisibleLineCount(wndPtr));
+		e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
 				EDIT_ColFromWndX(wndPtr, l, x);
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
 }
 
 
@@ -1002,21 +1105,21 @@
  */
 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;
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
+	INT x;
 
 	if (l) {
-		x = EDIT_WndXFromCol(wndPtr, l, e - lineindex);
+		x = EDIT_WndXFromCol(wndPtr, l, e - li);
 		l = MAX(0, l - EDIT_GetVisibleLineCount(wndPtr));
-		e = EDIT_EM_LineIndex(wndPtr, l, 0L) +
+		e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
 				EDIT_ColFromWndX(wndPtr, l, x);
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
 }
 
 
@@ -1027,21 +1130,21 @@
  */
 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;
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
+	INT x;
 
 	if (l) {
-		x = EDIT_WndXFromCol(wndPtr, l, e - lineindex);
+		x = EDIT_WndXFromCol(wndPtr, l, e - li);
 		l--;
-		e = EDIT_EM_LineIndex(wndPtr, l, 0L) +
+		e = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L) +
 				EDIT_ColFromWndX(wndPtr, l, x);
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
 }
 
 
@@ -1052,26 +1155,26 @@
  */
 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);
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
+	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
 	char *text;
 
-	if (e - lineindex == 0) {
+	if (e - li == 0) {
 		if (l) {
-			lineindex = EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
-			e = lineindex + EDIT_EM_LineLength(wndPtr, lineindex, 0L);
+			li = (UINT)EDIT_EM_LineIndex(wndPtr, l - 1, 0L);
+			e = li + (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
 		}
 	} else {
 		text = EDIT_GetPointer(wndPtr);
-		e = lineindex + EDIT_CallWordBreakProc(wndPtr, text + lineindex,
-				e - lineindex, linelength, WB_LEFT);
+		e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
+				text + li, e - li, ll, WB_LEFT);
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
 }
 
 
@@ -1082,25 +1185,25 @@
  */
 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);
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT l = (UINT)EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, e, 0L);
+	UINT ll = (UINT)EDIT_EM_LineLength(wndPtr, e, 0L);
+	UINT li = (UINT)EDIT_EM_LineIndex(wndPtr, l, 0L);
 	char *text;
 
-	if (e - lineindex == linelength) {
-		if (l != linecount - 1)
-			e = EDIT_EM_LineIndex(wndPtr, l + 1, 0L);
+	if (e - li == ll) {
+		if (l != lc - 1)
+			e = (UINT)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);
+		e = li + (UINT)EDIT_CallWordBreakProc(wndPtr,
+				text + li, e - li + 1, ll, WB_RIGHT);
 	}
 	if (!extend)
 		s = e;
-	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
 }
 
 
@@ -1109,44 +1212,40 @@
  *	EDIT_PaintLine
  *
  */
-static void EDIT_PaintLine(WND *wndPtr, HDC hdc, int line)
+static void EDIT_PaintLine(WND *wndPtr, HDC hdc, UINT line, BOOL rev)
 {
-	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;
+	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
+	UINT lc = (UINT)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	UINT li;
+	UINT ll;
+	UINT s;
+	UINT e;
+	INT x;
+	INT y;
 
-	if ((line < firstvis) || (line > firstvis + viscount) || (line >= linecount))
+	if ((line < fv) || (line > fv + vlc) || (line >= lc))
 		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);
+	li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
+	ll = (UINT)EDIT_EM_LineLength(wndPtr, li, 0L);
+	s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	ORDER_UINT(s, e);
+	s = MIN(li + ll, MAX(li, s));
+	e = MIN(li + ll, MAX(li, e));
+	if (rev && (s != e) &&
+			((GetFocus() == wndPtr->hwndSelf) ||
+				(wndPtr->dwStyle & ES_NOHIDESEL))) {
+		x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, s - li, FALSE);
+		x += EDIT_PaintText(wndPtr, hdc, x, y, line, s - li, e - s, TRUE);
+		x += EDIT_PaintText(wndPtr, hdc, x, y, line, e - li, li + ll - e, FALSE);
 	} else
-		x += EDIT_PaintText(wndPtr, hdc, x, y, line,
-				0, LineEnd - LineStart, FALSE);
+		x += EDIT_PaintText(wndPtr, hdc, x, y, line, 0, ll, FALSE);
 }
 
 
@@ -1155,19 +1254,18 @@
  *	EDIT_PaintText
  *
  */
-static int EDIT_PaintText(WND *wndPtr, HDC hdc, int x, int y, int line, int col, int count, BOOL rev)
+static UINT EDIT_PaintText(WND *wndPtr, HDC hdc, INT x, INT y, UINT line, UINT col, UINT count, BOOL rev)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	COLORREF BkColor;
 	COLORREF TextColor;
-	int ret;
+	UINT ret;
 	char *text;
-	int lineindex = EDIT_EM_LineIndex(wndPtr, line, 0L);
-	int xoffset = EDIT_GetXOffset(wndPtr);
+	UINT li;
+	INT xoff;
 
-	if (count < 1)
+	if (!count)
 		return 0;
-		
 	BkColor = GetBkColor(hdc);
 	TextColor = GetTextColor(hdc);
 	if (rev) {
@@ -1175,8 +1273,10 @@
 		SetTextColor(hdc, GetSysColor(COLOR_HIGHLIGHTTEXT));
 	}
 	text = EDIT_GetPointer(wndPtr);
-	ret = LOWORD(TabbedTextOut(hdc, x, y, text + lineindex + col, count,
-					es->NumTabStops, es->TabStops, -xoffset));	
+	li = (UINT)EDIT_EM_LineIndex(wndPtr, line, 0L);
+	xoff = EDIT_GetXOffset(wndPtr);
+	ret = LOWORD(TabbedTextOut(hdc, x, y, text + li + col, count,
+					es->NumTabStops, es->TabStops, -xoff));	
 	if (rev) {
 		SetBkColor(hdc, BkColor);
 		SetTextColor(hdc, TextColor);
@@ -1219,14 +1319,14 @@
 	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));
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
 	int i;
 	char *p;
 	char *text;
 	BOOL redraw;
 
-	ORDER_INT(s,e);
+	ORDER_UINT(s,e);
 	if (!EDIT_MakeFit(wndPtr, tl - (e - s) + strl)) {
 		EDIT_NOTIFY_PARENT(wndPtr, EN_MAXTEXT);
 		return 0L;
@@ -1243,7 +1343,7 @@
 		p[i] = str[i];
 	EDIT_BuildLineDefs(wndPtr);
 	e += strl;
-	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(e, e));
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(e, e));
 	EDIT_EM_SetModify(wndPtr, TRUE, 0L);
 	EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
 	EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
@@ -1264,10 +1364,10 @@
  */
 static void EDIT_ScrollIntoView(WND *wndPtr)
 {
-	int e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT 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 firstvis = (int)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
 	int vislinecount = EDIT_GetVisibleLineCount(wndPtr);
 	int wndwidth = EDIT_GetWndWidth(wndPtr);
 	int charwidth = EDIT_GetAveCharWidth(wndPtr);
@@ -1300,7 +1400,7 @@
  *	Calculates, for a given line and column, the X-coordinate on the screen.
  *
  */
-static int EDIT_WndXFromCol(WND *wndPtr, int line, int col)
+static INT EDIT_WndXFromCol(WND *wndPtr, UINT line, UINT col)
 {	
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	char *text = EDIT_GetPointer(wndPtr);
@@ -1308,7 +1408,7 @@
 	HDC hdc;
 	HFONT hFont;
 	HFONT oldFont = 0;
-	int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	int linecount = (int)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);
@@ -1336,9 +1436,9 @@
  *	Calculates, for a given line, the Y-coordinate on the screen.
  *
  */
-static int EDIT_WndYFromLine(WND *wndPtr, int line)
+static INT EDIT_WndYFromLine(WND *wndPtr, UINT line)
 {
-	int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	int firstvis = (int)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
 	int lineheight = EDIT_GetLineHeight(wndPtr);
 
 	return (line - firstvis) * lineheight;
@@ -1356,7 +1456,7 @@
  *		internally, so we can decide this for ourselves.
  *
  */
-static int EDIT_WordBreakProc(char *s, int index, int count, int action)
+static INT EDIT_WordBreakProc(char *s, INT index, INT count, INT action)
 {
 	int ret = 0;
 
@@ -1481,9 +1581,9 @@
 	char *text;
 	char *src;
 	char *dst;
-	int len;
+	UINT len;
 	int i;
-	int linecount = EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	int linecount = (int)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
 
 	if (!IsMultiLine(wndPtr))
 		wParam = 0;
@@ -1629,7 +1729,7 @@
 		return 0L;
 	if ((INT)wParam == -1)
 		wParam = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
-	l = EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1;
+	l = (int)EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1;
 	while (EDIT_EM_LineIndex(wndPtr, l, 0L) > (UINT)wParam)
 		l--;
 	return (LRESULT)l;
@@ -1644,19 +1744,19 @@
 static LRESULT EDIT_EM_LineIndex(WND *wndPtr, WPARAM wParam, LPARAM lParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	int e;
+	UINT e;
 	int l;
 
-	if ((INT)wParam < 0) {
+	if ((INT)wParam == -1) {
 		e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
-		l = EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1;
-		while (es->LineDefs[l].offset > (UINT)wParam)
+		l = (int)EDIT_EM_GetLineCount(wndPtr, 0, 0L) - 1;
+		while (es->LineDefs[l].offset > e)
 			l--;
 		return (LRESULT)es->LineDefs[l].offset;
 	}
-	if (wParam >= es->LineCount)
+	if ((UINT)wParam >= es->LineCount)
 		return -1L;
-	return (LRESULT)es->LineDefs[wParam].offset;
+	return (LRESULT)es->LineDefs[(UINT)wParam].offset;
 }
 
 
@@ -1668,18 +1768,23 @@
 static LRESULT EDIT_EM_LineLength(WND *wndPtr, WPARAM wParam, LPARAM lParam)
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	int SelStartLine;
-	int SelEndLine;
+	UINT selstart;
+	UINT selend;
+	int startline;
+	int endline;
 
 	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);
+	if ((INT)wParam == -1) {
+		selstart = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+		selend = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+		startline = EDIT_EM_LineFromChar(wndPtr, selstart, 0L);
+		endline = EDIT_EM_LineFromChar(wndPtr, selend, 0L);
+		return (LRESULT)(selstart - es->LineDefs[startline].offset +
+				es->LineDefs[endline].offset +
+				es->LineDefs[endline].length - selend);
+	}
+	return (LRESULT)es->LineDefs[(UINT)EDIT_EM_LineFromChar(wndPtr, wParam, 0L)].length;
 }
  
 
@@ -1691,8 +1796,8 @@
 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 linecount = (int)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	int firstvis = (int)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
 	int newfirstvis = firstvis + (INT)LOWORD(lParam);
 	int xoffset = EDIT_GetXOffset(wndPtr);
 	int newxoffset = xoffset + (INT)HIWORD(lParam);
@@ -1760,6 +1865,7 @@
  *	EM_SCROLL
  *
  *	FIXME: undocumented message.
+ *
  */
 static LRESULT EDIT_EM_Scroll(WND *wndPtr, WPARAM wParam, LPARAM lParam)
 {
@@ -1780,14 +1886,10 @@
 	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 ?
+		 *	old buffer is freed by caller
 		 */
-		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->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
 		es->LineCount = 0;
 		es->FirstVisibleLine = 0;
 		es->SelStart = es->SelEnd = 0;
@@ -1810,7 +1912,7 @@
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-	es->TextChanged = wParam;
+	es->TextChanged = (BOOL)wParam;
 	return 0L;
 }
 
@@ -1876,27 +1978,20 @@
 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;
+	UINT ns = LOWORD(lParam);
+	UINT ne = HIWORD(lParam);
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
 	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;
+	if ((INT)ns == -1) {
 		ns = e;
-	} else {
+		ne = e;
+	}
+	else {
 		ns = MIN(ns, tl);
-		if (ne < 0)
-			ne = tl;
 		ne = MIN(ne, tl);
 	}
 	es->SelStart = ns;
@@ -1907,75 +2002,20 @@
 		SetCaretPos(EDIT_WndXFromCol(wndPtr, el, ne - elineindex),
 				EDIT_WndYFromLine(wndPtr, el));
 	}
-	if (wParam)
+	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);		
+	if (EDIT_GetRedraw(wndPtr)) {
+		ORDER_UINT(s, e);
+		ORDER_UINT(s, ns);
+		ORDER_UINT(s, ne);
+		ORDER_UINT(e, ns);
+		ORDER_UINT(e, ne);
+		ORDER_UINT(ns, ne);
+		if (e != ns) {
+			EDIT_InvalidateText(wndPtr, s, e);
+			EDIT_InvalidateText(wndPtr, ns, ne);
+		} else
+			EDIT_InvalidateText(wndPtr, s, ne);
 	}
 	return -1L;
 }
@@ -1994,13 +2034,13 @@
 		return 0L;
 	if (es->TabStops)
 		free(es->TabStops);
-	es->NumTabStops = wParam;
-	if (wParam == 0)
+	es->NumTabStops = (UINT)wParam;
+	if (!wParam)
 		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));
+		es->TabStops = (LPINT)xmalloc(wParam * sizeof(unsigned short));
+		memcpy(es->TabStops, (LPINT)PTR_SEG_TO_LIN(lParam),
+				(UINT)wParam * sizeof(INT));
 	}
 	return 1L;
 }
@@ -2075,19 +2115,19 @@
  */
 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));
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT 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);
+		ORDER_UINT(s, e);
 		text = EDIT_GetPointer(wndPtr);
 		strcpy(text + s, text + e);
 		EDIT_BuildLineDefs(wndPtr);
-		EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, s));
+		EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, s));
 		EDIT_EM_SetModify(wndPtr, TRUE, 0L);
 		EDIT_NOTIFY_PARENT(wndPtr, EN_UPDATE);
 		EDIT_WM_SetRedraw(wndPtr, redraw, 0L);
@@ -2107,8 +2147,8 @@
  */
 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));
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
 	HGLOBAL hdst;
 	char *text;
 	char *dst;
@@ -2117,7 +2157,7 @@
 
 	if (e == s)
 		return -1L;
-	ORDER_INT(s, e);
+	ORDER_UINT(s, e);
 	hdst = GlobalAlloc(GMEM_MOVEABLE, (DWORD)(e - s + 1));
 	dst = GlobalLock(hdst);
 	text = EDIT_GetPointer(wndPtr);
@@ -2143,37 +2183,12 @@
 {
 	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)
@@ -2184,7 +2199,26 @@
 	if ((cs->style & WS_BORDER) && (cs->style & WS_DLGFRAME))
 		cs->style ^= WS_DLGFRAME;
 
+	if (IsMultiLine(wndPtr)) {
+		es->BufSize = BUFSTART_MULTI;
+		es->BufLimit = BUFLIMIT_MULTI;
+		es->PasswordChar = '\0';
+	} else {
+		es->BufSize = BUFSTART_SINGLE;
+		es->BufLimit = BUFLIMIT_SINGLE;
+		es->PasswordChar = (cs->style & ES_PASSWORD) ? '*' : '\0';
+	}
+	if (!(es->hBuf = LOCAL_Alloc(wndPtr->hInstance, LMEM_MOVEABLE, es->BufSize + 1))) {
+		fprintf(stderr, "edit: WM_CREATE: unable to heap buffer, please report !\n");
+		return -1L;
+	}
+	es->BufSize = LOCAL_Size(wndPtr->hInstance, es->hBuf) - 1;
+	text = EDIT_GetPointer(wndPtr);
+	*text = '\0';
+	EDIT_BuildLineDefs(wndPtr);
 	EDIT_WM_SetFont(wndPtr, 0, 0L);
+	if (cs->lpszName)
+		EDIT_EM_ReplaceSel(wndPtr, FALSE, (LPARAM)cs->lpszName);
 	EDIT_WM_SetRedraw(wndPtr, TRUE, 0L);
 	return 0L;
 }
@@ -2230,6 +2264,7 @@
  */
 static LRESULT EDIT_WM_Enable(WND *wndPtr, WPARAM wParam, LPARAM lParam)
 {
+	EDIT_InvalidateText(wndPtr, 0, -1);
 	return 0L;
 }
 
@@ -2245,6 +2280,8 @@
 	RECT rc;
 
 	hBrush = (HBRUSH)EDIT_SEND_CTLCOLOR(wndPtr, wParam);
+	if (!hBrush)
+		hBrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
 
 	GetClientRect(wndPtr->hwndSelf, &rc);
 	IntersectClipRect((HDC)wParam, rc.left, rc.top, rc.right, rc.bottom);
@@ -2296,7 +2333,7 @@
 	LRESULT lResult = 0L;
 
 	len = strlen(text);
-	if ((int)wParam > len) {
+	if ((UINT)wParam > len) {
 		strcpy((char *)PTR_SEG_TO_LIN(lParam), text);
 		lResult = (LRESULT)len ;
 	}
@@ -2392,8 +2429,8 @@
  */
 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));
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
 	BOOL shift;
 	BOOL control;
 
@@ -2479,9 +2516,15 @@
  */
 static LRESULT EDIT_WM_KillFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam)
 {
+	UINT s;
+	UINT e;
+
 	DestroyCaret();
-	if(!(wndPtr->dwStyle & ES_NOHIDESEL))
-		EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(-1, 0));
+	if(!(wndPtr->dwStyle & ES_NOHIDESEL)) {
+		s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+		e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+		EDIT_InvalidateText(wndPtr, s, e);
+	}
 	EDIT_NOTIFY_PARENT(wndPtr, EN_KILLFOCUS);
 	return 0L;
 }
@@ -2491,19 +2534,21 @@
  *
  *	WM_LBUTTONDBLCLK
  *
+ *	The caret position has been set on the WM_LBUTTONDOWN message
+ *
  */
 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);
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT l = EDIT_EM_LineFromChar(wndPtr, e, 0L);
+	int li = EDIT_EM_LineIndex(wndPtr, l, 0L);
+	int ll = 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));
+	s = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_LEFT);
+	e = li + EDIT_CallWordBreakProc(wndPtr, text + li, e - li, ll, WB_RIGHT);
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
 	return 0L;
 }
 
@@ -2515,20 +2560,28 @@
  */
 static LRESULT EDIT_WM_LButtonDown(WND *wndPtr, WPARAM wParam, LPARAM lParam)
 {
-	int l;
-	int s;
-	int e;
+	INT x = (INT)LOWORD(lParam);
+	INT y = (INT)HIWORD(lParam);
+	UINT l = EDIT_LineFromWndY(wndPtr, y);
+	UINT c;
+	UINT s;
+	UINT e;
+	UINT fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	UINT vlc = EDIT_GetVisibleLineCount(wndPtr);
+	UINT li;
 
 	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));
+	l = MIN(fv + vlc - 1, MAX(fv, l));
+	x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
+	c = EDIT_ColFromWndX(wndPtr, l, x);
+	li = EDIT_EM_LineIndex(wndPtr, l, 0L);
+	e = li + c;
 	if (GetKeyState(VK_SHIFT) & 0x8000)
 		s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
 	else 
 		s = e;
-	EDIT_EM_SetSel(wndPtr, TRUE, MAKELPARAM(s, e));
+	EDIT_EM_SetSel(wndPtr, 0, MAKELPARAM(s, e));
 	return 0L;
 }
 
@@ -2553,19 +2606,27 @@
  */
 static LRESULT EDIT_WM_MouseMove(WND *wndPtr, WPARAM wParam, LPARAM lParam)
 {
-	EDITSTATE *es = EDITSTATEPTR(wndPtr);
-	int Line;
-	int Col;
-	int x = (INT)LOWORD(lParam);
+	INT x;
+	INT y;
+	UINT l;
+	UINT c;
+	UINT s;
+	UINT fv;
+	UINT vlc;
+	UINT li;
 
 	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 = (INT)LOWORD(lParam);
+		y = (INT)HIWORD(lParam);
+		fv = (UINT)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+		vlc = EDIT_GetVisibleLineCount(wndPtr);
+		l = EDIT_LineFromWndY(wndPtr, y);
+		l = MIN(fv + vlc - 1, MAX(fv, l));
 		x = MIN(EDIT_GetWndWidth(wndPtr), MAX(0, x));
-		Col = EDIT_ColFromWndX(wndPtr, Line, x);
-		EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(es->SelStart,
-				EDIT_EM_LineIndex(wndPtr, Line, 0L) + Col));
+		c = EDIT_ColFromWndX(wndPtr, l, x);
+		s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+		li = EDIT_EM_LineIndex(wndPtr, l, 0L);
+		EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, li + c));
 	}
 	return 0L;
 }
@@ -2581,13 +2642,16 @@
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 	PAINTSTRUCT ps;
 	int i;
-	int firstvis = EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
+	int firstvis = (int)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
 	HDC hdc;
 	HFONT hFont;
 	HFONT oldFont = 0;
 	RECT rc;
 	RECT rcLine;
 	RECT rcRgn;
+	BOOL rev = IsWindowEnabled(wndPtr->hwndSelf) &&
+				((GetFocus() == wndPtr->hwndSelf) ||
+					(wndPtr->dwStyle & ES_NOHIDESEL));
 
 	hdc = BeginPaint(wndPtr->hwndSelf, &ps);
 	GetClientRect(wndPtr->hwndSelf, &rc);
@@ -2596,11 +2660,13 @@
 	if (hFont)
 		oldFont = SelectObject(hdc, hFont);
 	EDIT_SEND_CTLCOLOR(wndPtr, hdc);
+	if (!IsWindowEnabled(wndPtr->hwndSelf))
+		SetTextColor(hdc, GetSysColor(COLOR_GRAYTEXT));
 	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);
+			EDIT_PaintLine(wndPtr, hdc, i, rev);
 	}
 	if (hFont)
 		SelectObject(hdc, oldFont);
@@ -2652,10 +2718,13 @@
  */
 static LRESULT EDIT_WM_SetFocus(WND *wndPtr, WPARAM wParam, LPARAM lParam)
 {
-	LPARAM sel = EDIT_EM_GetSel(wndPtr, 0, 0L);
+	UINT s = LOWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
+	UINT e = HIWORD(EDIT_EM_GetSel(wndPtr, 0, 0L));
 
 	CreateCaret(wndPtr->hwndSelf, 0, 2, EDIT_GetLineHeight(wndPtr));
-	EDIT_EM_SetSel(wndPtr, FALSE, sel);
+	EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(s, e));
+	if(!(wndPtr->dwStyle & ES_NOHIDESEL))
+		EDIT_InvalidateText(wndPtr, s, e);
 	ShowCaret(wndPtr->hwndSelf);
 	EDIT_NOTIFY_PARENT(wndPtr, EN_SETFOCUS);
 	return 0L;
@@ -2686,12 +2755,12 @@
 		SelectObject(hdc, oldFont);
 	ReleaseDC(wndPtr->hwndSelf, hdc);
 	EDIT_BuildLineDefs(wndPtr);
-	if (lParam && EDIT_GetRedraw(wndPtr))
+	if ((BOOL)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);
+		EDIT_EM_SetSel(wndPtr, 1, sel);
 		ShowCaret(wndPtr->hwndSelf);
 	}
 	return 0L;
@@ -2707,7 +2776,7 @@
 {
 	EDITSTATE *es = EDITSTATEPTR(wndPtr);
 
-	es->Redraw = wParam ? TRUE : FALSE;
+	es->Redraw = (BOOL)wParam;
 	return 0L;
 }
 
@@ -2719,7 +2788,7 @@
  */
 static LRESULT EDIT_WM_SetText(WND *wndPtr, WPARAM wParam, LPARAM lParam)
 {
-	EDIT_EM_SetSel(wndPtr, FALSE, MAKELPARAM(0, -1));
+	EDIT_EM_SetSel(wndPtr, 1, MAKELPARAM(0, -1));
 	EDIT_WM_Clear(wndPtr, 0, 0L);
 	if (lParam)
 		EDIT_EM_ReplaceSel(wndPtr, 0, lParam);
@@ -2738,8 +2807,11 @@
 {
 	if (EDIT_GetRedraw(wndPtr) &&
 			((wParam == SIZE_MAXIMIZED) ||
-				(wParam == SIZE_RESTORED)))
+				(wParam == SIZE_RESTORED))) {
+		if (IsMultiLine(wndPtr) && IsWordWrap(wndPtr))
+			EDIT_BuildLineDefs(wndPtr);
 		InvalidateRect(wndPtr->hwndSelf, NULL, TRUE);
+	}
 	return 0L;
 }
 
@@ -2753,8 +2825,8 @@
  */
 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 linecount = (int)EDIT_EM_GetLineCount(wndPtr, 0, 0L);
+	int firstvis = (int)EDIT_EM_GetFirstVisibleLine(wndPtr, 0, 0L);
 	int vislinecount = EDIT_GetVisibleLineCount(wndPtr);
 	int dy = 0;
 	BOOL not = TRUE;
diff --git a/controls/menu.c b/controls/menu.c
index 7f09a8ea..78e991d 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -2227,8 +2227,9 @@
 	    lpmenu->wFlags &= ~MF_POPUP;  /* Can't be a popup */
 	    lpmenu->Height = 0;  /* Make sure we recalculate the size */
 	}
-	SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
-		      SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+        if (IsWindowVisible(hWnd))
+            SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
+                          SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
 	return TRUE;
 }
 
diff --git a/controls/scroll.c b/controls/scroll.c
index 9824b3b..27323a6 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -94,14 +94,12 @@
     hRgArrowI = LoadBitmap((HINSTANCE)NULL, MAKEINTRESOURCE(OBM_RGARROWI));
 }
 
-
 /***********************************************************************
- *           SCROLL_GetScrollInfo
+ *           SCROLL_GetPtrScrollInfo
  */
-static SCROLLINFO *SCROLL_GetScrollInfo( HWND hwnd, int nBar )
+static SCROLLINFO *SCROLL_GetPtrScrollInfo( WND* wndPtr, int nBar )
 {
     HANDLE handle;
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
 
     if (!wndPtr) return NULL;
     switch(nBar)
@@ -128,6 +126,15 @@
     return (SCROLLINFO *) USER_HEAP_LIN_ADDR( handle );
 }
 
+/***********************************************************************
+ *           SCROLL_GetScrollInfo
+ */
+static SCROLLINFO *SCROLL_GetScrollInfo( HWND hwnd, int nBar )
+{
+   WND *wndPtr = WIN_FindWndPtr( hwnd );
+   return SCROLL_GetPtrScrollInfo( wndPtr, nBar );
+}
+
 
 /***********************************************************************
  *           SCROLL_GetScrollBarRect
@@ -188,7 +195,7 @@
     
     if ((pixels -= 3*SYSMETRICS_CXVSCROLL+1) > 0)
     {
-        SCROLLINFO *info = SCROLL_GetScrollInfo( hwnd, nBar );
+        SCROLLINFO *info = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
         if ((info->flags & ESB_DISABLE_BOTH) == ESB_DISABLE_BOTH)
             *thumbPos = 0;
         else if (info->MinVal == info->MaxVal)
@@ -449,7 +456,7 @@
     RECT rect;
     BOOL vertical;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
-    SCROLLINFO *infoPtr = SCROLL_GetScrollInfo( hwnd, nBar );
+    SCROLLINFO *infoPtr = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
 
     if (!wndPtr || !infoPtr ||
         ((nBar == SB_VERT) && !(wndPtr->dwStyle & WS_VSCROLL)) ||
@@ -480,7 +487,7 @@
     BOOL vertical;
     HDC hdc;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
-    SCROLLINFO *infoPtr = SCROLL_GetScrollInfo( hwnd, nBar );
+    SCROLLINFO *infoPtr = SCROLL_GetPtrScrollInfo( wndPtr, nBar );
 
     if (!wndPtr || !infoPtr ||
         ((nBar == SB_VERT) && !(wndPtr->dwStyle & WS_VSCROLL)) ||
@@ -913,6 +920,38 @@
     if (bRedraw) SCROLL_RefreshScrollBar( hwnd, nBar );
 }
 
+/*************************************************************************
+ *	     SCROLL_SetNCSbState
+ *
+ * This is for CalcChildScroll in windows/mdi.c
+ */
+DWORD SCROLL_SetNCSbState(WND* wndPtr, int vMin, int vMax, int vPos,
+				       int hMin, int hMax, int hPos)
+{
+  SCROLLINFO  *infoPtr = SCROLL_GetPtrScrollInfo(wndPtr, SB_VERT);
+ 
+  wndPtr->dwStyle |= (WS_VSCROLL | WS_HSCROLL);
+
+  if( vMin >= vMax ) 
+    { vMin = vMax;
+      wndPtr->dwStyle &= ~WS_VSCROLL; }
+  if( vPos > vMax ) vPos = vMax; else if( vPos < vMin ) vPos = vMin;
+  infoPtr->MinVal = vMin;
+  infoPtr->MaxVal = vMax;
+  infoPtr->CurVal = vPos;
+
+  infoPtr = SCROLL_GetPtrScrollInfo(wndPtr, SB_HORZ);
+
+  if( hMin >= hMax )
+    { hMin = hMax;
+      wndPtr->dwStyle &= ~WS_HSCROLL; }
+  if( hPos > hMax ) hPos = hMax; else if( hPos < hMin ) hPos = hMin;
+  infoPtr->MinVal = hMin;
+  infoPtr->MaxVal = hMax;
+  infoPtr->CurVal = hPos;
+
+  return wndPtr->dwStyle & (WS_VSCROLL | WS_HSCROLL);
+}
 
 /*************************************************************************
  *           GetScrollRange   (USER.65)
diff --git a/if1632/Makefile.in b/if1632/Makefile.in
index d55fe40..288e84a 100644
--- a/if1632/Makefile.in
+++ b/if1632/Makefile.in
@@ -34,6 +34,7 @@
 	toolhelp.spec \
 	user.spec \
 	user32.spec \
+	w32sys.spec \
 	win87em.spec \
 	winprocs.spec \
 	winprocs32.spec \
diff --git a/if1632/commdlg.spec b/if1632/commdlg.spec
index c579065..0f5dc75 100644
--- a/if1632/commdlg.spec
+++ b/if1632/commdlg.spec
@@ -13,10 +13,10 @@
 12  pascal16 ReplaceText(ptr) ReplaceText
 13  pascal   FindTextDlgProc(word word word long) FindTextDlgProc
 14  pascal   ReplaceTextDlgProc(word word word long) ReplaceTextDlgProc
-15  stub ChooseFont
-#16  pascal  FORMATCHARDLGPROC exported, shared data
-#18  pascal  FONTSTYLEENUMPROC exported, shared data
-#19  pascal  FONTFAMILYENUMPROC exported, shared data
+15  pascal16 ChooseFont(ptr) ChooseFont
+16  pascal16 FormatCharDlgProc(word word word long) FormatCharDlgProc
+18  pascal16 FontStyleEnumProc(ptr ptr word long)   FontStyleEnumProc
+19  pascal16 FontFamilyEnumProc(ptr ptr word long)  FontFamilyEnumProc
 20  pascal16 PrintDlg(ptr) PrintDlg
 21  pascal   PrintDlgProc(word word word long) PrintDlgProc
 22  pascal   PrintSetupDlgProc(word word word long) PrintSetupDlgProc
diff --git a/if1632/gdi.spec b/if1632/gdi.spec
index 08d7d6a..cbd75d0 100644
--- a/if1632/gdi.spec
+++ b/if1632/gdi.spec
@@ -136,7 +136,7 @@
 148 pascal SetBrushOrg(word s_word s_word) SetBrushOrg
 149 pascal GetBrushOrg(word) GetBrushOrg
 150 pascal16 UnrealizeObject(word) UnrealizeObject
-151 stub CopyMetaFile
+151 pascal16 CopyMetaFile(word ptr) CopyMetaFile
 153 pascal16 CreateIC(ptr ptr ptr ptr) CreateIC
 154 pascal GetNearestColor(word long) GetNearestColor
 155 stub QueryAbort
@@ -150,7 +150,7 @@
 170 stub SetDCStatus
 172 pascal16 SetRectRgn(word s_word s_word s_word s_word) SetRectRgn
 173 pascal16 GetClipRgn(word) GetClipRgn
-175 stub EnumMetaFile
+175 pascal16 EnumMetaFile(word word segptr long) EnumMetaFile
 176 pascal16 PlayMetaFileRecord(word ptr ptr word) PlayMetaFileRecord
 179 pascal16 GetDCState(word) GetDCState
 180 pascal16 SetDCState(word word) SetDCState
diff --git a/if1632/relay.c b/if1632/relay.c
index 9daacc1..1197af7 100644
--- a/if1632/relay.c
+++ b/if1632/relay.c
@@ -52,6 +52,7 @@
     DLL_ENTRY( WINPROCS,   DLL_FLAG_ALWAYS_USED),
     DLL_ENTRY( DDEML,      DLL_FLAG_NOT_USED),
     DLL_ENTRY( LZEXPAND,   0),
+    DLL_ENTRY( W32SYS,     0),
     /* Win32 DLLs */
     DLL_ENTRY( ADVAPI32,   0),
     DLL_ENTRY( COMCTL32,   0),
diff --git a/if1632/w32sys.spec b/if1632/w32sys.spec
new file mode 100644
index 0000000..04dd968
--- /dev/null
+++ b/if1632/w32sys.spec
@@ -0,0 +1,16 @@
+name	w32sys
+type	win16
+id	27
+
+#1 WEP
+2 stub ISPEFORMAT
+3 stub EXECPE
+4 stub GETPEEXEINFO
+5 stub GETW32SYSVERSION
+6 stub LOADPERESOURCE
+7 stub GETPERESOURCETABLE
+8 stub EXECPEEX
+9 stub ITSME
+10 stub W32SERROR
+11 stub EXP1
+12 pascal16 GetWin32sInfo(ptr) GetWin32sInfo
diff --git a/if1632/winprocs.spec b/if1632/winprocs.spec
index 62274e8..056c9f6 100644
--- a/if1632/winprocs.spec
+++ b/if1632/winprocs.spec
@@ -31,7 +31,10 @@
 27 pascal EntryAddrProc(word word) MODULE_GetEntryPoint
 28 pascal MyAlloc(word word word) MODULE_AllocateSegment
 29 pascal16 ActivateAppProc(word long) ACTIVATEAPP_callback
-
+30 pascal FormatCharDlgProc(word word word long) FormatCharDlgProc
+31 pascal16 FontStyleEnumProc(ptr ptr word long)   FontStyleEnumProc
+32 pascal16 FontFamilyEnumProc(ptr ptr word long)  FontFamilyEnumProc
+ 
 # Interrupt vectors 0-255 are ordinals 100-355
 # The 'word' parameter are the flags pushed on the stack by the interrupt
 100 register INT_Int00Handler(word) INT_DummyHandler
diff --git a/include/commdlg.h b/include/commdlg.h
index f51e4b6..384b0b4 100644
--- a/include/commdlg.h
+++ b/include/commdlg.h
@@ -298,6 +298,7 @@
 BOOL  GetSaveFileName(LPOPENFILENAME lpofn);
 BOOL  PrintDlg(LPPRINTDLG lpPrint);
 BOOL  ReplaceText(LPFINDREPLACE lpFind);
+BOOL  ChooseFont(LPCHOOSEFONT lpChFont);
 
 LRESULT FileOpenDlgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
 LRESULT FileSaveDlgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
@@ -306,6 +307,7 @@
 LRESULT ReplaceTextDlgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
 LRESULT PrintDlgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
 LRESULT PrintSetupDlgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
+LRESULT FormatCharDlgProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam);
 
 #endif 		/* #ifdef COMMDLG_H */
 
diff --git a/include/dlls.h b/include/dlls.h
index 304b142..70d34cc 100644
--- a/include/dlls.h
+++ b/include/dlls.h
@@ -57,6 +57,7 @@
 DECLARE_DLL(WINPROCS)
 DECLARE_DLL(DDEML)
 DECLARE_DLL(LZEXPAND)
+DECLARE_DLL(W32SYS)
 
 /* 32-bit DLLs */
 
diff --git a/include/local.h b/include/local.h
index d3f12f7..bfc6f12 100644
--- a/include/local.h
+++ b/include/local.h
@@ -20,6 +20,7 @@
 extern WORD LOCAL_Size( HANDLE ds, HLOCAL handle );
 extern WORD LOCAL_Flags( HANDLE ds, HLOCAL handle );
 extern WORD LOCAL_HeapSize( HANDLE ds );
+extern WORD LOCAL_CountFree( WORD ds );
 extern LPSTR LOCAL_Lock( HANDLE ds, HLOCAL handle );
 extern BOOL LOCAL_Unlock( HANDLE ds, HLOCAL handle );
 
diff --git a/include/mdi.h b/include/mdi.h
index a34c1d0..99d7974 100644
--- a/include/mdi.h
+++ b/include/mdi.h
@@ -37,7 +37,7 @@
     HMENU  hWindowMenu;
     WORD   idFirstChild;       /* order is 3.1-like up to this point */
     HANDLE hFrameTitle;
-    WORD   sbStop;
+    WORD   sbNeedUpdate;
     WORD   sbRecalc;
     HBITMAP obmClose;
     HBITMAP obmRestore;
diff --git a/include/metafile.h b/include/metafile.h
index 2c56e34..c83afcb 100644
--- a/include/metafile.h
+++ b/include/metafile.h
@@ -13,19 +13,7 @@
 #define MFVERSION 0x300
 #define META_EOF 0x0000
 
-typedef struct tagMETAFILE
-{
-    WORD   wMagic;	    /* `PO' */
-    char   Filename[80];    /* metafile name, if disk based */
-    int    hFile;           /* MSDOS file handle for metafile */
-    HANDLE hMetaHdr;	    /* handle of metafile header */
-    int    MetaOffset;      /* offset of current record in metafile */
-    HANDLE hBuffer;	    /* handle of buffer for disk based metafiles */
-} METAFILE;
-typedef METAFILE *LPMETAFILE;
-
-
-BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen);
+HMETAFILE MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen);
 int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj);
 int MF_AddHandleInternal(HANDLE hobj);
 BOOL MF_MetaParam0(DC *dc, short func);
diff --git a/include/options.h b/include/options.h
index c1b6f0e..9f6a1db 100644
--- a/include/options.h
+++ b/include/options.h
@@ -22,6 +22,8 @@
     LANG_It   /* Italian */
 } WINE_LANGUAGE;
 
+extern const char *langNames[];
+
 /* Supported modes */
 typedef enum
 {
diff --git a/include/w32sys.h b/include/w32sys.h
new file mode 100644
index 0000000..6388b6c
--- /dev/null
+++ b/include/w32sys.h
@@ -0,0 +1,17 @@
+/*
+ * W32SYS
+ * 
+ * Copyright (c) 1996 Anand Kumria
+ */
+
+#ifndef __WINE__W32SYS_H
+#define __WINE__W32SYS_H
+
+typedef struct _WIN32SINFO {
+    BYTE bMajor;
+    BYTE bMinor;
+    WORD wBuildNumber;
+    BOOL fDebug;
+} WIN32SINFO, *LPWIN32SINFO;
+
+#endif /* __WINE_W32SYS_H */
diff --git a/include/windows.h b/include/windows.h
index c25d916..5ad16fb 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -2322,6 +2322,8 @@
 #define LMEM_ZEROINIT       0x0040
 #define LMEM_MODIFY         0x0080
 #define LMEM_DISCARDABLE    0x0F00
+#define LMEM_DISCARDED	    0x4000
+#define LMEM_LOCKCOUNT	    0x00FF
 
 #define GMEM_FIXED          0x0000
 #define GMEM_MOVEABLE       0x0002
diff --git a/include/winpos.h b/include/winpos.h
index 455cce8..4ec7319 100644
--- a/include/winpos.h
+++ b/include/winpos.h
@@ -11,6 +11,10 @@
 
 #define DWP_MAGIC  0x5057  /* 'WP' */
 
+/* undocumented SWP flags - from SDK 3.1 */
+#define SWP_NOCLIENTSIZE	0x0800
+#define SWP_NOCLIENTMOVE	0x1000
+
 typedef struct
 {
     WORD        actualCount;
diff --git a/include/winreg.h b/include/winreg.h
index 01c60a0..d8e23b0 100644
--- a/include/winreg.h
+++ b/include/winreg.h
@@ -89,6 +89,7 @@
 	LPWSTR	name;	/* name of value (UNICODE) or NULL for win31 */
 	DWORD	type;	/* type of value */
 	DWORD	len;	/* length of data */
+	DWORD	lastmodified; /* time of seconds since 1.1.1970 */
 	LPBYTE	data;	/* content, may be strings, binaries, etc. */
 } KEYVALUE,*LPKEYVALUE;
 
diff --git a/memory/local.c b/memory/local.c
index 96fa999..b4aba40 100644
--- a/memory/local.c
+++ b/memory/local.c
@@ -47,6 +47,12 @@
 #define LOCAL_ARENA_FIXED      1
 #define LOCAL_ARENA_MOVEABLE   3
 
+/* Layout of a handle entry table
+ *
+ * WORD                     count of entries
+ * LOCALHANDLEENTRY[count]  entries
+ * WORD                     near ptr to next table
+ */
 typedef struct
 {
     WORD addr;                /* Address of the MOVEABLE block */
@@ -56,26 +62,26 @@
 
 typedef struct
 {
-    WORD check;               /* Heap checking flag */
-    WORD freeze;              /* Heap frozen flag */
-    WORD items;               /* Count of items on the heap */
-    WORD first;               /* First item of the heap */
-    WORD pad1;                /* Always 0 */
-    WORD last;                /* Last item of the heap */
-    WORD pad2;                /* Always 0 */
-    BYTE ncompact;            /* Compactions counter */
-    BYTE dislevel;            /* Discard level */
-    DWORD distotal;           /* Total bytes discarded */
-    WORD htable;              /* Pointer to handle table */
-    WORD hfree;               /* Pointer to free handle table */
-    WORD hdelta;              /* Delta to expand the handle table */
-    WORD expand;              /* Pointer to expand function (unused) */
-    WORD pstat;               /* Pointer to status structure (unused) */
-    DWORD notify WINE_PACKED; /* Pointer to LocalNotify() function */
-    WORD lock;                /* Lock count for the heap */
-    WORD extra;               /* Extra bytes to allocate when expanding */
-    WORD minsize;             /* Minimum size of the heap */
-    WORD magic;               /* Magic number */
+    WORD check;                 /* 00 Heap checking flag */
+    WORD freeze;                /* 02 Heap frozen flag */
+    WORD items;                 /* 04 Count of items on the heap */
+    WORD first;                 /* 06 First item of the heap */
+    WORD pad1;                  /* 08 Always 0 */
+    WORD last;                  /* 0a Last item of the heap */
+    WORD pad2;                  /* 0c Always 0 */
+    BYTE ncompact;              /* 0e Compactions counter */
+    BYTE dislevel;              /* 0f Discard level */
+    DWORD distotal;             /* 10 Total bytes discarded */
+    WORD htable;                /* 14 Pointer to handle table */
+    WORD hfree;                 /* 16 Pointer to free handle table */
+    WORD hdelta;                /* 18 Delta to expand the handle table */
+    WORD expand;                /* 1a Pointer to expand function (unused) */
+    WORD pstat;                 /* 1c Pointer to status structure (unused) */
+    FARPROC notify WINE_PACKED; /* 1e Pointer to LocalNotify() function */
+    WORD lock;                  /* 22 Lock count for the heap */
+    WORD extra;                 /* 24 Extra bytes to allocate when expanding */
+    WORD minsize;               /* 26 Minimum size of the heap */
+    WORD magic;                 /* 28 Magic number */
 } LOCALHEAPINFO;
 
 #ifndef WINELIB
@@ -455,8 +461,9 @@
     WORD arena;
     WORD freespace = 0;
     
-    if (!(pInfo = LOCAL_GetHeap( ds ))) {
-	dprintf_local( stddeb, "Local_FindFreeBlock: Local heap not found\n" );
+    if (!(pInfo = LOCAL_GetHeap( ds )))
+    {
+        fprintf( stderr, "Local_FindFreeBlock: Local heap not found\n" );
 	LOCAL_PrintHeap(ds);
 	return 0;
     }
@@ -468,6 +475,11 @@
         pArena = ARENA_PTR( ptr, arena );
         if (pArena->size >= freespace) freespace = pArena->size;
     }
+
+    if(freespace < ARENA_HEADER_SIZE)
+	freespace = 0;
+    else
+	freespace -= ARENA_HEADER_SIZE;
     
     if (flags & LMEM_NOCOMPACT) return freespace;
     
@@ -485,8 +497,9 @@
     LOCALARENA *pArena;
     WORD arena;
 
-    if (!(pInfo = LOCAL_GetHeap( ds ))) {
-	dprintf_local( stddeb, "Local_FindFreeBlock: Local heap not found\n" );
+    if (!(pInfo = LOCAL_GetHeap( ds )))
+    {
+        fprintf( stderr, "Local_FindFreeBlock: Local heap not found\n" );
 	LOCAL_PrintHeap(ds);
 	return 0;
     }
@@ -516,8 +529,9 @@
     LOCALARENA *pArena;
     WORD arena;
 
-    if (!(pInfo = LOCAL_GetHeap( ds ))) {
-	dprintf_local( stddeb, "Local_GetBlock: Local heap not found\n");
+    if (!(pInfo = LOCAL_GetHeap( ds )))
+    {
+        fprintf( stderr, "Local_GetBlock: Local heap not found\n");
 	LOCAL_PrintHeap(ds);
 	return 0;
     }
@@ -540,7 +554,8 @@
 	arena = LOCAL_FindFreeBlock( ds, size );
     }
     if (arena == 0) {
-	fprintf( stderr, "Local_GetBlock: not enough space!\n" );
+	fprintf( stderr, "Local_GetBlock: not enough space in heap %04x for %d bytes\n",
+                 ds, size );
 	return 0;
     }
 
@@ -564,6 +579,7 @@
     return arena + ARENA_HEADER_SIZE;
 }
 
+
 /***********************************************************************
  *           LOCAL_NewHTable
  */
@@ -571,56 +587,82 @@
 {
     char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
     LOCALHEAPINFO *pInfo;
+    LOCALHANDLEENTRY *pEntry;
     HLOCAL handle;
+    int i;
 
     dprintf_local( stddeb, "Local_NewHTable\n" );
-    if (!(pInfo = LOCAL_GetHeap( ds ))) {
-      dprintf_local( stddeb, "Local heap not found\n");
-      LOCAL_PrintHeap(ds);
-      return FALSE;
+    if (!(pInfo = LOCAL_GetHeap( ds )))
+    {
+        fprintf( stderr, "Local heap not found\n");
+        LOCAL_PrintHeap(ds);
+        return FALSE;
     }
 
-    handle = LOCAL_GetBlock( ds, pInfo->hdelta*4 + 2, LMEM_FIXED );
+    handle = LOCAL_GetBlock( ds, pInfo->hdelta * sizeof(LOCALHANDLEENTRY)
+                                  + 2 * sizeof(WORD), LMEM_FIXED );
     ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
     pInfo = LOCAL_GetHeap( ds );
     if (handle == 0) return FALSE;
-    *(WORD *)(ptr + handle) = 0; /* no handles in this block yet */
+
+    /* Fill the entry table */
+
+    *(WORD *)(ptr + handle) = pInfo->hdelta;
+    pEntry = (LOCALHANDLEENTRY *)(ptr + handle + sizeof(WORD));
+    for (i = pInfo->hdelta; i > 0; i--) (pEntry++)->lock = 0xff;
+    *(WORD *)pEntry = pInfo->htable;
     pInfo->htable = handle;
     return TRUE;
 }
 
+
 /***********************************************************************
- *           LOCAL_GetNewHandle
+ *           LOCAL_GetNewHandleEntry
  */
-static HLOCAL LOCAL_GetNewHandle( WORD ds )
+static HLOCAL LOCAL_GetNewHandleEntry( WORD ds )
 {
     char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
     LOCALHEAPINFO *pInfo;
-    WORD count;
-    
-    if (!(pInfo = LOCAL_GetHeap( ds ))) {
-	dprintf_local( stddeb, "LOCAL_GetNewHandle: Local heap not found\n");
+    LOCALHANDLEENTRY *pEntry = NULL;
+    WORD table;
+
+    if (!(pInfo = LOCAL_GetHeap( ds )))
+    {
+        fprintf( stderr, "LOCAL_GetNewHandleEntry: Local heap not found\n");
 	LOCAL_PrintHeap(ds);
 	return 0;
     }
-    /* Check if we need a new handle table */
-    if (pInfo->htable == 0)  {
-        if (!LOCAL_NewHTable( ds )) return 0;
-	ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
-	pInfo = LOCAL_GetHeap( ds );
-    }
-    if (*(WORD *)(ptr + pInfo->htable) == pInfo->hdelta) {
-        if (!LOCAL_NewHTable( ds )) return 0;
-	ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
-	pInfo = LOCAL_GetHeap( ds );
+
+    /* Find a free slot in existing tables */
+
+    table = pInfo->htable;
+    while (table)
+    {
+        WORD count = *(WORD *)(ptr + table);
+        pEntry = (LOCALHANDLEENTRY *)(ptr + table + sizeof(WORD));
+        for (; count > 0; count--, pEntry++)
+            if (pEntry->lock == 0xff) break;
+        if (count) break;
+        table = *(WORD *)pEntry;
     }
 
-    /* increase count */
-    count = (*(WORD *)(ptr + pInfo->htable))++;
-    dprintf_local( stddeb, "Local_GetNewHandle: %04x\n", pInfo->htable + 2 + 4*count );
-    return pInfo->htable + 2 + 4*count;
+    if (!table)  /* We need to create a new table */
+    {
+        if (!LOCAL_NewHTable( ds )) return 0;
+	ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
+	pInfo = LOCAL_GetHeap( ds );
+        pEntry = (LOCALHANDLEENTRY *)(ptr + pInfo->htable + sizeof(WORD));
+    }
+
+    /* Now allocate this entry */
+
+    pEntry->lock = 0;
+    dprintf_local( stddeb, "LOCAL_GetNewHandleEntry(%04x): %04x\n",
+                   ds, ((char *)pEntry - ptr) );
+    return (HLOCAL)((char *)pEntry - ptr);
 }
 
+
 /***********************************************************************
  *           LOCAL_FreeArena
  */
@@ -634,9 +676,11 @@
     if (!(pInfo = LOCAL_GetHeap( ds ))) return arena;
 
     pArena = ARENA_PTR( ptr, arena );
-    if ((pArena->prev & 3) == LOCAL_ARENA_FREE) {
+    if ((pArena->prev & 3) == LOCAL_ARENA_FREE)
+    {
 	/* shouldn't happen */
-	fprintf( stderr, "LocalFreeArena: Trying to free a block twice!\n" );
+        fprintf( stderr, "LocalFreeArena: Trying to free block %04x twice!\n",
+                 arena );
 	LOCAL_PrintHeap( ds );
 	return arena;
     }
@@ -670,6 +714,59 @@
 
 
 /***********************************************************************
+ *           LOCAL_FreeHandleEntry
+ *
+ * Free a handle table entry.
+ */
+static void LOCAL_FreeHandleEntry( WORD ds, HLOCAL handle )
+{
+    char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
+    LOCALHANDLEENTRY *pEntry = (LOCALHANDLEENTRY *)(ptr + handle);
+    LOCALHEAPINFO *pInfo;
+    WORD *pTable;
+    WORD table, count, i;
+
+    if (!(pInfo = LOCAL_GetHeap( ds ))) return;
+
+    /* Find the table where this handle comes from */
+
+    pTable = &pInfo->htable;
+    while (*pTable)
+    {
+        WORD size = (*(WORD *)(ptr + *pTable)) * sizeof(LOCALHANDLEENTRY);
+        if ((handle >= *pTable + sizeof(WORD)) &&
+            (handle < *pTable + sizeof(WORD) + size)) break;  /* Found it */
+        pTable = (WORD *)(ptr + *pTable + sizeof(WORD) + size);
+    }
+    if (!*pTable)
+    {
+        fprintf(stderr, "LOCAL_FreeHandleEntry: invalid entry %04x\n", handle);
+        LOCAL_PrintHeap( ds );
+        return;
+    }
+
+    /* Make the entry free */
+
+    pEntry->addr = 0;  /* just in case */
+    pEntry->lock = 0xff;
+
+    /* Now check if all entries in this table are free */
+
+    pEntry = (LOCALHANDLEENTRY *)(ptr + *pTable + sizeof(WORD));
+    count = *(WORD *)(ptr + *pTable);
+    for (i = count; i > 0; i--, pEntry++) if (pEntry->lock != 0xff) return;
+    
+    /* Remove the table from the linked list and free it */
+
+    table = *pTable;
+    dprintf_local( stddeb, "LOCAL_FreeHandleEntry(%04x): freeing table %04x\n",
+                   ds, table);
+    *pTable = *((WORD *)(ptr + count * sizeof(*pEntry)) + 1);
+    LOCAL_FreeArena( ds, ARENA_HEADER( table ) );
+}
+
+
+/***********************************************************************
  *           LOCAL_Free
  *
  * Implementation of LocalFree().
@@ -677,20 +774,23 @@
 HLOCAL LOCAL_Free( HANDLE ds, HLOCAL handle )
 {
     char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
-    WORD arena;
 
     dprintf_local( stddeb, "LocalFree: %04x ds=%04x\n", handle, ds );
     
     if (!handle) { fprintf( stderr, "LOCAL_Free: handle is 0.\n" ); return 0; }
-    if (HANDLE_FIXED( handle )) {
-	arena = ARENA_HEADER( handle );
-    } else {
-	arena = ARENA_HEADER( *(WORD *)(ptr + handle) );
-	dprintf_local( stddeb, "LocalFree: real block at %04x\n", arena);
+    if (HANDLE_FIXED( handle ))
+    {
+        if (!LOCAL_FreeArena( ds, ARENA_HEADER( handle ) )) return 0;  /* OK */
+        else return handle;  /* couldn't free it */
     }
-    arena = LOCAL_FreeArena( ds, arena );
-    if (arena != 0) return handle; /* couldn't free it */
-    return 0;
+    else
+    {
+	WORD arena = ARENA_HEADER( *(WORD *)(ptr + handle) );
+        dprintf_local( stddeb, "LocalFree: real block at %04x\n", arena );
+        if (LOCAL_FreeArena( ds, arena )) return handle; /* couldn't free it */
+        LOCAL_FreeHandleEntry( ds, handle );
+        return 0;  /* OK */
+    }
 }
 
 
@@ -706,26 +806,26 @@
     
     dprintf_local( stddeb, "LocalAlloc: %04x %d ds=%04x\n", flags, size, ds );
 
-    if (flags & LMEM_MOVEABLE) {
+    if (flags & LMEM_MOVEABLE)
+    {
 	LOCALHANDLEENTRY *plhe;
 	HLOCAL hmem;
 	
-	hmem = LOCAL_GetBlock( ds, size + 2, flags );
-	if (hmem == 0) return 0;
-	handle = LOCAL_GetNewHandle( ds );
-	if (handle == 0) {
+	if (!(hmem = LOCAL_GetBlock( ds, size, flags ))) return 0;
+	if (!(handle = LOCAL_GetNewHandleEntry( ds )))
+        {
 	    fprintf( stderr, "LocalAlloc: couldn't get handle\n");
 	    LOCAL_FreeArena( ds, ARENA_HEADER(hmem) );
 	    return 0;
 	}
 	ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
-	*(WORD *)(ptr + hmem) = handle;
 	plhe = (LOCALHANDLEENTRY *)(ptr + handle);
-	plhe->addr = hmem + 2;
+	plhe->addr = hmem;
+        plhe->flags = (BYTE)(flags >> 8);
 	plhe->lock = 0;
-    } else {
-	handle = LOCAL_GetBlock( ds, size, flags );
     }
+    else handle = LOCAL_GetBlock( ds, size, flags );
+
     return handle;
 }
 
@@ -749,14 +849,9 @@
                    handle, size, flags, ds );
     if (!(pInfo = LOCAL_GetHeap( ds ))) return 0;
     
-    if (HANDLE_FIXED( handle )) {
-	blockhandle = handle;
-    } else {
-	size += 2;
-	blockhandle = *(WORD *)(ptr + handle);
-	dprintf_local( stddeb, "  blockhandle %04x (%04x)\n", blockhandle,
-		      *(WORD *)(ptr + blockhandle - 2));
-    }
+    if (HANDLE_FIXED( handle )) blockhandle = handle;
+    else blockhandle = *(WORD *)(ptr + handle);
+
     arena = ARENA_HEADER( blockhandle );
     dprintf_local( stddeb, "LocalReAlloc: arena is %04x\n", arena );
     pArena = ARENA_PTR( ptr, arena );
@@ -811,8 +906,8 @@
     ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
     memcpy( ptr + newhandle, ptr + (arena + ARENA_HEADER_SIZE), size );
     LOCAL_FreeArena( ds, arena );
-    if (HANDLE_MOVEABLE( handle )) {
-	newhandle += 2;
+    if (HANDLE_MOVEABLE( handle ))
+    {
 	dprintf_local( stddeb, "LocalReAlloc: fixing handle\n");
 	*(WORD *)(ptr + handle) = newhandle;
 	newhandle = handle;
@@ -831,7 +926,7 @@
     if (HANDLE_MOVEABLE(handle))
     {
         LOCALHANDLEENTRY *pEntry = (LOCALHANDLEENTRY *)(heap + handle);
-        if (pEntry->lock < 255) pEntry->lock++;
+        if (pEntry->lock < 0xfe) pEntry->lock++;
         handle = pEntry->addr;
     }
     dprintf_local( stddeb, "returning %04x\n", handle );
@@ -860,7 +955,7 @@
     if (HANDLE_MOVEABLE(handle))
     {
         LOCALHANDLEENTRY *pEntry = (LOCALHANDLEENTRY *)(ptr + handle);
-        if (!pEntry->lock || (pEntry->lock == 255)) return FALSE;
+        if (!pEntry->lock || (pEntry->lock == 0xff)) return FALSE;
         /* For moveable block, return the new lock count */
         /* (see _Windows_Internals_ p. 197) */
         return --pEntry->lock;
@@ -878,21 +973,41 @@
 {
     char *ptr = PTR_SEG_OFF_TO_LIN( CURRENT_DS, 0 );
     LOCALARENA *pArena;
-    WORD arena;
 
     dprintf_local( stddeb, "LocalSize: %04x ds=%04x\n", handle, ds );
-    
-    if (HANDLE_FIXED( handle )) {
-	arena = ARENA_HEADER( handle );
-    } else {
-	arena = ARENA_HEADER( handle = *(WORD *)(ptr + handle) );
-    }
-    pArena = ARENA_PTR( ptr, arena );
+
+    if (HANDLE_MOVEABLE( handle )) handle = *(WORD *)(ptr + handle);
+    pArena = ARENA_PTR( ptr, ARENA_HEADER(handle) );
     return pArena->next - handle;
 }
 
 
 /***********************************************************************
+ *           LOCAL_Flags
+ *
+ * Implementation of LocalFlags().
+ */
+WORD LOCAL_Flags( WORD ds, HLOCAL handle )
+{
+    char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
+
+    if (HANDLE_MOVEABLE(handle))
+    {
+        LOCALHANDLEENTRY *pEntry = (LOCALHANDLEENTRY *)(ptr + handle);
+        dprintf_local( stddeb, "LOCAL_Flags(%04x,%04x): returning %04x\n",
+                       ds, handle, pEntry->lock | (pEntry->flags << 8) );
+        return pEntry->lock | (pEntry->flags << 8);
+    }
+    else
+    {
+        dprintf_local( stddeb, "LOCAL_Flags(%04x,%04x): returning 0\n",
+                       ds, handle );
+        return 0;
+    }
+}
+
+
+/***********************************************************************
  *           LOCAL_HeapSize
  *
  * Implementation of LocalHeapSize().
@@ -906,6 +1021,67 @@
 
 
 /***********************************************************************
+ *           LOCAL_CountFree
+ *
+ * Implementation of LocalCountFree().
+ */
+WORD LOCAL_CountFree( WORD ds )
+{
+    WORD arena, total;
+    LOCALARENA *pArena;
+    char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
+    LOCALHEAPINFO *pInfo = LOCAL_GetHeap( ds );
+
+    total = 0;
+    arena = pInfo->first;
+    pArena = ARENA_PTR( ptr, arena );
+    for (;;)
+    {
+        arena = pArena->free_next;
+        pArena = ARENA_PTR( ptr, arena );
+	if (arena == pArena->free_next) break;
+        total += pArena->size;
+    }
+    dprintf_local( stddeb, "LOCAL_CountFree(%04x): returning %d\n", ds, total);
+    return total;
+}
+
+
+/***********************************************************************
+ *           LOCAL_Handle
+ *
+ * Implementation of LocalHandle().
+ */
+HLOCAL LOCAL_Handle( WORD ds, WORD addr )
+{ 
+    char *ptr = PTR_SEG_OFF_TO_LIN( ds, 0 );
+    LOCALHEAPINFO *pInfo;
+    WORD table;
+
+    if (!(pInfo = LOCAL_GetHeap( ds )))
+    {
+        fprintf( stderr, "LOCAL_Handle(%04x): Local heap not found\n", ds );
+	LOCAL_PrintHeap( ds );
+	return 0;
+    }
+
+    /* Find the address in the entry tables */
+
+    table = pInfo->htable;
+    while (table)
+    {
+        WORD count = *(WORD *)(ptr + table);
+        LOCALHANDLEENTRY *pEntry = (LOCALHANDLEENTRY*)(ptr+table+sizeof(WORD));
+        for (; count > 0; count--, pEntry++)
+            if (pEntry->addr == addr) return (HLOCAL)((char *)pEntry - ptr);
+        table = *(WORD *)pEntry;
+    }
+
+    return (HLOCAL)addr;  /* Fixed block handle is addr */
+}
+
+
+/***********************************************************************
  *           LocalAlloc   (KERNEL.5)
  */
 HLOCAL LocalAlloc( WORD flags, WORD size )
@@ -964,14 +1140,8 @@
  *           LocalHandle   (KERNEL.11)
  */
 HLOCAL LocalHandle( WORD addr )
-{
-    char *ptr = PTR_SEG_OFF_TO_LIN( CURRENT_DS, 0 );
-
-    dprintf_local( stddeb, "LocalHandle: %04x\n", addr );
-    if (HANDLE_MOVEABLE( addr )) {
-	addr = *(WORD *)(ptr + addr - 2);
-    }
-    return addr;
+{ 
+    return LOCAL_Handle( CURRENT_DS, addr );
 }
 
 
@@ -980,8 +1150,7 @@
  */
 WORD LocalFlags( HLOCAL handle )
 {
-    dprintf_local( stddeb, "LocalFlags: %04x\n", handle );
-    return 0;
+    return LOCAL_Flags( CURRENT_DS, handle );
 }
 
 
@@ -1000,8 +1169,20 @@
  */
 FARPROC LocalNotify( FARPROC func )
 {
-    dprintf_local( stddeb, "LocalNotify: %08lx\n", func );
-    return 0;
+    LOCALHEAPINFO *pInfo;
+    FARPROC oldNotify;
+    WORD ds = CURRENT_DS;
+
+    if (!(pInfo = LOCAL_GetHeap( ds )))
+    {
+        fprintf( stderr, "LOCAL_Notify(%04x): Local heap not found\n", ds );
+	LOCAL_PrintHeap( ds );
+	return 0;
+    }
+    dprintf_local( stddeb, "LocalNotify(%04x): %08lx\n", ds, func );
+    oldNotify = pInfo->notify;
+    pInfo->notify = func;
+    return oldNotify;
 }
 
 
@@ -1020,16 +1201,22 @@
  */
 DWORD GetHeapSpaces( HMODULE module )
 {
-    return MAKELONG( 0x7fff, 0xffff );
+    NE_MODULE *pModule;
+    WORD ds;
+
+    module = GetExePtr( module );
+    if (!(pModule = MODULE_GetPtr( module ))) return 0;
+    ds = (NE_SEG_TABLE( pModule ) + pModule->dgroup - 1)->selector;
+    return MAKELONG( LOCAL_CountFree( ds ), LOCAL_HeapSize( ds ) );
 }
 
 
 /***********************************************************************
  *           LocalCountFree   (KERNEL.161)
  */
-void LocalCountFree()
+WORD LocalCountFree(void)
 {
-    dprintf_local( stddeb, "LocalCountFree:\n" );
+    return LOCAL_CountFree( CURRENT_DS );
 }
 
 
@@ -1048,8 +1235,17 @@
  */
 WORD LocalHandleDelta( WORD delta )
 {
-    dprintf_local( stddeb, "LocalHandleDelta: %04x\n", delta );
-    return 0;
+    LOCALHEAPINFO *pInfo;
+
+    if (!(pInfo = LOCAL_GetHeap( CURRENT_DS )))
+    {
+        fprintf( stderr, "LocalHandleDelta: Local heap not found\n");
+	LOCAL_PrintHeap( CURRENT_DS );
+	return 0;
+    }
+    if (delta) pInfo->hdelta = delta;
+    dprintf_local(stddeb, "LocalHandleDelta: returning %04x\n", pInfo->hdelta);
+    return pInfo->hdelta;
 }
 
 
diff --git a/misc/Makefile.in b/misc/Makefile.in
index 1266b05..5e7701f 100644
--- a/misc/Makefile.in
+++ b/misc/Makefile.in
@@ -28,6 +28,7 @@
 	stress.c \
 	toolhelp.c \
 	user.c \
+	w32sys.c \
 	winsocket.c \
 	xmalloc.c
 
diff --git a/misc/comm.c b/misc/comm.c
index d0dfef3..d863ec5 100644
--- a/misc/comm.c
+++ b/misc/comm.c
@@ -164,7 +164,7 @@
 			return -1;
 		
 		strcpy(temp,device+5);
-		ptr = strtok(temp, ","); 
+		ptr = strtok(temp, ", "); 
 
 		if (COM[port].baudrate > 0)
 			lpdcb->BaudRate = COM[port].baudrate;
@@ -172,7 +172,7 @@
 			lpdcb->BaudRate = atoi(ptr);
         	dprintf_comm(stddeb,"BuildCommDCB: baudrate (%d)\n", lpdcb->BaudRate);
 
-		ptr = strtok(NULL, ",");
+		ptr = strtok(NULL, ", ");
 		if (islower(*ptr))
 			*ptr = toupper(*ptr);
 
@@ -199,11 +199,11 @@
 				return -1;
 		}
 
-		ptr = strtok(NULL, ","); 
+		ptr = strtok(NULL, ", "); 
          	dprintf_comm(stddeb, "BuildCommDCB: charsize (%c)\n", *ptr);
 		lpdcb->ByteSize = *ptr - '0';
 
-		ptr = strtok(NULL, ",");
+		ptr = strtok(NULL, ", ");
         	dprintf_comm(stddeb, "BuildCommDCB: stopbits (%c)\n", *ptr);
 		switch (*ptr) {
 			case '1':
diff --git a/misc/commdlg.c b/misc/commdlg.c
index 089019b..a749ba2 100644
--- a/misc/commdlg.c
+++ b/misc/commdlg.c
@@ -320,6 +320,8 @@
   LPSTR pstr;
   SetWindowLong(hWnd, DWL_USER, lParam);
   lpofn = (LPOPENFILENAME)lParam;
+  if (lpofn->lpstrTitle)
+      SendMessage( hWnd, WM_SETTEXT, 0, (LPARAM)lpofn->lpstrTitle );
   /* read custom filter information */
   if (lpofn->lpstrCustomFilter)
     {
@@ -1120,10 +1122,12 @@
  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() */
+ HBITMAP hbmMem;      /* color graph bitmap */    
  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 */
+ BOOL updating;       /* to prevent recursive WM_COMMAND/EN_UPDATE procesing */
  int h;
  int s;
  int l;               /* for temporary storing of hue,sat,lum */
@@ -1501,7 +1505,6 @@
 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); 
@@ -1512,56 +1515,34 @@
  if (IsWindowVisible(GetDlgItem(hDlg,0x2c6)))   /* if full size */
  {
    GetClientRect(hwnd,&rect);
-
    hDC=GetDC(hwnd);
+   SelectClipRgn(hDC,CreateRectRgnIndirect(&rect));   
    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;
-
+   point.x=((long)rect.right*(long)x)/(long)MAXHORI;
+   point.y=rect.bottom-((long)rect.bottom*(long)y)/(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;
+   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);
-   }
-
+   MoveTo(hDC,point.x-w,point.y); 
+   LineTo(hDC,point.x+w,point.y);
+   MoveTo(hDC,point.x,point.y-w); 
+   LineTo(hDC,point.x,point.y+w);
    DeleteObject(SelectObject(hDC,hPen));
    ReleaseDC(hwnd,hDC);
  }
 }
 
 
-#define XSTEPS 36
-#define YSTEPS 48
+#define XSTEPS 48
+#define YSTEPS 24
 
 
 /***********************************************************************
@@ -1575,14 +1556,13 @@
  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);
+ lpp->hbmMem = CreateCompatibleBitmap(hdc,client.right,client.bottom);
+ SelectObject(lpp->hdcMem,lpp->hbmMem);
 
  xdif=client.right /XSTEPS;
  ydif=client.bottom/YSTEPS+1;
@@ -1607,7 +1587,6 @@
  }
  ReleaseDC(hwnd,hdc);
  SetCursor(hcursor);
- /* FIXME perhaps we should do it only ONCE for all, like hCDRom,.... ? */
 }
 
 /***********************************************************************
@@ -1675,17 +1654,20 @@
 static void CC_EditSetRGB(HWND hDlg,COLORREF cr)
 {
  char buffer[10];
+ struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); 
  int r=GetRValue(cr);
  int g=GetGValue(cr);
  int b=GetBValue(cr);
  if (IsWindowVisible(GetDlgItem(hDlg,0x2c6)))   /* if full size */
  {
+   lpp->updating=TRUE;
    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);
+   lpp->updating=FALSE;
  }
 }
 
@@ -1695,14 +1677,18 @@
 static void CC_EditSetHSL(HWND hDlg,int h,int s,int l)
 {
  char buffer[10];
+ struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); 
+ lpp->updating=TRUE;
  if (IsWindowVisible(GetDlgItem(hDlg,0x2c6)))   /* if full size */
  {
+   lpp->updating=TRUE;
    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);
+   lpp->updating=FALSE;
  }
  CC_PaintLumBar(hDlg,h,s);
 }
@@ -1911,12 +1897,13 @@
     HDC hdc;
     COLORREF *cr;
     struct CCPRIVATE * lpp=(struct CCPRIVATE *)GetWindowLong(hDlg, DWL_USER); 
+    dprintf_commdlg(stddeb,"CC_WMCommand wParam=%x lParam=%lx\n",wParam,lParam);
     switch (wParam)
     {
           case 0x2c2:  /* edit notify RGB */
 	  case 0x2c3:
 	  case 0x2c4:
-	       if (HIWORD(lParam)==EN_UPDATE)
+	       if (HIWORD(lParam)==EN_UPDATE && !lpp->updating)
 			 {
 			   i=CC_CheckDigitsInEdit(LOWORD(lParam),255);
 			   r=GetRValue(lpp->lpcc->rgbResult);
@@ -1946,7 +1933,7 @@
 	  case 0x2bf:  /* edit notify HSL */
 	  case 0x2c0:
 	  case 0x2c1:
-	       if (HIWORD(lParam)==EN_UPDATE)
+	       if (HIWORD(lParam)==EN_UPDATE && !lpp->updating)
 			 {
 			   i=CC_CheckDigitsInEdit(LOWORD(lParam),wParam==0x2bf?239:240);
 			   xx=0;
@@ -2131,7 +2118,8 @@
 	  case WM_INITDIALOG:
 	                return CC_WMInitDialog(hDlg,wParam,lParam);
 	  case WM_NCDESTROY:
-	                /* FIXME: what about lpp->hdcMem ? */
+	                DeleteDC(lpp->hdcMem); 
+	                DeleteObject(lpp->hbmMem); 
 	                free(lpp);
 	                SetWindowLong(hDlg, DWL_USER, 0L); /* we don't need it anymore */
 	                break;
@@ -2158,3 +2146,84 @@
      return FALSE ;
 }
 
+
+
+/***********************************************************************
+ *                        ChooseFont   (COMMDLG.15)     
+     --April 1996--
+     please note: ChooseFont etc. are still under construction
+ */
+BOOL ChooseFont(LPCHOOSEFONT lpChFont)
+{
+    HANDLE hInst, hDlgTmpl;
+    BOOL bRet;
+    dprintf_commdlg(stddeb,"ChoseFont\n");
+    hDlgTmpl = SYSRES_LoadResource( SYSRES_DIALOG_CHOOSE_FONT );
+    hInst = WIN_GetWindowInstance( lpChFont->hwndOwner );
+    bRet = DialogBoxIndirectParam( hInst, hDlgTmpl, lpChFont->hwndOwner,
+                                   MODULE_GetWndProcEntry16("FormatCharDlgProc"), 
+                                   (DWORD)lpChFont );
+    SYSRES_FreeResource( hDlgTmpl );
+    return bRet;
+}
+
+/***********************************************************************
+ *           FontStyleEnumProc   (COMMDLG.18)
+ */
+int FontStyleEnumProc(LOGFONT *lf ,TEXTMETRIC *tm, int fonttype, LPARAM lParam)
+{
+ dprintf_commdlg(stddeb,"FontStyleEnumProc: font=%s (height=%d)\n",lf->lfFaceName,lf->lfHeight);
+ return 1;
+}
+
+/***********************************************************************
+ *           FontFamilyEnumProc   (COMMDLG.19)
+ */
+int FontFamilyEnumProc(LOGFONT *lf ,TEXTMETRIC *tm, int fonttype, LPARAM lParam)
+{
+ dprintf_commdlg(stddeb,"FontFamilyEnumProc: font=%s\n",lf->lfFaceName);
+ return 1;
+}
+
+/***********************************************************************
+ *           ColorDlgProc   (COMMDLG.16)
+ */
+LRESULT FormatCharDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam)
+{
+  HDC hdc;
+  FARPROC  enumCallback;
+  
+  switch (wMsg) 
+    {
+    case WM_INITDIALOG:
+      dprintf_commdlg(stddeb,"FormatCharDlgProc // WM_INITDIALOG lParam=%08lX\n", lParam);
+      ShowWindow(hDlg, SW_SHOWNORMAL);
+      hdc = GetDC(hDlg);
+      if (hdc)
+      {
+       HCURSOR hcursor=SetCursor(LoadCursor(0,IDC_WAIT));
+       /*  
+         currently only called for testing of 2 necessary EnumProcs 
+       */
+       enumCallback = MODULE_GetWndProcEntry16("FontFamilyEnumProc");
+       EnumFontFamilies (hdc, NULL,enumCallback ,NULL); 
+       enumCallback = MODULE_GetWndProcEntry16("FontStyleEnumProc");
+       EnumFontFamilies(hdc, /* for example : */ "COURIER",enumCallback,NULL);
+       ReleaseDC(hDlg,hdc);
+       SetCursor(hcursor);
+      }
+      return (TRUE);
+    case WM_COMMAND:
+      switch (wParam)
+	{
+	case IDOK:
+	  EndDialog(hDlg, TRUE);
+	  return(TRUE);
+	case IDCANCEL:
+	  EndDialog(hDlg, FALSE);
+	  return(TRUE);
+	}
+      return(FALSE);
+    }
+  return FALSE;
+}
diff --git a/misc/main.c b/misc/main.c
index e7bfdda..3dcd171 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -32,21 +32,28 @@
 #include "xmalloc.h"
 
 const char people[] = "Wine is available thanks to the work of "
-"Bob Amstadt, Dag Asheim, Martin Ayotte, Ross Biro, Erik Bos, "
-"Fons Botman, John Brezak, Andrew Bulhak, John Burton, Paul Falstad, "
+"Bob Amstadt, Dag Asheim, Martin Ayotte, Ross Biro, Uwe Bonnes, Erik Bos, "
+"Fons Botman, John Brezak, Andrew Bulhak, John Burton, "
+"Niels de Carpentier, Roman Dolejsi, Frans van Dorsselaer, Paul Falstad, "
 "Olaf Flebbe, Peter Galbavy, Ramon Garcia, Hans de Graaff, "
-"Charles M. Hannum, Cameron Heide, Jochen Hoenicke, Jeffrey Hsu, "
-"Miguel de Icaza, Alexandre Julliard, Jon Konrath, Scott A. Laird, "
+"Charles M. Hannum, John Harvey, Cameron Heide, Jochen Hoenicke, "
+"Onno Hovers, Jeffrey Hsu, Miguel de Icaza, Jukka Iivonen, "
+"Alexandre Julliard, Jochen Karrer, Andreas Kirschbaum, Albrecht Kleine, "
+"Jon Konrath, Alex Korobka, Greg Kreider, Anand Kumria, Scott A. Laird, "
 "Martin von Loewis, Kenneth MacDonald, Peter MacDonald, William Magro, "
-"Marcus Meissner, Graham Menhennitt, David Metcalfe, Michael Patra, "
-"John Richardson, Johannes Ruscheinski, Thomas Sandford, "
-"Constantine Sapuntzakis, Daniel Schepler, Bernd Schmidt, "
-"Yngvi Sigurjonsson, Rick Sladkey, William Smith, Erik Svendsen, "
-"Goran Thyni, Jimmy Tirtawangsa, Jon Tombs, Linus Torvalds, "
-"Gregory Trubetskoy, Michael Veksler, Morten Welinder, Jan Willamowius, "
-"Carl Williams, Karl Guenter Wuensch, Eric Youngdale, and James Youngman.";
+"Juergen Marquardt, Marcus Meissner, Graham Menhennitt, David Metcalfe, "
+"Steffen Moeller, Philippe De Muyter, Itai Nahshon, Michael Patra, "
+"Jim Peterson, Robert Pouliot, Keith Reynolds, John Richardson, "
+"Johannes Ruscheinski, Thomas Sandford, Constantine Sapuntzakis, "
+"Daniel Schepler, Ulrich Schmid, Bernd Schmidt, Yngvi Sigurjonsson, "
+"Rick Sladkey, William Smith, Erik Svendsen, Tristan Tarrant, "
+"Andrew Taylor, Duncan C Thomson, Goran Thyni, Jimmy Tirtawangsa, "
+"Jon Tombs, Linus Torvalds, Gregory Trubetskoy, Michael Veksler, "
+"Sven Verdoolaege, Eric Warnke, Manfred Weichel, Morten Welinder, "
+"Jan Willamowius, Carl Williams, Karl Guenter Wuensch, Eric Youngdale, "
+"and James Youngman. ";
 
-static const char *langNames[] =
+const char *langNames[] =
 {
     "En",  /* LANG_En */
     "Es",  /* LANG_Es */
diff --git a/misc/registry.c b/misc/registry.c
index 6483078..7e72b71 100644
--- a/misc/registry.c
+++ b/misc/registry.c
@@ -10,22 +10,32 @@
 #include <unistd.h>
 #include <ctype.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <time.h>
 #include "windows.h"
 #include "win.h"
 #include "winerror.h"
 #include "string32.h"	
-#include "kernel32.h"	/* LPSECURITY_ATTRIBUTES */
 #include "stddebug.h"
 #include "debug.h"
 #include "xmalloc.h"
 #include "winreg.h"
 
-#define SAVE_CLASSES_ROOT	"/tmp/reg.classes_root"
-#define SAVE_CURRENT_USER	"/tmp/reg.current_user"
-#define SAVE_LOCAL_MACHINE	"/tmp/reg.local_machine"
-#define SAVE_USERS		"/tmp/reg.users"
+/* FIXME: following defines should be configured global ... */
 
-static KEYSTRUCT	*key_classes_root=NULL;	/* windows global values */
+/* NOTE: do not append a /. linux' mkdir() WILL FAIL if you do that */
+#define WINE_PREFIX			"/.wine"
+#define SAVE_CURRENT_USER_DEFAULT	"/usr/local/etc/wine.userreg"
+	/* relative in ~user/.wine/ */
+#define SAVE_CURRENT_USER		"user.reg"
+#define SAVE_LOCAL_MACHINE_DEFAULT	"/usr/local/etc/wine.systemreg"
+	/* relative in ~user/.wine/ */
+#define SAVE_LOCAL_MACHINE		"system.reg"
+
+static KEYSTRUCT	*key_classes_root=NULL;	/* windows 3.1 global values */
 static KEYSTRUCT	*key_current_user=NULL;	/* user specific values */
 static KEYSTRUCT	*key_local_machine=NULL;/* machine specific values */
 static KEYSTRUCT	*key_users=NULL;	/* all users? */
@@ -181,21 +191,46 @@
 }
 #define FREE_KEY_PATH	free(wps[0]);free(wps);
 
-/**
+/*
  * Shell initialisation, allocates keys. 
- * FIXME:should set default values too
  */
 void
 SHELL_Init() {
+	struct	passwd	*pwd;
+
+	HKEY	cl_r_hkey,c_u_hkey;
 #define ADD_ROOT_KEY(xx) \
 	xx = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));\
 	memset(xx,'\0',sizeof(KEYSTRUCT));\
 	xx->keyname= strdupA2W("<should_not_appear_anywhere>");
 
-	ADD_ROOT_KEY(key_classes_root);
-	ADD_ROOT_KEY(key_current_user);
 	ADD_ROOT_KEY(key_local_machine);
+	if (RegCreateKey(HKEY_LOCAL_MACHINE,"\\SOFTWARE\\Classes",&cl_r_hkey)!=ERROR_SUCCESS) {
+		fprintf(stderr,"couldn't create HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes. This is impossible.\n");
+		exit(1);
+	}
+	key_classes_root = lookup_hkey(cl_r_hkey);
+
 	ADD_ROOT_KEY(key_users);
+
+#if 0
+	/* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg 
+	 *	  (later, when a win32 registry editing tool becomes avail.)
+	 */
+	while (pwd=getpwent()) {
+		if (pwd->pw_name == NULL)
+			continue;
+		RegCreateKey(HKEY_USERS,pwd->pw_name,&c_u_hkey);
+		RegCloseKey(c_u_hkey);
+	}
+#endif
+	pwd=getpwuid(getuid());
+	if (pwd && pwd->pw_name) {
+		RegCreateKey(HKEY_USERS,pwd->pw_name,&c_u_hkey);
+		key_current_user = lookup_hkey(c_u_hkey);
+	} else {
+		ADD_ROOT_KEY(key_current_user);
+	}
 	ADD_ROOT_KEY(key_performance_data);
 	ADD_ROOT_KEY(key_current_config);
 	ADD_ROOT_KEY(key_dyn_data);
@@ -211,96 +246,83 @@
  * old registry database files.
  * 
  * Global:
- * 	DWORD	version
- * 	DWORD	nrofkeys
- *	KEY	keys[nrofkeys]
- *
- * KEY:
- * 	USTRING	name
- *	USTRING class
- * 	DWORD	nrofvalues
- *	VALUE	vals[nrofvalues]
- * 	DWORD	nrofsubkeys
- *	KEY	keys[nrofsubkeys]
- *
- * Value:
- * 	USTRING	name
- * 	DWORD	type
- * 	DWORD	len
- * 	BYTE	data[len]
- *
- * USTRING:
- * 	DWORD	len (len==0 means data=NULL)
- * 	BYTE	data[len]
+ * 	"WINE REGISTRY Version %d"
+ * 	subkeys....
+ * Subkeys:
+ * 	keyname
+ *		valuename=lastmodified,type,data
+ *		...
+ *		subkeys
+ *	...
+ * keyname,valuename,stringdata:
+ *	the usual ascii characters from 0x00-0xff (well, not 0x00)
+ *	and \uXXXX as UNICODE value XXXX with XXXX>0xff
+ *	( "=\\\t" escaped in \uXXXX form.)
+ * type,lastmodified: 
+ *	int
  * 
- *
- * All _write_XXX and _read_XXX functions return !0 on sucess.
+ * FIXME: doesn't save 'class' (what does it mean anyway?), nor flags.
  */
 
+static void
+_write_USTRING(FILE *F,LPWSTR wstr,int escapeeq) {
+	LPWSTR	s;
+	int	doescape;
 
-static int 
-_write_DWORD(FILE *F,DWORD dw) {
-	return fwrite(&dw,sizeof(dw),1,F);
-}
-
-static int
-_write_USTRING(FILE *F,LPWSTR str) {
-	int	len;
-
-	if (str==NULL) {
-		if (!_write_DWORD(F,0))
-			return 0;
-	} else {
-		len=strlenW(str)*2+2;
-
-		if (!_write_DWORD(F,len))
-			return 0;
-		if (!fwrite(str,len,1,F))
-			return 0;
+	if (wstr==NULL) {
+		/* FIXME: NULL equals empty string... I hope
+		 * the empty string isn't a valid valuename
+		 */
+		return;
 	}
-	return 1;
+	s=wstr;
+	while (*s) {
+		doescape=0;
+		if (*s>0xff)
+			doescape = 1;
+		if (*s=='\n')
+			doescape = 1;
+		if (escapeeq && *s=='=')
+			doescape = 1;
+		if (*s=='\\')
+			fputc(*s,F); /* if \\ than put it twice. */
+		if (doescape)
+			fprintf(F,"\\u%04x",*((unsigned short*)s));
+		else
+			fputc(*s,F);
+		s++;
+	}
 }
 
-
 static int
-_do_save_subkey(FILE *F,LPKEYSTRUCT lpkey) {
+_do_save_subkey(FILE *F,LPKEYSTRUCT lpkey,int level) {
 	LPKEYSTRUCT	lpxkey;
-	int		nrofkeys;
-	int		i;
-
-	nrofkeys= 0;
-	lpxkey	= lpkey;
-	while (lpxkey) {
-		if (!(lpxkey->flags & REG_OPTION_VOLATILE))
-			nrofkeys++;
-		lpxkey	= lpxkey->next;
-	}
-	if (!_write_DWORD(F,nrofkeys))
-		return 0;
+	int		i,tabs,j;
 
 	lpxkey	= lpkey;
 	while (lpxkey) {
 		if (!(lpxkey->flags & REG_OPTION_VOLATILE)) {
-			if (!_write_USTRING(F,lpxkey->keyname))
-				return 0;
-			if (!_write_USTRING(F,lpxkey->class))
-				return 0;
-			if (!_write_DWORD(F,lpxkey->nrofvalues))
-				return 0;
+			for (tabs=level;tabs--;)
+				fputc('\t',F);
+			_write_USTRING(F,lpxkey->keyname,1);
+			fputs("\n",F);
 			for (i=0;i<lpxkey->nrofvalues;i++) {
 				LPKEYVALUE	val=lpxkey->values+i;
 
-				if (!_write_USTRING(F,val->name))
-					return 0;
-				if (!_write_DWORD(F,val->type))
-					return 0;
-				if (!_write_DWORD(F,val->len))
-					return 0;
-				if (!fwrite(val->data,val->len,1,F))
-					return 0;
+				for (tabs=level+1;tabs--;)
+					fputc('\t',F);
+				_write_USTRING(F,val->name,0);
+				fputc('=',F);
+				fprintf(F,"%ld,%ld,",val->type,val->lastmodified);
+				if ((1<<val->type) & UNICONVMASK)
+					_write_USTRING(F,(LPWSTR)val->data,0);
+				else
+					for (j=0;j<val->len;j++)
+						fprintf(F,"%02x",*((unsigned char*)val->data+j));
+				fputs("\n",F);
 			}
 			/* descend recursively */
-			if (!_do_save_subkey(F,lpxkey->nextsub))
+			if (!_do_save_subkey(F,lpxkey->nextsub,level+1))
 				return 0;
 		}
 		lpxkey=lpxkey->next;
@@ -310,16 +332,15 @@
 
 static int
 _do_savesubreg(FILE *F,LPKEYSTRUCT lpkey) {
-	if (!_write_DWORD(F,REGISTRY_SAVE_VERSION))
-		return 0;
-	return _do_save_subkey(F,lpkey->nextsub);
+	fprintf(F,"WINE REGISTRY Version %d\n",REGISTRY_SAVE_VERSION);
+	return _do_save_subkey(F,lpkey->nextsub,0);
 }
 
 static void
 _SaveSubReg(LPKEYSTRUCT lpkey,char *fn) {
 	FILE	*F;
 
-	F=fopen(fn,"wb");
+	F=fopen(fn,"w");
 	if (F==NULL) {
 		fprintf(stddeb,__FILE__":_SaveSubReg:Couldn't open %s for writing: %s\n",
 			fn,strerror(errno)
@@ -337,105 +358,307 @@
 
 void
 SHELL_SaveRegistry() {
-	_SaveSubReg(key_classes_root,SAVE_CLASSES_ROOT);
-	_SaveSubReg(key_current_user,SAVE_CURRENT_USER);
-	_SaveSubReg(key_local_machine,SAVE_LOCAL_MACHINE);
-	_SaveSubReg(key_users,SAVE_USERS);
+	char	*fn;
+	struct	passwd	*pwd;
+
+	pwd=getpwuid(getuid());
+	if (pwd!=NULL && pwd->pw_dir!=NULL) {
+		fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+2);
+		strcpy(fn,pwd->pw_dir);
+		strcat(fn,WINE_PREFIX);
+		/* create the directory. don't care about errorcodes. */
+		mkdir(fn,0755); /* drwxr-xr-x */
+		strcat(fn,"/");
+		strcat(fn,SAVE_CURRENT_USER);
+		_SaveSubReg(key_current_user,fn);
+		free(fn);
+		fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+1);
+		strcpy(fn,pwd->pw_dir);
+		strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
+		_SaveSubReg(key_local_machine,fn);
+		free(fn);
+	} else {
+		fprintf(stderr,"SHELL_SaveRegistry:failed to get homedirectory of UID %d.\n",getuid());
+	}
 }
 
 /************************ LOAD Registry Function ****************************/
 
-/* FIXME: 
- * Currently overwrites any old registry data (leaks it away)
- * should better be a merge, or ?
+/* reads a line including dynamically enlarging the readbuffer and throwing
+ * away comments
  */
+static int 
+_read_line(FILE *F,char **buf,int *len) {
+	char	*s,*curread;
+	int	mylen,curoff;
 
-static int
-_read_DWORD(FILE *F,DWORD *dw) {
-	return fread(dw,sizeof(DWORD),1,F);
-}
-
-static int
-_read_USTRING(FILE *F,LPWSTR *str) {
-	DWORD	len;
-
-	if (!_read_DWORD(F,&len))
-		return 0;
-	if (len==0) {
-		*str=NULL;
-		return 1;
-	}
-	*str=xmalloc(len);
-	return fread(*str,len,1,F);
-}
-
-static int
-_do_load_subkey(FILE *F,LPKEYSTRUCT lpkey) {
-	DWORD		howmuch;
-	LPKEYSTRUCT	*lplpkey,lpxkey;
-	int		i;
-
-	if (!_read_DWORD(F,&howmuch))
-		return 0;
-
-	/* no subkeys? */
-	if (howmuch==0)
-		return 1;
-
-	lplpkey	= &(lpkey->nextsub);
-	while (howmuch--) {
-		*lplpkey= (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
-		memset(*lplpkey,'\0',sizeof(KEYSTRUCT));
-		lpxkey	= *lplpkey;
-		if (!_read_USTRING(F,&(lpxkey->keyname)))
-			return 0;
-		if (!_read_USTRING(F,&(lpxkey->class)))
-			return 0;
-		if (!_read_DWORD(F,&(lpxkey->nrofvalues)))
-			return 0;
-		if (lpxkey->nrofvalues) {
-			lpxkey->values = (LPKEYVALUE)xmalloc(
-				lpxkey->nrofvalues*sizeof(KEYVALUE)
-			);
-			for (i=0;i<lpxkey->nrofvalues;i++) {
-				LPKEYVALUE	val=lpxkey->values+i;
-
-				memset(val,'\0',sizeof(KEYVALUE));
-				if (!_read_USTRING(F,&(val->name)))
-					return 0;
-				if (!_read_DWORD(F,&(val->type)))
-					return 0;
-				if (!_read_DWORD(F,&(val->len)))
-					return 0;
-				val->data	= (LPBYTE)xmalloc(val->len);
-				if (!fread(val->data,val->len,1,F))
-					return 0;
+	curread	= *buf;
+	mylen	= *len;
+	**buf	= '\0';
+	while (1) {
+		while (1) {
+			s=fgets(curread,mylen,F);
+			if (s==NULL)
+				return 0; /* EOF */
+			if (NULL==(s=strchr(curread,'\n'))) {
+				/* buffer wasn't large enough */
+				curoff	= strlen(*buf);
+				*buf	= xrealloc(*buf,*len*2);
+				curread	= *buf + curoff;
+				mylen	= *len;	/* we filled up the buffer and 
+						 * got new '*len' bytes to fill
+						 */
+				*len	= *len * 2;
+			} else {
+				*s='\0';
+				break;
 			}
 		}
-		if (!_do_load_subkey(F,*lplpkey))
-			return 0;
-		lplpkey	= &(lpxkey->next);
+		/* throw away comments */
+		if (**buf=='#' || **buf==';') {
+			curread	= *buf;
+			mylen	= *len;
+			continue;
+		}
+		if (s) 	/* got end of line */
+			break;
+	}
+	return 1;
+}
+
+/* converts a char* into a UNICODE string (up to a special char)
+ * and returns the position exactly after that string
+ */
+static char*
+_read_USTRING(char *buf,LPWSTR *str) {
+	char	*s;
+	LPWSTR	ws;
+
+	/* read up to "=" or "\0" or "\n" */
+	s	= buf;
+	if (*s == '=') {
+		/* empty string is the win3.1 default value(NULL)*/
+		*str	= NULL;
+		return s;
+	}
+	*str	= (LPWSTR)xmalloc(2*strlen(buf)+2);
+	ws	= *str;
+	while (*s && (*s!='\n') && (*s!='=')) {
+		if (*s!='\\')
+			*ws++=*((unsigned char*)s++);
+		else {
+			s++;
+			if (*s=='\\') {
+				*ws+='\\';
+				s++;
+				continue;
+			}
+			if (*s!='u') {
+				fprintf(stderr,"_read_USTRING:Non unicode escape sequence \\%c found in |%s|\n",*s,buf);
+				*ws++='\\';
+				*ws++=*s++;
+			} else {
+				char	xbuf[5];
+				int	wc;
+
+				s++;
+				memcpy(xbuf,s,4);xbuf[4]='\0';
+				if (!sscanf(xbuf,"%x",&wc))
+					fprintf(stderr,"_read_USTRING:strange escape sequence %s found in |%s|\n",xbuf,buf);
+				s+=4;
+				*ws++	=(unsigned short)wc;
+			}
+		}
+	}
+	*ws	= 0;
+	ws	= *str;
+	*str	= strdupW(*str);
+	free(ws);
+	return s;
+}
+
+static int
+_do_load_subkey(FILE *F,LPKEYSTRUCT lpkey,int level,char **buf,int *buflen) {
+	LPKEYSTRUCT	lpxkey,*lplpkey;
+	int		i;
+	char		*s;
+	LPWSTR		name;
+
+	/* good. we already got a line here ... so parse it */
+	lpxkey	= NULL;
+	while (1) {
+		i=0;s=*buf;
+		while (*s=='\t') {
+			s++;
+			i++;
+		}
+		if (i>level) {
+			if (lpxkey==NULL) {
+				fprintf(stderr,"_do_load_subkey:Got a subhierarchy without resp. key?\n");
+				return 0;
+			}
+			_do_load_subkey(F,lpxkey,level+1,buf,buflen);
+			continue;
+		}
+		/* let the caller handle this line */
+		if (i<level || **buf=='\0')
+			return 1;
+		/* good. this is one line for us.
+		 * it can be: a value or a keyname. Parse the name first
+		 */
+		s=_read_USTRING(s,&name);
+
+		/* switch() default: hack to avoid gotos */
+		switch (0) {
+		default:
+			if (*s=='\0') {
+				/* this is a new key 
+				 * look for the name in the already existing keys
+				 * on this level.
+				 */
+				 lplpkey= &(lpkey->nextsub);
+				 lpxkey	= *lplpkey;
+				 while (lpxkey) {
+					if (!strcmpW(lpxkey->keyname,name))
+						break;
+					lplpkey	= &(lpxkey->next);
+					lpxkey	= *lplpkey;
+				 }
+				 if (lpxkey==NULL) {
+					/* we have no key with that name yet. allocate
+					 * it.
+					 */
+					*lplpkey = (LPKEYSTRUCT)xmalloc(sizeof(KEYSTRUCT));
+					lpxkey	= *lplpkey;
+					memset(lpxkey,'\0',sizeof(KEYSTRUCT));
+					lpxkey->keyname	= name;
+				 } else {
+					/* already got it. we just remember it in 
+					 * 'lpxkey'
+					 */
+					free(name);
+				 }
+			} else {
+				LPKEYVALUE	val=NULL;
+				LPBYTE		data;
+				int		len,lastmodified,type;
+
+				if (*s!='=') {
+					fprintf(stderr,"_do_load_subkey:unexpected character: %c\n",*s);
+					break;
+				}
+				/* good. this looks like a value to me */
+				s++;
+				for (i=0;i<lpkey->nrofvalues;i++) {
+					val=lpkey->values+i;
+					if (name==NULL) {
+						if (val->name==NULL)
+							break;
+					} else {
+						if (	val->name!=NULL && 
+							!strcmpW(val->name,name)
+						)
+							break;
+					}
+				}
+				if (i==lpkey->nrofvalues) {
+					lpkey->values = xrealloc(
+						lpkey->values,
+						(++lpkey->nrofvalues)*sizeof(KEYVALUE)
+					);
+					val=lpkey->values+i;
+					memset(val,'\0',sizeof(KEYVALUE));
+					val->name = name;
+				} else {
+					/* value already exists, free name */
+					free(name);
+				}
+				if (2!=sscanf(s,"%d,%d,",&type,&lastmodified)) {
+					fprintf(stderr,"_do_load_subkey: haven't understood possible value in |%s|, skipping.\n",*buf);
+					break;
+				}
+				/* skip the 2 , */
+				s=strchr(s,',');s++;
+				s=strchr(s,',');s++;
+				if ((1<<type) & UNICONVMASK) {
+					s=_read_USTRING(s,(LPWSTR*)&data);
+					if (data)
+						len = strlenW((LPWSTR)data)*2+2;
+					else	
+						len = 0;
+				} else {
+					len=strlen(s)/2;
+					data = (LPBYTE)xmalloc(len+1);
+					for (i=0;i<len;i++) {
+						data[i]=0;
+						if (*s>='0' && *s<='9')
+							data[i]=(*s-'0')<<4;
+						if (*s>='a' && *s<='f')
+							data[i]=(*s-'a')<<4;
+						if (*s>='A' && *s<='F')
+							data[i]=(*s-'A')<<4;
+						s++;
+						if (*s>='0' && *s<='9')
+							data[i]|=*s-'0';
+						if (*s>='a' && *s<='f')
+							data[i]|=*s-'a';
+						if (*s>='A' && *s<='F')
+							data[i]|=*s-'A';
+						s++;
+					}
+				}
+				if (val->lastmodified<lastmodified) {
+					val->lastmodified=lastmodified;
+					val->type = type;
+					val->len  = len;
+					if (val->data) 
+						free(val->data);
+					val->data = data;
+				} else {
+					free(data);
+				}
+			}
+		}
+		/* read the next line */
+		if (!_read_line(F,buf,buflen))
+			return 1;
 	}
 	return 1;
 }
 
 static int
 _do_loadsubreg(FILE *F,LPKEYSTRUCT lpkey) {
-	DWORD	ver;
+	int	ver;
+	char	*buf;
+	int	buflen;
 
-	if (!_read_DWORD(F,&ver))
-		return 0;
-	if (ver!=REGISTRY_SAVE_VERSION) {
-		dprintf_reg(stddeb,__FILE__":_do_loadsubreg:Old format (%lx) registry found, ignoring it.\n",ver);
+	buf=xmalloc(10);buflen=10;
+	if (!_read_line(F,&buf,&buflen)) {
+		free(buf);
 		return 0;
 	}
-	if (!_do_load_subkey(F,lpkey)) {
+	if (!sscanf(buf,"WINE REGISTRY Version %d",&ver)) {
+		free(buf);
+		return 0;
+	}
+	if (ver!=REGISTRY_SAVE_VERSION) {
+		dprintf_reg(stddeb,__FILE__":_do_loadsubreg:Old format (%d) registry found, ignoring it. (buf was %s).\n",ver,buf);
+		free(buf);
+		return 0;
+	}
+	if (!_read_line(F,&buf,&buflen)) {
+		free(buf);
+		return 0;
+	}
+	if (!_do_load_subkey(F,lpkey,0,&buf,&buflen)) {
+		free(buf);
 		/* FIXME: memory leak on failure to read registry ... 
 		 * But this won't happen very often.
 		 */
 		lpkey->nextsub=NULL;
 		return 0;
 	}
+	free(buf);
 	return 1;
 }
 
@@ -459,18 +682,40 @@
 
 void
 SHELL_LoadRegistry() {
+	char	*fn;
+	struct	passwd	*pwd;
+
 	if (key_classes_root==NULL)
 		SHELL_Init();
-	_LoadSubReg(key_classes_root,SAVE_CLASSES_ROOT);
-	_LoadSubReg(key_current_user,SAVE_CURRENT_USER);
-	_LoadSubReg(key_local_machine,SAVE_LOCAL_MACHINE);
-	_LoadSubReg(key_users,SAVE_USERS);
+	/* load the machine-wide defaults first */
+	_LoadSubReg(key_current_user,SAVE_CURRENT_USER_DEFAULT);
+	_LoadSubReg(key_local_machine,SAVE_LOCAL_MACHINE_DEFAULT);
+
+	/* load the user saved registry. overwriting only newer entries */
+	pwd=getpwuid(getuid());
+	if (pwd!=NULL && pwd->pw_dir!=NULL) {
+		fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_CURRENT_USER)+1);
+		strcpy(fn,pwd->pw_dir);
+		strcat(fn,WINE_PREFIX"/"SAVE_CURRENT_USER);
+		_LoadSubReg(key_current_user,fn);
+		free(fn);
+		fn=(char*)xmalloc(strlen(pwd->pw_dir)+strlen(WINE_PREFIX)+strlen(SAVE_LOCAL_MACHINE)+1);
+		strcpy(fn,pwd->pw_dir);
+		strcat(fn,WINE_PREFIX"/"SAVE_LOCAL_MACHINE);
+		_LoadSubReg(key_local_machine,fn);
+		free(fn);
+	} else {
+		fprintf(stderr,"SHELL_LoadRegistry:failed to get homedirectory of UID %d.\n",getuid());
+	}
+	/* FIXME: load all users and their resp. pwd->pw_dir/.wine/user.reg 
+	 *	  (later, when a win32 registry editing tool becomes avail.)
+	 */
 }
 
 /********************* API FUNCTIONS ***************************************/
 
 /*
- * Open Keys. 
+ * Open Keys.
  *
  * All functions are stubs to RegOpenKeyExW where all the
  * magic happens. 
@@ -508,6 +753,7 @@
 	}
 	split_keypath(lpszSubKey,&wps,&wpc);
 	i 	= 0;
+	while ((i<wpc) && (wps[i][0]=='\0')) i++;
 	lpxkey	= lpNextKey;
 	while (i<wpc) {
 		lpxkey=lpNextKey->nextsub;
@@ -647,6 +893,7 @@
 	}
 	split_keypath(lpszSubKey,&wps,&wpc);
 	i 	= 0;
+	while ((i<wpc) && (wps[i][0]=='\0')) i++;
 	lpxkey	= lpNextKey;
 	while (i<wpc) {
 		lpxkey=lpNextKey->nextsub;
@@ -1131,6 +1378,7 @@
 	if (lpkey->values[i].data !=NULL)
 		free(lpkey->values[i].data);
 	lpkey->values[i].data	= (LPBYTE)xmalloc(cbData);
+	lpkey->values[i].lastmodified = time(NULL);
 	memcpy(lpkey->values[i].data,lpbData,cbData);
 	return SHELL_ERROR_SUCCESS;
 }
diff --git a/misc/user.c b/misc/user.c
index 0a3cd4f..194da4c 100644
--- a/misc/user.c
+++ b/misc/user.c
@@ -24,30 +24,33 @@
  */
 WORD GetFreeSystemResources( WORD resType )
 {
-    DWORD user, gdi;
+    int userPercent, gdiPercent;
 
     switch(resType)
     {
     case GFSR_USERRESOURCES:
-        user = GetHeapSpaces( USER_HeapSel );
-        gdi  = 0xffffffff;
+        userPercent = (int)LOCAL_CountFree( USER_HeapSel ) * 100 /
+                               LOCAL_HeapSize( USER_HeapSel );
+        gdiPercent  = 100;
         break;
 
     case GFSR_GDIRESOURCES:
-        gdi  = GetHeapSpaces( GDI_HeapSel );
-        user = 0xffffffff;
+        gdiPercent  = (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
+                               LOCAL_HeapSize( GDI_HeapSel );
+        userPercent = 100;
         break;
 
     case GFSR_SYSTEMRESOURCES:
-        user = GetHeapSpaces( USER_HeapSel );
-        gdi  = GetHeapSpaces( GDI_HeapSel );
+        userPercent = (int)LOCAL_CountFree( USER_HeapSel ) * 100 /
+                               LOCAL_HeapSize( USER_HeapSel );
+        gdiPercent  = (int)LOCAL_CountFree( GDI_HeapSel ) * 100 /
+                               LOCAL_HeapSize( GDI_HeapSel );
         break;
 
     default:
         return 0;
     }
-    if (user > gdi) return LOWORD(gdi) * 100 / HIWORD(gdi);
-    else return LOWORD(user) * 100 / HIWORD(user);
+    return (WORD)MIN( userPercent, gdiPercent );
 }
 
 
diff --git a/misc/w32sys.c b/misc/w32sys.c
new file mode 100644
index 0000000..8fae50d
--- /dev/null
+++ b/misc/w32sys.c
@@ -0,0 +1,23 @@
+/*
+ * W32SYS
+ * helper DLL for Win32s
+ *
+ * Copyright (c) 1996 Anand Kumria
+ */
+
+#include "windows.h"
+#include "w32sys.h"
+
+
+/***********************************************************************
+ *           GetWin32sInfo   (W32SYS.12)
+ */
+WORD GetWin32sInfo( LPWIN32SINFO lpInfo)
+{
+    lpInfo->bMajor = 1;
+    lpInfo->bMinor = 3;
+    lpInfo->wBuildNumber = 0;
+    lpInfo->fDebug = FALSE;
+
+    return 0;
+}
diff --git a/objects/metafile.c b/objects/metafile.c
index b68373a..e831017 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -2,6 +2,7 @@
  * Metafile functions
  *
  * Copyright  David W. Metcalfe, 1994
+ *            Niels de Carpentier, 1996
  *
  */
 
@@ -12,7 +13,7 @@
 #include "file.h"
 #include "metafile.h"
 #include "stddebug.h"
-/* #define DEBUG_METAFILE */
+#include "callback.h"
 #include "debug.h"
 
 #define HTINCR  10      /* handle table allocation size increment */
@@ -23,52 +24,60 @@
 /******************************************************************
  *         GetMetafile         GDI.124 By Kenny MacDonald 30 Nov 94
  */
+
 HMETAFILE GetMetaFile(LPSTR lpFilename)
 {
   HMETAFILE hmf;
-  METAFILE *mf;
   METAHEADER *mh;
-
+  HFILE hFile;
+  DWORD size;
+  
   dprintf_metafile(stddeb,"GetMetaFile: %s\n", lpFilename);
 
   if (!lpFilename)
     return 0;
 
-  hmf = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE));
-  mf = (METAFILE *)GlobalLock(hmf);
-  if (!mf) {
-    GlobalFree(hmf);
-    return 0;
-  }
-
-  mf->hMetaHdr = GlobalAlloc(GMEM_MOVEABLE, MFHEADERSIZE);
-  mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+  hmf = GlobalAlloc(GMEM_MOVEABLE, MFHEADERSIZE);
+  mh = (METAHEADER *)GlobalLock(hmf);
+  
   if (!mh) {
-    GlobalFree(mf->hMetaHdr);
     GlobalFree(hmf);
     return 0;
   }
-  strcpy(mf->Filename, lpFilename);
-  mf->wMagic = METAFILE_MAGIC;
-  if ((mf->hFile = _lopen(lpFilename, OF_READ)) == HFILE_ERROR) {
-    GlobalFree(mf->hMetaHdr);
+  
+  if ((hFile = _lopen(lpFilename, OF_READ)) == HFILE_ERROR) {
     GlobalFree(hmf);
     return 0;
   }
-  if (FILE_Read(mf->hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR) {
-    GlobalFree(mf->hMetaHdr);
+  
+  if (FILE_Read(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR) {
     GlobalFree(hmf);
     return 0;
   }
-  _lclose(mf->hFile);
+  
+  size = mh->mtSize * 2;         /* alloc memory for whole metafile */
+  GlobalUnlock(hmf);
+  hmf = GlobalReAlloc(hmf,size,GMEM_MOVEABLE);
+  mh = (METAHEADER *)GlobalLock(hmf);
+  
+  if (!mh) {
+    GlobalFree(hmf);
+    return 0;
+  }
+  
+  if (FILE_Read(hFile, (char*)mh + mh->mtHeaderSize * 2, 
+	        size - mh->mtHeaderSize * 2) == HFILE_ERROR) {
+    GlobalFree(hmf);
+    return 0;
+  }
+  
+  _lclose(hFile);
 
   if (mh->mtType != 1) {
-    GlobalFree(mf->hMetaHdr);
     GlobalFree(hmf);
     return 0;
   }
-
-  GlobalUnlock(mf->hMetaHdr);
+  
   GlobalUnlock(hmf);
   return hmf;
 
@@ -77,34 +86,30 @@
 /******************************************************************
  *         CreateMetafile         GDI.125
  */
+
 HANDLE CreateMetaFile(LPCTSTR lpFilename)
 {
     DC *dc;
     HANDLE handle;
-    METAFILE *mf;
     METAHEADER *mh;
-    HANDLETABLE *ht;
-
+    int hFile;
+    
     dprintf_metafile(stddeb,"CreateMetaFile: %s\n", lpFilename);
 
     handle = GDI_AllocObject(sizeof(DC), METAFILE_DC_MAGIC);
-    if (!handle) return 0;
+    
+    if (!handle) 
+      return 0;
+    
     dc = (DC *)GDI_HEAP_LIN_ADDR(handle);
 
-    if (!(dc->w.hMetaFile = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE)))) {
+    if (!(dc->w.hMetaFile = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAHEADER)))) {
         GDI_FreeObject(handle);
 	return 0;
     }
-    mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
-    if (!(mf->hMetaHdr = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAHEADER))))
-    {
-        GDI_FreeObject(handle);
-	GlobalFree(dc->w.hMetaFile);
-	return 0;
-    }
-    mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    
+    mh = (METAHEADER *)GlobalLock(dc->w.hMetaFile);
 
-    mf->wMagic = METAFILE_MAGIC;
     mh->mtHeaderSize = MFHEADERSIZE / 2;
     mh->mtVersion = MFVERSION;
     mh->mtSize = MFHEADERSIZE / 2;
@@ -114,15 +119,15 @@
 
     if (lpFilename)          /* disk based metafile */
     {
-	mh->mtType = 1;
-	strcpy(mf->Filename, lpFilename);
-	mf->hFile = _lcreat(lpFilename, 0);
-	if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
+	mh->mtType = 1;     /* disk */
+	hFile = _lcreat(lpFilename, 0);
+	if (_lwrite(hFile, (char *)mh, MFHEADERSIZE) == -1)
 	{
-	    GlobalFree(mf->hMetaHdr);
 	    GlobalFree(dc->w.hMetaFile);
 	    return 0;
 	}
+	mh->mtNoParameters = hFile; /* store file descriptor here */
+	                            /* windows probably uses this too*/
     }
     else                     /* memory based metafile */
 	mh->mtType = 0;
@@ -131,63 +136,102 @@
     HTLen = HTINCR;
     hHT = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, 
 		      sizeof(HANDLETABLE) * HTLen);
-    ht = (HANDLETABLE *)GlobalLock(hHT);
-
-    GlobalUnlock(mf->hMetaHdr);
+    
     GlobalUnlock(dc->w.hMetaFile);
     return handle;
 }
 
 
 /******************************************************************
+ *         CopyMetafile         GDI.151 Niels de Carpentier, April 1996
+ */
+
+HMETAFILE CopyMetaFile(HMETAFILE hSrcMetaFile, LPCSTR lpFilename)
+{
+    HMETAFILE handle = 0;
+    METAHEADER *mh;
+    METAHEADER *mh2;
+    int hFile;
+    
+    dprintf_metafile(stddeb,"CopyMetaFile: %s\n", lpFilename);
+    
+    mh = (METAHEADER *)GlobalLock(hSrcMetaFile);
+    
+    if (!mh)
+      return 0;
+    
+    if (lpFilename)          /* disk based metafile */
+        {
+	hFile = _lcreat(lpFilename, 0);
+	if (_lwrite(hFile, (char *)mh, mh->mtSize * 2) == -1)
+	    {
+	    _lclose(hFile);
+	    return 0;
+	    }
+	_lclose(hFile);
+        }
+    else                     /* memory based metafile */
+        {
+	handle = GlobalAlloc(GMEM_MOVEABLE,mh->mtSize * 2);
+	mh2 = (METAHEADER *)GlobalLock(handle);
+	memcpy(mh2,mh, mh->mtSize * 2);
+	GlobalUnlock(handle);
+        }
+    
+    return handle;
+}
+
+
+/******************************************************************
  *         CloseMetafile         GDI.126
  */
+
 HMETAFILE CloseMetaFile(HDC hdc)
 {
     DC *dc;
-    METAFILE *mf;
     METAHEADER *mh;
     HMETAFILE hmf;
-/*    METARECORD *mr = (METARECORD *)&buffer;*/
-
+    HFILE hFile;
+    
     dprintf_metafile(stddeb,"CloseMetaFile\n");
 
     dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC);
-    if (!dc) return 0;
-    mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
-    mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    
+    if (!dc) 
+      return 0;
+    
+    mh = (METAHEADER *)GlobalLock(dc->w.hMetaFile);
 
     /* Construct the end of metafile record - this is documented
      * in SDK Knowledgebase Q99334.
      */
+
     if (!MF_MetaParam0(dc, META_EOF))
     {
-	GlobalFree(mf->hMetaHdr);
 	GlobalFree(dc->w.hMetaFile);
 	return 0;
     }	
 
     if (mh->mtType == 1)        /* disk based metafile */
     {
-	if (_llseek(mf->hFile, 0L, 0) == -1)
-	{
-	    GlobalFree(mf->hMetaHdr);
-	    GlobalFree(dc->w.hMetaFile);
-	    return 0;
-	}
-	if (_lwrite(mf->hFile, (char *)mh, MFHEADERSIZE) == -1)
-	{
-	    GlobalFree(mf->hMetaHdr);
-	    GlobalFree(dc->w.hMetaFile);
-	    return 0;
-	}
-	_lclose(mf->hFile);
+        hFile = mh->mtNoParameters;
+	mh->mtNoParameters = 0;
+        if (_llseek(hFile, 0L, 0) == -1)
+        {
+            GlobalFree(dc->w.hMetaFile);
+            return 0;
+        }
+        if (_lwrite(hFile, (char *)mh, MFHEADERSIZE) == -1)
+        {
+            GlobalFree(dc->w.hMetaFile);
+            return 0;
+        }
+        _lclose(hFile);
     }
 
     /* delete the handle table */
     GlobalFree(hHT);
 
-    GlobalUnlock(mf->hMetaHdr);
     hmf = dc->w.hMetaFile;
     GlobalUnlock(hmf);
     GDI_FreeObject(hdc);
@@ -198,14 +242,14 @@
 /******************************************************************
  *         DeleteMetafile         GDI.127
  */
+
 BOOL DeleteMetaFile(HMETAFILE hmf)
 {
-    METAFILE *mf = (METAFILE *)GlobalLock(hmf);
+    METAHEADER *mh = (METAHEADER *)GlobalLock(hmf);
 
-    if (!mf || mf->wMagic != METAFILE_MAGIC)
+    if (!mh)
 	return FALSE;
 
-    GlobalFree(mf->hMetaHdr);
     GlobalFree(hmf);
     return TRUE;
 }
@@ -214,60 +258,73 @@
 /******************************************************************
  *         PlayMetafile         GDI.123
  */
+
 BOOL PlayMetaFile(HDC hdc, HMETAFILE hmf)
 {
-    METAFILE *mf = (METAFILE *)GlobalLock(hmf);
-    METAHEADER *mh;
+    METAHEADER *mh = (METAHEADER *)GlobalLock(hmf);
     METARECORD *mr;
     HANDLETABLE *ht;
-    char *buffer = (char *)NULL;
-
-    if (mf->wMagic != METAFILE_MAGIC)
-	return FALSE;
-
-    mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
-    if (mh->mtType == 1)       /* disk based metafile */
-    {
-	mf->hFile = _lopen(mf->Filename, OF_READ);
-	mf->hBuffer = GlobalAlloc(GMEM_MOVEABLE, mh->mtMaxRecord * 2);
-	buffer = (char *)GlobalLock(mf->hBuffer);
-	_llseek(mf->hFile, mh->mtHeaderSize * 2, 0);
-	mf->MetaOffset = mh->mtHeaderSize * 2;
-    }
-    else if (mh->mtType == 0)   /* memory based metafile */
-	mf->MetaOffset = mh->mtHeaderSize * 2;
-    else                       /* not a valid metafile type */
-	return FALSE;
-
+    int offset = 0;
+    
+    dprintf_metafile(stddeb,"PlayMetaFile(%04x %04x)\n",hdc,hmf);
+    
     /* create the handle table */
     hHT = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,
 		      sizeof(HANDLETABLE) * mh->mtNoObjects);
     ht = (HANDLETABLE *)GlobalLock(hHT);
 
     /* loop through metafile playing records */
-    while (mf->MetaOffset < mh->mtSize * 2)
+    offset = mh->mtHeaderSize * 2;
+    while (offset < mh->mtSize * 2)
     {
-	if (mh->mtType == 1)   /* disk based metafile */
-	{
-	    FILE_Read(mf->hFile, buffer, sizeof(METARECORD));
-	    mr = (METARECORD *)buffer;
-	    FILE_Read(mf->hFile, (char *)(mr->rdParam + 1), (mr->rdSize * 2) -
-		                                       sizeof(METARECORD));
-	    mf->MetaOffset += mr->rdSize * 2;
-	}
-	else                   /* memory based metafile */
-	{
-	    mr = (METARECORD *)((char *)mh + mf->MetaOffset);
-	    mf->MetaOffset += mr->rdSize * 2;
-	}
+	mr = (METARECORD *)((char *)mh + offset);
+	dprintf_metafile(stddeb,"offset = %04x size = %08lx function = %04x\n",
+			 offset,mr->rdSize,mr->rdFunction);
+	offset += mr->rdSize * 2;
 	PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects);
     }
 
-    /* close disk based metafile and free buffer */
-    if (mh->mtType == 1)
+    /* free handle table */
+    GlobalFree(hHT);
+
+    return TRUE;
+}
+
+
+/******************************************************************
+ *         EnumMetafile         GDI.175    
+ *                                    Niels de carpentier, april 1996
+ */
+
+BOOL EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC lpEnumFunc,LPARAM lpData)
+{
+    METAHEADER *mh = (METAHEADER *)GlobalLock(hmf);
+    METARECORD *mr;
+    HANDLETABLE *ht;
+    int offset = 0;
+  
+    dprintf_metafile(stddeb,"EnumMetaFile(%04x, %04x, %08lx, %08lx)\n",
+		     hdc, hmf, (DWORD)lpEnumFunc, lpData);
+   
+    /* create the handle table */
+    
+    hHT = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
+		     sizeof(HANDLETABLE) * mh->mtNoObjects);
+    ht = (HANDLETABLE *)GlobalLock(hHT);
+   
+    offset = mh->mtHeaderSize * 2;
+    
+    /* loop through metafile records */
+    
+    while (offset < (mh->mtSize * 2))
     {
-	GlobalFree(mf->hBuffer);
-	_lclose(mf->hFile);
+	mr = (METARECORD *)((char *)mh + offset);
+        if (!CallEnumMetafileProc(lpEnumFunc, hdc, MAKE_SEGPTR(ht),
+	                          MAKE_SEGPTR(mr), mh->mtNoObjects,
+				  (LONG)lpData))
+	    break;
+
+	offset += (mr->rdSize * 2);
     }
 
     /* free handle table */
@@ -280,6 +337,7 @@
 /******************************************************************
  *         PlayMetaFileRecord      GDI.176
  */
+
 void PlayMetaFileRecord(HDC hdc, HANDLETABLE *ht, METARECORD *mr,
 			                           WORD nHandles)
 {
@@ -288,6 +346,9 @@
     char *ptr;
     BITMAPINFOHEADER *infohdr;
 
+    dprintf_metafile(stddeb,"PlayMetaFileRecord(%04x %08lx %08lx %04x)\n",
+		     hdc,(LONG)ht, (LONG)mr, nHandles);
+    
     switch (mr->rdFunction)
     {
     case META_EOF:
@@ -552,7 +613,52 @@
         }
         break;
         /* End new metafile operations. */
-
+    
+    case META_STRETCHDIB:
+      {
+      LPSTR bits;
+      LPBITMAPINFO info;
+      int offset;
+      info = (LPBITMAPINFO) &(mr->rdParam[11]);
+      if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
+	{
+        if (info->bmiHeader.biClrUsed)
+	  {
+	  if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
+	    offset = info->bmiHeader.biClrUsed * 4;
+          else
+	    offset = (1 << info->bmiHeader.biBitCount) * 4;
+          }
+        else
+	  offset = (1 << info->bmiHeader.biBitCount) * 4;
+	}
+      else if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+	{
+	if (info->bmiHeader.biClrUsed)
+	  {
+	  if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount))
+	    offset = info->bmiHeader.biClrUsed * 3;
+          else
+	    offset = (1 << info->bmiHeader.biBitCount) * 3;
+          }
+        else
+	  offset = (1 << info->bmiHeader.biBitCount) * 3;
+	}
+      else
+	{
+	fprintf(stderr,"Unknown size for BITMAPHEADER in PlayMetaRecord!\n");
+	break;
+	}
+	
+      offset += info->bmiHeader.biSize; 
+      bits = (LPSTR) info + offset;
+      StretchDIBits(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8],
+		    mr->rdParam[7],mr->rdParam[6],mr->rdParam[5],
+		    mr->rdParam[4],mr->rdParam[3],bits,info,
+		    mr->rdParam[2],(DWORD)mr->rdParam[0]);
+      }
+      break;
+		    
     default:
 	fprintf(stddeb,"PlayMetaFileRecord: Unknown record type %x\n",
 	                                      mr->rdFunction);
@@ -564,33 +670,12 @@
  *
  * Trade in a meta file object handle for a handle to the meta file memory
  */
+
 HANDLE GetMetaFileBits(HMETAFILE hmf)
 {
+    dprintf_metafile(stddeb,"GetMetaFileBits: hMem out: %04x\n", hmf);
 
-    /* save away the meta file bits handle */
-    METAFILE *mf = (METAFILE *)GlobalLock(hmf);
-    HANDLE hMem = mf->hMetaHdr;
-    METAHEADER *mh = (METAHEADER *)GlobalLock(hMem);
-
-    dprintf_metafile(stddeb,"GetMetaFileBits: hmf in: %04x\n", hmf);
-
-    /* can't get bits of disk based metafile */
-    /* FIXME: should the disk file be loaded in this case? */
-    if(mh->mtType == 1) {
-        fprintf(stderr,
-            "GetMetaFileBits: application requested bits of disk meta file.\n");
-        GlobalUnlock(hMem);
-        GlobalUnlock(hmf);
-        return FALSE;
-    }
-    
-    /* unlock the memory and invalidate the metafile handle */
-    GlobalUnlock(hMem);
-    GlobalFree(hmf);
-
-    dprintf_metafile(stddeb,"GetMetaFileBits: hMem out: %04x\n", hMem);
-
-    return hMem;
+    return hmf;
 }
 
 /******************************************************************
@@ -598,76 +683,50 @@
  *
  * Trade in a meta file memory handle for a handle to a meta file object
  */
+
 HMETAFILE SetMetaFileBits(HANDLE hMem)
 {
-    HMETAFILE hmf;
-    METAFILE *mf;
-    METAHEADER *mh = (METAHEADER *)GlobalLock(hMem);
+    dprintf_metafile(stddeb,"SetMetaFileBits: hmf out: %04x\n", hMem);
 
-    dprintf_metafile(stddeb,"SetMetaFileBits: hMem in: %04x\n", hMem);
-
-    if (!mh) return FALSE;
-
-    /* now it is a memory meta file */
-    mh->mtType = 0;
-
-    hmf = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILE));
-    mf = (METAFILE *)GlobalLock(hmf);
-    if (!mf) {
-      GlobalUnlock(hMem);
-      GlobalFree(hmf);
-      return FALSE;
-    }
-
-    /* use the supplied memory handle */
-    mf->hMetaHdr = hMem;
-    mf->wMagic = METAFILE_MAGIC;
-    mf->MetaOffset = mh->mtHeaderSize * 2;
-    mf->hFile = (int) (mf->hBuffer = (HANDLE) NULL);
-
-    GlobalUnlock(hMem);
-    GlobalUnlock(hmf);
-
-    dprintf_metafile(stddeb,"SetMetaFileBits: hmf out: %04x\n", hmf);
-
-    return hmf;
+    return hMem;
 }
 
 /******************************************************************
  *         MF_WriteRecord
  */
-BOOL MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen)
+
+HMETAFILE MF_WriteRecord(HMETAFILE hmf, METARECORD *mr, WORD rlen)
 {
     DWORD len;
-    METAFILE *mf = (METAFILE *)GlobalLock(hmf);
-    METAHEADER *mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
-
+    METAHEADER *mh = (METAHEADER *)GlobalLock(hmf);
+    
     if (mh->mtType == 0)          /* memory based metafile */
     {
 	len = mh->mtSize * 2 + rlen;
-	GlobalUnlock(mf->hMetaHdr);
-	mf->hMetaHdr = GlobalReAlloc(mf->hMetaHdr, len, GMEM_MOVEABLE);
-	mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+	GlobalUnlock(hmf);
+	hmf = GlobalReAlloc(hmf, len, GMEM_MOVEABLE); /* hmf can change */
+	mh = (METAHEADER *)GlobalLock(hmf);
 	memcpy((WORD *)mh + mh->mtSize, mr, rlen);
     }
     else if (mh->mtType == 1)     /* disk based metafile */
     {
-	if (_lwrite(mf->hFile, (char *)mr, rlen) == -1)
+      dprintf_metafile(stddeb,"Writing record to disk\n");
+	if (_lwrite(mh->mtNoParameters, (char *)mr, rlen) == -1)
 	{
-	    GlobalUnlock(mf->hMetaHdr);
-	    return FALSE;
+	    GlobalUnlock(hmf);
+	    return 0;
 	}
     }
     else
     {
-	GlobalUnlock(mf->hMetaHdr);
-	return FALSE;
+	GlobalUnlock(hmf);
+	return 0;
     }
 
     mh->mtSize += rlen / 2;
     mh->mtMaxRecord = MAX(mh->mtMaxRecord, rlen / 2);
-    GlobalUnlock(mf->hMetaHdr);
-    return TRUE;
+    GlobalUnlock(hmf);
+    return hmf;
 }
 
 
@@ -676,6 +735,7 @@
  *
  *    Add a handle to an external handle table and return the index
  */
+
 int MF_AddHandle(HANDLETABLE *ht, WORD htlen, HANDLE hobj)
 {
     int i;
@@ -697,6 +757,7 @@
  *
  *    Add a handle to the internal handle table and return the index
  */
+
 int MF_AddHandleInternal(HANDLE hobj)
 {
     int i;
@@ -725,14 +786,19 @@
 /******************************************************************
  *         MF_MetaParam0
  */
+
 BOOL MF_MetaParam0(DC *dc, short func)
 {
     char buffer[8];
     METARECORD *mr = (METARECORD *)&buffer;
-
+    HMETAFILE handle;
+    
     mr->rdSize = 3;
     mr->rdFunction = func;
-    return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
+    
+    return handle; 
 }
 
 
@@ -743,11 +809,15 @@
 {
     char buffer[8];
     METARECORD *mr = (METARECORD *)&buffer;
-
+    HMETAFILE handle;
+    
     mr->rdSize = 4;
     mr->rdFunction = func;
     *(mr->rdParam) = param1;
-    return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
+
+    return handle;
 }
 
 
@@ -758,43 +828,54 @@
 {
     char buffer[10];
     METARECORD *mr = (METARECORD *)&buffer;
-
+    HMETAFILE handle;
+    
     mr->rdSize = 5;
     mr->rdFunction = func;
     *(mr->rdParam) = param2;
     *(mr->rdParam + 1) = param1;
-    return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
+    
+    return handle;
 }
 
 
 /******************************************************************
  *         MF_MetaParam4
  */
+
 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2, 
 		   short param3, short param4)
 {
     char buffer[14];
     METARECORD *mr = (METARECORD *)&buffer;
-
+    HMETAFILE handle;
+    
     mr->rdSize = 7;
     mr->rdFunction = func;
     *(mr->rdParam) = param4;
     *(mr->rdParam + 1) = param3;
     *(mr->rdParam + 2) = param2;
     *(mr->rdParam + 3) = param1;
-    return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
+    
+    return handle;
 }
 
 
 /******************************************************************
  *         MF_MetaParam6
  */
+
 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2, 
 		   short param3, short param4, short param5, short param6)
 {
     char buffer[18];
     METARECORD *mr = (METARECORD *)&buffer;
-
+    HMETAFILE handle;
+    
     mr->rdSize = 9;
     mr->rdFunction = func;
     *(mr->rdParam) = param6;
@@ -803,7 +884,10 @@
     *(mr->rdParam + 3) = param3;
     *(mr->rdParam + 4) = param2;
     *(mr->rdParam + 5) = param1;
-    return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
+    
+    return handle; 
 }
 
 
@@ -816,7 +900,8 @@
 {
     char buffer[22];
     METARECORD *mr = (METARECORD *)&buffer;
-
+    HMETAFILE handle;
+    
     mr->rdSize = 11;
     mr->rdFunction = func;
     *(mr->rdParam) = param8;
@@ -827,48 +912,55 @@
     *(mr->rdParam + 5) = param3;
     *(mr->rdParam + 6) = param2;
     *(mr->rdParam + 7) = param1;
-    return MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
+    
+    return handle;
 }
 
 
 /******************************************************************
  *         MF_CreateBrushIndirect
  */
+
 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
 {
     int index;
-    BOOL rc;
+    HMETAFILE handle;
     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGBRUSH)];
     METARECORD *mr = (METARECORD *)&buffer;
-    METAFILE *mf;
     METAHEADER *mh;
 
     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGBRUSH) - 2) / 2;
     mr->rdFunction = META_CREATEBRUSHINDIRECT;
     memcpy(&(mr->rdParam), logbrush, sizeof(LOGBRUSH));
-    if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
+    if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, 
+					  mr, mr->rdSize * 2)))
 	return FALSE;
 
     mr->rdSize = sizeof(METARECORD) / 2;
     mr->rdFunction = META_SELECTOBJECT;
+
     if ((index = MF_AddHandleInternal(hBrush)) == -1)
 	return FALSE;
 
-    mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
-    mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    mh = (METAHEADER *)GlobalLock(dc->w.hMetaFile);
     *(mr->rdParam) = index;
     if (index >= mh->mtNoObjects)
 	mh->mtNoObjects++;
-    rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
-    GlobalUnlock(mf->hMetaHdr);
+    
     GlobalUnlock(dc->w.hMetaFile);
-    return rc;
+    handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
+
+    return handle;
 }
 
 
 /******************************************************************
  *         MF_CreatePatternBrush
  */
+
 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush)
 {
     DWORD len, bmSize, biSize;
@@ -878,9 +970,8 @@
     BITMAPINFO *info;
     BITMAPINFOHEADER *infohdr;
     int index;
-    BOOL rc;
+    HMETAFILE handle;
     char buffer[sizeof(METARECORD)];
-    METAFILE *mf;
     METAHEADER *mh;
 
     switch (logbrush->lbStyle)
@@ -930,98 +1021,103 @@
     default:
         return FALSE;
     }
-    if (!MF_WriteRecord(dc->w.hMetaFile, mr, len))
+    if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr, len)))
     {
 	GlobalFree(hmr);
 	return FALSE;
     }
 
     GlobalFree(hmr);
+    
     mr = (METARECORD *)&buffer;
     mr->rdSize = sizeof(METARECORD) / 2;
     mr->rdFunction = META_SELECTOBJECT;
     if ((index = MF_AddHandleInternal(hBrush)) == -1)
 	return FALSE;
 
-    mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
-    mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    mh = (METAHEADER *)GlobalLock(dc->w.hMetaFile);
     *(mr->rdParam) = index;
     if (index >= mh->mtNoObjects)
 	mh->mtNoObjects++;
-    rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
-    GlobalUnlock(mf->hMetaHdr);
     GlobalUnlock(dc->w.hMetaFile);
-    return rc;
+    handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
+
+    return handle;
 }
 
 
 /******************************************************************
  *         MF_CreatePenIndirect
  */
+
 BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen)
 {
     int index;
-    BOOL rc;
+    HMETAFILE handle;
     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGPEN)];
     METARECORD *mr = (METARECORD *)&buffer;
-    METAFILE *mf;
     METAHEADER *mh;
 
     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGPEN) - 2) / 2;
     mr->rdFunction = META_CREATEPENINDIRECT;
     memcpy(&(mr->rdParam), logpen, sizeof(LOGPEN));
-    if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
+    if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr, 
+					   mr->rdSize * 2)))
 	return FALSE;
 
     mr->rdSize = sizeof(METARECORD) / 2;
     mr->rdFunction = META_SELECTOBJECT;
+
     if ((index = MF_AddHandleInternal(hPen)) == -1)
 	return FALSE;
 
-    mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
-    mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    mh = (METAHEADER *)GlobalLock(dc->w.hMetaFile);
     *(mr->rdParam) = index;
     if (index >= mh->mtNoObjects)
 	mh->mtNoObjects++;
-    rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
-    GlobalUnlock(mf->hMetaHdr);
     GlobalUnlock(dc->w.hMetaFile);
-    return rc;
+    handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
+    
+    return handle;
 }
 
 
 /******************************************************************
  *         MF_CreateFontIndirect
  */
+
 BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT *logfont)
 {
     int index;
-    BOOL rc;
+    HMETAFILE handle;
     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT)];
     METARECORD *mr = (METARECORD *)&buffer;
-    METAFILE *mf;
     METAHEADER *mh;
 
     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT) - 2) / 2;
     mr->rdFunction = META_CREATEFONTINDIRECT;
     memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT));
-    if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
+    if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr, 
+					  mr->rdSize * 2)))
 	return FALSE;
 
     mr->rdSize = sizeof(METARECORD) / 2;
     mr->rdFunction = META_SELECTOBJECT;
+
     if ((index = MF_AddHandleInternal(hFont)) == -1)
 	return FALSE;
 
-    mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
-    mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    mh = (METAHEADER *)GlobalLock(dc->w.hMetaFile);
     *(mr->rdParam) = index;
     if (index >= mh->mtNoObjects)
 	mh->mtNoObjects++;
-    rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
-    GlobalUnlock(mf->hMetaHdr);
     GlobalUnlock(dc->w.hMetaFile);
-    return rc;
+    handle  = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
+    
+    return handle;
 }
 
 
@@ -1030,7 +1126,7 @@
  */
 BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count)
 {
-    BOOL rc;
+    HMETAFILE handle;
     DWORD len;
     HANDLE hmr;
     METARECORD *mr;
@@ -1047,9 +1143,10 @@
     memcpy(mr->rdParam + 1, str, count);
     *(mr->rdParam + ((count + 1) >> 1) + 1) = y;
     *(mr->rdParam + ((count + 1) >> 1) + 2) = x;
-    rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
     GlobalFree(hmr);
-    return rc;
+    return handle;
 }
 
 
@@ -1058,7 +1155,7 @@
  */
 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT pt, short count)
 {
-    BOOL rc;
+    HMETAFILE handle;
     DWORD len;
     HANDLE hmr;
     METARECORD *mr;
@@ -1073,9 +1170,10 @@
     mr->rdFunction = func;
     *(mr->rdParam) = count;
     memcpy(mr->rdParam + 1, pt, count * 4);
-    rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    handle  = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    dc->w.hMetaFile = handle;
     GlobalFree(hmr);
-    return rc;
+    return handle;
 }
 
 
diff --git a/programs/progman/ChangeLog b/programs/progman/ChangeLog
index 7688fe9..12efc7a 100644
--- a/programs/progman/ChangeLog
+++ b/programs/progman/ChangeLog
@@ -1,3 +1,8 @@
+Sun Apr 14 20:09:19 1996  Pablo Saratxaga <srtxg@linux.chanae.stben.be>
+
+	* [Fr.rc] (new)
+	Added French language support.
+
 Sun Mar 24 12:28:22 1996  Ulrich Schmid  <uschmid@mail.hh.provi.de>
 
 	* [Strings_En.c] [Strings_De.c] (deleted)
diff --git a/programs/progman/Fr.rc b/programs/progman/Fr.rc
new file mode 100644
index 0000000..251b5bd
--- /dev/null
+++ b/programs/progman/Fr.rc
@@ -0,0 +1,122 @@
+/*
+ * Program Manager
+ *
+ * Copyright 1996 Ulrich Schmid
+ * French Fr.rc by Pablo Saratxaga <srtxg@linux.chanae.stben.be>
+ */
+
+#define LANGUAGE_ID                  Fr
+#define LANGUAGE_NUMBER              4
+#define LANGUAGE_MENU_ITEM           "&Français"
+
+/* Menu */
+
+#define MENU_FILE                    "&Fichier"
+#define MENU_FILE_NEW                "&Nouveau..."
+#define MENU_FILE_OPEN               "O&uvrir\tEntrée"
+#define MENU_FILE_MOVE               "&Déplacer...\tF7"
+#define MENU_FILE_COPY               "&Copier...\tF8"
+#define MENU_FILE_DELETE             "&Supprimer\tSuppr"
+#define MENU_FILE_ATTRIBUTES         "&Propriétés...\tAlt+Entrée"
+#define MENU_FILE_EXECUTE            "E&xécuter..."
+#define MENU_FILE_EXIT               "&Quitter Windows..."
+
+#define MENU_OPTIONS                 "&Options"
+#define MENU_OPTIONS_AUTO_ARRANGE    "Réorg&anisation automatique"
+#define MENU_OPTIONS_MIN_ON_RUN      "&Réduire à l'utilisation"
+#define MENU_OPTIONS_SAVE_SETTINGS   "&Enregistrer la configuration en quittant"
+
+#define MENU_WINDOWS                 "F&enêtre"
+#define MENU_WINDOWS_OVERLAP         "&Cascade\tMaj+F5"
+#define MENU_WINDOWS_SIDE_BY_SIDE    "&Mosaïque\tMaj+F4"
+#define MENU_WINDOWS_ARRANGE         "&Réorganiser les icônes"
+
+#define MENU_LANGUAGE                "&Langue"
+
+#define MENU_HELP                    "&?"
+#define MENU_HELP_CONTENTS           "&Index"
+#define MENU_HELP_SEARCH             "&Rechercher l'Aide sur..."
+#define MENU_HELP_HELP_ON_HELP       "&Utiliser l'Aide"
+#define MENU_HELP_TUTORIAL           "Didacticiel &Windows"
+
+#define MENU_INFO                    "&Info..."
+#define MENU_INFO_LICENSE            "&License"
+#define MENU_INFO_NO_WARRANTY        "&NO WARRANTY"
+#define MENU_INFO_ABOUT_WINE         "&A propos de WINE"
+
+/* Dialogs */
+
+#define DIALOG_OK                    "OK"
+#define DIALOG_CANCEL                "Annuler"
+#define DIALOG_BROWSE                "Pa&rcourir..."
+#define DIALOG_HELP                  "&Aide"
+
+#define DIALOG_NEW_CAPTION           "Nouveau"
+#define DIALOG_NEW_NEW               "Nouveau"
+#define DIALOG_NEW_GROUP             "&Groupe de programmes"
+#define DIALOG_NEW_PROGRAM           "&Programme"
+
+#define DIALOG_MOVE_CAPTION          "Déplacer un programme"
+#define DIALOG_MOVE_PROGRAM          "Déplacer le programme:"
+#define DIALOG_MOVE_FROM_GROUP       "A partir du groupe:"
+#define DIALOG_MOVE_TO_GROUP         "&Vers le groupe:"
+
+#define DIALOG_COPY_CAPTION          "Copier un programme"
+#define DIALOG_COPY_PROGRAM          "Copier le programme:"
+#define DIALOG_COPY_FROM_GROUP       DIALOG_MOVE_FROM_GROUP
+#define DIALOG_COPY_TO_GROUP         DIALOG_MOVE_TO_GROUP
+
+#define DIALOG_GROUP_CAPTION         "Propriétés de groupe"
+#define DIALOG_GROUP_DESCRIPTION     "&Nom:"
+#define DIALOG_GROUP_FILE            "&Fichier de groupe:"
+
+#define DIALOG_PROGRAM_CAPTION       "Propriétés de programme"
+#define DIALOG_PROGRAM_DESCRIPTION   DIALOG_GROUP_DESCRIPTION
+#define DIALOG_PROGRAM_COMMAND_LINE  "&Ligne de commande:"
+#define DIALOG_PROGRAM_DIRECTORY     "Répertoire de tra&vail:"
+#define DIALOG_PROGRAM_HOT_KEY       "&Touche de raccourci:"
+#define DIALOG_PROGRAM_SYMBOL        "Réduire à l'&utilisation"
+#define DIALOG_PROGRAM_OTHER_SYMBOL  "&Changer d'icône..."
+
+#define DIALOG_SYMBOL_CAPTION        "Changer d'icône"
+#define DIALOG_SYMBOL_FILE           "&Nom:"
+#define DIALOG_SYMBOL_CURRENT        "Icône a&ctuelle:"
+
+#define DIALOG_EXECUTE_CAPTION       "Exécuter"
+#define DIALOG_EXECUTE_COMMAND_LINE  DIALOG_PROGRAM_COMMAND_LINE
+#define DIALOG_EXECUTE_SYMBOL        DIALOG_PROGRAM_SYMBOL
+
+
+/* Strings */
+
+#define STRING_PROGRAM_MANAGER            "Gestionaire de programmes"
+#define STRING_ERROR                      "ERREUR"
+#define STRING_WARNING                    "WARNING"
+#define STRING_INFO                       "Information"
+#define STRING_DELETE                     "Supprimer"
+#define STRING_DELETE_GROUP_s             "Voulez-vous supprimer le groupe '%s'?"
+#define STRING_DELETE_PROGRAM_s           "Voulez-vous supprimer le programme '%s'?"
+#define STRING_NOT_IMPLEMENTED            "Non implementé"
+#define STRING_FILE_READ_ERROR_s          "Impossible d'ouvrir '%s'."
+#define STRING_FILE_WRITE_ERROR_s         "Impossible d'enregistrer '%s'."
+
+#define STRING_GRPFILE_READ_ERROR_s       "\
+Impossible d'ouvrir le groupe '%s'.\n\
+Voulez-vous que le Gestionnaire de programmes essaie\n\
+de l'ouvrir dans les prochaines sessions?"
+
+#define STRING_OUT_OF_MEMORY              "Mémoire insuffisante."
+#define STRING_WINHELP_ERROR              "Impossible d'afficher l'Aide."
+#define STRING_UNKNOWN_FEATURE_s          "Caracteristique inconnue dans %s"
+#define STRING_FILE_NOT_OVERWRITTEN_s     "Le fichier `%s' existe. Non écrasé."
+#define STRING_SAVE_GROUP_AS_s            "Groupe sauvé sous `%s' pour éviter l'écrasement du fichier original."
+
+#define STRING_NO_HOT_KEY                 "Aucun"
+
+#define STRING_ALL_FILES                  "Tout fichier (*.*)"
+#define STRING_PROGRAMS                   "Programmes"
+#define STRING_LIBRARIES_DLL              "Bibliothèques (*.dll)"
+#define STRING_SYMBOL_FILES               "Icônes"
+#define STRING_SYMBOLS_ICO                "Icônes (*.ico)"
+
+#include "Xx.rc"
diff --git a/programs/progman/Makefile.in b/programs/progman/Makefile.in
index ee8a900..37af394 100644
--- a/programs/progman/Makefile.in
+++ b/programs/progman/Makefile.in
@@ -3,7 +3,7 @@
 PROGRAMS = progman
 ALL_LIBS = $(WINELIB) $(X_LIBS) $(XPM_LIB) $(XLIB) $(LDLIBS)
 
-LANGUAGES   = En De
+LANGUAGES   = En De Fr
 LICENSELANG = En
 
 MOSTOBJS = \
diff --git a/programs/progman/main.c b/programs/progman/main.c
index 561fc27..1dd5e6d 100644
--- a/programs/progman/main.c
+++ b/programs/progman/main.c
@@ -12,6 +12,10 @@
 #include <resource.h>
 #include <options.h>
 #include <shell.h>
+void LIBWINE_Register_accel();
+void LIBWINE_Register_De();
+void LIBWINE_Register_En();
+void LIBWINE_Register_Fr();
 #endif
 
 GLOBALS Globals;
@@ -39,6 +43,7 @@
   LIBWINE_Register_accel();
   LIBWINE_Register_De();
   LIBWINE_Register_En();
+  LIBWINE_Register_Fr();
 #endif
 
 #ifndef WINELIB
@@ -62,8 +67,8 @@
   }
 #endif
 
-  /* Select Language (FIXME) */
-#ifndef WINELIB
+  /* Select Language */
+#ifdef WINELIB
   Globals.lpszLanguage = langNames[Options.language];
 #else
   Globals.lpszLanguage = "En";
diff --git a/programs/progman/string.c b/programs/progman/string.c
index cb6e160..f33941b 100644
--- a/programs/progman/string.c
+++ b/programs/progman/string.c
@@ -120,8 +120,8 @@
   if (Globals.hMainMenu) DestroyMenu(Globals.hMainMenu);
   Globals.hMainMenu = hMainMenu;
 
-#ifndef WINELIB
-  /* Update system menus (FIXME) */
+#ifdef WINELIB
+  /* Update system menus */
   for (i = 0; langNames[i] && lstrcmp(lang, langNames[i]);) i++;
   if (langNames[i]) Options.language = i;
 
diff --git a/resources/TODO b/resources/TODO
index 31be6f5..eff85ce 100644
--- a/resources/TODO
+++ b/resources/TODO
@@ -45,6 +45,7 @@
 Today it works well for:
 * English 
 * German
+* French
 ...to be continued......
 
 Thank you.
diff --git a/resources/sysres_Fr.rc b/resources/sysres_Fr.rc
index 3a241bd..3df4265 100644
--- a/resources/sysres_Fr.rc
+++ b/resources/sysres_Fr.rc
@@ -144,25 +144,37 @@
  PUSHBUTTON "Annuler", 2, 206, 24, 56, 14, WS_GROUP | WS_TABSTOP
 }
 
-
-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 "Couleurs"
 FONT 8, "Helv"
 {
- LTEXT "Couleurs de &base:", 1088, 6, 6, 40, 9
- LTEXT "%Couleurs personnalisées:", 1089, 6, 126, 40, 9
- LTEXT "Couleur|&Uni", 1090, 100, 146, 40, 9
- LTEXT "&Couleur:", 1091, 150, 126, 40, 9
- LTEXT "&Sat. :", 1092, 150, 146, 40, 9
- LTEXT "&Lum. :", 1093, 150, 166, 40, 9
- LTEXT "&Rouge:", 1094, 150, 126, 40, 9
- LTEXT "&Vert:", 1095, 150, 146, 40, 9
- LTEXT "&Bleu:", 1096, 150, 166, 40, 9
- DEFPUSHBUTTON "OK", 1, 6, 182, 56, 14, BS_DEFPUSHBUTTON | WS_GROUP | WS_TABSTOP
- PUSHBUTTON "&Ajouter la couleur", 1024, 120, 182, 100, 14, WS_GROUP | WS_TABSTOP
- PUSHBUTTON "&Supprimer la couleur", 1025, 6, 164, 56, 14, WS_GROUP | WS_TABSTOP
- PUSHBUTTON "Annuler", 2, 76, 182, 56, 14, WS_GROUP | WS_TABSTOP
+ LTEXT "Couleurs de &base:",   1088, 4,    4,  140, 10
+ LTEXT "&Couleurs personnalisés:",  1089, 4,   106, 140, 10
+ LTEXT "Couleur |  &Uni",  1090, 150, 151,  48, 10
+ LTEXT   "&Rouge:", 726 /*1094*/,249,126,24,10
+ EDITTEXT 706, 275,124,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT   "&Vert:",727/*1095*/,249,140,24,10
+ EDITTEXT 707, 275,138,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+  LTEXT   "Bl&eu:",728 /*1096*/,249,154,24,10
+ EDITTEXT 708, 275,152,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT  "&Teinte:" ,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 "" ,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 "Annuler", 2, 52, 166, 44, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Aide", 1038,100,166, 44, 14
+ PUSHBUTTON "&Ajouter couleur personnalisées", 712/*1024*/, 152, 166, 142, 14, WS_GROUP | WS_TABSTOP 
+ PUSHBUTTON "&Definir couleurs personnalisées >>", 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" */
 }
 
 FIND_TEXT DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 236, 62
diff --git a/resources/sysres_It.rc b/resources/sysres_It.rc
index 91ba456..5fab00a 100644
--- a/resources/sysres_It.rc
+++ b/resources/sysres_It.rc
@@ -143,28 +143,39 @@
  PUSHBUTTON "Annulla", 2, 206, 24, 56, 14, WS_GROUP | WS_TABSTOP
 }
 
-
-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 "Colore"
 FONT 8, "Helv"
 {
- LTEXT "Colori di &Base:", 1088, 6, 6, 40, 9
- LTEXT "Colori &Utente:", 1089, 6, 126, 40, 9
- LTEXT "Colore|Sol&ido", 1090, 100, 146, 40, 9
- LTEXT "&Tinta:", 1091, 150, 126, 40, 9
- LTEXT "&Sat:", 1092, 150, 146, 40, 9
- LTEXT "&Lum:", 1093, 150, 166, 40, 9
- LTEXT "&Rosso:", 1094, 150, 126, 40, 9
- 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 "&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
+ LTEXT "Colori di &Base:",   1088, 4,    4,  140, 10
+ LTEXT "Colori &Utente:",  1089, 4,   106, 140, 10
+ LTEXT "Colore |  Sol&ido",  1090, 150, 151,  48, 10
+ LTEXT   "&Rosso:", 726 /*1094*/,249,126,24,10
+ EDITTEXT 706, 275,124,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT   "&Verde:",727/*1095*/,249,140,24,10
+ EDITTEXT 707, 275,138,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT   "&Blu:",728 /*1096*/,249,154,24,10
+ EDITTEXT 708, 275,152,18,12, WS_BORDER | WS_GROUP | WS_TABSTOP
+ LTEXT  "&Tinta:" ,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 "Annulla", 2, 52, 166, 44, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "Aiuto", 1038,100,166, 44, 14
+ PUSHBUTTON "&Aggiungi ai Colori Utente",    712/*1024*/, 152, 166, 142, 14, WS_GROUP | WS_TABSTOP
+ PUSHBUTTON "&Definisci Colori Utente >>", 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"  */
 }
 
-
 FIND_TEXT DIALOG LOADONCALL MOVEABLE DISCARDABLE 36, 24, 236, 62
 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
 CAPTION "Trova"
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 5eccbf4..f84bdda 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -141,18 +141,14 @@
 
     case WM_WINDOWPOSCHANGED:
 	{
-	    /*  Note: Windoze uses unknown SWP flags 0x1000 and 0x0800 to
-	     *        decide whether to send WM_MOVE or/and WM_SIZE respectively 
-	     */
-
 	    WINDOWPOS * winPos = (WINDOWPOS *)PTR_SEG_TO_LIN(lParam);
 	    WPARAM	wp     = SIZE_RESTORED;
 
-	    if (!(winPos->flags & SWP_NOMOVE))
+	    if (!(winPos->flags & SWP_NOCLIENTMOVE))
 		SendMessage( hwnd, WM_MOVE, 0,
 		             MAKELONG( wndPtr->rectClient.left,
 				       wndPtr->rectClient.top ));
-	    if (!(winPos->flags & SWP_NOSIZE))
+	    if (!(winPos->flags & SWP_NOCLIENTSIZE))
 		 {
 	       	   if( wndPtr->dwStyle & WS_MAXIMIZE ) wp = SIZE_MAXIMIZED;
 		   else if(wndPtr->dwStyle & WS_MINIMIZE ) wp = SIZE_MINIMIZED;
diff --git a/windows/mdi.c b/windows/mdi.c
index a22d1de..1a533f8 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -12,8 +12,6 @@
  *        SetWindowPos(childHwnd,...) implicitly calls it if SWP_NOACTIVATE
  *        is not used.
  *
- * To fix:
- *	  Sticky client crollbars 
  */
 
 #include <stdlib.h>
@@ -32,6 +30,10 @@
 #include "stddebug.h"
 #include "debug.h"
 
+
+DWORD SCROLL_SetNCSbState(WND*,int,int,int,int,int,int);
+
+/* ----------------- declarations ----------------- */
 void MDI_UpdateFrameText(WND *, HWND, BOOL, LPCSTR);
 BOOL MDI_AugmentFrameMenu(MDICLIENTINFO*, WND *, HWND);
 BOOL MDI_RestoreFrameMenu(WND *, HWND);
@@ -39,8 +41,6 @@
 void ScrollChildren(HWND , UINT , WPARAM , LPARAM );
 void CalcChildScroll(HWND, WORD);
 
-/* ----------------- declarations ----------------- */
-
 static LONG MDI_ChildActivate(WND* ,HWND );
 
 /* -------- Miscellaneous service functions ----------
@@ -55,6 +55,16 @@
     return 0;
 }
 
+static void MDI_PostUpdate(HWND hwnd, MDICLIENTINFO* ci, WORD recalc)
+{
+ if( !ci->sbNeedUpdate )
+   {
+      ci->sbNeedUpdate = TRUE;
+      PostMessage( hwnd, WM_MDICALCCHILDSCROLL, 0, 0);
+   }
+ ci->sbRecalc = recalc;
+}
+
 /**********************************************************************
  *			MDI_MenuAppendItem
  */
@@ -427,9 +437,8 @@
 
         if (flagDestroy)
 	   {
+	     MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1);
             DestroyWindow(child);
-	    PostMessage(parent,WM_MDICALCCHILDSCROLL,0,0L);
-	    ci->sbRecalc |= (SB_BOTH+1);
 	   }
     }
 
@@ -808,9 +817,8 @@
 
  child->dwStyle &= ~WS_SYSMENU;
 
- /* redraw frame */
- SetWindowPos(frame->hwndSelf, 0,0,0,0,0, SWP_FRAMECHANGED | SWP_NOSIZE | 
-                                 SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER );
+ /* redraw menu */
+ DrawMenuBar(frame->hwndSelf);
 
  return 1;
 }
@@ -837,9 +845,8 @@
  RemoveMenu(frameWnd->wIDmenu,0,MF_BYPOSITION);
  DeleteMenu(frameWnd->wIDmenu,nItems-1,MF_BYPOSITION);
 
-  /* redraw frame */
- SetWindowPos(hChild, 0,0,0,0,0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
-                                 SWP_NOACTIVATE | SWP_NOZORDER );
+ DrawMenuBar(frameWnd->hwndSelf);
+
  return 1;
 }
 
@@ -962,7 +969,7 @@
 	ci->flagChildMaximized  = 0;
 	ci->nActiveChildren	= 0;
 	ci->hFrameTitle		= frameWnd->hText;
-	ci->sbStop		= 0;
+	ci->sbNeedUpdate	= 0;
 	ci->self		= hwnd;
 	ci->obmClose		= CreateMDIMenuBitmap();
 	ci->obmRestore		= LoadBitmap(0, MAKEINTRESOURCE(OBM_RESTORE));
@@ -1014,11 +1021,11 @@
 		((LONG) (ci->flagChildMaximized>0) << 16));
 
       case WM_MDIICONARRANGE:
-	       ci->sbStop = TRUE;
-	       MDIIconArrange(hwnd);
-	       ci->sbStop = FALSE;
-	       SendMessage(hwnd,WM_MDICALCCHILDSCROLL,0,0L);
-	       return 0;
+	ci->sbNeedUpdate = TRUE;
+	MDIIconArrange(hwnd);
+	ci->sbRecalc = SB_BOTH+1;
+	SendMessage(hwnd,WM_MDICALCCHILDSCROLL,0,0L);
+	return 0;
 	
       case WM_MDIMAXIMIZE:
 	ShowWindow((HWND)wParam, SW_MAXIMIZE);
@@ -1040,17 +1047,17 @@
 #endif
 	
       case WM_MDITILE:
-	ci->sbStop = TRUE;
+	ci->sbNeedUpdate = TRUE;
 	ShowScrollBar(hwnd,SB_BOTH,FALSE);
 	MDITile(hwnd, ci,wParam);
-        ci->sbStop = FALSE;
+        ci->sbNeedUpdate = FALSE;
         return 0;
 
       case WM_VSCROLL:
       case WM_HSCROLL:
-	ci->sbStop = TRUE;
+	ci->sbNeedUpdate = TRUE;
         ScrollChildren(hwnd,message,wParam,lParam);
-	ci->sbStop = FALSE;
+	ci->sbNeedUpdate = FALSE;
         return 0;
 
       case WM_SETFOCUS:
@@ -1099,18 +1106,16 @@
 			rect.right - rect.left, rect.bottom - rect.top, 1);
 	  }
 	else
-	  {
-	     PostMessage(hwnd,WM_MDICALCCHILDSCROLL,0,0L);
-	     ci->sbRecalc |= (SB_BOTH+1);
-	  }
+	  MDI_PostUpdate(hwnd, ci, SB_BOTH+1);
+
 	break;
 
       case WM_MDICALCCHILDSCROLL:
-	if( !ci->sbStop )
+	if( ci->sbNeedUpdate )
 	  if( ci->sbRecalc )
 	    {
 	      CalcChildScroll(hwnd, ci->sbRecalc-1);
-	      ci->sbRecalc = 0;
+	      ci->sbRecalc = ci->sbNeedUpdate = 0;
 	    }
 	return 0;
     }
@@ -1256,11 +1261,10 @@
 	return 0;
 
       case WM_SETVISIBLE:
-         if( !ci->sbStop && !ci->flagChildMaximized)
-          {
-            PostMessage(ci->self,WM_MDICALCCHILDSCROLL,0,0L);
-            ci->sbRecalc |= (SB_BOTH+1);
-          }
+         if( ci->flagChildMaximized)
+             ci->sbNeedUpdate = 0;
+	 else
+            MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
 	break;
 
       case WM_SIZE:
@@ -1305,12 +1309,8 @@
 	    if( switchTo )
 	        SendMessage( switchTo, WM_CHILDACTIVATE, 0, 0L);
 	  }
-	    
-        if( !ci->sbStop )
-          {
-            PostMessage(ci->self,WM_MDICALCCHILDSCROLL,0,0L);
-            ci->sbRecalc |= (SB_BOTH+1);
-          }
+	  
+	MDI_PostUpdate(clientWnd->hwndSelf, ci, SB_BOTH+1);
 	break;
 
       case WM_MENUCHAR:
@@ -1379,27 +1379,47 @@
 void CalcChildScroll( HWND hwnd, WORD scroll )
 {
     RECT childRect, clientRect;
-    WND *pWnd;
+    INT  vmin, vmax, hmin, hmax, vpos, hpos;
+    BOOL noscroll = FALSE;
+    WND *pWnd, *Wnd;
 
-    if (!(pWnd = WIN_FindWndPtr( hwnd ))) return;
+    if (!(Wnd = pWnd = WIN_FindWndPtr( hwnd ))) return;
     GetClientRect( hwnd, &clientRect );
     SetRectEmpty( &childRect );
-    for (pWnd = pWnd->child; pWnd; pWnd = pWnd->next)
-        UnionRect( &childRect, &pWnd->rectWindow, &childRect );
+
+    for ( pWnd = pWnd->child; pWnd; pWnd = pWnd->next )
+	{
+          UnionRect( &childRect, &pWnd->rectWindow, &childRect );
+	  if( pWnd->dwStyle & WS_MAXIMIZE )
+	      noscroll = TRUE;
+	} 
     UnionRect( &childRect, &clientRect, &childRect );
 
-    if ((scroll == SB_HORZ) || (scroll == SB_BOTH))
-    {
-        SetScrollRange( hwnd, SB_HORZ, childRect.left,
-                        childRect.right - clientRect.right, FALSE );
-        SetScrollPos( hwnd, SB_HORZ, clientRect.left - childRect.left, TRUE );
-    }
-    if ((scroll == SB_VERT) || (scroll == SB_BOTH))
-    {
-        SetScrollRange( hwnd, SB_VERT, childRect.top,
-                        childRect.bottom - clientRect.bottom, FALSE );
-        SetScrollPos( hwnd, SB_HORZ, clientRect.top - childRect.top, TRUE );
-    }
+    /* jump through the hoops to prevent excessive flashing 
+     */
+
+    hmin = childRect.left; hmax = childRect.right - clientRect.right;
+    hpos = clientRect.left - childRect.left;
+    vmin = childRect.top; vmax = childRect.bottom - clientRect.bottom;
+    vpos = clientRect.top - childRect.top;
+
+    if( noscroll )
+	ShowScrollBar(hwnd, SB_BOTH, FALSE);
+    else
+    switch( scroll )
+      {
+	case SB_HORZ:
+			vpos = hpos; vmin = hmin; vmax = hmax;
+	case SB_VERT:
+			SetScrollPos(hwnd, scroll, vpos, FALSE);
+			SetScrollRange(hwnd, scroll, vmin, vmax, TRUE);
+			break;
+	case SB_BOTH:
+			SCROLL_SetNCSbState( Wnd, vmin, vmax, vpos,
+						  hmin, hmax, hpos);
+			SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE
+                                 | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
+      }    
 }
 
 /***********************************************************************
diff --git a/windows/message.c b/windows/message.c
index d1ac195..78942bc 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -201,6 +201,9 @@
     MESSAGEQUEUE *sysMsgQueue = QUEUE_GetSysQueue();
     int i, pos = sysMsgQueue->nextMessage;
 
+    /* If the queue is empty, attempt to fill it */
+    if (!sysMsgQueue->msgCount && XPending(display)) MSG_WaitXEvent( 0 );
+
     for (i = 0; i < sysMsgQueue->msgCount; i++, pos++)
     {
         if (pos >= sysMsgQueue->queueSize) pos = 0;
@@ -362,11 +365,11 @@
     {
 
 #ifdef CONFIG_IPC
-	if (DDE_GetRemoteMessage())
+        if (DDE_GetRemoteMessage())
         {
-	    while(DDE_GetRemoteMessage()) ;
-	    return TRUE;
-	}
+            while(DDE_GetRemoteMessage()) ;
+            return TRUE;
+        }
 #endif  /* CONFIG_IPC */
 
         XNextEvent( display, &event );
diff --git a/windows/painting.c b/windows/painting.c
index e8ce1bb..31573ff 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -23,13 +23,13 @@
  */
 void WIN_UpdateNCArea(WND* wnd, BOOL bUpdate)
 {
-    RECT rect = wnd->rectClient;
+    POINT pt = {0, 0}; 
     HRGN hClip = 1;
 
     dprintf_nonclient(stddeb,"NCUpdate: hwnd %04x, hrgnUpdate %04x\n", 
                       wnd->hwndSelf, wnd->hrgnUpdate );
 
-    /* desktop windows doesn't have nonclient area */
+    /* desktop window doesn't have nonclient area */
     if(wnd == WIN_GetDesktop()) 
     {
         wnd->flags &= ~WIN_NEEDS_NCPAINT;
@@ -38,7 +38,7 @@
 
     if( wnd->hrgnUpdate > 1 )
     {
-        MapWindowPoints(wnd->parent->hwndSelf, 0, (POINT*)&rect, 2);
+	ClientToScreen(wnd->hwndSelf, &pt);
 
         hClip = CreateRectRgn( 0, 0, 0, 0 );
         if (!CombineRgn(hClip, wnd->hrgnUpdate, 0, RGN_COPY) )
@@ -46,16 +46,22 @@
             DeleteObject(hClip);
             hClip = 1;
         }
+	else
+	    OffsetRgn(hClip, pt.x, pt.y);
 
         if (bUpdate)
         {
-            HRGN hrgn = CreateRectRgnIndirect(&rect);
+	    /* exclude non-client area from update region */
+            HRGN hrgn = CreateRectRgn(0, 0, wnd->rectClient.right - wnd->rectClient.left,
+					    wnd->rectClient.bottom - wnd->rectClient.top);
+
             if (hrgn && (CombineRgn(wnd->hrgnUpdate, wnd->hrgnUpdate,
                                     hrgn, RGN_AND) == NULLREGION))
             {
                 DeleteObject(wnd->hrgnUpdate);
                 wnd->hrgnUpdate = 1;
             }
+
             DeleteObject( hrgn );
         }
     }
@@ -204,19 +210,21 @@
     }
     else
     {
-        dprintf_win( stddeb, "RedrawWindow: %04x NULL %04x flags=%04x\n",
+        dprintf_win(stddeb, "RedrawWindow: %04x NULL %04x flags=%04x\n",
                      hwnd, hrgnUpdate, flags);
     }
     GetClientRect( hwnd, &rectClient );
 
     if (flags & RDW_INVALIDATE)  /* Invalidate */
     {
-        if (wndPtr->hrgnUpdate)  /* Is there already an update region? */
+        int rgnNotEmpty = COMPLEXREGION;
+
+        if (wndPtr->hrgnUpdate > 1)  /* Is there already an update region? */
         {
             if ((hrgn = hrgnUpdate) == 0)
                 hrgn = CreateRectRgnIndirect( rectUpdate ? rectUpdate :
                                               &rectClient );
-            CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate, hrgn, RGN_OR );
+            rgnNotEmpty = CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate, hrgn, RGN_OR );
             if (!hrgnUpdate) DeleteObject( hrgn );
         }
         else  /* No update region yet */
@@ -226,19 +234,31 @@
             if (hrgnUpdate)
             {
                 wndPtr->hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
-                CombineRgn( wndPtr->hrgnUpdate, hrgnUpdate, 0, RGN_COPY );
+                rgnNotEmpty = CombineRgn( wndPtr->hrgnUpdate, hrgnUpdate, 0, RGN_COPY );
             }
             else wndPtr->hrgnUpdate = CreateRectRgnIndirect( rectUpdate ?
                                                     rectUpdate : &rectClient );
         }
+	
         if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
-        if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
+
+	/* check for bogus update region */ 
+	if ( rgnNotEmpty == NULLREGION )
+	   {
+	     wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
+	     DeleteObject(wndPtr->hrgnUpdate);
+	     wndPtr->hrgnUpdate=0;
+             if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
+                   QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
+	   }
+	else
+             if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
 	flags |= RDW_FRAME;  /* Force invalidating the frame of children */
     }
     else if (flags & RDW_VALIDATE)  /* Validate */
     {
           /* We need an update region in order to validate anything */
-        if (wndPtr->hrgnUpdate)
+        if (wndPtr->hrgnUpdate > 1)
         {
             if (!hrgnUpdate && !rectUpdate)
             {
@@ -270,13 +290,13 @@
 
     if (flags & RDW_INTERNALPAINT)
     {
-	if (!wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT))
+	if ( wndPtr->hrgnUpdate <= 1 && !(wndPtr->flags & WIN_INTERNAL_PAINT))
 	    QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
 	wndPtr->flags |= WIN_INTERNAL_PAINT;	    
     }
     else if (flags & RDW_NOINTERNALPAINT)
     {
-	if (!wndPtr->hrgnUpdate && (wndPtr->flags & WIN_INTERNAL_PAINT))
+	if ( wndPtr->hrgnUpdate <= 1 && (wndPtr->flags & WIN_INTERNAL_PAINT))
 	    QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
 	wndPtr->flags &= ~WIN_INTERNAL_PAINT;
     }
@@ -401,7 +421,7 @@
 
     if (rect)
     {
-	if (wndPtr->hrgnUpdate)
+	if (wndPtr->hrgnUpdate > 1)
 	{
 	    HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
 	    if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR) return FALSE;
@@ -410,7 +430,7 @@
 	}
 	else SetRectEmpty( rect );
     }
-    return (wndPtr->hrgnUpdate != 0);
+    return (wndPtr->hrgnUpdate > 1);
 }
 
 
@@ -423,7 +443,7 @@
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return ERROR;
 
-    if (!wndPtr->hrgnUpdate)
+    if (wndPtr->hrgnUpdate <= 1)
     {
         SetRectRgn( hrgn, 0, 0, 0, 0 );
         return NULLREGION;
@@ -447,7 +467,8 @@
     if ((hrgn = CreateRectRgn( 0, 0, 0, 0 )) != 0)
     {
 	retval = CombineRgn( hrgn, InquireVisRgn(hdc),
-			     wndPtr->hrgnUpdate, RGN_DIFF );
+			     (wndPtr->hrgnUpdate>1)?wndPtr->hrgnUpdate:0,
+			     (wndPtr->hrgnUpdate>1)?RGN_DIFF:RGN_COPY);
 	if (retval) SelectVisRgn( hdc, hrgn );
 	DeleteObject( hrgn );
     }
diff --git a/windows/winpos.c b/windows/winpos.c
index 524f285..09ad76a 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -20,16 +20,18 @@
 /* #define DEBUG_WIN */
 #include "debug.h"
 
+#define  SWP_NOPOSCHANGE	(SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
+
 /* ----- external functions ----- */
 
 void 	FOCUS_SwitchFocus( HWND , HWND );
+HRGN 	DCE_GetVisRgn( HWND, WORD );
 
 /* ----- internal variables ----- */
 
 static HWND hwndActive      = 0;  /* Currently active window */
 static HWND hwndPrevActive  = 0;  /* Previously active window */
 
-
 /***********************************************************************
  *           WINPOS_FindIconPos
  *
@@ -424,6 +426,7 @@
     switch(cmd)
     {
         case SW_HIDE:
+            if (!wasVisible) return FALSE;
 	    swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
 		        SWP_NOACTIVATE | SWP_NOZORDER;
 	    break;
@@ -1040,6 +1043,129 @@
   return hwndInsertAfter;
 }
 
+/***********************************************************************
+ *	     WINPOS_SizeMoveClean
+ *
+ * Make window look nice without excessive repainting
+ *
+ * the pain:
+ *
+ * visible regions are in window coordinates
+ * update regions are in window client coordinates
+ * client and window rectangles are in parent client coordinates
+ */
+static void WINPOS_SizeMoveClean(WND* Wnd, HRGN oldVisRgn, LPRECT lpOldWndRect, LPRECT lpOldClientRect, BOOL bNoCopy )
+{
+ /* visible regions are in window coordinates */
+
+ HRGN newVisRgn    = DCE_GetVisRgn(Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS );
+ HRGN dirtyRgn     = CreateRectRgn(0,0,0,0);
+ int  other, my;
+
+ dprintf_win(stddeb,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n\
+\t\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
+		   Wnd->rectWindow.left, Wnd->rectWindow.top, Wnd->rectWindow.right, Wnd->rectWindow.bottom,
+		   lpOldWndRect->left, lpOldWndRect->top, lpOldWndRect->right, lpOldWndRect->bottom,
+		   Wnd->rectClient.left,Wnd->rectClient.top,Wnd->rectClient.right,Wnd->rectClient.bottom,
+		   lpOldClientRect->left,lpOldClientRect->top,lpOldClientRect->right,lpOldClientRect->bottom);
+
+ CombineRgn( dirtyRgn, newVisRgn, 0, RGN_COPY);
+
+ if( !bNoCopy )
+   {
+     HRGN hRgn = CreateRectRgn( lpOldClientRect->left - lpOldWndRect->left, lpOldClientRect->top - lpOldWndRect->top,
+				lpOldClientRect->right - lpOldWndRect->left, lpOldClientRect->bottom - lpOldWndRect->top);
+     CombineRgn( newVisRgn, newVisRgn, oldVisRgn, RGN_AND ); 
+     CombineRgn( newVisRgn, newVisRgn, hRgn, RGN_AND );
+     DeleteObject(hRgn);
+   }
+
+ /* map regions to the parent client area */
+ 
+ OffsetRgn(dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top);
+ OffsetRgn(oldVisRgn, lpOldWndRect->left, lpOldWndRect->top);
+
+ /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
+
+ other = CombineRgn(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
+
+ /* map visible region to the Wnd client area */
+
+ OffsetRgn( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
+                       Wnd->rectWindow.top - Wnd->rectClient.top );
+
+ /* substract previously invalidated region from the Wnd visible region */
+
+ my =  (Wnd->hrgnUpdate > 1)? CombineRgn( newVisRgn, newVisRgn, Wnd->hrgnUpdate, RGN_DIFF)
+                            : COMPLEXREGION;
+
+ if( bNoCopy )		/* invalidate Wnd visible region */
+   {
+     if (my != NULLREGION)  RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
+		            RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
+   } 
+ else			/* bitblt old client area */
+   { 
+     HDC   hDC;
+     int   update;
+     HRGN  updateRgn;
+
+     /* client rect */
+
+     updateRgn = CreateRectRgn( 0,0, Wnd->rectClient.right - Wnd->rectClient.left,
+				Wnd->rectClient.bottom - Wnd->rectClient.top );
+
+     /* clip visible region with client rect */
+
+     my = CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
+
+     /* substract result from client rect to get region that won't be copied */
+
+     update = CombineRgn( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
+
+     /* Blt valid bits using parent window DC */
+
+     if( my != NULLREGION )
+       {
+	 int xfrom = lpOldClientRect->left;
+	 int yfrom = lpOldClientRect->top;
+	 int xto = Wnd->rectClient.left;
+	 int yto = Wnd->rectClient.top;
+
+	 /* check if we can skip copying */
+
+	 if( xfrom != xto || yfrom != yto )
+	   {
+	     /* compute clipping region in parent client coordinates */
+
+	     OffsetRgn( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top);
+	     CombineRgn( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
+
+             hDC = GetDCEx( Wnd->parent->hwndSelf, oldVisRgn, DCX_INTERSECTRGN | DCX_CACHE | DCX_CLIPSIBLINGS);
+
+             BitBlt(hDC, xto, yto, lpOldClientRect->right - lpOldClientRect->left + 1, 
+				   lpOldClientRect->bottom - lpOldClientRect->top + 1,
+				   hDC, xfrom, yfrom, SRCCOPY );
+    
+             ReleaseDC( Wnd->parent->hwndSelf, hDC); 
+	  }
+       }
+
+     if( update != NULLREGION )
+         RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
+ 				      RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
+     DeleteObject( updateRgn );
+   }
+
+ /* erase uncovered areas */
+
+ if( other != NULLREGION )
+     RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
+		   RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
+
+ DeleteObject(dirtyRgn);
+ DeleteObject(newVisRgn);
+}
 
 /***********************************************************************
  *           WINPOS_SetXWindowPos
@@ -1088,10 +1214,13 @@
 BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, INT x, INT y,
 		   INT cx, INT cy, WORD flags )
 {
-    WINDOWPOS winpos;
-    WND *wndPtr;
-    RECT newWindowRect, newClientRect;
-    int result;
+    WINDOWPOS 	winpos;
+    WND *	wndPtr;
+    RECT 	newWindowRect, newClientRect;
+    HRGN	visRgn = 0;
+    int 	result = 0;
+
+    dprintf_win(stddeb,"SetWindowPos: hwnd %04x, flags %08x\n", hwnd, flags);  
 
       /* Check window handle */
 
@@ -1130,10 +1259,19 @@
       /* TOPMOST not supported yet */
     if ((hwndInsertAfter == HWND_TOPMOST) ||
         (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
+
       /* hwndInsertAfter must be a sibling of the window */
-    if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM) &&
-	(wndPtr->parent != WIN_FindWndPtr(hwndInsertAfter)->parent))
-        return FALSE;
+    if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
+       {
+	 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
+	 if( wnd->parent != wndPtr->parent ) return FALSE;
+	 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
+       }
+    else
+       if (hwndInsertAfter == HWND_TOP)
+	   flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
+       else /* HWND_BOTTOM */
+	   flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
 
       /* Fill the WINDOWPOS structure */
 
@@ -1166,8 +1304,13 @@
         newWindowRect.top     = winpos.y;
         newWindowRect.right  += winpos.x - wndPtr->rectWindow.left;
         newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
+
+	OffsetRect(&newClientRect, winpos.x - wndPtr->rectWindow.left, 
+				   winpos.y - wndPtr->rectWindow.top );
     }
 
+    winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
+
       /* Reposition window in Z order */
 
     if (!(winpos.flags & SWP_NOZORDER))
@@ -1186,17 +1329,42 @@
         else WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
     }
 
-      /* Send WM_NCCALCSIZE message to get new client area */
+    if ( !wndPtr->window && !(flags & SWP_NOREDRAW) && 
+        (!(flags & SWP_NOMOVE) || !(flags & SWP_NOSIZE) || (flags & SWP_FRAMECHANGED)) )
+          visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS);
 
-    result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
+
+      /* Send WM_NCCALCSIZE message to get new client area */
+    if( (flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
+      {
+         result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
 				    &wndPtr->rectWindow, &wndPtr->rectClient,
 				    &winpos, &newClientRect );
-    /* FIXME: Should handle result here */
+
+         /* FIXME: WVR_ALIGNxxx */
+
+         if( newClientRect.left != wndPtr->rectClient.left ||
+             newClientRect.top != wndPtr->rectClient.top )
+             winpos.flags &= ~SWP_NOCLIENTMOVE;
+
+         if( (newClientRect.right - newClientRect.left !=
+             wndPtr->rectClient.right - wndPtr->rectClient.left) ||
+  	    (newClientRect.bottom - newClientRect.top !=
+	     wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
+	     winpos.flags &= ~SWP_NOCLIENTSIZE;
+      }
+    else
+      if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
+				    newClientRect.top != wndPtr->rectClient.top) )
+	    winpos.flags &= ~SWP_NOCLIENTMOVE;
 
     /* Perform the moving and resizing */
 
     if (wndPtr->window)
     {
+        RECT oldWindowRect = wndPtr->rectWindow;
+        RECT oldClientRect = wndPtr->rectClient;
+
         HWND bogusInsertAfter = winpos.hwndInsertAfter;
 
         winpos.hwndInsertAfter = hwndInsertAfter;
@@ -1205,44 +1373,66 @@
         wndPtr->rectWindow = newWindowRect;
         wndPtr->rectClient = newClientRect;
         winpos.hwndInsertAfter = bogusInsertAfter;
+
+	/*  FIXME: should do something like WINPOS_SizeMoveClean */
+
+	if( (oldClientRect.left - oldWindowRect.left !=
+	     newClientRect.left - newWindowRect.left) ||
+	    (oldClientRect.top - oldWindowRect.top !=
+	     newClientRect.top - newWindowRect.top) )
+
+	    RedrawWindow(wndPtr->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE);
+	else
+	    if( winpos.flags & SWP_FRAMECHANGED )
+	      {
+		WORD wErase = 0;
+		RECT rect;
+
+	        if( oldClientRect.right > newClientRect.right ) 
+		  {
+		    rect.left = newClientRect.right; rect.top = newClientRect.top;
+		    rect.right = oldClientRect.right; rect.bottom = newClientRect.bottom;
+		    wErase = 1;
+		    RedrawWindow(wndPtr->hwndSelf, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
+		  }
+		if( oldClientRect.bottom > newClientRect.bottom )
+		  {
+		    rect.left = newClientRect.left; rect.top = newClientRect.bottom;
+		    rect.right = (wErase)?oldClientRect.right:newClientRect.right;
+		    rect.bottom = oldClientRect.bottom;
+		    wErase = 1;
+		    RedrawWindow(wndPtr->hwndSelf, &rect, 0, RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
+		  }
+
+		if( !wErase ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
+	      }
     }
     else
     {
         RECT oldWindowRect = wndPtr->rectWindow;
+	RECT oldClientRect = wndPtr->rectClient;
 
         wndPtr->rectWindow = newWindowRect;
         wndPtr->rectClient = newClientRect;
 
-        if (!(flags & SWP_NOREDRAW) &&
-            (!(flags & SWP_NOSIZE) || !(flags & SWP_NOMOVE) ||
-	     (!(flags & SWP_NOZORDER) && (hwndInsertAfter != HWND_TOP))))
-        {
-            HRGN hrgn1 = CreateRectRgnIndirect( &oldWindowRect );
-            HRGN hrgn2 = CreateRectRgnIndirect( &wndPtr->rectWindow );
-            HRGN hrgn3 = CreateRectRgn( 0, 0, 0, 0 );
-            CombineRgn( hrgn3, hrgn1, hrgn2, RGN_DIFF );
-            RedrawWindow( wndPtr->parent->hwndSelf, NULL, hrgn3,
-                          RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
+        if( !(flags & SWP_NOREDRAW) )
+	  {
+	    BOOL bNoCopy = (flags & SWP_NOCOPYBITS) || 
+			   (result >= WVR_HREDRAW && result < WVR_VALIDRECTS);
 
-	    /* DCE_GetVisRgn should be called for old coordinates
-	     * and for new, then OffsetRgn and CombineRgn -
-	     * voila, a nice update region to use here - AK.
-	     */ 
-            if ((oldWindowRect.left != wndPtr->rectWindow.left) ||
-                (oldWindowRect.top != wndPtr->rectWindow.top))
-            {
-                RedrawWindow( winpos.hwnd, NULL, 0, RDW_INVALIDATE |
-                              RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
-            }
- 	    else
-		if( CombineRgn( hrgn3, hrgn2, hrgn1, RGN_DIFF) != NULLREGION )
-		    RedrawWindow( winpos.hwnd, NULL, hrgn3, RDW_INVALIDATE |
-				  RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
+	    if( (winpos.flags & SWP_NOPOSCHANGE) != SWP_NOPOSCHANGE )
+	      {
+	        /* optimize cleanup by BitBlt'ing where possible */
 
-            DeleteObject( hrgn1 );
-            DeleteObject( hrgn2 );
-            DeleteObject( hrgn3 );
-        }
+	        WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect, &oldClientRect, bNoCopy);
+	        DeleteObject(visRgn);
+	      }
+	    else
+	       if( winpos.flags & SWP_FRAMECHANGED )
+        	  RedrawWindow( winpos.hwnd, NULL, 0, RDW_NOCHILDREN | RDW_FRAME ); 
+
+	  }
+        DeleteObject(visRgn);
     }
 
     if (flags & SWP_SHOWWINDOW)
@@ -1271,8 +1461,7 @@
         {
             if (!(flags & SWP_NOREDRAW))
                 RedrawWindow( wndPtr->parent->hwndSelf, &wndPtr->rectWindow, 0,
-                              RDW_INVALIDATE | RDW_FRAME |
-                              RDW_ALLCHILDREN | RDW_ERASE );
+                              RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
         }
 
         if ((winpos.hwnd == GetFocus()) || IsChild(winpos.hwnd, GetFocus()))
@@ -1303,18 +1492,12 @@
 
     EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
 
-    if ((flags & SWP_FRAMECHANGED) && !(flags & SWP_NOREDRAW))
-        RedrawWindow( winpos.hwnd, NULL, 0,
-                      RDW_ALLCHILDREN | /*FIXME: this should not be necessary*/
-                      RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
     if (!(flags & SWP_DEFERERASE))
         RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
                       RDW_ALLCHILDREN | RDW_ERASENOW );
 
       /* And last, send the WM_WINDOWPOSCHANGED message */
 
-    winpos.flags |= SWP_NOMOVE; /* prevent looping.. window is already moved ??? (FIXME)*/
-
     if (!(winpos.flags & SWP_NOSENDCHANGING))
         SendMessage( winpos.hwnd, WM_WINDOWPOSCHANGED,
                      0, (LPARAM)MAKE_SEGPTR(&winpos) );