update for HEAD-2003091401
[reactos.git] / lib / user32 / windows / defwnd.c
index 631d63e..ac1b551 100644 (file)
 #include <windows.h>
 #include <user32.h>
 #include <window.h>
-#include <debug.h>
 #include <user32/wininternal.h>
 #include <string.h>
+#include <menu.h>
+#include <cursor.h>
+#include <winpos.h>
 
-/* GLOBALS *******************************************************************/
+#define NDEBUG
+#include <debug.h>
 
-static HBITMAP hbitmapClose;
-static HBITMAP hbitmapMinimize;
-static HBITMAP hbitmapMinimizeD;
-static HBITMAP hbitmapMaximize;
-static HBITMAP hbitmapMaximizeD;
-static HBITMAP hbitmapRestore;
-static HBITMAP hbitmapRestoreD;
+/* GLOBALS *******************************************************************/
 
-static COLORREF SysColours[] =
+static HBITMAP hbSysMenu;
+/* TODO:  widgets will be cached here.
+static HBITMAP hbClose;
+static HBITMAP hbCloseD;
+static HBITMAP hbMinimize;
+static HBITMAP hbMinimizeD;
+static HBITMAP hbRestore;
+static HBITMAP hbRestoreD;
+static HBITMAP hbMaximize;
+static HBITMAP hbScrUp;
+static HBITMAP hbScrDwn;
+static HBITMAP hbScrLeft;
+static HBITMAP hbScrRight;
+*/
+
+
+static COLORREF SysColours[29] =
   {
     RGB(224, 224, 224) /* COLOR_SCROLLBAR */,
-    RGB(192, 192, 192) /* COLOR_BACKGROUND */,
-    RGB(0, 64, 128) /* COLOR_ACTIVECAPTION */,
-    RGB(255, 255, 255) /* COLOR_INACTIVECAPTION */,
-    RGB(255, 255, 255) /* COLOR_MENU */,
+    RGB(58, 110, 165) /* COLOR_BACKGROUND */,
+    RGB(0, 0, 128) /* COLOR_ACTIVECAPTION */,
+    RGB(128, 128, 128) /* COLOR_INACTIVECAPTION */,
+    RGB(192, 192, 192) /* COLOR_MENU */,
     RGB(255, 255, 255) /* COLOR_WINDOW */,
     RGB(0, 0, 0) /* COLOR_WINDOWFRAME */,
     RGB(0, 0, 0) /* COLOR_MENUTEXT */,
@@ -44,12 +57,12 @@ static COLORREF SysColours[] =
     RGB(255, 255, 255) /* COLOR_INACTIVEBORDER */,
     RGB(255, 255, 232) /* COLOR_APPWORKSPACE */,
     RGB(224, 224, 224) /* COLOR_HILIGHT */,
-    RGB(0, 0, 0) /* COLOR_HILIGHTTEXT */,
+    RGB(0, 0, 128) /* COLOR_HILIGHTTEXT */,
     RGB(192, 192, 192) /* COLOR_BTNFACE */,
     RGB(128, 128, 128) /* COLOR_BTNSHADOW */,
     RGB(192, 192, 192) /* COLOR_GRAYTEXT */,
     RGB(0, 0, 0) /* COLOR_BTNTEXT */,
-    RGB(0, 0, 0) /* COLOR_INACTIVECAPTIONTEXT */,
+    RGB(192, 192, 192) /* COLOR_INACTIVECAPTIONTEXT */,
     RGB(255, 255, 255) /* COLOR_BTNHILIGHT */,
     RGB(32, 32, 32) /* COLOR_3DDKSHADOW */,
     RGB(192, 192, 192) /* COLOR_3DLIGHT */,
@@ -63,39 +76,105 @@ static COLORREF SysColours[] =
 
 static ATOM AtomInternalPos;
 
+/* Bits in the dwKeyData */
+#define KEYDATA_ALT   0x2000
+
 /* FUNCTIONS *****************************************************************/
 
+BOOL
+IsMaxBoxActive(HWND hWnd)
+{
+    ULONG uStyle = GetWindowLongW(hWnd, GWL_STYLE);
+    return (uStyle & WS_MAXIMIZEBOX);
+}
+
+BOOL
+IsCloseBoxActive(HWND hWnd)
+{
+    ULONG uStyle = GetWindowLongW(hWnd, GWL_STYLE);
+    return (uStyle & WS_SYSMENU);
+}
+
+BOOL
+IsMinBoxActive(HWND hWnd)
+{
+    ULONG uStyle = GetWindowLongW(hWnd, GWL_STYLE);
+    return (uStyle & WS_MINIMIZEBOX);
+}
+
+INT
+UIGetFrameSizeX(HWND hWnd)
+{
+    ULONG uStyle = GetWindowLongW(hWnd, GWL_STYLE);
+
+    if ( uStyle & WS_THICKFRAME )
+        return GetSystemMetrics(SM_CXSIZEFRAME);
+    else
+        return GetSystemMetrics(SM_CXFRAME);
+}
+
+INT
+UIGetFrameSizeY(HWND hWnd)
+{
+    ULONG uStyle = GetWindowLongW(hWnd, GWL_STYLE);
+
+    if (uStyle & WS_THICKFRAME)
+        return GetSystemMetrics(SM_CYSIZEFRAME);
+    else
+        return GetSystemMetrics(SM_CYFRAME);
+}
+
 VOID
 UserSetupInternalPos(VOID)
 {
-  LPSTR Str = "SysIP";
-  AtomInternalPos = GlobalAddAtomA(Str);
+    LPSTR Str = "SysIP";
+    AtomInternalPos = GlobalAddAtomA(Str);
+}
+
+/*
+ * @implemented
+ */
+DWORD STDCALL
+GetSysColor(int nIndex)
+{
+    return SysColours[nIndex];
 }
 
-/* ReactOS extension */
+/*
+ * @implemented
+ */
 HPEN STDCALL
 GetSysColorPen(int nIndex)
 {
-  return(CreatePen(PS_SOLID, 1, SysColours[nIndex]));
+    return CreatePen(PS_SOLID, 1, SysColours[nIndex]);
 }
 
+/*
+ * @implemented
+ */
 HBRUSH STDCALL
 GetSysColorBrush(int nIndex)
 {
-  return(CreateSolidBrush(SysColours[nIndex]));
+    return CreateSolidBrush(SysColours[nIndex]);
 }
 
-
+/*
+ * @unimplemented
+ */
 LRESULT STDCALL
-DefFrameProcA(HWND hWnd,
+DefFrameProcA( HWND hWnd,
              HWND hWndMDIClient,
              UINT uMsg,
              WPARAM wParam,
-             LPARAM lParam)
+             LPARAM lParam )
 {
-  return((LRESULT)0);
+    UNIMPLEMENTED;
+    return ((LRESULT)0);
 }
 
+/*
+ * @unimplemented
+ */
 LRESULT STDCALL
 DefFrameProcW(HWND hWnd,
              HWND hWndMDIClient,
@@ -103,330 +182,464 @@ DefFrameProcW(HWND hWnd,
              WPARAM wParam,
              LPARAM lParam)
 {
-  return((LRESULT)0);
+    UNIMPLEMENTED;
+    return ((LRESULT)0);
 }
 
+PINTERNALPOS
+UserGetInternalPos(HWND hWnd)
+{
+    PINTERNALPOS lpPos;
+    lpPos = (PINTERNALPOS)GetPropA(hWnd, (LPSTR)(DWORD)AtomInternalPos);
+    return(lpPos);
+}
 
-BOOL 
+BOOL
 DefWndRedrawIconTitle(HWND hWnd)
 {
-  PINTERNALPOS lpPos = (PINTERNALPOS)GetPropA(hWnd, 
-                                             (LPSTR)(DWORD)AtomInternalPos);
-  if (lpPos != NULL)
+    PINTERNALPOS lpPos = (PINTERNALPOS)GetPropA(hWnd, (LPSTR)(DWORD)AtomInternalPos);
+
+    if (lpPos != NULL)
     {
-      if (lpPos->IconTitle != NULL)
-       {
-         SendMessageA(lpPos->IconTitle, WM_SHOWWINDOW, TRUE, 0);
-         InvalidateRect(lpPos->IconTitle, NULL, TRUE);
-         return(TRUE);
-       }
+        if (lpPos->IconTitle != NULL)
+        {
+            SendMessageA(lpPos->IconTitle, WM_SHOWWINDOW, TRUE, 0);
+            InvalidateRect(lpPos->IconTitle, NULL, TRUE);
+            return(TRUE);
+        }
     }
-  return(FALSE);
+    return(FALSE);
 }
 
 BOOL
 UserHasMenu(HWND hWnd, ULONG Style)
 {
-  return(!(Style & WS_CHILD) && GetWindowLong(hWnd, GWL_ID) != 0);
+    return (!(Style & WS_CHILD) && GetMenu(hWnd) != 0);
 }
 
 ULONG
 UserHasAnyFrameStyle(ULONG Style, ULONG ExStyle)
 {
-  return((Style & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) ||
-        (ExStyle & WS_EX_DLGMODALFRAME) ||
-        (!(Style & (WS_CHILD | WS_POPUP))));
+    return ((Style & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) ||
+            (ExStyle & WS_EX_DLGMODALFRAME) ||
+            (!(Style & (WS_CHILD | WS_POPUP))));
 }
 
 ULONG
 UserHasDlgFrameStyle(ULONG Style, ULONG ExStyle)
 {
-  return((ExStyle & WS_EX_DLGMODALFRAME) ||
-        ((Style & WS_DLGFRAME) && (!(Style & WS_THICKFRAME))));
+    return ((ExStyle & WS_EX_DLGMODALFRAME) ||
+            ((Style & WS_DLGFRAME) && (!(Style & WS_THICKFRAME))));
 }
 
 ULONG
 UserHasThickFrameStyle(ULONG Style, ULONG ExStyle)
 {
-  return((Style & WS_THICKFRAME) &&
-        (!((Style & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)));
+    return ((Style & WS_THICKFRAME) &&
+            (!((Style & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)));
 }
 
-ULONG 
+ULONG
 UserHasThinFrameStyle(ULONG Style, ULONG ExStyle)
 {
-  return((Style & WS_BORDER) ||
-        (!(Style & (WS_CHILD | WS_POPUP))));
+    return ((Style & WS_BORDER) || (!(Style & (WS_CHILD | WS_POPUP))));
 }
 
 ULONG
 UserHasBigFrameStyle(ULONG Style, ULONG ExStyle)
 {
-  return((Style & (WS_THICKFRAME | WS_DLGFRAME)) ||
-        (ExStyle & WS_EX_DLGMODALFRAME));
+    return ((Style & (WS_THICKFRAME | WS_DLGFRAME)) ||
+            (ExStyle & WS_EX_DLGMODALFRAME));
 }
 
-static void UserGetInsideRectNC( HWND hwnd, RECT *rect )
+void
+UserGetInsideRectNC(HWND hWnd, RECT *rect)
 {
-  RECT WindowRect;
-  ULONG Style;
-  ULONG ExStyle;
+    RECT WindowRect;
+    ULONG Style;
+    ULONG ExStyle;
 
-  Style = GetWindowLong(hwnd, GWL_STYLE);
-  ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
-  GetWindowRect(hwnd, &WindowRect);
-  rect->top    = rect->left = 0;
-  rect->right  = WindowRect.right - WindowRect.left;
-  rect->bottom = WindowRect.bottom - WindowRect.top;
-  
-  if (Style & WS_ICONIC) 
+    Style = GetWindowLongW(hWnd, GWL_STYLE);
+    ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
+    GetWindowRect(hWnd, &WindowRect);
+    rect->top    = rect->left = 0;
+    rect->right  = WindowRect.right - WindowRect.left;
+    rect->bottom = WindowRect.bottom - WindowRect.top;
+
+    if (Style & WS_ICONIC)
     {
-      return;
+        return;
     }
 
-  /* Remove frame from rectangle */
-  if (UserHasThickFrameStyle(Style, ExStyle ))
-      {
-       InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), 
-                    -GetSystemMetrics(SM_CYFRAME) );
-      }
+    /* Remove frame from rectangle */
+    if (UserHasThickFrameStyle(Style, ExStyle ))
+    {
+        InflateRect(rect, -GetSystemMetrics(SM_CXFRAME),
+                    -GetSystemMetrics(SM_CYFRAME));
+    }
     else
-      {
-       if (UserHasDlgFrameStyle(Style, ExStyle ))
-         {
-           InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), 
-                        -GetSystemMetrics(SM_CYDLGFRAME));
-           /* FIXME: this isn't in NC_AdjustRect? why not? */
-           if (ExStyle & WS_EX_DLGMODALFRAME)
-             InflateRect( rect, -1, 0 );
-         }
-       else
-         {
-           if (UserHasThinFrameStyle(Style, ExStyle))
-             {
-               InflateRect(rect, -GetSystemMetrics(SM_CXBORDER), 
-                           -GetSystemMetrics(SM_CYBORDER));
-             }
-         }
-      }
+    {
+        if (UserHasDlgFrameStyle(Style, ExStyle ))
+        {
+            InflateRect(rect, -GetSystemMetrics(SM_CXDLGFRAME),
+                        -GetSystemMetrics(SM_CYDLGFRAME));
+            /* FIXME: this isn't in NC_AdjustRect? why not? */
+            if (ExStyle & WS_EX_DLGMODALFRAME)
+                   InflateRect( rect, -1, 0 );
+        }
+        else
+        {
+            if (UserHasThinFrameStyle(Style, ExStyle))
+            {
+                InflateRect(rect, -GetSystemMetrics(SM_CXBORDER),
+                            -GetSystemMetrics(SM_CYBORDER));
+            }
+        }
+    }
 }
 
