Release 950202

Wed Feb  1 19:27:55 1995  Alexandre Julliard  (julliard@lamisun.epfl.ch)

	* [windows/nonclient.c] [windows/winpos.c]
	Implemented maximized windows.
	Implemented icon positioning and ArrangeIconicWindows().
	Bug fixes in SetWindowPos().

	* [windows/painting.c]
	Implemented GetControlBrush().
	Window frame is no longer contained in the update region.

	* [windows/win.c]
	Destroy owned windows upon DestroyWindow().

Sun Jan 29 16:17:22 1995  David Metcalfe <david@prism.demon.co.uk>

	* [controls/edit.c]
	Changed line terminator to \r\n to be compatible with
	Windows.  Fixed bug in text selection.

Sun Jan 29 14:10:22 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>

       * [misc/shell.c]
       Rewrote RegCreateKey and RegOpenKey, since they were completely broken.
       Fixed a bug in RegQueryKeyValue. Implemented RegEnumKey
       These functions now work somewhat more the way Windows programs expect
       them to work.
diff --git a/ANNOUNCE b/ANNOUNCE
index ebdf2dc..ed22ab8 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,14 +1,14 @@
-This is release 950122 of Wine the MS Windows emulator.  This is still a
+This is release 950202 of Wine the MS Windows emulator.  This is still a
 developer's only release.  There are many bugs and many unimplemented API
 features.  Most applications still do not work.
 
 Patches should be submitted to "wine-new@amscons.com".  Please don't forget
 to include a ChangeLog entry.  I'll make a new release every other Sunday.
 
-WHAT'S NEW with Wine-950122: (see ChangeLog for details)
-	- ELF format support
-	- New disassembler based on Mach code, replacing the gdb code
-	- Faster regions
+WHAT'S NEW with Wine-950202: (see ChangeLog for details)
+	- Maximized windows
+	- Edit control now uses \r\n for line endings
+	- Better registry functions
 	- Lots of bug fixes
 
 See the README file in the distribution for installation instructions.
@@ -17,11 +17,11 @@
 the release is available at the ftp sites.  The sources will be available
 from the following locations:
 
-	sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-950122.tar.gz
-	aris.com:/pub/linux/ALPHA/Wine/development/Wine-950122.tar.gz
-	tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950122.tar.gz
-	ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950122.tar.gz
-	ftp.wonderland.org:/Wine/Wine-950122.tar.gz
+	sunsite.unc.edu:/pub/Linux/ALPHA/wine/Wine-950202.tar.gz
+	aris.com:/pub/linux/ALPHA/Wine/development/Wine-950202.tar.gz
+	tsx-11.mit.edu:/pub/linux/ALPHA/Wine/development/Wine-950202.tar.gz
+	ftp.funet.fi:/pub/OS/Linux/ALPHA/Wine/Wine-950202.tar.gz
+	ftp.wonderland.org:/Wine/Wine-950202.tar.gz
 
 If you submitted a patch, please check to make sure it has been
 included in the new release.
diff --git a/ChangeLog b/ChangeLog
index 7592fc4..f2a9d94 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,33 @@
 ----------------------------------------------------------------------
+Wed Feb  1 19:27:55 1995  Alexandre Julliard  (julliard@lamisun.epfl.ch)
+
+	* [windows/nonclient.c] [windows/winpos.c]
+	Implemented maximized windows.
+	Implemented icon positioning and ArrangeIconicWindows().
+	Bug fixes in SetWindowPos().
+
+	* [windows/painting.c]
+	Implemented GetControlBrush().
+	Window frame is no longer contained in the update region.
+
+	* [windows/win.c]
+	Destroy owned windows upon DestroyWindow().
+
+Sun Jan 29 16:17:22 1995  David Metcalfe <david@prism.demon.co.uk>
+
+	* [controls/edit.c]
+	Changed line terminator to \r\n to be compatible with
+	Windows.  Fixed bug in text selection.
+
+Sun Jan 29 14:10:22 1995   Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
+
+       * [misc/shell.c]
+       Rewrote RegCreateKey and RegOpenKey, since they were completely broken.
+       Fixed a bug in RegQueryKeyValue. Implemented RegEnumKey
+       These functions now work somewhat more the way Windows programs expect
+       them to work.
+
+----------------------------------------------------------------------
 Sun Jan 22 18:55:33 1995  Alexandre Julliard  (julliard@lamisun.epfl.ch)
 
 	* [loader/resource.c] [objects/dib.c]
diff --git a/Configure b/Configure
index d1b3650..63e261c 100644
--- a/Configure
+++ b/Configure
@@ -47,10 +47,11 @@
 fi
 
 echo
-echo -n 'Use the XPM library (Y/N) [N]? '
+echo -n 'Use the XPM library (Y/N) [Y]? '
 read input
-if [ "$input" = 'y' -o "$input" = 'Y' ]
-then
+if [ "$input" = 'n' -o "$input" = 'N' ]
+then :
+else
 	XPM='#define USE_XPM'
 	ALLDEFINES="$ALLDEFINES -DUSE_XPM"
 fi
diff --git a/controls/EDIT.TODO b/controls/EDIT.TODO
new file mode 100644
index 0000000..3aa0ff9
--- /dev/null
+++ b/controls/EDIT.TODO
@@ -0,0 +1,23 @@
+-  Find all the remaining bugs!
+
+-  ES_LEFT, ES_RIGHT and ES_CENTER.  ES_RIGHT and ES_CENTER cannot be
+   used with single line edit controls or be combined with ES_AUTOHSCROLL.
+
+-  Hide selection when window loses focus and ES_NOHIDESEL to disable
+   this functionality.
+
+-  ES_LOWERCASE and ES_UPPERCASE.
+
+-  ES_PASSWORD and EM_PASSWORDCHAR.
+
+-  ES_OEMCONVERT.  Probably won't do anything very much.
+
+-  ES_READONLY.
+
+-  ES_WANTRETURN and Ctrl-Enter to move to next line when this
+   functionality is enabled.
+
+-  Implement undo buffer correctly.  Windows allows the user to undo
+   entered text as well as deleted text.  You can also undo an undo.
+
+-  Add word wrap - this is a very big change!
diff --git a/controls/edit.c b/controls/edit.c
index a04b2b9..e81ab13 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -278,7 +278,10 @@
 	break;
 
     case EM_SETHANDLE:
+	HideCaret(hwnd);
 	EDIT_SetHandleMsg(hwnd, wParam);
+	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
+	ShowCaret(hwnd);
 	break;
 
     case EM_SETMODIFY:
@@ -431,7 +434,13 @@
 	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
 	ShowCaret(hwnd);
 	break;
-
+#if 0
+    case WM_SETREDRAW:
+	dprintf_edit(stddeb, "WM_SETREDRAW: hwnd=%d, wParam=%x\n",
+		     hwnd, wParam);
+	lResult = 0;
+	break;
+#endif
     case WM_SETTEXT:
 	EDIT_SetTextMsg(hwnd, lParam);
 	break;
@@ -548,11 +557,14 @@
     char *text;
 
     /* initialize state variable structure */
-    /* --- char width array */
     hdc = GetDC(hwnd);
+
+    /* --- char width array                                        */
+    /*     only initialise chars <= 32 as X returns strange widths */
+    /*     for other chars                                         */
     charWidths = (short *)EDIT_HeapAddr(hwnd, es->hCharWidths);
     memset(charWidths, 0, 256 * sizeof(short));
-    GetCharWidth(hdc, 0, 255, charWidths);
+    GetCharWidth(hdc, 32, 254, &charWidths[32]);
 
     /* --- other structure variables */
     GetTextMetrics(hdc, &tm);
@@ -737,7 +749,7 @@
     dprintf_edit(stddeb,"GetTextLine %d\n", selection);
     cp = cp1 = EDIT_TextLine(hwnd, selection);
     /* advance through line */
-    while (*cp && *cp != '\n')
+    while (*cp && *cp != '\r')
     {
 	len++;
 	cp++;
@@ -804,7 +816,7 @@
     char *cp1;
 
     if(!cp)return 0;
-    cp1 = strchr(cp, '\n');
+    cp1 = strchr(cp, '\r');
     return cp1 ? (int)(cp1 - cp) : strlen(cp);
 }
 
@@ -1094,7 +1106,7 @@
 
     dprintf_edit(stddeb,"EDIT_GetStr lp='%s'  off=%d  len=%d\n", lp, off, len);
 
-    if (off<0) off=0;
+    if (off < 0) off = 0;
     while (i < off)
     {
 	s_i = i;
@@ -1111,6 +1123,8 @@
     ch1 = ch;
     while (i < len + off)
     {
+	if (*(lp + ch) == '\r' || *(lp + ch) == '\n')
+	    break;
 	i += EDIT_CharWidth(hwnd, (BYTE)(*(lp + ch)), i);
 	ch++;
     }
@@ -1191,8 +1205,9 @@
     if (*currchar == '\0' && IsMultiLine())
     {
 	/* insert a newline at end of text */
-	*currchar = '\n';
-	*(currchar + 1) = '\0';
+	*currchar = '\r';
+	*(currchar + 1) = '\n';
+	*(currchar + 2) = '\0';
 	EDIT_BuildTextPointers(hwnd);
     }
 
@@ -1220,9 +1235,19 @@
 	currchar = CurrChar;
     }
     /* make space for new character and put char in buffer */
-    memmove(currchar + 1, currchar, strlen(currchar) + 1);
-    *currchar = ch;
-    EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 1);
+    if (ch == '\n')
+    {
+	memmove(currchar + 2, currchar, strlen(currchar) + 1);
+	*currchar = '\r';
+	*(currchar + 1) = '\n';
+	EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 2);
+    }
+    else
+    {
+	memmove(currchar + 1, currchar, strlen(currchar) + 1);
+	*currchar = ch;
+	EDIT_ModTextPointers(hwnd, es->CurrLine + 1, 1);
+    }
     es->TextChanged = TRUE;
     NOTIFY_PARENT(hwnd, EN_UPDATE);
 
