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