-void UserDrawSysButton( HWND hwnd, HDC hdc, BOOL down )
+WINBOOL
+UserDrawSysMenuButton(HWND hWnd, HDC hDC, LPRECT Rect, BOOL down)
 {
-    RECT rect;
-    HDC hdcMem;
-    HBITMAP hbitmap;
-    ULONG Style;
+    HDC hDcMem;
+    HBITMAP hSavedBitmap;
 
-    Style = GetWindowLong(hwnd, GWL_STYLE);
-    UserGetInsideRectNC( hwnd, &rect );
-    hdcMem = CreateCompatibleDC( hdc );
-    hbitmap = SelectObject( hdcMem, hbitmapClose );
-    BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), 
-          GetSystemMetrics(SM_CYSIZE), hdcMem, 
-          (Style & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
-          down ? NOTSRCCOPY : SRCCOPY );
-    SelectObject( hdcMem, hbitmap );
-    DeleteDC( hdcMem );
-}
+    if (!hbSysMenu)
+    {
+        hbSysMenu = (HBITMAP)LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
+    }
+    hDcMem = CreateCompatibleDC(hDC);
+    if (!hDcMem)
+    {
+        return FALSE;
+    }
+    hSavedBitmap = SelectObject(hDcMem, hbSysMenu);
+    if (!hSavedBitmap)
+    {
+        DeleteDC(hDcMem);
+        return FALSE;
+    }
 
-static void UserDrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
-{
-    RECT rect;
-    HDC hdcMem;
-
-    UserGetInsideRectNC( hwnd, &rect );
-    hdcMem = CreateCompatibleDC( hdc );
-    SelectObject( hdcMem,  (IsZoomed(hwnd) 
-                           ? (down ? hbitmapRestoreD : hbitmapRestore)
-                           : (down ? hbitmapMaximizeD : hbitmapMaximize)) );
-    BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSMSIZE) - 1, rect.top,
-           GetSystemMetrics(SM_CXSMSIZE) + 1, GetSystemMetrics(SM_CYSMSIZE), hdcMem, 0, 0,
-           SRCCOPY );
-    DeleteDC( hdcMem );
-}
+    BitBlt(hDC, Rect->left + 2, Rect->top + 3, 16, 14, hDcMem,
+           (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD) ?
+               GetSystemMetrics(SM_CXSIZE): 0, 0, SRCCOPY);
 
-static void UserDrawMinButton( HWND hwnd, HDC hdc, BOOL down)
-{
-  RECT rect;
-  HDC hdcMem;
-    
-  UserGetInsideRectNC(hwnd, &rect);
-  hdcMem = CreateCompatibleDC(hdc);
-  SelectObject(hdcMem, (down ? hbitmapMinimizeD : hbitmapMinimize));
-  if (GetWindowLong(hwnd, GWL_STYLE) & WS_MAXIMIZEBOX) 
-    {
-      rect.right -= GetSystemMetrics(SM_CXSMSIZE)+1;
-    }
-  BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSMSIZE) - 1, rect.top,
-         GetSystemMetrics(SM_CXSMSIZE) + 1, GetSystemMetrics(SM_CYSMSIZE), 
-         hdcMem, 0, 0,
-         SRCCOPY );
-  DeleteDC( hdcMem );
+    SelectObject(hDcMem, hSavedBitmap);
+    DeleteDC(hDcMem);
+    return TRUE;
 }
 
-static void UserDrawCaptionNC( HDC hdc, RECT *rect, HWND hwnd,
-                           DWORD style, BOOL active )
+/*
+ * FIXME:
+ * Cache bitmaps, then just bitblt instead of calling DFC() (and
+ * wasting precious CPU cycles) every time
+ */
+static void
+UserDrawCaptionButton(HWND hWnd, HDC hDC, BOOL bDown, ULONG Type)
 {
-  RECT r = *rect;
-  char buffer[256];
+    RECT rect;
+    INT iBmpWidth = GetSystemMetrics(SM_CXSIZE) - 2;
+    INT iBmpHeight = GetSystemMetrics(SM_CYSIZE) - 4;
+    INT OffsetX = UIGetFrameSizeX(hWnd);
+    INT OffsetY = UIGetFrameSizeY(hWnd);
 
-  if (!hbitmapClose)
-    {      
-      hbitmapClose = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_CLOSE));
-      hbitmapMinimize  = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_REDUCE) );
-      hbitmapMinimizeD = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_REDUCED) );
-      hbitmapMaximize  = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_ZOOM) );
-      hbitmapMaximizeD = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_ZOOMD) );
-      hbitmapRestore   = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_RESTORE) );
-      hbitmapRestoreD  = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_RESTORED) );
+    if (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_SYSMENU))
+    {
+        return;
     }
-    
-  if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
+
+    GetWindowRect(hWnd, &rect);
+
+    rect.right = rect.right - rect.left;
+    rect.bottom = rect.bottom - rect.top;
+    rect.left = rect.top = 0;
+
+    switch(Type)
     {
-      HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
-      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 );
+        case DFCS_CAPTIONMIN:
+        {
+            if ((GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) == TRUE)
+                return; /* ToolWindows don't have min/max buttons */
+
+            SetRect(&rect, rect.right - OffsetX - (iBmpWidth * 3) - 5,
+                    OffsetY + 2, rect.right - (iBmpWidth * 2) - OffsetX - 5,
+                    rect.top + iBmpHeight + OffsetY + 2);
+            DrawFrameControl(hDC, &rect, DFC_CAPTION,
+                             DFCS_CAPTIONMIN | (bDown ? DFCS_PUSHED : 0) |
+                             (IsMinBoxActive(hWnd) ? 0 : DFCS_INACTIVE));
+            break;
+        }
+        case DFCS_CAPTIONMAX:
+        {
+            if ((GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) == TRUE)
+                return; /* ToolWindows don't have min/max buttons */
+
+            SetRect(&rect, rect.right - OffsetX - (iBmpWidth * 2) - 5,
+                    OffsetY + 2, rect.right - iBmpWidth - OffsetX - 5,
+                    rect.top + iBmpHeight + OffsetY + 2);
+            DrawFrameControl(hDC, &rect, DFC_CAPTION,
+                             (IsZoomed(hWnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX) |
+                             (bDown ? DFCS_PUSHED : 0) |
+                             (IsMaxBoxActive(hWnd) ? 0 : DFCS_INACTIVE));
+            break;
+        }
+        case DFCS_CAPTIONCLOSE:
+        {
+            SetRect(&rect, rect.right - OffsetX - iBmpWidth - 3,
+                    OffsetY + 2,       rect.right - OffsetX - 3,
+                    rect.top + iBmpHeight + OffsetY + 2 );      
+            DrawFrameControl(hDC, &rect, DFC_CAPTION,
+                             (DFCS_CAPTIONCLOSE | (bDown ? DFCS_PUSHED : 0) |
+                             (IsCloseBoxActive(hWnd) ? 0 : DFCS_INACTIVE)));
+            break;
+        }
     }
+}
 
-  MoveToEx( hdc, r.left, r.bottom, NULL );
-  LineTo( hdc, r.right, r.bottom );
+// Enabling this will cause captions to draw smoother, but slower:
+// #define DOUBLE_BUFFER_CAPTION
+// NOTE: Double buffering appears to be broken for this at the moment
 
-  if (style & WS_SYSMENU)
+/*
+ * @implemented
+ */
+WINBOOL STDCALL
+DrawCaption(
+  HWND hWnd,
+  HDC hDC,
+  LPRECT lprc,
+  UINT uFlags)
+{
+    NONCLIENTMETRICSW nclm;
+    BOOL result = FALSE;
+    RECT r = *lprc;
+    UINT VCenter = 0, Padding = 0, Height;
+    WCHAR buffer[256];
+    HFONT hFont = NULL;
+    HFONT hOldFont = NULL;
+    HBRUSH OldBrush = NULL;
+    HDC MemDC = NULL;
+    int ButtonWidth;
+
+#ifdef DOUBLE_BUFFER_CAPTION
+    HBITMAP MemBMP = NULL, OldBMP = NULL;
+
+    MemDC = CreateCompatibleDC(hDC);
+    if (! MemDC) goto cleanup;
+    MemBMP = CreateCompatibleBitmap(hDC, lprc->right - lprc->left, lprc->bottom - lprc->top);
+    if (! MemBMP) goto cleanup;
+    OldBMP = SelectObject(MemDC, MemBMP);
+    if (! OldBMP) goto cleanup;
+#else
+    MemDC = hDC;
+
+    OffsetViewportOrgEx(MemDC, lprc->left, lprc->top, NULL);
+#endif
+
+    // If DC_GRADIENT is specified, a Win 98/2000 style caption gradient should
+    // be painted. For now, that flag is ignored:
+    // Windows 98/Me, Windows 2000/XP: When this flag is set, the function uses
+    // COLOR_GRADIENTACTIVECAPTION (if the DC_ACTIVE flag was set) or
+    // COLOR_GRADIENTINACTIVECAPTION for the title-bar color. 
+
+    // Draw the caption background
+    if (uFlags & DC_INBUTTON)
     {
-      UserDrawSysButton( hwnd, hdc, FALSE );
-      r.left += GetSystemMetrics(SM_CXSIZE) + 1;
-      MoveToEx( hdc, r.left - 1, r.top, NULL );
-      LineTo( hdc, r.left - 1, r.bottom );
+        OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_BTNFACE : COLOR_BTNSHADOW) );
+        if (! OldBrush) goto cleanup;
+        if (! PatBlt(MemDC, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top, PATCOPY )) goto cleanup;
     }
-  if (style & WS_MAXIMIZEBOX)
+    else
     {
-      UserDrawMaxButton( hwnd, hdc, FALSE );
-      r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
+        // DC_GRADIENT check should go here somewhere
+        OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
+        if (! OldBrush) goto cleanup;
+        if (! PatBlt(MemDC, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top, PATCOPY )) goto cleanup;
     }
-  if (style & WS_MINIMIZEBOX)
+    
+    /* Windows behaves like this */
+    Height = GetSystemMetrics(SM_CYCAPTION) - 1;
+
+    VCenter = (lprc->bottom - lprc->top) / 2;
+    Padding = VCenter - (Height / 2);
+
+    r.left = Padding;
+    r.right = r.left + (lprc->right - lprc->left);
+    r.top = Padding;
+    r.bottom = r.top + (Height / 2);
+
+    if (uFlags & DC_ICON)
     {
-      UserDrawMinButton( hwnd, hdc, FALSE );
-      r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
+        // For some reason the icon isn't centered correctly...
+        r.top --;
+        UserDrawSysMenuButton(hWnd, MemDC, &r, FALSE);
+        r.top ++;
     }
