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