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