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