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