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