-  
-  FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
-                                           COLOR_INACTIVECAPTION) );
-  
-  if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
+
+    r.top ++;
+    r.left += 2;
+
+  if ((uFlags & DC_TEXT) && (GetWindowTextW( hWnd, buffer, sizeof(buffer)/sizeof(buffer[0]) )))
+  {
+    // Duplicate odd behaviour from Windows:
+    if ((! uFlags & DC_SMALLCAP) || (uFlags & DC_ICON) || (uFlags & DC_INBUTTON) ||
+        (! uFlags & DC_ACTIVE))
+        r.left += GetSystemMetrics(SM_CXSIZE) + Padding;
+
+    r.right = (lprc->right - lprc->left);
+    ButtonWidth = GetSystemMetrics(SM_CXSIZE) - 2;
+    if (GetWindowLongW(hWnd, GWL_STYLE) & WS_SYSMENU)
     {
-      NONCLIENTMETRICS nclm;
-      HFONT hFont, hOldFont;
+      r.right -= 3 + ButtonWidth;
+      if (! (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
+      {
+       r.right -= 2 + 2 * ButtonWidth;
+      }
+    }
+    r.right -= 2;
 
-      nclm.cbSize = sizeof(NONCLIENTMETRICS);
-      SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
-      if (style & WS_EX_TOOLWINDOW)
+    nclm.cbSize = sizeof(nclm);
+    if (! SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSW), &nclm, 0)) goto cleanup;
+
+    if (uFlags & DC_INBUTTON)
+        SetTextColor(MemDC, SysColours[ uFlags & DC_ACTIVE ? COLOR_BTNTEXT : COLOR_GRAYTEXT]);
+    else
+        SetTextColor(MemDC, SysColours[ uFlags & DC_ACTIVE ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT]);
+
+    SetBkMode( MemDC, TRANSPARENT );
+    if (GetWindowLongW(hWnd, GWL_STYLE) & WS_EX_TOOLWINDOW)
+//    if (uFlags & DC_SMALLCAP) // incorrect
         hFont = CreateFontIndirectW(&nclm.lfSmCaptionFont);
-      else
+    else
         hFont = CreateFontIndirectW(&nclm.lfCaptionFont);
-      hOldFont = SelectObject(hdc, hFont);
 
-      if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
-      else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
-      SetBkMode( hdc, TRANSPARENT );
-      /*DrawTextA( hdc, buffer, -1, &r,
-       DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );*/
-      TextOutA(hdc, r.left+5, r.top+2, buffer, strlen(buffer));
-      DeleteObject (SelectObject (hdc, hOldFont));
+    if (! hFont) goto cleanup;
+
+    hOldFont = SelectObject(MemDC, hFont);
+    if (! hOldFont) goto cleanup;
+
+    DrawTextW(MemDC, buffer, wcslen(buffer), &r, DT_VCENTER | DT_END_ELLIPSIS);
+    // Old method:
+    // TextOutW(hDC, r.left + (GetSystemMetrics(SM_CXDLGFRAME) * 2), lprc->top + (nclm.lfCaptionFont.lfHeight / 2), buffer, wcslen(buffer));
+  }
+
+    if (uFlags & DC_BUTTONS)
+    {
+        // Windows XP draws the caption buttons with DC_BUTTONS
+//        r.left += GetSystemMetrics(SM_CXSIZE) + 1;
+//        UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONCLOSE);
+//        r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
+//        UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMIN);
+//        UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMAX);
     }
+
+#ifdef DOUBLE_BUFFER_CAPTION
+    if (! BitBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top,
+            MemDC, 0, 0, SRCCOPY)) goto cleanup;
+#endif
+
+    result = TRUE;
+
+    cleanup :
+        if (MemDC)
+        {
+            if (OldBrush) SelectObject(MemDC, OldBrush);
+            if (hOldFont) SelectObject(MemDC, hOldFont);
+            if (hFont) DeleteObject(hFont);
+#ifdef DOUBLE_BUFFER_CAPTION
+            if (OldBMP) SelectObject(MemDC, OldBMP);
+            if (MemBMP) DeleteObject(MemBMP);
+            DeleteDC(MemDC);
+#else
+            OffsetViewportOrgEx(MemDC, -lprc->left, -lprc->top, NULL);
+#endif
+        }
+
+        return result;
 }
 
-VOID
-UserDrawFrameNC(HDC hdc, RECT* rect, BOOL dlgFrame, BOOL active)
+
+
+static void
+UserDrawCaptionNC (
+       HDC hDC,
+       RECT *rect,
+       HWND hWnd,
+       DWORD style,
+       BOOL active )
 {
-  INT width, height;
-  
-  if (dlgFrame)
-    {
-      width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
-      height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
-      SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
-                                         COLOR_INACTIVECAPTION) );
-    }
-  else
-    {
-      width = GetSystemMetrics(SM_CXFRAME) - 2;
-      height = GetSystemMetrics(SM_CYFRAME) - 2;
-      SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
-                                           COLOR_INACTIVEBORDER) );
-    }
+  POINT OldPos;
+  HPEN lPen, oPen;
+  RECT r = *rect;
+  UINT capflags = 0;
+
+    capflags = DC_ICON | DC_TEXT;
+    capflags |= (active & DC_ACTIVE);
+
+    if (GetWindowLongW(hWnd, GWL_STYLE) & WS_EX_TOOLWINDOW)
+        capflags |= DC_SMALLCAP;
+
+//  Old code:
+//  PatBlt(hDC,rect->left + GetSystemMetrics(SM_CXFRAME), rect->top +
+//     GetSystemMetrics(SM_CYFRAME), rect->right - (GetSystemMetrics(SM_CXFRAME) * 2), (rect->top + 
+//     GetSystemMetrics(SM_CYCAPTION)) - 1, PATCOPY );
+
+    r.left += GetSystemMetrics(SM_CXFRAME);
+    r.top += GetSystemMetrics(SM_CYFRAME);
+    r.right -= GetSystemMetrics(SM_CXFRAME);
+    r.bottom = r.top + GetSystemMetrics(SM_CYCAPTION) - 1;
+//     GetSystemMetrics(SM_CYCAPTION)) - 1, PATCOPY );
+
+    DrawCaption(hWnd, hDC, &r, capflags);
+    
+  /* draw line below caption */
+  lPen = GetSysColorPen(COLOR_MENU);
+  oPen = SelectObject(hDC, lPen);
+  MoveToEx(hDC, r.left, r.bottom, &OldPos);
+  LineTo(hDC, r.right, r.bottom);
+  MoveToEx(hDC, OldPos.x, OldPos.y, NULL);
+  SelectObject(hDC, oPen);
+  r.bottom++;
   
-  /* Draw frame */
-  PatBlt( hdc, rect->left, rect->top,
-         rect->right - rect->left, height, PATCOPY );
-  PatBlt( hdc, rect->left, rect->top,
-         width, rect->bottom - rect->top, PATCOPY );
-  PatBlt( hdc, rect->left, rect->bottom - 1,
-         rect->right - rect->left, -height, PATCOPY );
-  PatBlt( hdc, rect->right - 1, rect->top,
-         -width, rect->bottom - rect->top, PATCOPY );
+  if (style & WS_SYSMENU)
+  {
+//    UserDrawSysMenuButton( hWnd, hDC, FALSE);
+    r.left += GetSystemMetrics(SM_CXSIZE) + 1;
+    UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONCLOSE);
+    r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
+    UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMIN);
+    UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMAX);
+  }
+}
 
-  if (dlgFrame)
-    {
-      InflateRect( rect, -width, -height );
-    } 
-  else
-    {
-      INT decYOff = GetSystemMetrics(SM_CXFRAME) + 
-       GetSystemMetrics(SM_CXSIZE) - 1;
-      INT decXOff = GetSystemMetrics(SM_CYFRAME) + 
-       GetSystemMetrics(SM_CYSIZE) - 1;
 
-      /* Draw inner rectangle */
-      
-      SelectObject( hdc, GetStockObject(NULL_BRUSH) );
-      Rectangle( hdc, rect->left + width, rect->top + height,
-                rect->right - width , rect->bottom - height );
-      
-      /* Draw the decorations */
-      
-      MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
-      LineTo( hdc, rect->left + width, rect->top + decYOff );
-      MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
-      LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
-      MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
-      LineTo( hdc, rect->left + width, rect->bottom - decYOff );
-      MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
-      LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
-      
-      MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
-      LineTo( hdc, rect->left + decXOff, rect->top + height);
-      MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
-      LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
-      MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
-      LineTo( hdc, rect->right - decXOff, rect->top + height );
-      MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
-      LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
-      
-      InflateRect( rect, -width - 1, -height - 1 );
-    }
+static VOID
+UserDrawFrameNC(HDC hDC, RECT* rect, BOOL dlgFrame, BOOL active)
+{
+  DrawEdge(hDC, rect,EDGE_RAISED, BF_RECT | BF_MIDDLE);
 }
 
+
+void
+SCROLL_DrawScrollBar (HWND hWnd, HDC hDC, INT nBar, BOOL arrows, BOOL interior);
+
 VOID
 DefWndDoPaintNC(HWND hWnd, HRGN clip)
 {
-  ULONG Active;
-  HDC hDc;
+  BOOL Active = FALSE;
+  HDC hDC;
   RECT rect;
   ULONG Style;
   ULONG ExStyle;
+  int wFrame = 0;
 
-  Active = GetWindowLongW(hWnd, GWL_STYLE) & WIN_NCACTIVATED;
-  Style = GetWindowLong(hWnd, GWL_STYLE);
-  ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
+  if (GetActiveWindow() == hWnd) Active = TRUE;
+  Style = GetWindowLongW(hWnd, GWL_STYLE);
+  ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
 
-  hDc = GetDCEx(hWnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
+  hDC = GetDCEx(hWnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
                ((clip > (HRGN)1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0));
-  if (hDc == 0)
+  if (hDC == 0)
     {
       return;
     }
@@ -437,42 +650,48 @@ DefWndDoPaintNC(HWND hWnd, HRGN clip)
   rect.right = rect.right - rect.left;
   rect.bottom = rect.bottom - rect.top;
   rect.top = rect.left = 0;
-
-  SelectObject(hDc, GetSysColorPen(COLOR_WINDOWFRAME));
-  if (UserHasAnyFrameStyle(Style, ExStyle))
-    {
-      SelectObject(hDc, GetStockObject(NULL_BRUSH));
-      Rectangle(hDc, 0, 0, rect.right, rect.bottom);
-      InflateRect(&rect, -1, -1);
-    }
-  
+  SelectObject(hDC, GetSysColorPen(COLOR_WINDOWFRAME));
   if (UserHasThickFrameStyle(Style, ExStyle))
     {
-      UserDrawFrameNC(hDc, &rect, FALSE, Active);
+      UserDrawFrameNC(hDC, &rect, FALSE, Active);
+      wFrame = GetSystemMetrics(SM_CXSIZEFRAME);
     }
   else if (UserHasDlgFrameStyle(Style, ExStyle))
     {
-      UserDrawFrameNC(hDc, &rect, TRUE, Active);
+      UserDrawFrameNC(hDC, &rect, TRUE, Active);
+      wFrame = GetSystemMetrics(SM_CXDLGFRAME);
     }
-  
   if (Style & WS_CAPTION)
     {
       RECT r = rect;
       r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
-      rect.top += GetSystemMetrics(SM_CYSIZE) + 
+      rect.top += GetSystemMetrics(SM_CYSIZE) +
        GetSystemMetrics(SM_CYBORDER);
-      UserDrawCaptionNC(hDc, &r, hWnd, Style, Active);
+      UserDrawCaptionNC(hDC, &r, hWnd, Style, Active);
     }
 
-  /* FIXME: Draw menu bar. */
+  /*  Draw menu bar.  */
+  if (UserHasMenu(hWnd, Style))
+    {
+      RECT r = rect;
+      r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
+      r.left += wFrame;
+      r.right -= wFrame;
+      rect.top += MenuDrawMenuBar(hDC, &r, hWnd, FALSE);
+    }
 
-  /* FIXME: Draw scroll bars. */
+  /*  Draw scrollbars */
+  if (Style & WS_VSCROLL)
+      SCROLL_DrawScrollBar(hWnd, hDC, SB_VERT, TRUE, TRUE);
+  if (Style & WS_HSCROLL)
+      SCROLL_DrawScrollBar(hWnd, hDC, SB_HORZ, TRUE, TRUE);
 
-  /* FIXME: Draw size box. */
-  
-  ReleaseDC(hWnd, hDc);
+  /* FIXME: Draw size box.*/
+
+  ReleaseDC(hWnd, hDC);
 }
 
+
 LRESULT
 DefWndPaintNC(HWND hWnd, HRGN clip)
 {
@@ -490,17 +709,17 @@ DefWndPaintNC(HWND hWnd, HRGN clip)
   return(0);
 }
 
+
 LRESULT
 DefWndHitTestNC(HWND hWnd, POINT Point)
 {
   RECT WindowRect;
-  ULONG Style = GetWindowLong(hWnd, GWL_STYLE);
-  ULONG ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
+  ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
+  ULONG ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
 
   GetWindowRect(hWnd, &WindowRect);
-
   if (!PtInRect(&WindowRect, Point))
-    {
+    {      
       return(HTNOWHERE);
     }
   if (Style & WS_MINIMIZE)
@@ -561,9 +780,9 @@ DefWndHitTestNC(HWND hWnd, POINT Point)
                }
              return(HTRIGHT);
            }
-       }      
+       }
     }
