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