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