-  else 
+  else
     {
       if (UserHasDlgFrameStyle(Style, ExStyle))
        {
@@ -583,22 +802,27 @@ DefWndHitTestNC(HWND hWnd, POINT Point)
 
   if ((Style & WS_CAPTION) == WS_CAPTION)
     {
-      WindowRect.top += GetSystemMetrics(SM_CYCAPTION) - 
-       GetSystemMetrics(SM_CYBORDER);
+      WindowRect.top += (GetSystemMetrics(SM_CYCAPTION) -
+       GetSystemMetrics(SM_CYBORDER));
       if (!PtInRect(&WindowRect, Point))
        {
          if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW))
            {
              WindowRect.left += GetSystemMetrics(SM_CXSIZE);
+             WindowRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
            }
          if (Point.x <= WindowRect.left)
            {
              return(HTSYSMENU);
            }
+         if (WindowRect.right <= Point.x)
+           {
+             return(HTCLOSE);
+           }
 
-         if (Style & WS_MAXIMIZEBOX)
+         if (Style & WS_MAXIMIZEBOX || Style & WS_MINIMIZEBOX)
            {
-             WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
+             WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
            }
          if (Point.x >= WindowRect.right)
            {
@@ -607,7 +831,7 @@ DefWndHitTestNC(HWND hWnd, POINT Point)
 
          if (Style & WS_MINIMIZEBOX)
            {
-             WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
+             WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
            }
          if (Point.x >= WindowRect.right)
            {
@@ -642,7 +866,7 @@ DefWndHitTestNC(HWND hWnd, POINT Point)
          if ((Style & WS_VSCROLL) &&
              (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXVSCROLL))))
            {
-             return(HTSIZE);
+             return(HTBOTTOMRIGHT);
            }
          return(HTHSCROLL);
        }
@@ -659,184 +883,192 @@ DefWndHitTestNC(HWND hWnd, POINT Point)
   return(HTNOWHERE);
 }
 
-VOID
-DefWndTrackMinMaxBox(HWND hWnd, WPARAM wParam)
+VOID STATIC
+DefWndDoButton(HWND hWnd, WPARAM wParam)
 {
-  HDC hDC = GetWindowDC(hWnd);
-  BOOL Pressed = TRUE;
   MSG Msg;
-
+  BOOL InBtn = TRUE, HasBtn = FALSE;
+  ULONG Btn;
+  WPARAM SCMsg, CurBtn = wParam, OrigBtn = wParam;
+  
+  switch(wParam)
+  {
+    case HTCLOSE:
+      Btn = DFCS_CAPTIONCLOSE;
+      SCMsg = SC_CLOSE;
+      HasBtn = IsCloseBoxActive(hWnd);
+      break;
+    case HTMINBUTTON:
+      Btn = DFCS_CAPTIONMIN;
+      SCMsg = SC_MINIMIZE;
+      HasBtn = IsMinBoxActive(hWnd);
+      break;
+    case HTMAXBUTTON:
+      Btn = DFCS_CAPTIONMAX;
+      SCMsg = SC_MAXIMIZE;
+      HasBtn = IsMaxBoxActive(hWnd);
+      break;
+    default:
+      return;
+  }
+  
+  if(!HasBtn)
+    return;
+  
   SetCapture(hWnd);
-
-  if (wParam == HTMINBUTTON)
-    {
-      UserDrawMinButton(hWnd, hDC, TRUE);
-    }
-  else
+  UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), HasBtn , Btn);
+  
+  while(1)
+  {
+    GetMessageW(&Msg, 0, 0, 0);
+    switch(Msg.message)
     {
-      UserDrawMaxButton(hWnd, hDC, TRUE);
+      case WM_NCLBUTTONUP:
+      case WM_LBUTTONUP:
+        if(InBtn)
+          goto done;
+        else
+        {
+          ReleaseCapture();
+          return;
+        }
+      case WM_NCMOUSEMOVE:
+      case WM_MOUSEMOVE:
+        CurBtn = DefWndHitTestNC(hWnd, Msg.pt);
+        if(InBtn != (CurBtn == OrigBtn))
+        {
+          UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), (CurBtn == OrigBtn) , Btn);
+        }
+        InBtn = CurBtn == OrigBtn;
+        break;
     }
+  }
+  
+done:
+  UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), FALSE , Btn);
+  ReleaseCapture();
+  SendMessageA(hWnd, WM_SYSCOMMAND, SCMsg, 0);
+  return;
+}
 
-  for(;;)
-    {
-      BOOL OldState = Pressed;      
-
-      GetMessageA(hWnd, &Msg, 0, 0);
-      if (Msg.message == WM_LBUTTONUP)
-       {
-         break;
-       }
-      if (Msg.message != WM_MOUSEMOVE)
-       {
-         continue;
-       }
+VOID STATIC
+DefWndDoScrollBarDown(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+  POINT Point;
+  DWORD hit;
+  Point.x = SLOWORD(lParam);
+  Point.y = SHIWORD(lParam);
+  
+  hit = SCROLL_HitTest(hWnd, (wParam == HTHSCROLL) ? SB_HORZ : SB_VERT, Point, FALSE);
+  
+  if(hit)
+    DbgPrint("SCROLL_HitTest() == 0x%x\n", hit);
+  
+  SendMessageA(hWnd, WM_SYSCOMMAND, Msg + (UINT)wParam, lParam);
+}
 
-      Pressed = DefWndHitTestNC(hWnd, Msg.pt) == wParam;
-      if (Pressed != OldState)
-       {
-         if (wParam == HTMINBUTTON)
-           {
-             UserDrawMinButton(hWnd, hDC, Pressed);
-           }
-         else
-           {
-             UserDrawMaxButton(hWnd, hDC, Pressed);
+LRESULT
+DefWndHandleLButtonDownNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+    switch (wParam)
+    {
+        case HTCAPTION:
+        {
+               HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
+               if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
+               {
+                   SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
+               }
+               break;
+        }
+        case HTSYSMENU:
+        {
+         if (GetWindowLongW(hWnd, GWL_STYLE) & WS_SYSMENU)
+            {
+             if (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
+               {
+                 HDC hDC = GetWindowDC(hWnd);
+//               UserDrawSysMenuButton(hWnd, hDC, TRUE);
+                 ReleaseDC(hWnd, hDC);
+               }
+             SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU,
+                          lParam);
            }
-       }
+         break;
+        }
+        case HTMENU:
+        {
+            SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTMENU, lParam);
+            break;
+        }
+        case HTHSCROLL:
+        {
+            DefWndDoScrollBarDown(hWnd, SC_HSCROLL, HTHSCROLL, lParam);
+            //SendMessageA(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
+            break;
+        }
+        case HTVSCROLL:
+        {
+            DefWndDoScrollBarDown(hWnd, SC_VSCROLL, HTVSCROLL, lParam);
+            //SendMessageA(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
+            break;
+        }
+        case HTMINBUTTON:
+        case HTMAXBUTTON:
+        case HTCLOSE:
+        {
+          DefWndDoButton(hWnd, wParam);
+          break;
+        }
+        case HTLEFT:
+        case HTRIGHT:
+        case HTTOP:
+        case HTBOTTOM:
+        case HTTOPLEFT:
+        case HTTOPRIGHT:
+        case HTBOTTOMLEFT:
+        case HTBOTTOMRIGHT:
+        {
+            SendMessageA(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
+            break;
+        }
     }
+    return(0);
+}
 
-  if (Pressed)
-    {
-      if (wParam == HTMINBUTTON)
-       {
-         UserDrawMinButton(hWnd, hDC, FALSE);
-       }
-      else
-       {
-         UserDrawMaxButton(hWnd, hDC, FALSE);
-       }
-    }
 
-  ReleaseCapture();
-  ReleaseDC(hWnd, hDC);
+LRESULT
+DefWndHandleLButtonDblClkNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+  UNIMPLEMENTED;
+  return(0);
+}
 
-  if (!Pressed)
-    {
-      return;
-    }
 
-  if (wParam == HTMINBUTTON)
-    {
-      SendMessageA(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 
-                  MAKELONG(Msg.pt.x, Msg.pt.y));
-    }
-  else
-    {
-      SendMessageA(hWnd, WM_SYSCOMMAND, 
-                  IsZoomed(hWnd) ? SC_RESTORE : SC_MAXIMIZE, 
-                  MAKELONG(Msg.pt.x, Msg.pt.y));
-    }
+LRESULT
+DefWndHandleLButtonUpNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+  UNIMPLEMENTED;
+  return(0);
+}
+
+
+LRESULT
+DefWndHandleActiveNC(HWND hWnd, WPARAM wParam)
+{
+  UNIMPLEMENTED;
+  return(0);
 }
 
+
 VOID
-DefWndDrawSysButton(HWND hWnd, HDC hDC, BOOL Down)
+DefWndSetRedraw(HWND hWnd, WPARAM wParam)
 {
-  RECT Rect;
-  HDC hDcMem;
-  HBITMAP hSavedBitmap;
-
-  UserGetInsideRectNC(hWnd, &Rect);
-  hDcMem = CreateCompatibleDC(hDC);
-  hSavedBitmap = SelectObject(hDcMem, hbitmapClose);
-  BitBlt(hDC, Rect.left, Rect.top, GetSystemMetrics(SM_CXSIZE),
-        GetSystemMetrics(SM_CYSIZE), hDcMem, 
-        (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) ? 
-        GetSystemMetrics(SM_CXSIZE): 0, 0, Down ? NOTSRCCOPY : SRCCOPY);
-  SelectObject(hDcMem, hSavedBitmap);
-  DeleteDC(hDcMem);
+  UNIMPLEMENTED;
 }
 
+
 LRESULT
-DefWndHandleLButtonDownNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
-{
-  switch (wParam)
-    {
-    case HTCAPTION:
-      {
-       HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
-       if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
-         {
-           SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
-         }
-       break;
-      }
-    case HTSYSMENU:
-      {
-       if (GetWindowLong(hWnd, GWL_STYLE) & WS_SYSMENU)
-         {
-           if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE))
-             {
-               HDC hDC = GetWindowDC(hWnd);
-               DefWndDrawSysButton(hWnd, hDC, TRUE);
-               ReleaseDC(hWnd, hDC);
-             }
-           SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, 
-                        lParam);
-         }
-       break;
-      }
-
-    case HTMENU:
-      SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam);
-      break;
-
-    case HTHSCROLL:
-      SendMessageA(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
-      break;
-
-    case HTVSCROLL:
-      SendMessageA(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
-      break;
-
-    case HTMINBUTTON:
-    case HTMAXBUTTON:
-      DefWndTrackMinMaxBox(hWnd, wParam);
-      break;
-
-    case HTLEFT:
-    case HTRIGHT:
-    case HTTOP:
-    case HTBOTTOM:
-    case HTTOPLEFT:
-    case HTTOPRIGHT:
-    case HTBOTTOMLEFT:
-    case HTBOTTOMRIGHT:
-      SendMessageA(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
-      break;
-    }
-  return(0);
-}
-
-LRESULT
-DefWndHandleLButtonDblClkNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
-{
-  /* FIXME: Implement this. */
-  return(0);
-}
-
-LRESULT
-DefWndHandleActiveNC(HWND hWnd, WPARAM wParam)
-{
-  /* FIXME: Implement this. */
-  return(0);
-}
-
-VOID
-DefWndSetRedraw(HWND hWnd, WPARAM wParam)
-{
-}
-
-LRESULT 
 DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam)
 {
   /* Not for child windows. */
@@ -860,7 +1092,7 @@ DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam)
 
     case HTCLIENT:
       {
-       HICON hCursor = (HICON)GetClassLong(hWnd, GCL_HCURSOR);
+       HICON hCursor = (HICON)GetClassLongW(hWnd, GCL_HCURSOR);
        if (hCursor)
          {
            SetCursor(hCursor);
@@ -896,13 +1128,434 @@ DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam)
   return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW)));
 }
 
