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