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