user32: WM_IME_CHAR should result in posted, not sent, WM_CHAR messages.
[wine] / dlls / user32 / nonclient.c
1 /*
2  * Non-client area window functions
3  *
4  * Copyright 1994 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wingdi.h"
28 #include "wine/winuser16.h"
29 #include "win.h"
30 #include "user_private.h"
31 #include "controls.h"
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(nonclient);
35
36 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
37
38 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
39                                    0x55, 0x50,
40                                    0xAA, 0xA0,
41                                    0x55, 0x50,
42                                    0xAA, 0xA0,
43                                    0x55, 0x50,
44                                    0xAA, 0xA0,
45                                    0x55, 0x50,
46                                    0xAA, 0xA0,
47                                    0x55, 0x50};
48
49 #define SC_ABOUTWINE            (SC_SCREENSAVE+1)
50 #define SC_PUTMARK              (SC_SCREENSAVE+2)
51
52   /* Some useful macros */
53 #define HAS_DLGFRAME(style,exStyle) \
54     (((exStyle) & WS_EX_DLGMODALFRAME) || \
55      (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
56
57 #define HAS_THICKFRAME(style,exStyle) \
58     (((style) & WS_THICKFRAME) && \
59      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
60
61 #define HAS_THINFRAME(style) \
62     (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
63
64 #define HAS_BIGFRAME(style,exStyle) \
65     (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
66      ((exStyle) & WS_EX_DLGMODALFRAME))
67
68 #define HAS_STATICOUTERFRAME(style,exStyle) \
69     (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
70      WS_EX_STATICEDGE)
71
72 #define HAS_ANYFRAME(style,exStyle) \
73     (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
74      ((exStyle) & WS_EX_DLGMODALFRAME) || \
75      !((style) & (WS_CHILD | WS_POPUP)))
76
77 #define HAS_MENU(w)  ((((w)->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD) && ((w)->wIDmenu != 0))
78
79
80 /******************************************************************************
81  * NC_AdjustRectOuter
82  *
83  * Computes the size of the "outside" parts of the window based on the
84  * parameters of the client area.
85  *
86  * PARAMS
87  *     LPRECT  rect
88  *     DWORD  style
89  *     BOOL  menu
90  *     DWORD  exStyle
91  *
92  * NOTES
93  *     "Outer" parts of a window means the whole window frame, caption and
94  *     menu bar. It does not include "inner" parts of the frame like client
95  *     edge, static edge or scroll bars.
96  *
97  *****************************************************************************/
98
99 static void
100 NC_AdjustRectOuter (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
101 {
102     int adjust;
103     if(style & WS_ICONIC) return;
104
105     if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
106         WS_EX_STATICEDGE)
107     {
108         adjust = 1; /* for the outer frame always present */
109     }
110     else
111     {
112         adjust = 0;
113         if ((exStyle & WS_EX_DLGMODALFRAME) ||
114             (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
115     }
116     if (style & WS_THICKFRAME)
117         adjust +=  ( GetSystemMetrics (SM_CXFRAME)
118                    - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
119     if ((style & (WS_BORDER|WS_DLGFRAME)) ||
120         (exStyle & WS_EX_DLGMODALFRAME))
121         adjust++; /* The other border */
122
123     InflateRect (rect, adjust, adjust);
124
125     if ((style & WS_CAPTION) == WS_CAPTION)
126     {
127         if (exStyle & WS_EX_TOOLWINDOW)
128             rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
129         else
130             rect->top -= GetSystemMetrics(SM_CYCAPTION);
131     }
132     if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
133 }
134
135
136 /******************************************************************************
137  * NC_AdjustRectInner
138  *
139  * Computes the size of the "inside" part of the window based on the
140  * parameters of the client area.
141  *
142  * PARAMS
143  *     LPRECT   rect
144  *     DWORD    style
145  *     DWORD    exStyle
146  *
147  * NOTES
148  *     "Inner" part of a window means the window frame inside of the flat
149  *     window frame. It includes the client edge, the static edge and the
150  *     scroll bars.
151  *
152  *****************************************************************************/
153
154 static void
155 NC_AdjustRectInner (LPRECT rect, DWORD style, DWORD exStyle)
156 {
157     if(style & WS_ICONIC) return;
158
159     if (exStyle & WS_EX_CLIENTEDGE)
160         InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
161
162     if (style & WS_VSCROLL)
163     {
164         if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
165             rect->left  -= GetSystemMetrics(SM_CXVSCROLL);
166         else
167             rect->right += GetSystemMetrics(SM_CXVSCROLL);
168     }
169     if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
170 }
171
172
173
174 static HICON NC_IconForWindow( HWND hwnd )
175 {
176     HICON hIcon = 0;
177     WND *wndPtr = WIN_GetPtr( hwnd );
178
179     if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
180     {
181         hIcon = wndPtr->hIconSmall;
182         if (!hIcon) hIcon = wndPtr->hIcon;
183         WIN_ReleasePtr( wndPtr );
184     }
185     if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICONSM );
186     if (!hIcon) hIcon = (HICON) GetClassLongPtrW( hwnd, GCLP_HICON );
187
188     /* If there is no hIcon specified and this is a modal dialog,
189      * get the default one.
190      */
191     if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
192         hIcon = LoadImageW(0, (LPCWSTR)IDI_WINLOGO, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
193     return hIcon;
194 }
195
196 /* Draws the bar part(ie the big rectangle) of the caption */
197 static void NC_DrawCaptionBar (HDC hdc, const RECT *rect, DWORD dwStyle, 
198                                BOOL active, BOOL gradient)
199 {
200     if (gradient)
201     {
202         TRIVERTEX vertices[6];
203         DWORD colLeft = 
204             GetSysColor (active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
205         DWORD colRight = 
206             GetSysColor (active ? COLOR_GRADIENTACTIVECAPTION 
207                                 : COLOR_GRADIENTINACTIVECAPTION);
208         int v;
209         int buttonsAreaSize = GetSystemMetrics(SM_CYCAPTION) - 1;
210         static GRADIENT_RECT mesh[] = {{0, 1}, {2, 3}, {4, 5}};
211     
212         for (v = 0; v < 3; v++)
213         {
214             vertices[v].Red = GetRValue (colLeft) << 8;
215             vertices[v].Green = GetGValue (colLeft) << 8;
216             vertices[v].Blue = GetBValue (colLeft) << 8;
217             vertices[v].Alpha = 0x8000;
218             vertices[v+3].Red = GetRValue (colRight) << 8;
219             vertices[v+3].Green = GetGValue (colRight) << 8;
220             vertices[v+3].Blue = GetBValue (colRight) << 8;
221             vertices[v+3].Alpha = 0x8000;
222         }
223     
224         if ((dwStyle & WS_SYSMENU) 
225             && ((dwStyle & WS_MAXIMIZEBOX) || (dwStyle & WS_MINIMIZEBOX)))
226             buttonsAreaSize += 2 * (GetSystemMetrics(SM_CXSIZE) + 1);
227         
228         /* area behind icon; solid filled with left color */
229         vertices[0].x = rect->left;
230         vertices[0].y = rect->top;
231         if (dwStyle & WS_SYSMENU) 
232             vertices[1].x = 
233                 min (rect->left + GetSystemMetrics(SM_CXSMICON), rect->right);
234         else
235             vertices[1].x = vertices[0].x;
236         vertices[1].y = rect->bottom;
237         
238         /* area behind text; gradient */
239         vertices[2].x = vertices[1].x;
240         vertices[2].y = rect->top;
241         vertices[3].x = max (vertices[2].x, rect->right - buttonsAreaSize);
242         vertices[3].y = rect->bottom;
243         
244         /* area behind buttons; solid filled with right color */
245         vertices[4].x = vertices[3].x;
246         vertices[4].y = rect->top;
247         vertices[5].x = rect->right;
248         vertices[5].y = rect->bottom;
249         
250         GdiGradientFill (hdc, vertices, 6, mesh, 3, GRADIENT_FILL_RECT_H);
251     }
252     else
253         FillRect (hdc, rect, GetSysColorBrush (active ?
254                   COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
255 }
256
257 /***********************************************************************
258  *              DrawCaption (USER32.@) Draws a caption bar
259  *
260  * PARAMS
261  *     hwnd   [I]
262  *     hdc    [I]
263  *     lpRect [I]
264  *     uFlags [I]
265  *
266  * RETURNS
267  *     Success:
268  *     Failure:
269  */
270
271 BOOL WINAPI
272 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
273 {
274     return DrawCaptionTempW (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x103F);
275 }
276
277
278 /***********************************************************************
279  *              DrawCaptionTempA (USER32.@)
280  */
281 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
282                               HICON hIcon, LPCSTR str, UINT uFlags)
283 {
284     LPWSTR strW;
285     INT len;
286     BOOL ret = FALSE;
287
288     if (!(uFlags & DC_TEXT) || !str)
289         return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
290
291     len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
292     if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
293     {
294         MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
295         ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
296         HeapFree( GetProcessHeap (), 0, strW );
297     }
298     return ret;
299 }
300
301
302 /***********************************************************************
303  *              DrawCaptionTempW (USER32.@)
304  */
305 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
306                               HICON hIcon, LPCWSTR str, UINT uFlags)
307 {
308     RECT   rc = *rect;
309
310     TRACE("(%p,%p,%p,%p,%p,%s,%08x)\n",
311           hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
312
313     /* drawing background */
314     if (uFlags & DC_INBUTTON) {
315         FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
316
317         if (uFlags & DC_ACTIVE) {
318             HBRUSH hbr = SelectObject (hdc, SYSCOLOR_55AABrush);
319             PatBlt (hdc, rc.left, rc.top,
320                       rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
321             SelectObject (hdc, hbr);
322         }
323     }
324     else {
325         DWORD style = GetWindowLongW (hwnd, GWL_STYLE);
326         NC_DrawCaptionBar (hdc, rect, style, uFlags & DC_ACTIVE, uFlags & DC_GRADIENT);
327     }
328
329
330     /* drawing icon */
331     if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
332         POINT pt;
333
334         pt.x = rc.left + 2;
335         pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
336
337         if (!hIcon) hIcon = NC_IconForWindow(hwnd);
338         DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
339                     GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
340         rc.left += (rc.bottom - rc.top);
341     }
342
343     /* drawing text */
344     if (uFlags & DC_TEXT) {
345         HFONT hOldFont;
346
347         if (uFlags & DC_INBUTTON)
348             SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
349         else if (uFlags & DC_ACTIVE)
350             SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
351         else
352             SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
353
354         SetBkMode (hdc, TRANSPARENT);
355
356         if (hFont)
357             hOldFont = SelectObject (hdc, hFont);
358         else {
359             NONCLIENTMETRICSW nclm;
360             HFONT hNewFont;
361             nclm.cbSize = sizeof(NONCLIENTMETRICSW);
362             SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
363             hNewFont = CreateFontIndirectW ((uFlags & DC_SMALLCAP) ?
364                 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
365             hOldFont = SelectObject (hdc, hNewFont);
366         }
367
368         if (str)
369             DrawTextW (hdc, str, -1, &rc,
370                          DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
371         else {
372             WCHAR szText[128];
373             INT nLen;
374             nLen = GetWindowTextW (hwnd, szText, 128);
375             DrawTextW (hdc, szText, nLen, &rc,
376                          DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
377         }
378
379         if (hFont)
380             SelectObject (hdc, hOldFont);
381         else
382             DeleteObject (SelectObject (hdc, hOldFont));
383     }
384
385     /* drawing focus ??? */
386     if (uFlags & 0x2000)
387         FIXME("undocumented flag (0x2000)!\n");
388
389     return 0;
390 }
391
392
393 /***********************************************************************
394  *              AdjustWindowRect (USER32.@)
395  */
396 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
397 {
398     return AdjustWindowRectEx( rect, style, menu, 0 );
399 }
400
401
402 /***********************************************************************
403  *              AdjustWindowRectEx (USER32.@)
404  */
405 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
406 {
407     /* Correct the window style */
408     style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
409     exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
410                 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
411     if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
412
413     TRACE("(%d,%d)-(%d,%d) %08x %d %08x\n",
414           rect->left, rect->top, rect->right, rect->bottom,
415           style, menu, exStyle );
416
417     NC_AdjustRectOuter( rect, style, menu, exStyle );
418     NC_AdjustRectInner( rect, style, exStyle );
419
420     return TRUE;
421 }
422
423
424 /***********************************************************************
425  *           NC_HandleNCCalcSize
426  *
427  * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
428  */
429 LRESULT NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
430 {
431     RECT tmpRect = { 0, 0, 0, 0 };
432     LRESULT result = 0;
433     LONG cls_style = GetClassLongW(hwnd, GCL_STYLE);
434     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
435     LONG exStyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
436
437     if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
438     if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
439
440     if (!IsIconic(hwnd))
441     {
442         NC_AdjustRectOuter( &tmpRect, style, FALSE, exStyle );
443
444         winRect->left   -= tmpRect.left;
445         winRect->top    -= tmpRect.top;
446         winRect->right  -= tmpRect.right;
447         winRect->bottom -= tmpRect.bottom;
448
449         if (((style & (WS_CHILD | WS_POPUP)) != WS_CHILD) && GetMenu(hwnd))
450         {
451             TRACE("Calling GetMenuBarHeight with hwnd %p, width %d, at (%d, %d).\n",
452                   hwnd, winRect->right - winRect->left, -tmpRect.left, -tmpRect.top );
453
454             winRect->top +=
455                 MENU_GetMenuBarHeight( hwnd,
456                                        winRect->right - winRect->left,
457                                        -tmpRect.left, -tmpRect.top );
458         }
459
460         if( exStyle & WS_EX_CLIENTEDGE)
461             if( winRect->right - winRect->left > 2 * GetSystemMetrics(SM_CXEDGE) &&
462                    winRect->bottom - winRect->top > 2 * GetSystemMetrics(SM_CYEDGE))
463                 InflateRect( winRect, - GetSystemMetrics(SM_CXEDGE),
464                         - GetSystemMetrics(SM_CYEDGE));
465
466         if (style & WS_VSCROLL)
467             if( winRect->right - winRect->left >= GetSystemMetrics(SM_CXVSCROLL)){
468                 if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
469                     winRect->left  += GetSystemMetrics(SM_CXVSCROLL);
470                 else
471                     winRect->right -= GetSystemMetrics(SM_CXVSCROLL);
472             }
473
474         if (style & WS_HSCROLL)
475             if( winRect->bottom - winRect->top > GetSystemMetrics(SM_CYHSCROLL))
476                     winRect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
477
478         if (winRect->top > winRect->bottom)
479             winRect->bottom = winRect->top;
480
481         if (winRect->left > winRect->right)
482             winRect->right = winRect->left;
483     }
484     return result;
485 }
486
487
488 /***********************************************************************
489  *           NC_GetInsideRect
490  *
491  * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
492  * but without the borders (if any).
493  * The rectangle is in window coordinates (for drawing with GetWindowDC()).
494  */
495 static void NC_GetInsideRect( HWND hwnd, RECT *rect )
496 {
497     WND *wndPtr = WIN_GetPtr( hwnd );
498
499     if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
500
501     rect->top    = rect->left = 0;
502     rect->right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
503     rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
504
505     if (wndPtr->dwStyle & WS_ICONIC) goto END;
506
507     /* Remove frame from rectangle */
508     if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
509     {
510         InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
511     }
512     else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
513     {
514         InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
515     }
516     else if (HAS_THINFRAME( wndPtr->dwStyle ))
517     {
518         InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
519     }
520
521     /* We have additional border information if the window
522      * is a child (but not an MDI child) */
523     if ( (wndPtr->dwStyle & WS_CHILD)  &&
524          ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
525     {
526         if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
527             InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
528         if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
529             InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
530     }
531
532 END:
533     WIN_ReleasePtr( wndPtr );
534 }
535
536
537 /***********************************************************************
538  * NC_DoNCHitTest
539  *
540  * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
541  *
542  * FIXME:  Just a modified copy of the Win 3.1 version.
543  */
544
545 static LRESULT NC_DoNCHitTest (WND *wndPtr, POINT pt )
546 {
547     RECT rect, rcClient;
548     POINT ptClient;
549
550     TRACE("hwnd=%p pt=%d,%d\n", wndPtr->hwndSelf, pt.x, pt.y );
551
552     GetWindowRect(wndPtr->hwndSelf, &rect );
553     if (!PtInRect( &rect, pt )) return HTNOWHERE;
554
555     if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
556
557     /* Check client area */
558     ptClient = pt;
559     ScreenToClient( wndPtr->hwndSelf, &ptClient );
560     GetClientRect( wndPtr->hwndSelf, &rcClient );
561     if (PtInRect( &rcClient, ptClient )) return HTCLIENT;
562
563     /* Check borders */
564     if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
565     {
566         InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
567         if (!PtInRect( &rect, pt ))
568         {
569             /* Check top sizing border */
570             if (pt.y < rect.top)
571             {
572                 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
573                 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
574                 return HTTOP;
575             }
576             /* Check bottom sizing border */
577             if (pt.y >= rect.bottom)
578             {
579                 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
580                 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
581                 return HTBOTTOM;
582             }
583             /* Check left sizing border */
584             if (pt.x < rect.left)
585             {
586                 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
587                 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
588                 return HTLEFT;
589             }
590             /* Check right sizing border */
591             if (pt.x >= rect.right)
592             {
593                 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
594                 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
595                 return HTRIGHT;
596             }
597         }
598     }
599     else  /* No thick frame */
600     {
601         if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
602             InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
603         else if (HAS_THINFRAME( wndPtr->dwStyle ))
604             InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
605         if (!PtInRect( &rect, pt )) return HTBORDER;
606     }
607
608     /* Check caption */
609
610     if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
611     {
612         if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
613             rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
614         else
615             rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
616         if (!PtInRect( &rect, pt ))
617         {
618             BOOL min_or_max_box = (wndPtr->dwStyle & WS_MAXIMIZEBOX) ||
619                                   (wndPtr->dwStyle & WS_MINIMIZEBOX);
620             /* Check system menu */
621             if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
622             {
623                 if (NC_IconForWindow(wndPtr->hwndSelf))
624                     rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
625             }
626             if (pt.x < rect.left) return HTSYSMENU;
627
628             /* Check close button */
629             if (wndPtr->dwStyle & WS_SYSMENU)
630                 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
631             if (pt.x > rect.right) return HTCLOSE;
632
633             /* Check maximize box */
634             /* In win95 there is automatically a Maximize button when there is a minimize one*/
635             if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
636                 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
637             if (pt.x > rect.right) return HTMAXBUTTON;
638
639             /* Check minimize box */
640             /* In win95 there is automatically a Maximize button when there is a Maximize one*/
641             if (min_or_max_box && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
642                 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
643
644             if (pt.x > rect.right) return HTMINBUTTON;
645             return HTCAPTION;
646         }
647     }
648
649       /* Check vertical scroll bar */
650
651     if (wndPtr->dwStyle & WS_VSCROLL)
652     {
653         if((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
654             rcClient.left -= GetSystemMetrics(SM_CXVSCROLL);
655         else
656             rcClient.right += GetSystemMetrics(SM_CXVSCROLL);
657         if (PtInRect( &rcClient, ptClient )) return HTVSCROLL;
658     }
659
660       /* Check horizontal scroll bar */
661
662     if (wndPtr->dwStyle & WS_HSCROLL)
663     {
664         rcClient.bottom += GetSystemMetrics(SM_CYHSCROLL);
665         if (PtInRect( &rcClient, ptClient ))
666         {
667             /* Check size box */
668             if ((wndPtr->dwStyle & WS_VSCROLL) &&
669                 ((((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) != 0) && (ptClient.x <= rcClient.left + GetSystemMetrics(SM_CXVSCROLL))) ||
670                 (((wndPtr->dwExStyle & WS_EX_LEFTSCROLLBAR) == 0) && (ptClient.x >= rcClient.right - GetSystemMetrics(SM_CXVSCROLL)))))
671                 return HTSIZE;
672             return HTHSCROLL;
673         }
674     }
675
676       /* Check menu bar */
677
678     if (HAS_MENU(wndPtr))
679     {
680         if ((ptClient.y < 0) && (ptClient.x >= 0) && (ptClient.x < rcClient.right))
681             return HTMENU;
682     }
683
684     /* Has to return HTNOWHERE if nothing was found
685        Could happen when a window has a customized non client area */
686     return HTNOWHERE;
687 }
688
689
690 /***********************************************************************
691  * NC_HandleNCHitTest
692  *
693  * Handle a WM_NCHITTEST message. Called from DefWindowProc().
694  */
695 LRESULT NC_HandleNCHitTest (HWND hwnd , POINT pt)
696 {
697     LRESULT retvalue;
698     WND *wndPtr = WIN_GetPtr( hwnd );
699
700     if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return HTERROR;
701
702     retvalue = NC_DoNCHitTest (wndPtr, pt);
703     WIN_ReleasePtr( wndPtr );
704     return retvalue;
705 }
706
707
708 /******************************************************************************
709  *
710  *   NC_DrawSysButton
711  *
712  *   Draws the system icon.
713  *
714  *****************************************************************************/
715 BOOL NC_DrawSysButton (HWND hwnd, HDC hdc, BOOL down)
716 {
717     HICON hIcon = NC_IconForWindow( hwnd );
718
719     if (hIcon)
720     {
721         RECT rect;
722         NC_GetInsideRect( hwnd, &rect );
723         DrawIconEx (hdc, rect.left + 2, rect.top + 1, hIcon,
724                     GetSystemMetrics(SM_CXSMICON),
725                     GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
726     }
727     return (hIcon != 0);
728 }
729
730
731 /******************************************************************************
732  *
733  *   NC_DrawCloseButton
734  *
735  *   Draws the close button.
736  *
737  *   If bGrayed is true, then draw a disabled Close button
738  *
739  *****************************************************************************/
740
741 static void NC_DrawCloseButton (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
742 {
743     RECT rect;
744
745     NC_GetInsideRect( hwnd, &rect );
746
747     /* A tool window has a smaller Close button */
748     if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
749     {
750         INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE   */
751         INT iBmpWidth = 11;  /* it uses 11x11 for  the close button in tool window */
752         INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
753
754         rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
755         rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
756         rect.bottom = rect.top + iBmpHeight;
757         rect.right = rect.left + iBmpWidth;
758     }
759     else
760     {
761         rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
762         rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
763         rect.top += 2;
764         rect.right -= 2;
765     }
766     DrawFrameControl( hdc, &rect, DFC_CAPTION,
767                       (DFCS_CAPTIONCLOSE |
768                        (down ? DFCS_PUSHED : 0) |
769                        (bGrayed ? DFCS_INACTIVE : 0)) );
770 }
771
772 /******************************************************************************
773  *   NC_DrawMaxButton
774  *
775  *   Draws the maximize button for windows.
776  *   If bGrayed is true, then draw a disabled Maximize button
777  */
778 static void NC_DrawMaxButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
779 {
780     RECT rect;
781     UINT flags;
782
783     /* never draw maximize box when window has WS_EX_TOOLWINDOW style */
784     if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
785         return;
786
787     flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
788
789     NC_GetInsideRect( hwnd, &rect );
790     if (GetWindowLongW( hwnd, GWL_STYLE) & WS_SYSMENU)
791         rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
792     rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
793     rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
794     rect.top += 2;
795     rect.right -= 2;
796     if (down) flags |= DFCS_PUSHED;
797     if (bGrayed) flags |= DFCS_INACTIVE;
798     DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
799 }
800
801 /******************************************************************************
802  *   NC_DrawMinButton
803  *
804  *   Draws the minimize button for windows.
805  *   If bGrayed is true, then draw a disabled Minimize button
806  */
807 static void  NC_DrawMinButton(HWND hwnd,HDC hdc,BOOL down, BOOL bGrayed)
808 {
809     RECT rect;
810     UINT flags = DFCS_CAPTIONMIN;
811     DWORD style = GetWindowLongW( hwnd, GWL_STYLE );
812
813     /* never draw minimize box when window has WS_EX_TOOLWINDOW style */
814     if (GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
815         return;
816
817     NC_GetInsideRect( hwnd, &rect );
818     if (style & WS_SYSMENU)
819         rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
820     if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
821         rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
822     rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
823     rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
824     rect.top += 2;
825     rect.right -= 2;
826     if (down) flags |= DFCS_PUSHED;
827     if (bGrayed) flags |= DFCS_INACTIVE;
828     DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
829 }
830
831 /******************************************************************************
832  *
833  *   NC_DrawFrame
834  *
835  *   Draw a window frame inside the given rectangle, and update the rectangle.
836  *
837  *   Bugs
838  *        Many.  First, just what IS a frame in Win95?  Note that the 3D look
839  *        on the outer edge is handled by NC_DoNCPaint.  As is the inner
840  *        edge.  The inner rectangle just inside the frame is handled by the
841  *        Caption code.
842  *
843  *        In short, for most people, this function should be a nop (unless
844  *        you LIKE thick borders in Win95/NT4.0 -- I've been working with
845  *        them lately, but just to get this code right).  Even so, it doesn't
846  *        appear to be so.  It's being worked on...
847  *
848  *****************************************************************************/
849
850 static void  NC_DrawFrame( HDC  hdc, RECT  *rect, BOOL  active, DWORD style, DWORD exStyle)
851 {
852     INT width, height;
853
854     /* Firstly the "thick" frame */
855     if (style & WS_THICKFRAME)
856     {
857         width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
858         height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
859
860         SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
861                                             COLOR_INACTIVEBORDER) );
862         /* Draw frame */
863         PatBlt( hdc, rect->left, rect->top,
864                   rect->right - rect->left, height, PATCOPY );
865         PatBlt( hdc, rect->left, rect->top,
866                   width, rect->bottom - rect->top, PATCOPY );
867         PatBlt( hdc, rect->left, rect->bottom - 1,
868                   rect->right - rect->left, -height, PATCOPY );
869         PatBlt( hdc, rect->right - 1, rect->top,
870                   -width, rect->bottom - rect->top, PATCOPY );
871
872         InflateRect( rect, -width, -height );
873     }
874
875     /* Now the other bit of the frame */
876     if ((style & (WS_BORDER|WS_DLGFRAME)) ||
877         (exStyle & WS_EX_DLGMODALFRAME))
878     {
879         width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
880         height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
881         /* This should give a value of 1 that should also work for a border */
882
883         SelectObject( hdc, GetSysColorBrush(
884                       (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
885                           COLOR_3DFACE :
886                       (exStyle & WS_EX_STATICEDGE) ?
887                           COLOR_WINDOWFRAME :
888                       (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
889                           COLOR_3DFACE :
890                       /* else */
891                           COLOR_WINDOWFRAME));
892
893         /* Draw frame */
894         PatBlt( hdc, rect->left, rect->top,
895                   rect->right - rect->left, height, PATCOPY );
896         PatBlt( hdc, rect->left, rect->top,
897                   width, rect->bottom - rect->top, PATCOPY );
898         PatBlt( hdc, rect->left, rect->bottom - 1,
899                   rect->right - rect->left, -height, PATCOPY );
900         PatBlt( hdc, rect->right - 1, rect->top,
901                   -width, rect->bottom - rect->top, PATCOPY );
902
903         InflateRect( rect, -width, -height );
904     }
905 }
906
907
908 /******************************************************************************
909  *
910  *   NC_DrawCaption
911  *
912  *   Draw the window caption for windows.
913  *   The correct pen for the window frame must be selected in the DC.
914  *
915  *****************************************************************************/
916
917 static void  NC_DrawCaption( HDC  hdc, RECT *rect, HWND hwnd, DWORD  style, 
918                              DWORD  exStyle, BOOL active )
919 {
920     RECT  r = *rect;
921     WCHAR buffer[256];
922     HPEN  hPrevPen;
923     HMENU hSysMenu;
924     BOOL gradient = FALSE;
925
926     hPrevPen = SelectObject( hdc, SYSCOLOR_GetPen(
927                      ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
928                                  WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
929                       COLOR_WINDOWFRAME : COLOR_3DFACE) );
930     MoveToEx( hdc, r.left, r.bottom - 1, NULL );
931     LineTo( hdc, r.right, r.bottom - 1 );
932     SelectObject( hdc, hPrevPen );
933     r.bottom--;
934
935     SystemParametersInfoW (SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0);
936     NC_DrawCaptionBar (hdc, rect, style, active, gradient);
937
938     if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
939         if (NC_DrawSysButton (hwnd, hdc, FALSE))
940             r.left += GetSystemMetrics(SM_CXSMICON) + 2;
941     }
942
943     if (style & WS_SYSMENU)
944     {
945         UINT state;
946
947         /* Go get the sysmenu */
948         hSysMenu = GetSystemMenu(hwnd, FALSE);
949         state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
950
951         /* Draw a grayed close button if disabled or if SC_CLOSE is not there */
952         NC_DrawCloseButton (hwnd, hdc, FALSE,
953                             (state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF));
954         r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
955
956         if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
957         {
958             /* In win95 the two buttons are always there */
959             /* But if the menu item is not in the menu they're disabled*/
960
961             NC_DrawMaxButton( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
962             r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
963
964             NC_DrawMinButton( hwnd, hdc, FALSE,  (!(style & WS_MINIMIZEBOX)));
965             r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
966         }
967     }
968
969     if (GetWindowTextW( hwnd, buffer, sizeof(buffer)/sizeof(WCHAR) ))
970     {
971         NONCLIENTMETRICSW nclm;
972         HFONT hFont, hOldFont;
973         nclm.cbSize = sizeof(nclm);
974         SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
975         if (exStyle & WS_EX_TOOLWINDOW)
976             hFont = CreateFontIndirectW (&nclm.lfSmCaptionFont);
977         else
978             hFont = CreateFontIndirectW (&nclm.lfCaptionFont);
979         hOldFont = SelectObject (hdc, hFont);
980         if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
981         else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
982         SetBkMode( hdc, TRANSPARENT );
983         r.left += 2;
984         DrawTextW( hdc, buffer, -1, &r,
985                      DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
986         DeleteObject (SelectObject (hdc, hOldFont));
987     }
988 }
989
990
991 /******************************************************************************
992  *   NC_DoNCPaint
993  *
994  *   Paint the non-client area for windows.
995  */
996 static void  NC_DoNCPaint( HWND  hwnd, HRGN  clip, BOOL  suppress_menupaint )
997 {
998     HDC hdc;
999     RECT rfuzz, rect, rectClip;
1000     BOOL active;
1001     WND *wndPtr;
1002     DWORD dwStyle, dwExStyle;
1003     WORD flags;
1004     HRGN hrgn;
1005     RECT rectClient, rectWindow;
1006     int has_menu;
1007
1008     if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1009     has_menu = HAS_MENU(wndPtr);
1010     dwStyle = wndPtr->dwStyle;
1011     dwExStyle = wndPtr->dwExStyle;
1012     flags = wndPtr->flags;
1013     rectWindow = wndPtr->rectWindow;
1014     WIN_ReleasePtr( wndPtr );
1015
1016     if ( dwStyle & WS_MINIMIZE ||
1017          !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1018
1019     active  = flags & WIN_NCACTIVATED;
1020
1021     TRACE("%p %d\n", hwnd, active );
1022
1023     /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1024        the call to GetDCEx implying that it is allowed not to use it either.
1025        However, the suggested GetDCEx(    , DCX_WINDOW | DCX_INTERSECTRGN)
1026        will cause clipRgn to be deleted after ReleaseDC().
1027        Now, how is the "system" supposed to tell what happened?
1028      */
1029
1030     GetClientRect( hwnd, &rectClient );
1031     MapWindowPoints( hwnd, 0, (POINT *)&rectClient, 2 );
1032     hrgn = CreateRectRgnIndirect( &rectClient );
1033
1034     if (clip > (HRGN)1)
1035     {
1036         CombineRgn( hrgn, clip, hrgn, RGN_DIFF );
1037         hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_INTERSECTRGN );
1038     }
1039     else
1040     {
1041         hdc = GetDCEx( hwnd, hrgn, DCX_USESTYLE | DCX_WINDOW | DCX_EXCLUDERGN );
1042     }
1043
1044     if (!hdc) return;
1045
1046     rect.top = rect.left = 0;
1047     rect.right  = rectWindow.right - rectWindow.left;
1048     rect.bottom = rectWindow.bottom - rectWindow.top;
1049     GetClipBox( hdc, &rectClip );
1050
1051     SelectObject( hdc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME) );
1052
1053     if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1054         DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1055     }
1056     else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1057         DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1058     }
1059
1060     NC_DrawFrame(hdc, &rect, active, dwStyle, dwExStyle );
1061
1062     if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1063     {
1064         RECT  r = rect;
1065         if (dwExStyle & WS_EX_TOOLWINDOW) {
1066             r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1067             rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1068         }
1069         else {
1070             r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1071             rect.top += GetSystemMetrics(SM_CYCAPTION);
1072         }
1073         if( IntersectRect( &rfuzz, &r, &rectClip ) )
1074             NC_DrawCaption(hdc, &r, hwnd, dwStyle, dwExStyle, active);
1075     }
1076
1077     if (has_menu)
1078     {
1079         RECT r = rect;
1080         r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1081
1082         TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1083               r.left, r.top, r.right, r.bottom);
1084
1085         rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1086     }
1087
1088     TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1089           rect.left, rect.top, rect.right, rect.bottom );
1090
1091     if (dwExStyle & WS_EX_CLIENTEDGE)
1092         DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1093
1094     /* Draw the scroll-bars */
1095
1096     if (dwStyle & WS_VSCROLL)
1097         SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1098     if (dwStyle & WS_HSCROLL)
1099         SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1100
1101     /* Draw the "size-box" */
1102     if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1103     {
1104         RECT r = rect;
1105         if((dwExStyle & WS_EX_LEFTSCROLLBAR) != 0)
1106             r.right = r.left + GetSystemMetrics(SM_CXVSCROLL) + 1;
1107         else
1108             r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1109         r.top  = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1110         FillRect( hdc, &r,  GetSysColorBrush(COLOR_SCROLLBAR) );
1111     }
1112
1113     ReleaseDC( hwnd, hdc );
1114 }
1115
1116
1117
1118
1119 /***********************************************************************
1120  *           NC_HandleNCPaint
1121  *
1122  * Handle a WM_NCPAINT message. Called from DefWindowProc().
1123  */
1124 LRESULT NC_HandleNCPaint( HWND hwnd , HRGN clip)
1125 {
1126     DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1127
1128     if( dwStyle & WS_VISIBLE )
1129     {
1130         if( dwStyle & WS_MINIMIZE )
1131             WINPOS_RedrawIconTitle( hwnd );
1132         else
1133             NC_DoNCPaint( hwnd, clip, FALSE );
1134     }
1135     return 0;
1136 }
1137
1138
1139 /***********************************************************************
1140  *           NC_HandleNCActivate
1141  *
1142  * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1143  */
1144 LRESULT NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1145 {
1146     WND* wndPtr = WIN_GetPtr( hwnd );
1147
1148     if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return FALSE;
1149
1150     /* Lotus Notes draws menu descriptions in the caption of its main
1151      * window. When it wants to restore original "system" view, it just
1152      * sends WM_NCACTIVATE message to itself. Any optimizations here in
1153      * attempt to minimize redrawings lead to a not restored caption.
1154      */
1155     if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1156     else wndPtr->flags &= ~WIN_NCACTIVATED;
1157     WIN_ReleasePtr( wndPtr );
1158
1159     if (IsIconic(hwnd))
1160         WINPOS_RedrawIconTitle( hwnd );
1161     else
1162         NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1163
1164     return TRUE;
1165 }
1166
1167
1168 /***********************************************************************
1169  *           NC_HandleSetCursor
1170  *
1171  * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1172  */
1173 LRESULT NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1174 {
1175     hwnd = WIN_GetFullHandle( (HWND)wParam );
1176
1177     switch((short)LOWORD(lParam))
1178     {
1179     case HTERROR:
1180         {
1181             WORD msg = HIWORD( lParam );
1182             if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1183                 (msg == WM_RBUTTONDOWN) || (msg == WM_XBUTTONDOWN))
1184                 MessageBeep(0);
1185         }
1186         break;
1187
1188     case HTCLIENT:
1189         {
1190             HCURSOR hCursor = (HCURSOR)GetClassLongPtrW(hwnd, GCLP_HCURSOR);
1191             if(hCursor) {
1192                 SetCursor(hCursor);
1193                 return TRUE;
1194             }
1195             return FALSE;
1196         }
1197
1198     case HTLEFT:
1199     case HTRIGHT:
1200         return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZEWE ) );
1201
1202     case HTTOP:
1203     case HTBOTTOM:
1204         return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENS ) );
1205
1206     case HTTOPLEFT:
1207     case HTBOTTOMRIGHT:
1208         return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENWSE ) );
1209
1210     case HTTOPRIGHT:
1211     case HTBOTTOMLEFT:
1212         return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_SIZENESW ) );
1213     }
1214
1215     /* Default cursor: arrow */
1216     return (LRESULT)SetCursor( LoadCursorA( 0, (LPSTR)IDC_ARROW ) );
1217 }
1218
1219 /***********************************************************************
1220  *           NC_GetSysPopupPos
1221  */
1222 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1223 {
1224     if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1225     else
1226     {
1227         WND *wndPtr = WIN_GetPtr( hwnd );
1228         if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return;
1229
1230         NC_GetInsideRect( hwnd, rect );
1231         OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1232         if (wndPtr->dwStyle & WS_CHILD)
1233             ClientToScreen( GetParent(hwnd), (POINT *)rect );
1234         rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1235         rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1236         WIN_ReleasePtr( wndPtr );
1237     }
1238 }
1239
1240 /***********************************************************************
1241  *           NC_TrackMinMaxBox
1242  *
1243  * Track a mouse button press on the minimize or maximize box.
1244  *
1245  * The big difference between 3.1 and 95 is the disabled button state.
1246  * In win95 the system button can be disabled, so it can ignore the mouse
1247  * event.
1248  *
1249  */
1250 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1251 {
1252     MSG msg;
1253     HDC hdc = GetWindowDC( hwnd );
1254     BOOL pressed = TRUE;
1255     UINT state;
1256     DWORD wndStyle = GetWindowLongW( hwnd, GWL_STYLE);
1257     HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1258
1259     void  (*paintButton)(HWND, HDC, BOOL, BOOL);
1260
1261     if (wParam == HTMINBUTTON)
1262     {
1263         /* If the style is not present, do nothing */
1264         if (!(wndStyle & WS_MINIMIZEBOX))
1265             return;
1266
1267         /* Check if the sysmenu item for minimize is there  */
1268         state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1269
1270         paintButton = &NC_DrawMinButton;
1271     }
1272     else
1273     {
1274         /* If the style is not present, do nothing */
1275         if (!(wndStyle & WS_MAXIMIZEBOX))
1276             return;
1277
1278         /* Check if the sysmenu item for maximize is there  */
1279         state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1280
1281         paintButton = &NC_DrawMaxButton;
1282     }
1283
1284     SetCapture( hwnd );
1285
1286     (*paintButton)( hwnd, hdc, TRUE, FALSE);
1287
1288     while(1)
1289     {
1290         BOOL oldstate = pressed;
1291
1292         if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1293         if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1294
1295         if(msg.message == WM_LBUTTONUP)
1296             break;
1297
1298         if(msg.message != WM_MOUSEMOVE)
1299             continue;
1300
1301         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1302         if (pressed != oldstate)
1303            (*paintButton)( hwnd, hdc, pressed, FALSE);
1304     }
1305
1306     if(pressed)
1307         (*paintButton)(hwnd, hdc, FALSE, FALSE);
1308
1309     ReleaseCapture();
1310     ReleaseDC( hwnd, hdc );
1311
1312     /* If the item minimize or maximize of the sysmenu are not there */
1313     /* or if the style is not present, do nothing */
1314     if ((!pressed) || (state == 0xFFFFFFFF))
1315         return;
1316
1317     if (wParam == HTMINBUTTON)
1318         SendMessageW( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1319     else
1320         SendMessageW( hwnd, WM_SYSCOMMAND,
1321                       IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1322 }
1323
1324 /***********************************************************************
1325  * NC_TrackCloseButton
1326  *
1327  * Track a mouse button press on the Win95 close button.
1328  */
1329 static void NC_TrackCloseButton (HWND hwnd, WORD wParam)
1330 {
1331     MSG msg;
1332     HDC hdc;
1333     BOOL pressed = TRUE;
1334     HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1335     UINT state;
1336
1337     if(hSysMenu == 0)
1338         return;
1339
1340     state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1341
1342     /* If the item close of the sysmenu is disabled or not there do nothing */
1343     if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1344         return;
1345
1346     hdc = GetWindowDC( hwnd );
1347
1348     SetCapture( hwnd );
1349
1350     NC_DrawCloseButton (hwnd, hdc, TRUE, FALSE);
1351
1352     while(1)
1353     {
1354         BOOL oldstate = pressed;
1355
1356         if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1357         if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1358
1359         if(msg.message == WM_LBUTTONUP)
1360             break;
1361
1362         if(msg.message != WM_MOUSEMOVE)
1363             continue;
1364
1365         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1366         if (pressed != oldstate)
1367            NC_DrawCloseButton (hwnd, hdc, pressed, FALSE);
1368     }
1369
1370     if(pressed)
1371         NC_DrawCloseButton (hwnd, hdc, FALSE, FALSE);
1372
1373     ReleaseCapture();
1374     ReleaseDC( hwnd, hdc );
1375     if (!pressed) return;
1376
1377     SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1378 }
1379
1380
1381 /***********************************************************************
1382  *           NC_TrackScrollBar
1383  *
1384  * Track a mouse button press on the horizontal or vertical scroll-bar.
1385  */
1386 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1387 {
1388     INT scrollbar;
1389
1390     if ((wParam & 0xfff0) == SC_HSCROLL)
1391     {
1392         if ((wParam & 0x0f) != HTHSCROLL) return;
1393         scrollbar = SB_HORZ;
1394     }
1395     else  /* SC_VSCROLL */
1396     {
1397         if ((wParam & 0x0f) != HTVSCROLL) return;
1398         scrollbar = SB_VERT;
1399     }
1400     SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1401 }
1402
1403
1404 /***********************************************************************
1405  *           NC_HandleNCLButtonDown
1406  *
1407  * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1408  */
1409 LRESULT NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1410 {
1411     LONG style = GetWindowLongW( hwnd, GWL_STYLE );
1412
1413     switch(wParam)  /* Hit test */
1414     {
1415     case HTCAPTION:
1416         {
1417             HWND top = GetAncestor( hwnd, GA_ROOT );
1418
1419             if (FOCUS_MouseActivate( top ) || (GetActiveWindow() == top))
1420                 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1421             break;
1422         }
1423
1424     case HTSYSMENU:
1425          if( style & WS_SYSMENU )
1426          {
1427              if( !(style & WS_MINIMIZE) )
1428              {
1429                 HDC hDC = GetWindowDC(hwnd);
1430                 NC_DrawSysButton( hwnd, hDC, TRUE );
1431                 ReleaseDC( hwnd, hDC );
1432              }
1433              SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1434          }
1435          break;
1436
1437     case HTMENU:
1438         SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1439         break;
1440
1441     case HTHSCROLL:
1442         SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1443         break;
1444
1445     case HTVSCROLL:
1446         SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1447         break;
1448
1449     case HTMINBUTTON:
1450     case HTMAXBUTTON:
1451         NC_TrackMinMaxBox( hwnd, wParam );
1452         break;
1453
1454     case HTCLOSE:
1455         NC_TrackCloseButton (hwnd, wParam);
1456         break;
1457
1458     case HTLEFT:
1459     case HTRIGHT:
1460     case HTTOP:
1461     case HTTOPLEFT:
1462     case HTTOPRIGHT:
1463     case HTBOTTOM:
1464     case HTBOTTOMLEFT:
1465     case HTBOTTOMRIGHT:
1466         /* Old comment:
1467          * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
1468          * This was previously done by setting wParam=SC_SIZE + wParam - 2
1469          */
1470         /* But that is not what WinNT does. Instead it sends this. This
1471          * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
1472          * SC_MOUSEMENU into wParam.
1473          */
1474         SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT-WMSZ_LEFT), lParam);
1475         break;
1476
1477     case HTBORDER:
1478         break;
1479     }
1480     return 0;
1481 }
1482
1483
1484 /***********************************************************************
1485  *           NC_HandleNCLButtonDblClk
1486  *
1487  * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1488  */
1489 LRESULT NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
1490 {
1491     /*
1492      * if this is an icon, send a restore since we are handling
1493      * a double click
1494      */
1495     if (IsIconic(hwnd))
1496     {
1497         SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
1498         return 0;
1499     }
1500
1501     switch(wParam)  /* Hit test */
1502     {
1503     case HTCAPTION:
1504         /* stop processing if WS_MAXIMIZEBOX is missing */
1505         if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
1506             SendMessageW( hwnd, WM_SYSCOMMAND,
1507                           IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
1508         break;
1509
1510     case HTSYSMENU:
1511         {
1512             HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1513             UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1514
1515             /* If the item close of the sysmenu is disabled or not there do nothing */
1516             if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
1517                 break;
1518
1519             SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1520             break;
1521         }
1522
1523     case HTHSCROLL:
1524         SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1525         break;
1526
1527     case HTVSCROLL:
1528         SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1529         break;
1530     }
1531     return 0;
1532 }
1533
1534
1535 /***********************************************************************
1536  *           NC_HandleSysCommand
1537  *
1538  * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1539  */
1540 LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
1541 {
1542     TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", hwnd, wParam, lParam );
1543
1544     if (!IsWindowEnabled( hwnd )) return 0;
1545
1546     if (HOOK_CallHooks( WH_CBT, HCBT_SYSCOMMAND, wParam, lParam, TRUE ))
1547         return 0;
1548
1549     switch (wParam & 0xfff0)
1550     {
1551     case SC_SIZE:
1552     case SC_MOVE:
1553         USER_Driver->pSysCommandSizeMove( hwnd, wParam );
1554         break;
1555
1556     case SC_MINIMIZE:
1557         if (hwnd == GetForegroundWindow())
1558             ShowOwnedPopups(hwnd,FALSE);
1559         ShowWindow( hwnd, SW_MINIMIZE );
1560         break;
1561
1562     case SC_MAXIMIZE:
1563         if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1564             ShowOwnedPopups(hwnd,TRUE);
1565         ShowWindow( hwnd, SW_MAXIMIZE );
1566         break;
1567
1568     case SC_RESTORE:
1569         if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
1570             ShowOwnedPopups(hwnd,TRUE);
1571         ShowWindow( hwnd, SW_RESTORE );
1572         break;
1573
1574     case SC_CLOSE:
1575         return SendMessageW( hwnd, WM_CLOSE, 0, 0 );
1576
1577     case SC_VSCROLL:
1578     case SC_HSCROLL:
1579         {
1580             POINT pt;
1581             pt.x = (short)LOWORD(lParam);
1582             pt.y = (short)HIWORD(lParam);
1583             NC_TrackScrollBar( hwnd, wParam, pt );
1584         }
1585         break;
1586
1587     case SC_MOUSEMENU:
1588         {
1589             POINT pt;
1590             pt.x = (short)LOWORD(lParam);
1591             pt.y = (short)HIWORD(lParam);
1592             MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
1593         }
1594         break;
1595
1596     case SC_KEYMENU:
1597         MENU_TrackKbdMenuBar( hwnd, wParam, (WCHAR)lParam );
1598         break;
1599
1600     case SC_TASKLIST:
1601         WinExec( "taskman.exe", SW_SHOWNORMAL );
1602         break;
1603
1604     case SC_SCREENSAVE:
1605         if (wParam == SC_ABOUTWINE)
1606         {
1607             HMODULE hmodule = LoadLibraryA( "shell32.dll" );
1608             if (hmodule)
1609             {
1610                 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
1611                 if (aboutproc) aboutproc( hwnd, PACKAGE_NAME, PACKAGE_STRING, 0 );
1612                 FreeLibrary( hmodule );
1613             }
1614         }
1615         else
1616           if (wParam == SC_PUTMARK)
1617             DPRINTF("Debug mark requested by user\n");
1618         break;
1619
1620     case SC_HOTKEY:
1621     case SC_ARRANGE:
1622     case SC_NEXTWINDOW:
1623     case SC_PREVWINDOW:
1624         FIXME("unimplemented WM_SYSCOMMAND %04lx!\n", wParam);
1625         break;
1626     }
1627     return 0;
1628 }
1629
1630 /*************************************************************
1631 *  NC_DrawGrayButton
1632 *
1633 * Stub for the grayed button of the caption
1634 *
1635 *************************************************************/
1636
1637 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
1638 {
1639     HBITMAP hMaskBmp;
1640     HDC hdcMask;
1641     HBRUSH hOldBrush;
1642
1643     hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
1644
1645     if(hMaskBmp == 0)
1646         return FALSE;
1647
1648     hdcMask = CreateCompatibleDC (0);
1649     SelectObject (hdcMask, hMaskBmp);
1650
1651     /* Draw the grayed bitmap using the mask */
1652     hOldBrush = SelectObject (hdc, (HGDIOBJ)RGB(128, 128, 128));
1653     BitBlt (hdc, x, y, 12, 10,
1654             hdcMask, 0, 0, 0xB8074A);
1655
1656     /* Clean up */
1657     SelectObject (hdc, hOldBrush);
1658     DeleteObject(hMaskBmp);
1659     DeleteDC (hdcMask);
1660
1661     return TRUE;
1662 }
1663
1664 /***********************************************************************
1665  *              GetTitleBarInfo (USER32.@)
1666  * TODO: Handle STATE_SYSTEM_PRESSED
1667  */
1668 BOOL WINAPI GetTitleBarInfo(HWND hwnd, PTITLEBARINFO tbi) {
1669     DWORD dwStyle;
1670     DWORD dwExStyle;
1671     RECT wndRect;
1672
1673     TRACE("(%p %p)\n", hwnd, tbi);
1674
1675     if(tbi->cbSize != sizeof(TITLEBARINFO)) {
1676         TRACE("Invalid TITLEBARINFO size: %d\n", tbi->cbSize);
1677         SetLastError(ERROR_INVALID_PARAMETER);
1678         return FALSE;
1679     }
1680     dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
1681     dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
1682     NC_GetInsideRect(hwnd, &tbi->rcTitleBar);
1683
1684     GetWindowRect(hwnd, &wndRect);
1685
1686     tbi->rcTitleBar.top += wndRect.top;
1687     tbi->rcTitleBar.left += wndRect.left;
1688     tbi->rcTitleBar.right += wndRect.left;
1689
1690     tbi->rcTitleBar.bottom = tbi->rcTitleBar.top;
1691     if(dwExStyle & WS_EX_TOOLWINDOW)
1692         tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYSMCAPTION);
1693     else {
1694         tbi->rcTitleBar.bottom += GetSystemMetrics(SM_CYCAPTION);
1695         tbi->rcTitleBar.left += GetSystemMetrics(SM_CXSIZE);
1696     }
1697
1698     ZeroMemory(&tbi->rgstate, sizeof(tbi->rgstate));
1699     /* Does the title bar always have STATE_SYSTEM_FOCUSABLE?
1700      * Under XP it seems to
1701      */
1702     tbi->rgstate[0] = STATE_SYSTEM_FOCUSABLE;
1703     if(dwStyle & WS_CAPTION) {
1704         tbi->rgstate[1] = STATE_SYSTEM_INVISIBLE;
1705         if(dwStyle & WS_SYSMENU) {
1706             if(!(dwStyle & (WS_MINIMIZEBOX|WS_MAXIMIZEBOX))) {
1707                 tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1708                 tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1709             }
1710             else {
1711                 if(!(dwStyle & WS_MINIMIZEBOX))
1712                     tbi->rgstate[2] = STATE_SYSTEM_UNAVAILABLE;
1713                 if(!(dwStyle & WS_MAXIMIZEBOX))
1714                     tbi->rgstate[3] = STATE_SYSTEM_UNAVAILABLE;
1715             }
1716             if(!(dwExStyle & WS_EX_CONTEXTHELP))
1717                 tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1718             if(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE)
1719                 tbi->rgstate[5] = STATE_SYSTEM_UNAVAILABLE;
1720         }
1721         else {
1722             tbi->rgstate[2] = STATE_SYSTEM_INVISIBLE;
1723             tbi->rgstate[3] = STATE_SYSTEM_INVISIBLE;
1724             tbi->rgstate[4] = STATE_SYSTEM_INVISIBLE;
1725             tbi->rgstate[5] = STATE_SYSTEM_INVISIBLE;
1726         }
1727     }
1728     else
1729         tbi->rgstate[0] |= STATE_SYSTEM_INVISIBLE;
1730     return TRUE;
1731 }