update for HEAD-2003091401
[reactos.git] / lib / user32 / windows / defwnd.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS user32.dll
5  * FILE:            lib/user32/windows/window.c
6  * PURPOSE:         Window management
7  * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
8  * UPDATE HISTORY:
9  *      06-06-2001  CSH  Created
10  */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <windows.h>
15 #include <user32.h>
16 #include <window.h>
17 #include <user32/wininternal.h>
18 #include <string.h>
19 #include <menu.h>
20 #include <cursor.h>
21 #include <winpos.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 /* GLOBALS *******************************************************************/
27
28 static HBITMAP hbSysMenu;
29 /* TODO:  widgets will be cached here.
30 static HBITMAP hbClose;
31 static HBITMAP hbCloseD;
32 static HBITMAP hbMinimize;
33 static HBITMAP hbMinimizeD;
34 static HBITMAP hbRestore;
35 static HBITMAP hbRestoreD;
36 static HBITMAP hbMaximize;
37 static HBITMAP hbScrUp;
38 static HBITMAP hbScrDwn;
39 static HBITMAP hbScrLeft;
40 static HBITMAP hbScrRight;
41 */
42
43
44 static COLORREF SysColours[29] =
45   {
46     RGB(224, 224, 224) /* COLOR_SCROLLBAR */,
47     RGB(58, 110, 165) /* COLOR_BACKGROUND */,
48     RGB(0, 0, 128) /* COLOR_ACTIVECAPTION */,
49     RGB(128, 128, 128) /* COLOR_INACTIVECAPTION */,
50     RGB(192, 192, 192) /* COLOR_MENU */,
51     RGB(255, 255, 255) /* COLOR_WINDOW */,
52     RGB(0, 0, 0) /* COLOR_WINDOWFRAME */,
53     RGB(0, 0, 0) /* COLOR_MENUTEXT */,
54     RGB(0, 0, 0) /* COLOR_WINDOWTEXT */,
55     RGB(255, 255, 255) /* COLOR_CAPTIONTEXT */,
56     RGB(128, 128, 128) /* COLOR_ACTIVEBORDER */,
57     RGB(255, 255, 255) /* COLOR_INACTIVEBORDER */,
58     RGB(255, 255, 232) /* COLOR_APPWORKSPACE */,
59     RGB(224, 224, 224) /* COLOR_HILIGHT */,
60     RGB(0, 0, 128) /* COLOR_HILIGHTTEXT */,
61     RGB(192, 192, 192) /* COLOR_BTNFACE */,
62     RGB(128, 128, 128) /* COLOR_BTNSHADOW */,
63     RGB(192, 192, 192) /* COLOR_GRAYTEXT */,
64     RGB(0, 0, 0) /* COLOR_BTNTEXT */,
65     RGB(192, 192, 192) /* COLOR_INACTIVECAPTIONTEXT */,
66     RGB(255, 255, 255) /* COLOR_BTNHILIGHT */,
67     RGB(32, 32, 32) /* COLOR_3DDKSHADOW */,
68     RGB(192, 192, 192) /* COLOR_3DLIGHT */,
69     RGB(0, 0, 0) /* COLOR_INFOTEXT */,
70     RGB(255, 255, 192) /* COLOR_INFOBK */,
71     RGB(184, 180, 184) /* COLOR_ALTERNATEBTNFACE */,
72     RGB(0, 0, 255) /* COLOR_HOTLIGHT */,
73     RGB(16, 132, 208) /* COLOR_GRADIENTACTIVECAPTION */,
74     RGB(181, 181, 181) /* COLOR_GRADIENTINACTIVECAPTION */,
75   };
76
77 static ATOM AtomInternalPos;
78
79 /* Bits in the dwKeyData */
80 #define KEYDATA_ALT   0x2000
81
82 /* FUNCTIONS *****************************************************************/
83
84 BOOL
85 IsMaxBoxActive(HWND hWnd)
86 {
87     ULONG uStyle = GetWindowLongW(hWnd, GWL_STYLE);
88     return (uStyle & WS_MAXIMIZEBOX);
89 }
90
91 BOOL
92 IsCloseBoxActive(HWND hWnd)
93 {
94     ULONG uStyle = GetWindowLongW(hWnd, GWL_STYLE);
95     return (uStyle & WS_SYSMENU);
96 }
97
98 BOOL
99 IsMinBoxActive(HWND hWnd)
100 {
101     ULONG uStyle = GetWindowLongW(hWnd, GWL_STYLE);
102     return (uStyle & WS_MINIMIZEBOX);
103 }
104
105 INT
106 UIGetFrameSizeX(HWND hWnd)
107 {
108     ULONG uStyle = GetWindowLongW(hWnd, GWL_STYLE);
109
110     if ( uStyle & WS_THICKFRAME )
111         return GetSystemMetrics(SM_CXSIZEFRAME);
112     else
113         return GetSystemMetrics(SM_CXFRAME);
114 }
115
116 INT
117 UIGetFrameSizeY(HWND hWnd)
118 {
119     ULONG uStyle = GetWindowLongW(hWnd, GWL_STYLE);
120
121     if (uStyle & WS_THICKFRAME)
122         return GetSystemMetrics(SM_CYSIZEFRAME);
123     else
124         return GetSystemMetrics(SM_CYFRAME);
125 }
126
127 VOID
128 UserSetupInternalPos(VOID)
129 {
130     LPSTR Str = "SysIP";
131     AtomInternalPos = GlobalAddAtomA(Str);
132 }
133
134 /*
135  * @implemented
136  */
137 DWORD STDCALL
138 GetSysColor(int nIndex)
139 {
140     return SysColours[nIndex];
141 }
142
143 /*
144  * @implemented
145  */
146 HPEN STDCALL
147 GetSysColorPen(int nIndex)
148 {
149     return CreatePen(PS_SOLID, 1, SysColours[nIndex]);
150 }
151
152 /*
153  * @implemented
154  */
155 HBRUSH STDCALL
156 GetSysColorBrush(int nIndex)
157 {
158     return CreateSolidBrush(SysColours[nIndex]);
159 }
160
161 /*
162  * @unimplemented
163  */
164 LRESULT STDCALL
165 DefFrameProcA( HWND hWnd,
166               HWND hWndMDIClient,
167               UINT uMsg,
168               WPARAM wParam,
169               LPARAM lParam )
170 {
171     UNIMPLEMENTED;
172     return ((LRESULT)0);
173 }
174
175 /*
176  * @unimplemented
177  */
178 LRESULT STDCALL
179 DefFrameProcW(HWND hWnd,
180               HWND hWndMDIClient,
181               UINT uMsg,
182               WPARAM wParam,
183               LPARAM lParam)
184 {
185     UNIMPLEMENTED;
186     return ((LRESULT)0);
187 }
188
189 PINTERNALPOS
190 UserGetInternalPos(HWND hWnd)
191 {
192     PINTERNALPOS lpPos;
193     lpPos = (PINTERNALPOS)GetPropA(hWnd, (LPSTR)(DWORD)AtomInternalPos);
194     return(lpPos);
195 }
196
197 BOOL
198 DefWndRedrawIconTitle(HWND hWnd)
199 {
200     PINTERNALPOS lpPos = (PINTERNALPOS)GetPropA(hWnd, (LPSTR)(DWORD)AtomInternalPos);
201
202     if (lpPos != NULL)
203     {
204         if (lpPos->IconTitle != NULL)
205         {
206             SendMessageA(lpPos->IconTitle, WM_SHOWWINDOW, TRUE, 0);
207             InvalidateRect(lpPos->IconTitle, NULL, TRUE);
208             return(TRUE);
209         }
210     }
211     return(FALSE);
212 }
213
214 BOOL
215 UserHasMenu(HWND hWnd, ULONG Style)
216 {
217     return (!(Style & WS_CHILD) && GetMenu(hWnd) != 0);
218 }
219
220 ULONG
221 UserHasAnyFrameStyle(ULONG Style, ULONG ExStyle)
222 {
223     return ((Style & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) ||
224             (ExStyle & WS_EX_DLGMODALFRAME) ||
225             (!(Style & (WS_CHILD | WS_POPUP))));
226 }
227
228 ULONG
229 UserHasDlgFrameStyle(ULONG Style, ULONG ExStyle)
230 {
231     return ((ExStyle & WS_EX_DLGMODALFRAME) ||
232             ((Style & WS_DLGFRAME) && (!(Style & WS_THICKFRAME))));
233 }
234
235 ULONG
236 UserHasThickFrameStyle(ULONG Style, ULONG ExStyle)
237 {
238     return ((Style & WS_THICKFRAME) &&
239             (!((Style & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)));
240 }
241
242 ULONG
243 UserHasThinFrameStyle(ULONG Style, ULONG ExStyle)
244 {
245     return ((Style & WS_BORDER) || (!(Style & (WS_CHILD | WS_POPUP))));
246 }
247
248 ULONG
249 UserHasBigFrameStyle(ULONG Style, ULONG ExStyle)
250 {
251     return ((Style & (WS_THICKFRAME | WS_DLGFRAME)) ||
252             (ExStyle & WS_EX_DLGMODALFRAME));
253 }
254
255 void
256 UserGetInsideRectNC(HWND hWnd, RECT *rect)
257 {
258     RECT WindowRect;
259     ULONG Style;
260     ULONG ExStyle;
261
262     Style = GetWindowLongW(hWnd, GWL_STYLE);
263     ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
264     GetWindowRect(hWnd, &WindowRect);
265     rect->top    = rect->left = 0;
266     rect->right  = WindowRect.right - WindowRect.left;
267     rect->bottom = WindowRect.bottom - WindowRect.top;
268
269     if (Style & WS_ICONIC)
270     {
271         return;
272     }
273
274     /* Remove frame from rectangle */
275     if (UserHasThickFrameStyle(Style, ExStyle ))
276     {
277         InflateRect(rect, -GetSystemMetrics(SM_CXFRAME),
278                     -GetSystemMetrics(SM_CYFRAME));
279     }
280     else
281     {
282         if (UserHasDlgFrameStyle(Style, ExStyle ))
283         {
284             InflateRect(rect, -GetSystemMetrics(SM_CXDLGFRAME),
285                         -GetSystemMetrics(SM_CYDLGFRAME));
286             /* FIXME: this isn't in NC_AdjustRect? why not? */
287             if (ExStyle & WS_EX_DLGMODALFRAME)
288                     InflateRect( rect, -1, 0 );
289         }
290         else
291         {
292             if (UserHasThinFrameStyle(Style, ExStyle))
293             {
294                 InflateRect(rect, -GetSystemMetrics(SM_CXBORDER),
295                             -GetSystemMetrics(SM_CYBORDER));
296             }
297         }
298     }
299 }
300
301 WINBOOL
302 UserDrawSysMenuButton(HWND hWnd, HDC hDC, LPRECT Rect, BOOL down)
303 {
304     HDC hDcMem;
305     HBITMAP hSavedBitmap;
306
307     if (!hbSysMenu)
308     {
309         hbSysMenu = (HBITMAP)LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
310     }
311     hDcMem = CreateCompatibleDC(hDC);
312     if (!hDcMem)
313     {
314         return FALSE;
315     }
316     hSavedBitmap = SelectObject(hDcMem, hbSysMenu);
317     if (!hSavedBitmap)
318     {
319         DeleteDC(hDcMem);
320         return FALSE;
321     }
322
323     BitBlt(hDC, Rect->left + 2, Rect->top + 3, 16, 14, hDcMem,
324            (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD) ?
325                 GetSystemMetrics(SM_CXSIZE): 0, 0, SRCCOPY);
326
327     SelectObject(hDcMem, hSavedBitmap);
328     DeleteDC(hDcMem);
329     return TRUE;
330 }
331
332 /*
333  * FIXME:
334  * Cache bitmaps, then just bitblt instead of calling DFC() (and
335  * wasting precious CPU cycles) every time
336  */
337 static void
338 UserDrawCaptionButton(HWND hWnd, HDC hDC, BOOL bDown, ULONG Type)
339 {
340     RECT rect;
341     INT iBmpWidth = GetSystemMetrics(SM_CXSIZE) - 2;
342     INT iBmpHeight = GetSystemMetrics(SM_CYSIZE) - 4;
343     INT OffsetX = UIGetFrameSizeX(hWnd);
344     INT OffsetY = UIGetFrameSizeY(hWnd);
345
346     if (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_SYSMENU))
347     {
348         return;
349     }
350
351     GetWindowRect(hWnd, &rect);
352
353     rect.right = rect.right - rect.left;
354     rect.bottom = rect.bottom - rect.top;
355     rect.left = rect.top = 0;
356
357     switch(Type)
358     {
359         case DFCS_CAPTIONMIN:
360         {
361             if ((GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) == TRUE)
362                 return; /* ToolWindows don't have min/max buttons */
363
364             SetRect(&rect, rect.right - OffsetX - (iBmpWidth * 3) - 5,
365                     OffsetY + 2, rect.right - (iBmpWidth * 2) - OffsetX - 5,
366                     rect.top + iBmpHeight + OffsetY + 2);
367             DrawFrameControl(hDC, &rect, DFC_CAPTION,
368                              DFCS_CAPTIONMIN | (bDown ? DFCS_PUSHED : 0) |
369                              (IsMinBoxActive(hWnd) ? 0 : DFCS_INACTIVE));
370             break;
371         }
372         case DFCS_CAPTIONMAX:
373         {
374             if ((GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) == TRUE)
375                 return; /* ToolWindows don't have min/max buttons */
376
377             SetRect(&rect, rect.right - OffsetX - (iBmpWidth * 2) - 5,
378                     OffsetY + 2, rect.right - iBmpWidth - OffsetX - 5,
379                     rect.top + iBmpHeight + OffsetY + 2);
380             DrawFrameControl(hDC, &rect, DFC_CAPTION,
381                              (IsZoomed(hWnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX) |
382                              (bDown ? DFCS_PUSHED : 0) |
383                              (IsMaxBoxActive(hWnd) ? 0 : DFCS_INACTIVE));
384             break;
385         }
386         case DFCS_CAPTIONCLOSE:
387         {
388             SetRect(&rect, rect.right - OffsetX - iBmpWidth - 3,
389                     OffsetY + 2,        rect.right - OffsetX - 3,
390                     rect.top + iBmpHeight + OffsetY + 2 );      
391             DrawFrameControl(hDC, &rect, DFC_CAPTION,
392                              (DFCS_CAPTIONCLOSE | (bDown ? DFCS_PUSHED : 0) |
393                              (IsCloseBoxActive(hWnd) ? 0 : DFCS_INACTIVE)));
394             break;
395         }
396     }
397 }
398
399 // Enabling this will cause captions to draw smoother, but slower:
400 // #define DOUBLE_BUFFER_CAPTION
401 // NOTE: Double buffering appears to be broken for this at the moment
402
403 /*
404  * @implemented
405  */
406 WINBOOL STDCALL
407 DrawCaption(
408   HWND hWnd,
409   HDC hDC,
410   LPRECT lprc,
411   UINT uFlags)
412 {
413     NONCLIENTMETRICSW nclm;
414     BOOL result = FALSE;
415     RECT r = *lprc;
416     UINT VCenter = 0, Padding = 0, Height;
417     WCHAR buffer[256];
418     HFONT hFont = NULL;
419     HFONT hOldFont = NULL;
420     HBRUSH OldBrush = NULL;
421     HDC MemDC = NULL;
422     int ButtonWidth;
423
424 #ifdef DOUBLE_BUFFER_CAPTION
425     HBITMAP MemBMP = NULL, OldBMP = NULL;
426
427     MemDC = CreateCompatibleDC(hDC);
428     if (! MemDC) goto cleanup;
429     MemBMP = CreateCompatibleBitmap(hDC, lprc->right - lprc->left, lprc->bottom - lprc->top);
430     if (! MemBMP) goto cleanup;
431     OldBMP = SelectObject(MemDC, MemBMP);
432     if (! OldBMP) goto cleanup;
433 #else
434     MemDC = hDC;
435
436     OffsetViewportOrgEx(MemDC, lprc->left, lprc->top, NULL);
437 #endif
438
439     // If DC_GRADIENT is specified, a Win 98/2000 style caption gradient should
440     // be painted. For now, that flag is ignored:
441     // Windows 98/Me, Windows 2000/XP: When this flag is set, the function uses
442     // COLOR_GRADIENTACTIVECAPTION (if the DC_ACTIVE flag was set) or
443     // COLOR_GRADIENTINACTIVECAPTION for the title-bar color. 
444
445     // Draw the caption background
446     if (uFlags & DC_INBUTTON)
447     {
448         OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_BTNFACE : COLOR_BTNSHADOW) );
449         if (! OldBrush) goto cleanup;
450         if (! PatBlt(MemDC, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top, PATCOPY )) goto cleanup;
451     }
452     else
453     {
454         // DC_GRADIENT check should go here somewhere
455         OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
456         if (! OldBrush) goto cleanup;
457         if (! PatBlt(MemDC, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top, PATCOPY )) goto cleanup;
458     }
459     
460     /* Windows behaves like this */
461     Height = GetSystemMetrics(SM_CYCAPTION) - 1;
462
463     VCenter = (lprc->bottom - lprc->top) / 2;
464     Padding = VCenter - (Height / 2);
465
466     r.left = Padding;
467     r.right = r.left + (lprc->right - lprc->left);
468     r.top = Padding;
469     r.bottom = r.top + (Height / 2);
470
471     if (uFlags & DC_ICON)
472     {
473         // For some reason the icon isn't centered correctly...
474         r.top --;
475         UserDrawSysMenuButton(hWnd, MemDC, &r, FALSE);
476         r.top ++;
477     }
478
479     r.top ++;
480     r.left += 2;
481
482   if ((uFlags & DC_TEXT) && (GetWindowTextW( hWnd, buffer, sizeof(buffer)/sizeof(buffer[0]) )))
483   {
484     // Duplicate odd behaviour from Windows:
485     if ((! uFlags & DC_SMALLCAP) || (uFlags & DC_ICON) || (uFlags & DC_INBUTTON) ||
486         (! uFlags & DC_ACTIVE))
487         r.left += GetSystemMetrics(SM_CXSIZE) + Padding;
488
489     r.right = (lprc->right - lprc->left);
490     ButtonWidth = GetSystemMetrics(SM_CXSIZE) - 2;
491     if (GetWindowLongW(hWnd, GWL_STYLE) & WS_SYSMENU)
492     {
493       r.right -= 3 + ButtonWidth;
494       if (! (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
495       {
496         r.right -= 2 + 2 * ButtonWidth;
497       }
498     }
499     r.right -= 2;
500
501     nclm.cbSize = sizeof(nclm);
502     if (! SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSW), &nclm, 0)) goto cleanup;
503
504     if (uFlags & DC_INBUTTON)
505         SetTextColor(MemDC, SysColours[ uFlags & DC_ACTIVE ? COLOR_BTNTEXT : COLOR_GRAYTEXT]);
506     else
507         SetTextColor(MemDC, SysColours[ uFlags & DC_ACTIVE ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT]);
508
509     SetBkMode( MemDC, TRANSPARENT );
510     if (GetWindowLongW(hWnd, GWL_STYLE) & WS_EX_TOOLWINDOW)
511 //    if (uFlags & DC_SMALLCAP) // incorrect
512         hFont = CreateFontIndirectW(&nclm.lfSmCaptionFont);
513     else
514         hFont = CreateFontIndirectW(&nclm.lfCaptionFont);
515
516     if (! hFont) goto cleanup;
517
518     hOldFont = SelectObject(MemDC, hFont);
519     if (! hOldFont) goto cleanup;
520
521     DrawTextW(MemDC, buffer, wcslen(buffer), &r, DT_VCENTER | DT_END_ELLIPSIS);
522     // Old method:
523     // TextOutW(hDC, r.left + (GetSystemMetrics(SM_CXDLGFRAME) * 2), lprc->top + (nclm.lfCaptionFont.lfHeight / 2), buffer, wcslen(buffer));
524   }
525
526     if (uFlags & DC_BUTTONS)
527     {
528         // Windows XP draws the caption buttons with DC_BUTTONS
529 //        r.left += GetSystemMetrics(SM_CXSIZE) + 1;
530 //        UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONCLOSE);
531 //        r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
532 //        UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMIN);
533 //        UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMAX);
534     }
535
536 #ifdef DOUBLE_BUFFER_CAPTION
537     if (! BitBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top,
538             MemDC, 0, 0, SRCCOPY)) goto cleanup;
539 #endif
540
541     result = TRUE;
542
543     cleanup :
544         if (MemDC)
545         {
546             if (OldBrush) SelectObject(MemDC, OldBrush);
547             if (hOldFont) SelectObject(MemDC, hOldFont);
548             if (hFont) DeleteObject(hFont);
549 #ifdef DOUBLE_BUFFER_CAPTION
550             if (OldBMP) SelectObject(MemDC, OldBMP);
551             if (MemBMP) DeleteObject(MemBMP);
552             DeleteDC(MemDC);
553 #else
554             OffsetViewportOrgEx(MemDC, -lprc->left, -lprc->top, NULL);
555 #endif
556         }
557
558         return result;
559 }
560
561
562
563 static void
564 UserDrawCaptionNC (
565         HDC hDC,
566         RECT *rect,
567         HWND hWnd,
568         DWORD style,
569         BOOL active )
570 {
571   POINT OldPos;
572   HPEN lPen, oPen;
573   RECT r = *rect;
574   UINT capflags = 0;
575
576     capflags = DC_ICON | DC_TEXT;
577     capflags |= (active & DC_ACTIVE);
578
579     if (GetWindowLongW(hWnd, GWL_STYLE) & WS_EX_TOOLWINDOW)
580         capflags |= DC_SMALLCAP;
581
582 //  Old code:
583 //  PatBlt(hDC,rect->left + GetSystemMetrics(SM_CXFRAME), rect->top +
584 //     GetSystemMetrics(SM_CYFRAME), rect->right - (GetSystemMetrics(SM_CXFRAME) * 2), (rect->top + 
585 //     GetSystemMetrics(SM_CYCAPTION)) - 1, PATCOPY );
586
587     r.left += GetSystemMetrics(SM_CXFRAME);
588     r.top += GetSystemMetrics(SM_CYFRAME);
589     r.right -= GetSystemMetrics(SM_CXFRAME);
590     r.bottom = r.top + GetSystemMetrics(SM_CYCAPTION) - 1;
591 //     GetSystemMetrics(SM_CYCAPTION)) - 1, PATCOPY );
592
593     DrawCaption(hWnd, hDC, &r, capflags);
594     
595   /* draw line below caption */
596   lPen = GetSysColorPen(COLOR_MENU);
597   oPen = SelectObject(hDC, lPen);
598   MoveToEx(hDC, r.left, r.bottom, &OldPos);
599   LineTo(hDC, r.right, r.bottom);
600   MoveToEx(hDC, OldPos.x, OldPos.y, NULL);
601   SelectObject(hDC, oPen);
602   r.bottom++;
603   
604   if (style & WS_SYSMENU)
605   {
606 //    UserDrawSysMenuButton( hWnd, hDC, FALSE);
607     r.left += GetSystemMetrics(SM_CXSIZE) + 1;
608     UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONCLOSE);
609     r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
610     UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMIN);
611     UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMAX);
612   }
613 }
614
615
616 static VOID
617 UserDrawFrameNC(HDC hDC, RECT* rect, BOOL dlgFrame, BOOL active)
618 {
619   DrawEdge(hDC, rect,EDGE_RAISED, BF_RECT | BF_MIDDLE);
620 }
621
622
623 void
624 SCROLL_DrawScrollBar (HWND hWnd, HDC hDC, INT nBar, BOOL arrows, BOOL interior);
625
626 VOID
627 DefWndDoPaintNC(HWND hWnd, HRGN clip)
628 {
629   BOOL Active = FALSE;
630   HDC hDC;
631   RECT rect;
632   ULONG Style;
633   ULONG ExStyle;
634   int wFrame = 0;
635
636   if (GetActiveWindow() == hWnd) Active = TRUE;
637   Style = GetWindowLongW(hWnd, GWL_STYLE);
638   ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
639
640   hDC = GetDCEx(hWnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
641                 ((clip > (HRGN)1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0));
642   if (hDC == 0)
643     {
644       return;
645     }
646
647   /* FIXME: Test whether we need to draw anything at all. */
648
649   GetWindowRect(hWnd, &rect);
650   rect.right = rect.right - rect.left;
651   rect.bottom = rect.bottom - rect.top;
652   rect.top = rect.left = 0;
653   SelectObject(hDC, GetSysColorPen(COLOR_WINDOWFRAME));
654   if (UserHasThickFrameStyle(Style, ExStyle))
655     {
656       UserDrawFrameNC(hDC, &rect, FALSE, Active);
657       wFrame = GetSystemMetrics(SM_CXSIZEFRAME);
658     }
659   else if (UserHasDlgFrameStyle(Style, ExStyle))
660     {
661       UserDrawFrameNC(hDC, &rect, TRUE, Active);
662       wFrame = GetSystemMetrics(SM_CXDLGFRAME);
663     }
664   if (Style & WS_CAPTION)
665     {
666       RECT r = rect;
667       r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
668       rect.top += GetSystemMetrics(SM_CYSIZE) +
669         GetSystemMetrics(SM_CYBORDER);
670       UserDrawCaptionNC(hDC, &r, hWnd, Style, Active);
671     }
672
673   /*  Draw menu bar.  */
674   if (UserHasMenu(hWnd, Style))
675     {
676       RECT r = rect;
677       r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
678       r.left += wFrame;
679       r.right -= wFrame;
680       rect.top += MenuDrawMenuBar(hDC, &r, hWnd, FALSE);
681     }
682
683   /*  Draw scrollbars */
684   if (Style & WS_VSCROLL)
685       SCROLL_DrawScrollBar(hWnd, hDC, SB_VERT, TRUE, TRUE);
686   if (Style & WS_HSCROLL)
687       SCROLL_DrawScrollBar(hWnd, hDC, SB_HORZ, TRUE, TRUE);
688
689   /* FIXME: Draw size box.*/
690
691   ReleaseDC(hWnd, hDC);
692 }
693
694
695 LRESULT
696 DefWndPaintNC(HWND hWnd, HRGN clip)
697 {
698   if (IsWindowVisible(hWnd))
699     {
700       if (IsIconic(hWnd))
701         {
702           DefWndRedrawIconTitle(hWnd);
703         }
704       else
705         {
706           DefWndDoPaintNC(hWnd, clip);
707         }
708     }
709   return(0);
710 }
711
712
713 LRESULT
714 DefWndHitTestNC(HWND hWnd, POINT Point)
715 {
716   RECT WindowRect;
717   ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
718   ULONG ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
719
720   GetWindowRect(hWnd, &WindowRect);
721   if (!PtInRect(&WindowRect, Point))
722     {      
723       return(HTNOWHERE);
724     }
725   if (Style & WS_MINIMIZE)
726     {
727       return(HTCAPTION);
728     }
729   if (UserHasThickFrameStyle(Style, ExStyle))
730     {
731       InflateRect(&WindowRect, -GetSystemMetrics(SM_CXFRAME),
732                   -GetSystemMetrics(SM_CYFRAME));
733       if (!PtInRect(&WindowRect, Point))
734         {
735           if (Point.y < WindowRect.top)
736             {
737               if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE)))
738                 {
739                   return(HTTOPLEFT);
740                 }
741               if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE)))
742                 {
743                   return(HTTOPRIGHT);
744                 }
745               return(HTTOP);
746             }
747           if (Point.y >= WindowRect.bottom)
748             {
749               if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE)))
750                 {
751                   return(HTBOTTOMLEFT);
752                 }
753               if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE)))
754                 {
755                   return(HTBOTTOMRIGHT);
756                 }
757               return(HTBOTTOM);
758             }
759           if (Point.x < WindowRect.left)
760             {
761               if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE)))
762                 {
763                   return(HTTOPLEFT);
764                 }
765               if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE)))
766                 {
767                   return(HTBOTTOMLEFT);
768                 }
769               return(HTLEFT);
770             }
771           if (Point.x >= WindowRect.right)
772             {
773               if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE)))
774                 {
775                   return(HTTOPRIGHT);
776                 }
777               if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE)))
778                 {
779                   return(HTBOTTOMRIGHT);
780                 }
781               return(HTRIGHT);
782             }
783         }
784     }
785   else
786     {
787       if (UserHasDlgFrameStyle(Style, ExStyle))
788         {
789           InflateRect(&WindowRect, -GetSystemMetrics(SM_CXDLGFRAME),
790                       -GetSystemMetrics(SM_CYDLGFRAME));
791         }
792       else if (UserHasThinFrameStyle(Style, ExStyle))
793         {
794           InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER),
795                       -GetSystemMetrics(SM_CYBORDER));
796         }
797       if (!PtInRect(&WindowRect, Point))
798         {
799           return(HTBORDER);
800         }
801     }
802
803   if ((Style & WS_CAPTION) == WS_CAPTION)
804     {
805       WindowRect.top += (GetSystemMetrics(SM_CYCAPTION) -
806         GetSystemMetrics(SM_CYBORDER));
807       if (!PtInRect(&WindowRect, Point))
808         {
809           if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW))
810             {
811               WindowRect.left += GetSystemMetrics(SM_CXSIZE);
812               WindowRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
813             }
814           if (Point.x <= WindowRect.left)
815             {
816               return(HTSYSMENU);
817             }
818           if (WindowRect.right <= Point.x)
819             {
820               return(HTCLOSE);
821             }
822
823           if (Style & WS_MAXIMIZEBOX || Style & WS_MINIMIZEBOX)
824             {
825               WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
826             }
827           if (Point.x >= WindowRect.right)
828             {
829               return(HTMAXBUTTON);
830             }
831
832           if (Style & WS_MINIMIZEBOX)
833             {
834               WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
835             }
836           if (Point.x >= WindowRect.right)
837             {
838               return(HTMINBUTTON);
839             }
840           return(HTCAPTION);
841         }
842     }
843
844   ScreenToClient(hWnd, &Point);
845   GetClientRect(hWnd, &WindowRect);
846
847   if (PtInRect(&WindowRect, Point))
848     {
849       return(HTCLIENT);
850     }
851
852   if (Style & WS_VSCROLL)
853     {
854       WindowRect.right += GetSystemMetrics(SM_CXVSCROLL);
855       if (PtInRect(&WindowRect, Point))
856         {
857           return(HTVSCROLL);
858         }
859     }
860
861   if (Style & WS_HSCROLL)
862     {
863       WindowRect.bottom += GetSystemMetrics(SM_CYHSCROLL);
864       if (PtInRect(&WindowRect, Point))
865         {
866           if ((Style & WS_VSCROLL) &&
867               (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXVSCROLL))))
868             {
869               return(HTBOTTOMRIGHT);
870             }
871           return(HTHSCROLL);
872         }
873     }
874
875   if (UserHasMenu(hWnd, Style))
876     {
877       if (Point.y < 0 && Point.x >= 0 && Point.x <= WindowRect.right)
878         {
879           return(HTMENU);
880         }
881     }
882
883   return(HTNOWHERE);
884 }
885
886 VOID STATIC
887 DefWndDoButton(HWND hWnd, WPARAM wParam)
888 {
889   MSG Msg;
890   BOOL InBtn = TRUE, HasBtn = FALSE;
891   ULONG Btn;
892   WPARAM SCMsg, CurBtn = wParam, OrigBtn = wParam;
893   
894   switch(wParam)
895   {
896     case HTCLOSE:
897       Btn = DFCS_CAPTIONCLOSE;
898       SCMsg = SC_CLOSE;
899       HasBtn = IsCloseBoxActive(hWnd);
900       break;
901     case HTMINBUTTON:
902       Btn = DFCS_CAPTIONMIN;
903       SCMsg = SC_MINIMIZE;
904       HasBtn = IsMinBoxActive(hWnd);
905       break;
906     case HTMAXBUTTON:
907       Btn = DFCS_CAPTIONMAX;
908       SCMsg = SC_MAXIMIZE;
909       HasBtn = IsMaxBoxActive(hWnd);
910       break;
911     default:
912       return;
913   }
914   
915   if(!HasBtn)
916     return;
917   
918   SetCapture(hWnd);
919   UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), HasBtn , Btn);
920   
921   while(1)
922   {
923     GetMessageW(&Msg, 0, 0, 0);
924     switch(Msg.message)
925     {
926       case WM_NCLBUTTONUP:
927       case WM_LBUTTONUP:
928         if(InBtn)
929           goto done;
930         else
931         {
932           ReleaseCapture();
933           return;
934         }
935       case WM_NCMOUSEMOVE:
936       case WM_MOUSEMOVE:
937         CurBtn = DefWndHitTestNC(hWnd, Msg.pt);
938         if(InBtn != (CurBtn == OrigBtn))
939         {
940           UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), (CurBtn == OrigBtn) , Btn);
941         }
942         InBtn = CurBtn == OrigBtn;
943         break;
944     }
945   }
946   
947 done:
948   UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), FALSE , Btn);
949   ReleaseCapture();
950   SendMessageA(hWnd, WM_SYSCOMMAND, SCMsg, 0);
951   return;
952 }
953
954 VOID STATIC
955 DefWndDoScrollBarDown(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
956 {
957   POINT Point;
958   DWORD hit;
959   Point.x = SLOWORD(lParam);
960   Point.y = SHIWORD(lParam);
961   
962   hit = SCROLL_HitTest(hWnd, (wParam == HTHSCROLL) ? SB_HORZ : SB_VERT, Point, FALSE);
963   
964   if(hit)
965     DbgPrint("SCROLL_HitTest() == 0x%x\n", hit);
966   
967   SendMessageA(hWnd, WM_SYSCOMMAND, Msg + (UINT)wParam, lParam);
968 }
969
970 LRESULT
971 DefWndHandleLButtonDownNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
972 {
973     switch (wParam)
974     {
975         case HTCAPTION:
976         {
977                 HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
978                 if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
979                 {
980                     SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
981                 }
982                 break;
983         }
984         case HTSYSMENU:
985         {
986           if (GetWindowLongW(hWnd, GWL_STYLE) & WS_SYSMENU)
987             {
988               if (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
989                 {
990                   HDC hDC = GetWindowDC(hWnd);
991 //                UserDrawSysMenuButton(hWnd, hDC, TRUE);
992                   ReleaseDC(hWnd, hDC);
993                 }
994               SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU,
995                            lParam);
996             }
997           break;
998         }
999         case HTMENU:
1000         {
1001             SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTMENU, lParam);
1002             break;
1003         }
1004         case HTHSCROLL:
1005         {
1006             DefWndDoScrollBarDown(hWnd, SC_HSCROLL, HTHSCROLL, lParam);
1007             //SendMessageA(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
1008             break;
1009         }
1010         case HTVSCROLL:
1011         {
1012             DefWndDoScrollBarDown(hWnd, SC_VSCROLL, HTVSCROLL, lParam);
1013             //SendMessageA(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
1014             break;
1015         }
1016         case HTMINBUTTON:
1017         case HTMAXBUTTON:
1018         case HTCLOSE:
1019         {
1020           DefWndDoButton(hWnd, wParam);
1021           break;
1022         }
1023         case HTLEFT:
1024         case HTRIGHT:
1025         case HTTOP:
1026         case HTBOTTOM:
1027         case HTTOPLEFT:
1028         case HTTOPRIGHT:
1029         case HTBOTTOMLEFT:
1030         case HTBOTTOMRIGHT:
1031         {
1032             SendMessageA(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
1033             break;
1034         }
1035     }
1036     return(0);
1037 }
1038
1039
1040 LRESULT
1041 DefWndHandleLButtonDblClkNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
1042 {
1043   UNIMPLEMENTED;
1044   return(0);
1045 }
1046
1047
1048 LRESULT
1049 DefWndHandleLButtonUpNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
1050 {
1051   UNIMPLEMENTED;
1052   return(0);
1053 }
1054
1055
1056 LRESULT
1057 DefWndHandleActiveNC(HWND hWnd, WPARAM wParam)
1058 {
1059   UNIMPLEMENTED;
1060   return(0);
1061 }
1062
1063
1064 VOID
1065 DefWndSetRedraw(HWND hWnd, WPARAM wParam)
1066 {
1067   UNIMPLEMENTED;
1068 }
1069
1070
1071 LRESULT
1072 DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam)
1073 {
1074   /* Not for child windows. */
1075   if (hWnd != (HWND)wParam)
1076     {
1077       return(0);
1078     }
1079
1080   switch(LOWORD(lParam))
1081     {
1082     case HTERROR:
1083       {
1084         WORD Msg = HIWORD(lParam);
1085         if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN ||
1086             Msg == WM_RBUTTONDOWN)
1087           {
1088             MessageBeep(0);
1089           }
1090         break;
1091       }
1092
1093     case HTCLIENT:
1094       {
1095         HICON hCursor = (HICON)GetClassLongW(hWnd, GCL_HCURSOR);
1096         if (hCursor)
1097           {
1098             SetCursor(hCursor);
1099             return(TRUE);
1100           }
1101         return(FALSE);
1102       }
1103
1104     case HTLEFT:
1105     case HTRIGHT:
1106       {
1107         return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZEWE)));
1108       }
1109
1110     case HTTOP:
1111     case HTBOTTOM:
1112       {
1113         return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENS)));
1114       }
1115
1116     case HTTOPLEFT:
1117     case HTBOTTOMRIGHT:
1118       {
1119         return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENWSE)));
1120       }
1121
1122     case HTBOTTOMLEFT:
1123     case HTTOPRIGHT:
1124       {
1125         return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENESW)));
1126       }
1127     }
1128   return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW)));
1129 }
1130
1131 static LONG 
1132 DefWndStartSizeMove(HWND hWnd, WPARAM wParam, POINT *capturePoint)
1133 {
1134   LONG hittest = 0;
1135   POINT pt;
1136   MSG msg;
1137   RECT rectWindow;
1138   ULONG Style = GetWindowLongW(hWnd, GWL_STYLE); 
1139   
1140   GetWindowRect(hWnd, &rectWindow);
1141
1142   if ((wParam & 0xfff0) == SC_MOVE)
1143     {
1144       /* Move pointer at the center of the caption */
1145       RECT rect;
1146       UserGetInsideRectNC(hWnd, &rect);
1147       if (Style & WS_SYSMENU)
1148         rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
1149       if (Style & WS_MINIMIZEBOX)
1150         rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1151       if (Style & WS_MAXIMIZEBOX)
1152         rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1153       pt.x = rectWindow.left + (rect.right - rect.left) / 2;
1154       pt.y = rectWindow.top + rect.top + GetSystemMetrics(SM_CYSIZE)/2;
1155       hittest = HTCAPTION;
1156       *capturePoint = pt;
1157     }
1158   else  /* SC_SIZE */
1159     {
1160       while(!hittest)
1161         {
1162           GetMessageW(&msg, NULL, 0, 0);
1163           switch(msg.message)
1164             {
1165             case WM_MOUSEMOVE:
1166               hittest = DefWndHitTestNC(hWnd, msg.pt);
1167               if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
1168                 hittest = 0;
1169               break;
1170               
1171             case WM_LBUTTONUP:
1172               return 0;
1173               
1174             case WM_KEYDOWN:
1175               switch(msg.wParam)
1176                 {
1177                 case VK_UP:
1178                   hittest = HTTOP;
1179                   pt.x =(rectWindow.left+rectWindow.right)/2;
1180                   pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
1181                   break;
1182                 case VK_DOWN:
1183                   hittest = HTBOTTOM;
1184                   pt.x =(rectWindow.left+rectWindow.right)/2;
1185                   pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
1186                   break;
1187                 case VK_LEFT:
1188                   hittest = HTLEFT;
1189                   pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
1190                   pt.y =(rectWindow.top+rectWindow.bottom)/2;
1191                   break;
1192                 case VK_RIGHT:
1193                   hittest = HTRIGHT;
1194                   pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
1195                   pt.y =(rectWindow.top+rectWindow.bottom)/2;
1196                   break;
1197                 case VK_RETURN:
1198                 case VK_ESCAPE: return 0;
1199                 }
1200             }
1201         }
1202       *capturePoint = pt;
1203     }
1204     SetCursorPos( pt.x, pt.y );
1205     DefWndHandleSetCursor(hWnd, (WPARAM)hWnd, MAKELONG(hittest, WM_MOUSEMOVE));
1206     return hittest;
1207 }
1208
1209 #define ON_LEFT_BORDER(hit) \
1210  (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
1211 #define ON_RIGHT_BORDER(hit) \
1212  (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
1213 #define ON_TOP_BORDER(hit) \
1214  (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
1215 #define ON_BOTTOM_BORDER(hit) \
1216  (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
1217
1218 VOID STATIC 
1219 UserDrawWindowFrame(HDC hdc, const RECT *rect,
1220                     ULONG width, ULONG height, DWORD rop )
1221 {
1222   HBRUSH hbrush = SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
1223   PatBlt( hdc, rect->left, rect->top,
1224           rect->right - rect->left - width, height, rop );
1225   PatBlt( hdc, rect->left, rect->top + height, width,
1226           rect->bottom - rect->top - height, rop );
1227   PatBlt( hdc, rect->left + width, rect->bottom - 1,
1228           rect->right - rect->left - width, -height, rop );
1229   PatBlt( hdc, rect->right - 1, rect->top, -width,
1230           rect->bottom - rect->top - height, rop );
1231   SelectObject( hdc, hbrush );
1232 }
1233
1234 VOID STATIC
1235 UserDrawMovingFrame(HDC hdc, RECT *rect, BOOL thickframe)
1236 {
1237   if (thickframe)
1238     {
1239       UserDrawWindowFrame(hdc, rect, GetSystemMetrics(SM_CXFRAME),
1240                           GetSystemMetrics(SM_CYFRAME), PATINVERT );
1241     }
1242   else DrawFocusRect( hdc, rect );
1243 }
1244
1245 VOID STATIC
1246 DefWndDoSizeMove(HWND hwnd, WORD wParam)
1247 {
1248   MSG msg;
1249   RECT sizingRect, mouseRect, origRect;
1250   HDC hdc;
1251   LONG hittest = (LONG)(wParam & 0x0f);
1252   HCURSOR hDragCursor = 0, hOldCursor = 0;
1253   POINT minTrack, maxTrack;
1254   POINT capturePoint, pt;
1255   ULONG Style = GetWindowLongW(hwnd, GWL_STYLE);
1256   ULONG ExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE); 
1257   BOOL thickframe = UserHasThickFrameStyle(Style, ExStyle);
1258   BOOL iconic = Style & WS_MINIMIZE;
1259   BOOL moved = FALSE;
1260   DWORD dwPoint = GetMessagePos();
1261   BOOL DragFullWindows = FALSE;
1262   HWND hWndParent;
1263
1264   SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
1265   
1266   pt.x = SLOWORD(dwPoint);
1267   pt.y = SHIWORD(dwPoint);
1268   capturePoint = pt;
1269   
1270   if (IsZoomed(hwnd) || !IsWindowVisible(hwnd))
1271     {
1272       return;
1273     }
1274   
1275   if ((wParam & 0xfff0) == SC_MOVE)
1276     {
1277       if (!hittest) 
1278         {
1279           hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
1280         }
1281       if (!hittest)
1282         {
1283           return;
1284         }
1285     }
1286   else  /* SC_SIZE */
1287     {
1288       if (!thickframe)
1289         {
1290           return;
1291         }
1292       if (hittest && hittest != HTSYSMENU) 
1293         {
1294           hittest += 2;
1295         }
1296       else
1297         {
1298           SetCapture(hwnd);
1299           hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
1300           if (!hittest)
1301             {
1302               ReleaseCapture();
1303               return;
1304             }
1305         }
1306     }
1307
1308   if (Style & WS_CHILD)
1309     {
1310       hWndParent = GetParent(hwnd);
1311     }
1312   
1313   /* Get min/max info */
1314   
1315   WinPosGetMinMaxInfo(hwnd, NULL, NULL, &minTrack, &maxTrack);
1316   GetWindowRect(hwnd, &sizingRect);
1317   origRect = sizingRect;
1318   if (Style & WS_CHILD)
1319     {
1320       GetClientRect(hWndParent, &mouseRect );
1321     }
1322   else 
1323     {
1324       SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), 
1325               GetSystemMetrics(SM_CYSCREEN));
1326     }
1327   if (ON_LEFT_BORDER(hittest))
1328     {
1329       mouseRect.left  = max( mouseRect.left, sizingRect.right-maxTrack.x );
1330       mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
1331     }
1332   else if (ON_RIGHT_BORDER(hittest))
1333     {
1334       mouseRect.left  = max( mouseRect.left, sizingRect.left+minTrack.x );
1335       mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
1336     }
1337   if (ON_TOP_BORDER(hittest))
1338     {
1339       mouseRect.top    = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
1340       mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
1341     }
1342   else if (ON_BOTTOM_BORDER(hittest))
1343     {
1344       mouseRect.top    = max( mouseRect.top, sizingRect.top+minTrack.y );
1345       mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
1346     }
1347   if (Style & WS_CHILD)
1348     {      
1349       MapWindowPoints( hWndParent, 0, (LPPOINT)&mouseRect, 2 );
1350     }
1351   SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
1352   
1353   if (GetCapture() != hwnd) SetCapture( hwnd );    
1354   
1355   if (Style & WS_CHILD)
1356     {
1357       /* Retrieve a default cache DC (without using the window style) */
1358       hdc = GetDCEx(hWndParent, 0, DCX_CACHE);
1359     }
1360   else
1361     {
1362       hdc = GetDC( 0 );
1363     }
1364   
1365   if( iconic ) /* create a cursor for dragging */
1366     {
1367       HICON hIcon = (HICON)GetClassLongW(hwnd, GCL_HICON);
1368       if(!hIcon) hIcon = (HICON)SendMessageW( hwnd, WM_QUERYDRAGICON, 0, 0L);
1369       if( hIcon ) hDragCursor = CursorIconToCursor( hIcon, TRUE );
1370       if( !hDragCursor ) iconic = FALSE;
1371     }
1372   
1373   /* invert frame if WIN31_LOOK to indicate mouse click on caption */
1374   if( !iconic && !DragFullWindows)
1375     {
1376       UserDrawMovingFrame( hdc, &sizingRect, thickframe );
1377     }
1378   
1379   while(1)
1380     {
1381       int dx = 0, dy = 0;
1382
1383       GetMessageW(&msg, 0, 0, 0);
1384       
1385       /* Exit on button-up, Return, or Esc */
1386       if ((msg.message == WM_LBUTTONUP) ||
1387           ((msg.message == WM_KEYDOWN) && 
1388            ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
1389       
1390       if (msg.message == WM_PAINT)
1391         {
1392           if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
1393           UpdateWindow( msg.hwnd );
1394           if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
1395           continue;
1396         }
1397       
1398       if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
1399         continue;  /* We are not interested in other messages */
1400       
1401       pt = msg.pt;
1402       
1403       if (msg.message == WM_KEYDOWN) switch(msg.wParam)
1404         {
1405         case VK_UP:    pt.y -= 8; break;
1406         case VK_DOWN:  pt.y += 8; break;
1407         case VK_LEFT:  pt.x -= 8; break;
1408         case VK_RIGHT: pt.x += 8; break;                
1409         }
1410       
1411       pt.x = max( pt.x, mouseRect.left );
1412       pt.x = min( pt.x, mouseRect.right );
1413       pt.y = max( pt.y, mouseRect.top );
1414       pt.y = min( pt.y, mouseRect.bottom );
1415       
1416       dx = pt.x - capturePoint.x;
1417       dy = pt.y - capturePoint.y;
1418       
1419       if (dx || dy)
1420         {
1421           if( !moved )
1422             {
1423               moved = TRUE;
1424               
1425                 if( iconic ) /* ok, no system popup tracking */
1426                   {
1427                     hOldCursor = SetCursor(hDragCursor);
1428                     ShowCursor( TRUE );
1429                     WinPosShowIconTitle( hwnd, FALSE );
1430                   } 
1431             }
1432           
1433           if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
1434           else
1435             {
1436               RECT newRect = sizingRect;
1437               WPARAM wpSizingHit = 0;
1438               
1439               if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
1440               if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
1441               else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
1442               if (ON_TOP_BORDER(hittest)) newRect.top += dy;
1443               else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
1444               if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
1445               capturePoint = pt;
1446               
1447               /* determine the hit location */
1448               if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
1449                 wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
1450               SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
1451               
1452               if (!iconic)
1453                 {
1454                   if(!DragFullWindows)
1455                     UserDrawMovingFrame( hdc, &newRect, thickframe );
1456                   else {
1457                     /* To avoid any deadlocks, all the locks on the windows
1458                        structures must be suspended before the SetWindowPos */
1459                     SetWindowPos( hwnd, 0, newRect.left, newRect.top,
1460                                   newRect.right - newRect.left,
1461                                   newRect.bottom - newRect.top,
1462                                   ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
1463                   }
1464                 }
1465               sizingRect = newRect;
1466             }
1467         }
1468     }
1469   
1470   ReleaseCapture();
1471   if( iconic )
1472     {
1473       if( moved ) /* restore cursors, show icon title later on */
1474         {
1475           ShowCursor( FALSE );
1476           SetCursor( hOldCursor );
1477         }
1478       DestroyCursor( hDragCursor );
1479     }
1480   else if(!DragFullWindows)
1481       UserDrawMovingFrame( hdc, &sizingRect, thickframe );
1482   
1483   if (Style & WS_CHILD)
1484     ReleaseDC( hWndParent, hdc );
1485   else
1486     ReleaseDC( 0, hdc );
1487   
1488   SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
1489   SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
1490   
1491   /* window moved or resized */
1492   if (moved)
1493     {
1494       /* if the moving/resizing isn't canceled call SetWindowPos
1495        * with the new position or the new size of the window
1496        */
1497       if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
1498         {
1499           /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
1500           if(!DragFullWindows)
1501             SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
1502                           sizingRect.right - sizingRect.left,
1503                           sizingRect.bottom - sizingRect.top,
1504                           ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
1505         }
1506       else { /* restore previous size/position */
1507         if(DragFullWindows)
1508           SetWindowPos( hwnd, 0, origRect.left, origRect.top,
1509                         origRect.right - origRect.left,
1510                         origRect.bottom - origRect.top,
1511                         ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
1512       }      
1513     }
1514   
1515   if( IsWindow(hwnd) )
1516     if( Style & WS_MINIMIZE )
1517       {
1518         /* Single click brings up the system menu when iconized */
1519         
1520         if( !moved ) 
1521           {
1522             if( Style & WS_SYSMENU ) 
1523               SendMessageA( hwnd, WM_SYSCOMMAND,
1524                             SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
1525           }
1526         else WinPosShowIconTitle( hwnd, TRUE );
1527       }
1528 }
1529
1530
1531 LRESULT
1532 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
1533 {
1534   switch (wParam & 0xfff0)
1535     {
1536       case SC_MOVE:
1537       case SC_SIZE:
1538         DefWndDoSizeMove(hWnd, wParam);
1539         break;
1540       case SC_CLOSE:
1541         SendMessageA(hWnd, WM_CLOSE, 0, 0);
1542         break;
1543       case SC_MOUSEMENU:
1544         MenuTrackMouseMenuBar(hWnd, wParam, Pt);
1545         break;
1546       case SC_KEYMENU:
1547         MenuTrackKbdMenuBar(hWnd, wParam, Pt.x);
1548         break;
1549       default:
1550         /* FIXME: Implement */
1551         UNIMPLEMENTED;
1552         break;
1553     }
1554
1555   return(0);
1556 }
1557
1558
1559 VOID
1560 DefWndAdjustRect(RECT* Rect, ULONG Style, BOOL Menu, ULONG ExStyle)
1561 {
1562   if (Style & WS_ICONIC)
1563     {
1564       return;
1565     }
1566
1567   if (UserHasThickFrameStyle(Style, ExStyle))
1568     {
1569       InflateRect(Rect, GetSystemMetrics(SM_CXFRAME),
1570                   GetSystemMetrics(SM_CYFRAME));
1571     }
1572   else if (UserHasDlgFrameStyle(Style, ExStyle))
1573     {
1574       InflateRect(Rect, GetSystemMetrics(SM_CXDLGFRAME),
1575                   GetSystemMetrics(SM_CYDLGFRAME));
1576     }
1577   else if (UserHasThinFrameStyle(Style, ExStyle))
1578     {
1579       InflateRect(Rect, GetSystemMetrics(SM_CXBORDER),
1580                   GetSystemMetrics(SM_CYBORDER));
1581     }
1582   if (Style & WS_CAPTION)
1583     {
1584       Rect->top -= (GetSystemMetrics(SM_CYCAPTION) -
1585         GetSystemMetrics(SM_CYBORDER)) + 1;
1586     }
1587   if (Menu)
1588     {
1589       Rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
1590     }
1591   if (Style & WS_VSCROLL)
1592     {
1593       Rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
1594       if (UserHasAnyFrameStyle(Style, ExStyle))
1595         {
1596           Rect->right++;
1597         }
1598     }
1599   if (Style & WS_HSCROLL)
1600     {
1601       Rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
1602       if (UserHasAnyFrameStyle(Style, ExStyle))
1603         {
1604           Rect->bottom++;
1605         }
1606     }
1607 }
1608
1609 LRESULT STDCALL
1610 DefWndNCCalcSize(HWND hWnd, RECT* Rect)
1611 {
1612     LRESULT Result = 0;
1613     LONG Style = GetClassLongW(hWnd, GCL_STYLE);
1614     RECT TmpRect = {0, 0, 0, 0};
1615
1616     if (Style & CS_VREDRAW)
1617     {
1618         Result |= WVR_VREDRAW;
1619     }
1620     if (Style & CS_HREDRAW)
1621     {
1622         Result |= WVR_HREDRAW;
1623     }
1624
1625     if (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1626     {
1627         DefWndAdjustRect(&TmpRect, GetWindowLongW(hWnd, GWL_STYLE),
1628                          FALSE, GetWindowLongW(hWnd, GWL_EXSTYLE));
1629         Rect->left -= TmpRect.left;
1630         Rect->top -= TmpRect.top;
1631         Rect->right -= TmpRect.right;
1632         Rect->bottom -= TmpRect.bottom;
1633         if (UserHasMenu(hWnd, GetWindowLongW(hWnd, GWL_STYLE)))
1634         {
1635             Rect->top += MenuGetMenuBarHeight(hWnd, Rect->right - Rect->left,
1636                 -TmpRect.left, -TmpRect.top) + 1;
1637         }
1638         if (Rect->top > Rect->bottom)
1639             Rect->bottom = Rect->top;
1640         if (Rect->left > Rect->right)
1641             Rect->right = Rect->left;
1642     }
1643
1644     return (Result);
1645 }
1646
1647 LRESULT
1648 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
1649 {
1650     POINT maxSize, minTrack;
1651     LONG style = GetWindowLongA(hWnd, GWL_STYLE);
1652
1653     if (Pos->flags & SWP_NOSIZE) return 0;
1654     if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1655     {
1656         WinPosGetMinMaxInfo(hWnd, &maxSize, NULL, &minTrack, NULL);
1657         Pos->cx = min(Pos->cx, maxSize.x);
1658         Pos->cy = min(Pos->cy, maxSize.y);
1659         if (!(style & WS_MINIMIZE))
1660         {
1661             if (Pos->cx < minTrack.x) Pos->cx = minTrack.x;
1662             if (Pos->cy < minTrack.y) Pos->cy = minTrack.y;
1663         }
1664     }
1665     return 0;
1666 }
1667
1668 /* Undocumented flags. */
1669 #define SWP_NOCLIENTMOVE          0x0800
1670 #define SWP_NOCLIENTSIZE          0x1000
1671
1672 LRESULT
1673 DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
1674 {
1675     RECT rect;
1676
1677     GetClientRect(hWnd, &rect);
1678
1679     if (!(Pos->flags & SWP_NOCLIENTMOVE))
1680         SendMessageW(hWnd, WM_MOVE, 0, MAKELONG(rect.left, rect.top));
1681
1682     if (!(Pos->flags & SWP_NOCLIENTSIZE))
1683     {
1684         WPARAM wp = SIZE_RESTORED;
1685         if (IsZoomed(hWnd)) wp = SIZE_MAXIMIZED;
1686         else if (IsIconic(hWnd)) wp = SIZE_MINIMIZED;
1687         SendMessageW(hWnd, WM_SIZE, wp,
1688             MAKELONG(rect.right - rect.left, rect.bottom - rect.top));
1689     }
1690
1691     return 0;
1692 }
1693
1694 /***********************************************************************
1695  *           DefWndControlColor
1696  *
1697  * Default colors for control painting.
1698  */
1699 static HBRUSH
1700 DefWndControlColor(HDC hDC, UINT ctlType)
1701 {
1702   if (CTLCOLOR_SCROLLBAR == ctlType)
1703     {
1704       HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
1705       COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
1706       SetTextColor(hDC, GetSysColor(COLOR_3DFACE));
1707       SetBkColor(hDC, bk);
1708
1709       /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
1710        * we better use 0x55aa bitmap brush to make scrollbar's background
1711        * look different from the window background.
1712        */
1713       if (bk == GetSysColor(COLOR_WINDOW))
1714         {
1715 #if 0 /* FIXME */
1716           return CACHE_GetPattern55AABrush();
1717 #else
1718           return NULL;
1719 #endif
1720         }
1721       UnrealizeObject(hb);
1722       return hb;
1723     }
1724
1725   SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
1726
1727   if ((CTLCOLOR_EDIT == ctlType) || (CTLCOLOR_LISTBOX == ctlType))
1728     {
1729       SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
1730     }
1731   else
1732     {
1733       SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
1734       return GetSysColorBrush(COLOR_3DFACE);
1735     }
1736
1737   return GetSysColorBrush(COLOR_WINDOW);
1738 }
1739
1740
1741 LRESULT STDCALL
1742 User32DefWindowProc(HWND hWnd,
1743                     UINT Msg,
1744                     WPARAM wParam,
1745                     LPARAM lParam,
1746                     BOOL bUnicode)
1747 {
1748     switch (Msg)
1749     {
1750         case WM_NCPAINT:
1751         {
1752             return (DefWndPaintNC(hWnd, (HRGN)wParam));
1753         }
1754
1755         case WM_NCCALCSIZE:
1756         {
1757             return (DefWndNCCalcSize(hWnd, (RECT*)lParam));
1758         }
1759
1760         case WM_WINDOWPOSCHANGING:
1761         {
1762             return (DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1763         }
1764
1765         case WM_WINDOWPOSCHANGED:
1766         {
1767             return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));
1768         }
1769
1770         case WM_NCHITTEST:
1771         {
1772             POINT Point;
1773             Point.x = SLOWORD(lParam);
1774             Point.y = SHIWORD(lParam);
1775             return (DefWndHitTestNC(hWnd, Point));
1776         }
1777
1778         case WM_NCLBUTTONDOWN:
1779         {
1780             return (DefWndHandleLButtonDownNC(hWnd, wParam, lParam));
1781         }
1782
1783         case WM_NCLBUTTONUP:
1784         {
1785             return (DefWndHandleLButtonUpNC(hWnd, wParam, lParam));
1786         }
1787
1788         case WM_LBUTTONDBLCLK:
1789         case WM_NCLBUTTONDBLCLK:
1790         {
1791             return (DefWndHandleLButtonDblClkNC(hWnd, wParam, lParam));
1792         }
1793
1794         case WM_NCRBUTTONDOWN:
1795         {
1796             if (wParam == HTCAPTION)
1797             {
1798                 SetCapture(hWnd);
1799             }
1800             break;
1801         }
1802
1803         case WM_RBUTTONUP:
1804         {
1805             POINT Pt;
1806             if (hWnd == GetCapture())
1807             {
1808                 ReleaseCapture();
1809             }
1810             Pt.x = SLOWORD(lParam);
1811             Pt.y = SHIWORD(lParam);
1812             ClientToScreen(hWnd, &Pt);
1813             lParam = MAKELPARAM(Pt.x, Pt.y);
1814             if (bUnicode)
1815             {
1816                 SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1817             }
1818             else
1819             {
1820                 SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1821             }
1822             break;
1823         }
1824
1825         case WM_CONTEXTMENU:
1826         {
1827             if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1828             {
1829                 if (bUnicode)
1830                 {
1831                     SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1832                 }
1833                 else
1834                 {
1835                     SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
1836                 }
1837             }
1838             else
1839             {
1840                 LONG HitCode;
1841                 POINT Pt;
1842
1843                 Pt.x = SLOWORD(lParam);
1844                 Pt.y = SHIWORD(lParam);
1845                 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1846                 {
1847                     ScreenToClient(GetParent(hWnd), &Pt);
1848                 }
1849
1850                 HitCode = DefWndHitTestNC(hWnd, Pt);
1851
1852                 if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
1853                 {
1854                     TrackPopupMenu(GetSystemMenu(hWnd, FALSE),
1855                                    TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
1856                                    Pt.x, Pt.y, 0, hWnd, NULL);
1857                 }
1858                 }
1859             break;
1860         }
1861
1862         case WM_NCACTIVATE:
1863         {
1864             return (DefWndHandleActiveNC(hWnd, wParam));
1865         }
1866
1867         case WM_PRINT:
1868         {
1869             /* FIXME: Implement. */
1870             return (0);
1871         }
1872
1873         case WM_PAINTICON:
1874         case WM_PAINT:
1875         {
1876             PAINTSTRUCT Ps;
1877             HDC hDC = BeginPaint(hWnd, &Ps);
1878             if (hDC)
1879             {           
1880                 HICON hIcon;
1881                 if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1882                     (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
1883                 {
1884                     RECT WindowRect;
1885                     INT x, y;
1886                     GetWindowRect(hWnd, &WindowRect);
1887                     x = (WindowRect.right - WindowRect.left -
1888                          GetSystemMetrics(SM_CXICON)) / 2;
1889                     y = (WindowRect.bottom - WindowRect.top -
1890                          GetSystemMetrics(SM_CYICON)) / 2;
1891                     DrawIcon(hDC, x, y, hIcon);
1892                 } 
1893                 if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
1894                 {
1895                     RECT WindowRect;
1896                     GetClientRect(hWnd, &WindowRect);
1897                     DrawEdge(hDC, &WindowRect, EDGE_SUNKEN, BF_RECT);
1898                 }
1899                 EndPaint(hWnd, &Ps);
1900             }
1901             return (0);
1902         }
1903
1904         case WM_SYNCPAINT:
1905         {
1906             HRGN hRgn;
1907             hRgn = CreateRectRgn(0, 0, 0, 0);
1908             if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1909             {
1910                 RedrawWindow(hWnd, NULL, hRgn,
1911                                 RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1912                     RDW_ALLCHILDREN);
1913             }
1914             DeleteObject(hRgn);
1915             return (0);
1916         }
1917
1918         case WM_SETREDRAW:
1919         {
1920             DefWndSetRedraw(hWnd, wParam);
1921             return (0);
1922         }
1923
1924         case WM_CLOSE:
1925         {
1926             DestroyWindow(hWnd);
1927             return (0);
1928         }
1929
1930         case WM_MOUSEACTIVATE:
1931         {
1932             if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
1933             {
1934                 LONG Ret;
1935                 if (bUnicode)
1936                 {
1937                     Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1938                                        wParam, lParam);
1939                 }
1940                 else
1941                 {
1942                     Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1943                                        wParam, lParam);
1944                 }
1945                 if (Ret)
1946                 {
1947                     return (Ret);
1948                 }
1949             }
1950             return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1951         }
1952
1953         case WM_ACTIVATE:
1954         {
1955             /* Check if the window is minimized. */
1956             if (LOWORD(lParam) != WA_INACTIVE &&
1957                 !(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
1958             {
1959                 SetFocus(hWnd);
1960             }
1961             break;
1962         }
1963
1964         case WM_MOUSEWHEEL:
1965         {
1966             if (GetWindowLongW(hWnd, GWL_STYLE & WS_CHILD))
1967             {
1968                 if (bUnicode)
1969                 {
1970                     return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1971                                          wParam, lParam));
1972                 }
1973                 else
1974                 {
1975                     return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1976                                          wParam, lParam));
1977                 }
1978             }
1979             break;
1980         }
1981
1982         case WM_ERASEBKGND:
1983         case WM_ICONERASEBKGND:
1984         {
1985             RECT Rect;
1986             HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
1987
1988             if (NULL == hBrush)
1989             {
1990                 return 0;
1991             }
1992             if (0 == (((DWORD) hBrush) & 0xffff0000))
1993             {
1994                 hBrush = GetSysColorBrush((DWORD) hBrush - 1);
1995             }
1996             GetClipBox((HDC)wParam, &Rect);
1997             FillRect((HDC)wParam, &Rect, hBrush);
1998             return (1);
1999         }
2000
2001         case WM_CTLCOLORMSGBOX:
2002         case WM_CTLCOLOREDIT:
2003         case WM_CTLCOLORLISTBOX:
2004         case WM_CTLCOLORBTN:
2005         case WM_CTLCOLORDLG:
2006         case WM_CTLCOLORSTATIC:
2007         case WM_CTLCOLORSCROLLBAR:
2008             return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
2009
2010         case WM_SETCURSOR:
2011         {
2012             if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
2013             {
2014                 if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
2015                 {
2016                     BOOL bResult;
2017                     if (bUnicode)
2018                     {
2019                         bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
2020                                                wParam, lParam);
2021                     }
2022                     else
2023                     {
2024                         bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
2025                                                wParam, lParam);
2026                     }
2027                     if (bResult)
2028                     {
2029                         return(TRUE);
2030                     }
2031                 }
2032             }
2033             return (DefWndHandleSetCursor(hWnd, wParam, lParam));
2034         }
2035
2036         case WM_SYSCOMMAND:
2037         {
2038             POINT Pt;
2039             Pt.x = SLOWORD(lParam);
2040             Pt.y = SHIWORD(lParam);
2041             return (DefWndHandleSysCommand(hWnd, wParam, Pt));
2042         }
2043
2044         /* FIXME: Handle key messages. */
2045 /*
2046         case WM_KEYDOWN:
2047         case WM_KEYUP:
2048         case WM_SYSKEYUP:
2049         case WM_SYSCHAR:
2050 */
2051
2052         /* FIXME: This is also incomplete. */
2053         case WM_SYSKEYDOWN:
2054         {
2055             if (HIWORD(lParam) & KEYDATA_ALT)
2056             {
2057                 if (wParam == VK_F4) /* Try to close the window */
2058                 {
2059                     HWND top = GetAncestor(hWnd, GA_ROOT);
2060                     if (!(GetClassLongW(top, GCL_STYLE) & CS_NOCLOSE))
2061                     {
2062                         if (bUnicode)
2063                             PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
2064                         else
2065                             PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
2066                     }
2067                     }
2068             }
2069             break;
2070         }
2071         
2072         case WM_SHOWWINDOW:
2073         {
2074             LONG Style;
2075
2076             if (!lParam)
2077                 return 0;
2078             Style = GetWindowLongW(hWnd, GWL_STYLE);
2079             if (!(Style & WS_POPUP))
2080                 return 0;
2081             if ((Style & WS_VISIBLE) && wParam)
2082                 return 0;
2083             if (!(Style & WS_VISIBLE) && !wParam)
2084                 return 0;
2085             if (!GetWindow(hWnd, GW_OWNER))
2086                 return 0;
2087             ShowWindow(hWnd, wParam ? SW_SHOWNA : SW_HIDE);
2088             break;
2089         }
2090
2091         case WM_CANCELMODE:
2092         {
2093             /* FIXME: Check for a desktop. */
2094             if (GetCapture() == hWnd)
2095             {
2096                 ReleaseCapture();
2097             }
2098             break;
2099         }
2100
2101         case WM_VKEYTOITEM:
2102         case WM_CHARTOITEM:
2103             return (-1);
2104
2105         case WM_DROPOBJECT:
2106             /* FIXME: Implement this. */
2107             break;
2108
2109         case WM_QUERYDROPOBJECT:
2110         {
2111             if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
2112             {
2113                 return(1);
2114             }
2115             break;
2116         }
2117
2118         case WM_QUERYDRAGICON:
2119         {
2120             UINT Len;
2121             HICON hIcon;
2122
2123             hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
2124             if (hIcon)
2125             {
2126                 return ((LRESULT)hIcon);
2127             }
2128             for (Len = 1; Len < 64; Len++)
2129             {
2130                 if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
2131                 {
2132                     return((LRESULT)hIcon);
2133                 }
2134             }
2135             return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
2136         }
2137
2138         /* FIXME: WM_ISACTIVEICON */
2139
2140         case WM_NOTIFYFORMAT:
2141         {
2142             if (IsWindowUnicode(hWnd))
2143             {
2144                 return(NFR_UNICODE);
2145             }
2146             else
2147             {
2148                 return(NFR_ANSI);
2149             }
2150         }
2151
2152         case WM_SETICON:
2153         {
2154            INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
2155            HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
2156            SetClassLongW(hWnd, Index, lParam);
2157            SetWindowPos(hWnd, 0, 0, 0, 0, 0,
2158                        SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
2159                        SWP_NOACTIVATE | SWP_NOZORDER);
2160            return ((LRESULT)hOldIcon);
2161         }
2162
2163         case WM_GETICON:
2164         {
2165             INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
2166             return (GetClassLongW(hWnd, Index));
2167         }
2168
2169         case WM_HELP:
2170         {
2171             if (bUnicode)
2172             {
2173                 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
2174             }
2175             else
2176             {
2177                 SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
2178             }
2179             break;
2180         }
2181
2182         case WM_QUERYOPEN:
2183         case WM_QUERYENDSESSION:
2184         {
2185             return (1);
2186         }
2187     }
2188     return 0;
2189 }
2190
2191
2192 LRESULT STDCALL
2193 DefWindowProcA(HWND hWnd,
2194                UINT Msg,
2195                WPARAM wParam,
2196                LPARAM lParam)
2197 {
2198     static LPSTR WindowTextAtom = 0;
2199     PSTR WindowText;
2200
2201     switch (Msg)
2202     {
2203         case WM_NCCREATE:
2204         {
2205             CREATESTRUCTA *Cs = (CREATESTRUCTA*)lParam;
2206             if (HIWORD(Cs->lpszName))
2207             {
2208                 if (0 == WindowTextAtom)
2209                 {
2210                     WindowTextAtom =
2211                         (LPSTR)(ULONG)GlobalAddAtomA("USER32!WindowTextAtomA");
2212                 }
2213                 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
2214                     strlen(Cs->lpszName) * sizeof(CHAR));
2215                 strcpy(WindowText, Cs->lpszName);
2216                 SetPropA(hWnd, WindowTextAtom, WindowText);
2217                 }
2218             return (1);
2219         }
2220
2221         case WM_GETTEXTLENGTH:
2222         {
2223             if (WindowTextAtom == 0 ||
2224                 (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
2225             {
2226                 return(0);
2227             }
2228             return (strlen(WindowText));
2229         }
2230
2231         case WM_GETTEXT:
2232         {
2233             if (WindowTextAtom == 0 ||
2234                 (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
2235             {
2236                 if (wParam > 1)
2237                     {
2238                     *((PSTR)lParam) = '\0';
2239                 }
2240                 return (0);
2241             }
2242             strncpy((LPSTR)lParam, WindowText, wParam);
2243             return (min(wParam, strlen(WindowText)));
2244         }
2245
2246         case WM_SETTEXT:
2247         {
2248             if (0 == WindowTextAtom)
2249             {
2250                 WindowTextAtom =
2251                     (LPSTR)(DWORD)GlobalAddAtomA("USER32!WindowTextAtomA");
2252                 }
2253             if (WindowTextAtom != 0 &&
2254                 (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
2255                 {
2256                 RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
2257             }
2258             WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
2259                 (strlen((PSTR)lParam) + 1) * sizeof(CHAR));
2260             strcpy(WindowText, (PSTR)lParam);
2261             SetPropA(hWnd, WindowTextAtom, WindowText);
2262             if (0 != (GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION))
2263                 {
2264                 DefWndPaintNC(hWnd, (HRGN) 1);
2265             }
2266             return (1);
2267         }
2268
2269 /*
2270         FIXME: Implement these.
2271         case WM_IME_CHAR:
2272         case WM_IME_KEYDOWN:
2273         case WM_IME_KEYUP:
2274         case WM_IME_STARTCOMPOSITION:
2275         case WM_IME_COMPOSITION:
2276         case WM_IME_ENDCOMPOSITION:
2277         case WM_IME_SELECT:
2278         case WM_IME_SETCONTEXT:
2279 */
2280
2281         case WM_NCDESTROY:
2282         {
2283             if (WindowTextAtom != 0 &&
2284                 (WindowText = RemovePropA(hWnd, WindowTextAtom)) == NULL)
2285             {
2286                 RtlFreeHeap(GetProcessHeap(), 0, WindowText);
2287             }
2288             return(0);
2289         }
2290     }
2291
2292     return User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
2293 }
2294
2295
2296 LRESULT STDCALL
2297 DefWindowProcW(HWND hWnd,
2298                UINT Msg,
2299                WPARAM wParam,
2300                LPARAM lParam)
2301 {
2302     static LPWSTR WindowTextAtom = 0;
2303     PWSTR WindowText;
2304
2305     switch (Msg)
2306     {
2307         case WM_NCCREATE:
2308         {
2309             CREATESTRUCTW* CreateStruct = (CREATESTRUCTW*)lParam;
2310             if (HIWORD(CreateStruct->lpszName))
2311             {
2312                 if (0 == WindowTextAtom)
2313                 {
2314                     WindowTextAtom =
2315                         (LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
2316                 }
2317                 WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
2318                                 wcslen(CreateStruct->lpszName) * sizeof(WCHAR));
2319                 wcscpy(WindowText, CreateStruct->lpszName);
2320                 SetPropW(hWnd, WindowTextAtom, WindowText);
2321             }
2322             return (1);
2323         }
2324
2325         case WM_GETTEXTLENGTH:
2326         {
2327             if (WindowTextAtom == 0 ||
2328                 (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
2329             {
2330                 return(0);
2331             }
2332             return (wcslen(WindowText));
2333         }
2334
2335         case WM_GETTEXT:
2336         {
2337             if (WindowTextAtom == 0 ||
2338                 (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
2339             {
2340                if (wParam > 1)
2341                {
2342                    ((PWSTR)lParam) = '\0';
2343                }
2344                return (0);
2345             }
2346             wcsncpy((PWSTR)lParam, WindowText, wParam);
2347             return (min(wParam, wcslen(WindowText)));
2348         }
2349
2350         case WM_SETTEXT:
2351         {
2352             if (WindowTextAtom == 0)
2353             {
2354                 WindowTextAtom =
2355                     (LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
2356             }
2357             if (WindowTextAtom != 0 &&
2358                 (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
2359             {
2360                 RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
2361             }
2362             WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
2363                             (wcslen((PWSTR)lParam) + 1) * sizeof(WCHAR));
2364             wcscpy(WindowText, (PWSTR)lParam);
2365             SetPropW(hWnd, WindowTextAtom, WindowText);
2366             if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
2367                 {
2368                 DefWndPaintNC(hWnd, (HRGN)1);
2369             }
2370             return (1);
2371         }
2372
2373         case WM_IME_CHAR:
2374         {
2375             SendMessageW(hWnd, WM_CHAR, wParam, lParam);
2376             return (0);
2377         }
2378
2379         case WM_IME_SETCONTEXT:
2380         {
2381             /* FIXME */
2382             return (0);
2383         }
2384
2385         case WM_NCDESTROY:
2386         {
2387             if (WindowTextAtom != 0 &&
2388                 (WindowText = RemovePropW(hWnd, WindowTextAtom)) == NULL)
2389             {
2390                 RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
2391             }
2392             return (0);
2393         }
2394     }
2395
2396     return User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
2397 }