update for HEAD-2003021201
[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 <debug.h>
18 #include <user32/wininternal.h>
19 #include <string.h>
20
21 /* GLOBALS *******************************************************************/
22
23 static HBITMAP hbitmapClose;
24 static HBITMAP hbitmapMinimize;
25 static HBITMAP hbitmapMinimizeD;
26 static HBITMAP hbitmapMaximize;
27 static HBITMAP hbitmapMaximizeD;
28 static HBITMAP hbitmapRestore;
29 static HBITMAP hbitmapRestoreD;
30
31 static COLORREF SysColours[] =
32   {
33     RGB(224, 224, 224) /* COLOR_SCROLLBAR */,
34     RGB(192, 192, 192) /* COLOR_BACKGROUND */,
35     RGB(0, 64, 128) /* COLOR_ACTIVECAPTION */,
36     RGB(255, 255, 255) /* COLOR_INACTIVECAPTION */,
37     RGB(255, 255, 255) /* COLOR_MENU */,
38     RGB(255, 255, 255) /* COLOR_WINDOW */,
39     RGB(0, 0, 0) /* COLOR_WINDOWFRAME */,
40     RGB(0, 0, 0) /* COLOR_MENUTEXT */,
41     RGB(0, 0, 0) /* COLOR_WINDOWTEXT */,
42     RGB(255, 255, 255) /* COLOR_CAPTIONTEXT */,
43     RGB(128, 128, 128) /* COLOR_ACTIVEBORDER */,
44     RGB(255, 255, 255) /* COLOR_INACTIVEBORDER */,
45     RGB(255, 255, 232) /* COLOR_APPWORKSPACE */,
46     RGB(224, 224, 224) /* COLOR_HILIGHT */,
47     RGB(0, 0, 0) /* COLOR_HILIGHTTEXT */,
48     RGB(192, 192, 192) /* COLOR_BTNFACE */,
49     RGB(128, 128, 128) /* COLOR_BTNSHADOW */,
50     RGB(192, 192, 192) /* COLOR_GRAYTEXT */,
51     RGB(0, 0, 0) /* COLOR_BTNTEXT */,
52     RGB(0, 0, 0) /* COLOR_INACTIVECAPTIONTEXT */,
53     RGB(255, 255, 255) /* COLOR_BTNHILIGHT */,
54     RGB(32, 32, 32) /* COLOR_3DDKSHADOW */,
55     RGB(192, 192, 192) /* COLOR_3DLIGHT */,
56     RGB(0, 0, 0) /* COLOR_INFOTEXT */,
57     RGB(255, 255, 192) /* COLOR_INFOBK */,
58     RGB(184, 180, 184) /* COLOR_ALTERNATEBTNFACE */,
59     RGB(0, 0, 255) /* COLOR_HOTLIGHT */,
60     RGB(16, 132, 208) /* COLOR_GRADIENTACTIVECAPTION */,
61     RGB(181, 181, 181) /* COLOR_GRADIENTINACTIVECAPTION */,
62   };
63
64 static ATOM AtomInternalPos;
65
66 /* FUNCTIONS *****************************************************************/
67
68 VOID
69 UserSetupInternalPos(VOID)
70 {
71   LPSTR Str = "SysIP";
72   AtomInternalPos = GlobalAddAtomA(Str);
73 }
74
75 /* ReactOS extension */
76 HPEN STDCALL
77 GetSysColorPen(int nIndex)
78 {
79   return(CreatePen(PS_SOLID, 1, SysColours[nIndex]));
80 }
81
82 HBRUSH STDCALL
83 GetSysColorBrush(int nIndex)
84 {
85   return(CreateSolidBrush(SysColours[nIndex]));
86 }
87
88
89 LRESULT STDCALL
90 DefFrameProcA(HWND hWnd,
91               HWND hWndMDIClient,
92               UINT uMsg,
93               WPARAM wParam,
94               LPARAM lParam)
95 {
96   return((LRESULT)0);
97 }
98
99 LRESULT STDCALL
100 DefFrameProcW(HWND hWnd,
101               HWND hWndMDIClient,
102               UINT uMsg,
103               WPARAM wParam,
104               LPARAM lParam)
105 {
106   return((LRESULT)0);
107 }
108
109
110 BOOL
111 DefWndRedrawIconTitle(HWND hWnd)
112 {
113   PINTERNALPOS lpPos = (PINTERNALPOS)GetPropA(hWnd,
114                                               (LPSTR)(DWORD)AtomInternalPos);
115   if (lpPos != NULL)
116     {
117       if (lpPos->IconTitle != NULL)
118         {
119           SendMessageA(lpPos->IconTitle, WM_SHOWWINDOW, TRUE, 0);
120           InvalidateRect(lpPos->IconTitle, NULL, TRUE);
121           return(TRUE);
122         }
123     }
124   return(FALSE);
125 }
126
127 BOOL
128 UserHasMenu(HWND hWnd, ULONG Style)
129 {
130   return(!(Style & WS_CHILD) && GetWindowLong(hWnd, GWL_ID) != 0);
131 }
132
133 ULONG
134 UserHasAnyFrameStyle(ULONG Style, ULONG ExStyle)
135 {
136   return((Style & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) ||
137          (ExStyle & WS_EX_DLGMODALFRAME) ||
138          (!(Style & (WS_CHILD | WS_POPUP))));
139 }
140
141 ULONG
142 UserHasDlgFrameStyle(ULONG Style, ULONG ExStyle)
143 {
144   return((ExStyle & WS_EX_DLGMODALFRAME) ||
145          ((Style & WS_DLGFRAME) && (!(Style & WS_THICKFRAME))));
146 }
147
148 ULONG
149 UserHasThickFrameStyle(ULONG Style, ULONG ExStyle)
150 {
151   return((Style & WS_THICKFRAME) &&
152          (!((Style & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)));
153 }
154
155 ULONG
156 UserHasThinFrameStyle(ULONG Style, ULONG ExStyle)
157 {
158   return((Style & WS_BORDER) ||
159          (!(Style & (WS_CHILD | WS_POPUP))));
160 }
161
162 ULONG
163 UserHasBigFrameStyle(ULONG Style, ULONG ExStyle)
164 {
165   return((Style & (WS_THICKFRAME | WS_DLGFRAME)) ||
166          (ExStyle & WS_EX_DLGMODALFRAME));
167 }
168
169 void UserGetInsideRectNC( HWND hwnd, RECT *rect )
170 {
171   RECT WindowRect;
172   ULONG Style;
173   ULONG ExStyle;
174
175   Style = GetWindowLong(hwnd, GWL_STYLE);
176   ExStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
177   GetWindowRect(hwnd, &WindowRect);
178   rect->top    = rect->left = 0;
179   rect->right  = WindowRect.right - WindowRect.left;
180   rect->bottom = WindowRect.bottom - WindowRect.top;
181
182   if (Style & WS_ICONIC)
183     {
184       return;
185     }
186
187   /* Remove frame from rectangle */
188   if (UserHasThickFrameStyle(Style, ExStyle ))
189       {
190         InflateRect( rect, -GetSystemMetrics(SM_CXFRAME),
191                      -GetSystemMetrics(SM_CYFRAME) );
192       }
193     else
194       {
195         if (UserHasDlgFrameStyle(Style, ExStyle ))
196           {
197             InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME),
198                          -GetSystemMetrics(SM_CYDLGFRAME));
199             /* FIXME: this isn't in NC_AdjustRect? why not? */
200             if (ExStyle & WS_EX_DLGMODALFRAME)
201               InflateRect( rect, -1, 0 );
202           }
203         else
204           {
205             if (UserHasThinFrameStyle(Style, ExStyle))
206               {
207                 InflateRect(rect, -GetSystemMetrics(SM_CXBORDER),
208                             -GetSystemMetrics(SM_CYBORDER));
209               }
210           }
211       }
212 }
213
214 void UserDrawSysButton( HWND hwnd, HDC hdc, BOOL down )
215 {
216     RECT rect;
217     HDC hdcMem;
218     HBITMAP hbitmap;
219     ULONG Style;
220
221     Style = GetWindowLong(hwnd, GWL_STYLE);
222     UserGetInsideRectNC( hwnd, &rect );
223     hdcMem = CreateCompatibleDC( hdc );
224     hbitmap = SelectObject( hdcMem, hbitmapClose );
225     BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE),
226            GetSystemMetrics(SM_CYSIZE), hdcMem,
227            (Style & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
228            down ? NOTSRCCOPY : SRCCOPY );
229     SelectObject( hdcMem, hbitmap );
230     DeleteDC( hdcMem );
231 }
232
233 static void UserDrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
234 {
235     RECT rect;
236     HDC hdcMem;
237
238     UserGetInsideRectNC( hwnd, &rect );
239     hdcMem = CreateCompatibleDC( hdc );
240     SelectObject( hdcMem,  (IsZoomed(hwnd)
241                             ? (down ? hbitmapRestoreD : hbitmapRestore)
242                             : (down ? hbitmapMaximizeD : hbitmapMaximize)) );
243     BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSMSIZE) - 1, rect.top,
244             GetSystemMetrics(SM_CXSMSIZE) + 1, GetSystemMetrics(SM_CYSMSIZE), hdcMem, 0, 0,
245             SRCCOPY );
246     DeleteDC( hdcMem );
247 }
248
249 static void UserDrawMinButton( HWND hwnd, HDC hdc, BOOL down)
250 {
251   RECT rect;
252   HDC hdcMem;
253
254   UserGetInsideRectNC(hwnd, &rect);
255   hdcMem = CreateCompatibleDC(hdc);
256   SelectObject(hdcMem, (down ? hbitmapMinimizeD : hbitmapMinimize));
257   if (GetWindowLong(hwnd, GWL_STYLE) & WS_MAXIMIZEBOX)
258     {
259       rect.right -= GetSystemMetrics(SM_CXSMSIZE)+1;
260     }
261   BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSMSIZE) - 1, rect.top,
262           GetSystemMetrics(SM_CXSMSIZE) + 1, GetSystemMetrics(SM_CYSMSIZE),
263           hdcMem, 0, 0,
264           SRCCOPY );
265   DeleteDC( hdcMem );
266 }
267
268 static void UserDrawCaptionNC( HDC hdc, RECT *rect, HWND hwnd,
269                             DWORD style, BOOL active )
270 {
271   RECT r = *rect;
272   char buffer[256];
273
274   if (!hbitmapClose)
275     {
276       hbitmapClose = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_CLOSE));
277       hbitmapMinimize  = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_REDUCE) );
278       hbitmapMinimizeD = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_REDUCED) );
279       hbitmapMaximize  = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_ZOOM) );
280       hbitmapMaximizeD = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_ZOOMD) );
281       hbitmapRestore   = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_RESTORE) );
282       hbitmapRestoreD  = LoadBitmapW( 0, MAKEINTRESOURCE(OBM_RESTORED) );
283     }
284
285   if (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
286     {
287       HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
288       PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
289       PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
290       PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
291       r.left++;
292       r.right--;
293       SelectObject( hdc, hbrushOld );
294     }
295
296   MoveToEx( hdc, r.left, r.bottom, NULL );
297   LineTo( hdc, r.right, r.bottom );
298
299   if (style & WS_SYSMENU)
300     {
301       UserDrawSysButton( hwnd, hdc, FALSE );
302       r.left += GetSystemMetrics(SM_CXSIZE) + 1;
303       MoveToEx( hdc, r.left - 1, r.top, NULL );
304       LineTo( hdc, r.left - 1, r.bottom );
305     }
306   if (style & WS_MAXIMIZEBOX)
307     {
308       UserDrawMaxButton( hwnd, hdc, FALSE );
309       r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
310     }
311   if (style & WS_MINIMIZEBOX)
312     {
313       UserDrawMinButton( hwnd, hdc, FALSE );
314       r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
315     }
316
317   FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
318                                             COLOR_INACTIVECAPTION) );
319
320   if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
321     {
322       NONCLIENTMETRICS nclm;
323       HFONT hFont, hOldFont;
324
325       nclm.cbSize = sizeof(NONCLIENTMETRICS);
326       SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
327       if (style & WS_EX_TOOLWINDOW)
328         hFont = CreateFontIndirectW(&nclm.lfSmCaptionFont);
329       else
330         hFont = CreateFontIndirectW(&nclm.lfCaptionFont);
331       hOldFont = SelectObject(hdc, hFont);
332
333       if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
334       else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
335       SetBkMode( hdc, TRANSPARENT );
336       /*DrawTextA( hdc, buffer, -1, &r,
337         DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );*/
338       TextOutA(hdc, r.left+5, r.top+2, buffer, strlen(buffer));
339       DeleteObject (SelectObject (hdc, hOldFont));
340     }
341 }
342
343 VOID
344 UserDrawFrameNC(HDC hdc, RECT* rect, BOOL dlgFrame, BOOL active)
345 {
346   INT width, height;
347
348   if (dlgFrame)
349     {
350       width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
351       height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
352       SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
353                                           COLOR_INACTIVECAPTION) );
354     }
355   else
356     {
357       width = GetSystemMetrics(SM_CXFRAME) - 2;
358       height = GetSystemMetrics(SM_CYFRAME) - 2;
359       SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
360                                             COLOR_INACTIVEBORDER) );
361     }
362
363   /* Draw frame */
364   PatBlt( hdc, rect->left, rect->top,
365           rect->right - rect->left, height, PATCOPY );
366   PatBlt( hdc, rect->left, rect->top,
367           width, rect->bottom - rect->top, PATCOPY );
368   PatBlt( hdc, rect->left, rect->bottom - 1,
369           rect->right - rect->left, -height, PATCOPY );
370   PatBlt( hdc, rect->right - 1, rect->top,
371           -width, rect->bottom - rect->top, PATCOPY );
372
373   if (dlgFrame)
374     {
375       InflateRect( rect, -width, -height );
376     }
377   else
378     {
379       INT decYOff = GetSystemMetrics(SM_CXFRAME) +
380         GetSystemMetrics(SM_CXSIZE) - 1;
381       INT decXOff = GetSystemMetrics(SM_CYFRAME) +
382         GetSystemMetrics(SM_CYSIZE) - 1;
383
384       /* Draw inner rectangle */
385
386       SelectObject( hdc, GetStockObject(NULL_BRUSH) );
387       Rectangle( hdc, rect->left + width, rect->top + height,
388                  rect->right - width , rect->bottom - height );
389
390       /* Draw the decorations */
391
392       MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
393       LineTo( hdc, rect->left + width, rect->top + decYOff );
394       MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
395       LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
396       MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
397       LineTo( hdc, rect->left + width, rect->bottom - decYOff );
398       MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
399       LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
400
401       MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
402       LineTo( hdc, rect->left + decXOff, rect->top + height);
403       MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
404       LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
405       MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
406       LineTo( hdc, rect->right - decXOff, rect->top + height );
407       MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
408       LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
409
410       InflateRect( rect, -width - 1, -height - 1 );
411     }
412 }
413
414 void SCROLL_DrawScrollBar (HWND hwnd, HDC hdc, INT nBar, BOOL arrows, BOOL interior);
415
416 VOID
417 DefWndDoPaintNC(HWND hWnd, HRGN clip)
418 {
419   ULONG Active;
420   HDC hDc;
421   RECT rect;
422   ULONG Style;
423   ULONG ExStyle;
424
425   Active = GetWindowLongW(hWnd, GWL_STYLE) & WIN_NCACTIVATED;
426   Style = GetWindowLong(hWnd, GWL_STYLE);
427   ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
428
429   hDc = GetDCEx(hWnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
430                 ((clip > (HRGN)1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0));
431   if (hDc == 0)
432     {
433       return;
434     }
435
436   /* FIXME: Test whether we need to draw anything at all. */
437
438   GetWindowRect(hWnd, &rect);
439   rect.right = rect.right - rect.left;
440   rect.bottom = rect.bottom - rect.top;
441   rect.top = rect.left = 0;
442
443   SelectObject(hDc, GetSysColorPen(COLOR_WINDOWFRAME));
444   if (UserHasAnyFrameStyle(Style, ExStyle))
445     {
446       SelectObject(hDc, GetStockObject(NULL_BRUSH));
447       Rectangle(hDc, 0, 0, rect.right, rect.bottom);
448       InflateRect(&rect, -1, -1);
449     }
450
451   if (UserHasThickFrameStyle(Style, ExStyle))
452     {
453       UserDrawFrameNC(hDc, &rect, FALSE, Active);
454     }
455   else if (UserHasDlgFrameStyle(Style, ExStyle))
456     {
457       UserDrawFrameNC(hDc, &rect, TRUE, Active);
458     }
459
460   if (Style & WS_CAPTION)
461     {
462       RECT r = rect;
463       r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
464       rect.top += GetSystemMetrics(SM_CYSIZE) +
465         GetSystemMetrics(SM_CYBORDER);
466       UserDrawCaptionNC(hDc, &r, hWnd, Style, Active);
467     }
468
469   /* FIXME: Draw menu bar. */
470
471 DbgPrint("drawing scrollbars..\n");
472   /* Draw scrollbars */
473   if (Style & WS_VSCROLL)
474       SCROLL_DrawScrollBar(hWnd, hDc, SB_VERT, TRUE, TRUE);
475   if (Style & WS_HSCROLL)
476       SCROLL_DrawScrollBar(hWnd, hDc, SB_HORZ, TRUE, TRUE);
477
478   /* FIXME: Draw size box. */
479
480   ReleaseDC(hWnd, hDc);
481 }
482
483 LRESULT
484 DefWndPaintNC(HWND hWnd, HRGN clip)
485 {
486   if (IsWindowVisible(hWnd))
487     {
488       if (IsIconic(hWnd))
489         {
490           DefWndRedrawIconTitle(hWnd);
491         }
492       else
493         {
494           DefWndDoPaintNC(hWnd, clip);
495         }
496     }
497   return(0);
498 }
499
500 LRESULT
501 DefWndHitTestNC(HWND hWnd, POINT Point)
502 {
503   RECT WindowRect;
504   ULONG Style = GetWindowLong(hWnd, GWL_STYLE);
505   ULONG ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
506
507   GetWindowRect(hWnd, &WindowRect);
508
509   if (!PtInRect(&WindowRect, Point))
510     {
511       return(HTNOWHERE);
512     }
513   if (Style & WS_MINIMIZE)
514     {
515       return(HTCAPTION);
516     }
517   if (UserHasThickFrameStyle(Style, ExStyle))
518     {
519       InflateRect(&WindowRect, -GetSystemMetrics(SM_CXFRAME),
520                   -GetSystemMetrics(SM_CYFRAME));
521       if (!PtInRect(&WindowRect, Point))
522         {
523           if (Point.y < WindowRect.top)
524             {
525               if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE)))
526                 {
527                   return(HTTOPLEFT);
528                 }
529               if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE)))
530                 {
531                   return(HTTOPRIGHT);
532                 }
533               return(HTTOP);
534             }
535           if (Point.y >= WindowRect.bottom)
536             {
537               if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE)))
538                 {
539                   return(HTBOTTOMLEFT);
540                 }
541               if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE)))
542                 {
543                   return(HTBOTTOMRIGHT);
544                 }
545               return(HTBOTTOM);
546             }
547           if (Point.x < WindowRect.left)
548             {
549               if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE)))
550                 {
551                   return(HTTOPLEFT);
552                 }
553               if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE)))
554                 {
555                   return(HTBOTTOMLEFT);
556                 }
557               return(HTLEFT);
558             }
559           if (Point.x >= WindowRect.right)
560             {
561               if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE)))
562                 {
563                   return(HTTOPRIGHT);
564                 }
565               if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE)))
566                 {
567                   return(HTBOTTOMRIGHT);
568                 }
569               return(HTRIGHT);
570             }
571         }
572     }
573   else
574     {
575       if (UserHasDlgFrameStyle(Style, ExStyle))
576         {
577           InflateRect(&WindowRect, -GetSystemMetrics(SM_CXDLGFRAME),
578                       -GetSystemMetrics(SM_CYDLGFRAME));
579         }
580       else if (UserHasThinFrameStyle(Style, ExStyle))
581         {
582           InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER),
583                       -GetSystemMetrics(SM_CYBORDER));
584         }
585       if (!PtInRect(&WindowRect, Point))
586         {
587           return(HTBORDER);
588         }
589     }
590
591   if ((Style & WS_CAPTION) == WS_CAPTION)
592     {
593       WindowRect.top += GetSystemMetrics(SM_CYCAPTION) -
594         GetSystemMetrics(SM_CYBORDER);
595       if (!PtInRect(&WindowRect, Point))
596         {
597           if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW))
598             {
599               WindowRect.left += GetSystemMetrics(SM_CXSIZE);
600             }
601           if (Point.x <= WindowRect.left)
602             {
603               return(HTSYSMENU);
604             }
605
606           if (Style & WS_MAXIMIZEBOX)
607             {
608               WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
609             }
610           if (Point.x >= WindowRect.right)
611             {
612               return(HTMAXBUTTON);
613             }
614
615           if (Style & WS_MINIMIZEBOX)
616             {
617               WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
618             }
619           if (Point.x >= WindowRect.right)
620             {
621               return(HTMINBUTTON);
622             }
623           return(HTCAPTION);
624         }
625     }
626
627   ScreenToClient(hWnd, &Point);
628   GetClientRect(hWnd, &WindowRect);
629
630   if (PtInRect(&WindowRect, Point))
631     {
632       return(HTCLIENT);
633     }
634
635   if (Style & WS_VSCROLL)
636     {
637       WindowRect.right += GetSystemMetrics(SM_CXVSCROLL);
638       if (PtInRect(&WindowRect, Point))
639         {
640           return(HTVSCROLL);
641         }
642     }
643
644   if (Style & WS_HSCROLL)
645     {
646       WindowRect.bottom += GetSystemMetrics(SM_CYHSCROLL);
647       if (PtInRect(&WindowRect, Point))
648         {
649           if ((Style & WS_VSCROLL) &&
650               (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXVSCROLL))))
651             {
652               return(HTSIZE);
653             }
654           return(HTHSCROLL);
655         }
656     }
657
658   if (UserHasMenu(hWnd, Style))
659     {
660       if (Point.y < 0 && Point.x >= 0 && Point.x <= WindowRect.right)
661         {
662           return(HTMENU);
663         }
664     }
665
666   return(HTNOWHERE);
667 }
668
669 VOID
670 DefWndTrackMinMaxBox(HWND hWnd, WPARAM wParam)
671 {
672   HDC hDC = GetWindowDC(hWnd);
673   BOOL Pressed = TRUE;
674   MSG Msg;
675
676   SetCapture(hWnd);
677
678   if (wParam == HTMINBUTTON)
679     {
680       UserDrawMinButton(hWnd, hDC, TRUE);
681     }
682   else
683     {
684       UserDrawMaxButton(hWnd, hDC, TRUE);
685     }
686
687   for(;;)
688     {
689       BOOL OldState = Pressed;
690
691       GetMessageA(hWnd, &Msg, 0, 0);
692       if (Msg.message == WM_LBUTTONUP)
693         {
694           break;
695         }
696       if (Msg.message != WM_MOUSEMOVE)
697         {
698           continue;
699         }
700
701       Pressed = DefWndHitTestNC(hWnd, Msg.pt) == (LRESULT) wParam;
702       if (Pressed != OldState)
703         {
704           if (wParam == HTMINBUTTON)
705             {
706               UserDrawMinButton(hWnd, hDC, Pressed);
707             }
708           else
709             {
710               UserDrawMaxButton(hWnd, hDC, Pressed);
711             }
712         }
713     }
714
715   if (Pressed)
716     {
717       if (wParam == HTMINBUTTON)
718         {
719           UserDrawMinButton(hWnd, hDC, FALSE);
720         }
721       else
722         {
723           UserDrawMaxButton(hWnd, hDC, FALSE);
724         }
725     }
726
727   ReleaseCapture();
728   ReleaseDC(hWnd, hDC);
729
730   if (!Pressed)
731     {
732       return;
733     }
734
735   if (wParam == HTMINBUTTON)
736     {
737       SendMessageA(hWnd, WM_SYSCOMMAND, SC_MINIMIZE,
738                    MAKELONG(Msg.pt.x, Msg.pt.y));
739     }
740   else
741     {
742       SendMessageA(hWnd, WM_SYSCOMMAND,
743                    IsZoomed(hWnd) ? SC_RESTORE : SC_MAXIMIZE,
744                    MAKELONG(Msg.pt.x, Msg.pt.y));
745     }
746 }
747
748 VOID
749 DefWndDrawSysButton(HWND hWnd, HDC hDC, BOOL Down)
750 {
751   RECT Rect;
752   HDC hDcMem;
753   HBITMAP hSavedBitmap;
754
755   UserGetInsideRectNC(hWnd, &Rect);
756   hDcMem = CreateCompatibleDC(hDC);
757   hSavedBitmap = SelectObject(hDcMem, hbitmapClose);
758   BitBlt(hDC, Rect.left, Rect.top, GetSystemMetrics(SM_CXSIZE),
759          GetSystemMetrics(SM_CYSIZE), hDcMem,
760          (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) ?
761          GetSystemMetrics(SM_CXSIZE): 0, 0, Down ? NOTSRCCOPY : SRCCOPY);
762   SelectObject(hDcMem, hSavedBitmap);
763   DeleteDC(hDcMem);
764 }
765
766 LRESULT
767 DefWndHandleLButtonDownNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
768 {
769   switch (wParam)
770     {
771     case HTCAPTION:
772       {
773         HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
774         if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
775           {
776             SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
777           }
778         break;
779       }
780     case HTSYSMENU:
781       {
782         if (GetWindowLong(hWnd, GWL_STYLE) & WS_SYSMENU)
783           {
784             if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE))
785               {
786                 HDC hDC = GetWindowDC(hWnd);
787                 DefWndDrawSysButton(hWnd, hDC, TRUE);
788                 ReleaseDC(hWnd, hDC);
789               }
790             SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU,
791                          lParam);
792           }
793         break;
794       }
795
796     case HTMENU:
797       SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam);
798       break;
799
800     case HTHSCROLL:
801       SendMessageA(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
802       break;
803
804     case HTVSCROLL:
805       SendMessageA(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
806       break;
807
808     case HTMINBUTTON:
809     case HTMAXBUTTON:
810       DefWndTrackMinMaxBox(hWnd, wParam);
811       break;
812
813     case HTLEFT:
814     case HTRIGHT:
815     case HTTOP:
816     case HTBOTTOM:
817     case HTTOPLEFT:
818     case HTTOPRIGHT:
819     case HTBOTTOMLEFT:
820     case HTBOTTOMRIGHT:
821       SendMessageA(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
822       break;
823     }
824   return(0);
825 }
826
827 LRESULT
828 DefWndHandleLButtonDblClkNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
829 {
830   /* FIXME: Implement this. */
831   return(0);
832 }
833
834 LRESULT
835 DefWndHandleActiveNC(HWND hWnd, WPARAM wParam)
836 {
837   /* FIXME: Implement this. */
838   return(0);
839 }
840
841 VOID
842 DefWndSetRedraw(HWND hWnd, WPARAM wParam)
843 {
844 }
845
846 LRESULT
847 DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam)
848 {
849   /* Not for child windows. */
850   if (hWnd != (HWND)wParam)
851     {
852       return(0);
853     }
854
855   switch(LOWORD(lParam))
856     {
857     case HTERROR:
858       {
859         WORD Msg = HIWORD(lParam);
860         if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN ||
861             Msg == WM_RBUTTONDOWN)
862           {
863             MessageBeep(0);
864           }
865         break;
866       }
867
868     case HTCLIENT:
869       {
870         HICON hCursor = (HICON)GetClassLong(hWnd, GCL_HCURSOR);
871         if (hCursor)
872           {
873             SetCursor(hCursor);
874             return(TRUE);
875           }
876         return(FALSE);
877       }
878
879     case HTLEFT:
880     case HTRIGHT:
881       {
882         return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZEWE)));
883       }
884
885     case HTTOP:
886     case HTBOTTOM:
887       {
888         return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENS)));
889       }
890
891     case HTTOPLEFT:
892     case HTBOTTOMRIGHT:
893       {
894         return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENWSE)));
895       }
896
897     case HTBOTTOMLEFT:
898     case HTTOPRIGHT:
899       {
900         return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENESW)));
901       }
902     }
903   return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW)));
904 }
905
906 LRESULT
907 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
908 {
909   /* FIXME: Implement system commands. */
910   return(0);
911 }
912
913 VOID
914 DefWndAdjustRect(RECT* Rect, ULONG Style, BOOL Menu, ULONG ExStyle)
915 {
916   if (Style & WS_ICONIC)
917     {
918       return;
919     }
920
921   if (UserHasThickFrameStyle(Style, ExStyle))
922     {
923       InflateRect(Rect, GetSystemMetrics(SM_CXFRAME),
924                   GetSystemMetrics(SM_CYFRAME));
925     }
926   else if (UserHasDlgFrameStyle(Style, ExStyle))
927     {
928       InflateRect(Rect, GetSystemMetrics(SM_CXDLGFRAME),
929                   GetSystemMetrics(SM_CYDLGFRAME));
930     }
931   else if (UserHasThinFrameStyle(Style, ExStyle))
932     {
933       InflateRect(Rect, GetSystemMetrics(SM_CXBORDER),
934                   GetSystemMetrics(SM_CYBORDER));
935     }
936   if (Style & WS_CAPTION)
937     {
938       Rect->top -= GetSystemMetrics(SM_CYCAPTION) -
939         GetSystemMetrics(SM_CYBORDER);
940     }
941   if (Menu)
942     {
943       Rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
944     }
945   if (Style & WS_VSCROLL)
946     {
947       Rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
948       if (UserHasAnyFrameStyle(Style, ExStyle))
949         {
950           Rect->right++;
951         }
952     }
953   if (Style & WS_HSCROLL)
954     {
955       Rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
956       if (UserHasAnyFrameStyle(Style, ExStyle))
957         {
958           Rect->bottom++;
959         }
960     }
961 }
962
963 LRESULT STDCALL
964 DefWndNCCalcSize(HWND hWnd, RECT* Rect)
965 {
966   LRESULT Result = 0;
967   LONG Style = GetClassLongW(hWnd, GCL_STYLE);
968   RECT TmpRect = {0, 0, 0, 0};
969
970   if (Style & CS_VREDRAW)
971     {
972       Result |= WVR_VREDRAW;
973     }
974   if (Style & CS_HREDRAW)
975     {
976       Result |= WVR_HREDRAW;
977     }
978
979   if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE))
980     {
981       DefWndAdjustRect(&TmpRect, GetWindowLong(hWnd, GWL_STYLE),
982                        FALSE, GetWindowLong(hWnd, GWL_EXSTYLE));
983       Rect->left -= TmpRect.left;
984       Rect->top -= TmpRect.top;
985       Rect->right -= TmpRect.right;
986       Rect->bottom -= TmpRect.bottom;
987       /* FIXME: Adjust if the window has a menu. */
988       Rect->bottom = max(Rect->top, Rect->bottom);
989       Rect->right = max(Rect->left, Rect->right);
990     }
991   return(Result);
992 }
993
994 LRESULT
995 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
996 {
997   /* FIXME: Implement this. */
998   return(0);
999 }
1000
1001 LRESULT STDCALL
1002 User32DefWindowProc(HWND hWnd,
1003                     UINT Msg,
1004                     WPARAM wParam,
1005                     LPARAM lParam,
1006                     BOOL bUnicode)
1007 {
1008   switch (Msg)
1009     {
1010     case WM_NCPAINT:
1011       {
1012         return(DefWndPaintNC(hWnd, (HRGN)wParam));
1013       }
1014
1015     case WM_NCHITTEST:
1016       {
1017         POINT Point;
1018         Point.x = SLOWORD(lParam);
1019         Point.y = SHIWORD(lParam);
1020         return(DefWndHitTestNC(hWnd, Point));
1021       }
1022
1023     case WM_NCLBUTTONDOWN:
1024       {
1025         return(DefWndHandleLButtonDownNC(hWnd, wParam, lParam));
1026       }
1027
1028     case WM_LBUTTONDBLCLK:
1029     case WM_NCLBUTTONDBLCLK:
1030       {
1031         return(DefWndHandleLButtonDblClkNC(hWnd, wParam, lParam));
1032       }
1033
1034     case WM_NCRBUTTONDOWN:
1035       {
1036         if (wParam == HTCAPTION)
1037           {
1038             SetCapture(hWnd);
1039           }
1040         break;
1041       }
1042
1043     case WM_RBUTTONUP:
1044       {
1045         POINT Pt;
1046         if (hWnd == GetCapture())
1047           {
1048             ReleaseCapture();
1049           }
1050         Pt.x = SLOWORD(lParam);
1051         Pt.y = SHIWORD(lParam);
1052         ClientToScreen(hWnd, &Pt);
1053         lParam = MAKELPARAM(Pt.x, Pt.y);
1054         if (bUnicode)
1055           {
1056             SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1057           }
1058         else
1059           {
1060             SendMessageA (hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1061           }
1062         break;
1063       }
1064
1065     case WM_NCRBUTTONUP:
1066       {
1067         /* Wine does nothing here. */
1068         break;
1069       }
1070
1071     case WM_CONTEXTMENU:
1072       {
1073         if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1074           {
1075             if (bUnicode)
1076               {
1077                 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1078               }
1079             else
1080               {
1081                 SendMessageA(hWnd, WM_CONTEXTMENU, wParam, lParam);
1082               }
1083           }
1084         else
1085           {
1086             LONG HitCode;
1087             POINT Pt;
1088
1089             Pt.x = SLOWORD(lParam);
1090             Pt.y = SHIWORD(lParam);
1091
1092             if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1093               {
1094                 ScreenToClient(GetParent(hWnd), &Pt);
1095               }
1096
1097             HitCode = DefWndHitTestNC(hWnd, Pt);
1098
1099             if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
1100               {
1101                 TrackPopupMenu(GetSystemMenu(hWnd, FALSE),
1102                                TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
1103                                Pt.x, Pt.y, 0, hWnd, NULL);
1104               }
1105           }
1106         break;
1107       }
1108
1109     case WM_NCACTIVATE:
1110       {
1111         return(DefWndHandleActiveNC(hWnd, wParam));
1112       }
1113
1114     case WM_NCDESTROY:
1115       {
1116         return(0);
1117       }
1118
1119     case WM_PRINT:
1120       {
1121         return(0);
1122       }
1123
1124     case WM_PAINTICON:
1125     case WM_PAINT:
1126       {
1127         PAINTSTRUCT Ps;
1128         HDC hDc = BeginPaint(hWnd, &Ps);
1129         if (hDc)
1130           {
1131             HICON hIcon;
1132             if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1133                 (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
1134               {
1135                 RECT WindowRect;
1136                 INT x, y;
1137                 GetWindowRect(hWnd, &WindowRect);
1138                 x = (WindowRect.right - WindowRect.left -
1139                      GetSystemMetrics(SM_CXICON)) / 2;
1140                 y = (WindowRect.bottom - WindowRect.top -
1141                      GetSystemMetrics(SM_CYICON)) / 2;
1142                 DrawIcon(hDc, x, y, hIcon);
1143               }
1144             EndPaint(hWnd, &Ps);
1145           }
1146         return(0);
1147       }
1148
1149     case WM_SYNCPAINT:
1150       {
1151         HRGN hRgn;
1152         hRgn = CreateRectRgn(0, 0, 0, 0);
1153         if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1154           {
1155             RedrawWindow(hWnd, NULL, hRgn,
1156                          RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1157                          RDW_ALLCHILDREN);
1158           }
1159         DeleteObject(hRgn);
1160         return(0);
1161       }
1162
1163     case WM_SETREDRAW:
1164       {
1165         DefWndSetRedraw(hWnd, wParam);
1166         return(0);
1167       }
1168
1169     case WM_CLOSE:
1170       {
1171         DestroyWindow(hWnd);
1172         return(0);
1173       }
1174
1175     case WM_MOUSEACTIVATE:
1176       {
1177         if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1178           {
1179             LONG Ret;
1180             if (bUnicode)
1181               {
1182                 Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1183                                    wParam, lParam);
1184               }
1185             else
1186               {
1187                 Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1188                                    wParam, lParam);
1189               }
1190             if (Ret)
1191               {
1192                 return(Ret);
1193               }
1194           }
1195         return((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1196       }
1197
1198     case WM_ACTIVATE:
1199       {
1200         if (LOWORD(lParam) != WA_INACTIVE &&
1201             GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE)
1202           {
1203             /* Check if the window is minimized. */
1204             SetFocus(hWnd);
1205           }
1206         break;
1207       }
1208
1209     case WM_MOUSEWHEEL:
1210       {
1211         if (GetWindowLong(hWnd, GWL_STYLE & WS_CHILD))
1212           {
1213             if (bUnicode)
1214               {
1215                 return(SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1216                                     wParam, lParam));
1217               }
1218             else
1219               {
1220                 return(SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1221                                     wParam, lParam));
1222               }
1223           }
1224         break;
1225       }
1226
1227     case WM_ERASEBKGND:
1228     case WM_ICONERASEBKGND:
1229       {
1230         RECT Rect;
1231         HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
1232         GetClipBox((HDC)wParam, &Rect);
1233         FillRect((HDC)wParam, &Rect, hBrush);
1234         return(1);
1235       }
1236
1237     case WM_GETDLGCODE:
1238       {
1239         return(0);
1240       }
1241
1242       /* FIXME: Implement colour controls. */
1243
1244     case WM_SETCURSOR:
1245       {
1246         if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1247           {
1248             if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1249               {
1250                 BOOL bResult;
1251                 if (bUnicode)
1252                   {
1253                     bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
1254                                            wParam, lParam);
1255                   }
1256                 else
1257                   {
1258                     bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
1259                                            wParam, lParam);
1260                   }
1261                 if (bResult)
1262                   {
1263                     return(TRUE);
1264                   }
1265               }
1266           }
1267         return(DefWndHandleSetCursor(hWnd, wParam, lParam));
1268       }
1269
1270     case WM_SYSCOMMAND:
1271       {
1272         POINT Pt;
1273         Pt.x = SLOWORD(lParam);
1274         Pt.y = SHIWORD(lParam);
1275         return(DefWndHandleSysCommand(hWnd, wParam, Pt));
1276       }
1277
1278       /* FIXME: Handle key messages. */
1279
1280     case WM_SHOWWINDOW:
1281       {
1282         if (lParam)
1283           {
1284             return(0);
1285           }
1286         /* FIXME: Check for a popup window. */
1287         if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_VISIBLE && !wParam) ||
1288             (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_VISIBLE) && wParam))
1289           {
1290             return(0);
1291           }
1292         ShowWindow(hWnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE);
1293         break;
1294       }
1295
1296     case WM_CANCELMODE:
1297       {
1298         /* FIXME: Check for a desktop. */
1299         if (GetCapture() == hWnd)
1300           {
1301             ReleaseCapture();
1302           }
1303         break;
1304       }
1305
1306     case WM_VKEYTOITEM:
1307     case WM_CHARTOITEM:
1308       return(-1);
1309
1310     case WM_DROPOBJECT:
1311       /* FIXME: Implement this. */
1312       break;
1313
1314     case WM_QUERYDROPOBJECT:
1315       {
1316         if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1317           {
1318             return(1);
1319           }
1320         break;
1321       }
1322
1323     case WM_QUERYDRAGICON:
1324       {
1325         UINT Len;
1326         HICON hIcon;
1327
1328         hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
1329         if (hIcon)
1330           {
1331             return((LRESULT)hIcon);
1332           }
1333         for (Len = 1; Len < 64; Len++)
1334           {
1335             if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCE(Len))) != NULL)
1336               {
1337                 return((LRESULT)hIcon);
1338               }
1339           }
1340         return((LRESULT)LoadIconW(0, IDI_APPLICATION));
1341       }
1342
1343       /* FIXME: WM_ISACTIVEICON */
1344
1345     case WM_NOTIFYFORMAT:
1346       {
1347         if (IsWindowUnicode(hWnd))
1348           {
1349             return(NFR_UNICODE);
1350           }
1351         else
1352           {
1353             return(NFR_ANSI);
1354           }
1355       }
1356
1357     case WM_SETICON:
1358       {
1359         INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1360         HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
1361         SetClassLongW(hWnd, Index, lParam);
1362         SetWindowPos(hWnd, 0, 0, 0, 0, 0,
1363                      SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1364                      SWP_NOACTIVATE | SWP_NOZORDER);
1365         return((LRESULT)hOldIcon);
1366       }
1367
1368     case WM_GETICON:
1369       {
1370         INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1371         return(GetClassLongW(hWnd, Index));
1372       }
1373
1374     case WM_HELP:
1375       {
1376         if (bUnicode)
1377           {
1378             SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1379           }
1380         else
1381           {
1382             SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1383           }
1384         break;
1385       }
1386     }
1387   return 0;
1388 }
1389
1390 LRESULT STDCALL
1391 DefWindowProcA(HWND hWnd,
1392                UINT Msg,
1393                WPARAM wParam,
1394                LPARAM lParam)
1395 {
1396   LRESULT Result;
1397   static LPSTR WindowTextAtom = 0;
1398   PSTR WindowText;
1399
1400   switch (Msg)
1401     {
1402     case WM_NCCREATE:
1403       {
1404         CREATESTRUCTA* Cs = (CREATESTRUCTA*)lParam;
1405         if (HIWORD(Cs->lpszName))
1406           {
1407             WindowTextAtom =
1408               (LPSTR)(ULONG)GlobalAddAtomA("USER32!WindowTextAtomA");
1409             WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1410                                          strlen(Cs->lpszName) * sizeof(CHAR));
1411             strcpy(WindowText, Cs->lpszName);
1412             SetPropA(hWnd, WindowTextAtom, WindowText);
1413           }
1414         return(1);
1415       }
1416
1417     case WM_NCCALCSIZE:
1418       {
1419         return(DefWndNCCalcSize(hWnd, (RECT*)lParam));
1420       }
1421
1422     case WM_WINDOWPOSCHANGING:
1423       {
1424         return(DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1425       }
1426
1427     case WM_GETTEXTLENGTH:
1428       {
1429         if (WindowTextAtom == 0 ||
1430             (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1431           {
1432             return(0);
1433           }
1434         return(strlen(WindowText));
1435       }
1436
1437     case WM_GETTEXT:
1438       {
1439         if (WindowTextAtom == 0 ||
1440             (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1441           {
1442             if (wParam > 1)
1443               {
1444                 ((PSTR)lParam) = '\0';
1445               }
1446             return(0);
1447           }
1448         strncpy((LPSTR)lParam, WindowText, wParam);
1449         return(min(wParam, strlen(WindowText)));
1450       }
1451
1452     case WM_SETTEXT:
1453       {
1454         if (WindowTextAtom != 0)
1455           {
1456             WindowTextAtom =
1457               (LPSTR)(DWORD)GlobalAddAtomA("USER32!WindowTextAtomW");
1458           }
1459         if (WindowTextAtom != 0 &&
1460             (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1461           {
1462             RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1463           }
1464         WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1465                                      strlen((PSTR)lParam) * sizeof(CHAR));
1466         strcpy(WindowText, (PSTR)lParam);
1467         SetPropA(hWnd, WindowTextAtom, WindowText);
1468       }
1469
1470     case WM_NCDESTROY:
1471       {
1472         if (WindowTextAtom != 0 &&
1473             (WindowText = RemovePropA(hWnd, WindowTextAtom)) == NULL)
1474           {
1475             RtlFreeHeap(GetProcessHeap(), 0, WindowText);
1476           }
1477         if (WindowTextAtom != 0)
1478           {
1479             GlobalDeleteAtom((ATOM)(ULONG)WindowTextAtom);
1480           }
1481         /* FIXME: Destroy scroll bars here as well. */
1482         return(0);
1483       }
1484
1485     default:
1486       Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1487       break;
1488     }
1489
1490   return(Result);
1491 }
1492
1493 LRESULT STDCALL
1494 DefWindowProcW(HWND hWnd,
1495                UINT Msg,
1496                WPARAM wParam,
1497                LPARAM lParam)
1498 {
1499   LRESULT Result;
1500   static LPWSTR WindowTextAtom = 0;
1501   PWSTR WindowText;
1502
1503   switch (Msg)
1504     {
1505     case WM_NCCREATE:
1506       {
1507         CREATESTRUCTW* Cs = (CREATESTRUCTW*)lParam;
1508         if (HIWORD(Cs->lpszName))
1509           {
1510             WindowTextAtom =
1511               (LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
1512             WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1513                                          wcslen(Cs->lpszName) * sizeof(WCHAR));
1514             wcscpy(WindowText, Cs->lpszName);
1515             SetPropW(hWnd, WindowTextAtom, WindowText);
1516           }
1517         return(1);
1518       }
1519
1520     case WM_NCCALCSIZE:
1521       {
1522         return(DefWndNCCalcSize(hWnd, (RECT*)lParam));
1523       }
1524
1525     case WM_WINDOWPOSCHANGING:
1526       {
1527         return(DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1528       }
1529
1530     case WM_GETTEXTLENGTH:
1531       {
1532         if (WindowTextAtom == 0 ||
1533             (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1534           {
1535             return(0);
1536           }
1537         return(wcslen(WindowText));
1538       }
1539
1540     case WM_GETTEXT:
1541       {
1542         if (WindowTextAtom == 0 ||
1543             (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1544           {
1545             if (wParam > 1)
1546               {
1547                 ((PWSTR)lParam) = '\0';
1548               }
1549             return(0);
1550           }
1551         wcsncpy((PWSTR)lParam, WindowText, wParam);
1552         return(min(wParam, wcslen(WindowText)));
1553       }
1554
1555     case WM_SETTEXT:
1556       {
1557         if (WindowTextAtom != 0)
1558           {
1559             WindowTextAtom =
1560               (LPWSTR)(DWORD)GlobalAddAtom(L"USER32!WindowTextAtomW");
1561           }
1562         if (WindowTextAtom != 0 &&
1563             (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1564           {
1565             RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1566           }
1567         WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1568                                      wcslen((PWSTR)lParam) * sizeof(WCHAR));
1569         wcscpy(WindowText, (PWSTR)lParam);
1570         SetPropW(hWnd, WindowTextAtom, WindowText);
1571       }
1572           //FIXME: return correct code
1573           return TRUE;
1574
1575     case WM_NCDESTROY:
1576       {
1577         if (WindowTextAtom != 0 &&
1578             (WindowText = RemovePropW(hWnd, WindowTextAtom)) == NULL)
1579           {
1580             RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1581           }
1582         if (WindowTextAtom != 0)
1583           {
1584             GlobalDeleteAtom((ATOM)(DWORD)WindowTextAtom);
1585           }
1586         /* FIXME: Destroy scroll bars here as well. */
1587         return(0);
1588       }
1589
1590     default:
1591       Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
1592       break;
1593     }
1594
1595   return(Result);
1596 }