Release 940201

Tue Feb  1 21:14:47 1994  Bob Amstadt  (bob@pooh)

	* [loader/selector.c]
	Added function CreateNewSegments().  Modified IPCCopySelector
	to allow aliasing to any arbitrary memory space.

	* [memory/global.c]
	Fixed potential bug in GlobalGetFreeSegments().

	* [memory/linear.c]
	Created functions GlobalLinearLock() and GlobalLinearUnlock().

Tue Feb  1 05:51:43 1994  julliard@di.epfl.ch (Alexandre Julliard)

	* [controls/widgets.c]
	Removed CAPTION window class.

	* [loader/cursor.c]
	Bug fix in LoadCursor(): don't allocate memory every time for
	built-in cursors.

	* [windows/clipping.c]
	Invalidate child windows in InvalidateRgn().

	* [windows/defwnd.c]
	Added repaint of the caption when changing window text.

	* [windows/event.c]
	Modified SetCapture() to allow keyboard events while capturing.

	* [windows/message.c]
	New function MSG_GetHardwareMessage(), to do mouse tracking
	without returning control to the Windows program.

	* [windows/nonclient.c]
	A couple of changes in frame drawing for DLGMODALFRAME windows.
	Rewritten window moving code, to use MSG_GetHardwareMessage()
	instead of non-client mouse events (this is the way Windows
	does it), and to send WM_ENTERSIZEMOVE messages.
	Removed WM_NCBUTTONUP and WM_NCMOUSEMOVE handlers.

	* [windows/win.c]
	Allocate temporary structures on the USER heap instead of
	using GlobalAlloc().

	* [windows/winpos.c]
	Added function WINPOS_GetMinMaxInfo() to get sizing informations.

Jan 31, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [windows/nonclient.c]
	Call to StdDrawScrollBar() during NC's drawing.
	Call to NC_ScrollBarButtonDown() on NC mouse events WM_LBUTTONDOWN.
	Call to NC_ScrollBarButtonUp() on NC mouse events WM_LBUTTONUP.
	Call to NC_ScrollBarMouseMove() on NC mouse events WM_MOUSEMOVE.

	* [controls/menu.c]
	New GetSubMenu() function.
	Move GetMenu() & SetMenu() functions from 'windows/win.c'.

	* [controls/listbox.c]
	Start changes to satisfy recent changes in scrollbars/windows.

	* [loader/resource.c]
	Put some code in LoadAccelerators() stub.
	New TranslateAccelerator() function.

	* [windows/win.c]
	Remove GetMenu() & SetMenu() functions.
	Call to NC_CreateScrollBars() if required by CreateWindow().

Mon Jan 24 10:40:10 EST 1994 John Richardson (jrichard@cs.uml.edu)

        * [window/win.c]
        Added functions EnumWindows, EnumChildWindows, and helper
        WIN_EnumChildWin.  EnumWindows won't list all wine windows
        because GetDesktopWindow isn't complete.  However, the code
        is in place for it to work correctly and only needs 
        GetDesktopWindow to do so.  

Tue Jan 25 05:51:47 1994  julliard@di.epfl.ch (Alexandre Julliard)

	* [windows/defwnd.c]
	Added handling of activation messages (WM_ACTIVATE,
	WM_NCACTIVATE, WM_MOUSEACTIVATE)

	* [windows/event.c]
	De-activate the window when losing input focus.

	* [windows/focus.c]
	Bug fix in SetFocus().

	* [windows/message.c]
	Added activation of the window on mouse-clicks.

	* [windows/nonclient.c]
	Changed non-client area painting to use the correct colors
	depending upon the activation state.
	Added WM_NCACTIVATE message handling.
	Fixed a couple of bugs in window moving and resizing.

	* [windows/winpos.c]
	Implemented Get/SetActiveWindow().
	Implemented SWP_NOACTIVATE flag in SetWindowPos().

Jan 17, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [misc/message.c]
	MessageBox has a CaptionBar for his title except for
		MB_SYSTEMMODAL with MB_ICONHAND.

	* [windows/nonclient.c]
	Call to NC_TrackSysMenu on SysMenu button mouse click.

	* [windows/defwnd.c]
	Call to NC_TrackSysMenu on Alt key (VK_MENU).

	* [controls/menu.c]
	New GetSystemMenu() function.
	New CopySystemMenu() internal function.
	New NC_TrackSysMenu() internal function.

	* [include/windows.h]
	New WM_INITMENU, WM_INITMENUPOPUP, WM_MENUSELECT & WM_MENUCHAR defines.
diff --git a/windows/Imakefile b/windows/Imakefile
index b16652f..5aa561e 100644
--- a/windows/Imakefile
+++ b/windows/Imakefile
@@ -3,46 +3,54 @@
 MODULE = windows
 
 SRCS = \
+	caret.c \
 	class.c \
+	clipping.c \
 	dc.c \
 	dce.c \
-	event.c \
-	message.c \
-	win.c \
-	timer.c \
-	graphics.c \
-	clipping.c \
-	mapping.c \
-	painting.c \
-	keyboard.c \
-	utility.c \
-	syscolor.c \
-	defwnd.c \
 	defdlg.c \
+	defwnd.c \
 	dialog.c \
+	event.c \
 	focus.c \
-	scroll.c
+	graphics.c \
+	keyboard.c \
+	mapping.c \
+	message.c \
+	nonclient.c \
+	painting.c \
+	scroll.c \
+	syscolor.c \
+	sysmetrics.c \
+	timer.c \
+	utility.c \
+	win.c \
+	winpos.c
 
 OBJS = \
+	caret.o \
 	class.o \
+	clipping.o \
 	dc.o \
 	dce.o \
-	event.o \
-	message.o \
-	win.o \
-	timer.o \
-	graphics.o \
-	clipping.o \
-	mapping.o \
-	painting.o \
-	keyboard.o \
-	utility.o \
-	syscolor.o \
-	defwnd.o \
 	defdlg.o \
+	defwnd.o \
 	dialog.o \
+	event.o \
 	focus.o \
-	scroll.o
+	graphics.o \
+	keyboard.o \
+	mapping.o \
+	message.o \
+	nonclient.o \
+	painting.o \
+	scroll.o \
+	syscolor.o \
+	sysmetrics.o \
+	timer.o \
+	utility.o \
+	win.o \
+	winpos.o
 
 WineRelocatableTarget($(TOP)/$(MODULE),,$(OBJS))
 DependTarget()
diff --git a/windows/clipping.c b/windows/clipping.c
index 3c759a6..28d0da9 100644
--- a/windows/clipping.c
+++ b/windows/clipping.c
@@ -38,6 +38,16 @@
     else MSG_IncPaintCount( wndPtr->hmemTaskQ );
     wndPtr->hrgnUpdate = newRgn;
     if (erase) wndPtr->flags |= WIN_ERASE_UPDATERGN;
+
+      /* Invalidate the children overlapping the region */
+
+    if (wndPtr->dwStyle & WS_CLIPCHILDREN) return;
+    for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
+    {
+	if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
+	if (hrgn && !RectInRegion( hrgn, &wndPtr->rectWindow )) continue;
+	InvalidateRgn( hwnd, hrgn, erase );
+    }
 }
 
 
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 95bb0f0..62f9f50 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -13,14 +13,34 @@
 #include "user.h"
 
 extern LONG NC_HandleNCPaint( HWND hwnd, HRGN hrgn );
+extern LONG NC_HandleNCActivate( HWND hwnd, WORD wParam );
 extern LONG NC_HandleNCCalcSize( HWND hwnd, NCCALCSIZE_PARAMS *params );
 extern LONG NC_HandleNCHitTest( HWND hwnd, POINT pt );
 extern LONG NC_HandleNCLButtonDown( HWND hwnd, WORD wParam, LONG lParam );
-extern LONG NC_HandleNCLButtonUp( HWND hwnd, WORD wParam, LONG lParam );
 extern LONG NC_HandleNCLButtonDblClk( HWND hwnd, WORD wParam, LONG lParam );
-extern LONG NC_HandleNCMouseMove( HWND hwnd, WORD wParam, POINT pt );
 extern LONG NC_HandleSysCommand( HWND hwnd, WORD wParam, POINT pt );
 extern LONG NC_HandleSetCursor( HWND hwnd, WORD wParam, LONG lParam );
