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