update for HEAD-2002110701
[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 static 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
415 DefWndDoPaintNC(HWND hWnd, HRGN clip)
416 {
417   ULONG Active;
418   HDC hDc;
419   RECT rect;
420   ULONG Style;
421   ULONG ExStyle;
422
423   Active = GetWindowLongW(hWnd, GWL_STYLE) & WIN_NCACTIVATED;
424   Style = GetWindowLong(hWnd, GWL_STYLE);
425   ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
426
427   hDc = GetDCEx(hWnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
428                 ((clip > (HRGN)1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0));
429   if (hDc == 0)
430     {
431       return;
432     }
433
434   /* FIXME: Test whether we need to draw anything at all. */
435
436   GetWindowRect(hWnd, &rect);
437   rect.right = rect.right - rect.left;
438   rect.bottom = rect.bottom - rect.top;
439   rect.top = rect.left = 0;
440
441   SelectObject(hDc, GetSysColorPen(COLOR_WINDOWFRAME));
442   if (UserHasAnyFrameStyle(Style, ExStyle))
443     {
444       SelectObject(hDc, GetStockObject(NULL_BRUSH));
445       Rectangle(hDc, 0, 0, rect.right, rect.bottom);
446       InflateRect(&rect, -1, -1);
447     }
448   
449   if (UserHasThickFrameStyle(Style, ExStyle))
450     {
451       UserDrawFrameNC(hDc, &rect, FALSE, Active);
452     }
453   else if (UserHasDlgFrameStyle(Style, ExStyle))
454     {
455       UserDrawFrameNC(hDc, &rect, TRUE, Active);
456     }
457   
458   if (Style & WS_CAPTION)
459     {
460       RECT r = rect;
461       r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
462       rect.top += GetSystemMetrics(SM_CYSIZE) + 
463         GetSystemMetrics(SM_CYBORDER);
464       UserDrawCaptionNC(hDc, &r, hWnd, Style, Active);
465     }
466
467   /* FIXME: Draw menu bar. */
468
469   /* FIXME: Draw scroll bars. */
470
471   /* FIXME: Draw size box. */
472   
473   ReleaseDC(hWnd, hDc);
474 }
475
476 LRESULT
477 DefWndPaintNC(HWND hWnd, HRGN clip)
478 {
479   if (IsWindowVisible(hWnd))
480     {
481       if (IsIconic(hWnd))
482         {
483           DefWndRedrawIconTitle(hWnd);
484         }
485       else
486         {
487           DefWndDoPaintNC(hWnd, clip);
488         }
489     }
490   return(0);
491 }
492
493 LRESULT
494 DefWndHitTestNC(HWND hWnd, POINT Point)
495 {
496   RECT WindowRect;
497   ULONG Style = GetWindowLong(hWnd, GWL_STYLE);
498   ULONG ExStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
499
500   GetWindowRect(hWnd, &WindowRect);
501
502   if (!PtInRect(&WindowRect, Point))
503     {
504       return(HTNOWHERE);
505     }
506   if (Style & WS_MINIMIZE)
507     {
508       return(HTCAPTION);
509     }
510   if (UserHasThickFrameStyle(Style, ExStyle))
511     {
512       InflateRect(&WindowRect, -GetSystemMetrics(SM_CXFRAME),
513                   -GetSystemMetrics(SM_CYFRAME));
514       if (!PtInRect(&WindowRect, Point))
515         {
516           if (Point.y < WindowRect.top)
517             {
518               if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE)))
519                 {
520                   return(HTTOPLEFT);
521                 }
522               if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE)))
523                 {
524                   return(HTTOPRIGHT);
525                 }
526               return(HTTOP);
527             }
528           if (Point.y >= WindowRect.bottom)
529             {
530               if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE)))
531                 {
532                   return(HTBOTTOMLEFT);
533                 }
534               if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE)))
535                 {
536                   return(HTBOTTOMRIGHT);
537                 }
538               return(HTBOTTOM);
539             }
540           if (Point.x < WindowRect.left)
541             {
542               if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE)))
543                 {
544                   return(HTTOPLEFT);
545                 }
546               if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE)))
547                 {
548                   return(HTBOTTOMLEFT);
549                 }
550               return(HTLEFT);
551             }
552           if (Point.x >= WindowRect.right)
553             {
554               if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE)))
555                 {
556                   return(HTTOPRIGHT);
557                 }
558               if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE)))
559                 {
560                   return(HTBOTTOMRIGHT);
561                 }
562               return(HTRIGHT);
563             }
564         }      
565     }
566   else 
567     {
568       if (UserHasDlgFrameStyle(Style, ExStyle))
569         {
570           InflateRect(&WindowRect, -GetSystemMetrics(SM_CXDLGFRAME),
571                       -GetSystemMetrics(SM_CYDLGFRAME));
572         }
573       else if (UserHasThinFrameStyle(Style, ExStyle))
574         {
575           InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER),
576                       -GetSystemMetrics(SM_CYBORDER));
577         }
578       if (!PtInRect(&WindowRect, Point))
579         {
580           return(HTBORDER);
581         }
582     }
583
584   if ((Style & WS_CAPTION) == WS_CAPTION)
585     {
586       WindowRect.top += GetSystemMetrics(SM_CYCAPTION) - 
587         GetSystemMetrics(SM_CYBORDER);
588       if (!PtInRect(&WindowRect, Point))
589         {
590           if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW))
591             {
592               WindowRect.left += GetSystemMetrics(SM_CXSIZE);
593             }
594           if (Point.x <= WindowRect.left)
595             {
596               return(HTSYSMENU);
597             }
598
599           if (Style & WS_MAXIMIZEBOX)
600             {
601               WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
602             }
603           if (Point.x >= WindowRect.right)
604             {
605               return(HTMAXBUTTON);
606             }
607
608           if (Style & WS_MINIMIZEBOX)
609             {
610               WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
611             }
612           if (Point.x >= WindowRect.right)
613             {
614               return(HTMINBUTTON);
615             }
616           return(HTCAPTION);
617         }
618     }
619
620   ScreenToClient(hWnd, &Point);
621   GetClientRect(hWnd, &WindowRect);
622
623   if (PtInRect(&WindowRect, Point))
624     {
625       return(HTCLIENT);
626     }
627
628   if (Style & WS_VSCROLL)
629     {
630       WindowRect.right += GetSystemMetrics(SM_CXVSCROLL);
631       if (PtInRect(&WindowRect, Point))
632         {
633           return(HTVSCROLL);
634         }
635     }
636
637   if (Style & WS_HSCROLL)
638     {
639       WindowRect.bottom += GetSystemMetrics(SM_CYHSCROLL);
640       if (PtInRect(&WindowRect, Point))
641         {
642           if ((Style & WS_VSCROLL) &&
643               (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXVSCROLL))))
644             {
645               return(HTSIZE);
646             }
647           return(HTHSCROLL);
648         }
649     }
650
651   if (UserHasMenu(hWnd, Style))
652     {
653       if (Point.y < 0 && Point.x >= 0 && Point.x <= WindowRect.right)
654         {
655           return(HTMENU);
656         }
657     }
658
659   return(HTNOWHERE);
660 }
661
662 VOID
663 DefWndTrackMinMaxBox(HWND hWnd, WPARAM wParam)
664 {
665   HDC hDC = GetWindowDC(hWnd);
666   BOOL Pressed = TRUE;
667   MSG Msg;
668
669   SetCapture(hWnd);
670
671   if (wParam == HTMINBUTTON)
672     {
673       UserDrawMinButton(hWnd, hDC, TRUE);
674     }
675   else
676     {
677       UserDrawMaxButton(hWnd, hDC, TRUE);
678     }
679
680   for(;;)
681     {
682       BOOL OldState = Pressed;      
683
684       GetMessageA(hWnd, &Msg, 0, 0);
685       if (Msg.message == WM_LBUTTONUP)
686         {
687           break;
688         }
689       if (Msg.message != WM_MOUSEMOVE)
690         {
691           continue;
692         }
693
694       Pressed = DefWndHitTestNC(hWnd, Msg.pt) == wParam;
695       if (Pressed != OldState)
696         {
697           if (wParam == HTMINBUTTON)
698             {
699               UserDrawMinButton(hWnd, hDC, Pressed);
700             }
701           else
702             {
703               UserDrawMaxButton(hWnd, hDC, Pressed);
704             }
705         }
706     }
707
708   if (Pressed)
709     {
710       if (wParam == HTMINBUTTON)
711         {
712           UserDrawMinButton(hWnd, hDC, FALSE);
713         }
714       else
715         {
716           UserDrawMaxButton(hWnd, hDC, FALSE);
717         }
718     }
719
720   ReleaseCapture();
721   ReleaseDC(hWnd, hDC);
722
723   if (!Pressed)
724     {
725       return;
726     }
727
728   if (wParam == HTMINBUTTON)
729     {
730       SendMessageA(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 
731                    MAKELONG(Msg.pt.x, Msg.pt.y));
732     }
733   else
734     {
735       SendMessageA(hWnd, WM_SYSCOMMAND, 
736                    IsZoomed(hWnd) ? SC_RESTORE : SC_MAXIMIZE, 
737                    MAKELONG(Msg.pt.x, Msg.pt.y));
738     }
739 }
740
741 VOID
742 DefWndDrawSysButton(HWND hWnd, HDC hDC, BOOL Down)
743 {
744   RECT Rect;
745   HDC hDcMem;
746   HBITMAP hSavedBitmap;
747
748   UserGetInsideRectNC(hWnd, &Rect);
749   hDcMem = CreateCompatibleDC(hDC);
750   hSavedBitmap = SelectObject(hDcMem, hbitmapClose);
751   BitBlt(hDC, Rect.left, Rect.top, GetSystemMetrics(SM_CXSIZE),
752          GetSystemMetrics(SM_CYSIZE), hDcMem, 
753          (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD) ? 
754          GetSystemMetrics(SM_CXSIZE): 0, 0, Down ? NOTSRCCOPY : SRCCOPY);
755   SelectObject(hDcMem, hSavedBitmap);
756   DeleteDC(hDcMem);
757 }
758
759 LRESULT
760 DefWndHandleLButtonDownNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
761 {
762   switch (wParam)
763     {
764     case HTCAPTION:
765       {
766         HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
767         if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
768           {
769             SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
770           }
771         break;
772       }
773     case HTSYSMENU:
774       {
775         if (GetWindowLong(hWnd, GWL_STYLE) & WS_SYSMENU)
776           {
777             if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE))
778               {
779                 HDC hDC = GetWindowDC(hWnd);
780                 DefWndDrawSysButton(hWnd, hDC, TRUE);
781                 ReleaseDC(hWnd, hDC);
782               }
783             SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, 
784                          lParam);
785           }
786         break;
787       }
788
789     case HTMENU:
790       SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam);
791       break;
792
793     case HTHSCROLL:
794       SendMessageA(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
795       break;
796
797     case HTVSCROLL:
798       SendMessageA(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
799       break;
800
801     case HTMINBUTTON:
802     case HTMAXBUTTON:
803       DefWndTrackMinMaxBox(hWnd, wParam);
804       break;
805
806     case HTLEFT:
807     case HTRIGHT:
808     case HTTOP:
809     case HTBOTTOM:
810     case HTTOPLEFT:
811     case HTTOPRIGHT:
812     case HTBOTTOMLEFT:
813     case HTBOTTOMRIGHT:
814       SendMessageA(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
815       break;
816     }
817   return(0);
818 }
819
820 LRESULT
821 DefWndHandleLButtonDblClkNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
822 {
823   /* FIXME: Implement this. */
824   return(0);
825 }
826
827 LRESULT
828 DefWndHandleActiveNC(HWND hWnd, WPARAM wParam)
829 {
830   /* FIXME: Implement this. */
831   return(0);
832 }
833
834 VOID
835 DefWndSetRedraw(HWND hWnd, WPARAM wParam)
836 {
837 }
838
839 LRESULT 
840 DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam)
841 {
842   /* Not for child windows. */
843   if (hWnd != (HWND)wParam)
844     {
845       return(0);
846     }
847
848   switch(LOWORD(lParam))
849     {
850     case HTERROR:
851       {
852         WORD Msg = HIWORD(lParam);
853         if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN ||
854             Msg == WM_RBUTTONDOWN)
855           {
856             MessageBeep(0);
857           }
858         break;
859       }
860
861     case HTCLIENT:
862       {
863         HICON hCursor = (HICON)GetClassLong(hWnd, GCL_HCURSOR);
864         if (hCursor)
865           {
866             SetCursor(hCursor);
867             return(TRUE);
868           }
869         return(FALSE);
870       }
871
872     case HTLEFT:
873     case HTRIGHT:
874       {
875         return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZEWE)));
876       }
877
878     case HTTOP:
879     case HTBOTTOM:
880       {
881         return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENS)));
882       }
883
884     case HTTOPLEFT:
885     case HTBOTTOMRIGHT:
886       {
887         return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENWSE)));
888       }
889
890     case HTBOTTOMLEFT:
891     case HTTOPRIGHT:
892       {
893         return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENESW)));
894       }
895     }
896   return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW)));
897 }
898
899 LRESULT
900 DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
901 {
902   /* FIXME: Implement system commands. */
903   return(0);
904 }
905
906 VOID
907 DefWndAdjustRect(RECT* Rect, ULONG Style, BOOL Menu, ULONG ExStyle)
908 {
909   if (Style & WS_ICONIC)
910     {
911       return;
912     }
913
914   if (UserHasThickFrameStyle(Style, ExStyle))
915     {
916       InflateRect(Rect, GetSystemMetrics(SM_CXFRAME), 
917                   GetSystemMetrics(SM_CYFRAME));
918     }
919   else if (UserHasDlgFrameStyle(Style, ExStyle))
920     {
921       InflateRect(Rect, GetSystemMetrics(SM_CXDLGFRAME),
922                   GetSystemMetrics(SM_CYDLGFRAME));
923     }
924   else if (UserHasThinFrameStyle(Style, ExStyle))
925     {
926       InflateRect(Rect, GetSystemMetrics(SM_CXBORDER),
927                   GetSystemMetrics(SM_CYBORDER));
928     }
929   if (Style & WS_CAPTION)
930     {
931       Rect->top -= GetSystemMetrics(SM_CYCAPTION) - 
932         GetSystemMetrics(SM_CYBORDER);
933     }
934   if (Menu)
935     {
936       Rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
937     }
938   if (Style & WS_VSCROLL)
939     {
940       Rect->right += GetSystemMetrics(SM_CXVSCROLL) - 1;
941       if (UserHasAnyFrameStyle(Style, ExStyle))
942         {
943           Rect->right++;
944         }
945     }
946   if (Style & WS_HSCROLL)
947     {
948       Rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
949       if (UserHasAnyFrameStyle(Style, ExStyle))
950         {
951           Rect->bottom++;
952         }
953     }
954 }
955
956 LRESULT STDCALL
957 DefWndNCCalcSize(HWND hWnd, RECT* Rect)
958 {
959   LRESULT Result = 0;
960   LONG Style = GetClassLongW(hWnd, GCL_STYLE);
961   RECT TmpRect = {0, 0, 0, 0};
962
963   if (Style & CS_VREDRAW)
964     {
965       Result |= WVR_VREDRAW;
966     }
967   if (Style & CS_HREDRAW)
968     {
969       Result |= WVR_HREDRAW;
970     }
971
972   if (!(GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE))
973     {
974       DefWndAdjustRect(&TmpRect, GetWindowLong(hWnd, GWL_STYLE),
975                        FALSE, GetWindowLong(hWnd, GWL_EXSTYLE));
976       Rect->left -= TmpRect.left;
977       Rect->top -= TmpRect.top;
978       Rect->right -= TmpRect.right;
979       Rect->bottom -= TmpRect.bottom;
980       /* FIXME: Adjust if the window has a menu. */
981       Rect->bottom = max(Rect->top, Rect->bottom);
982       Rect->right = max(Rect->left, Rect->right);
983     }
984   return(Result);
985 }
986
987 LRESULT
988 DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
989 {
990   /* FIXME: Implement this. */
991   return(0);
992 }
993
994 LRESULT STDCALL
995 User32DefWindowProc(HWND hWnd,
996                     UINT Msg,
997                     WPARAM wParam,
998                     LPARAM lParam,
999                     BOOL bUnicode)
1000 {
1001   switch (Msg)
1002     {
1003     case WM_NCPAINT:
1004       {
1005         return(DefWndPaintNC(hWnd, (HRGN)wParam));
1006       }
1007
1008     case WM_NCHITTEST:
1009       {
1010         POINT Point;
1011         Point.x = SLOWORD(lParam);
1012         Point.y = SHIWORD(lParam);
1013         return(DefWndHitTestNC(hWnd, Point));
1014       }
1015
1016     case WM_NCLBUTTONDOWN:
1017       {
1018         return(DefWndHandleLButtonDownNC(hWnd, wParam, lParam));
1019       }
1020
1021     case WM_LBUTTONDBLCLK:
1022     case WM_NCLBUTTONDBLCLK:
1023       {
1024         return(DefWndHandleLButtonDblClkNC(hWnd, wParam, lParam));
1025       }
1026
1027     case WM_NCRBUTTONDOWN:
1028       {
1029         if (wParam == HTCAPTION)
1030           {
1031             SetCapture(hWnd);
1032           }
1033         break;
1034       }
1035
1036     case WM_RBUTTONUP:
1037       {
1038         POINT Pt;
1039         if (hWnd == GetCapture())
1040           {
1041             ReleaseCapture();
1042           }
1043         Pt.x = SLOWORD(lParam);
1044         Pt.y = SHIWORD(lParam);
1045         ClientToScreen(hWnd, &Pt);
1046         lParam = MAKELPARAM(Pt.x, Pt.y);
1047         if (bUnicode)
1048           {
1049             SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1050           }
1051         else
1052           {
1053             SendMessageA (hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
1054           }
1055         break;
1056       }
1057
1058     case WM_NCRBUTTONUP:
1059       {
1060         /* Wine does nothing here. */
1061         break;
1062       }
1063
1064     case WM_CONTEXTMENU:
1065       {
1066         if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1067           {
1068             if (bUnicode)
1069               {
1070                 SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1071               }
1072             else
1073               {
1074                 SendMessageA(hWnd, WM_CONTEXTMENU, wParam, lParam);
1075               }
1076           }
1077         else
1078           {
1079             LONG HitCode;
1080             POINT Pt;
1081
1082             Pt.x = SLOWORD(lParam);
1083             Pt.y = SHIWORD(lParam);
1084             
1085             if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1086               {
1087                 ScreenToClient(GetParent(hWnd), &Pt);
1088               }
1089
1090             HitCode = DefWndHitTestNC(hWnd, Pt);
1091
1092             if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
1093               {
1094                 TrackPopupMenu(GetSystemMenu(hWnd, FALSE),
1095                                TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
1096                                Pt.x, Pt.y, 0, hWnd, NULL);
1097               }
1098           }
1099         break;
1100       }
1101
1102     case WM_NCACTIVATE:
1103       {
1104         return(DefWndHandleActiveNC(hWnd, wParam));
1105       }
1106
1107     case WM_NCDESTROY:
1108       {
1109         return(0);
1110       }
1111
1112     case WM_PRINT:
1113       {
1114         return(0);
1115       }
1116
1117     case WM_PAINTICON:
1118     case WM_PAINT:
1119       {
1120         PAINTSTRUCT Ps;
1121         HDC hDc = BeginPaint(hWnd, &Ps);
1122         if (hDc)
1123           {
1124             HICON hIcon;
1125             if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
1126                 (hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
1127               {
1128                 RECT WindowRect;
1129                 INT x, y;
1130                 GetWindowRect(hWnd, &WindowRect);
1131                 x = (WindowRect.right - WindowRect.left - 
1132                      GetSystemMetrics(SM_CXICON)) / 2;
1133                 y = (WindowRect.bottom - WindowRect.top - 
1134                      GetSystemMetrics(SM_CYICON)) / 2;
1135                 DrawIcon(hDc, x, y, hIcon);
1136               }
1137             EndPaint(hWnd, &Ps);
1138           }
1139         return(0);
1140       }
1141
1142     case WM_SYNCPAINT:
1143       {
1144         HRGN hRgn;
1145         hRgn = CreateRectRgn(0, 0, 0, 0);
1146         if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
1147           {
1148             RedrawWindow(hWnd, NULL, hRgn, 
1149                          RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
1150                          RDW_ALLCHILDREN);
1151           }
1152         DeleteObject(hRgn);
1153         return(0);
1154       }
1155
1156     case WM_SETREDRAW:
1157       {
1158         DefWndSetRedraw(hWnd, wParam);
1159         return(0);
1160       }
1161
1162     case WM_CLOSE:
1163       {
1164         DestroyWindow(hWnd);
1165         return(0);
1166       }
1167
1168     case WM_MOUSEACTIVATE:
1169       {
1170         if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1171           {
1172             LONG Ret;
1173             if (bUnicode)
1174               {
1175                 Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
1176                                    wParam, lParam);
1177               }
1178             else
1179               {
1180                 Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
1181                                    wParam, lParam);
1182               }
1183             if (Ret)
1184               {
1185                 return(Ret);
1186               }
1187           }
1188         return((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
1189       }
1190
1191     case WM_ACTIVATE:
1192       {
1193         if (LOWORD(lParam) != WA_INACTIVE &&
1194             GetWindowLong(hWnd, GWL_STYLE) & WS_MINIMIZE)
1195           {
1196             /* Check if the window is minimized. */
1197             SetFocus(hWnd);
1198           }
1199         break;
1200       }
1201
1202     case WM_MOUSEWHEEL:
1203       {
1204         if (GetWindowLong(hWnd, GWL_STYLE & WS_CHILD))
1205           {
1206             if (bUnicode)
1207               {
1208                 return(SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
1209                                     wParam, lParam));
1210               }
1211             else
1212               {
1213                 return(SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
1214                                     wParam, lParam));
1215               }
1216           }
1217         break;
1218       }
1219
1220     case WM_ERASEBKGND:
1221     case WM_ICONERASEBKGND:
1222       {
1223         RECT Rect;
1224         HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
1225         GetClipBox((HDC)wParam, &Rect);
1226         FillRect((HDC)wParam, &Rect, hBrush);
1227         return(1);
1228       }
1229
1230     case WM_GETDLGCODE:
1231       {
1232         return(0);
1233       }
1234
1235       /* FIXME: Implement colour controls. */
1236
1237     case WM_SETCURSOR:
1238       {
1239         if (GetWindowLong(hWnd, GWL_STYLE) & WS_CHILD)
1240           {
1241             if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
1242               {
1243                 BOOL bResult;
1244                 if (bUnicode)
1245                   {
1246                     bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR, 
1247                                            wParam, lParam);
1248                   }
1249                 else              
1250                   {
1251                     bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR, 
1252                                            wParam, lParam);
1253                   }
1254                 if (bResult)
1255                   {
1256                     return(TRUE);
1257                   }
1258               }
1259           }
1260         return(DefWndHandleSetCursor(hWnd, wParam, lParam));      
1261       }
1262
1263     case WM_SYSCOMMAND:
1264       {
1265         POINT Pt;
1266         Pt.x = SLOWORD(lParam);
1267         Pt.y = SHIWORD(lParam);
1268         return(DefWndHandleSysCommand(hWnd, wParam, Pt));
1269       }
1270
1271       /* FIXME: Handle key messages. */
1272
1273     case WM_SHOWWINDOW:
1274       {
1275         if (lParam)
1276           {
1277             return(0);
1278           }
1279         /* FIXME: Check for a popup window. */
1280         if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_VISIBLE && !wParam) ||
1281             (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_VISIBLE) && wParam))
1282           {
1283             return(0);
1284           } 
1285         ShowWindow(hWnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE);
1286         break;
1287       }
1288
1289     case WM_CANCELMODE:
1290       {
1291         /* FIXME: Check for a desktop. */
1292         if (GetCapture() == hWnd)
1293           {
1294             ReleaseCapture();
1295           }
1296         break;
1297       }
1298
1299     case WM_VKEYTOITEM:
1300     case WM_CHARTOITEM:
1301       return(-1);
1302
1303     case WM_DROPOBJECT:
1304       /* FIXME: Implement this. */
1305       break;
1306
1307     case WM_QUERYDROPOBJECT:
1308       {
1309         if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
1310           {
1311             return(1);
1312           }
1313         break;
1314       }
1315
1316     case WM_QUERYDRAGICON:
1317       {
1318         UINT Len;
1319         HICON hIcon;
1320
1321         hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
1322         if (hIcon)
1323           {
1324             return((LRESULT)hIcon);
1325           }
1326         for (Len = 1; Len < 64; Len++)
1327           {
1328             if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCE(Len))) != NULL)
1329               {
1330                 return((LRESULT)hIcon);
1331               }
1332           }
1333         return((LRESULT)LoadIconW(0, IDI_APPLICATION));
1334       }
1335
1336       /* FIXME: WM_ISACTIVEICON */
1337
1338     case WM_NOTIFYFORMAT:
1339       {
1340         if (IsWindowUnicode(hWnd))
1341           {
1342             return(NFR_UNICODE);
1343           }
1344         else
1345           {
1346             return(NFR_ANSI);
1347           }
1348       }
1349
1350     case WM_SETICON:
1351       {
1352         INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1353         HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
1354         SetClassLongW(hWnd, Index, lParam);
1355         SetWindowPos(hWnd, 0, 0, 0, 0, 0, 
1356                      SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
1357                      SWP_NOACTIVATE | SWP_NOZORDER);
1358         return((LRESULT)hOldIcon);
1359       }
1360
1361     case WM_GETICON:
1362       {
1363         INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
1364         return(GetClassLongW(hWnd, Index));
1365       }
1366
1367     case WM_HELP:
1368       {
1369         if (bUnicode)
1370           {
1371             SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
1372           }
1373         else
1374           {
1375             SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
1376           }
1377         break;
1378       }
1379     }
1380   return 0;
1381 }
1382
1383 LRESULT STDCALL
1384 DefWindowProcA(HWND hWnd,
1385                UINT Msg,
1386                WPARAM wParam,
1387                LPARAM lParam)
1388 {
1389   LRESULT Result;
1390   static LPSTR WindowTextAtom = 0;
1391   PSTR WindowText;
1392
1393   switch (Msg)
1394     {
1395     case WM_NCCREATE:
1396       {
1397         CREATESTRUCTA* Cs = (CREATESTRUCTA*)lParam;
1398         if (HIWORD(Cs->lpszName))
1399           {
1400             WindowTextAtom = 
1401               (LPSTR)(ULONG)GlobalAddAtomA("USER32!WindowTextAtomA");
1402             WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1403                                          strlen(Cs->lpszName) * sizeof(CHAR));
1404             strcpy(WindowText, Cs->lpszName);
1405             SetPropA(hWnd, WindowTextAtom, WindowText);
1406           }
1407         return(1);
1408       }
1409
1410     case WM_NCCALCSIZE:
1411       {
1412         return(DefWndNCCalcSize(hWnd, (RECT*)lParam));
1413       }
1414
1415     case WM_WINDOWPOSCHANGING:
1416       {
1417         return(DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1418       }
1419
1420     case WM_GETTEXTLENGTH:
1421       {
1422         if (WindowTextAtom == 0 ||
1423             (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1424           {
1425             return(0);
1426           }
1427         return(strlen(WindowText));
1428       }
1429
1430     case WM_GETTEXT:
1431       {
1432         if (WindowTextAtom == 0 ||
1433             (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1434           {
1435             if (wParam > 1)
1436               {
1437                 ((PSTR)lParam) = '\0';
1438               }
1439             return(0);
1440           }
1441         strncpy((LPSTR)lParam, WindowText, wParam);
1442         return(min(wParam, strlen(WindowText)));
1443       }
1444
1445     case WM_SETTEXT:
1446       {
1447         if (WindowTextAtom != 0)
1448           {
1449             WindowTextAtom = 
1450               (LPSTR)(DWORD)GlobalAddAtomA("USER32!WindowTextAtomW");       
1451           }
1452         if (WindowTextAtom != 0 &&
1453             (WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
1454           {
1455             RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1456           }
1457         WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1458                                      strlen((PSTR)lParam) * sizeof(CHAR));
1459         strcpy(WindowText, (PSTR)lParam);
1460         SetPropA(hWnd, WindowTextAtom, WindowText);
1461       }
1462
1463     case WM_NCDESTROY:
1464       {
1465         if (WindowTextAtom != 0 &&
1466             (WindowText = RemovePropA(hWnd, WindowTextAtom)) == NULL)
1467           {
1468             RtlFreeHeap(GetProcessHeap(), 0, WindowText);
1469           }
1470         if (WindowTextAtom != 0)
1471           {
1472             GlobalDeleteAtom((ATOM)(ULONG)WindowTextAtom);
1473           }
1474         /* FIXME: Destroy scroll bars here as well. */
1475         return(0);
1476       }
1477
1478     default:
1479       Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
1480       break;
1481     }
1482
1483   return(Result);
1484 }
1485
1486 LRESULT STDCALL
1487 DefWindowProcW(HWND hWnd,
1488                UINT Msg,
1489                WPARAM wParam,
1490                LPARAM lParam)
1491 {
1492   LRESULT Result;
1493   static LPWSTR WindowTextAtom = 0;
1494   PWSTR WindowText;
1495
1496   switch (Msg)
1497     {
1498     case WM_NCCREATE:
1499       {
1500         CREATESTRUCTW* Cs = (CREATESTRUCTW*)lParam;
1501         if (HIWORD(Cs->lpszName))
1502           {
1503             WindowTextAtom = 
1504               (LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
1505             WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1506                                          wcslen(Cs->lpszName) * sizeof(WCHAR));
1507             wcscpy(WindowText, Cs->lpszName);
1508             SetPropW(hWnd, WindowTextAtom, WindowText);
1509           }
1510         return(1);
1511       }
1512
1513     case WM_NCCALCSIZE:
1514       {
1515         return(DefWndNCCalcSize(hWnd, (RECT*)lParam));
1516       }
1517
1518     case WM_WINDOWPOSCHANGING:
1519       {
1520         return(DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
1521       }
1522
1523     case WM_GETTEXTLENGTH:
1524       {
1525         if (WindowTextAtom == 0 ||
1526             (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1527           {
1528             return(0);
1529           }
1530         return(wcslen(WindowText));
1531       }
1532
1533     case WM_GETTEXT:
1534       {
1535         if (WindowTextAtom == 0 ||
1536             (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1537           {
1538             if (wParam > 1)
1539               {
1540                 ((PWSTR)lParam) = '\0';
1541               }
1542             return(0);
1543           }
1544         wcsncpy((PWSTR)lParam, WindowText, wParam);
1545         return(min(wParam, wcslen(WindowText)));
1546       }
1547
1548     case WM_SETTEXT:
1549       {
1550         if (WindowTextAtom != 0)
1551           {
1552             WindowTextAtom = 
1553               (LPWSTR)(DWORD)GlobalAddAtom(L"USER32!WindowTextAtomW");      
1554           }
1555         if (WindowTextAtom != 0 &&
1556             (WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
1557           {
1558             RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1559           }
1560         WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
1561                                      wcslen((PWSTR)lParam) * sizeof(WCHAR));
1562         wcscpy(WindowText, (PWSTR)lParam);
1563         SetPropW(hWnd, WindowTextAtom, WindowText);
1564       }
1565
1566     case WM_NCDESTROY:
1567       {
1568         if (WindowTextAtom != 0 &&
1569             (WindowText = RemovePropW(hWnd, WindowTextAtom)) == NULL)
1570           {
1571             RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
1572           }
1573         if (WindowTextAtom != 0)
1574           {
1575             GlobalDeleteAtom((ATOM)(DWORD)WindowTextAtom);
1576           }
1577         /* FIXME: Destroy scroll bars here as well. */
1578         return(0);
1579       }
1580
1581     default:
1582       Result = User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
1583       break;
1584     }
1585
1586   return(Result);
1587 }