+extern void NC_TrackSysMenu( HWND hwnd ); /* menu.c */
+
+
+
+/***********************************************************************
+ *           DEFWND_SetText
+ *
+ * Set the window text.
+ */
+void DEFWND_SetText( HWND hwnd, LPSTR text )
+{
+    LPSTR textPtr;
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+
+    if (wndPtr->hText) USER_HEAP_FREE( wndPtr->hText );
+    wndPtr->hText = USER_HEAP_ALLOC( LMEM_MOVEABLE, strlen(text) + 2 );
+    textPtr = (LPSTR) USER_HEAP_ADDR( wndPtr->hText );
+    strcpy( textPtr, text );
+        /* for use by edit control */
+    *(textPtr + strlen(text) + 1) = '\0';
+}
 
 
 /***********************************************************************
@@ -43,15 +63,7 @@
 	{
 	    CREATESTRUCT * createStruct = (CREATESTRUCT *)lParam;
 	    if (createStruct->lpszName)
-	    {
-		  /* Allocate space for window text */
-		wndPtr->hText = USER_HEAP_ALLOC(GMEM_MOVEABLE, 
-					strlen(createStruct->lpszName) + 2);
-		textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
-		strcpy(textPtr, createStruct->lpszName);
-		*(textPtr + strlen(createStruct->lpszName) + 1) = '\0';
-		                         /* for use by edit control */
-	    }
+		DEFWND_SetText( hwnd, createStruct->lpszName );
 	    return 1;
 	}
 
@@ -67,14 +79,11 @@
     case WM_NCLBUTTONDOWN:
 	return NC_HandleNCLButtonDown( hwnd, wParam, lParam );
 
-    case WM_NCLBUTTONUP:
-	return NC_HandleNCLButtonUp( hwnd, wParam, lParam );
-
     case WM_NCLBUTTONDBLCLK:
 	return NC_HandleNCLButtonDblClk( hwnd, wParam, lParam );
 
-    case WM_NCMOUSEMOVE:
-	return NC_HandleNCMouseMove( hwnd, wParam, MAKEPOINT(lParam) );
+    case WM_NCACTIVATE:
+	return NC_HandleNCActivate( hwnd, wParam );
 
     case WM_NCDESTROY:
 	{
@@ -95,6 +104,19 @@
 	DestroyWindow( hwnd );
 	return 0;
 
+    case WM_MOUSEACTIVATE:
+	if (wndPtr->dwStyle & WS_CHILD)
+	{
+	    LONG ret = SendMessage( wndPtr->hwndParent, WM_MOUSEACTIVATE,
+				    wParam, lParam );
+	    if (ret) return ret;
+	}
+	return MA_ACTIVATE;
+
+    case WM_ACTIVATE:
+	if (wParam) SetFocus( hwnd );
+	break;
+
     case WM_WINDOWPOSCHANGED:
 	{
 	    WINDOWPOS * winPos = (WINDOWPOS *)lParam;
@@ -170,16 +192,9 @@
 	}
 
     case WM_SETTEXT:
-	{
-	    if (wndPtr->hText)
-		USER_HEAP_FREE(wndPtr->hText);
-
-	    wndPtr->hText = USER_HEAP_ALLOC(GMEM_MOVEABLE, 
-					    strlen((LPSTR)lParam) + 1);
-	    textPtr = (LPSTR)USER_HEAP_ADDR(wndPtr->hText);
-	    strcpy(textPtr, (LPSTR)lParam);
-	    return (0L);
-	}
+	DEFWND_SetText( hwnd, (LPSTR)lParam );
+	NC_HandleNCPaint( hwnd, (HRGN)1 );  /* Repaint caption */
+	return 0;
 
     case WM_SETCURSOR:
 	if (wndPtr->dwStyle & WS_CHILD)
@@ -193,6 +208,7 @@
     case WM_SYSKEYDOWN:
     	if (wParam == VK_MENU) {
     	    printf("VK_MENU Pressed // hMenu=%04X !\n", GetMenu(hwnd));
+	    NC_TrackSysMenu(hwnd);
     	    }
     	break;    	
     case WM_SYSKEYUP:
diff --git a/windows/dialog.c b/windows/dialog.c
index 6316e34..9f0b64a 100644
--- a/windows/dialog.c
+++ b/windows/dialog.c
@@ -9,6 +9,7 @@
 #include "windows.h"
 #include "dialog.h"
 #include "win.h"
+#include "user.h"
 
 
   /* Dialog base units */
@@ -510,14 +511,13 @@
  */
 void SetDlgItemInt( HWND hwnd, WORD id, WORD value, BOOL fSigned )
 {
-    HANDLE hText = LocalAlloc( LMEM_MOVEABLE, 10 );
-    char * str = (char *) LocalLock( hText );
+    HANDLE hText = USER_HEAP_ALLOC(0, 10 );
+    char * str = (char *) USER_HEAP_ADDR( hText );
 
     if (fSigned) sprintf( str, "%d", value );
     else sprintf( str, "%u", value );
     SendDlgItemMessage( hwnd, id, WM_SETTEXT, 0, (DWORD)str );
-    LocalUnlock( hText );
-    LocalFree( hText );
+    USER_HEAP_FREE( hText );
 }
 
 
@@ -534,9 +534,9 @@
     if (translated) *translated = FALSE;
     if (!(len = SendDlgItemMessage( hwnd, id, WM_GETTEXTLENGTH, 0, 0 )))
 	return 0;
-    if (!(hText = LocalAlloc(LMEM_MOVEABLE, len+1 )))
+    if (!(hText = USER_HEAP_ALLOC(0, len+1 )))
 	return 0;
-    str = (char *) LocalLock( hText );
+    str = (char *) USER_HEAP_ADDR( hText );
     if (SendDlgItemMessage( hwnd, id, WM_GETTEXT, len+1, (DWORD)str ))
     {
 	char * endptr;
@@ -555,8 +555,7 @@
 	    }
 	}
     }
-    LocalUnlock( hText );
-    LocalFree( hText );
+    USER_HEAP_FREE( hText );
     return (WORD)result;
 }
 
diff --git a/windows/event.c b/windows/event.c
index ba1c0a3..155c66f 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -18,6 +18,8 @@
 
 extern Display * display;
 
+extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
+
   /* X context to associate a hwnd to an X window */
 static XContext winContext = 0;
 