+static LONG 
+DefWndStartSizeMove(HWND hWnd, WPARAM wParam, POINT *capturePoint)
+{
+  LONG hittest = 0;
+  POINT pt;
+  MSG msg;
+  RECT rectWindow;
+  ULONG Style = GetWindowLongW(hWnd, GWL_STYLE); 
+  
+  GetWindowRect(hWnd, &rectWindow);
+
+  if ((wParam & 0xfff0) == SC_MOVE)
+    {
+      /* Move pointer at the center of the caption */
+      RECT rect;
+      UserGetInsideRectNC(hWnd, &rect);
+      if (Style & WS_SYSMENU)
+       rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
+      if (Style & WS_MINIMIZEBOX)
+       rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
+      if (Style & WS_MAXIMIZEBOX)
+       rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
+      pt.x = rectWindow.left + (rect.right - rect.left) / 2;
+      pt.y = rectWindow.top + rect.top + GetSystemMetrics(SM_CYSIZE)/2;
+      hittest = HTCAPTION;
+      *capturePoint = pt;
+    }
+  else  /* SC_SIZE */
+    {
+      while(!hittest)
+       {
+         GetMessageW(&msg, NULL, 0, 0);
+         switch(msg.message)
+           {
+           case WM_MOUSEMOVE:
+             hittest = DefWndHitTestNC(hWnd, msg.pt);
+             if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
+               hittest = 0;
+             break;
+             
+           case WM_LBUTTONUP:
+             return 0;
+             
+           case WM_KEYDOWN:
+             switch(msg.wParam)
+               {
+               case VK_UP:
+                 hittest = HTTOP;
+                 pt.x =(rectWindow.left+rectWindow.right)/2;
+                 pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
+                 break;
+               case VK_DOWN:
+                 hittest = HTBOTTOM;
+                 pt.x =(rectWindow.left+rectWindow.right)/2;
+                 pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
+                 break;
+               case VK_LEFT:
+                 hittest = HTLEFT;
+                 pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
+                 pt.y =(rectWindow.top+rectWindow.bottom)/2;
+                 break;
+               case VK_RIGHT:
+                 hittest = HTRIGHT;
+                 pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
+                 pt.y =(rectWindow.top+rectWindow.bottom)/2;
+                 break;
+               case VK_RETURN:
+               case VK_ESCAPE: return 0;
+               }
+           }
+       }
+      *capturePoint = pt;
+    }
+    SetCursorPos( pt.x, pt.y );
+    DefWndHandleSetCursor(hWnd, (WPARAM)hWnd, MAKELONG(hittest, WM_MOUSEMOVE));
+    return hittest;
+}
+
+#define ON_LEFT_BORDER(hit) \
+ (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
+#define ON_RIGHT_BORDER(hit) \
+ (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
+#define ON_TOP_BORDER(hit) \
+ (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
+#define ON_BOTTOM_BORDER(hit) \
+ (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
+
+VOID STATIC 
+UserDrawWindowFrame(HDC hdc, const RECT *rect,
+                   ULONG width, ULONG height, DWORD rop )
+{
+  HBRUSH hbrush = SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
+  PatBlt( hdc, rect->left, rect->top,
+         rect->right - rect->left - width, height, rop );
+  PatBlt( hdc, rect->left, rect->top + height, width,
+         rect->bottom - rect->top - height, rop );
+  PatBlt( hdc, rect->left + width, rect->bottom - 1,
+         rect->right - rect->left - width, -height, rop );
+  PatBlt( hdc, rect->right - 1, rect->top, -width,
+         rect->bottom - rect->top - height, rop );
+  SelectObject( hdc, hbrush );
+}
+
+VOID STATIC
+UserDrawMovingFrame(HDC hdc, RECT *rect, BOOL thickframe)
+{
+  if (thickframe)
+    {
+      UserDrawWindowFrame(hdc, rect, GetSystemMetrics(SM_CXFRAME),
+                         GetSystemMetrics(SM_CYFRAME), PATINVERT );
+    }
+  else DrawFocusRect( hdc, rect );
+}
+
+VOID STATIC
+DefWndDoSizeMove(HWND hwnd, WORD wParam)
+{
+  MSG msg;
+  RECT sizingRect, mouseRect, origRect;
+  HDC hdc;
+  LONG hittest = (LONG)(wParam & 0x0f);
+  HCURSOR hDragCursor = 0, hOldCursor = 0;
+  POINT minTrack, maxTrack;
+  POINT capturePoint, pt;
+  ULONG Style = GetWindowLongW(hwnd, GWL_STYLE);
+  ULONG ExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE); 
+  BOOL thickframe = UserHasThickFrameStyle(Style, ExStyle);
+  BOOL iconic = Style & WS_MINIMIZE;
+  BOOL moved = FALSE;
+  DWORD dwPoint = GetMessagePos();
+  BOOL DragFullWindows = FALSE;
+  HWND hWndParent;
+
+  SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
+  
+  pt.x = SLOWORD(dwPoint);
+  pt.y = SHIWORD(dwPoint);
+  capturePoint = pt;
+  
+  if (IsZoomed(hwnd) || !IsWindowVisible(hwnd))
+    {
+      return;
+    }
+  
+  if ((wParam & 0xfff0) == SC_MOVE)
+    {
+      if (!hittest) 
+       {
+         hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
+       }
+      if (!hittest)
+       {
+         return;
+       }
+    }
+  else  /* SC_SIZE */
+    {
+      if (!thickframe)
+       {
+         return;
+       }
+      if (hittest && hittest != HTSYSMENU) 
+       {
+         hittest += 2;
+       }
+      else
+       {
+         SetCapture(hwnd);
+         hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
+         if (!hittest)
+           {
+             ReleaseCapture();
+             return;
+           }
+       }
+    }
+
+  if (Style & WS_CHILD)
+    {
+      hWndParent = GetParent(hwnd);
+    }
+  
+  /* Get min/max info */
+  
+  WinPosGetMinMaxInfo(hwnd, NULL, NULL, &minTrack, &maxTrack);
+  GetWindowRect(hwnd, &sizingRect);
+  origRect = sizingRect;
+  if (Style & WS_CHILD)
+    {
+      GetClientRect(hWndParent, &mouseRect );
+    }
+  else 
+    {
+      SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), 
+             GetSystemMetrics(SM_CYSCREEN));
+    }
+  if (ON_LEFT_BORDER(hittest))
+    {
+      mouseRect.left  = max( mouseRect.left, sizingRect.right-maxTrack.x );
+      mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
+    }
+  else if (ON_RIGHT_BORDER(hittest))
+    {
+      mouseRect.left  = max( mouseRect.left, sizingRect.left+minTrack.x );
+      mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
+    }
+  if (ON_TOP_BORDER(hittest))
+    {
+      mouseRect.top    = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
+      mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
+    }
+  else if (ON_BOTTOM_BORDER(hittest))
+    {
+      mouseRect.top    = max( mouseRect.top, sizingRect.top+minTrack.y );
+      mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
+    }
+  if (Style & WS_CHILD)
+    {      
+      MapWindowPoints( hWndParent, 0, (LPPOINT)&mouseRect, 2 );
+    }
+  SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
+  
+  if (GetCapture() != hwnd) SetCapture( hwnd );    
+  
+  if (Style & WS_CHILD)
+    {
+      /* Retrieve a default cache DC (without using the window style) */
+      hdc = GetDCEx(hWndParent, 0, DCX_CACHE);
+    }
+  else
+    {
+      hdc = GetDC( 0 );
+    }
+  
+  if( iconic ) /* create a cursor for dragging */
+    {
+      HICON hIcon = (HICON)GetClassLongW(hwnd, GCL_HICON);
+      if(!hIcon) hIcon = (HICON)SendMessageW( hwnd, WM_QUERYDRAGICON, 0, 0L);
+      if( hIcon ) hDragCursor = CursorIconToCursor( hIcon, TRUE );
+      if( !hDragCursor ) iconic = FALSE;
+    }
+  
+  /* invert frame if WIN31_LOOK to indicate mouse click on caption */
+  if( !iconic && !DragFullWindows)
+    {
+      UserDrawMovingFrame( hdc, &sizingRect, thickframe );
+    }
+  
+  while(1)
+    {
+      int dx = 0, dy = 0;
+
+      GetMessageW(&msg, 0, 0, 0);
+      
+      /* 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 (msg.message == WM_PAINT)
+        {
+         if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
+         UpdateWindow( msg.hwnd );
+         if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
+         continue;
+        }
+      
+      if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
+       continue;  /* We are not interested in other messages */
+      
+      pt = msg.pt;
+      
+      if (msg.message == WM_KEYDOWN) switch(msg.wParam)
+       {
+       case VK_UP:    pt.y -= 8; break;
+       case VK_DOWN:  pt.y += 8; break;
+       case VK_LEFT:  pt.x -= 8; break;
+       case VK_RIGHT: pt.x += 8; break;                
+       }
+      
+      pt.x = max( pt.x, mouseRect.left );
+      pt.x = min( pt.x, mouseRect.right );
+      pt.y = max( pt.y, mouseRect.top );
+      pt.y = min( pt.y, mouseRect.bottom );
+      
+      dx = pt.x - capturePoint.x;
+      dy = pt.y - capturePoint.y;
+      
+      if (dx || dy)
+       {
+         if( !moved )
+           {
+             moved = TRUE;
+             
+               if( iconic ) /* ok, no system popup tracking */
+                 {
+                   hOldCursor = SetCursor(hDragCursor);
+                   ShowCursor( TRUE );
+                   WinPosShowIconTitle( hwnd, FALSE );
+                 } 
+           }
+         
+         if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
+         else
+           {
+             RECT newRect = sizingRect;
+             WPARAM wpSizingHit = 0;
+             
+             if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
+             if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
+             else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
+             if (ON_TOP_BORDER(hittest)) newRect.top += dy;
+             else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
+             if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
+             capturePoint = pt;
+             
+             /* determine the hit location */
+             if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
+               wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
+             SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
+             
+             if (!iconic)
+               {
+                 if(!DragFullWindows)
+                   UserDrawMovingFrame( hdc, &newRect, thickframe );
+                 else {
+                   /* To avoid any deadlocks, all the locks on the windows
+                      structures must be suspended before the SetWindowPos */
+                   SetWindowPos( hwnd, 0, newRect.left, newRect.top,
+                                 newRect.right - newRect.left,
+                                 newRect.bottom - newRect.top,
+                                 ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
+                 }
+               }
+             sizingRect = newRect;
+           }
+       }
+    }
+  
+  ReleaseCapture();
+  if( iconic )
+    {
+      if( moved ) /* restore cursors, show icon title later on */
+       {
+         ShowCursor( FALSE );
+         SetCursor( hOldCursor );
+       }
+      DestroyCursor( hDragCursor );
+    }
+  else if(!DragFullWindows)
+      UserDrawMovingFrame( hdc, &sizingRect, thickframe );
+  
+  if (Style & WS_CHILD)
+    ReleaseDC( hWndParent, hdc );
+  else
+    ReleaseDC( 0, hdc );
+  
+  SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
+  SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
+  
+  /* window moved or resized */
+  if (moved)
+    {
+      /* if the moving/resizing isn't canceled call SetWindowPos
+       * with the new position or the new size of the window
+       */
+      if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
+        {
+         /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
+         if(!DragFullWindows)
+           SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
+                         sizingRect.right - sizingRect.left,
+                         sizingRect.bottom - sizingRect.top,
+                         ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
+        }
+      else { /* restore previous size/position */
+       if(DragFullWindows)
+         SetWindowPos( hwnd, 0, origRect.left, origRect.top,
+                       origRect.right - origRect.left,
+                       origRect.bottom - origRect.top,
+                       ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
+      }      
+    }
+  
+  if( IsWindow(hwnd) )
+    if( Style & WS_MINIMIZE )
+      {
+       /* Single click brings up the system menu when iconized */
+       
+       if( !moved ) 
+         {
+           if( Style & WS_SYSMENU ) 
+             SendMessageA( hwnd, WM_SYSCOMMAND,
+                           SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
+         }
+       else WinPosShowIconTitle( hwnd, TRUE );
+      }
+}
+
+
 LRESULT
 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
 {
-  /* FIXME: Implement system commands. */
+  switch (wParam & 0xfff0)
+    {
+      case SC_MOVE:
+      case SC_SIZE:
+       DefWndDoSizeMove(hWnd, wParam);
+       break;
+      case SC_CLOSE:
+        SendMessageA(hWnd, WM_CLOSE, 0, 0);
+        break;
+      case SC_MOUSEMENU:
+        MenuTrackMouseMenuBar(hWnd, wParam, Pt);
+       break;
+      case SC_KEYMENU:
+        MenuTrackKbdMenuBar(hWnd, wParam, Pt.x);
+       break;
+      default:
+       /* FIXME: Implement */
+        UNIMPLEMENTED;
+        break;
+    }
+
   return(0);
 }
 
+
 VOID
 DefWndAdjustRect(RECT* Rect, ULONG Style, BOOL Menu, ULONG ExStyle)
 {
@@ -913,7 +1566,7 @@ DefWndAdjustRect(RECT* Rect, ULONG Style, BOOL Menu, ULONG ExStyle)
 
   if (UserHasThickFrameStyle(Style, ExStyle))
     {
-      InflateRect(Rect, GetSystemMetrics(SM_CXFRAME), 
+      InflateRect(Rect, GetSystemMetrics(SM_CXFRAME),
                  GetSystemMetrics(SM_CYFRAME));
     }
   else if (UserHasDlgFrameStyle(Style, ExStyle))
@@ -928,8 +1581,8 @@ DefWndAdjustRect(RECT* Rect, ULONG Style, BOOL Menu, ULONG ExStyle)
     }
   if (Style & WS_CAPTION)
     {
-      Rect->top -= GetSystemMetrics(SM_CYCAPTION) - 
-       GetSystemMetrics(SM_CYBORDER);
+      Rect->top -= (GetSystemMetrics(SM_CYCAPTION) -
+       GetSystemMetrics(SM_CYBORDER)) + 1;
     }
   if (Menu)
     {
@@ -956,632 +1609,789 @@ DefWndAdjustRect(RECT* Rect, ULONG Style, BOOL Menu, ULONG ExStyle)
 LRESULT STDCALL
 DefWndNCCalcSize(HWND hWnd, RECT* Rect)
 {
-  LRESULT Result;
-  LONG Style = GetClassLongW(hWnd, GCL_STYLE);
-  RECT TmpRect = {0, 0, 0, 0};
+    LRESULT Result = 0;
+    LONG Style = GetClassLongW(hWnd, GCL_STYLE);
+    RECT TmpRect = {0, 0, 0, 0};
 
-  if (Style & CS_VREDRAW)
+    if (Style & CS_VREDRAW)
     {
-      Result |= WVR_VREDRAW;
+        Result |= WVR_VREDRAW;
     }
-  if (Style & CS_HREDRAW)
+    if (Style & CS_HREDRAW)
     {
-      Result |= WVR_HREDRAW;
+        Result |= WVR_HREDRAW;
     }
 
-  if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE))
+    if (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
     {
-      DefWndAdjustRect(&TmpRect, GetWindowLong(hWnd, GWL_STYLE),
-                      FALSE, GetWindowLong(hWnd, GWL_EXSTYLE));
-      Rect->left -= TmpRect.left;
-      Rect->top -= TmpRect.top;
-      Rect->right -= TmpRect.right;
-      Rect->bottom -= TmpRect.bottom;
-      /* FIXME: Adjust if the window has a menu. */
-      Rect->bottom = max(Rect->top, Rect->bottom);
-      Rect->right = max(Rect->left, Rect->right);
+        DefWndAdjustRect(&TmpRect, GetWindowLongW(hWnd, GWL_STYLE),
+                         FALSE, GetWindowLongW(hWnd, GWL_EXSTYLE));
+        Rect->left -= TmpRect.left;
+        Rect->top -= TmpRect.top;
+        Rect->right -= TmpRect.right;
+        Rect->bottom -= TmpRect.bottom;
+        if (UserHasMenu(hWnd, GetWindowLongW(hWnd, GWL_STYLE)))
+        {
+            Rect->top += MenuGetMenuBarHeight(hWnd, Rect->right - Rect->left,
+                -TmpRect.left, -TmpRect.top) + 1;
+        }
+        if (Rect->top > Rect->bottom)
+            Rect->bottom = Rect->top;
+        if (Rect->left > Rect->right)
+            Rect->right = Rect->left;
     }
-  return(Result);
+
+    return (Result);
 }
 
 LRESULT
 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
 {
-  /* FIXME: Implement this. */
-  return(0);
-}
+    POINT maxSize, minTrack;
+    LONG style = GetWindowLongA(hWnd, GWL_STYLE);
 
-LRESULT STDCALL
-User32DefWindowProc(HWND hWnd,
-                   UINT Msg,
-                   WPARAM wParam,
-                   LPARAM lParam,
-                   BOOL bUnicode)
-{
-  switch (Msg)
+    if (Pos->flags & SWP_NOSIZE) return 0;
+    if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
     {
-    case WM_NCPAINT:
-      {
-       return(DefWndPaintNC(hWnd, (HRGN)wParam));
-      }
-
-    case WM_NCHITTEST:
-      {
-       POINT Point;
-       Point.x = SLOWORD(lParam);
-       Point.y = SHIWORD(lParam);
-       return(DefWndHitTestNC(hWnd, Point));
-      }
-
-    case WM_NCLBUTTONDOWN:
-      {
-       return(DefWndHandleLButtonDownNC(hWnd, wParam, lParam));
-      }
-
-    case WM_LBUTTONDBLCLK:
-    case WM_NCLBUTTONDBLCLK:
-      {
-       return(DefWndHandleLButtonDblClkNC(hWnd, wParam, lParam));
-      }
-
-    case WM_NCRBUTTONDOWN:
-      {
-       if (wParam == HTCAPTION)
-         {
-           SetCapture(hWnd);
-         }
-       break;
-      }
-
-    case WM_RBUTTONUP:
-      {
-       POINT Pt;
-       if (hWnd == GetCapture())
-         {
-           ReleaseCapture();
-         }
-       Pt.x = SLOWORD(lParam);
-       Pt.y = SHIWORD(lParam);
-       ClientToScreen(hWnd, &Pt);
-       lParam = MAKELPARAM(Pt.x, Pt.y);
-       if (bUnicode)
-         {
-           SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
-         }
-       else
-         {
-           SendMessageA (hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
-         }
-       break;
-      }
-
-    case WM_NCRBUTTONUP:
-      {
-       /* Wine does nothing here. */
-       break;
-      }
-
-    case WM_CONTEXTMENU:
-      {
-       if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
-         {
-           if (bUnicode)
-             {
-               SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
-             }
-           else
-             {
-               SendMessageA(hWnd, WM_CONTEXTMENU, wParam, lParam);
-             }
-         }
-       else
-         {
-           LONG HitCode;
-           POINT Pt;
-
-           Pt.x = SLOWORD(lParam);
-           Pt.y = SHIWORD(lParam);
-           
-           if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
-             {
-               ScreenToClient(GetParent(hWnd), &Pt);
-             }
-
-           HitCode = DefWndHitTestNC(hWnd, Pt);
-
-           if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
-             {
-               TrackPopupMenu(GetSystemMenu(hWnd, FALSE),
-                              TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
-                              Pt.x, Pt.y, 0, hWnd, NULL);
-             }
-         }
-       break;
-      }
-
-    case WM_NCACTIVATE:
-      {
-       return(DefWndHandleActiveNC(hWnd, wParam));
-      }
-
-    case WM_NCDESTROY:
-      {
-       return(0);
-      }
-
-    case WM_PRINT:
-      {
-       return(0);
-      }
-
-    case WM_PAINTICON:
-    case WM_PAINT:
-      {
-       PAINTSTRUCT Ps;
-       HDC hDc = BeginPaint(hWnd, &Ps);
-       if (hDc)
-         {
-           HICON hIcon;
-           if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
-               (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
-             {
-               RECT WindowRect;
-               INT x, y;
-               GetWindowRect(hWnd, &WindowRect);
-               x = (WindowRect.right - WindowRect.left - 
-                    GetSystemMetrics(SM_CXICON)) / 2;
-               y = (WindowRect.bottom - WindowRect.top - 
-                    GetSystemMetrics(SM_CYICON)) / 2;
-               DrawIcon(hDc, x, y, hIcon);
-             }
-           EndPaint(hWnd, &Ps);
-         }
-       return(0);
-      }
-
-    case WM_SYNCPAINT:
-      {
-       HRGN hRgn;
-       hRgn = CreateRectRgn(0, 0, 0, 0);
-       if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
-         {
-           RedrawWindow(hWnd, NULL, hRgn, 
-                        RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
-                        RDW_ALLCHILDREN);
-         }
-       DeleteObject(hRgn);
-       return(0);
-      }
-
-    case WM_SETREDRAW:
-      {
-       DefWndSetRedraw(hWnd, wParam);
-       return(0);
-      }
-
-    case WM_CLOSE:
-      {
-       DestroyWindow(hWnd);
-       return(0);
-      }
-
-    case WM_MOUSEACTIVATE:
-      {
-       if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
-         {
-           LONG Ret;
-           if (bUnicode)
-             {
-               Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
-                                  wParam, lParam);
-             }
-           else
-             {
-               Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
-                                  wParam, lParam);
-             }
-           if (Ret)
-             {
-               return(Ret);
-             }
-         }
-       return((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
-      }
-
-    case WM_ACTIVATE:
-      {
-       if (LOWORD(lParam) != WA_INACTIVE &&
-           GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE)
-         {
-           /* Check if the window is minimized. */
-           SetFocus(hWnd);
-         }
-       break;
-      }
-
-    case WM_MOUSEWHEEL:
-      {
-       if (GetWindowLong(hWnd, GWL_STYLE & WS_CHILD))
-         {
-           if (bUnicode)
-             {
-               return(SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
-                                   wParam, lParam));
-             }
-           else
-             {
-               return(SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
-                                   wParam, lParam));
-             }
-         }
-       break;
-      }
-
-    case WM_ERASEBKGND:
-    case WM_ICONERASEBKGND:
-      {
-       RECT Rect;
-       HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
-       GetClipBox((HDC)wParam, &Rect);
-       FillRect((HDC)wParam, &Rect, hBrush);
-       return(1);
-      }
-
-    case WM_GETDLGCODE:
-      {
-       return(0);
-      }
-
-      /* FIXME: Implement colour controls. */
-
-    case WM_SETCURSOR:
-      {
-       if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
-         {
-           if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
-             {
-               BOOL bResult;
-               if (bUnicode)
-                 {
-                   bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR, 
-                                          wParam, lParam);
-                 }
-               else              
-                 {
-                   bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR, 
-                                          wParam, lParam);
-                 }
-               if (bResult)
-                 {
-                   return(TRUE);
-                 }
-             }
-         }
-       return(DefWndHandleSetCursor(hWnd, wParam, lParam));      
-      }
-
-    case WM_SYSCOMMAND:
-      {
-       POINT Pt;
-       Pt.x = SLOWORD(lParam);
-       Pt.y = SHIWORD(lParam);
-       return(DefWndHandleSysCommand(hWnd, wParam, Pt));
-      }
-
-      /* FIXME: Handle key messages. */
+        WinPosGetMinMaxInfo(hWnd, &maxSize, NULL, &minTrack, NULL);
+        Pos->cx = min(Pos->cx, maxSize.x);
+        Pos->cy = min(Pos->cy, maxSize.y);
+        if (!(style & WS_MINIMIZE))
+        {
+            if (Pos->cx < minTrack.x) Pos->cx = minTrack.x;
+            if (Pos->cy < minTrack.y) Pos->cy = minTrack.y;
+        }
+    }
+    return 0;
+}
 
-    case WM_SHOWWINDOW:
-      {
-       if (lParam)
-         {
-           return(0);
-         }
-       /* FIXME: Check for a popup window. */
-       if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_VISIBLE && !wParam) ||
-           (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_VISIBLE) && wParam))
-         {
-           return(0);
-         } 
-       ShowWindow(hWnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE);
-       break;
-      }
+/* Undocumented flags. */
+#define SWP_NOCLIENTMOVE          0x0800
+#define SWP_NOCLIENTSIZE          0x1000
 
