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