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