@@ -1347,7 +1372,7 @@
     if (*CurrChar == '\0')
 	return;
 
-    if (*CurrChar == '\n')
+    if (*CurrChar == '\r')
     {
 	EDIT_Home(hwnd);
 	EDIT_Downward(hwnd);
@@ -1465,7 +1490,7 @@
     EDITSTATE *es = 
 	(EDITSTATE *)EDIT_HeapAddr(hwnd, (HANDLE)(*(wndPtr->wExtra)));
 
-    while (*CurrChar && *CurrChar != '\n')
+    while (*CurrChar && *CurrChar != '\r')
     {
 	es->WndCol += EDIT_CharWidth(hwnd, (BYTE)(*CurrChar), es->WndCol + es->wleft);
 	es->CurrCol++;
@@ -2557,7 +2582,7 @@
     if (es->WndCol > EDIT_StrLength(hwnd, cp, len, 0) - es->wleft || end)
 	es->WndCol = EDIT_StrLength(hwnd, cp, len, 0) - es->wleft;
     es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
-    es->SelEndCol = es->CurrCol - 1;
+    es->SelEndCol = es->CurrCol;
 
     bel = es->SelEndLine;
     bec = es->SelEndCol;
@@ -2622,10 +2647,15 @@
     if (end == -1)
 	end = EDIT_LineLength(hwnd, y);
 
+    /* For some reason Rectangle, when called with R2_XORPEN filling,
+     * appears to leave a 2 pixel gap between characters and between
+     * lines.  I have kludged this by adding on two pixels to ecol and
+     * to the line height in the call to Rectangle.
+     */
     scol = EDIT_StrLength(hwnd, cp, start, 0);
     if (scol > rc.right) return;
     if (scol < rc.left) scol = rc.left;
-    ecol = EDIT_StrLength(hwnd, cp, end, 0);
+    ecol = EDIT_StrLength(hwnd, cp, end, 0) + 2;   /* ??? */
     if (ecol < rc.left) return;
     if (ecol > rc.right) ecol = rc.right;
 
@@ -2633,7 +2663,7 @@
     hbrush = GetStockObject(BLACK_BRUSH);
     holdbrush = (HBRUSH)SelectObject(hdc, (HANDLE)hbrush);
     olddm = SetROP2(hdc, R2_XORPEN);
-    Rectangle(hdc, scol, y * es->txtht, ecol, (y + 1) * es->txtht);
+    Rectangle(hdc, scol, y * es->txtht, ecol, (y + 1) * es->txtht + 2);
     SetROP2(hdc, olddm);
     SelectObject(hdc, (HANDLE)holdbrush);
     ReleaseDC(hwnd, hdc);
@@ -3054,7 +3084,7 @@
     if (IsMultiLine())
     {
 	es->hText = wParam;
-	es->MaxTextLen = EDIT_HeapSize(hwnd, es->hText);
+	es->textlen = EDIT_HeapSize(hwnd, es->hText);
 	es->wlines = 0;
 	es->wtop = es->wleft = 0;
 	es->CurrLine = es->CurrCol = 0;
@@ -3063,7 +3093,10 @@
 	es->textwidth = 0;
 	es->SelBegLine = es->SelBegCol = 0;
 	es->SelEndLine = es->SelEndCol = 0;
+	dprintf_edit(stddeb, "EDIT_SetHandleMsg: textlen=%d\n",
+                                                es->textlen);
 
+	EDIT_BuildTextPointers(hwnd);
 	es->PaintBkgd = TRUE;
 	InvalidateRect(hwnd, NULL, TRUE);
 	UpdateWindow(hwnd);
diff --git a/controls/scroll.c b/controls/scroll.c
index 03de3c8..e335ade 100644
--- a/controls/scroll.c
+++ b/controls/scroll.c
@@ -896,8 +896,6 @@
     }
     SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE
                  | SWP_NOACTIVATE | SWP_NOZORDER | SWP_FRAMECHANGED );
-      /* FIXME: Hack until SetWindowPos works correctly */
-    InvalidateRect( hwnd, NULL, TRUE );
 }
 
 
diff --git a/if1632/user.spec b/if1632/user.spec
index 87b6510..ac57b7b 100644
--- a/if1632/user.spec
+++ b/if1632/user.spec
@@ -320,7 +320,7 @@
 #323 GETMESSAGE2
 324 pascal FillWindow(word word word word) FillWindow(1 2 3 4)
 325 pascal PaintRect(word word word word ptr) PaintRect(1 2 3 4 5)
-#326 GETCONTROLBRUSH
+326 pascal16 GetControlBrush(word word word) GetControlBrush(1 2 3)
 331 pascal EnableHardwareInput(word) EnableHardwareInput(1)
 332 return UserYield 0 0
 #333 ISUSERIDLE
diff --git a/include/nonclient.h b/include/nonclient.h
index 0e8c665..0a34d90 100644
--- a/include/nonclient.h
+++ b/include/nonclient.h
@@ -10,6 +10,8 @@
 #include "windows.h"
 
 extern void NC_GetInsideRect( HWND hwnd, RECT *rect );
+extern void NC_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
+                              POINT *minTrack, POINT *maxTrack );
 extern void NC_DoNCPaint( HWND hwnd, BOOL active, BOOL suppress_menupaint );
 extern LONG NC_HandleNCPaint( HWND hwnd );
 extern LONG NC_HandleNCActivate( HWND hwnd, WORD wParam );
diff --git a/include/win.h b/include/win.h
index 0ffedbf..c33e722 100644
--- a/include/win.h
+++ b/include/win.h
@@ -48,7 +48,6 @@
     HANDLE       hText;          /* Handle of window text */
     WORD         flags;          /* Misc. flags (see below) */
     Window       window;         /* X window (only for top-level windows) */
-    RECT         rectClientSave; /* where client rect is saved when icon*/
     HMENU        hSysMenu;	 /* window's copy of System Menu */
     HANDLE       hProp;          /* Handle of Properties List */
     HTASK        hTask;          /* Task Handle of the owner */
diff --git a/include/windows.h b/include/windows.h
index 65ebf08..0c4c17e 100644
--- a/include/windows.h
+++ b/include/windows.h
@@ -2711,6 +2711,7 @@
 Fc(HANDLE,LocalReAlloc,HANDLE,a,WORD,b,WORD,c)
 Fc(HBITMAP,CreateCompatibleBitmap,HDC,a,short,b,short,c)
 Fc(HBITMAP,CreateDiscardableBitmap,HDC,a,short,b,short,c)
+Fc(HBRUSH,GetControlBrush,HWND,a,HDC,b,WORD,c)
 Fc(HDC,GetDCEx,HWND,a,HRGN,b,DWORD,c)
 Fc(HPALETTE,SelectPalette,HDC,a,HPALETTE,b,BOOL,c)
 Fc(HPEN,CreatePen,short,a,short,b,COLORREF,c)
diff --git a/include/winpos.h b/include/winpos.h
index 1df7d57..19ca5c7 100644
--- a/include/winpos.h
+++ b/include/winpos.h
@@ -22,8 +22,6 @@
 
 extern HWND WINPOS_NextWindowFromPoint( HWND hwnd, POINT pt );
 extern HWND WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg );
-extern void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
-			    POINT *minTrack, POINT *maxTrack );
 extern LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
 				   RECT *newWindowRect, RECT *oldWindowRect,
 				   RECT *oldClientRect, WINDOWPOS *winpos,
diff --git a/loader/library.c b/loader/library.c
index 6d7e973..ef7bd18 100644
--- a/loader/library.c
+++ b/loader/library.c
@@ -203,7 +203,8 @@
     if (read(wpnt->fd, wpnt->mz_header, sizeof(struct mz_header_s)) !=
 	sizeof(struct mz_header_s))
     {
-	myerror("Unable to read MZ header from file");
+	fprintf(stderr, "Unable to read MZ header from file '%s'\n", buffer);
+        exit(1);
     }
 
       /* This field is ignored according to "Windows Internals", p.242 */
diff --git a/misc/network.c b/misc/network.c
index 7ccc901..b662d99 100644
--- a/misc/network.c
+++ b/misc/network.c
@@ -4,7 +4,6 @@
 
 #include "stdio.h"
 #include "windows.h"
-#include "win.h"
 #include "user.h"
 
 #define WN_SUCCESS       			0x0000
diff --git a/misc/shell.c b/misc/shell.c
index 97a9653..c4c4a46 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -14,60 +14,88 @@
 /* #define DEBUG_REG */
 #include "debug.h"
 