@@ -453,10 +455,11 @@
  */
 static void EVENT_FocusOut( HWND hwnd, XFocusChangeEvent *event )
 {
-
     WND * wndPtr = WIN_FindWndPtr( hwnd );
-
     if (!wndPtr) return;
+
+    if (hwnd == GetActiveWindow()) WINPOS_ChangeActiveWindow( 0, FALSE );
+
     if (wndPtr->dwStyle & WS_DISABLED) {
 	return;
     }
@@ -503,8 +506,8 @@
 	return 0;
     
     rv = XGrabPointer(display, wnd_p->window, False, 
-		      ButtonPressMask | ButtonReleaseMask | ButtonMotionMask,
-		      GrabModeAsync, GrabModeSync, None, None, CurrentTime);
+		      ButtonPressMask | ButtonReleaseMask | PointerMotionMask,
+		      GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
 
     if (rv == GrabSuccess)
     {
diff --git a/windows/focus.c b/windows/focus.c
index a2d2b8d..0e88138 100644
--- a/windows/focus.c
+++ b/windows/focus.c
@@ -24,6 +24,7 @@
     WND *wndPtr;
 
     hWndPrevFocus = hWndFocus;
+    hWndFocus = hwnd;
 
     if (hwnd == 0)
     {
diff --git a/windows/message.c b/windows/message.c
index b41dbf8..de06f28 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -24,6 +24,7 @@
 
 extern BOOL TIMER_CheckTimer( DWORD *next );      /* timer.c */
 extern void EVENT_ProcessEvent( XEvent *event );  /* event.c */
+extern void WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg ); /*winpos.c*/
   
 extern Display * display;
 
@@ -195,32 +196,65 @@
  *           MSG_TranslateMouseMsg
  *
  * Translate an mouse hardware event into a real mouse message.
+ * Return value indicates whether the translated message must be passed
+ * to the user.
  * Actions performed:
  * - Translate button-down messages in double-clicks.
  * - Send the WM_NCHITTEST message to find where the cursor is.
+ * - Activate the window if needed.
  * - Translate the message into a non-client message, or translate
  *   the coordinates to client coordinates.
  * - Send the WM_SETCURSOR message.
  */
-static void MSG_TranslateMouseMsg( MSG *msg )
+static BOOL MSG_TranslateMouseMsg( MSG *msg )
 {
+    BOOL eatMsg = FALSE;
     static DWORD lastClickTime = 0;
     static WORD  lastClickMsg = 0;
     static POINT lastClickPos = { 0, 0 };
 
+    BOOL mouseClick = ((msg->message == WM_LBUTTONDOWN) ||
+		       (msg->message == WM_RBUTTONDOWN) ||
+		       (msg->message == WM_MBUTTONDOWN));
+
+      /* Send the WM_NCHITTEST message */
+
     LONG hittest_result = SendMessage( msg->hwnd, WM_NCHITTEST, 0,
 				       MAKELONG( msg->pt.x, msg->pt.y ) );
+
+      /* Activate the window if needed */
+
+    if (mouseClick)
+    {
+	HWND parent, hwndTop = msg->hwnd;	
+	while ((parent = GetParent(hwndTop)) != 0) hwndTop = parent;
+	if (hwndTop != GetActiveWindow())
+	{
+	    LONG ret = SendMessage( msg->hwnd, WM_MOUSEACTIVATE, hwndTop,
+				    MAKELONG( hittest_result, msg->message ) );
+	    if ((ret == MA_ACTIVATEANDEAT) || (ret == MA_NOACTIVATEANDEAT))
+		eatMsg = TRUE;
+	    if ((ret == MA_ACTIVATE) || (ret == MA_ACTIVATEANDEAT))
+	    {
+		SetWindowPos( hwndTop, HWND_TOP, 0, 0, 0, 0,
+			      SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
+		WINPOS_ChangeActiveWindow( hwndTop, TRUE );
+	    }
+	}
+    }
+
+      /* Send the WM_SETCURSOR message */
+
     SendMessage( msg->hwnd, WM_SETCURSOR, msg->hwnd,
 		 MAKELONG( hittest_result, msg->message ));
+    if (eatMsg) return FALSE;
 
-    if ((msg->message == WM_LBUTTONDOWN) ||
-        (msg->message == WM_RBUTTONDOWN) ||
-        (msg->message == WM_MBUTTONDOWN))
+      /* Check for double-click */
+
+    if (mouseClick)
     {
 	BOOL dbl_click = FALSE;
 
-	  /* Check for double-click */
-
 	if ((msg->message == lastClickMsg) &&
 	    (msg->time - lastClickTime < doubleClickSpeed) &&
 	    (abs(msg->pt.x - lastClickPos.x) < SYSMETRICS_CXDOUBLECLK/2) &&
@@ -247,6 +281,8 @@
 	lastClickPos  = msg->pt;
     }
 
+      /* Build the translated message */
+
     msg->lParam = MAKELONG( msg->pt.x, msg->pt.y );
     if (hittest_result == HTCLIENT)
     {
@@ -257,6 +293,7 @@
 	msg->wParam = hittest_result;
 	msg->message += WM_NCLBUTTONDOWN - WM_LBUTTONDOWN;
     }
+    return TRUE;
 }
 
 
@@ -351,6 +388,33 @@
 
 		    
 /***********************************************************************
+ *           MSG_GetHardwareMessage
+ *
+ * Like GetMessage(), but only return mouse and keyboard events.
+ * Used internally for window moving and resizing. Mouse messages
+ * are not translated.
+ */
+BOOL MSG_GetHardwareMessage( LPMSG msg )
+{
+    int pos;
+    XEvent event;
+
+    while(1)
+    {    
+	if ((pos = MSG_FindMsg( sysMsgQueue, 0, 0, 0 )) != -1)
+	{
+	    *msg = sysMsgQueue->messages[pos].msg;
+	    MSG_RemoveMsg( sysMsgQueue, pos );
+	    break;
+	}
+	XNextEvent( display, &event );
+	EVENT_ProcessEvent( &event );
+    }
+    return TRUE;
+}
+
+
+/***********************************************************************
  *           SetTaskQueue  (KERNEL.34)
  */
 WORD SetTaskQueue( HANDLE hTask, HANDLE hQueue )
@@ -505,9 +569,14 @@
 	    msgQueue->GetMessagePosVal       = *(DWORD *)&msg->pt;
 	    msgQueue->GetMessageExtraInfoVal = qmsg->extraInfo;
 
-	    if (flags & PM_REMOVE) MSG_RemoveMsg( sysMsgQueue, pos );
 	    if ((msg->message >= WM_MOUSEFIRST) &&
-		(msg->message <= WM_MOUSELAST)) MSG_TranslateMouseMsg( msg );
+		(msg->message <= WM_MOUSELAST))
+		if (!MSG_TranslateMouseMsg( msg )) 
+		{
+		    MSG_RemoveMsg( sysMsgQueue, pos );
+		    continue;
+		}
+	    if (flags & PM_REMOVE) MSG_RemoveMsg( sysMsgQueue, pos );
 	    break;
 	}
 
diff --git a/windows/nonclient.c b/windows/nonclient.c
index d326ab9..8f84802 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -7,7 +7,10 @@
 static char Copyright[] = "Copyright  Alexandre Julliard, 1994";
 
 #include "win.h"
+#include "message.h"
 #include "sysmetrics.h"
+#include "user.h"
+#include "scroll.h"
 
 
 static HBITMAP hbitmapClose = 0;
@@ -18,15 +21,12 @@
 static HBITMAP hbitmapRestore = 0;
 static HBITMAP hbitmapRestoreD = 0;
 
-  /* Hit test code returned when the mouse is captured. */
-  /* Used to direct NC mouse messages to the correct part of the window. */
-static WORD captureHitTest = HTCLIENT; 
+extern void NC_TrackSysMenu( HWND hwnd ); /* menu.c */
+extern void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
+			    POINT *minTrack, POINT *maxTrack );  /* winpos.c */
 
-  /* Point where the current capture started. Used for SC_SIZE and SC_MOVE. */
-static POINT capturePoint;
+extern Display * display;
 
-  /* Current window rectangle when a move or resize is in progress. */
-static RECT sizingRect;
 
   /* Some useful macros */
 #define HAS_DLGFRAME(style,exStyle) \
@@ -136,7 +136,10 @@
 
       /* Remove frame from rectangle */
     if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
+    {
 	InflateRect( rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
+	if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) InflateRect( rect, -1, 0);
+    }
     else
     {
 	if (HAS_THICKFRAME( wndPtr->dwStyle ))
@@ -264,7 +267,7 @@
 #ifdef DEBUG_NONCLIENT
     printf( "NC_HandleNCHitTest: hwnd=%x pt=%d,%d\n", hwnd, pt.x, pt.y );
 #endif
-    if (hwnd == GetCapture()) return captureHitTest;
+    if (hwnd == GetCapture()) return HTCLIENT;
     return NC_InternalNCHitTest( hwnd, pt );
 }
 
@@ -272,18 +275,16 @@
 /***********************************************************************
  *           NC_DrawSysButton
  */
-static void NC_DrawSysButton( HWND hwnd, HDC hdc )
+static void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
 {
     RECT rect;
-    BOOL down;
     HDC hdcMem = CreateCompatibleDC( hdc );
     if (hdcMem)
     {
 	NC_GetInsideRect( hwnd, &rect );
-	down = ((GetCapture() == hwnd) && (captureHitTest == HTSYSMENU));
 	SelectObject( hdcMem, hbitmapClose );
-	BitBlt( hdc, rect.left-1, rect.top-1, SYSMETRICS_CXSIZE+1,
-	       SYSMETRICS_CYSIZE+1, hdcMem, 0, 0, down ? NOTSRCCOPY : SRCCOPY);
+	BitBlt( hdc, rect.left, rect.top, SYSMETRICS_CXSIZE,
+	       SYSMETRICS_CYSIZE, hdcMem, 1, 1, down ? NOTSRCCOPY : SRCCOPY );
 	DeleteDC( hdcMem );
     }
 }
@@ -292,15 +293,13 @@
 /***********************************************************************
  *           NC_DrawMaxButton
  */
-static void NC_DrawMaxButton( HWND hwnd, HDC hdc )
+static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
 {
     RECT rect;
-    BOOL down;
     HDC hdcMem = CreateCompatibleDC( hdc );
     if (hdcMem)
     {
 	NC_GetInsideRect( hwnd, &rect );
-	down = ((GetCapture() == hwnd) && (captureHitTest == HTMAXBUTTON));
 	if (IsZoomed(hwnd))
 	    SelectObject( hdcMem, down ? hbitmapRestoreD : hbitmapRestore );
 	else SelectObject( hdcMem, down ? hbitmapMaximizeD : hbitmapMaximize );
@@ -314,7 +313,7 @@
 /***********************************************************************
  *           NC_DrawMinButton
  */
-static void NC_DrawMinButton( HWND hwnd, HDC hdc )
+static void NC_DrawMinButton( HWND hwnd, HDC hdc, BOOL down )
 {
     RECT rect;
     WND *wndPtr = WIN_FindWndPtr( hwnd );
@@ -324,8 +323,7 @@
 	NC_GetInsideRect( hwnd, &rect );
 	if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
 	    rect.right -= SYSMETRICS_CXSIZE + 1;	
-	if ((GetCapture() == hwnd) && (captureHitTest == HTMINBUTTON))
-	    SelectObject( hdcMem, hbitmapMinimizeD );
+	if (down) SelectObject( hdcMem, hbitmapMinimizeD );
 	else SelectObject( hdcMem, hbitmapMinimize );
 	BitBlt( hdc, rect.right - SYSMETRICS_CXSIZE - 1, rect.top - 1,
 	      SYSMETRICS_CXSIZE+2, SYSMETRICS_CYSIZE+2, hdcMem, 0, 0, SRCCOPY);
@@ -346,8 +344,8 @@
 
     if (dlgFrame)
     {
-	width = SYSMETRICS_CXDLGFRAME;
-	height = SYSMETRICS_CYDLGFRAME;
+	width = SYSMETRICS_CXDLGFRAME - 1;
+	height = SYSMETRICS_CYDLGFRAME - 1;
     }
     else
     {
@@ -412,12 +410,9 @@
  *
  * Draw the frame used when moving or resizing window.
  */
-static void NC_DrawMovingFrame( HWND hwnd, RECT *rect )
+static void NC_DrawMovingFrame( HDC hdc, RECT *rect, BOOL thickframe )
 {
-    WND *wndPtr = WIN_FindWndPtr( hwnd );
-    HDC hdc = GetDC( 0 );
-
-    if (HAS_THICKFRAME( wndPtr->dwStyle ))
+    if (thickframe)
     {
 	SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
 	PatBlt( hdc, rect->left, rect->top,
@@ -433,7 +428,6 @@
 	        rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
     }
     else DrawFocusRect( hdc, rect );
-    ReleaseDC( 0, hdc );
 }
 
 
@@ -443,10 +437,12 @@
  * Draw the window caption.
  * The correct pen for the window frame must be selected in the DC.
  */
-static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd, DWORD style )
+static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
+			    DWORD style, BOOL active )
 {
     RECT r = *rect;
     HBRUSH hbrushCaption;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
     char buffer[256];
 
     if (!hbitmapClose)
@@ -461,52 +457,66 @@
 	hbitmapRestoreD  = LoadBitmap( 0, MAKEINTRESOURCE(OBM_RESTORED) );
     }
     
-    hbrushCaption = CreateSolidBrush( GetSysColor( COLOR_ACTIVECAPTION ) );
+    if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
+    {
+	HBRUSH hbrushWindow = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
+	HBRUSH hbrushOld = SelectObject( hdc, hbrushWindow );
+	PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
+	PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
+	PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
+	r.left++;
+	r.right--;
+	SelectObject( hdc, hbrushOld );
+	DeleteObject( hbrushWindow );
+    }
+
+    if (active)
+	hbrushCaption = CreateSolidBrush( GetSysColor(COLOR_ACTIVECAPTION) );
+    else hbrushCaption = CreateSolidBrush( GetSysColor(COLOR_INACTIVECAPTION));
 
     MoveTo( hdc, r.left, r.bottom );
     LineTo( hdc, r.right-1, r.bottom );
 
     if (style & WS_SYSMENU)
     {
-	NC_DrawSysButton( hwnd, hdc );
+	NC_DrawSysButton( hwnd, hdc, FALSE );
 	r.left += SYSMETRICS_CXSIZE + 1;
 	MoveTo( hdc, r.left - 1, r.top );
 	LineTo( hdc, r.left - 1, r.bottom );
     }
     if (style & WS_MAXIMIZEBOX)
     {
-	NC_DrawMaxButton( hwnd, hdc );
+	NC_DrawMaxButton( hwnd, hdc, FALSE );
 	r.right -= SYSMETRICS_CXSIZE + 1;
     }
     if (style & WS_MINIMIZEBOX)
     {
-	NC_DrawMinButton( hwnd, hdc );
+	NC_DrawMinButton( hwnd, hdc, FALSE );
 	r.right -= SYSMETRICS_CXSIZE + 1;
     }
 
     FillRect( hdc, &r, hbrushCaption );
+    DeleteObject( hbrushCaption );
 
     if (GetWindowText( hwnd, buffer, 256 ))
     {
-	SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
+	if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
+	else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
 	SetBkMode( hdc, TRANSPARENT );
-	DrawText( hdc, buffer, -1, &r,
-		 DT_SINGLELINE | DT_CENTER | DT_VCENTER );
+	DrawText( hdc, buffer, -1, &r, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
     }
-
-    DeleteObject( hbrushCaption );
 }
 
 
 /***********************************************************************
- *           NC_HandleNCPaint
+ *           NC_DoNCPaint
  *
- * Handle a WM_NCPAINT message. Called from DefWindowProc().
+ * Paint the non-client area.
  */
-LONG NC_HandleNCPaint( HWND hwnd, HRGN hrgn )
+static void NC_DoNCPaint( HWND hwnd, HRGN hrgn, BOOL active )
 {
     HDC hdc;
-    RECT rect;
+    RECT rect, rect2;
     HBRUSH hbrushBorder = 0;
     HPEN hpenFrame = 0;
 
@@ -516,13 +526,13 @@
     printf( "NC_HandleNCPaint: %d %d\n", hwnd, hrgn );
 #endif
 
-    if (!wndPtr || !hrgn) return 0;
+    if (!wndPtr || !hrgn) return;
     if (!(wndPtr->dwStyle & (WS_BORDER | WS_DLGFRAME | WS_THICKFRAME)))
-	return 0;  /* Nothing to do! */
+	return;  /* Nothing to do! */
 
     if (hrgn == 1) hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
     else hdc = GetDCEx( hwnd, hrgn, DCX_CACHE | DCX_WINDOW | DCX_INTERSECTRGN);
-    if (!hdc) return 0;
+    if (!hdc) return;
     if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
 		        wndPtr->rectClient.top-wndPtr->rectWindow.top,
 		        wndPtr->rectClient.right-wndPtr->rectWindow.left,
@@ -530,7 +540,7 @@
 	== NULLREGION)
     {
 	ReleaseDC( hwnd, hdc );
-	return 0;
+	return;
     }
 
     rect.top = rect.left = 0;
@@ -539,7 +549,9 @@
 
     hpenFrame = CreatePen( PS_SOLID, 1, GetSysColor(COLOR_WINDOWFRAME) );
     SelectObject( hdc, hpenFrame );
-    hbrushBorder = CreateSolidBrush( GetSysColor(COLOR_ACTIVEBORDER) );
+    if (active)
+	hbrushBorder = CreateSolidBrush( GetSysColor(COLOR_ACTIVEBORDER) );
+    else hbrushBorder = CreateSolidBrush( GetSysColor(COLOR_INACTIVEBORDER) );
     SelectObject( hdc, hbrushBorder );
 
     if ((wndPtr->dwStyle & WS_BORDER) || (wndPtr->dwStyle & WS_DLGFRAME))
@@ -552,34 +564,36 @@
 	InflateRect( &rect, -1, -1 );
     }
 
-    if ((wndPtr->dwStyle & WS_DLGFRAME) &&
-	((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) || 
-	 !(wndPtr->dwStyle & WS_BORDER))) NC_DrawFrame( hdc, &rect, TRUE );
-    else if (wndPtr->dwStyle & WS_THICKFRAME) NC_DrawFrame(hdc, &rect, FALSE);
+    if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle )) 
+	NC_DrawFrame( hdc, &rect, TRUE );
+    else if (wndPtr->dwStyle & WS_THICKFRAME)
+	NC_DrawFrame(hdc, &rect, FALSE);
 
     if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
     {
 	RECT r = rect;
 	rect.top += SYSMETRICS_CYSIZE + 1;
 	r.bottom = rect.top - 1;
-	if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
-	{
-	    HBRUSH hbrushWindow = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
-	    HBRUSH hbrushOld = SelectObject( hdc, hbrushWindow );
-	    PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1, PATCOPY );
-	    PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
-	    PatBlt( hdc, r.left, r.top, r.right-r.left, 1, PATCOPY );
-	    r.left++;
-	    r.right--;
-	    r.top++;
-	    SelectObject( hdc, hbrushOld );
-	    DeleteObject( hbrushWindow );
-	}
-	NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle );
+	NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
     }
 
     if (wndPtr->dwStyle & (WS_VSCROLL | WS_HSCROLL))
     {
+	if (wndPtr->dwStyle & WS_VSCROLL) {
+	    int bottom = rect.bottom;
+	    if (wndPtr->dwStyle & WS_HSCROLL) bottom -= SYSMETRICS_CYHSCROLL;
+	    SetRect(&rect2, rect.right - SYSMETRICS_CXVSCROLL, rect.top,
+		    rect.right, bottom); 
+	    StdDrawScrollBar(hwnd, hdc, SB_VERT, &rect2, (LPHEADSCROLL)wndPtr->VScroll);
+	    }
+	if (wndPtr->dwStyle & WS_HSCROLL) {
+	    int right = rect.right;
+	    if (wndPtr->dwStyle & WS_VSCROLL) right -= SYSMETRICS_CYVSCROLL;
+	    SetRect(&rect2, rect.left, rect.bottom - SYSMETRICS_CYHSCROLL,
+		    right, rect.bottom);
+	    StdDrawScrollBar(hwnd, hdc, SB_HORZ, &rect2, (LPHEADSCROLL)wndPtr->HScroll);
+	    }
+/*
 	HBRUSH hbrushScroll = CreateSolidBrush( GetSysColor(COLOR_SCROLLBAR) );
 	HBRUSH hbrushOld = SelectObject( hdc, hbrushScroll );
 	if (wndPtr->dwStyle & WS_VSCROLL)
@@ -590,16 +604,245 @@
 		    rect.right-rect.left, SYSMETRICS_CYHSCROLL, PATCOPY );
 	SelectObject( hdc, hbrushOld );
 	DeleteObject( hbrushScroll );
+*/
     }    
 
     ReleaseDC( hwnd, hdc );
     if (hbrushBorder) DeleteObject( hbrushBorder );
     if (hpenFrame) DeleteObject( hpenFrame );    