-    case WM_CANCELMODE:
-      {
-       /* FIXME: Check for a desktop. */
-       if (GetCapture() == hWnd)
-         {
-           ReleaseCapture();
-         }
-       break;
-      }
+LRESULT
+DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
+{
+    RECT rect;
 
-    case WM_VKEYTOITEM:
-    case WM_CHARTOITEM:
-      return(-1);
+    GetClientRect(hWnd, &rect);
 
-    case WM_DROPOBJECT:
-      /* FIXME: Implement this. */
-      break;
+    if (!(Pos->flags & SWP_NOCLIENTMOVE))
+        SendMessageW(hWnd, WM_MOVE, 0, MAKELONG(rect.left, rect.top));
 
-    case WM_QUERYDROPOBJECT:
-      {
-       if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
-         {
-           return(1);
-         }
-       break;
-      }
+    if (!(Pos->flags & SWP_NOCLIENTSIZE))
+    {
+        WPARAM wp = SIZE_RESTORED;
+        if (IsZoomed(hWnd)) wp = SIZE_MAXIMIZED;
+        else if (IsIconic(hWnd)) wp = SIZE_MINIMIZED;
+        SendMessageW(hWnd, WM_SIZE, wp,
+            MAKELONG(rect.right - rect.left, rect.bottom - rect.top));
+    }
 
-    case WM_QUERYDRAGICON:
-      {
-       UINT Len;
-       HICON hIcon;
+    return 0;
+}
 
-       hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
-       if (hIcon)
-         {
-           return((LRESULT)hIcon);
-         }
-       for (Len = 1; Len < 64; Len++)
-         {
-           if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCE(Len))) != NULL)
-             {
-               return((LRESULT)hIcon);
-             }
-         }
-       return((LRESULT)LoadIconW(0, IDI_APPLICATION));
-      }
+/***********************************************************************
+ *           DefWndControlColor
+ *
+ * Default colors for control painting.
+ */
+static HBRUSH
+DefWndControlColor(HDC hDC, UINT ctlType)
+{
+  if (CTLCOLOR_SCROLLBAR == ctlType)
+    {
+      HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
+      COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
+      SetTextColor(hDC, GetSysColor(COLOR_3DFACE));
+      SetBkColor(hDC, bk);
+
+      /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
+       * we better use 0x55aa bitmap brush to make scrollbar's background
+       * look different from the window background.
+       */
+      if (bk == GetSysColor(COLOR_WINDOW))
+       {
+#if 0 /* FIXME */
+         return CACHE_GetPattern55AABrush();
+#else
+         return NULL;
+#endif
+       }
+      UnrealizeObject(hb);
+      return hb;
+    }
 
-      /* FIXME: WM_ISACTIVEICON */
+  SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
 
-    case WM_NOTIFYFORMAT:
-      {
-       if (IsWindowUnicode(hWnd))
-         {
-           return(NFR_UNICODE);
-         }
-       else
-         {
-           return(NFR_ANSI);
-         }
-      }
+  if ((CTLCOLOR_EDIT == ctlType) || (CTLCOLOR_LISTBOX == ctlType))
+    {
+      SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
+    }
+  else
+    {
+      SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
+      return GetSysColorBrush(COLOR_3DFACE);
+    }
 
-    case WM_SETICON:
-      {
-       INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
-       HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
-       SetClassLongW(hWnd, Index, lParam);
-       SetWindowPos(hWnd, 0, 0, 0, 0, 0, 
-                    SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
-                    SWP_NOACTIVATE | SWP_NOZORDER);
-       return((LRESULT)hOldIcon);
-      }
+  return GetSysColorBrush(COLOR_WINDOW);
+}
 
