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