+}
+
+
+/***********************************************************************
+ *           NC_HandleNCPaint
+ *
+ * Handle a WM_NCPAINT message. Called from DefWindowProc().
+ */
+LONG NC_HandleNCPaint( HWND hwnd, HRGN hrgn )
+{
+    NC_DoNCPaint( hwnd, hrgn, (hwnd == GetActiveWindow()) );
     return 0;
 }
 
 
 /***********************************************************************
+ *           NC_HandleNCActivate
+ *
+ * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
+ */
+LONG NC_HandleNCActivate( HWND hwnd, WORD wParam )
+{
+    NC_DoNCPaint( hwnd, (HRGN)1, wParam );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           NC_DoSizeMove
+ *
+ * Perform SC_MOVE and SC_SIZE commands.
+ */
+static void NC_DoSizeMove( HWND hwnd, WORD wParam, POINT pt )
+{
+    MSG msg;
+    WORD hittest;
+    RECT sizingRect;
+    HDC hdc;
+    BOOL thickframe;
+    POINT minTrack, maxTrack, capturePoint = pt;
+    WND * wndPtr = WIN_FindWndPtr( hwnd );
+
+    if (IsZoomed(hwnd) || IsIconic(hwnd) || !IsWindowVisible(hwnd)) return;
+    hittest = wParam & 0x0f;
+    thickframe = HAS_THICKFRAME( wndPtr->dwStyle );
+
+    if ((wParam & 0xfff0) == SC_MOVE)
+    {
+	if (!(wndPtr->dwStyle & WS_CAPTION)) return;
+	if (!hittest)
+	{
+	      /* Move pointer at the center of the caption */
+	    RECT rect;
+	    POINT point;
+	    NC_GetInsideRect( hwnd, &rect );
+	    if (wndPtr->dwStyle & WS_SYSMENU)
+		rect.left += SYSMETRICS_CXSIZE + 1;
+	    if (wndPtr->dwStyle & WS_MINIMIZEBOX)
+		rect.right -= SYSMETRICS_CXSIZE + 1;
+	    if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
+		rect.right -= SYSMETRICS_CXSIZE + 1;
+	    point.x = wndPtr->rectWindow.left + (rect.right - rect.left) / 2;
+	    point.y = wndPtr->rectWindow.top + rect.top + SYSMETRICS_CYSIZE/2;
+	    if (wndPtr->dwStyle & WS_CHILD)
+		ClientToScreen( wndPtr->hwndParent, &point );
+	    SetCursorPos( point.x, point.y );
+	    hittest = HTCAPTION;
+	    capturePoint = point;
+	}
+    }
+    else  /* SC_SIZE */
+    {
+	if (!thickframe) return;
+	if (hittest) hittest += HTLEFT-1;
+    }
+
+    WINPOS_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
+    SendMessage( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
+
+    if (wndPtr->dwStyle & WS_CHILD) hdc = GetDC( wndPtr->hwndParent );
+    else
+    {  /* Grab the server only when moving top-level windows */
+	hdc = GetDC( 0 );
+	XGrabServer( display );
+    }
+    SetCapture( hwnd );    
+    sizingRect = wndPtr->rectWindow;
+    NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
+
+    while(1)
+    {
+	int dx = 0, dy = 0;
+
+	MSG_GetHardwareMessage( &msg );
+
+	  /* Exit on button-up, Return, or Esc */
+	if ((msg.message == WM_LBUTTONUP) ||
+	    ((msg.message == WM_KEYDOWN) && 
+	     ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
+
+	if (wndPtr->dwStyle & WS_CHILD)
+	    ScreenToClient( wndPtr->hwndParent, &msg.pt );
+
+	switch(msg.message)
+	{
+	case WM_MOUSEMOVE:
+	    dx = msg.pt.x - capturePoint.x;
+	    dy = msg.pt.y - capturePoint.y;
+	    break;
+
+	case WM_KEYDOWN:
+	    switch(msg.wParam)
+	    {
+	        case VK_UP:    msg.pt.y -= 8; break;
+		case VK_DOWN:  msg.pt.y += 8; break;
+		case VK_LEFT:  msg.pt.x -= 8; break;
+		case VK_RIGHT: msg.pt.x += 8; break;		
+	    }
+	    SetCursorPos( msg.pt.x, msg.pt.y );
+	    break;
+	}	
+
+	if (dx || dy)
+	{
+	    RECT newRect = sizingRect;
+	    switch(hittest)
+	    {
+	    case HTCAPTION:
+		OffsetRect( &newRect, dx, dy );
+		break;
+	    case HTLEFT:
+		newRect.left += dx;
+		break;
+	    case HTRIGHT:
+		newRect.right += dx;
+		break;
+	    case HTTOP:
+		newRect.top += dy;
+		break;
+	    case HTTOPLEFT:
+		newRect.left += dx;
+		newRect.top  += dy;
+		break;
+	    case HTTOPRIGHT:
+		newRect.right += dx;
+		newRect.top   += dy;
+		break;
+	    case HTBOTTOM:
+		newRect.bottom += dy;
+		break;
+	    case HTBOTTOMLEFT:
+		newRect.left   += dx;
+		newRect.bottom += dy;
+		break;
+	    case HTBOTTOMRIGHT:
+		newRect.right  += dx;
+		newRect.bottom += dy;
+		break; 
+	    }	    
+	    NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
+	    NC_DrawMovingFrame( hdc, &newRect, thickframe );
+	    capturePoint = msg.pt;
+	    sizingRect = newRect;
+	}
+    }
+
+    NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
+    ReleaseCapture();
+    if (wndPtr->dwStyle & WS_CHILD) ReleaseDC( wndPtr->hwndParent, hdc );
+    else
+    {
+	ReleaseDC( 0, hdc );
+	XUngrabServer( display );
+    }
+    SendMessage( hwnd, WM_EXITSIZEMOVE, 0, 0 );
+
+      /* If Esc key, don't move the window */
+    if ((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) return;
+
+    if (hittest != HTCAPTION)
+	SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
+		     sizingRect.right - sizingRect.left,
+		     sizingRect.bottom - sizingRect.top,
+		     SWP_NOACTIVATE | SWP_NOZORDER );
+    else SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top, 0, 0,
+		      SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
+}
+
+
+/***********************************************************************
+ *           NC_TrackMinMaxBox
+ *
+ * Track a mouse button press on the minimize or maximize box.
+ */
+static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
+{
+    MSG msg;
+    HDC hdc = GetWindowDC( hwnd );
+    BOOL pressed = TRUE;
+
+    SetCapture( hwnd );
+    if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, TRUE );
+    else NC_DrawMaxButton( hwnd, hdc, TRUE );
+
+    do
+    {
+	BOOL oldstate = pressed;
+	MSG_GetHardwareMessage( &msg );
+
+	pressed = (NC_InternalNCHitTest( hwnd, msg.pt ) == wParam);
+	if (pressed != oldstate)
+	{
+	    if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, pressed );
+	    else NC_DrawMaxButton( hwnd, hdc, pressed );	    
+	}
+    } while (msg.message != WM_LBUTTONUP);
+
+    if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, FALSE );
+    else NC_DrawMaxButton( hwnd, hdc, FALSE );
+
+    ReleaseCapture();
+    ReleaseDC( hwnd, hdc );
+    if (!pressed) return;
+
+    if (wParam == HTMINBUTTON) 
+	SendMessage( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, *(LONG*)&msg.pt );
+    else
+	SendMessage( hwnd, WM_SYSCOMMAND, 
+		  IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, *(LONG*)&msg.pt );
+}
+
+
+/***********************************************************************
  *           NC_HandleNCLButtonDown
  *
  * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
@@ -611,39 +854,28 @@
     switch(wParam)  /* Hit test */
     {
     case HTCAPTION:
-	if (GetCapture() != hwnd)
-	    SendMessage( hwnd, WM_SYSCOMMAND, SC_MOVE, lParam );
+	SendMessage( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
 	break;
 
     case HTSYSMENU:
-	captureHitTest = wParam;
-	SetCapture( hwnd );
-	NC_DrawSysButton( hwnd, hdc );
+	NC_DrawSysButton( hwnd, hdc, TRUE );
+	NC_TrackSysMenu(hwnd);
 	break;
 
     case HTMENU:
 	break;
 
     case HTHSCROLL:
-	if (GetCapture() != hwnd)
-	    SendMessage( hwnd, WM_SYSCOMMAND, SC_HSCROLL, lParam );
+	SendMessage( hwnd, WM_SYSCOMMAND, SC_HSCROLL, lParam );
 	break;
 
     case HTVSCROLL:
-	if (GetCapture() != hwnd)
-	    SendMessage( hwnd, WM_SYSCOMMAND, SC_VSCROLL, lParam );
+	SendMessage( hwnd, WM_SYSCOMMAND, SC_VSCROLL, lParam );
 	break;
 
     case HTMINBUTTON:
-	captureHitTest = wParam;
-	SetCapture( hwnd );
-	NC_DrawMinButton( hwnd, hdc );
-	break;
-
     case HTMAXBUTTON:
-	captureHitTest = wParam;
-	SetCapture( hwnd );
-	NC_DrawMaxButton( hwnd, hdc );
+	NC_TrackMinMaxBox( hwnd, wParam );
 	break;
 
     case HTLEFT:
@@ -654,9 +886,7 @@
     case HTBOTTOM:
     case HTBOTTOMLEFT:
     case HTBOTTOMRIGHT:
-	if (GetCapture() != hwnd)
-	    SendMessage( hwnd, WM_SYSCOMMAND,
-			 SC_SIZE + wParam - HTLEFT + 1, lParam );
+	SendMessage( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - HTLEFT+1, lParam);
 	break;
 
     case HTBORDER:
@@ -669,79 +899,6 @@
 
 
 /***********************************************************************
- *           NC_HandleNCLButtonUp
- *
- * Handle a WM_NCLBUTTONUP message. Called from DefWindowProc().
- */
-LONG NC_HandleNCLButtonUp( HWND hwnd, WORD wParam, LONG lParam )
-{
-    HDC hdc;
-    WORD hittest;
-
-    if (hwnd != GetCapture()) return 0;
-
-    ReleaseCapture();
-    captureHitTest = HTCLIENT;
-    hdc = GetWindowDC( hwnd );
-    hittest = NC_InternalNCHitTest( hwnd, MAKEPOINT(lParam) );
-
-    switch(wParam)  /* Hit test */
-    {
-    case HTCAPTION:  /* End of window moving */
-	NC_DrawMovingFrame( hwnd, &sizingRect );
-	SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top, 0, 0,
-		      SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
-	break;
-
-    case HTSYSMENU:
-	NC_DrawSysButton( hwnd, hdc );
-	break;
-
-    case HTMENU:
-    case HTHSCROLL:
-    case HTVSCROLL:
-	break;
-
-    case HTMINBUTTON:
-	NC_DrawMinButton( hwnd, hdc );
-	if (hittest == HTMINBUTTON)
-	    SendMessage( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, lParam );
-	break;
-
-    case HTMAXBUTTON:
-	NC_DrawMaxButton( hwnd, hdc );
-	if (hittest == HTMAXBUTTON)
-	{
-	    if (IsZoomed(hwnd))
-		SendMessage( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
-	    else SendMessage( hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, lParam );
-	}
-	break;
-
-    case HTLEFT:
-    case HTRIGHT:
-    case HTTOP:
-    case HTTOPLEFT:
-    case HTTOPRIGHT:
-    case HTBOTTOM:
-    case HTBOTTOMLEFT:
-    case HTBOTTOMRIGHT:  /* End of window resizing */
-	NC_DrawMovingFrame( hwnd, &sizingRect );
-	SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
-		      sizingRect.right - sizingRect.left,
-		      sizingRect.bottom - sizingRect.top,
-		      SWP_NOACTIVATE | SWP_NOZORDER );
-	break;
-
-    case HTBORDER:
-	    break;
-    }
-    ReleaseDC( hwnd, hdc );
-    return 0;
-}
-
-
-/***********************************************************************
  *           NC_HandleNCLButtonDblClk
  *
  * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
@@ -763,73 +920,6 @@
 
 
 /***********************************************************************
- *           NC_HandleNCMouseMove
- *
- * Handle a WM_NCMOUSEMOVE message. Called from DefWindowProc().
- */
-LONG NC_HandleNCMouseMove( HWND hwnd, WORD wParam, POINT pt )
-{
-    RECT newRect;
-
-    if (hwnd != GetCapture()) return 0;
-    newRect = sizingRect;
-
-    switch(wParam)  /* Hit test */
-    {
-    case HTCAPTION:
-	OffsetRect( &newRect, pt.x - capturePoint.x, pt.y - capturePoint.y);
-	break;
-
-    case HTLEFT:
-	newRect.left += pt.x - capturePoint.x;
-	break;
-
-    case HTRIGHT:
-	newRect.right += pt.x - capturePoint.x;
-	break;
-
-    case HTTOP:
-	newRect.top += pt.y - capturePoint.y;
-	break;
-
-    case HTTOPLEFT:
-	newRect.left += pt.x - capturePoint.x;
-	newRect.top  += pt.y - capturePoint.y;
-	break;
-
-    case HTTOPRIGHT:
-	newRect.right += pt.x - capturePoint.x;
-	newRect.top   += pt.y - capturePoint.y;
-	break;
-
-    case HTBOTTOM:
-	newRect.bottom += pt.y - capturePoint.y;
-	break;
-
-    case HTBOTTOMLEFT:
-	newRect.left   += pt.x - capturePoint.x;
-	newRect.bottom += pt.y - capturePoint.y;
-	break;
-
-    case HTBOTTOMRIGHT:
-	newRect.right  += pt.x - capturePoint.x;
-	newRect.bottom += pt.y - capturePoint.y;
-	break;
- 
-    default:
-	return 0;  /* Nothing to do */
-   }
-
-    NC_DrawMovingFrame( hwnd, &sizingRect );
-    NC_DrawMovingFrame( hwnd, &newRect );
-    capturePoint = pt;
-    sizingRect = newRect;
-
-    return 0;
-}
-
-
-/***********************************************************************
  *           NC_HandleSysCommand
  *
  * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
@@ -842,27 +932,13 @@
     printf( "Handling WM_SYSCOMMAND %x %d,%d\n", wParam, pt.x, pt.y );
 #endif
 
+    if (wndPtr->dwStyle & WS_CHILD) ScreenToClient( wndPtr->hwndParent, &pt );
+
     switch (wParam & 0xfff0)
     {
     case SC_SIZE:
-	if (!HAS_THICKFRAME(wndPtr->dwStyle)) break;
-	if (IsZoomed(hwnd) || IsIconic(hwnd)) break;
-	if (wParam & 0x0f) captureHitTest = (wParam & 0x0f) + HTLEFT - 1;
-	else captureHitTest = HTBORDER;
-	capturePoint = pt;
-	SetCapture( hwnd );
-	GetWindowRect( hwnd, &sizingRect );
-	NC_DrawMovingFrame( hwnd, &sizingRect );
-	break;
-
     case SC_MOVE:
-	if (!(wndPtr->dwStyle & WS_CAPTION)) break;
-	if (IsZoomed(hwnd) || IsIconic(hwnd)) break;
-	captureHitTest = HTCAPTION;
-	capturePoint = pt;
-	SetCapture( hwnd );
-	GetWindowRect( hwnd, &sizingRect );
-	NC_DrawMovingFrame( hwnd, &sizingRect );
+	NC_DoSizeMove( hwnd, wParam, pt );
 	break;
 
     case SC_MINIMIZE:
@@ -886,6 +962,7 @@
 
     case SC_VSCROLL:
     case SC_HSCROLL:
+	break;
     case SC_MOUSEMENU:
     case SC_KEYMENU:
     case SC_ARRANGE:
@@ -956,3 +1033,5 @@
     SetCursor( LoadCursor( 0, IDC_ARROW ) );
     return TRUE;
 }
+
+
diff --git a/windows/timer.c b/windows/timer.c
index da64961..2a40bec 100644
--- a/windows/timer.c
+++ b/windows/timer.c
@@ -142,7 +142,10 @@
     pTimer->proc    = proc;
     TIMER_InsertTimer( pTimer );
     MSG_IncTimerCount( GetTaskQueue(0) );
-    return id;
+    if (!id)
+	return TRUE;
+    else
+	return id;
 }
 
 
diff --git a/windows/win.c b/windows/win.c
index 95730dd..5cef378 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -16,11 +16,13 @@
 #include "user.h"
 #include "dce.h"
 #include "sysmetrics.h"
+#include "scroll.h"
 
 extern Display * display;
 extern Colormap COLOR_WinColormap;
 
 extern void EVENT_RegisterWindow( Window w, HWND hwnd );  /* event.c */
+extern HMENU CopySysMenu(); /* menu.c */
 
 HWND firstWindow = 0;
 
@@ -256,10 +258,10 @@
     wndPtr->hText             = 0;
     wndPtr->flags             = 0;
     wndPtr->hCursor           = 0;
-    wndPtr->hWndVScroll       = 0;
-    wndPtr->hWndHScroll       = 0;
+    wndPtr->VScroll           = NULL;
+    wndPtr->HScroll           = NULL;
+    wndPtr->hSysMenu          = 0;
     wndPtr->hWndMenuBar       = 0;
-    wndPtr->hWndCaption       = 0;
 
     if (classPtr->wc.cbWndExtra)
 	memset( wndPtr->wExtra, 0, classPtr->wc.cbWndExtra );
@@ -311,8 +313,8 @@
 
       /* Send the WM_CREATE message */
 	
-    hcreateStruct = GlobalAlloc( GMEM_MOVEABLE, sizeof(CREATESTRUCT) );
-    createStruct = (CREATESTRUCT *) GlobalLock( hcreateStruct );
+    hcreateStruct = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(CREATESTRUCT) );
+    createStruct = (CREATESTRUCT *) USER_HEAP_ADDR( hcreateStruct );
     createStruct->lpCreateParams = data;
     createStruct->hInstance      = instance;
     createStruct->hMenu          = menu;
@@ -333,22 +335,20 @@
 	  /* Send WM_NCCALCSIZE message */
 	NCCALCSIZE_PARAMS *params;
 	HANDLE hparams;
-	hparams = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) );
+	hparams = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(*params) );
 	if (hparams)
 	{
-	    params = (NCCALCSIZE_PARAMS *) GlobalLock( hparams );
+	    params = (NCCALCSIZE_PARAMS *) USER_HEAP_ADDR( hparams );
 	    params->rgrc[0] = wndPtr->rectWindow;
 	    params->lppos = NULL;
 	    SendMessage( hwnd, WM_NCCALCSIZE, FALSE, (LONG)params );
 	    wndPtr->rectClient = params->rgrc[0];
-	    GlobalUnlock( hparams );
-	    GlobalFree( hparams );
+	    USER_HEAP_FREE( hparams );
 	}	
 	wmcreate = SendMessage( hwnd, WM_CREATE, 0, (LONG)createStruct );
     }
 
