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