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