-LPKEYSTRUCT	lphRootKey = NULL;
+LPKEYSTRUCT	lphRootKey = NULL,lphTopKey = NULL;
+
+static char RootKeyName[]=".classes", TopKeyName[] = "(null)";
+
+/*************************************************************************
+ *                        SHELL_RegCheckForRoot()     internal use only
+ */
+static LONG SHELL_RegCheckForRoot()
+{
+    HKEY hNewKey;
+
+    if (lphRootKey == NULL){
+      hNewKey = GlobalAlloc(GMEM_MOVEABLE,sizeof(KEYSTRUCT));
+      lphRootKey = (LPKEYSTRUCT) GlobalLock(hNewKey);
+      if (lphRootKey == NULL) {
+        printf("SHELL_RegCheckForRoot: Couldn't allocate root key!\n");
+        return ERROR_OUTOFMEMORY;
+      }
+      lphRootKey->hKey = 1;
+      lphRootKey->lpSubKey = RootKeyName;
+      lphRootKey->dwType = 0;
+      lphRootKey->lpValue = NULL;
+      lphRootKey->lpSubLvl = lphRootKey->lpNextKey = lphRootKey->lpPrevKey = NULL;
+
+      hNewKey = GlobalAlloc(GMEM_MOVEABLE,sizeof(KEYSTRUCT));
+      lphTopKey = (LPKEYSTRUCT) GlobalLock(hNewKey);
+      if (lphTopKey == NULL) {
+        printf("SHELL_RegCheckForRoot: Couldn't allocate top key!\n");
+        return ERROR_OUTOFMEMORY;
+      }
+      lphTopKey->hKey = 0;
+      lphTopKey->lpSubKey = TopKeyName;
+      lphTopKey->dwType = 0;
+      lphTopKey->lpValue = NULL;
+      lphTopKey->lpSubLvl = lphRootKey; lphTopKey->lpNextKey = lphTopKey->lpPrevKey = NULL;
+
+      dprintf_reg(stddeb,"SHELL_RegCheckForRoot: Root/Top created\n");
+    }
+    return ERROR_SUCCESS;
+}
 
 /*************************************************************************
  *				RegOpenKey		[SHELL.1]
  */
 LONG RegOpenKey(HKEY hKey, LPCSTR lpSubKey, HKEY FAR *lphKey)
 {
-	LPKEYSTRUCT	lpKey = lphRootKey;
-	LPSTR		ptr;
+	LPKEYSTRUCT	lpKey;
+	LPCSTR		ptr;
 	char		str[128];
+	LONG            dwRet;
 
+        dwRet = SHELL_RegCheckForRoot();
+        if (dwRet != ERROR_SUCCESS) return dwRet;
 	dprintf_reg(stddeb, "RegOpenKey(%08lX, %p='%s', %p)\n",
 						hKey, lpSubKey, lpSubKey, lphKey);
-	if (lpKey == NULL) return ERROR_BADKEY;
 	if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
 	if (lphKey == NULL) return ERROR_INVALID_PARAMETER;
-	if (hKey != HKEY_CLASSES_ROOT) {
-		dprintf_reg(stddeb,"RegOpenKey // specific key = %08lX !\n", hKey);
-		lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
-		}
-	while ( (ptr = strchr(lpSubKey, '\\')) != NULL ) {
-		strncpy(str, lpSubKey, (LONG)ptr - (LONG)lpSubKey);
-		str[(LONG)ptr - (LONG)lpSubKey] = '\0';
-		lpSubKey = ptr + 1;
-		dprintf_reg(stddeb,"RegOpenKey // next level '%s' !\n", str);
-		while(TRUE) {
-			dprintf_reg(stddeb,"RegOpenKey // '%s' <-> '%s' !\n", str, lpKey->lpSubKey);
-			if (lpKey->lpSubKey != NULL && lpKey->lpSubKey[0] != '\0' &&
-				strcmp(lpKey->lpSubKey, str) == 0) {
-				lpKey = lpKey->lpSubLvl;
-				if (lpKey == NULL) {
-					printf("RegOpenKey // can't find subkey '%s' !\n", str);
-					return ERROR_BADKEY;
-					}
-				break;
-				}
-			if (lpKey->lpNextKey == NULL) {
-				printf("RegOpenKey // can't find subkey '%s' !\n", str);
-				return ERROR_BADKEY;
-				}
-			lpKey = lpKey->lpNextKey;
-			}
-		}
-	while(TRUE) {
-		if (lpKey->lpSubKey != NULL && 
-			strcmp(lpKey->lpSubKey, lpSubKey) == 0)	break;
-		if (lpKey->lpNextKey == NULL) {
-			printf("RegOpenKey // can't find subkey '%s' !\n", str);
-			return ERROR_BADKEY;
-			}
-		lpKey = lpKey->lpNextKey;
-		}
-	*lphKey = lpKey->hKey;
-	dprintf_reg(stddeb,"RegOpenKey // return hKey=%08lX !\n", lpKey->hKey);
+        switch(hKey) {
+	case 0: 
+	  lpKey = lphTopKey; break;
+        case HKEY_CLASSES_ROOT: /* == 1 */
+          lpKey = lphRootKey; break;
+        default: 
+	  dprintf_reg(stddeb,"RegOpenKey // specific key = %08lX !\n", hKey);
+	  lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
+        }
+        while(*lpSubKey) {
+          ptr = strchr(lpSubKey,'\\');
+          if (!ptr) ptr = lpSubKey + strlen(lpSubKey);
+          strncpy(str,lpSubKey,ptr-lpSubKey);
+          str[ptr-lpSubKey] = 0;
+          lpSubKey = ptr; 
+          if (*lpSubKey) lpSubKey++;
+	  
+	  lpKey = lpKey->lpSubLvl;
+          while(lpKey != NULL && strcmp(lpKey->lpSubKey, str) != 0) { lpKey = lpKey->lpNextKey; }
+          if (lpKey == NULL) {
+	    dprintf_reg(stddeb,"RegOpenKey: key %s not found!\n",str);
+	    return ERROR_BADKEY;
+	  }	    
+	}
+        *lphKey = lpKey->hKey;
 	return ERROR_SUCCESS;
 }
 
@@ -79,86 +107,69 @@
 {
 	HKEY		hNewKey;
 	LPKEYSTRUCT	lpNewKey;
-	LPKEYSTRUCT	lpKey = lphRootKey;
+	LPKEYSTRUCT	lpKey;
 	LPKEYSTRUCT	lpPrevKey;
 	LONG		dwRet;
-	LPSTR		ptr;
+	LPCSTR		ptr;
 	char		str[128];
+
+	dwRet = SHELL_RegCheckForRoot();
+        if (dwRet != ERROR_SUCCESS) return dwRet;
 	dprintf_reg(stddeb, "RegCreateKey(%08lX, '%s', %p)\n",	hKey, lpSubKey, lphKey);
 	if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
 	if (lphKey == NULL) return ERROR_INVALID_PARAMETER;
-	if (hKey != HKEY_CLASSES_ROOT) {
-		dprintf_reg(stddeb,"RegCreateKey // specific key = %08lX !\n", hKey);
-		lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
-		}
-	while ( (ptr = strchr(lpSubKey, '\\')) != NULL ) {
-		strncpy(str, lpSubKey, (LONG)ptr - (LONG)lpSubKey);
-		str[(LONG)ptr - (LONG)lpSubKey] = '\0';
-		lpSubKey = ptr + 1;
-		dprintf_reg(stddeb,"RegCreateKey // next level '%s' !\n", str);
-		lpPrevKey = lpKey;
-		while(TRUE) {
-			dprintf_reg(stddeb,"RegCreateKey // '%s' <-> '%s' !\n", str, lpKey->lpSubKey);
-			if (lpKey->lpSubKey != NULL &&
-				strcmp(lpKey->lpSubKey, str) == 0) {
-				if (lpKey->lpSubLvl == NULL) {
-					dprintf_reg(stddeb,"RegCreateKey // '%s' found !\n", str);
-					if ( (ptr = strchr(lpSubKey, '\\')) != NULL ) {
-						strncpy(str, lpSubKey, (LONG)ptr - (LONG)lpSubKey);
-						str[(LONG)ptr - (LONG)lpSubKey] = '\0';
-						lpSubKey = ptr + 1;
-						}
-					else
-						strcpy(str, lpSubKey);
-					dwRet = RegCreateKey(lpKey->hKey, str, &hNewKey);
-					if (dwRet != ERROR_SUCCESS) {
-						printf("RegCreateKey // can't create subkey '%s' !\n", str);
-						return dwRet;
-						}
-					lpKey->lpSubLvl = (LPKEYSTRUCT)GlobalLock(hNewKey);
-					}
-				lpKey = lpKey->lpSubLvl;
-				break;
-				}
-			if (lpKey->lpNextKey == NULL) {
-				dwRet = RegCreateKey(lpPrevKey->hKey, str, &hNewKey);
-				if (dwRet != ERROR_SUCCESS) {
-					printf("RegCreateKey // can't create subkey '%s' !\n", str);
-					return dwRet;
-					}
-				lpKey = (LPKEYSTRUCT)GlobalLock(hNewKey);
-				break;
-				}
-			lpKey = lpKey->lpNextKey;
-			}
-		}
-	hNewKey = GlobalAlloc(GMEM_MOVEABLE, sizeof(KEYSTRUCT));
-	lpNewKey = (LPKEYSTRUCT) GlobalLock(hNewKey);
-	if (lpNewKey == NULL) {
-		printf("RegCreateKey // Can't alloc new key !\n");
-		return ERROR_OUTOFMEMORY;
-		}
-	if (lphRootKey == NULL) {
-		lphRootKey = lpNewKey;
-		lpNewKey->lpPrevKey = NULL;
-		}
-	else {
-		lpKey->lpNextKey = lpNewKey;
-		lpNewKey->lpPrevKey = lpKey;
-		}
-	lpNewKey->hKey = hNewKey;
-	lpNewKey->lpSubKey = malloc(strlen(lpSubKey) + 1);
-	if (lpNewKey->lpSubKey == NULL) {
-		printf("RegCreateKey // Can't alloc key string !\n");
-		return ERROR_OUTOFMEMORY;
-		}
-	strcpy(lpNewKey->lpSubKey, lpSubKey);
-	lpNewKey->dwType = 0;
-	lpNewKey->lpValue = NULL;
-	lpNewKey->lpNextKey = NULL;
-	lpNewKey->lpSubLvl = NULL;
-	*lphKey = hNewKey;
-	dprintf_reg(stddeb,"RegCreateKey // successful '%s' key=%08lX !\n", lpSubKey, hNewKey);
+        switch(hKey) {
+	case 0: 
+	  lpKey = lphTopKey; break;
+        case HKEY_CLASSES_ROOT: /* == 1 */
+          lpKey = lphRootKey; break;
+        default: 
+	  dprintf_reg(stddeb,"RegCreateKey // specific key = %08lX !\n", hKey);
+	  lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
+        }
+        while (*lpSubKey) {
+          dprintf_reg(stddeb, "RegCreateKey: Looking for subkey %s\n", lpSubKey);
+          ptr = strchr(lpSubKey,'\\');
+          if (!ptr) ptr = lpSubKey + strlen(lpSubKey);
+          strncpy(str,lpSubKey,ptr-lpSubKey);
+          str[ptr-lpSubKey] = 0;
+          lpSubKey = ptr; 
+          if (*lpSubKey) lpSubKey++;
+	  
+	  lpPrevKey = lpKey;
+	  lpKey = lpKey->lpSubLvl;
+          while(lpKey != NULL && strcmp(lpKey->lpSubKey, str) != 0) { 
+	    lpKey = lpKey->lpNextKey; 
+	  }
+          if (lpKey == NULL) {
+	    hNewKey = GlobalAlloc(GMEM_MOVEABLE, sizeof(KEYSTRUCT));
+	    lpNewKey = (LPKEYSTRUCT) GlobalLock(hNewKey);
+	    if (lpNewKey == NULL) {
+	      printf("RegCreateKey // Can't alloc new key !\n");
+	      return ERROR_OUTOFMEMORY;
+	    }
+	    lpNewKey->hKey = hNewKey;
+	    lpNewKey->lpSubKey = malloc(strlen(str) + 1);
+	    if (lpNewKey->lpSubKey == NULL) {
+	      printf("RegCreateKey // Can't alloc key string !\n");
+	      return ERROR_OUTOFMEMORY;
+	    }
+	    strcpy(lpNewKey->lpSubKey, str);
+	    lpNewKey->lpNextKey = lpPrevKey->lpSubLvl;
+	    lpNewKey->lpPrevKey = NULL;
+            lpPrevKey->lpSubLvl = lpNewKey;
+
+	    lpNewKey->dwType = 0;
+	    lpNewKey->lpValue = NULL;
+	    lpNewKey->lpSubLvl = NULL;
+	    *lphKey = hNewKey;
+	    dprintf_reg(stddeb,"RegCreateKey // successful '%s' key=%08lX !\n", str, hNewKey);
+	    lpKey = lpNewKey;
+	  } else {
+            *lphKey = lpKey->hKey;
+	    dprintf_reg(stddeb,"RegCreateKey // found '%s', key=%08lX\n", str, *lphKey);
+	  }
+	}
 	return ERROR_SUCCESS;
 }
 
