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