-    GlobalUnlock( hcreateStruct );
-    GlobalFree( hcreateStruct );
+    USER_HEAP_FREE( hcreateStruct );
 
     if (wmcreate == -1)
     {
@@ -364,14 +364,9 @@
 
       /* Create scrollbars */
 
-#if 0
-    if (windowName != NULL) SetWindowText(hwnd, windowName);
-    if ((style & WS_CAPTION) == WS_CAPTION) {
-	wndPtr->hWndCaption = CreateWindow("CAPTION", "",
-		WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE,
-		0, -20, width, 20, hwnd, 1, instance, 0L);
+    if ((style & WS_SYSMENU) == WS_SYSMENU) {
+	wndPtr->hSysMenu = CopySysMenu();
 	}
-#endif
     if (((style & WS_CHILD) != WS_CHILD) && (wndPtr->wIDmenu != 0)) {
 	lpbar = (LPPOPUPMENU) GlobalLock(wndPtr->wIDmenu);
 	if (lpbar != NULL) {
@@ -381,25 +376,11 @@
 		0, 0, width, 20, hwnd, 2, instance, (LPSTR)lpbar);
 	    }
 	}
-    if ((style & WS_VSCROLL) == WS_VSCROLL)
-    {
-	wndPtr->hWndVScroll = CreateWindow("SCROLLBAR", "",
-		WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBS_VERT,
-		wndPtr->rectClient.right-wndPtr->rectClient.left, 0,
-                SYSMETRICS_CXVSCROLL,
-		wndPtr->rectClient.bottom-wndPtr->rectClient.top,
-                hwnd, 3, instance, 0L);
-    }
-    if ((style & WS_HSCROLL) == WS_HSCROLL)
-    {
-	wndPtr->hWndHScroll = CreateWindow("SCROLLBAR", "",
-		WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | SBS_HORZ,
-		0, wndPtr->rectClient.bottom-wndPtr->rectClient.top,
-                wndPtr->rectClient.right-wndPtr->rectClient.left,
-		SYSMETRICS_CYHSCROLL,
-                hwnd, 4, instance, 0L);
-    }
-
+      /* Create scrollbars */
+    if ((style & WS_VSCROLL) == WS_VSCROLL ||
+	(style & WS_HSCROLL) == WS_HSCROLL) {
+    	NC_CreateScrollBars(hwnd);
+	}
     EVENT_RegisterWindow( wndPtr->window, hwnd );
 
     WIN_SendParentNotify( hwnd, wndPtr, WM_CREATE );
@@ -429,8 +410,8 @@
     
       /* Destroy all children */
 
-    if (wndPtr->hWndVScroll) DestroyWindow(wndPtr->hWndVScroll);
-    if (wndPtr->hWndHScroll) DestroyWindow(wndPtr->hWndHScroll);
+    if (wndPtr->VScroll) free(wndPtr->VScroll);
+    if (wndPtr->HScroll) free(wndPtr->HScroll);
     while (wndPtr->hwndChild)  /* The child removes itself from the list */
 	DestroyWindow( wndPtr->hwndChild );
 
@@ -445,6 +426,9 @@
     if (wndPtr->flags & WIN_OWN_DC) DCE_FreeDCE( wndPtr->hdce );
     classPtr->cWindows--;
     USER_HEAP_FREE( hwnd );
+/*
+    printf("End of DestroyWindow // hwnd=%04X !\n", hwnd);
+*/
     return TRUE;
 }
 
