Fixed DC leak.
[wine] / windows / nonclient.c
1 /*
2  * Non-client area window functions
3  *
4  * Copyright 1994 Alexandre Julliard
5  *
6  */
7
8 #include "windef.h"
9 #include "wingdi.h"
10 #include "wine/winuser16.h"
11 #include "version.h"
12 #include "win.h"
13 #include "user.h"
14 #include "dce.h"
15 #include "controls.h"
16 #include "cursoricon.h"
17 #include "winpos.h"
18 #include "hook.h"
19 #include "nonclient.h"
20 #include "debugtools.h"
21 #include "shellapi.h"
22 #include "bitmap.h"
23
24 DEFAULT_DEBUG_CHANNEL(nonclient);
25 DECLARE_DEBUG_CHANNEL(shell);
26
27 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
28
29 static HBITMAP hbitmapClose;
30
31 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
32                       0x55, 0x50,  
33                       0xAA, 0xA0,
34                       0x55, 0x50,  
35                       0xAA, 0xA0,
36                       0x55, 0x50,  
37                       0xAA, 0xA0,
38                       0x55, 0x50,  
39                       0xAA, 0xA0,
40                       0x55, 0x50};
41
42 #define SC_ABOUTWINE            (SC_SCREENSAVE+1)
43 #define SC_PUTMARK              (SC_SCREENSAVE+2)
44
45   /* Some useful macros */
46 #define HAS_DLGFRAME(style,exStyle) \
47     (((exStyle) & WS_EX_DLGMODALFRAME) || \
48      (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
49
50 #define HAS_THICKFRAME(style,exStyle) \
51     (((style) & WS_THICKFRAME) && \
52      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
53
54 #define HAS_THINFRAME(style) \
55     (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
56
57 #define HAS_BIGFRAME(style,exStyle) \
58     (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
59      ((exStyle) & WS_EX_DLGMODALFRAME))
60
61 #define HAS_STATICOUTERFRAME(style,exStyle) \
62     (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
63      WS_EX_STATICEDGE)
64
65 #define HAS_ANYFRAME(style,exStyle) \
66     (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
67      ((exStyle) & WS_EX_DLGMODALFRAME) || \
68      !((style) & (WS_CHILD | WS_POPUP)))
69
70 #define HAS_MENU(w)  (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
71
72
73 /***********************************************************************
74  *           NC_AdjustRect
75  *
76  * Compute the size of the window rectangle from the size of the
77  * client rectangle.
78  */
79 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
80 {
81     if (TWEAK_WineLook > WIN31_LOOK)
82         ERR("Called in Win95 mode. Aiee! Please report this.\n" );
83
84     if(style & WS_ICONIC) return;
85
86     if (HAS_THICKFRAME( style, exStyle ))
87         InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
88     else if (HAS_DLGFRAME( style, exStyle ))
89         InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
90     else if (HAS_THINFRAME( style ))
91         InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
92
93     if ((style & WS_CAPTION) == WS_CAPTION)
94         rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
95
96     if (menu) rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
97
98     if (style & WS_VSCROLL) {
99       rect->right  += GetSystemMetrics(SM_CXVSCROLL) - 1;
100       if(!HAS_ANYFRAME( style, exStyle ))
101          rect->right++;
102     }
103
104     if (style & WS_HSCROLL) {
105       rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
106       if(!HAS_ANYFRAME( style, exStyle ))
107          rect->bottom++;
108     }
109 }
110
111
112 /******************************************************************************
113  * NC_AdjustRectOuter95
114  *
115  * Computes the size of the "outside" parts of the window based on the
116  * parameters of the client area.
117  *
118  + PARAMS
119  *     LPRECT16  rect
120  *     DWORD  style
121  *     BOOL  menu
122  *     DWORD  exStyle
123  *
124  * NOTES
125  *     "Outer" parts of a window means the whole window frame, caption and
126  *     menu bar. It does not include "inner" parts of the frame like client
127  *     edge, static edge or scroll bars.
128  *
129  * Revision history
130  *     05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
131  *        Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
132  *
133  *     20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
134  *        Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
135  *        NC_AdjustRectInner95 and added handling of Win95 styles.
136  *
137  *     28-Jul-1999 Ove Kåven (ovek@arcticnet.no)
138  *        Streamlined window style checks.
139  *
140  *****************************************************************************/
141
142 static void
143 NC_AdjustRectOuter95 (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
144 {
145     int adjust;
146     if(style & WS_ICONIC) return;
147
148     if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == 
149         WS_EX_STATICEDGE)
150     {
151         adjust = 1; /* for the outer frame always present */
152     }
153     else
154     {
155         adjust = 0;
156         if ((exStyle & WS_EX_DLGMODALFRAME) ||
157             (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
158     }
159     if (style & WS_THICKFRAME)
160         adjust +=  ( GetSystemMetrics (SM_CXFRAME)
161                    - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
162     if ((style & (WS_BORDER|WS_DLGFRAME)) || 
163         (exStyle & WS_EX_DLGMODALFRAME))
164         adjust++; /* The other border */
165
166     InflateRect (rect, adjust, adjust);
167
168     if ((style & WS_CAPTION) == WS_CAPTION)
169     {
170         if (exStyle & WS_EX_TOOLWINDOW)
171             rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
172         else
173             rect->top -= GetSystemMetrics(SM_CYCAPTION);
174     }
175     if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
176 }
177
178
179 /******************************************************************************
180  * NC_AdjustRectInner95
181  *
182  * Computes the size of the "inside" part of the window based on the
183  * parameters of the client area.
184  *
185  + PARAMS
186  *     LPRECT16 rect
187  *     DWORD    style
188  *     DWORD    exStyle
189  *
190  * NOTES
191  *     "Inner" part of a window means the window frame inside of the flat
192  *     window frame. It includes the client edge, the static edge and the
193  *     scroll bars.
194  *
195  * Revision history
196  *     05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
197  *        Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
198  *
199  *     20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
200  *        Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
201  *        NC_AdjustRectInner95 and added handling of Win95 styles.
202  *
203  *****************************************************************************/
204
205 static void
206 NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle)
207 {
208     if(style & WS_ICONIC) return;
209
210     if (exStyle & WS_EX_CLIENTEDGE)
211         InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
212
213     if (style & WS_VSCROLL) rect->right  += GetSystemMetrics(SM_CXVSCROLL);
214     if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
215 }
216
217
218
219 static HICON NC_IconForWindow( HWND hwnd )
220 {
221     HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
222     if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
223
224     /* If there is no hIcon specified and this is a modal dialog,
225      * get the default one.
226      */
227     if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
228         hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
229     return hIcon;
230 }
231
232 /***********************************************************************
233  *              DrawCaption (USER32.@) Draws a caption bar
234  *
235  * PARAMS
236  *     hwnd   [I]
237  *     hdc    [I]
238  *     lpRect [I]
239  *     uFlags [I]
240  *
241  * RETURNS
242  *     Success:
243  *     Failure:
244  */
245
246 BOOL WINAPI
247 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
248 {
249     return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
250 }
251
252
253 /***********************************************************************
254  *              DrawCaptionTempA (USER32.@)
255  */
256 BOOL WINAPI DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
257                               HICON hIcon, LPCSTR str, UINT uFlags)
258 {
259     LPWSTR strW;
260     INT len;
261     BOOL ret = FALSE;
262
263     if (!(uFlags & DC_TEXT) || !str)
264         return DrawCaptionTempW( hwnd, hdc, rect, hFont, hIcon, NULL, uFlags );
265
266     len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
267     if ((strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
268     {
269         MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
270         ret = DrawCaptionTempW (hwnd, hdc, rect, hFont, hIcon, strW, uFlags);
271         HeapFree( GetProcessHeap (), 0, strW );
272     }
273     return ret;
274 }
275
276
277 /***********************************************************************
278  *              DrawCaptionTempW (USER32.@)
279  */
280 BOOL WINAPI DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
281                               HICON hIcon, LPCWSTR str, UINT uFlags)
282 {
283     RECT   rc = *rect;
284
285     TRACE("(%08x,%08x,%p,%08x,%08x,%s,%08x)\n",
286           hwnd, hdc, rect, hFont, hIcon, debugstr_w(str), uFlags);
287
288     /* drawing background */
289     if (uFlags & DC_INBUTTON) {
290         FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
291
292         if (uFlags & DC_ACTIVE) {
293             HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
294             PatBlt (hdc, rc.left, rc.top,
295                       rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
296             SelectObject (hdc, hbr);
297         }
298     }
299     else {
300         FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
301                     COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
302     }
303
304
305     /* drawing icon */
306     if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
307         POINT pt;
308
309         pt.x = rc.left + 2;
310         pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
311
312         if (!hIcon) hIcon = NC_IconForWindow(hwnd);
313         DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
314                     GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
315         rc.left += (rc.bottom - rc.top);
316     }
317
318     /* drawing text */
319     if (uFlags & DC_TEXT) {
320         HFONT hOldFont;
321
322         if (uFlags & DC_INBUTTON)
323             SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
324         else if (uFlags & DC_ACTIVE)
325             SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
326         else
327             SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
328
329         SetBkMode (hdc, TRANSPARENT);
330
331         if (hFont)
332             hOldFont = SelectObject (hdc, hFont);
333         else {
334             NONCLIENTMETRICSA nclm;
335             HFONT hNewFont;
336             nclm.cbSize = sizeof(NONCLIENTMETRICSA);
337             SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
338             hNewFont = CreateFontIndirectA ((uFlags & DC_SMALLCAP) ?
339                 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
340             hOldFont = SelectObject (hdc, hNewFont);
341         }
342
343         if (str)
344             DrawTextW (hdc, str, -1, &rc,
345                          DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
346         else {
347             WCHAR szText[128];
348             INT nLen;
349             nLen = GetWindowTextW (hwnd, szText, 128);
350             DrawTextW (hdc, szText, nLen, &rc,
351                          DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
352         }
353
354         if (hFont)
355             SelectObject (hdc, hOldFont);
356         else
357             DeleteObject (SelectObject (hdc, hOldFont));
358     }
359
360     /* drawing focus ??? */
361     if (uFlags & 0x2000)
362         FIXME("undocumented flag (0x2000)!\n");
363
364     return 0;
365 }
366
367
368 /***********************************************************************
369  *              AdjustWindowRect (USER.102)
370  */
371 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
372 {
373     return AdjustWindowRectEx16( rect, style, menu, 0 );
374 }
375
376
377 /***********************************************************************
378  *              AdjustWindowRect (USER32.@)
379  */
380 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
381 {
382     return AdjustWindowRectEx( rect, style, menu, 0 );
383 }
384
385
386 /***********************************************************************
387  *              AdjustWindowRectEx (USER.454)
388  */
389 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
390                                     BOOL16 menu, DWORD exStyle )
391 {
392     RECT rect32;
393     BOOL ret;
394
395     CONV_RECT16TO32( rect, &rect32 );
396     ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
397     CONV_RECT32TO16( &rect32, rect );
398     return ret;
399 }
400
401
402 /***********************************************************************
403  *              AdjustWindowRectEx (USER32.@)
404  */
405 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
406 {
407     /* Correct the window style */
408
409     if (!(style & (WS_POPUP | WS_CHILD))) style |= WS_CAPTION; /* Overlapped window */
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) %08lx %d %08lx\n",
416           rect->left, rect->top, rect->right, rect->bottom,
417           style, menu, exStyle );
418
419     if (TWEAK_WineLook == WIN31_LOOK)
420         NC_AdjustRect( rect, style, menu, exStyle );
421     else
422     {
423         NC_AdjustRectOuter95( rect, style, menu, exStyle );
424         NC_AdjustRectInner95( rect, style, exStyle );
425     }
426     return TRUE;
427 }
428
429
430 /***********************************************************************
431  *           NC_HandleNCCalcSize
432  *
433  * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
434  */
435 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
436 {
437     RECT tmpRect = { 0, 0, 0, 0 };
438     LONG result = 0;
439     LONG cls_style = GetClassLongA(hwnd, GCL_STYLE);
440     LONG style = GetWindowLongA( hwnd, GWL_STYLE );
441     LONG exStyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
442
443     if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
444     if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
445
446     if (!IsIconic(hwnd))
447     {
448         if (TWEAK_WineLook == WIN31_LOOK)
449             NC_AdjustRect( &tmpRect, style, FALSE, exStyle );
450         else
451             NC_AdjustRectOuter95( &tmpRect, style, FALSE, exStyle );
452
453         winRect->left   -= tmpRect.left;
454         winRect->top    -= tmpRect.top;
455         winRect->right  -= tmpRect.right;
456         winRect->bottom -= tmpRect.bottom;
457
458         if (!(style & WS_CHILD) && GetMenu(hwnd))
459         {
460             TRACE("Calling GetMenuBarHeight with HWND 0x%x, width %d, "
461                   "at (%d, %d).\n", hwnd,
462                   winRect->right - winRect->left,
463                   -tmpRect.left, -tmpRect.top );
464
465             winRect->top +=
466                 MENU_GetMenuBarHeight( hwnd,
467                                        winRect->right - winRect->left,
468                                        -tmpRect.left, -tmpRect.top ) + 1;
469         }
470
471         if (TWEAK_WineLook > WIN31_LOOK) {
472             SetRect(&tmpRect, 0, 0, 0, 0);
473             NC_AdjustRectInner95 (&tmpRect, style, exStyle);
474             winRect->left   -= tmpRect.left;
475             winRect->top    -= tmpRect.top;
476             winRect->right  -= tmpRect.right;
477             winRect->bottom -= tmpRect.bottom;
478         }
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 void NC_GetInsideRect( HWND hwnd, RECT *rect )
498 {
499     WND * wndPtr = WIN_FindWndPtr( hwnd );
500
501     rect->top    = rect->left = 0;
502     rect->right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
503     rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
504
505     if (wndPtr->dwStyle & WS_ICONIC) goto END;
506
507     /* Remove frame from rectangle */
508     if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
509     {
510         InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
511     }
512     else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
513     {
514         InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
515         /* FIXME: this isn't in NC_AdjustRect? why not? */
516         if ((TWEAK_WineLook == WIN31_LOOK) && (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
517             InflateRect( rect, -1, 0 );
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 (TWEAK_WineLook != WIN31_LOOK)
527     {
528         if ( (wndPtr->dwStyle & WS_CHILD)  &&
529              ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
530         {
531             if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
532                 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
533             if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
534                 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
535         }
536     }
537
538 END:
539     WIN_ReleaseWndPtr(wndPtr);
540     return;
541 }
542
543
544 /***********************************************************************
545  * NC_DoNCHitTest
546  *
547  * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
548  */
549
550 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
551 {
552     RECT rect;
553
554     TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
555
556     GetWindowRect(wndPtr->hwndSelf, &rect );
557     if (!PtInRect( &rect, pt )) return HTNOWHERE;
558
559     if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
560
561     /* Check borders */
562     if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
563     {
564         InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
565         if (!PtInRect( &rect, pt ))
566         {
567             /* Check top sizing border */
568             if (pt.y < rect.top)
569             {
570                 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
571                 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
572                 return HTTOP;
573             }
574             /* Check bottom sizing border */
575             if (pt.y >= rect.bottom)
576             {
577                 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
578                 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
579                 return HTBOTTOM;
580             }
581             /* Check left sizing border */
582             if (pt.x < rect.left)
583             {
584                 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
585                 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
586                 return HTLEFT;
587             }
588             /* Check right sizing border */
589             if (pt.x >= rect.right)
590             {
591                 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
592                 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
593                 return HTRIGHT;
594             }
595         }
596     }
597     else  /* No thick frame */
598     {
599         if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
600             InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
601         else if (HAS_THINFRAME( wndPtr->dwStyle ))
602             InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
603         if (!PtInRect( &rect, pt )) return HTBORDER;
604     }
605
606     /* Check caption */
607
608     if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
609     {
610         rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
611         if (!PtInRect( &rect, pt ))
612         {
613             /* Check system menu */
614             if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
615                 rect.left += GetSystemMetrics(SM_CXSIZE);
616             if (pt.x <= rect.left) return HTSYSMENU;
617
618             /* Check maximize box */
619             if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
620                 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
621
622             if (pt.x >= rect.right) return HTMAXBUTTON;
623             /* Check minimize box */
624             if (wndPtr->dwStyle & WS_MINIMIZEBOX)
625                 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
626             if (pt.x >= rect.right) return HTMINBUTTON;
627             return HTCAPTION;
628         }
629     }
630
631       /* Check client area */
632
633     ScreenToClient( wndPtr->hwndSelf, &pt );
634     GetClientRect( wndPtr->hwndSelf, &rect );
635     if (PtInRect( &rect, pt )) return HTCLIENT;
636
637       /* Check vertical scroll bar */
638
639     if (wndPtr->dwStyle & WS_VSCROLL)
640     {
641         rect.right += GetSystemMetrics(SM_CXVSCROLL);
642         if (PtInRect( &rect, pt )) return HTVSCROLL;
643     }
644
645       /* Check horizontal scroll bar */
646
647     if (wndPtr->dwStyle & WS_HSCROLL)
648     {
649         rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
650         if (PtInRect( &rect, pt ))
651         {
652               /* Check size box */
653             if ((wndPtr->dwStyle & WS_VSCROLL) &&
654                 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
655                 return HTSIZE;
656             return HTHSCROLL;
657         }
658     }
659
660       /* Check menu bar */
661
662     if (HAS_MENU(wndPtr))
663     {
664         if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
665             return HTMENU;
666     }
667
668     /* Has to return HTNOWHERE if nothing was found  
669        Could happen when a window has a customized non client area */
670     return HTNOWHERE;  
671 }
672
673
674 /***********************************************************************
675  * NC_DoNCHitTest95
676  *
677  * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
678  *
679  * FIXME:  Just a modified copy of the Win 3.1 version.
680  */
681
682 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
683 {
684     RECT rect;
685
686     TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
687
688     GetWindowRect(wndPtr->hwndSelf, &rect );
689     if (!PtInRect( &rect, pt )) return HTNOWHERE;
690
691     if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
692
693     /* Check borders */
694     if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
695     {
696         InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
697         if (!PtInRect( &rect, pt ))
698         {
699             /* Check top sizing border */
700             if (pt.y < rect.top)
701             {
702                 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
703                 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
704                 return HTTOP;
705             }
706             /* Check bottom sizing border */
707             if (pt.y >= rect.bottom)
708             {
709                 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
710                 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
711                 return HTBOTTOM;
712             }
713             /* Check left sizing border */
714             if (pt.x < rect.left)
715             {
716                 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
717                 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
718                 return HTLEFT;
719             }
720             /* Check right sizing border */
721             if (pt.x >= rect.right)
722             {
723                 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
724                 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
725                 return HTRIGHT;
726             }
727         }
728     }
729     else  /* No thick frame */
730     {
731         if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
732             InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
733         else if (HAS_THINFRAME( wndPtr->dwStyle ))
734             InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
735         if (!PtInRect( &rect, pt )) return HTBORDER;
736     }
737
738     /* Check caption */
739
740     if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
741     {
742         if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
743             rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
744         else
745             rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
746         if (!PtInRect( &rect, pt ))
747         {
748             /* Check system menu */
749             if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
750             {
751                 if (NC_IconForWindow(wndPtr->hwndSelf))
752                     rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
753             }
754             if (pt.x < rect.left) return HTSYSMENU;
755
756             /* Check close button */
757             if (wndPtr->dwStyle & WS_SYSMENU)
758                 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
759             if (pt.x > rect.right) return HTCLOSE;
760
761             /* Check maximize box */
762             /* In win95 there is automatically a Maximize button when there is a minimize one*/
763             if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
764                 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
765             if (pt.x > rect.right) return HTMAXBUTTON;
766
767             /* Check minimize box */
768             /* In win95 there is automatically a Maximize button when there is a Maximize one*/
769             if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
770                 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
771
772             if (pt.x > rect.right) return HTMINBUTTON;
773             return HTCAPTION;
774         }
775     }
776
777       /* Check client area */
778
779     ScreenToClient( wndPtr->hwndSelf, &pt );
780     GetClientRect( wndPtr->hwndSelf, &rect );
781     if (PtInRect( &rect, pt )) return HTCLIENT;
782
783       /* Check vertical scroll bar */
784
785     if (wndPtr->dwStyle & WS_VSCROLL)
786     {
787         rect.right += GetSystemMetrics(SM_CXVSCROLL);
788         if (PtInRect( &rect, pt )) return HTVSCROLL;
789     }
790
791       /* Check horizontal scroll bar */
792
793     if (wndPtr->dwStyle & WS_HSCROLL)
794     {
795         rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
796         if (PtInRect( &rect, pt ))
797         {
798               /* Check size box */
799             if ((wndPtr->dwStyle & WS_VSCROLL) &&
800                 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
801                 return HTSIZE;
802             return HTHSCROLL;
803         }
804     }
805
806       /* Check menu bar */
807
808     if (HAS_MENU(wndPtr))
809     {
810         if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
811             return HTMENU;
812     }
813
814     /* Has to return HTNOWHERE if nothing was found  
815        Could happen when a window has a customized non client area */
816     return HTNOWHERE;
817 }
818
819
820 /***********************************************************************
821  * NC_HandleNCHitTest
822  *
823  * Handle a WM_NCHITTEST message. Called from DefWindowProc().
824  */
825 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
826 {
827     LONG retvalue;
828     WND *wndPtr = WIN_FindWndPtr (hwnd);
829
830     if (!wndPtr)
831         return HTERROR;
832
833     if (TWEAK_WineLook == WIN31_LOOK)
834         retvalue = NC_DoNCHitTest (wndPtr, pt);
835     else
836         retvalue = NC_DoNCHitTest95 (wndPtr, pt);
837     WIN_ReleaseWndPtr(wndPtr);
838     return retvalue;
839 }
840
841
842 /***********************************************************************
843  *           NC_DrawSysButton
844  */
845 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
846 {
847     RECT rect;
848     HDC hdcMem;
849     HBITMAP hbitmap;
850
851     NC_GetInsideRect( hwnd, &rect );
852     hdcMem = CreateCompatibleDC( hdc );
853     hbitmap = SelectObject( hdcMem, hbitmapClose );
854     BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
855            hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
856            down ? NOTSRCCOPY : SRCCOPY );
857     SelectObject( hdcMem, hbitmap );
858     DeleteDC( hdcMem );
859 }
860
861
862 /***********************************************************************
863  *           NC_DrawMaxButton
864  */
865 static void NC_DrawMaxButton( HWND hwnd, HDC16 hdc, BOOL down )
866 {
867     RECT rect;
868     UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
869
870     NC_GetInsideRect( hwnd, &rect );
871     rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
872     rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
873     rect.top += 1;
874     rect.right -= 1;
875     if (down) flags |= DFCS_PUSHED;
876     DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
877 }
878
879
880 /***********************************************************************
881  *           NC_DrawMinButton
882  */
883 static void NC_DrawMinButton( HWND hwnd, HDC16 hdc, BOOL down )
884 {
885     RECT rect;
886     UINT flags = DFCS_CAPTIONMIN;
887     DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
888
889     NC_GetInsideRect( hwnd, &rect );
890     if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
891         rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
892     rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) + 1;
893     rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
894     rect.top += 1;
895     rect.right -= 1;
896     if (down) flags |= DFCS_PUSHED;
897     DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
898 }
899
900
901 /******************************************************************************
902  *
903  *   void  NC_DrawSysButton95(
904  *      HWND  hwnd,
905  *      HDC  hdc,
906  *      BOOL  down )
907  *
908  *   Draws the Win95 system icon.
909  *
910  *   Revision history
911  *        05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
912  *             Original implementation from NC_DrawSysButton source.
913  *        11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
914  *             Fixed most bugs.
915  *
916  *****************************************************************************/
917
918 BOOL
919 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
920 {
921     HICON hIcon = NC_IconForWindow( hwnd );
922
923     if (hIcon)
924     {
925         RECT rect;
926         NC_GetInsideRect( hwnd, &rect );
927         DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon,
928                     GetSystemMetrics(SM_CXSMICON),
929                     GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
930     }
931     return (hIcon != 0);
932 }
933
934
935 /******************************************************************************
936  *
937  *   void  NC_DrawCloseButton95(
938  *      HWND  hwnd,
939  *      HDC  hdc,
940  *      BOOL  down,
941  *      BOOL    bGrayed )
942  *
943  *   Draws the Win95 close button.
944  *
945  *   If bGrayed is true, then draw a disabled Close button
946  *
947  *   Revision history
948  *        11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
949  *             Original implementation from NC_DrawSysButton95 source.
950  *
951  *****************************************************************************/
952
953 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
954 {
955     RECT rect;
956
957     NC_GetInsideRect( hwnd, &rect );
958
959     /* A tool window has a smaller Close button */
960     if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
961     {
962         INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE   */
963         INT iBmpWidth = 11;  /* it uses 11x11 for  the close button in tool window */
964         INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
965
966         rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
967         rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
968         rect.bottom = rect.top + iBmpHeight;
969         rect.right = rect.left + iBmpWidth;
970     }
971     else
972     {
973         rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
974         rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
975         rect.top += 2;
976         rect.right -= 2;
977     }
978     DrawFrameControl( hdc, &rect, DFC_CAPTION,
979                       (DFCS_CAPTIONCLOSE |
980                        (down ? DFCS_PUSHED : 0) |
981                        (bGrayed ? DFCS_INACTIVE : 0)) );
982 }
983
984 /******************************************************************************
985  *   NC_DrawMaxButton95
986  *
987  *   Draws the maximize button for Win95 style windows.
988  *   If bGrayed is true, then draw a disabled Maximize button
989  */
990 static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
991 {
992     RECT rect;
993     UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
994
995     NC_GetInsideRect( hwnd, &rect );
996     if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
997         rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
998     rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
999     rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1000     rect.top += 2;
1001     rect.right -= 2;
1002     if (down) flags |= DFCS_PUSHED;
1003     if (bGrayed) flags |= DFCS_INACTIVE;
1004     DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1005 }
1006
1007 /******************************************************************************
1008  *   NC_DrawMinButton95
1009  *
1010  *   Draws the minimize button for Win95 style windows.
1011  *   If bGrayed is true, then draw a disabled Minimize button
1012  */
1013 static void  NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1014 {
1015     RECT rect;
1016     UINT flags = DFCS_CAPTIONMIN;
1017     DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
1018
1019     NC_GetInsideRect( hwnd, &rect );
1020     if (style & WS_SYSMENU)
1021         rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1022     if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1023         rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1024     rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1025     rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1026     rect.top += 2;
1027     rect.right -= 2;
1028     if (down) flags |= DFCS_PUSHED;
1029     if (bGrayed) flags |= DFCS_INACTIVE;
1030     DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1031 }
1032
1033 /***********************************************************************
1034  *           NC_DrawFrame
1035  *
1036  * Draw a window frame inside the given rectangle, and update the rectangle.
1037  * The correct pen for the frame must be selected in the DC.
1038  */
1039 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1040                           BOOL active )
1041 {
1042     INT width, height;
1043
1044     if (TWEAK_WineLook != WIN31_LOOK)
1045         ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1046
1047     if (dlgFrame)
1048     {
1049         width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1050         height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1051         SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1052                                                 COLOR_INACTIVECAPTION) );
1053     }
1054     else
1055     {
1056         width = GetSystemMetrics(SM_CXFRAME) - 2;
1057         height = GetSystemMetrics(SM_CYFRAME) - 2;
1058         SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1059                                                 COLOR_INACTIVEBORDER) );
1060     }
1061
1062       /* Draw frame */
1063     PatBlt( hdc, rect->left, rect->top,
1064               rect->right - rect->left, height, PATCOPY );
1065     PatBlt( hdc, rect->left, rect->top,
1066               width, rect->bottom - rect->top, PATCOPY );
1067     PatBlt( hdc, rect->left, rect->bottom - 1,
1068               rect->right - rect->left, -height, PATCOPY );
1069     PatBlt( hdc, rect->right - 1, rect->top,
1070               -width, rect->bottom - rect->top, PATCOPY );
1071
1072     if (dlgFrame)
1073     {
1074         InflateRect( rect, -width, -height );
1075     } 
1076     else
1077     {
1078         INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1079         INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1080
1081       /* Draw inner rectangle */
1082
1083         SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1084         Rectangle( hdc, rect->left + width, rect->top + height,
1085                      rect->right - width , rect->bottom - height );
1086
1087       /* Draw the decorations */
1088
1089         MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1090         LineTo( hdc, rect->left + width, rect->top + decYOff );
1091         MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1092         LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1093         MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1094         LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1095         MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1096         LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1097
1098         MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1099         LineTo( hdc, rect->left + decXOff, rect->top + height);
1100         MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1101         LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1102         MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1103         LineTo( hdc, rect->right - decXOff, rect->top + height );
1104         MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1105         LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1106
1107         InflateRect( rect, -width - 1, -height - 1 );
1108     }
1109 }
1110
1111
1112 /******************************************************************************
1113  *
1114  *   void  NC_DrawFrame95(
1115  *      HDC  hdc,
1116  *      RECT  *rect,
1117  *      BOOL  active,
1118  *      DWORD style,
1119  *      DWORD exStyle )
1120  *
1121  *   Draw a window frame inside the given rectangle, and update the rectangle.
1122  *
1123  *   Bugs
1124  *        Many.  First, just what IS a frame in Win95?  Note that the 3D look
1125  *        on the outer edge is handled by NC_DoNCPaint95.  As is the inner
1126  *        edge.  The inner rectangle just inside the frame is handled by the
1127  *        Caption code.
1128  *
1129  *        In short, for most people, this function should be a nop (unless
1130  *        you LIKE thick borders in Win95/NT4.0 -- I've been working with
1131  *        them lately, but just to get this code right).  Even so, it doesn't
1132  *        appear to be so.  It's being worked on...
1133  * 
1134  *   Revision history
1135  *        06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1136  *             Original implementation (based on NC_DrawFrame)
1137  *        02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1138  *             Some minor fixes.
1139  *        29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1140  *             Fixed a fix or something.
1141  *
1142  *****************************************************************************/
1143
1144 static void  NC_DrawFrame95(
1145     HDC  hdc,
1146     RECT  *rect,
1147     BOOL  active,
1148     DWORD style,
1149     DWORD exStyle)
1150 {
1151     INT width, height;
1152
1153     /* Firstly the "thick" frame */
1154     if (style & WS_THICKFRAME)
1155     {
1156         width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
1157         height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
1158
1159         SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1160                       COLOR_INACTIVEBORDER) );
1161         /* Draw frame */
1162         PatBlt( hdc, rect->left, rect->top,
1163                   rect->right - rect->left, height, PATCOPY );
1164         PatBlt( hdc, rect->left, rect->top,
1165                   width, rect->bottom - rect->top, PATCOPY );
1166         PatBlt( hdc, rect->left, rect->bottom - 1,
1167                   rect->right - rect->left, -height, PATCOPY );
1168         PatBlt( hdc, rect->right - 1, rect->top,
1169                   -width, rect->bottom - rect->top, PATCOPY );
1170
1171         InflateRect( rect, -width, -height );
1172     }
1173
1174     /* Now the other bit of the frame */
1175     if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1176         (exStyle & WS_EX_DLGMODALFRAME))
1177     {
1178         width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1179         height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1180         /* This should give a value of 1 that should also work for a border */
1181
1182         SelectObject( hdc, GetSysColorBrush(
1183                       (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
1184                           COLOR_3DFACE :
1185                       (exStyle & WS_EX_STATICEDGE) ?
1186                           COLOR_WINDOWFRAME :
1187                       (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
1188                           COLOR_3DFACE :
1189                       /* else */
1190                           COLOR_WINDOWFRAME));
1191
1192         /* Draw frame */
1193         PatBlt( hdc, rect->left, rect->top,
1194                   rect->right - rect->left, height, PATCOPY );
1195         PatBlt( hdc, rect->left, rect->top,
1196                   width, rect->bottom - rect->top, PATCOPY );
1197         PatBlt( hdc, rect->left, rect->bottom - 1,
1198                   rect->right - rect->left, -height, PATCOPY );
1199         PatBlt( hdc, rect->right - 1, rect->top,
1200                   -width, rect->bottom - rect->top, PATCOPY );
1201
1202         InflateRect( rect, -width, -height );
1203     }
1204 }
1205
1206
1207 /***********************************************************************
1208  *           NC_DrawCaption
1209  *
1210  * Draw the window caption.
1211  * The correct pen for the window frame must be selected in the DC.
1212  */
1213 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1214                             DWORD style, BOOL active )
1215 {
1216     RECT r = *rect;
1217     char buffer[256];
1218
1219     if (!hbitmapClose)
1220     {
1221         if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_OLD_CLOSE) ))) return;
1222     }
1223     
1224     if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
1225     {
1226         HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1227         PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1228         PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1229         PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1230         r.left++;
1231         r.right--;
1232         SelectObject( hdc, hbrushOld );
1233     }
1234     MoveToEx( hdc, r.left, r.bottom, NULL );
1235     LineTo( hdc, r.right, r.bottom );
1236
1237     if (style & WS_SYSMENU)
1238     {
1239         NC_DrawSysButton( hwnd, hdc, FALSE );
1240         r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1241         MoveToEx( hdc, r.left - 1, r.top, NULL );
1242         LineTo( hdc, r.left - 1, r.bottom );
1243     }
1244     FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
1245     if (style & WS_MAXIMIZEBOX)
1246     {
1247         NC_DrawMaxButton( hwnd, hdc, FALSE );
1248         r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1249     }
1250     if (style & WS_MINIMIZEBOX)
1251     {
1252         NC_DrawMinButton( hwnd, hdc, FALSE );
1253         r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1254     }
1255
1256     if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1257     {
1258         if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1259         else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1260         SetBkMode( hdc, TRANSPARENT );
1261         DrawTextA( hdc, buffer, -1, &r,
1262                      DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1263     }
1264 }
1265
1266
1267 /******************************************************************************
1268  *
1269  *   NC_DrawCaption95(
1270  *      HDC  hdc,
1271  *      RECT *rect,
1272  *      HWND hwnd,
1273  *      DWORD  style,
1274  *      BOOL active )
1275  *
1276  *   Draw the window caption for Win95 style windows.
1277  *   The correct pen for the window frame must be selected in the DC.
1278  *
1279  *   Bugs
1280  *        Hey, a function that finally works!  Well, almost.
1281  *        It's being worked on.
1282  *
1283  *   Revision history
1284  *        05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1285  *             Original implementation.
1286  *        02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1287  *             Some minor fixes.
1288  *
1289  *****************************************************************************/
1290
1291 static void  NC_DrawCaption95(
1292     HDC  hdc,
1293     RECT *rect,
1294     HWND hwnd,
1295     DWORD  style,
1296     DWORD  exStyle,
1297     BOOL active )
1298 {
1299     RECT  r = *rect;
1300     char    buffer[256];
1301     HPEN  hPrevPen;
1302     HMENU hSysMenu;
1303
1304     hPrevPen = SelectObject( hdc, GetSysColorPen(
1305                      ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
1306                                  WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
1307                       COLOR_WINDOWFRAME : COLOR_3DFACE) );
1308     MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1309     LineTo( hdc, r.right, r.bottom - 1 );
1310     SelectObject( hdc, hPrevPen );
1311     r.bottom--;
1312
1313     FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1314                                             COLOR_INACTIVECAPTION) );
1315
1316     if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1317         if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1318             r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1319     }
1320
1321     if (style & WS_SYSMENU) 
1322     {
1323         UINT state;
1324
1325         /* Go get the sysmenu */
1326         hSysMenu = GetSystemMenu(hwnd, FALSE);
1327         state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1328
1329         /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1330         NC_DrawCloseButton95 (hwnd, hdc, FALSE, 
1331                               ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1332         r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1333
1334         if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1335         {
1336             /* In win95 the two buttons are always there */
1337             /* But if the menu item is not in the menu they're disabled*/
1338
1339             NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1340             r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1341             
1342             NC_DrawMinButton95( hwnd, hdc, FALSE,  (!(style & WS_MINIMIZEBOX)));
1343             r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1344         }
1345     }
1346
1347     if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1348         NONCLIENTMETRICSA nclm;
1349         HFONT hFont, hOldFont;
1350         nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1351         SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1352         if (exStyle & WS_EX_TOOLWINDOW)
1353             hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1354         else
1355             hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1356         hOldFont = SelectObject (hdc, hFont);
1357         if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1358         else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1359         SetBkMode( hdc, TRANSPARENT );
1360         r.left += 2;
1361         DrawTextA( hdc, buffer, -1, &r,
1362                      DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1363         DeleteObject (SelectObject (hdc, hOldFont));
1364     }
1365 }
1366
1367
1368
1369 /***********************************************************************
1370  *           NC_DoNCPaint
1371  *
1372  * Paint the non-client area. clip is currently unused.
1373  */
1374 static void NC_DoNCPaint( HWND hwnd, HRGN clip, BOOL suppress_menupaint )
1375 {
1376     HDC hdc;
1377     RECT rect;
1378     BOOL active;
1379     WND *wndPtr;
1380     DWORD dwStyle, dwExStyle;
1381     WORD flags;
1382     RECT rectClient, rectWindow;
1383     int has_menu;
1384
1385     if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1386     has_menu = HAS_MENU(wndPtr);
1387     dwStyle = wndPtr->dwStyle;
1388     dwExStyle = wndPtr->dwExStyle;    
1389     flags = wndPtr->flags;
1390     rectClient = wndPtr->rectClient;
1391     rectWindow = wndPtr->rectWindow;
1392     WIN_ReleasePtr( wndPtr );
1393
1394     if ( dwStyle & WS_MINIMIZE ||
1395          !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1396
1397     active  = flags & WIN_NCACTIVATED;
1398
1399     TRACE("%04x %d\n", hwnd, active );
1400
1401     if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1402                               ((clip > 1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1403
1404     if (ExcludeVisRect16( hdc, rectClient.left-rectWindow.left,
1405                         rectClient.top-rectWindow.top,
1406                         rectClient.right-rectWindow.left,
1407                         rectClient.bottom-rectWindow.top )
1408         == NULLREGION)
1409     {
1410         ReleaseDC( hwnd, hdc );
1411         return;
1412     }
1413
1414     rect.top = rect.left = 0;
1415     rect.right  = rectWindow.right - rectWindow.left;
1416     rect.bottom = rectWindow.bottom - rectWindow.top;
1417
1418     SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1419
1420     if (HAS_ANYFRAME( dwStyle, dwExStyle ))
1421     {
1422         SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1423         Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1424         InflateRect( &rect, -1, -1 );
1425     }
1426
1427     if (HAS_THICKFRAME( dwStyle, dwExStyle ))
1428         NC_DrawFrame(hdc, &rect, FALSE, active );
1429     else if (HAS_DLGFRAME( dwStyle, dwExStyle ))
1430         NC_DrawFrame( hdc, &rect, TRUE, active );
1431
1432     if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1433     {
1434         RECT r = rect;
1435         r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1436         rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1437         NC_DrawCaption( hdc, &r, hwnd, dwStyle, active );
1438     }
1439
1440     if (has_menu)
1441     {
1442         RECT r = rect;
1443         r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);  /* default height */
1444         rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1445     }
1446
1447       /* Draw the scroll-bars */
1448
1449     if (dwStyle & WS_VSCROLL)
1450         SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1451     if (dwStyle & WS_HSCROLL)
1452         SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1453
1454       /* Draw the "size-box" */
1455
1456     if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1457     {
1458         RECT r = rect;
1459         r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1460         r.top  = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1461         if(wndPtr->dwStyle & WS_BORDER) {
1462           r.left++;
1463           r.top++;
1464         }
1465         FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1466     }    
1467
1468     ReleaseDC( hwnd, hdc );
1469 }
1470
1471
1472 /******************************************************************************
1473  *
1474  *   void  NC_DoNCPaint95(
1475  *      HWND  hwnd,
1476  *      HRGN  clip,
1477  *      BOOL  suppress_menupaint )
1478  *
1479  *   Paint the non-client area for Win95 windows.  The clip region is
1480  *   currently ignored.
1481  *
1482  *   Bugs
1483  *        grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1484  *           misc/tweak.c controls/menu.c  # :-)
1485  *
1486  *   Revision history
1487  *        03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1488  *             Original implementation
1489  *        10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1490  *             Fixed some bugs.
1491  *        29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1492  *             Streamlined window style checks.
1493  *
1494  *****************************************************************************/
1495
1496 static void  NC_DoNCPaint95(
1497     HWND  hwnd,
1498     HRGN  clip,
1499     BOOL  suppress_menupaint )
1500 {
1501     HDC hdc;
1502     RECT rfuzz, rect, rectClip;
1503     BOOL active;
1504     WND *wndPtr;
1505     DWORD dwStyle, dwExStyle;
1506     WORD flags;
1507     RECT rectClient, rectWindow;
1508     int has_menu;
1509
1510     if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return;
1511     has_menu = HAS_MENU(wndPtr);
1512     dwStyle = wndPtr->dwStyle;
1513     dwExStyle = wndPtr->dwExStyle;    
1514     flags = wndPtr->flags;
1515     rectClient = wndPtr->rectClient;
1516     rectWindow = wndPtr->rectWindow;
1517     WIN_ReleasePtr( wndPtr );
1518
1519     if ( dwStyle & WS_MINIMIZE ||
1520          !WIN_IsWindowDrawable( hwnd, 0 )) return; /* Nothing to do */
1521
1522     active  = flags & WIN_NCACTIVATED;
1523
1524     TRACE("%04x %d\n", hwnd, active );
1525
1526     /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1527        the call to GetDCEx implying that it is allowed not to use it either.
1528        However, the suggested GetDCEx(    , DCX_WINDOW | DCX_INTERSECTRGN)
1529        will cause clipRgn to be deleted after ReleaseDC().
1530        Now, how is the "system" supposed to tell what happened?
1531      */
1532
1533     if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1534                               ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1535
1536
1537     if (ExcludeVisRect16( hdc, rectClient.left-rectWindow.left,
1538                         rectClient.top-rectWindow.top,
1539                         rectClient.right-rectWindow.left,
1540                         rectClient.bottom-rectWindow.top )
1541         == NULLREGION)
1542     {
1543         ReleaseDC( hwnd, hdc );
1544         return;
1545     }
1546
1547     rect.top = rect.left = 0;
1548     rect.right  = rectWindow.right - rectWindow.left;
1549     rect.bottom = rectWindow.bottom - rectWindow.top;
1550
1551     if( clip > 1 )
1552         GetRgnBox( clip, &rectClip );
1553     else
1554     {
1555         clip = 0;
1556         rectClip = rect;
1557     }
1558
1559     SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1560
1561     if (HAS_STATICOUTERFRAME(dwStyle, dwExStyle)) {
1562         DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1563     }
1564     else if (HAS_BIGFRAME( dwStyle, dwExStyle)) {
1565         DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1566     }
1567
1568     NC_DrawFrame95(hdc, &rect, active, dwStyle, dwExStyle );
1569
1570     if ((dwStyle & WS_CAPTION) == WS_CAPTION)
1571     {
1572         RECT  r = rect;
1573         if (dwExStyle & WS_EX_TOOLWINDOW) {
1574             r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1575             rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1576         }
1577         else {
1578             r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1579             rect.top += GetSystemMetrics(SM_CYCAPTION);
1580         }
1581         if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1582             NC_DrawCaption95 (hdc, &r, hwnd, dwStyle,
1583                               dwExStyle, active);
1584     }
1585
1586     if (has_menu)
1587     {
1588         RECT r = rect;
1589         r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1590         
1591         TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1592               r.left, r.top, r.right, r.bottom);
1593
1594         rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1595     }
1596
1597     TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1598           rect.left, rect.top, rect.right, rect.bottom );
1599
1600     if (dwExStyle & WS_EX_CLIENTEDGE)
1601         DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1602
1603     /* Draw the scroll-bars */
1604
1605     if (dwStyle & WS_VSCROLL)
1606         SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1607     if (dwStyle & WS_HSCROLL)
1608         SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1609
1610     /* Draw the "size-box" */
1611     if ((dwStyle & WS_VSCROLL) && (dwStyle & WS_HSCROLL))
1612     {
1613         RECT r = rect;
1614         r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1615         r.top  = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1616         FillRect( hdc, &r,  GetSysColorBrush(COLOR_SCROLLBAR) );
1617     }    
1618
1619     ReleaseDC( hwnd, hdc );
1620 }
1621
1622
1623
1624
1625 /***********************************************************************
1626  *           NC_HandleNCPaint
1627  *
1628  * Handle a WM_NCPAINT message. Called from DefWindowProc().
1629  */
1630 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1631 {
1632     DWORD dwStyle = GetWindowLongW( hwnd, GWL_STYLE );
1633
1634     if( dwStyle & WS_VISIBLE )
1635     {
1636         if( dwStyle & WS_MINIMIZE )
1637             WINPOS_RedrawIconTitle( hwnd );
1638         else if (TWEAK_WineLook == WIN31_LOOK)
1639             NC_DoNCPaint( hwnd, clip, FALSE );
1640         else
1641             NC_DoNCPaint95( hwnd, clip, FALSE );
1642     }
1643     return 0;
1644 }
1645
1646
1647 /***********************************************************************
1648  *           NC_HandleNCActivate
1649  *
1650  * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1651  */
1652 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1653 {
1654     WND* wndPtr = WIN_FindWndPtr( hwnd );
1655
1656     /* Lotus Notes draws menu descriptions in the caption of its main
1657      * window. When it wants to restore original "system" view, it just
1658      * sends WM_NCACTIVATE message to itself. Any optimizations here in
1659      * attempt to minimize redrawings lead to a not restored caption.
1660      */
1661     if (wndPtr)
1662     {
1663         if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1664         else wndPtr->flags &= ~WIN_NCACTIVATED;
1665         WIN_ReleaseWndPtr(wndPtr);
1666
1667         if (IsIconic(hwnd)) WINPOS_RedrawIconTitle( hwnd );
1668         else if (TWEAK_WineLook == WIN31_LOOK)
1669             NC_DoNCPaint( hwnd, (HRGN)1, FALSE );
1670         else
1671             NC_DoNCPaint95( hwnd, (HRGN)1, FALSE );
1672     }
1673     return TRUE;
1674 }
1675
1676
1677 /***********************************************************************
1678  *           NC_HandleSetCursor
1679  *
1680  * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1681  */
1682 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1683 {
1684     if (hwnd != WIN_GetFullHandle( (HWND)wParam ))
1685         return 0;  /* Don't set the cursor for child windows */
1686
1687     switch(LOWORD(lParam))
1688     {
1689     case HTERROR:
1690         {
1691             WORD msg = HIWORD( lParam );
1692             if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1693                 (msg == WM_RBUTTONDOWN))
1694                 MessageBeep(0);
1695         }
1696         break;
1697
1698     case HTCLIENT:
1699         {
1700             HCURSOR hCursor = GetClassLongA(hwnd, GCL_HCURSOR);
1701             if(hCursor) {
1702                 SetCursor(hCursor);
1703                 return TRUE;
1704             }
1705             return FALSE;
1706         }
1707
1708     case HTLEFT:
1709     case HTRIGHT:
1710         return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZEWEA ) );
1711
1712     case HTTOP:
1713     case HTBOTTOM:
1714         return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENSA ) );
1715
1716     case HTTOPLEFT:
1717     case HTBOTTOMRIGHT: 
1718         return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENWSEA ) );
1719
1720     case HTTOPRIGHT:
1721     case HTBOTTOMLEFT:
1722         return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENESWA ) );
1723     }
1724
1725     /* Default cursor: arrow */
1726     return (LONG)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
1727 }
1728
1729 /***********************************************************************
1730  *           NC_GetSysPopupPos
1731  */
1732 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1733 {
1734     if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1735     else
1736     {
1737         WND *wndPtr = WIN_FindWndPtr( hwnd );
1738         if (!wndPtr) return;
1739
1740         NC_GetInsideRect( hwnd, rect );
1741         OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1742         if (wndPtr->dwStyle & WS_CHILD)
1743             ClientToScreen( GetParent(hwnd), (POINT *)rect );
1744         if (TWEAK_WineLook == WIN31_LOOK) {
1745             rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
1746             rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
1747         }
1748         else {
1749             rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1750             rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1751         }
1752         WIN_ReleaseWndPtr( wndPtr );
1753     }
1754 }
1755
1756 /***********************************************************************
1757  *           NC_TrackMinMaxBox95
1758  *
1759  * Track a mouse button press on the minimize or maximize box.
1760  *
1761  * The big difference between 3.1 and 95 is the disabled button state.
1762  * In win95 the system button can be disabled, so it can ignore the mouse
1763  * event.
1764  *
1765  */
1766 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
1767 {
1768     MSG msg;
1769     HDC hdc = GetWindowDC( hwnd );
1770     BOOL pressed = TRUE;
1771     UINT state;
1772     DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
1773     HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1774
1775     void  (*paintButton)(HWND, HDC16, BOOL, BOOL);
1776
1777     if (wParam == HTMINBUTTON)
1778     {
1779         /* If the style is not present, do nothing */
1780         if (!(wndStyle & WS_MINIMIZEBOX))
1781             return;
1782
1783         /* Check if the sysmenu item for minimize is there  */
1784         state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1785         
1786         paintButton = &NC_DrawMinButton95;
1787     }
1788     else
1789     {
1790         /* If the style is not present, do nothing */
1791         if (!(wndStyle & WS_MAXIMIZEBOX))
1792             return;
1793
1794         /* Check if the sysmenu item for maximize is there  */
1795         state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1796         
1797         paintButton = &NC_DrawMaxButton95;
1798     }
1799
1800     SetCapture( hwnd );
1801
1802     (*paintButton)( hwnd, hdc, TRUE, FALSE);
1803
1804     while(1)
1805     {
1806         BOOL oldstate = pressed;
1807
1808         if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1809         if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1810
1811         if(msg.message == WM_LBUTTONUP)
1812             break;
1813
1814         if(msg.message != WM_MOUSEMOVE)
1815             continue;
1816
1817         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1818         if (pressed != oldstate)
1819            (*paintButton)( hwnd, hdc, pressed, FALSE);
1820     }
1821
1822     if(pressed)
1823         (*paintButton)(hwnd, hdc, FALSE, FALSE);
1824
1825     ReleaseCapture();
1826     ReleaseDC( hwnd, hdc );
1827
1828     /* If the item minimize or maximize of the sysmenu are not there */
1829     /* or if the style is not present, do nothing */
1830     if ((!pressed) || (state == 0xFFFFFFFF))
1831         return;
1832
1833     if (wParam == HTMINBUTTON) 
1834         SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1835     else
1836         SendMessageA( hwnd, WM_SYSCOMMAND,
1837                       IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1838 }
1839
1840 /***********************************************************************
1841  *           NC_TrackMinMaxBox
1842  *
1843  * Track a mouse button press on the minimize or maximize box.
1844  */
1845 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1846 {
1847     MSG msg;
1848     HDC hdc = GetWindowDC( hwnd );
1849     BOOL pressed = TRUE;
1850     void  (*paintButton)(HWND, HDC16, BOOL);
1851
1852     SetCapture( hwnd );
1853
1854     if (wParam == HTMINBUTTON)
1855         paintButton = &NC_DrawMinButton;
1856     else
1857         paintButton = &NC_DrawMaxButton;
1858
1859     (*paintButton)( hwnd, hdc, TRUE);
1860
1861     while(1)
1862     {
1863         BOOL oldstate = pressed;
1864
1865         if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1866         if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1867
1868         if(msg.message == WM_LBUTTONUP)
1869             break;
1870
1871         if(msg.message != WM_MOUSEMOVE)
1872             continue;
1873
1874         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1875         if (pressed != oldstate)
1876            (*paintButton)( hwnd, hdc, pressed);
1877     }
1878
1879     if(pressed)
1880         (*paintButton)( hwnd, hdc, FALSE);
1881
1882     ReleaseCapture();
1883     ReleaseDC( hwnd, hdc );
1884
1885     if (!pressed) return;
1886
1887     if (wParam == HTMINBUTTON) 
1888         SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1889     else
1890         SendMessageA( hwnd, WM_SYSCOMMAND,
1891                       IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1892 }
1893
1894
1895 /***********************************************************************
1896  * NC_TrackCloseButton95
1897  *
1898  * Track a mouse button press on the Win95 close button.
1899  */
1900 static void
1901 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
1902 {
1903     MSG msg;
1904     HDC hdc;
1905     BOOL pressed = TRUE;
1906     HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1907     UINT state;
1908
1909     if(hSysMenu == 0)
1910         return;
1911
1912     state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1913             
1914     /* If the item close of the sysmenu is disabled or not there do nothing */
1915     if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1916         return;
1917
1918     hdc = GetWindowDC( hwnd );
1919
1920     SetCapture( hwnd );
1921
1922     NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
1923
1924     while(1)
1925     {
1926         BOOL oldstate = pressed;
1927
1928         if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1929         if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1930
1931         if(msg.message == WM_LBUTTONUP)
1932             break;
1933
1934         if(msg.message != WM_MOUSEMOVE)
1935             continue;
1936
1937         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1938         if (pressed != oldstate)
1939            NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
1940     }
1941
1942     if(pressed)
1943         NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
1944
1945     ReleaseCapture();
1946     ReleaseDC( hwnd, hdc );
1947     if (!pressed) return;
1948
1949     SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1950 }
1951
1952
1953 /***********************************************************************
1954  *           NC_TrackScrollBar
1955  *
1956  * Track a mouse button press on the horizontal or vertical scroll-bar.
1957  */
1958 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1959 {
1960     INT scrollbar;
1961
1962     if ((wParam & 0xfff0) == SC_HSCROLL)
1963     {
1964         if ((wParam & 0x0f) != HTHSCROLL) return;
1965         scrollbar = SB_HORZ;
1966     }
1967     else  /* SC_VSCROLL */
1968     {
1969         if ((wParam & 0x0f) != HTVSCROLL) return;
1970         scrollbar = SB_VERT;
1971     }
1972     SCROLL_TrackScrollBar( hwnd, scrollbar, pt );
1973 }
1974
1975
1976 /***********************************************************************
1977  *           NC_HandleNCLButtonDown
1978  *
1979  * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1980  */
1981 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1982 {
1983     LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1984
1985     switch(wParam)  /* Hit test */
1986     {
1987     case HTCAPTION:
1988         {
1989             HWND top = GetAncestor( hwnd, GA_ROOT );
1990
1991             if( WINPOS_SetActiveWindow(top, TRUE, TRUE) || (GetActiveWindow() == top) )
1992                 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1993             break;
1994         }
1995
1996     case HTSYSMENU:
1997          if( style & WS_SYSMENU )
1998          {
1999              if( !(style & WS_MINIMIZE) )
2000              {
2001                 HDC hDC = GetWindowDC(hwnd);
2002                 if (TWEAK_WineLook == WIN31_LOOK)
2003                     NC_DrawSysButton( hwnd, hDC, TRUE );
2004                 else
2005                     NC_DrawSysButton95( hwnd, hDC, TRUE );
2006                 ReleaseDC( hwnd, hDC );
2007              }
2008              SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2009          }
2010          break;
2011
2012     case HTMENU:
2013         SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2014         break;
2015
2016     case HTHSCROLL:
2017         SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2018         break;
2019
2020     case HTVSCROLL:
2021         SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2022         break;
2023
2024     case HTMINBUTTON:
2025     case HTMAXBUTTON:
2026         if (TWEAK_WineLook == WIN31_LOOK)
2027             NC_TrackMinMaxBox( hwnd, wParam );
2028         else
2029             NC_TrackMinMaxBox95( hwnd, wParam );            
2030         break;
2031
2032     case HTCLOSE:
2033         if (TWEAK_WineLook >= WIN95_LOOK)
2034             NC_TrackCloseButton95 (hwnd, wParam);
2035         break;
2036         
2037     case HTLEFT:
2038     case HTRIGHT:
2039     case HTTOP:
2040     case HTTOPLEFT:
2041     case HTTOPRIGHT:
2042     case HTBOTTOM:
2043     case HTBOTTOMLEFT:
2044     case HTBOTTOMRIGHT:
2045         /* make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU */
2046         SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
2047         break;
2048
2049     case HTBORDER:
2050         break;
2051     }
2052     return 0;
2053 }
2054
2055
2056 /***********************************************************************
2057  *           NC_HandleNCLButtonDblClk
2058  *
2059  * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2060  */
2061 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
2062 {
2063     /*
2064      * if this is an icon, send a restore since we are handling
2065      * a double click
2066      */
2067     if (IsIconic(hwnd))
2068     {
2069         SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
2070         return 0;
2071     } 
2072
2073     switch(wParam)  /* Hit test */
2074     {
2075     case HTCAPTION:
2076         /* stop processing if WS_MAXIMIZEBOX is missing */
2077         if (GetWindowLongA( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
2078             SendMessageW( hwnd, WM_SYSCOMMAND,
2079                           IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
2080         break;
2081
2082     case HTSYSMENU:
2083         if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE))
2084             SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
2085         break;
2086
2087     case HTHSCROLL:
2088         SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2089         break;
2090
2091     case HTVSCROLL:
2092         SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2093         break;
2094     }
2095     return 0;
2096 }
2097
2098
2099 /***********************************************************************
2100  *           NC_HandleSysCommand
2101  *
2102  * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2103  */
2104 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
2105 {
2106     TRACE("Handling WM_SYSCOMMAND %x %lx\n", wParam, lParam );
2107
2108     switch (wParam & 0xfff0)
2109     {
2110     case SC_SIZE:
2111     case SC_MOVE:
2112         if (USER_Driver.pSysCommandSizeMove)
2113             USER_Driver.pSysCommandSizeMove( hwnd, wParam );
2114         break;
2115
2116     case SC_MINIMIZE:
2117         if (hwnd == GetForegroundWindow())
2118             ShowOwnedPopups(hwnd,FALSE);
2119         ShowWindow( hwnd, SW_MINIMIZE ); 
2120         break;
2121
2122     case SC_MAXIMIZE:
2123         if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2124             ShowOwnedPopups(hwnd,TRUE);
2125         ShowWindow( hwnd, SW_MAXIMIZE );
2126         break;
2127
2128     case SC_RESTORE:
2129         if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2130             ShowOwnedPopups(hwnd,TRUE);
2131         ShowWindow( hwnd, SW_RESTORE );
2132         break;
2133
2134     case SC_CLOSE:
2135         return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2136
2137     case SC_VSCROLL:
2138     case SC_HSCROLL:
2139         {
2140             POINT pt;
2141             pt.x = SLOWORD(lParam);
2142             pt.y = SHIWORD(lParam);
2143             NC_TrackScrollBar( hwnd, wParam, pt );
2144         }
2145         break;
2146
2147     case SC_MOUSEMENU:
2148         {
2149             POINT pt;
2150             pt.x = SLOWORD(lParam);
2151             pt.y = SHIWORD(lParam);
2152             MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
2153         }
2154         break;
2155
2156     case SC_KEYMENU:
2157         MENU_TrackKbdMenuBar( hwnd, wParam, LOWORD(lParam) );
2158         break;
2159
2160     case SC_TASKLIST:
2161         WinExec( "taskman.exe", SW_SHOWNORMAL ); 
2162         break;
2163
2164     case SC_SCREENSAVE:
2165         if (wParam == SC_ABOUTWINE)
2166         {
2167             HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2168             if (hmodule)
2169             {
2170                 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2171                 if (aboutproc) aboutproc( hwnd, "Wine", WINE_RELEASE_INFO, 0 );
2172                 FreeLibrary( hmodule );
2173             }
2174         }
2175         else 
2176           if (wParam == SC_PUTMARK)
2177             TRACE_(shell)("Mark requested by user\n");
2178         break;
2179   
2180     case SC_HOTKEY:
2181     case SC_ARRANGE:
2182     case SC_NEXTWINDOW:
2183     case SC_PREVWINDOW:
2184         FIXME("unimplemented!\n");
2185         break;
2186     }
2187     return 0;
2188 }
2189
2190 /*************************************************************
2191 *  NC_DrawGrayButton
2192 *
2193 * Stub for the grayed button of the caption
2194 *
2195 *************************************************************/
2196
2197 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2198 {
2199     HBITMAP hMaskBmp;
2200     HDC hdcMask = CreateCompatibleDC (0);
2201     HBRUSH hOldBrush;
2202
2203     hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2204     
2205     if(hMaskBmp == 0)
2206         return FALSE;
2207     
2208     SelectObject (hdcMask, hMaskBmp);
2209     
2210     /* Draw the grayed bitmap using the mask */
2211     hOldBrush = SelectObject (hdc, RGB(128, 128, 128));
2212     BitBlt (hdc, x, y, 12, 10,
2213             hdcMask, 0, 0, 0xB8074A);
2214     
2215     /* Clean up */
2216     SelectObject (hdc, hOldBrush);
2217     DeleteObject(hMaskBmp);
2218     DeleteDC (hdcMask);
2219     
2220     return TRUE;
2221 }