-    case WM_GETICON:
-      {
-       INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
-       return(GetClassLongW(hWnd, Index));
-      }
 
-    case WM_HELP:
-      {
-       if (bUnicode)
-         {
-           SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
-         }
-       else
-         {
-           SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
-         }
-       break;
-      }
+LRESULT STDCALL
+User32DefWindowProc(HWND hWnd,
+                   UINT Msg,
+                   WPARAM wParam,
+                   LPARAM lParam,
+                   BOOL bUnicode)
+{
+    switch (Msg)
+    {
+        case WM_NCPAINT:
+        {
+            return (DefWndPaintNC(hWnd, (HRGN)wParam));
+        }
+
+        case WM_NCCALCSIZE:
+        {
+            return (DefWndNCCalcSize(hWnd, (RECT*)lParam));
+        }
+
+        case WM_WINDOWPOSCHANGING:
+        {
+            return (DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
+        }
+
+        case WM_WINDOWPOSCHANGED:
+        {
+            return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));
+        }
+
+        case WM_NCHITTEST:
+        {
+            POINT Point;
+            Point.x = SLOWORD(lParam);
+            Point.y = SHIWORD(lParam);
+            return (DefWndHitTestNC(hWnd, Point));
+        }
+
+        case WM_NCLBUTTONDOWN:
+        {
+            return (DefWndHandleLButtonDownNC(hWnd, wParam, lParam));
+        }
+
+        case WM_NCLBUTTONUP:
+        {
+            return (DefWndHandleLButtonUpNC(hWnd, wParam, lParam));
+        }
+
+        case WM_LBUTTONDBLCLK:
+        case WM_NCLBUTTONDBLCLK:
+        {
+            return (DefWndHandleLButtonDblClkNC(hWnd, wParam, lParam));
+        }
+
+        case WM_NCRBUTTONDOWN:
+        {
+            if (wParam == HTCAPTION)
+            {
+                SetCapture(hWnd);
+            }
+            break;
+        }
+
+        case WM_RBUTTONUP:
+        {
+            POINT Pt;
+            if (hWnd == GetCapture())
+            {
+                ReleaseCapture();
+            }
+            Pt.x = SLOWORD(lParam);
+            Pt.y = SHIWORD(lParam);
+            ClientToScreen(hWnd, &Pt);
+            lParam = MAKELPARAM(Pt.x, Pt.y);
+            if (bUnicode)
+            {
+                SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
+            }
+            else
+            {
+                SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
+            }
+            break;
+        }
+
+        case WM_CONTEXTMENU:
+        {
+            if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
+            {
+                if (bUnicode)
+                {
+                    SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
+                }
+                else
+                {
+                    SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
+                }
+            }
+            else
+            {
+                LONG HitCode;
+                POINT Pt;
+
+                Pt.x = SLOWORD(lParam);
+                Pt.y = SHIWORD(lParam);
+                if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
+                {
+                    ScreenToClient(GetParent(hWnd), &Pt);
+                }
+
+                HitCode = DefWndHitTestNC(hWnd, Pt);
+
+                if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
+                {
+                    TrackPopupMenu(GetSystemMenu(hWnd, FALSE),
+                                   TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
+                                   Pt.x, Pt.y, 0, hWnd, NULL);
+                }
+               }
+            break;
+        }
+
+        case WM_NCACTIVATE:
+        {
+            return (DefWndHandleActiveNC(hWnd, wParam));
+        }
+
+        case WM_PRINT:
+        {
+            /* FIXME: Implement. */
+            return (0);
+        }
+
+        case WM_PAINTICON:
+        case WM_PAINT:
+        {
+            PAINTSTRUCT Ps;
+            HDC hDC = BeginPaint(hWnd, &Ps);
+            if (hDC)
+            {          
+                HICON hIcon;
+                if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
+                    (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
+                {
+                    RECT WindowRect;
+                    INT x, y;
+                    GetWindowRect(hWnd, &WindowRect);
+                    x = (WindowRect.right - WindowRect.left -
+                         GetSystemMetrics(SM_CXICON)) / 2;
+                    y = (WindowRect.bottom - WindowRect.top -
+                         GetSystemMetrics(SM_CYICON)) / 2;
+                    DrawIcon(hDC, x, y, hIcon);
+                } 
+                if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
+                {
+                    RECT WindowRect;
+                    GetClientRect(hWnd, &WindowRect);
+                    DrawEdge(hDC, &WindowRect, EDGE_SUNKEN, BF_RECT);
+                }
+                EndPaint(hWnd, &Ps);
+            }
+            return (0);
+        }
+
+        case WM_SYNCPAINT:
+        {
+            HRGN hRgn;
+            hRgn = CreateRectRgn(0, 0, 0, 0);
+            if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
+            {
+                RedrawWindow(hWnd, NULL, hRgn,
+                               RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
+                    RDW_ALLCHILDREN);
+            }
+            DeleteObject(hRgn);
+            return (0);
+        }
+
+        case WM_SETREDRAW:
+        {
+            DefWndSetRedraw(hWnd, wParam);
+            return (0);
+        }
+
+        case WM_CLOSE:
+        {
+            DestroyWindow(hWnd);
+            return (0);
+        }
+
+        case WM_MOUSEACTIVATE:
+        {
+            if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
+            {
+                LONG Ret;
+                if (bUnicode)
+                {
+                    Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
+                                       wParam, lParam);
+                }
+                else
+                {
+                    Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
+                                       wParam, lParam);
+                }
+                if (Ret)
+                {
+                    return (Ret);
+                }
+            }
+            return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
+        }
+
+        case WM_ACTIVATE:
+        {
+            /* Check if the window is minimized. */
+            if (LOWORD(lParam) != WA_INACTIVE &&
+                !(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
+            {
+                SetFocus(hWnd);
+            }
+            break;
+        }
+
+        case WM_MOUSEWHEEL:
+        {
+            if (GetWindowLongW(hWnd, GWL_STYLE & WS_CHILD))
+            {
+                if (bUnicode)
+                {
+                    return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
+                                         wParam, lParam));
+                }
+                else
+                {
+                    return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
+                                         wParam, lParam));
+                }
+            }
+            break;
+        }
+
+        case WM_ERASEBKGND:
+        case WM_ICONERASEBKGND:
+        {
+            RECT Rect;
+            HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
+
+            if (NULL == hBrush)
+            {
+                return 0;
+            }
+            if (0 == (((DWORD) hBrush) & 0xffff0000))
+            {
+                hBrush = GetSysColorBrush((DWORD) hBrush - 1);
+            }
+            GetClipBox((HDC)wParam, &Rect);
+            FillRect((HDC)wParam, &Rect, hBrush);
+            return (1);
+        }
+
+        case WM_CTLCOLORMSGBOX:
+        case WM_CTLCOLOREDIT:
+        case WM_CTLCOLORLISTBOX:
+        case WM_CTLCOLORBTN:
+        case WM_CTLCOLORDLG:
+        case WM_CTLCOLORSTATIC:
+        case WM_CTLCOLORSCROLLBAR:
+           return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
+
+        case WM_SETCURSOR:
+        {
+            if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
+            {
+                if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
+                {
+                    BOOL bResult;
+                    if (bUnicode)
+                    {
+                        bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
+                                               wParam, lParam);
+                    }
+                    else
+                    {
+                        bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
+                                               wParam, lParam);
+                    }
+                    if (bResult)
+                    {
+                        return(TRUE);
+                    }
+                }
+            }
+            return (DefWndHandleSetCursor(hWnd, wParam, lParam));
+        }
+
+        case WM_SYSCOMMAND:
+        {
+            POINT Pt;
+            Pt.x = SLOWORD(lParam);
+            Pt.y = SHIWORD(lParam);
+            return (DefWndHandleSysCommand(hWnd, wParam, Pt));
+        }
+
+        /* FIXME: Handle key messages. */
+/*
+        case WM_KEYDOWN:
+        case WM_KEYUP:
+        case WM_SYSKEYUP:
+        case WM_SYSCHAR:
+*/
+
+        /* FIXME: This is also incomplete. */
+        case WM_SYSKEYDOWN:
+        {
+            if (HIWORD(lParam) & KEYDATA_ALT)
+            {
+                if (wParam == VK_F4) /* Try to close the window */
+                {
+                    HWND top = GetAncestor(hWnd, GA_ROOT);
+                    if (!(GetClassLongW(top, GCL_STYLE) & CS_NOCLOSE))
+                    {
+                        if (bUnicode)
+                            PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
+                        else
+                            PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
+                    }
+                   }
+            }
+            break;
+        }
+        
+        case WM_SHOWWINDOW:
+        {
+            LONG Style;
+
+            if (!lParam)
+                return 0;
+            Style = GetWindowLongW(hWnd, GWL_STYLE);
+            if (!(Style & WS_POPUP))
+                return 0;
+            if ((Style & WS_VISIBLE) && wParam)
+                return 0;
+            if (!(Style & WS_VISIBLE) && !wParam)
+                return 0;
+            if (!GetWindow(hWnd, GW_OWNER))
+                return 0;
+            ShowWindow(hWnd, wParam ? SW_SHOWNA : SW_HIDE);
+            break;
+        }
+
+        case WM_CANCELMODE:
+        {
+            /* FIXME: Check for a desktop. */
+            if (GetCapture() == hWnd)
+            {
+                ReleaseCapture();
+            }
+            break;
+        }
+
+        case WM_VKEYTOITEM:
+        case WM_CHARTOITEM:
+            return (-1);
+
+        case WM_DROPOBJECT:
+            /* FIXME: Implement this. */
+            break;
+
+        case WM_QUERYDROPOBJECT:
+        {
+            if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
+            {
+                return(1);
+            }
+            break;
+        }
+
+        case WM_QUERYDRAGICON:
+        {
+            UINT Len;
+            HICON hIcon;
+
+            hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
+            if (hIcon)
+            {
+                return ((LRESULT)hIcon);
+            }
+            for (Len = 1; Len < 64; Len++)
+            {
+                if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
+                {
+                    return((LRESULT)hIcon);
+                }
+            }
+            return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
+        }
+
+        /* FIXME: WM_ISACTIVEICON */
+
+        case WM_NOTIFYFORMAT:
+        {
+            if (IsWindowUnicode(hWnd))
+            {
+                return(NFR_UNICODE);
+            }
+            else
+            {
+                return(NFR_ANSI);
+            }
+        }
+
+        case WM_SETICON:
+        {
+           INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
+           HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
+           SetClassLongW(hWnd, Index, lParam);
+           SetWindowPos(hWnd, 0, 0, 0, 0, 0,
+                      SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
+                      SWP_NOACTIVATE | SWP_NOZORDER);
+           return ((LRESULT)hOldIcon);
+        }
+
+        case WM_GETICON:
+        {
+            INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
+            return (GetClassLongW(hWnd, Index));
+        }
+
+        case WM_HELP:
+        {
+            if (bUnicode)
+            {
+                SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
+            }
+            else
+            {
+                SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
+            }
+            break;
+        }
+
+        case WM_QUERYOPEN:
+        case WM_QUERYENDSESSION:
+        {
+            return (1);
+        }
     }