@@ -493,25 +477,6 @@
     }
 }
 
-/**********************************************************************
- *	     GetMenu	    (USER.157)
- */
-HMENU GetMenu( HWND hwnd ) 
-{ 
-    WND * wndPtr = WIN_FindWndPtr(hwnd);
-    if (wndPtr == NULL)
-	return 0;
-    return wndPtr->wIDmenu;
-}
-
-/**********************************************************************
- *           SetMenu        (USER.158)
- */
-BOOL SetMenu(HWND hwnd, HMENU hmenu)
-{
-    return FALSE;
-}
-
 
 /**********************************************************************
  *           GetDesktopWindow        (USER.286)
@@ -842,3 +807,127 @@
     if ((flag != GW_HWNDNEXT) && (flag != GW_HWNDPREV)) return 0;
     return GetWindow( hwnd, flag );
 }
+
+
+
+
+/*******************************************************************
+ *    EnumWindows             (USER.54)
+ * 
+ *  o gets the desktop window and iterates over all the windows
+ *    which are direct decendents of the desktop * by iterating over
+ *    the desktop's child window and all the child windows next
+ *    pointers
+ *
+ *  o call wndenumprc for every child window the desktop has
+ *    (parameters to Callback16 passed backwards so they are
+ *    put in in pascal calling order)
+ *
+ *  o if wndenumprc returns 0 exit
+ * 
+ *  * remove the HAS_DESKTOP_WINDOW ifdef when the GetDesktopWindow() call
+ *    is fixed to actually return the desktop window
+ * 
+ */
+BOOL EnumWindows(FARPROC wndenumprc, LPARAM lParam)
+{
+    HWND hwnd = GetDesktopWindow(); 
+    WND *wndPtr;
+    int result;
+
+#ifdef DEBUG_ENUM
+    printf("EnumWindows\n");
+#endif 
+#ifdef HAS_DESKTOP_WINDOW 
+    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+    hwnd = wndPtr->hwndChild;
+#else
+    hwnd = firstWindow;
+#endif
+
+    while (hwnd) {
+      char *ptr;
+
+        if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
+              return 0;
+      }
+#ifdef DEBUG_ENUM
+      if (XFetchName(display, wndPtr->window, &ptr) && ptr)
+              printf("found a window (%s)\n", ptr);
+      else 
+              printf("found nameless parent window\n");
+#endif 
+      result = CallBack16(wndenumprc, 2, lParam, (int) hwnd);
+      if ( ! result )  {
+              return 0;
+      }
+      hwnd=wndPtr->hwndNext;
+    }
+    return 1; /* for now */
+}
+
+/*******************************************************************
+ *    WIN_EnumChildWin
+ *
+ *   o hwnd is the first child to use, loop until all next windows
+ *     are processed
+ * 
+ *   o call wdnenumprc with parameters in inverse order (pascal)
+ *
+ *   o call ourselves with the next child window
+ * 
+ */
+static BOOL WIN_EnumChildWin(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
+{
+    WND *wndPtr;
+    int result;
+
+
+    while (hwnd) {
+      char *ptr;
+      if ( !(wndPtr=WIN_FindWndPtr(hwnd)) ) {
+            return 0;
+        }
+#ifdef DEBUG_ENUM
+      if (XFetchName(display, wndPtr->window, &ptr) && ptr)
+              printf("EnumChild: found a child window (%s)\n", ptr);
+      else 
+              printf("EnumChild: nameless child\n");
+      
+        if (!(wndPtr->dwStyle & WS_CHILD)) {
+           printf("this is not a child window!  What is it doing here?\n");
+           return 0;
+      }
+#endif
+        if (!CallBack16(wndenumprc, 2, lParam, (int) hwnd)) {
+                return 0;
+      }
+      if (!WIN_EnumChildWin(wndPtr->hwndChild, wndenumprc, lParam)) {
+          return 0;
+      }
+        hwnd=wndPtr->hwndNext;
+    } 
+    return 1;
+}
+
+/*******************************************************************
+ *    EnumChildWindows        (USER.55)
+ *
+ *   o gets the first child of hwnd
+ *
+ *   o calls WIN_EnumChildWin to do a recursive decent of child windows
+ */
+BOOL EnumChildWindows(HWND hwnd, FARPROC wndenumprc, LPARAM lParam)
+{
+    WND *wndPtr;
+
+#ifdef DEBUG_ENUM
+    printf("EnumChildWindows\n");
+#endif
+
+    if (hwnd == 0) return 0;
+    if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0;
+    hwnd = wndPtr->hwndChild;
+    return WIN_EnumChildWin(hwnd, wndenumprc, lParam);         
+}
+
diff --git a/windows/winpos.c b/windows/winpos.c
index ad23161..49d091f 100644
--- a/windows/winpos.c
+++ b/windows/winpos.c
@@ -6,10 +6,14 @@
 
 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
 
+#include "sysmetrics.h"
+#include "user.h"
 #include "win.h"
 
 extern Display * display;
 
+static HWND hwndActive = 0;  /* Currently active window */
+
 
 /***********************************************************************
  *           GetWindowRect   (USER.32)
@@ -156,6 +160,28 @@
 }
 
 
+/*******************************************************************
+ *         GetActiveWindow    (USER.60)
+ */
+HWND GetActiveWindow()
+{
+    return hwndActive;
+}
+
+
+/*******************************************************************
+ *         SetActiveWindow    (USER.59)
+ */
+HWND SetActiveWindow( HWND hwnd )
+{
+    HWND prev = hwndActive;
+    WND *wndPtr = WIN_FindWndPtr( hwnd );
+    if (!wndPtr || (wndPtr->dwStyle & WS_CHILD)) return 0;
+    SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
+    return prev;
+}
+
+
 /***********************************************************************
  *           BringWindowToTop   (USER.45)
  */
@@ -204,6 +230,7 @@
 
 	case SW_SHOWMINNOACTIVE:
 	case SW_SHOWMINIMIZED:
+	case SW_SHOWMAXIMIZED:
 	case SW_MINIMIZE:
 	    wndPtr->dwStyle |= WS_MINIMIZE;
 	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
@@ -211,15 +238,23 @@
 	    break;
 
 	case SW_SHOWNA:
-	case SW_SHOWNOACTIVATE:
 	case SW_MAXIMIZE:
-	case SW_SHOWMAXIMIZED:
 	case SW_SHOW:
+	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+	    break;
+
 	case SW_NORMAL:
 	case SW_SHOWNORMAL:
+	case SW_SHOWNOACTIVATE:
+	case SW_RESTORE:
 	    wndPtr->dwStyle &= ~WS_MINIMIZE;
-	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE | 
-		        SWP_NOACTIVATE | SWP_NOZORDER;
+	    wndPtr->dwStyle &= ~WS_MAXIMIZE;
+	    swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+	    if (cmd == SW_SHOWNOACTIVATE)
+	    {
+		swpflags |= SWP_NOZORDER;
+		if (GetActiveWindow()) swpflags |= SWP_NOACTIVATE;
+	    }
 	    break;
     }
     SendMessage( hwnd, WM_SHOWWINDOW, (cmd != SW_HIDE), 0 );