@@ -198,7 +209,7 @@
 	if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
 	if (lpVal == NULL) return ERROR_INVALID_PARAMETER;
 	if ((dwRet = RegOpenKey(hKey, lpSubKey, &hRetKey)) != ERROR_SUCCESS) {
-		dprintf_reg(stddeb, "RegSetValue // key not found ... so create it !\n");
+	        dprintf_reg(stddeb, "RegSetValue // key not found ... so create it !\n");
 		if ((dwRet = RegCreateKey(hKey, lpSubKey, &hRetKey)) != ERROR_SUCCESS) {
 			fprintf(stderr, "RegSetValue // key creation error %08lX !\n", dwRet);
 			return dwRet;
@@ -209,7 +220,7 @@
 	if (lpKey->lpValue != NULL) free(lpKey->lpValue);
 	lpKey->lpValue = malloc(strlen(lpVal) + 1);
 	strcpy(lpKey->lpValue, lpVal);
-	dprintf_reg(stddeb,"RegSetValue // successful key='%s' val='%s' !\n", lpSubKey, lpVal);
+	dprintf_reg(stddeb,"RegSetValue // successful key='%s' val='%s' !\n", lpSubKey, lpKey->lpValue);
 	return ERROR_SUCCESS;
 }
 
@@ -228,6 +239,8 @@
 	if (lpSubKey == NULL) return ERROR_INVALID_PARAMETER;
 	if (lpVal == NULL) return ERROR_INVALID_PARAMETER;
 	if (lpcb == NULL) return ERROR_INVALID_PARAMETER;
+        if (!*lpcb) return ERROR_INVALID_PARAMETER;
+
 	if ((dwRet = RegOpenKey(hKey, lpSubKey, &hRetKey)) != ERROR_SUCCESS) {
 		fprintf(stderr, "RegQueryValue // key not found !\n");
 		return dwRet;
@@ -235,14 +248,17 @@
 	lpKey = (LPKEYSTRUCT)GlobalLock(hRetKey);
 	if (lpKey == NULL) return ERROR_BADKEY;
 	if (lpKey->lpValue != NULL) {
-		size = min(strlen(lpKey->lpValue), *lpcb);
-		strncpy(lpVal, lpKey->lpValue, size);
-		*lpcb = (LONG)size;
-		}
-	else {
-		lpVal[0] = '\0';
-		*lpcb = (LONG)0;
-		}
+          if ((size = strlen(lpKey->lpValue)+1) > *lpcb){
+            strncpy(lpVal,lpKey->lpValue,*lpcb-1);
+            lpVal[*lpcb-1] = 0;
+	  } else {
+            strcpy(lpVal,lpKey->lpValue);
+            *lpcb = size;
+          }
+	} else {
+	  *lpVal = 0;
+	  *lpcb = (LONG)1;
+	}
 	dprintf_reg(stddeb,"RegQueryValue // return '%s' !\n", lpVal);
 	return ERROR_SUCCESS;
 }
@@ -253,7 +269,37 @@
  */
 LONG RegEnumKey(HKEY hKey, DWORD dwSubKey, LPSTR lpBuf, DWORD dwSize)
 {
-	dprintf_reg(stdnimp, "RegEnumKey : Empty Stub !!!\n");
+	LPKEYSTRUCT	lpKey;
+	LONG		dwRet;
+	LONG            len;
+
+	dwRet = SHELL_RegCheckForRoot();
+        if (dwRet != ERROR_SUCCESS) return dwRet;
+	dprintf_reg(stddeb, "RegEnumKey(%08lX, %ld)\n", hKey, dwSubKey);
+	if (lpBuf == NULL) return ERROR_INVALID_PARAMETER;
+        switch(hKey) {
+	case 0: 
+	  lpKey = lphTopKey; break;
+        case HKEY_CLASSES_ROOT: /* == 1 */
+          lpKey = lphRootKey; break;
+        default: 
+	  dprintf_reg(stddeb,"RegEnumKey // specific key = %08lX !\n", hKey);
+	  lpKey = (LPKEYSTRUCT)GlobalLock(hKey);
+        }
+
+        lpKey = lpKey->lpSubLvl;
+        while(lpKey != NULL){
+          if (!dwSubKey){
+            len = min(dwSize-1,strlen(lpKey->lpSubKey));
+	    strncpy(lpBuf,lpKey->lpSubKey,len);
+	    lpBuf[len] = 0;
+            dprintf_reg(stddeb, "RegEnumKey: found %s\n",lpBuf);
+	    return ERROR_SUCCESS;
+	  }
+          dwSubKey--;
+	  lpKey = lpKey->lpNextKey;
+        }
+	dprintf_reg(stddeb, "RegEnumKey: key not found!\n");
 	return ERROR_INVALID_PARAMETER;
 }
 
@@ -340,7 +386,9 @@
 	else
 		*AppMisc = 0;
 
-	return DialogBoxIndirectPtr(hSysRes, sysres_DIALOG_SHELL_ABOUT_MSGBOX, hWnd, (WNDPROC)AboutDlgProc);
+	return DialogBoxIndirectPtr( GetWindowWord(hWnd, GWW_HINSTANCE),
+                                     sysres_DIALOG_SHELL_ABOUT_MSGBOX,
+                                     hWnd, (WNDPROC)AboutDlgProc);
 }
 
 
diff --git a/rc/Imakefile b/rc/Imakefile
index 36decda..9e89e0c 100644
--- a/rc/Imakefile
+++ b/rc/Imakefile
@@ -23,6 +23,7 @@
 $(RCOBJS): winerc $(TOP)/include/windows.h
 
 includes::
+	touch $(RCSRCS:.rc=.h)
 
 clean::
 	$(RM) $(RCSRCS:.rc=.c) $(RCSRCS:.rc=.h)
diff --git a/tools/build.c b/tools/build.c
index 9a4bce6..c2ea2f2 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -757,8 +757,10 @@
 
     sprintf(filename, "dll_%s.S", LowerDLLName);
     fp = fopen(filename, "w");
+#ifdef __ELF__
     fprintf (fp, "#define __ASSEMBLY__\n");
     fprintf (fp, "#include <asm/segment.h>\n");
+#endif
     fprintf(fp, "\t.globl " PREFIX "%s_Dispatch\n", UpperDLLName);
     fprintf(fp, PREFIX "%s_Dispatch:\n", UpperDLLName);
     fprintf(fp, "\tandl\t$0x0000ffff,%%esp\n");
