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