Added offsetof (for the MFC).
[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( &msg, 0, 0, WM_KEYFIRST, WM_MOUSELAST,
1965                                     MSGF_SIZE, PM_REMOVE, FALSE, NULL );
1966             switch(msg.message)
1967             {
1968             case WM_MOUSEMOVE:
1969                 hittest = NC_HandleNCHitTest( wndPtr->hwndSelf, msg.pt );
1970                 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
1971                     hittest = 0;
1972                 break;
1973
1974             case WM_LBUTTONUP:
1975                 return 0;
1976
1977             case WM_KEYDOWN:
1978                 switch(msg.wParam)
1979                 {
1980                 case VK_UP:
1981                     hittest = HTTOP;
1982                     pt.x =(rectWindow.left+rectWindow.right)/2;
1983                     pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
1984                     break;
1985                 case VK_DOWN:
1986                     hittest = HTBOTTOM;
1987                     pt.x =(rectWindow.left+rectWindow.right)/2;
1988                     pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
1989                     break;
1990                 case VK_LEFT:
1991                     hittest = HTLEFT;
1992                     pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
1993                     pt.y =(rectWindow.top+rectWindow.bottom)/2;
1994                     break;
1995                 case VK_RIGHT:
1996                     hittest = HTRIGHT;
1997                     pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
1998                     pt.y =(rectWindow.top+rectWindow.bottom)/2;
1999                     break;
2000                 case VK_RETURN:
2001                 case VK_ESCAPE: return 0;
2002                 }
2003             }
2004         }
2005         *capturePoint = pt;
2006     }
2007     SetCursorPos( pt.x, pt.y );
2008     NC_HandleSetCursor( wndPtr->hwndSelf, 
2009                         wndPtr->hwndSelf, MAKELONG( hittest, WM_MOUSEMOVE ));
2010     return hittest;
2011 }
2012
2013
2014 /***********************************************************************
2015  *           NC_DoSizeMove
2016  *
2017  * Perform SC_MOVE and SC_SIZE commands.               `
2018  */
2019 static void NC_DoSizeMove( HWND hwnd, WORD wParam )
2020 {
2021     MSG msg;
2022     RECT sizingRect, mouseRect, origRect;
2023     HDC hdc;
2024     LONG hittest = (LONG)(wParam & 0x0f);
2025     HCURSOR16 hDragCursor = 0, hOldCursor = 0;
2026     POINT minTrack, maxTrack;
2027     POINT capturePoint, pt;
2028     WND *     wndPtr = WIN_FindWndPtr( hwnd );
2029     BOOL    thickframe = HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle );
2030     BOOL    iconic = wndPtr->dwStyle & WS_MINIMIZE;
2031     BOOL    moved = FALSE;
2032     DWORD     dwPoint = GetMessagePos ();
2033     BOOL DragFullWindows = FALSE;
2034     int iWndsLocks;
2035     
2036     SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
2037
2038     pt.x = SLOWORD(dwPoint);
2039     pt.y = SHIWORD(dwPoint);
2040     capturePoint = pt;
2041
2042     if (IsZoomed(hwnd) || !IsWindowVisible(hwnd) ||
2043         (wndPtr->dwExStyle & WS_EX_MANAGED)) goto END;
2044
2045     if ((wParam & 0xfff0) == SC_MOVE)
2046     {
2047         if (!hittest) 
2048              hittest = NC_StartSizeMove( wndPtr, wParam, &capturePoint );
2049         if (!hittest) goto END;
2050     }
2051     else  /* SC_SIZE */
2052     {
2053         if (!thickframe) goto END;
2054         if ( hittest && hittest != HTSYSMENU ) hittest += 2;
2055         else
2056         {
2057             SetCapture(hwnd);
2058             hittest = NC_StartSizeMove( wndPtr, wParam, &capturePoint );
2059             if (!hittest)
2060             {
2061                 ReleaseCapture();
2062                 goto END;
2063             }
2064         }
2065     }
2066
2067       /* Get min/max info */
2068
2069     WINPOS_GetMinMaxInfo( wndPtr, NULL, NULL, &minTrack, &maxTrack );
2070     sizingRect = wndPtr->rectWindow;
2071     origRect = sizingRect;
2072     if (wndPtr->dwStyle & WS_CHILD)
2073         GetClientRect( wndPtr->parent->hwndSelf, &mouseRect );
2074     else 
2075         SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
2076     if (ON_LEFT_BORDER(hittest))
2077     {
2078         mouseRect.left  = max( mouseRect.left, sizingRect.right-maxTrack.x );
2079         mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
2080     }
2081     else if (ON_RIGHT_BORDER(hittest))
2082     {
2083         mouseRect.left  = max( mouseRect.left, sizingRect.left+minTrack.x );
2084         mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
2085     }
2086     if (ON_TOP_BORDER(hittest))
2087     {
2088         mouseRect.top    = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
2089         mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
2090     }
2091     else if (ON_BOTTOM_BORDER(hittest))
2092     {
2093         mouseRect.top    = max( mouseRect.top, sizingRect.top+minTrack.y );
2094         mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
2095     }
2096     if (wndPtr->dwStyle & WS_CHILD)
2097     {
2098         MapWindowPoints( wndPtr->parent->hwndSelf, 0, 
2099                 (LPPOINT)&mouseRect, 2 );
2100     }
2101     SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
2102
2103     if (GetCapture() != hwnd) SetCapture( hwnd );    
2104
2105     if (wndPtr->parent && (wndPtr->parent->hwndSelf != GetDesktopWindow()))
2106     {
2107           /* Retrieve a default cache DC (without using the window style) */
2108         hdc = GetDCEx( wndPtr->parent->hwndSelf, 0, DCX_CACHE );
2109     }
2110     else
2111         hdc = GetDC( 0 );
2112
2113     if( iconic ) /* create a cursor for dragging */
2114     {
2115         HICON16 hIcon = GetClassWord(wndPtr->hwndSelf, GCW_HICON);
2116         if(!hIcon) hIcon = (HICON16) SendMessage16( hwnd, WM_QUERYDRAGICON, 0, 0L);
2117         if( hIcon ) hDragCursor =  CURSORICON_IconToCursor( hIcon, TRUE );
2118         if( !hDragCursor ) iconic = FALSE;
2119     }
2120
2121     wndPtr->pDriver->pPreSizeMove(wndPtr);
2122
2123     /* invert frame if WIN31_LOOK to indicate mouse click on caption */
2124     if( !iconic && TWEAK_WineLook == WIN31_LOOK )
2125         if(!DragFullWindows)
2126         NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2127
2128     while(1)
2129     {
2130         int dx = 0, dy = 0;
2131
2132         MSG_InternalGetMessage( &msg, 0, 0, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE, NULL );
2133
2134           /* Exit on button-up, Return, or Esc */
2135         if ((msg.message == WM_LBUTTONUP) ||
2136             ((msg.message == WM_KEYDOWN) && 
2137              ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
2138
2139         if (msg.message == WM_PAINT)
2140         {
2141             if(!iconic && !DragFullWindows) NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2142             UpdateWindow( msg.hwnd );
2143             if(!iconic && !DragFullWindows) NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2144             continue;
2145         }
2146
2147         if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
2148             continue;  /* We are not interested in other messages */
2149
2150         pt = msg.pt;
2151         
2152         if (msg.message == WM_KEYDOWN) switch(msg.wParam)
2153         {
2154             case VK_UP:    pt.y -= 8; break;
2155             case VK_DOWN:  pt.y += 8; break;
2156             case VK_LEFT:  pt.x -= 8; break;
2157             case VK_RIGHT: pt.x += 8; break;            
2158         }
2159
2160         pt.x = max( pt.x, mouseRect.left );
2161         pt.x = min( pt.x, mouseRect.right );
2162         pt.y = max( pt.y, mouseRect.top );
2163         pt.y = min( pt.y, mouseRect.bottom );
2164
2165         dx = pt.x - capturePoint.x;
2166         dy = pt.y - capturePoint.y;
2167
2168         if (dx || dy)
2169         {
2170             if( !moved )
2171             {
2172                 moved = TRUE;
2173
2174                 if( iconic ) /* ok, no system popup tracking */
2175                 {
2176                     hOldCursor = SetCursor(hDragCursor);
2177                     ShowCursor( TRUE );
2178                     WINPOS_ShowIconTitle( wndPtr, FALSE );
2179                 } else if(TWEAK_WineLook != WIN31_LOOK)
2180                 {
2181                     if(!DragFullWindows)
2182                     NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2183                 }
2184             }
2185
2186             if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
2187             else
2188             {
2189                 RECT newRect = sizingRect;
2190                 WPARAM wpSizingHit = 0;
2191
2192                 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
2193                 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
2194                 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
2195                 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
2196                 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
2197                 if(!iconic && !DragFullWindows) NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2198                 capturePoint = pt;
2199                 
2200                 /* determine the hit location */
2201                 if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
2202                     wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
2203                 SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
2204
2205                 if (!iconic)
2206                 {
2207                     if(!DragFullWindows)
2208                         NC_DrawMovingFrame( hdc, &newRect, thickframe );
2209                     else {
2210                         /* To avoid any deadlocks, all the locks on the windows
2211                            structures must be suspended before the SetWindowPos */
2212                         iWndsLocks = WIN_SuspendWndsLock();
2213                         SetWindowPos( hwnd, 0, newRect.left, newRect.top,
2214                             newRect.right - newRect.left,
2215                             newRect.bottom - newRect.top,
2216                             ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
2217                         WIN_RestoreWndsLock(iWndsLocks);
2218                     }
2219                 }
2220                 sizingRect = newRect;
2221             }
2222         }
2223     }
2224
2225     ReleaseCapture();
2226     if( iconic )
2227     {
2228         if( moved ) /* restore cursors, show icon title later on */
2229         {
2230             ShowCursor( FALSE );
2231             SetCursor( hOldCursor );
2232         }
2233         DestroyCursor( hDragCursor );
2234     }
2235     else if(moved || TWEAK_WineLook == WIN31_LOOK)
2236         if(!DragFullWindows)
2237         NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
2238
2239     if (wndPtr->parent && (wndPtr->parent->hwndSelf != GetDesktopWindow()))
2240         ReleaseDC( wndPtr->parent->hwndSelf, hdc );
2241     else
2242         ReleaseDC( 0, hdc );
2243
2244     wndPtr->pDriver->pPostSizeMove(wndPtr);
2245
2246     if (HOOK_IsHooked( WH_CBT ))
2247     {
2248         RECT16* pr = SEGPTR_NEW(RECT16);
2249         if( pr )
2250         {
2251             CONV_RECT32TO16( &sizingRect, pr );
2252             if( HOOK_CallHooks16( WH_CBT, HCBT_MOVESIZE, hwnd,
2253                                 (LPARAM)SEGPTR_GET(pr)) )
2254                 sizingRect = wndPtr->rectWindow;
2255             else
2256                 CONV_RECT16TO32( pr, &sizingRect );
2257             SEGPTR_FREE(pr);
2258         }
2259     }
2260     SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
2261     SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic16(hwnd), 0L);
2262
2263     /* window moved or resized */
2264     if (moved)
2265     {
2266         /* To avoid any deadlocks, all the locks on the windows
2267            structures must be suspended before the SetWindowPos */
2268         iWndsLocks = WIN_SuspendWndsLock();
2269
2270         /* if the moving/resizing isn't canceled call SetWindowPos
2271          * with the new position or the new size of the window
2272          */
2273         if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
2274         {
2275         /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
2276         if(!DragFullWindows)
2277         SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
2278                         sizingRect.right - sizingRect.left,
2279                         sizingRect.bottom - sizingRect.top,
2280                       ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
2281         }
2282         else { /* restore previous size/position */
2283             if(DragFullWindows)
2284                 SetWindowPos( hwnd, 0, origRect.left, origRect.top,
2285                         origRect.right - origRect.left,
2286                         origRect.bottom - origRect.top,
2287                         ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
2288         }
2289
2290         WIN_RestoreWndsLock(iWndsLocks);
2291     }
2292
2293     if( IsWindow(hwnd) )
2294         if( wndPtr->dwStyle & WS_MINIMIZE )
2295         {
2296             /* Single click brings up the system menu when iconized */
2297
2298             if( !moved ) 
2299             {
2300                  if( wndPtr->dwStyle & WS_SYSMENU ) 
2301                      SendMessageA( hwnd, WM_SYSCOMMAND,
2302                                    SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
2303             }
2304             else WINPOS_ShowIconTitle( wndPtr, TRUE );
2305         }
2306
2307 END:
2308     WIN_ReleaseWndPtr(wndPtr);
2309 }
2310
2311
2312 /***********************************************************************
2313  *           NC_TrackMinMaxBox95
2314  *
2315  * Track a mouse button press on the minimize or maximize box.
2316  *
2317  * The big difference between 3.1 and 95 is the disabled button state.
2318  * In win95 the system button can be disabled, so it can ignore the mouse
2319  * event.
2320  *
2321  */
2322 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
2323 {
2324     MSG msg;
2325     HDC hdc = GetWindowDC( hwnd );
2326     BOOL pressed = TRUE;
2327     UINT state;
2328     DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
2329     HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
2330
2331     void  (*paintButton)(HWND, HDC16, BOOL, BOOL);
2332
2333     if (wParam == HTMINBUTTON)
2334     {
2335         /* If the style is not present, do nothing */
2336         if (!(wndStyle & WS_MINIMIZEBOX))
2337             return;
2338
2339         /* Check if the sysmenu item for minimize is there  */
2340         state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
2341         
2342         paintButton = &NC_DrawMinButton95;
2343     }
2344     else
2345     {
2346         /* If the style is not present, do nothing */
2347         if (!(wndStyle & WS_MAXIMIZEBOX))
2348             return;
2349
2350         /* Check if the sysmenu item for maximize is there  */
2351         state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
2352         
2353         paintButton = &NC_DrawMaxButton95;
2354     }
2355
2356     SetCapture( hwnd );
2357
2358     (*paintButton)( hwnd, hdc, TRUE, FALSE);
2359
2360     while(1)
2361     {
2362         BOOL oldstate = pressed;
2363         MSG_InternalGetMessage( &msg, 0, 0, WM_MOUSEFIRST, WM_MOUSELAST,
2364                                 0, PM_REMOVE, FALSE, NULL );
2365
2366         if(msg.message == WM_LBUTTONUP)
2367             break;
2368
2369         if(msg.message != WM_MOUSEMOVE)
2370             continue;
2371
2372         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
2373         if (pressed != oldstate)
2374            (*paintButton)( hwnd, hdc, pressed, FALSE);
2375     }
2376
2377     if(pressed)
2378         (*paintButton)(hwnd, hdc, FALSE, FALSE);
2379
2380     ReleaseCapture();
2381     ReleaseDC( hwnd, hdc );
2382
2383     /* If the item minimize or maximize of the sysmenu are not there */
2384     /* or if the style is not present, do nothing */
2385     if ((!pressed) || (state == 0xFFFFFFFF))
2386         return;
2387
2388     if (wParam == HTMINBUTTON) 
2389         SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
2390     else
2391         SendMessageA( hwnd, WM_SYSCOMMAND,
2392                       IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
2393 }
2394
2395 /***********************************************************************
2396  *           NC_TrackMinMaxBox
2397  *
2398  * Track a mouse button press on the minimize or maximize box.
2399  */
2400 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
2401 {
2402     MSG msg;
2403     HDC hdc = GetWindowDC( hwnd );
2404     BOOL pressed = TRUE;
2405     void  (*paintButton)(HWND, HDC16, BOOL);
2406
2407     SetCapture( hwnd );
2408
2409     if (wParam == HTMINBUTTON)
2410         paintButton = &NC_DrawMinButton;
2411     else
2412         paintButton = &NC_DrawMaxButton;
2413
2414     (*paintButton)( hwnd, hdc, TRUE);
2415
2416     while(1)
2417     {
2418         BOOL oldstate = pressed;
2419         MSG_InternalGetMessage( &msg, 0, 0, WM_MOUSEFIRST, WM_MOUSELAST,
2420                                 0, PM_REMOVE, FALSE, NULL );
2421
2422         if(msg.message == WM_LBUTTONUP)
2423             break;
2424
2425         if(msg.message != WM_MOUSEMOVE)
2426             continue;
2427
2428         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
2429         if (pressed != oldstate)
2430            (*paintButton)( hwnd, hdc, pressed);
2431     }
2432
2433     if(pressed)
2434         (*paintButton)( hwnd, hdc, FALSE);
2435
2436     ReleaseCapture();
2437     ReleaseDC( hwnd, hdc );
2438
2439     if (!pressed) return;
2440
2441     if (wParam == HTMINBUTTON) 
2442         SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
2443     else
2444         SendMessageA( hwnd, WM_SYSCOMMAND,
2445                       IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
2446 }
2447
2448
2449 /***********************************************************************
2450  * NC_TrackCloseButton95
2451  *
2452  * Track a mouse button press on the Win95 close button.
2453  */
2454 static void
2455 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
2456 {
2457     MSG msg;
2458     HDC hdc;
2459     BOOL pressed = TRUE;
2460     HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
2461     UINT state;
2462
2463     if(hSysMenu == 0)
2464         return;
2465
2466     state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
2467             
2468     /* If the item close of the sysmenu is disabled or not there do nothing */
2469     if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
2470         return;
2471
2472     hdc = GetWindowDC( hwnd );
2473
2474     SetCapture( hwnd );
2475
2476     NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
2477
2478     while(1)
2479     {
2480         BOOL oldstate = pressed;
2481         MSG_InternalGetMessage( &msg, 0, 0, WM_MOUSEFIRST, WM_MOUSELAST,
2482                                 0, PM_REMOVE, FALSE, NULL );
2483
2484         if(msg.message == WM_LBUTTONUP)
2485             break;
2486
2487         if(msg.message != WM_MOUSEMOVE)
2488             continue;
2489
2490         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
2491         if (pressed != oldstate)
2492            NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
2493     }
2494
2495     if(pressed)
2496         NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
2497
2498     ReleaseCapture();
2499     ReleaseDC( hwnd, hdc );
2500     if (!pressed) return;
2501
2502     SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
2503 }
2504
2505
2506 /***********************************************************************
2507  *           NC_TrackScrollBar
2508  *
2509  * Track a mouse button press on the horizontal or vertical scroll-bar.
2510  */
2511 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
2512 {
2513     MSG16 *msg;
2514     INT scrollbar;
2515     WND *wndPtr = WIN_FindWndPtr( hwnd );
2516
2517     if ((wParam & 0xfff0) == SC_HSCROLL)
2518     {
2519         if ((wParam & 0x0f) != HTHSCROLL) goto END;
2520         scrollbar = SB_HORZ;
2521     }
2522     else  /* SC_VSCROLL */
2523     {
2524         if ((wParam & 0x0f) != HTVSCROLL) goto END;
2525         scrollbar = SB_VERT;
2526     }
2527
2528     if (!(msg = SEGPTR_NEW(MSG16))) goto END;
2529     pt.x -= wndPtr->rectWindow.left;
2530     pt.y -= wndPtr->rectWindow.top;
2531     SetCapture( hwnd );
2532     SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
2533
2534     do
2535     {
2536         GetMessage16( SEGPTR_GET(msg), 0, 0, 0 );
2537         switch(msg->message)
2538         {
2539         case WM_LBUTTONUP:
2540         case WM_MOUSEMOVE:
2541         case WM_SYSTIMER:
2542             pt.x = LOWORD(msg->lParam) + wndPtr->rectClient.left - 
2543               wndPtr->rectWindow.left;
2544             pt.y = HIWORD(msg->lParam) + wndPtr->rectClient.top - 
2545               wndPtr->rectWindow.top;
2546             SCROLL_HandleScrollEvent( hwnd, scrollbar, msg->message, pt );
2547             break;
2548         default:
2549             TranslateMessage16( msg );
2550             DispatchMessage16( msg );
2551             break;
2552         }
2553         if (!IsWindow( hwnd ))
2554         {
2555             ReleaseCapture();
2556             break;
2557         }
2558     } while (msg->message != WM_LBUTTONUP);
2559     SEGPTR_FREE(msg);
2560 END:
2561     WIN_ReleaseWndPtr(wndPtr);
2562 }
2563
2564 /***********************************************************************
2565  *           NC_HandleNCLButtonDown
2566  *
2567  * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
2568  */
2569 LONG NC_HandleNCLButtonDown( WND* pWnd, WPARAM16 wParam, LPARAM lParam )
2570 {
2571     HWND hwnd = pWnd->hwndSelf;
2572
2573     switch(wParam)  /* Hit test */
2574     {
2575     case HTCAPTION:
2576          hwnd = WIN_GetTopParent(hwnd);
2577
2578          if( WINPOS_SetActiveWindow(hwnd, TRUE, TRUE) || (GetActiveWindow() == hwnd) )
2579                 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
2580          break;
2581
2582     case HTSYSMENU:
2583          if( pWnd->dwStyle & WS_SYSMENU )
2584          {
2585              if( !(pWnd->dwStyle & WS_MINIMIZE) )
2586              {
2587                 HDC hDC = GetWindowDC(hwnd);
2588                 if (TWEAK_WineLook == WIN31_LOOK)
2589                     NC_DrawSysButton( hwnd, hDC, TRUE );
2590                 else
2591                     NC_DrawSysButton95( hwnd, hDC, TRUE );
2592                 ReleaseDC( hwnd, hDC );
2593              }
2594              SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2595          }
2596          break;
2597
2598     case HTMENU:
2599         SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2600         break;
2601
2602     case HTHSCROLL:
2603         SendMessage16( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2604         break;
2605
2606     case HTVSCROLL:
2607         SendMessage16( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2608         break;
2609
2610     case HTMINBUTTON:
2611     case HTMAXBUTTON:
2612         if (TWEAK_WineLook == WIN31_LOOK)
2613             NC_TrackMinMaxBox( hwnd, wParam );
2614         else
2615             NC_TrackMinMaxBox95( hwnd, wParam );            
2616         break;
2617
2618     case HTCLOSE:
2619         if (TWEAK_WineLook >= WIN95_LOOK)
2620             NC_TrackCloseButton95 (hwnd, wParam);
2621         break;
2622         
2623     case HTLEFT:
2624     case HTRIGHT:
2625     case HTTOP:
2626     case HTTOPLEFT:
2627     case HTTOPRIGHT:
2628     case HTBOTTOM:
2629     case HTBOTTOMLEFT:
2630     case HTBOTTOMRIGHT:
2631         /* make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU */
2632         SendMessage16( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
2633         break;
2634
2635     case HTBORDER:
2636         break;
2637     }
2638     return 0;
2639 }
2640
2641
2642 /***********************************************************************
2643  *           NC_HandleNCLButtonDblClk
2644  *
2645  * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2646  */
2647 LONG NC_HandleNCLButtonDblClk( WND *pWnd, WPARAM16 wParam, LPARAM lParam )
2648 {
2649     /*
2650      * if this is an icon, send a restore since we are handling
2651      * a double click
2652      */
2653     if (pWnd->dwStyle & WS_MINIMIZE)
2654     {
2655         SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_RESTORE, lParam );
2656         return 0;
2657     } 
2658
2659     switch(wParam)  /* Hit test */
2660     {
2661     case HTCAPTION:
2662         /* stop processing if WS_MAXIMIZEBOX is missing */
2663         if (pWnd->dwStyle & WS_MAXIMIZEBOX)
2664             SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND,
2665                       (pWnd->dwStyle & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE,
2666                       lParam );
2667         break;
2668
2669     case HTSYSMENU:
2670         if (!(GetClassWord(pWnd->hwndSelf, GCW_STYLE) & CS_NOCLOSE))
2671             SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, lParam );
2672         break;
2673
2674     case HTHSCROLL:
2675         SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL,
2676                        lParam );
2677         break;
2678
2679     case HTVSCROLL:
2680         SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL,
2681                        lParam );
2682         break;
2683     }
2684     return 0;
2685 }
2686
2687
2688 /***********************************************************************
2689  *           NC_HandleSysCommand
2690  *
2691  * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2692  */
2693 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, POINT pt )
2694 {
2695     WND *wndPtr = WIN_FindWndPtr( hwnd );
2696     UINT16 uCommand = wParam & 0xFFF0;
2697
2698     TRACE("Handling WM_SYSCOMMAND %x %ld,%ld\n", wParam, pt.x, pt.y );
2699
2700     if (wndPtr->parent && (uCommand != SC_KEYMENU))
2701         ScreenToClient( wndPtr->parent->hwndSelf, &pt );
2702
2703     switch (uCommand)
2704     {
2705     case SC_SIZE:
2706     case SC_MOVE:
2707         NC_DoSizeMove( hwnd, wParam );
2708         break;
2709
2710     case SC_MINIMIZE:
2711         if (hwnd == GetForegroundWindow())
2712             ShowOwnedPopups(hwnd,FALSE);
2713         ShowWindow( hwnd, SW_MINIMIZE ); 
2714         break;
2715
2716     case SC_MAXIMIZE:
2717         if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2718             ShowOwnedPopups(hwnd,TRUE);
2719         ShowWindow( hwnd, SW_MAXIMIZE );
2720         break;
2721
2722     case SC_RESTORE:
2723         if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2724             ShowOwnedPopups(hwnd,TRUE);
2725         ShowWindow( hwnd, SW_RESTORE );
2726         break;
2727
2728     case SC_CLOSE:
2729         WIN_ReleaseWndPtr(wndPtr);
2730         return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2731
2732     case SC_VSCROLL:
2733     case SC_HSCROLL:
2734         NC_TrackScrollBar( hwnd, wParam, pt );
2735         break;
2736
2737     case SC_MOUSEMENU:
2738         MENU_TrackMouseMenuBar( wndPtr, wParam & 0x000F, pt );
2739         break;
2740
2741     case SC_KEYMENU:
2742         MENU_TrackKbdMenuBar( wndPtr , wParam , pt.x );
2743         break;
2744         
2745     case SC_TASKLIST:
2746         WinExec( "taskman.exe", SW_SHOWNORMAL ); 
2747         break;
2748
2749     case SC_SCREENSAVE:
2750         if (wParam == SC_ABOUTWINE)
2751         {
2752             HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2753             if (hmodule)
2754             {
2755                 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2756                 if (aboutproc) aboutproc( hwnd, "Wine", WINE_RELEASE_INFO, 0 );
2757                 FreeLibrary( hmodule );
2758             }
2759         }
2760         else 
2761           if (wParam == SC_PUTMARK)
2762             TRACE_(shell)("Mark requested by user\n");
2763         break;
2764   
2765     case SC_HOTKEY:
2766     case SC_ARRANGE:
2767     case SC_NEXTWINDOW:
2768     case SC_PREVWINDOW:
2769         FIXME("unimplemented!\n");
2770         break;
2771     }
2772     WIN_ReleaseWndPtr(wndPtr);
2773     return 0;
2774 }
2775
2776 /*************************************************************
2777 *  NC_DrawGrayButton
2778 *
2779 * Stub for the grayed button of the caption
2780 *
2781 *************************************************************/
2782
2783 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2784 {
2785     HBITMAP hMaskBmp;
2786     HDC hdcMask = CreateCompatibleDC (0);
2787     HBRUSH hOldBrush;
2788
2789     hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2790     
2791     if(hMaskBmp == 0)
2792         return FALSE;
2793     
2794     SelectObject (hdcMask, hMaskBmp);
2795     
2796     /* Draw the grayed bitmap using the mask */
2797     hOldBrush = SelectObject (hdc, RGB(128, 128, 128));
2798     BitBlt (hdc, x, y, 12, 10,
2799             hdcMask, 0, 0, 0xB8074A);
2800     
2801     /* Clean up */
2802     SelectObject (hdc, hOldBrush);
2803     DeleteObject(hMaskBmp);
2804     DeleteDC (hdcMask);
2805     
2806     return TRUE;
2807 }
2808
2809 HICON16 NC_IconForWindow(WND *wndPtr)
2810 {
2811         HICON16 hIcon = (HICON) GetClassLongA(wndPtr->hwndSelf, GCL_HICONSM);
2812         if(!hIcon) hIcon = (HICON) GetClassLongA(wndPtr->hwndSelf, GCL_HICON);
2813
2814         /* If there is no hIcon specified and this is a modal dialog, */ 
2815         /* get the default one.                                       */
2816         if (!hIcon && (wndPtr->dwStyle & DS_MODALFRAME))
2817                 hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
2818
2819         return hIcon;
2820 }