diff --git a/windows/cursor.c b/windows/cursor.c
index 7c98f92..911637e 100644
--- a/windows/cursor.c
+++ b/windows/cursor.c
@@ -82,7 +82,6 @@
     lpcur = (CURSORALLOC *)GlobalLock(hCursor);
     memset(lpcur, 0, sizeof(CURSORALLOC));
     if (instance == (HANDLE)NULL) {
-	instance = hSysRes;
 	switch((LONG)cursor_name) {
 	    case IDC_ARROW:
 		lpcur->xcursor = XCreateFontCursor(display, XC_top_left_arrow);
diff --git a/windows/mdi.c b/windows/mdi.c
index ee6f575..f59d501 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -283,23 +283,13 @@
 LONG MDIRestoreChild(HWND parent, MDICLIENTINFO *ci)
 {
     HWND    child;
-    WND    *w      = WIN_FindWndPtr(parent);
-    LPRECT  lprect = &ci->rectRestore;
 
     dprintf_mdi(stddeb,"restoring mdi child\n");
 
     child = ci->hwndActiveChild;
-    
-    w->dwStyle &= ~WS_MAXIMIZE;
-    SetWindowPos(child, 0, lprect->left, lprect->top, 
-		 lprect->right - lprect->left + 1, 
-		 lprect->bottom - lprect->top + 1,
-		 SWP_NOACTIVATE | SWP_NOZORDER);
-    
     ci->flagChildMaximized = FALSE;
 
     ShowWindow(child, SW_RESTORE);		/* display the window */
-    SendMessage(GetParent(parent), WM_NCPAINT, 0, 0);
     MDIBringChildToTop(parent, child, FALSE, FALSE);
 
     return 0;
diff --git a/windows/nonclient.c b/windows/nonclient.c
index 6d0903f..6f586a4 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -110,6 +110,82 @@
 }
 
 
+/*******************************************************************
+ *         NC_GetMinMaxInfo
+ *
+ * Get the minimized and maximized information for a window.
+ */
+void NC_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
+                       POINT *minTrack, POINT *maxTrack )
+{
+    HANDLE minmaxHandle;
+    MINMAXINFO MinMax, *pMinMax;
+    short xinc, yinc;
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+
+      /* Compute default values */
+
+    MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
+    MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
+    MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
+    MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
+    MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
+    MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
+
+    if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
+    {
+        xinc = SYSMETRICS_CXDLGFRAME;
+        yinc = SYSMETRICS_CYDLGFRAME;
+    }
+    else
+    {
+        xinc = yinc = 0;
+	if (HAS_THICKFRAME(wndPtr->dwStyle))
+        {
+            xinc += SYSMETRICS_CXFRAME;
+            yinc += SYSMETRICS_CYFRAME;
+        }
+	if (wndPtr->dwStyle & WS_BORDER)
+        {
+            xinc += SYSMETRICS_CXBORDER;
+            yinc += SYSMETRICS_CYBORDER;
+        }
+    }
+    MinMax.ptMaxSize.x += 2 * xinc;
+    MinMax.ptMaxSize.y += 2 * yinc;
+
+    if ((wndPtr->ptMaxPos.x != -1) || (wndPtr->ptMaxPos.y != -1))
+        MinMax.ptMaxPosition = wndPtr->ptMaxPos;
+    else
+    {
+        MinMax.ptMaxPosition.x = -xinc;
+        MinMax.ptMaxPosition.y = -yinc;
+    }
+
+    minmaxHandle = USER_HEAP_ALLOC( LMEM_MOVEABLE, sizeof(MINMAXINFO) );
+    if (minmaxHandle)
+    {
+	pMinMax = (MINMAXINFO *) USER_HEAP_ADDR( minmaxHandle );
+	memcpy( pMinMax, &MinMax, sizeof(MinMax) );	
+	SendMessage( hwnd, WM_GETMINMAXINFO, 0, (LONG)pMinMax );
+    }
+    else pMinMax = &MinMax;
+
+      /* Some sanity checks */
+
+    pMinMax->ptMaxTrackSize.x = max( pMinMax->ptMaxTrackSize.x,
+				     pMinMax->ptMinTrackSize.x );
+    pMinMax->ptMaxTrackSize.y = max( pMinMax->ptMaxTrackSize.y,
+				     pMinMax->ptMinTrackSize.y );
+    
+    if (maxSize) *maxSize = pMinMax->ptMaxSize;
+    if (maxPos) *maxPos = pMinMax->ptMaxPosition;
+    if (minTrack) *minTrack = pMinMax->ptMinTrackSize;
+    if (maxTrack) *maxTrack = pMinMax->ptMaxTrackSize;
+    if (minmaxHandle) USER_HEAP_FREE( minmaxHandle );
+}
+
+
 /***********************************************************************
  *           NC_HandleNCCalcSize
  *
@@ -841,7 +917,7 @@
 
       /* Get min/max info */
 
-    WINPOS_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
+    NC_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
     sizingRect = wndPtr->rectWindow;
     if (wndPtr->dwStyle & WS_CHILD)
 	GetClientRect( wndPtr->hwndParent, &mouseRect );
@@ -1162,7 +1238,8 @@
     switch(wParam)  /* Hit test */
     {
     case HTCAPTION:
-	SendMessage( hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, lParam );
+        SendMessage( hwnd, WM_SYSCOMMAND,
+                     IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
 	break;
 
     case HTSYSMENU:
@@ -1239,7 +1316,7 @@
     case SC_SCREENSAVE:
 	if (wParam == SC_ABOUTWINE)
 	{   extern char sysres_DIALOG_2[];
-	    DialogBoxIndirectPtr( hSysRes, sysres_DIALOG_2,
+	    DialogBoxIndirectPtr( wndPtr->hInstance, sysres_DIALOG_2,
 		       hwnd, (WNDPROC)AboutWine_Proc );
         }
 	break;
diff --git a/windows/painting.c b/windows/painting.c
index e44110b..782626c 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -1,7 +1,7 @@
 /*
  * Window painting functions
  *
- * Copyright 1993 Alexandre Julliard
+ * Copyright 1993, 1994, 1995 Alexandre Julliard
  */
 
 #include <stdio.h>
@@ -104,12 +104,22 @@
 
 
 /***********************************************************************
+ *           GetControlBrush    (USER.326)
+ */
+HBRUSH GetControlBrush( HWND hwnd, HDC hdc, WORD control )
+{
+    return (HBRUSH)SendMessage( GetParent(hwnd), WM_CTLCOLOR,
+                                hdc, MAKELONG( hwnd, control ) );
+}
+
+
+/***********************************************************************
  *           RedrawWindow    (USER.290)
  */
 BOOL RedrawWindow( HWND hwnd, LPRECT rectUpdate, HRGN hrgnUpdate, UINT flags )
 {
-    HRGN tmpRgn, hrgn = 0;
-    RECT rectClient, rectWindow;
+    HRGN tmpRgn, hrgn;
+    RECT rectClient;
     WND * wndPtr;
 
     if (!hwnd) hwnd = GetDesktopWindow();
@@ -129,111 +139,68 @@
                      hwnd, hrgnUpdate, flags);
     }
     GetClientRect( hwnd, &rectClient );
-    rectWindow = wndPtr->rectWindow;
-    OffsetRect(&rectWindow, -wndPtr->rectClient.left, -wndPtr->rectClient.top);
 
     if (flags & RDW_INVALIDATE)  /* Invalidate */
     {
-	if (hrgnUpdate)  /* Invalidate a region */
-	{
-	    if (flags & RDW_FRAME) tmpRgn = CreateRectRgnIndirect(&rectWindow);
-	    else tmpRgn = CreateRectRgnIndirect( &rectClient );
-	    if (!tmpRgn) return FALSE;
-	    hrgn = CreateRectRgn( 0, 0, 0, 0 );
-	    if (CombineRgn( hrgn, hrgnUpdate, tmpRgn, RGN_AND ) == NULLREGION)
-	    {
-		DeleteObject( hrgn );
-		hrgn = 0;
-	    }
-	    DeleteObject( tmpRgn );
-	}
-	else  /* Invalidate a rectangle */
-	{
-	    RECT rect;
-	    if (flags & RDW_FRAME)
-	    {
-		if (rectUpdate) IntersectRect( &rect, rectUpdate, &rectWindow);
-		else rect = rectWindow;
-	    }
-	    else
-	    {
-		if (rectUpdate) IntersectRect( &rect, rectUpdate, &rectClient);
-		else rect = rectClient;
-	    }
-	    if (!IsRectEmpty(&rect)) hrgn = CreateRectRgnIndirect( &rect );
-	}
-
-	  /* Set update region */
-
-	if (hrgn)
-	{
-	    if (!wndPtr->hrgnUpdate)
-	    {
-		wndPtr->hrgnUpdate = hrgn;
-		if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
-		    MSG_IncPaintCount( wndPtr->hmemTaskQ );
-	    }
-	    else
-	    {
-		tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
-		CombineRgn( tmpRgn, wndPtr->hrgnUpdate, hrgn, RGN_OR );
-		DeleteObject( wndPtr->hrgnUpdate );
-		DeleteObject( hrgn );
-		wndPtr->hrgnUpdate = tmpRgn;
-	    }
-	}
+        if (wndPtr->hrgnUpdate)  /* Is there already an update region? */
+        {
+            tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
+            if ((hrgn = hrgnUpdate) == 0)
+                hrgn = CreateRectRgnIndirect( rectUpdate ? rectUpdate :
+                                              &rectClient );
+            CombineRgn( tmpRgn, wndPtr->hrgnUpdate, hrgn, RGN_OR );
+            DeleteObject( wndPtr->hrgnUpdate );
+            wndPtr->hrgnUpdate = tmpRgn;
+            if (!hrgnUpdate) DeleteObject( hrgn );
+        }
+        else  /* No update region yet */
+        {
+            if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
+                MSG_IncPaintCount( wndPtr->hmemTaskQ );
+            if (hrgnUpdate)
+            {
+                wndPtr->hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
+                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;
 	flags |= RDW_FRAME;  /* Force invalidating the frame of children */
     }
     else if (flags & RDW_VALIDATE)  /* Validate */
     {
-	if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
-	if (!(hrgn = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
-
-	  /* Remove frame from update region */
-
-	if (wndPtr->hrgnUpdate && (flags & RDW_NOFRAME))
-	{
-	    if (!(tmpRgn = CreateRectRgnIndirect( &rectClient )))
-		return FALSE;
-	    if (CombineRgn(hrgn,tmpRgn,wndPtr->hrgnUpdate,RGN_AND) == NULLREGION)
-	    {
-		DeleteObject( hrgn );
-		hrgn = 0;
-	    }
-	    DeleteObject( tmpRgn );
-	    DeleteObject( wndPtr->hrgnUpdate );
-	    wndPtr->hrgnUpdate = hrgn;
-	    hrgn = CreateRectRgn( 0, 0, 0, 0 );
-	}
-
-	  /* Set update region */
-
-	if (wndPtr->hrgnUpdate)
-	{
-	    int res;
-	    if (hrgnUpdate)  /* Validate a region */
-	    {
-		res = CombineRgn(hrgn,wndPtr->hrgnUpdate,hrgnUpdate,RGN_DIFF);
-	    }
-	    else  /* Validate a rectangle */
-	    {
-		if (rectUpdate) tmpRgn = CreateRectRgnIndirect( rectUpdate );
-		else tmpRgn = CreateRectRgnIndirect( &rectWindow );
-		res = CombineRgn( hrgn, wndPtr->hrgnUpdate, tmpRgn, RGN_DIFF );
-		DeleteObject( tmpRgn );
-	    }
-	    DeleteObject( wndPtr->hrgnUpdate );
-	    if (res == NULLREGION)
-	    {
-		DeleteObject( hrgn );
-		wndPtr->hrgnUpdate = 0;
+          /* We need an update region in order to validate anything */
+        if (wndPtr->hrgnUpdate)
+        {
+            if (!hrgnUpdate && !rectUpdate)
+            {
+                  /* Special case: validate everything */
+                DeleteObject( wndPtr->hrgnUpdate );
+                wndPtr->hrgnUpdate = 0;
+            }
+            else
+            {
+                tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
+                if ((hrgn = hrgnUpdate) == 0)
+                    hrgn = CreateRectRgnIndirect( rectUpdate );
+                if (CombineRgn( tmpRgn, wndPtr->hrgnUpdate,
+                                hrgn, RGN_DIFF ) == NULLREGION)
+                {
+                    DeleteObject( tmpRgn );
+                    tmpRgn = 0;
+                }
+                DeleteObject( wndPtr->hrgnUpdate );
+                wndPtr->hrgnUpdate = tmpRgn;
+                if (!hrgnUpdate) DeleteObject( hrgn );
+            }
+            if (!wndPtr->hrgnUpdate)  /* No more update region */
 		if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
 		    MSG_DecPaintCount( wndPtr->hmemTaskQ );
-	    }
-	    else wndPtr->hrgnUpdate = hrgn;
-	}
+        }
+        if (flags & RDW_NOFRAME) wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
+	if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
     }
 
       /* Set/clear internal paint flag */
@@ -393,7 +360,6 @@
  */
 int GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
 {
-    HRGN hrgnClip;
     int retval;
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return ERROR;
@@ -403,13 +369,8 @@
         SetRectRgn( hrgn, 0, 0, 0, 0 );
         return NULLREGION;
     }
-    hrgnClip = CreateRectRgn( 0, 0,
-                             wndPtr->rectClient.right-wndPtr->rectClient.left,
-                             wndPtr->rectClient.bottom-wndPtr->rectClient.top);
-    if (!hrgnClip) return ERROR;
-    retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, hrgnClip, RGN_AND );
+    retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
     if (erase) RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN );
-    DeleteObject( hrgnClip );
     return retval;
 }
 
diff --git a/windows/win.c b/windows/win.c
index 809c333..5148b94 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -400,7 +400,7 @@
 
       /* Send the WM_GETMINMAXINFO message and fix the size if needed */
 
-    WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
+    NC_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack );
 
     if ( maxSize.x < width)
       {
@@ -532,6 +532,21 @@
 	ReleaseCapture();
     WIN_SendParentNotify( hwnd, WM_DESTROY, MAKELONG(hwnd, wndPtr->wIDmenu) );
 
+      /* Recursively destroy owned windows */
+
+    for (;;)
+    {
+        HWND hwndSibling = GetWindow( hwnd, GW_HWNDFIRST );
+        while (hwndSibling)
+        {
+            WND *siblingPtr = WIN_FindWndPtr( hwndSibling );
+            if (siblingPtr->hwndOwner == hwnd) break;
+            hwndSibling = siblingPtr->hwndNext;
+        }
+        if (hwndSibling) DestroyWindow( hwndSibling );
+        else break;
+    }
+
       /* Send destroy messages and destroy children */
 
     SendMessage( hwnd, WM_DESTROY, 0, 0 );
@@ -560,7 +575,6 @@
 }
 
  
- 
 /***********************************************************************
  *           OpenIcon   (USER.44)
  */
@@ -572,7 +586,6 @@
 }
 
  
- 
 /***********************************************************************
  *           FindWindow   (USER.50)
  */
diff --git a/windows/winpos.c b/windows/winpos.c
index 6de8899..5f71349 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -1,7 +1,7 @@
 /*
  * Window position related functions.
  *
- * Copyright 1993, 1994 Alexandre Julliard
+ * Copyright 1993, 1994, 1995 Alexandre Julliard
  */
 
 #include "sysmetrics.h"
@@ -9,6 +9,7 @@
 #include "win.h"
 #include "message.h"
 #include "winpos.h"
+#include "nonclient.h"
 #include "stddebug.h"
 /* #define DEBUG_WIN */
 #include "debug.h"
@@ -17,6 +18,95 @@
 
 
 /***********************************************************************
+ *           WINPOS_FindIconPos
+ *
+ * Find a suitable place for an iconic window.
+ * The new position is stored into wndPtr->ptIconPos.
+ */
+static void WINPOS_FindIconPos( HWND hwnd )
+{
+    RECT rectParent;
+    short x, y, xspacing, yspacing;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+
+    if (!wndPtr) return;
+    GetClientRect( wndPtr->hwndParent, &rectParent );
+    if ((wndPtr->ptIconPos.x >= rectParent.left) &&
+        (wndPtr->ptIconPos.x + SYSMETRICS_CXICON < rectParent.right) &&
+        (wndPtr->ptIconPos.y >= rectParent.top) &&
+        (wndPtr->ptIconPos.y + SYSMETRICS_CYICON < rectParent.bottom))
+        return;  /* The icon already has a suitable position */
+
+    xspacing = yspacing = 70;  /* FIXME: This should come from WIN.INI */
+    y = rectParent.bottom;
+    for (;;)
+    {
+        for (x = rectParent.left; x<=rectParent.right-xspacing; x += xspacing)
+        {
+              /* Check if another icon already occupies this spot */
+            HWND hwndChild = GetWindow( wndPtr->hwndParent, GW_CHILD );
+            while (hwndChild)
+            {
+                WND *childPtr = WIN_FindWndPtr( hwndChild );
+                if ((childPtr->dwStyle & WS_MINIMIZE) && (hwndChild != hwnd))
+                {
+                    if ((childPtr->rectWindow.left < x + xspacing) &&
+                        (childPtr->rectWindow.right >= x) &&
+                        (childPtr->rectWindow.top <= y) &&
+                        (childPtr->rectWindow.bottom > y - yspacing))
+                        break;  /* There's a window in there */
+                }
+                
+                hwndChild = childPtr->hwndNext;
+            }
+            if (!hwndChild)
+            {
+                  /* No window was found, so it's OK for us */
+                wndPtr->ptIconPos.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
+                wndPtr->ptIconPos.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
+                return;
+            }
+        }
+        y -= yspacing;
+    }
+}
+
+
+/***********************************************************************
+ *           ArrangeIconicWindows   (USER.170)
+ */
+WORD ArrangeIconicWindows( HWND parent )
+{
+    RECT rectParent;
+    HWND hwndChild;
+    short x, y, xspacing, yspacing;
+
+    GetClientRect( parent, &rectParent );
+    x = rectParent.left;
+    y = rectParent.bottom;
+    xspacing = yspacing = 70;  /* FIXME: This should come from WIN.INI */
+    hwndChild = GetWindow( parent, GW_CHILD );
+    while (hwndChild)
+    {
+        if (IsIconic( hwndChild ))
+        {
+            SetWindowPos( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
+                          y - (yspacing + SYSMETRICS_CYICON) / 2, 0, 0,
+                          SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
+            if (x <= rectParent.right - xspacing) x += xspacing;
+            else
+            {
+                x = rectParent.left;
+                y -= yspacing;
+            }
+        }
+        hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
+    }
+    return yspacing;
+}
+
+
+/***********************************************************************
  *           GetWindowRect   (USER.32)
  */
 void GetWindowRect( HWND hwnd, LPRECT rect ) 
@@ -99,6 +189,7 @@
     return hwndRet;
 }
 
+
 /*******************************************************************
  *         ChildWindowFromPoint   (USER.191)
  */
@@ -187,6 +278,7 @@
     return hwndActive;
 }
 
+
 /*******************************************************************
  *         SetActiveWindow    (USER.59)
  */
@@ -229,84 +321,126 @@
 {    
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     BOOL wasVisible;
-    BOOL wasIconic;
+    POINT maxSize;
     int swpflags = 0;
+    short x = 0, y = 0, cx = 0, cy = 0;
 
     if (!wndPtr) return FALSE;
 
     dprintf_win(stddeb,"ShowWindow: hwnd=%04X, cmd=%d\n", hwnd, cmd);
 
-    /*
-     *  wasVisible is true if user has not made window invisible 
-     *  wasIconic is true if the window is not iconified
-     */
     wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
 
     switch(cmd)
     {
         case SW_HIDE:
-	    /*
-	     *  if the window wasn't visible to begin with -- just return
-	     */
-	    if (!wasVisible) 
-		return FALSE;  /* Nothing to do */
 	    swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
 		        SWP_NOACTIVATE | SWP_NOZORDER;
 	    break;
 
-
 	case SW_SHOWMINNOACTIVE:
+            swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
+            /* fall through */
 	case SW_SHOWMINIMIZED:
-	case SW_MINIMIZE: 
-	    wndPtr->dwStyle |= WS_MINIMIZE;
-	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
-		        SWP_NOACTIVATE | SWP_NOZORDER;
-
-	    /* store the size and position of the window, so we can
-	     *	deiconify it to the same size and position	
-	     */
-            wndPtr->rectNormal = wndPtr->rectWindow; 
-            wndPtr->ptIconPos.x = wndPtr->rectWindow.left;
-            wndPtr->ptIconPos.y = wndPtr->rectWindow.top;
-	    /* move the window to icon size and position and
-	     * tell it that it is going to have to be painted
-	     */
-            MoveWindow(hwnd, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
-                       SYSMETRICS_CXICON, SYSMETRICS_CYICON, FALSE);
-            RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_ERASE | RDW_ERASENOW);
+            swpflags |= SWP_SHOWWINDOW;
+            /* fall through */
+	case SW_MINIMIZE:
+            swpflags |= SWP_FRAMECHANGED;
+            if (!(wndPtr->dwStyle & WS_MINIMIZE))
+            {
+                if (wndPtr->dwStyle & WS_MAXIMIZE)
+                {
+                    wndPtr->flags |= WIN_RESTORE_MAX;
+                    wndPtr->dwStyle &= ~WS_MAXIMIZE;
+                }
+                else
+                {
+                    wndPtr->flags &= ~WIN_RESTORE_MAX;
+                    wndPtr->rectNormal = wndPtr->rectWindow;
+                }
+                wndPtr->dwStyle |= WS_MINIMIZE;
+                WINPOS_FindIconPos( hwnd );
+                x  = wndPtr->ptIconPos.x;
+                y  = wndPtr->ptIconPos.y;
+                cx = SYSMETRICS_CXICON;
+                cy = SYSMETRICS_CYICON;
+            }
+            else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
 	    break;
 
-	case SW_SHOWNA:
 	case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE: */
+            swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
+            if (!(wndPtr->dwStyle & WS_MAXIMIZE))
+            {
+                  /* Store the current position and find the maximized size */
+                if (!(wndPtr->dwStyle & WS_MINIMIZE))
+                    wndPtr->rectNormal = wndPtr->rectWindow; 
+                NC_GetMinMaxInfo( hwnd, &maxSize,
+                                  &wndPtr->ptMaxPos, NULL, NULL );
+                x  = wndPtr->ptMaxPos.x;
+                y  = wndPtr->ptMaxPos.y;
+                cx = maxSize.x;
+                cy = maxSize.y;
+                wndPtr->dwStyle &= ~WS_MINIMIZE;
+                wndPtr->dwStyle |= WS_MAXIMIZE;
+            }
+            else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
+            break;
+
+	case SW_SHOWNA:
+            swpflags |= SWP_NOACTIVATE | SWP_NOZORDER;
+            /* fall through */
 	case SW_SHOW:
 	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
 	    break;
 
-
-	case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
 	case SW_SHOWNOACTIVATE:
+            swpflags |= SWP_NOZORDER;
+            if (GetActiveWindow()) swpflags |= SWP_NOACTIVATE;
+            /* fall through */
+	case SW_SHOWNORMAL:  /* same as SW_NORMAL: */
 	case SW_RESTORE:
-	    wasIconic = IsIconic(hwnd);
-	    wndPtr->dwStyle &= ~WS_MINIMIZE;
-	    wndPtr->dwStyle &= ~WS_MAXIMIZE;
-	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
-	    if (cmd == SW_SHOWNOACTIVATE)
-	    {
-		swpflags |= SWP_NOZORDER;
-		if (GetActiveWindow()) swpflags |= SWP_NOACTIVATE;
-	    }
-	    if (wasIconic) {
-		MoveWindow(hwnd, wndPtr->rectNormal.left, 
-			   wndPtr->rectNormal.top,
-			   wndPtr->rectNormal.right - wndPtr->rectNormal.left, 
-			   wndPtr->rectNormal.bottom - wndPtr->rectNormal.top, 
-			   FALSE);
-	    }
+	    swpflags |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
+            if (wndPtr->dwStyle & WS_MINIMIZE)
+            {
+                wndPtr->ptIconPos.x = wndPtr->rectWindow.left;
+                wndPtr->ptIconPos.y = wndPtr->rectWindow.top;
+                wndPtr->dwStyle &= ~WS_MINIMIZE;
+                if (wndPtr->flags & WIN_RESTORE_MAX)
+                {
+                    /* Restore to maximized position */
+                    NC_GetMinMaxInfo( hwnd, &maxSize, &wndPtr->ptMaxPos,
+                                      NULL, NULL );
+                    x  = wndPtr->ptMaxPos.x;
+                    y  = wndPtr->ptMaxPos.y;
+                    cx = maxSize.x;
+                    cy = maxSize.y;
+                   wndPtr->dwStyle |= WS_MAXIMIZE;
+                }
+                else  /* Restore to normal position */
+                {
+                    x  = wndPtr->rectNormal.left;
+                    y  = wndPtr->rectNormal.top;
+                    cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
+                    cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
+                }
+            }
+            else if (wndPtr->dwStyle & WS_MAXIMIZE)
+            {
+                wndPtr->ptMaxPos.x = wndPtr->rectWindow.left;
+                wndPtr->ptMaxPos.y = wndPtr->rectWindow.top;
+                wndPtr->dwStyle &= ~WS_MAXIMIZE;
+                x  = wndPtr->rectNormal.left;
+                y  = wndPtr->rectNormal.top;
+                cx = wndPtr->rectNormal.right - wndPtr->rectNormal.left;
+                cy = wndPtr->rectNormal.bottom - wndPtr->rectNormal.top;
+            }
+            else swpflags |= SWP_NOSIZE | SWP_NOMOVE;
 	    break;
     }
 
     SendMessage( hwnd, WM_SHOWWINDOW, (cmd != SW_HIDE), 0 );
-    SetWindowPos( hwnd, 0, 0, 0, 0, 0, swpflags );
+    SetWindowPos( hwnd, HWND_TOP, x, y, cx, cy, swpflags );
 
       /* Send WM_SIZE and WM_MOVE messages if not already done */
     if (!(wndPtr->flags & WIN_GOT_SIZEMSG))
@@ -422,50 +556,6 @@
 
 
 /*******************************************************************
- *         WINPOS_GetMinMaxInfo
- *
- * Send a WM_GETMINMAXINFO to the window.
- */
-void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
-			   POINT *minTrack, POINT *maxTrack )
-{
-    HANDLE minmaxHandle;
-    MINMAXINFO MinMax, *pMinMax;
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-
-    MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
-    MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
-    MinMax.ptMaxPosition = wndPtr->ptMaxPos;
-    MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
-    MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
-    MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
-    MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
-
-    minmaxHandle = USER_HEAP_ALLOC( LMEM_MOVEABLE, sizeof(MINMAXINFO) );
-    if (minmaxHandle)
-    {
-	pMinMax = (MINMAXINFO *) USER_HEAP_ADDR( minmaxHandle );
-	memcpy( pMinMax, &MinMax, sizeof(MinMax) );	
-	SendMessage( hwnd, WM_GETMINMAXINFO, 0, (LONG)pMinMax );
-    }
-    else pMinMax = &MinMax;
-
-      /* Some sanity checks */
-
-    pMinMax->ptMaxTrackSize.x = max( pMinMax->ptMaxTrackSize.x,
-				     pMinMax->ptMinTrackSize.x );
-    pMinMax->ptMaxTrackSize.y = max( pMinMax->ptMaxTrackSize.y,
-				     pMinMax->ptMinTrackSize.y );
-    
-    if (maxSize) *maxSize = pMinMax->ptMaxSize;
-    if (maxPos) *maxPos = pMinMax->ptMaxPosition;
-    if (minTrack) *minTrack = pMinMax->ptMinTrackSize;
-    if (maxTrack) *maxTrack = pMinMax->ptMaxTrackSize;
-    if (minmaxHandle) USER_HEAP_FREE( minmaxHandle );
-}
-
-
-/*******************************************************************
  *         WINPOS_ChangeActiveWindow
  *
  * Change the active window and send the corresponding messages.
@@ -543,7 +633,7 @@
     if ((wndPtr->dwStyle & WS_THICKFRAME) ||
 	(wndPtr->dwStyle & (WS_POPUP | WS_CHILD) == 0))
     {
-	WINPOS_GetMinMaxInfo( winpos->hwnd, &maxSize, NULL, NULL, NULL );
+	NC_GetMinMaxInfo( winpos->hwnd, &maxSize, NULL, NULL, NULL );
 	winpos->cx = min( winpos->cx, maxSize.x );
 	winpos->cy = min( winpos->cy, maxSize.y );
     }
@@ -557,7 +647,7 @@
  * Move a window in Z order, invalidating everything that needs it.
  * Only necessary for windows without associated X window.
  */