@@ -311,10 +346,76 @@
 }
 
 
+/*******************************************************************
+ *         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;
+
+    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.
+ */
+HWND WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg )
+{
+    HWND prevActive = hwndActive;
+    if (hwnd == hwndActive) return 0;
+    if (hwndActive)
+    {
+	if (!SendMessage( hwndActive, WM_NCACTIVATE, FALSE, 0 )) return 0;
+	SendMessage( hwndActive, WM_ACTIVATE, WA_INACTIVE,
+		     MAKELONG( IsIconic(hwndActive), hwnd ) );
+	/* Send WM_ACTIVATEAPP here */
+    }
+
+    hwndActive = hwnd;
+    if (hwndActive)
+    {
+	/* Send WM_ACTIVATEAPP here */
+	SendMessage( hwnd, WM_NCACTIVATE, TRUE, 0 );
+	SendMessage( hwnd, WM_ACTIVATE, mouseMsg ? WA_CLICKACTIVE : WA_ACTIVE,
+		     MAKELONG( IsIconic(hwnd), prevActive ) );
+    }
+    return prevActive;
+}
+
+
 /***********************************************************************
  *           SetWindowPos   (USER.232)
  */
-/* Unimplemented flags: SWP_NOREDRAW, SWP_NOACTIVATE
+/* Unimplemented flags: SWP_NOREDRAW
  */
 /* Note: all this code should be in the DeferWindowPos() routines,
  * and SetWindowPos() should simply call them.  This will be implemented
@@ -342,8 +443,9 @@
 
       /* Send WM_WINDOWPOSCHANGING message */
 
