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/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;
 }
+
+