-static void WINPOS_MoveWindowZOrder( HWND hwnd, HWND hwndAfter, BOOL erase )
+static void WINPOS_MoveWindowZOrder( HWND hwnd, HWND hwndAfter )
 {
     BOOL movingUp;
     HWND hwndCur;
@@ -603,7 +693,7 @@
             OffsetRect( &rect, -wndPtr->rectClient.left,
                         -wndPtr->rectClient.top );
             RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
-                          RDW_FRAME | RDW_ERASE | (erase ? RDW_ERASENOW : 0) );
+                          RDW_FRAME | RDW_ERASE );
             hwndCur = curPtr->hwndNext;
         }
     }
@@ -619,7 +709,7 @@
             OffsetRect( &rect, -curPtr->rectClient.left,
                         -curPtr->rectClient.top );
             RedrawWindow( hwndCur, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
-                          RDW_FRAME | RDW_ERASE | (erase ? RDW_ERASENOW : 0) );
+                          RDW_FRAME | RDW_ERASE );
             hwndCur = curPtr->hwndNext;
         }
     }
@@ -627,6 +717,47 @@
 
 
 /***********************************************************************
+ *           WINPOS_SetXWindosPos
+ *
+ * SetWindowPos() for an X window. Used by the real SetWindowPos().
+ */
+static void WINPOS_SetXWindowPos( WINDOWPOS *winpos )
+{
+    XWindowChanges winChanges;
+    int changeMask = 0;
+    WND *wndPtr = WIN_FindWndPtr( winpos->hwnd );
+
+    if (!(winpos->flags & SWP_NOSIZE))
+    {
+        winChanges.width     = winpos->cx;
+        winChanges.height    = winpos->cy;
+        changeMask |= CWWidth | CWHeight;
+    }
+    if (!(winpos->flags & SWP_NOMOVE))
+    {
+        winChanges.x = winpos->x;
+        winChanges.y = winpos->y;
+        changeMask |= CWX | CWY;
+    }
+    if (!(winpos->flags & SWP_NOZORDER))
+    {
+        if (winpos->hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
+        else winChanges.stack_mode = Below;
+        if ((winpos->hwndInsertAfter != HWND_TOP) &&
+            (winpos->hwndInsertAfter != HWND_BOTTOM))
+        {
+            WND * insertPtr = WIN_FindWndPtr( winpos->hwndInsertAfter );
+            winChanges.sibling = insertPtr->window;
+            changeMask |= CWSibling;
+        }
+        changeMask |= CWStackMode;
+    }
+    if (changeMask)
+        XConfigureWindow( display, wndPtr->window, changeMask, &winChanges );
+}
+
+
+/***********************************************************************
  *           WINPOS_InternalSetWindowPos
  *
  * Helper function for SetWindowPos.
@@ -637,8 +768,6 @@
     WND *wndPtr;
     RECT newWindowRect, newClientRect;
     int flags, result;
-    int changeMask = 0;
-    XWindowChanges winChanges;
 
       /* Send WM_WINDOWPOSCHANGING message */
 
@@ -657,13 +786,20 @@
 
       /* Check flags */
 
+    if (winpos->hwnd == hwndActive)
+        winpos->flags |= SWP_NOACTIVATE;   /* Already active */
+    if ((wndPtr->rectWindow.right-wndPtr->rectWindow.left == winpos->cx) &&
+        (wndPtr->rectWindow.bottom-wndPtr->rectWindow.top == winpos->cy))
+        winpos->flags |= SWP_NOSIZE;    /* Already the right size */
+    if ((wndPtr->rectWindow.left == winpos->x) &&
+        (wndPtr->rectWindow.top == winpos->y))
+        winpos->flags |= SWP_NOMOVE;    /* Already the right position */
     flags = winpos->flags;
-    if (winpos->hwnd == hwndActive) flags |= SWP_NOACTIVATE; /*Already active*/
 
       /* Check hwndAfter */
 
     hwndAfter = winpos->hwndInsertAfter;
-    if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
+    if (!(winpos->flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
     {
 	  /* Ignore TOPMOST flags when activating a window */
           /* _and_ moving it in Z order. */
@@ -676,72 +812,36 @@
       /* hwndAfter must be a sibling of the window */
     if ((hwndAfter != HWND_TOP) && (hwndAfter != HWND_BOTTOM) &&
 	(GetParent(winpos->hwnd) != GetParent(hwndAfter))) return FALSE;
+    winpos->hwndInsertAfter = hwndAfter;
 
       /* Calculate new position and size */
 
     newWindowRect = wndPtr->rectWindow;
     newClientRect = wndPtr->rectClient;
 
-    if (!(flags & SWP_NOSIZE))
+    if (!(winpos->flags & SWP_NOSIZE))
     {
-        if ((newWindowRect.right != newWindowRect.left + winpos->cx) ||
-            (newWindowRect.bottom != newWindowRect.top + winpos->cy))
-        {
-            newWindowRect.right  = newWindowRect.left + winpos->cx;
-            newWindowRect.bottom = newWindowRect.top + winpos->cy;
-            winChanges.width     = winpos->cx;
-            winChanges.height    = winpos->cy;
-            changeMask |= CWWidth | CWHeight;
-        }
-        else flags = winpos->flags |= SWP_NOSIZE;
+        newWindowRect.right  = newWindowRect.left + winpos->cx;
+        newWindowRect.bottom = newWindowRect.top + winpos->cy;
     }
-    if (!(flags & SWP_NOMOVE))
+    if (!(winpos->flags & SWP_NOMOVE))
     {
-        if ((newWindowRect.left != winpos->x) ||
-            (newWindowRect.top != winpos->y))
-        {
-            newWindowRect.left    = winpos->x;
-            newWindowRect.top     = winpos->y;
-            newWindowRect.right  += winpos->x - wndPtr->rectWindow.left;
-            newWindowRect.bottom += winpos->y - wndPtr->rectWindow.top;
-            if (wndPtr->dwStyle & WS_CHILD)
-            {
-                WND *parentPtr = WIN_FindWndPtr(wndPtr->hwndParent);
-                winChanges.x = winpos->x + parentPtr->rectClient.left 
-                                - parentPtr->rectWindow.left;
-                winChanges.y = winpos->y + parentPtr->rectClient.top
-                                - parentPtr->rectWindow.top;
-            }
-            else
-            {
-                winChanges.x = winpos->x;
-                winChanges.y = winpos->y;
-            }
-            changeMask |= CWX | CWY;
-        }
-        else flags = winpos->flags |= SWP_NOMOVE;
+        newWindowRect.left    = winpos->x;
+        newWindowRect.top     = winpos->y;
+        newWindowRect.right  += winpos->x - wndPtr->rectWindow.left;
+        newWindowRect.bottom += winpos->y - wndPtr->rectWindow.top;
     }
 
       /* Reposition window in Z order */
 
-    if (!(flags & SWP_NOZORDER))
+    if (!(winpos->flags & SWP_NOZORDER))
     {
         if (wndPtr->window)
         {
             WIN_UnlinkWindow( winpos->hwnd );
             WIN_LinkWindow( winpos->hwnd, hwndAfter );
-            if (hwndAfter == HWND_TOP) winChanges.stack_mode = Above;
-            else winChanges.stack_mode = Below;
-            if ((hwndAfter != HWND_TOP) && (hwndAfter != HWND_BOTTOM))
-            {
-                WND * insertPtr = WIN_FindWndPtr( hwndAfter );
-                winChanges.sibling = insertPtr->window;
-                changeMask |= CWSibling;
-            }
-            changeMask |= CWStackMode;
         }
-        else WINPOS_MoveWindowZOrder( winpos->hwnd, hwndAfter,
-                                      !(flags & SWP_DEFERERASE) );
+        else WINPOS_MoveWindowZOrder( winpos->hwnd, hwndAfter );
     }
 
       /* Send WM_NCCALCSIZE message to get new client area */
@@ -755,8 +855,7 @@
 
     if (wndPtr->window)
     {
-        if (changeMask) XConfigureWindow( display, wndPtr->window,
-                                          changeMask, &winChanges );
+        WINPOS_SetXWindowPos( winpos );
         wndPtr->rectWindow = newWindowRect;
         wndPtr->rectClient = newClientRect;
     }
@@ -767,20 +866,21 @@
         wndPtr->rectWindow = newWindowRect;
         wndPtr->rectClient = newClientRect;
 
-        if (changeMask)
+        if (!(flags & SWP_NOREDRAW) &&
+            (!(flags & SWP_NOSIZE) || !(flags & SWP_NOMOVE) ||
+             !(flags & SWP_NOZORDER)))
         {
             HRGN hrgn1 = CreateRectRgnIndirect( &oldWindowRect );
             HRGN hrgn2 = CreateRectRgnIndirect( &wndPtr->rectWindow );
             HRGN hrgn3 = CreateRectRgn( 0, 0, 0, 0 );
             CombineRgn( hrgn3, hrgn1, hrgn2, RGN_DIFF );
             RedrawWindow( wndPtr->hwndParent, NULL, hrgn3,
-                          RDW_INVALIDATE | RDW_ALLCHILDREN |
-                          RDW_ERASE | RDW_ERASENOW );
+                          RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE );
             if ((oldWindowRect.left != wndPtr->rectWindow.left) ||
                 (oldWindowRect.top != wndPtr->rectWindow.top))
             {
                 RedrawWindow( winpos->hwnd, NULL, 0, RDW_INVALIDATE |
-                      RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW );
+                              RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE );
             }
             DeleteObject( hrgn1 );
             DeleteObject( hrgn2 );
@@ -797,8 +897,9 @@
         }
         else
         {
-            RedrawWindow( winpos->hwnd, NULL, 0,
-                          RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
+            if (!(flags & SWP_NOREDRAW))
+                RedrawWindow( winpos->hwnd, NULL, 0,
+                              RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
         }
     }
     else if (flags & SWP_HIDEWINDOW)
@@ -810,9 +911,10 @@
         }
         else
         {
-            RedrawWindow( wndPtr->hwndParent, &wndPtr->rectWindow, 0,
-                          RDW_INVALIDATE | RDW_FRAME |
-                          RDW_ALLCHILDREN | RDW_ERASE | RDW_ERASENOW );
+            if (!(flags & SWP_NOREDRAW))
+                RedrawWindow( wndPtr->hwndParent, &wndPtr->rectWindow, 0,
+                              RDW_INVALIDATE | RDW_FRAME |
+                              RDW_ALLCHILDREN | RDW_ERASE );
         }
         if ((winpos->hwnd == GetFocus()) || IsChild(winpos->hwnd, GetFocus()))
             SetFocus( GetParent(winpos->hwnd) );  /* Revert focus to parent */
@@ -840,15 +942,17 @@
       /* Repaint the window */
 
     if (wndPtr->window) MSG_Synchronize();  /* Wait for all expose events */
-    if (flags & SWP_FRAMECHANGED)
+    if ((flags & SWP_FRAMECHANGED) && !(flags & SWP_NOREDRAW))
         RedrawWindow( winpos->hwnd, NULL, 0,
                       RDW_INVALIDATE | RDW_FRAME | RDW_ERASE );
-    RedrawWindow( winpos->hwnd, NULL, 0,
-                  (flags & SWP_NOREDRAW) ? RDW_VALIDATE : RDW_ERASENOW );
+    if (!(flags & SWP_DEFERERASE))
+        RedrawWindow( wndPtr->hwndParent, NULL, 0,
+                      RDW_ALLCHILDREN | RDW_ERASENOW );
 
       /* And last, send the WM_WINDOWPOSCHANGED message */
 
-    SendMessage( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LONG)winpos );
+    if (!(winpos->flags & SWP_NOSENDCHANGING))
+        SendMessage( winpos->hwnd, WM_WINDOWPOSCHANGED, 0, (LONG)winpos );
     return TRUE;
 }
 
@@ -996,12 +1100,3 @@
 {
     printf("STUB CascadeChildWindows(%04X, %d)\n", parent, action);
 }
-
-/***********************************************************************
- *           ArrangeIconicWindows   (USER.170)
- */
-WORD ArrangeIconicWindows( HWND parent )
-{
-    printf("STUB ArrangeIconicWindows(%04X)\n", parent);
-    return 0;
-}