-  return 0;
+    return 0;
 }
 
+
 LRESULT STDCALL
 DefWindowProcA(HWND hWnd,
               UINT Msg,
               WPARAM wParam,
               LPARAM lParam)
 {
-  LRESULT Result;
-  static LPSTR WindowTextAtom = 0;
-  PSTR WindowText;
+    static LPSTR WindowTextAtom = 0;
+    PSTR WindowText;
 
-  switch (Msg)
+    switch (Msg)
     {
-    case WM_NCCREATE:
-      {
-       CREATESTRUCTA* Cs = (CREATESTRUCTA*)lParam;
-       if (HIWORD(Cs->lpszName))
-         {
-           WindowTextAtom = 
-             (LPSTR)(ULONG)GlobalAddAtomA("USER32!WindowTextAtomA");
-           WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
-                                        strlen(Cs->lpszName) * sizeof(CHAR));
-           strcpy(WindowText, Cs->lpszName);
-           SetPropA(hWnd, WindowTextAtom, WindowText);
-         }
-       return(1);
-      }
-
-    case WM_NCCALCSIZE:
-      {
-       return(DefWndNCCalcSize(hWnd, (RECT*)lParam));
-      }
-
-    case WM_WINDOWPOSCHANGING:
-      {
-       return(DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
-      }
-
-    case WM_GETTEXTLENGTH:
-      {
-       if (WindowTextAtom == 0 ||
-           (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
-         {
-           return(0);
-         }
-       return(strlen(WindowText));
-      }
-
-    case WM_GETTEXT:
-      {
-       if (WindowTextAtom == 0 ||
-           (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
-         {
-           if (wParam > 1)
-             {
-               ((PSTR)lParam) = '\0';
-             }
-           return(0);
-         }
-       strncpy((LPSTR)lParam, WindowText, wParam);
-       return(min(wParam, strlen(WindowText)));
-      }
-
-    case WM_SETTEXT:
-      {
-       if (WindowTextAtom != 0)
-         {
-           WindowTextAtom = 
-             (LPSTR)(DWORD)GlobalAddAtomA("USER32!WindowTextAtomW");       
-         }
-       if (WindowTextAtom != 0 &&
-           (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
-         {
-           RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
-         }
-       WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
-                                    strlen((PSTR)lParam) * sizeof(CHAR));
-       strcpy(WindowText, (PSTR)lParam);
-       SetPropA(hWnd, WindowTextAtom, WindowText);
-      }
-
-    case WM_NCDESTROY:
-      {
-       if (WindowTextAtom != 0 &&
-           (WindowText = RemovePropA(hWnd, WindowTextAtom)) == NULL)
-         {
-           RtlFreeHeap(GetProcessHeap(), 0, WindowText);
-         }
-       if (WindowTextAtom != 0)
-         {
-           GlobalDeleteAtom((ATOM)(ULONG)WindowTextAtom);
-         }
-       /* FIXME: Destroy scroll bars here as well. */
-       return(0);
-      }
-
-    default:
-      Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
-      break;
+        case WM_NCCREATE:
+        {
+            CREATESTRUCTA *Cs = (CREATESTRUCTA*)lParam;
+            if (HIWORD(Cs->lpszName))
+            {
+                if (0 == WindowTextAtom)
+                {
+                    WindowTextAtom =
+                        (LPSTR)(ULONG)GlobalAddAtomA("USER32!WindowTextAtomA");
+                }
+                WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
+                    strlen(Cs->lpszName) * sizeof(CHAR));
+                strcpy(WindowText, Cs->lpszName);
+                SetPropA(hWnd, WindowTextAtom, WindowText);
+               }
+            return (1);
+        }
+
+        case WM_GETTEXTLENGTH:
+        {
+            if (WindowTextAtom == 0 ||
+                (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
+            {
+                return(0);
+            }
+            return (strlen(WindowText));
+        }
+
+        case WM_GETTEXT:
+        {
+            if (WindowTextAtom == 0 ||
+                (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
+            {
+                if (wParam > 1)
+                   {
+                    *((PSTR)lParam) = '\0';
+                }
+                return (0);
+            }
+            strncpy((LPSTR)lParam, WindowText, wParam);
+            return (min(wParam, strlen(WindowText)));
+        }
+
+        case WM_SETTEXT:
+        {
+            if (0 == WindowTextAtom)
+            {
+                WindowTextAtom =
+                    (LPSTR)(DWORD)GlobalAddAtomA("USER32!WindowTextAtomA");
+               }
+            if (WindowTextAtom != 0 &&
+                (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
+               {
+                RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
+            }
+            WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
+                (strlen((PSTR)lParam) + 1) * sizeof(CHAR));
+            strcpy(WindowText, (PSTR)lParam);
+            SetPropA(hWnd, WindowTextAtom, WindowText);
+            if (0 != (GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION))
+               {
+                DefWndPaintNC(hWnd, (HRGN) 1);
+            }
+            return (1);
+        }
+
+/*
+        FIXME: Implement these.
+        case WM_IME_CHAR:
+        case WM_IME_KEYDOWN:
+        case WM_IME_KEYUP:
+        case WM_IME_STARTCOMPOSITION:
+        case WM_IME_COMPOSITION:
+        case WM_IME_ENDCOMPOSITION:
+        case WM_IME_SELECT:
+        case WM_IME_SETCONTEXT:
+*/
+
+        case WM_NCDESTROY:
+        {
+            if (WindowTextAtom != 0 &&
+                (WindowText = RemovePropA(hWnd, WindowTextAtom)) == NULL)
+            {
+                RtlFreeHeap(GetProcessHeap(), 0, WindowText);
+            }
+            return(0);
+        }
     }
 
-  return(Result);
+    return User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
 }
 
+
 LRESULT STDCALL
 DefWindowProcW(HWND hWnd,
               UINT Msg,
               WPARAM wParam,
               LPARAM lParam)
 {
-  LRESULT Result;
-  static LPWSTR WindowTextAtom = 0;
-  PWSTR WindowText;
+    static LPWSTR WindowTextAtom = 0;
+    PWSTR WindowText;
 
-  switch (Msg)
+    switch (Msg)
     {
-    case WM_NCCREATE:
-      {
-       CREATESTRUCTW* Cs = (CREATESTRUCTW*)lParam;
-       if (HIWORD(Cs->lpszName))
-         {
-           WindowTextAtom = 
-             (LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
-           WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
-                                        wcslen(Cs->lpszName) * sizeof(WCHAR));
-           wcscpy(WindowText, Cs->lpszName);
-           SetPropW(hWnd, WindowTextAtom, WindowText);
-         }
-       return(1);
-      }
-
-    case WM_NCCALCSIZE:
-      {
-       return(DefWndNCCalcSize(hWnd, (RECT*)lParam));
-      }
-
-    case WM_WINDOWPOSCHANGING:
-      {
-       return(DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
-      }
-
-    case WM_GETTEXTLENGTH:
-      {
-       if (WindowTextAtom == 0 ||
-           (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
-         {
-           return(0);
-         }
-       return(wcslen(WindowText));
-      }
-
-    case WM_GETTEXT:
-      {
-       if (WindowTextAtom == 0 ||
-           (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
-         {
-           if (wParam > 1)
-             {
-               ((PWSTR)lParam) = '\0';
-             }
-           return(0);
-         }
-       wcsncpy((PWSTR)lParam, WindowText, wParam);
-       return(min(wParam, wcslen(WindowText)));
-      }
-
-    case WM_SETTEXT:
-      {
-       if (WindowTextAtom != 0)
-         {
-           WindowTextAtom = 
-             (LPWSTR)(DWORD)GlobalAddAtom(L"USER32!WindowTextAtomW");      
-         }
-       if (WindowTextAtom != 0 &&
-           (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
-         {
-           RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
-         }
-       WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
-                                    wcslen((PWSTR)lParam) * sizeof(WCHAR));
-       wcscpy(WindowText, (PWSTR)lParam);
-       SetPropW(hWnd, WindowTextAtom, WindowText);
-      }
-
-    case WM_NCDESTROY:
-      {
-       if (WindowTextAtom != 0 &&
-           (WindowText = RemovePropW(hWnd, WindowTextAtom)) == NULL)
-         {
-           RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
-         }
-       if (WindowTextAtom != 0)
-         {
-           GlobalDeleteAtom((ATOM)(DWORD)WindowTextAtom);
-         }
-       /* FIXME: Destroy scroll bars here as well. */
-       return(0);
-      }
-
-    default:
-      Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
-      break;
+        case WM_NCCREATE:
+        {
+            CREATESTRUCTW* CreateStruct = (CREATESTRUCTW*)lParam;
+            if (HIWORD(CreateStruct->lpszName))
+            {
+                if (0 == WindowTextAtom)
+                {
+                    WindowTextAtom =
+                        (LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
+                }
+                WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
+                               wcslen(CreateStruct->lpszName) * sizeof(WCHAR));
+                wcscpy(WindowText, CreateStruct->lpszName);
+                SetPropW(hWnd, WindowTextAtom, WindowText);
+            }
+            return (1);
+        }
+
+        case WM_GETTEXTLENGTH:
+        {
+            if (WindowTextAtom == 0 ||
+                (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
+            {
+                return(0);
+            }
+            return (wcslen(WindowText));
+        }
+
+        case WM_GETTEXT:
+        {
+            if (WindowTextAtom == 0 ||
+                (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
+            {
+               if (wParam > 1)
+               {
+                   ((PWSTR)lParam) = '\0';
+               }
+               return (0);
+            }
+            wcsncpy((PWSTR)lParam, WindowText, wParam);
+            return (min(wParam, wcslen(WindowText)));
+        }
+
+        case WM_SETTEXT:
+        {
+            if (WindowTextAtom == 0)
+            {
+                WindowTextAtom =
+                    (LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
+            }
+            if (WindowTextAtom != 0 &&
+                (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
+            {
+                RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
+            }
+            WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
+                           (wcslen((PWSTR)lParam) + 1) * sizeof(WCHAR));
+            wcscpy(WindowText, (PWSTR)lParam);
+            SetPropW(hWnd, WindowTextAtom, WindowText);
+            if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
+               {
+                DefWndPaintNC(hWnd, (HRGN)1);
+            }
+            return (1);
+        }
+
+        case WM_IME_CHAR:
+        {
+            SendMessageW(hWnd, WM_CHAR, wParam, lParam);
+            return (0);
+        }
+
+        case WM_IME_SETCONTEXT:
+        {
+            /* FIXME */
+            return (0);
+        }
+
+        case WM_NCDESTROY:
+        {
+            if (WindowTextAtom != 0 &&
+                (WindowText = RemovePropW(hWnd, WindowTextAtom)) == NULL)
+            {
+                RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
+            }
+            return (0);
+        }
     }
 
-  return(Result);
+    return User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
 }