-    if (!(hmem = GlobalAlloc( GMEM_MOVEABLE,sizeof(WINDOWPOS) ))) return FALSE;
-    winPos = (WINDOWPOS *)GlobalLock( hmem );
+    if (!(hmem = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(WINDOWPOS) )))
+	return FALSE;
+    winPos = (WINDOWPOS *)USER_HEAP_ADDR( hmem );
     winPos->hwnd = hwnd;
     winPos->hwndInsertAfter = hwndInsertAfter;
     winPos->x = x;
@@ -398,16 +500,15 @@
 	NCCALCSIZE_PARAMS *params;
 	HANDLE hparams;
 	
-	if (!(hparams = GlobalAlloc( GMEM_MOVEABLE, sizeof(*params) )))
+	if (!(hparams = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(*params) )))
 	    goto Abort;
-	params = (NCCALCSIZE_PARAMS *) GlobalLock( hparams );
+	params = (NCCALCSIZE_PARAMS *) USER_HEAP_ADDR( hparams );
 	params->rgrc[0] = newWindowRect;
 	params->rgrc[1] = wndPtr->rectWindow;
 	params->rgrc[2] = wndPtr->rectClient;
 	params->lppos = winPos;
 	calcsize_result = SendMessage(hwnd, WM_NCCALCSIZE, TRUE, (LONG)params);
-	GlobalUnlock( hparams );
-	GlobalFree( hparams );
+	USER_HEAP_FREE( hparams );
 	newClientRect = params->rgrc[0];
 	/* Handle result here */
     }
@@ -470,6 +571,12 @@
 	XUnmapWindow( display, wndPtr->window );
     }
 
+    if (!(winPos->flags & SWP_NOACTIVATE))
+    {
+	if (!(wndPtr->dwStyle & WS_CHILD))
+	    WINPOS_ChangeActiveWindow( hwnd, FALSE );
+    }
+    
       /* Send WM_NCPAINT message if needed */
     if ((winPos->flags & (SWP_FRAMECHANGED | SWP_SHOWWINDOW)) ||
 	(!(winPos->flags & SWP_NOSIZE)) ||
@@ -482,18 +589,11 @@
     wndPtr->rectWindow = newWindowRect;
     wndPtr->rectClient = newClientRect;
     SendMessage( hwnd, WM_WINDOWPOSCHANGED, 0, (LONG)winPos );
-    GlobalUnlock( hmem );
-    GlobalFree( hmem );
+    USER_HEAP_FREE( hmem );
 
     return TRUE;
 
  Abort:  /* Fatal error encountered */
-    if (hmem)
-    {
-	GlobalUnlock( hmem );
-	GlobalFree( hmem );
-    }
+    if (hmem) USER_HEAP_FREE( hmem );
     return FALSE;
 }
-
-