Made all 16<->32 HWND conversions use explicit functions instead of
[wine] / windows / nonclient.c
1 /*
2  * Non-client area window functions
3  *
4  * Copyright 1994 Alexandre Julliard
5  *
6  */
7
8 #include "windef.h"
9 #include "wingdi.h"
10 #include "wine/winuser16.h"
11 #include "version.h"
12 #include "win.h"
13 #include "user.h"
14 #include "heap.h"
15 #include "dce.h"
16 #include "controls.h"
17 #include "cursoricon.h"
18 #include "winpos.h"
19 #include "hook.h"
20 #include "nonclient.h"
21 #include "debugtools.h"
22 #include "shellapi.h"
23 #include "bitmap.h"
24
25 DEFAULT_DEBUG_CHANNEL(nonclient);
26 DECLARE_DEBUG_CHANNEL(shell);
27
28 BOOL NC_DrawGrayButton(HDC hdc, int x, int y);
29
30 static HBITMAP hbitmapClose;
31 static HBITMAP hbitmapMinimize;
32 static HBITMAP hbitmapMinimizeD;
33 static HBITMAP hbitmapMaximize;
34 static HBITMAP hbitmapMaximizeD;
35 static HBITMAP hbitmapRestore;
36 static HBITMAP hbitmapRestoreD;
37
38 static const BYTE lpGrayMask[] = { 0xAA, 0xA0,
39                       0x55, 0x50,  
40                       0xAA, 0xA0,
41                       0x55, 0x50,  
42                       0xAA, 0xA0,
43                       0x55, 0x50,  
44                       0xAA, 0xA0,
45                       0x55, 0x50,  
46                       0xAA, 0xA0,
47                       0x55, 0x50};
48
49 #define SC_ABOUTWINE            (SC_SCREENSAVE+1)
50 #define SC_PUTMARK              (SC_SCREENSAVE+2)
51
52   /* Some useful macros */
53 #define HAS_DLGFRAME(style,exStyle) \
54     (((exStyle) & WS_EX_DLGMODALFRAME) || \
55      (((style) & WS_DLGFRAME) && !((style) & WS_THICKFRAME)))
56
57 #define HAS_THICKFRAME(style,exStyle) \
58     (((style) & WS_THICKFRAME) && \
59      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
60
61 #define HAS_THINFRAME(style) \
62     (((style) & WS_BORDER) || !((style) & (WS_CHILD | WS_POPUP)))
63
64 #define HAS_BIGFRAME(style,exStyle) \
65     (((style) & (WS_THICKFRAME | WS_DLGFRAME)) || \
66      ((exStyle) & WS_EX_DLGMODALFRAME))
67
68 #define HAS_STATICOUTERFRAME(style,exStyle) \
69     (((exStyle) & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == \
70      WS_EX_STATICEDGE)
71
72 #define HAS_ANYFRAME(style,exStyle) \
73     (((style) & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) || \
74      ((exStyle) & WS_EX_DLGMODALFRAME) || \
75      !((style) & (WS_CHILD | WS_POPUP)))
76
77 #define HAS_MENU(w)  (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
78
79
80 /***********************************************************************
81  *           NC_AdjustRect
82  *
83  * Compute the size of the window rectangle from the size of the
84  * client rectangle.
85  */
86 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
87 {
88     if (TWEAK_WineLook > WIN31_LOOK)
89         ERR("Called in Win95 mode. Aiee! Please report this.\n" );
90
91     if(style & WS_ICONIC) return;
92
93     if (HAS_THICKFRAME( style, exStyle ))
94         InflateRect( rect, GetSystemMetrics(SM_CXFRAME), GetSystemMetrics(SM_CYFRAME) );
95     else if (HAS_DLGFRAME( style, exStyle ))
96         InflateRect( rect, GetSystemMetrics(SM_CXDLGFRAME), GetSystemMetrics(SM_CYDLGFRAME) );
97     else if (HAS_THINFRAME( style ))
98         InflateRect( rect, GetSystemMetrics(SM_CXBORDER), GetSystemMetrics(SM_CYBORDER));
99
100     if ((style & WS_CAPTION) == WS_CAPTION)
101         rect->top -= GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
102
103     if (menu) rect->top -= GetSystemMetrics(SM_CYMENU) + GetSystemMetrics(SM_CYBORDER);
104
105     if (style & WS_VSCROLL) {
106       rect->right  += GetSystemMetrics(SM_CXVSCROLL) - 1;
107       if(!HAS_ANYFRAME( style, exStyle ))
108          rect->right++;
109     }
110
111     if (style & WS_HSCROLL) {
112       rect->bottom += GetSystemMetrics(SM_CYHSCROLL) - 1;
113       if(!HAS_ANYFRAME( style, exStyle ))
114          rect->bottom++;
115     }
116 }
117
118
119 /******************************************************************************
120  * NC_AdjustRectOuter95
121  *
122  * Computes the size of the "outside" parts of the window based on the
123  * parameters of the client area.
124  *
125  + PARAMS
126  *     LPRECT16  rect
127  *     DWORD  style
128  *     BOOL  menu
129  *     DWORD  exStyle
130  *
131  * NOTES
132  *     "Outer" parts of a window means the whole window frame, caption and
133  *     menu bar. It does not include "inner" parts of the frame like client
134  *     edge, static edge or scroll bars.
135  *
136  * Revision history
137  *     05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
138  *        Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
139  *
140  *     20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
141  *        Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
142  *        NC_AdjustRectInner95 and added handling of Win95 styles.
143  *
144  *     28-Jul-1999 Ove Kåven (ovek@arcticnet.no)
145  *        Streamlined window style checks.
146  *
147  *****************************************************************************/
148
149 static void
150 NC_AdjustRectOuter95 (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
151 {
152     int adjust;
153     if(style & WS_ICONIC) return;
154
155     if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) == 
156         WS_EX_STATICEDGE)
157     {
158         adjust = 1; /* for the outer frame always present */
159     }
160     else
161     {
162         adjust = 0;
163         if ((exStyle & WS_EX_DLGMODALFRAME) ||
164             (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
165     }
166     if (style & WS_THICKFRAME)
167         adjust +=  ( GetSystemMetrics (SM_CXFRAME)
168                    - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
169     if ((style & (WS_BORDER|WS_DLGFRAME)) || 
170         (exStyle & WS_EX_DLGMODALFRAME))
171         adjust++; /* The other border */
172
173     InflateRect (rect, adjust, adjust);
174
175     if ((style & WS_CAPTION) == WS_CAPTION)
176     {
177         if (exStyle & WS_EX_TOOLWINDOW)
178             rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
179         else
180             rect->top -= GetSystemMetrics(SM_CYCAPTION);
181     }
182     if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
183 }
184
185
186 /******************************************************************************
187  * NC_AdjustRectInner95
188  *
189  * Computes the size of the "inside" part of the window based on the
190  * parameters of the client area.
191  *
192  + PARAMS
193  *     LPRECT16 rect
194  *     DWORD    style
195  *     DWORD    exStyle
196  *
197  * NOTES
198  *     "Inner" part of a window means the window frame inside of the flat
199  *     window frame. It includes the client edge, the static edge and the
200  *     scroll bars.
201  *
202  * Revision history
203  *     05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
204  *        Original (NC_AdjustRect95) cut & paste from NC_AdjustRect
205  *
206  *     20-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
207  *        Split NC_AdjustRect95 into NC_AdjustRectOuter95 and
208  *        NC_AdjustRectInner95 and added handling of Win95 styles.
209  *
210  *****************************************************************************/
211
212 static void
213 NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle)
214 {
215     if(style & WS_ICONIC) return;
216
217     if (exStyle & WS_EX_CLIENTEDGE)
218         InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
219
220     if (style & WS_VSCROLL) rect->right  += GetSystemMetrics(SM_CXVSCROLL);
221     if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
222 }
223
224
225
226 static HICON NC_IconForWindow( HWND hwnd )
227 {
228     HICON hIcon = (HICON) GetClassLongA( hwnd, GCL_HICONSM );
229     if (!hIcon) hIcon = (HICON) GetClassLongA( hwnd, GCL_HICON );
230
231     /* If there is no hIcon specified and this is a modal dialog,
232      * get the default one.
233      */
234     if (!hIcon && (GetWindowLongA( hwnd, GWL_STYLE ) & DS_MODALFRAME))
235         hIcon = LoadImageA(0, IDI_WINLOGOA, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR);
236     return hIcon;
237 }
238
239 /***********************************************************************
240  *              DrawCaption (USER32.@) 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 BOOL WINAPI
254 DrawCaption (HWND hwnd, HDC hdc, const RECT *lpRect, UINT uFlags)
255 {
256     return DrawCaptionTempA (hwnd, hdc, lpRect, 0, 0, NULL, uFlags & 0x1F);
257 }
258
259
260 /***********************************************************************
261  *              DrawCaptionTempA (USER32.@)
262  *
263  * PARAMS
264  *
265  * RETURNS
266  *     Success:
267  *     Failure:
268  */
269
270 BOOL WINAPI
271 DrawCaptionTempA (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
272                     HICON hIcon, LPCSTR str, UINT uFlags)
273 {
274     RECT   rc = *rect;
275
276     TRACE("(%08x,%08x,%p,%08x,%08x,\"%s\",%08x)\n",
277           hwnd, hdc, rect, hFont, hIcon, str, uFlags);
278
279     /* drawing background */
280     if (uFlags & DC_INBUTTON) {
281         FillRect (hdc, &rc, GetSysColorBrush (COLOR_3DFACE));
282
283         if (uFlags & DC_ACTIVE) {
284             HBRUSH hbr = SelectObject (hdc, CACHE_GetPattern55AABrush ());
285             PatBlt (hdc, rc.left, rc.top,
286                       rc.right-rc.left, rc.bottom-rc.top, 0xFA0089);
287             SelectObject (hdc, hbr);
288         }
289     }
290     else {
291         FillRect (hdc, &rc, GetSysColorBrush ((uFlags & DC_ACTIVE) ?
292                     COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION));
293     }
294
295
296     /* drawing icon */
297     if ((uFlags & DC_ICON) && !(uFlags & DC_SMALLCAP)) {
298         POINT pt;
299
300         pt.x = rc.left + 2;
301         pt.y = (rc.bottom + rc.top - GetSystemMetrics(SM_CYSMICON)) / 2;
302
303         if (!hIcon) hIcon = NC_IconForWindow(hwnd);
304         DrawIconEx (hdc, pt.x, pt.y, hIcon, GetSystemMetrics(SM_CXSMICON),
305                     GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
306         rc.left += (rc.bottom - rc.top);
307     }
308
309     /* drawing text */
310     if (uFlags & DC_TEXT) {
311         HFONT hOldFont;
312
313         if (uFlags & DC_INBUTTON)
314             SetTextColor (hdc, GetSysColor (COLOR_BTNTEXT));
315         else if (uFlags & DC_ACTIVE)
316             SetTextColor (hdc, GetSysColor (COLOR_CAPTIONTEXT));
317         else
318             SetTextColor (hdc, GetSysColor (COLOR_INACTIVECAPTIONTEXT));
319
320         SetBkMode (hdc, TRANSPARENT);
321
322         if (hFont)
323             hOldFont = SelectObject (hdc, hFont);
324         else {
325             NONCLIENTMETRICSA nclm;
326             HFONT hNewFont;
327             nclm.cbSize = sizeof(NONCLIENTMETRICSA);
328             SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
329             hNewFont = CreateFontIndirectA ((uFlags & DC_SMALLCAP) ?
330                 &nclm.lfSmCaptionFont : &nclm.lfCaptionFont);
331             hOldFont = SelectObject (hdc, hNewFont);
332         }
333
334         if (str)
335             DrawTextA (hdc, str, -1, &rc,
336                          DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
337         else {
338             CHAR szText[128];
339             INT nLen;
340             nLen = GetWindowTextA (hwnd, szText, 128);
341             DrawTextA (hdc, szText, nLen, &rc,
342                          DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT);
343         }
344
345         if (hFont)
346             SelectObject (hdc, hOldFont);
347         else
348             DeleteObject (SelectObject (hdc, hOldFont));
349     }
350
351     /* drawing focus ??? */
352     if (uFlags & 0x2000)
353         FIXME("undocumented flag (0x2000)!\n");
354
355     return 0;
356 }
357
358
359 /***********************************************************************
360  *              DrawCaptionTempW (USER32.@)
361  *
362  * PARAMS
363  *
364  * RETURNS
365  *     Success:
366  *     Failure:
367  */
368
369 BOOL WINAPI
370 DrawCaptionTempW (HWND hwnd, HDC hdc, const RECT *rect, HFONT hFont,
371                     HICON hIcon, LPCWSTR str, UINT uFlags)
372 {
373     LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, str);
374     BOOL res = DrawCaptionTempA (hwnd, hdc, rect, hFont, hIcon, p, uFlags);
375     HeapFree (GetProcessHeap (), 0, p);
376     return res;
377 }
378
379
380 /***********************************************************************
381  *              AdjustWindowRect (USER.102)
382  */
383 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
384 {
385     return AdjustWindowRectEx16( rect, style, menu, 0 );
386 }
387
388
389 /***********************************************************************
390  *              AdjustWindowRect (USER32.@)
391  */
392 BOOL WINAPI AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
393 {
394     return AdjustWindowRectEx( rect, style, menu, 0 );
395 }
396
397
398 /***********************************************************************
399  *              AdjustWindowRectEx (USER.454)
400  */
401 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
402                                     BOOL16 menu, DWORD exStyle )
403 {
404     RECT rect32;
405     BOOL ret;
406
407     CONV_RECT16TO32( rect, &rect32 );
408     ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
409     CONV_RECT32TO16( &rect32, rect );
410     return ret;
411 }
412
413
414 /***********************************************************************
415  *              AdjustWindowRectEx (USER32.@)
416  */
417 BOOL WINAPI AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
418 {
419     /* Correct the window style */
420
421     if (!(style & (WS_POPUP | WS_CHILD))) style |= WS_CAPTION; /* Overlapped window */
422     style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
423     exStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
424                 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
425     if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
426
427     TRACE("(%d,%d)-(%d,%d) %08lx %d %08lx\n",
428           rect->left, rect->top, rect->right, rect->bottom,
429           style, menu, exStyle );
430
431     if (TWEAK_WineLook == WIN31_LOOK)
432         NC_AdjustRect( rect, style, menu, exStyle );
433     else
434     {
435         NC_AdjustRectOuter95( rect, style, menu, exStyle );
436         NC_AdjustRectInner95( rect, style, exStyle );
437     }
438     return TRUE;
439 }
440
441
442 /***********************************************************************
443  *           NC_HandleNCCalcSize
444  *
445  * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
446  */
447 LONG NC_HandleNCCalcSize( HWND hwnd, RECT *winRect )
448 {
449     RECT tmpRect = { 0, 0, 0, 0 };
450     LONG result = 0;
451     LONG cls_style = GetClassLongA(hwnd, GCL_STYLE);
452     LONG style = GetWindowLongA( hwnd, GWL_STYLE );
453     LONG exStyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
454
455     if (cls_style & CS_VREDRAW) result |= WVR_VREDRAW;
456     if (cls_style & CS_HREDRAW) result |= WVR_HREDRAW;
457
458     if (!IsIconic(hwnd))
459     {
460         if (TWEAK_WineLook == WIN31_LOOK)
461             NC_AdjustRect( &tmpRect, style, FALSE, exStyle );
462         else
463             NC_AdjustRectOuter95( &tmpRect, style, FALSE, exStyle );
464
465         winRect->left   -= tmpRect.left;
466         winRect->top    -= tmpRect.top;
467         winRect->right  -= tmpRect.right;
468         winRect->bottom -= tmpRect.bottom;
469
470         if (!(style & WS_CHILD) && GetMenu(hwnd))
471         {
472             TRACE("Calling GetMenuBarHeight with HWND 0x%x, width %d, "
473                   "at (%d, %d).\n", hwnd,
474                   winRect->right - winRect->left,
475                   -tmpRect.left, -tmpRect.top );
476
477             winRect->top +=
478                 MENU_GetMenuBarHeight( hwnd,
479                                        winRect->right - winRect->left,
480                                        -tmpRect.left, -tmpRect.top ) + 1;
481         }
482
483         if (TWEAK_WineLook > WIN31_LOOK) {
484             SetRect(&tmpRect, 0, 0, 0, 0);
485             NC_AdjustRectInner95 (&tmpRect, style, exStyle);
486             winRect->left   -= tmpRect.left;
487             winRect->top    -= tmpRect.top;
488             winRect->right  -= tmpRect.right;
489             winRect->bottom -= tmpRect.bottom;
490         }
491
492         if (winRect->top > winRect->bottom)
493             winRect->bottom = winRect->top;
494
495         if (winRect->left > winRect->right)
496             winRect->right = winRect->left;
497     }
498     return result;
499 }
500
501
502 /***********************************************************************
503  *           NC_GetInsideRect
504  *
505  * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
506  * but without the borders (if any).
507  * The rectangle is in window coordinates (for drawing with GetWindowDC()).
508  */
509 void NC_GetInsideRect( HWND hwnd, RECT *rect )
510 {
511     WND * wndPtr = WIN_FindWndPtr( hwnd );
512
513     rect->top    = rect->left = 0;
514     rect->right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
515     rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
516
517     if (wndPtr->dwStyle & WS_ICONIC) goto END;
518
519     /* Remove frame from rectangle */
520     if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
521     {
522         InflateRect( rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
523     }
524     else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
525     {
526         InflateRect( rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
527         /* FIXME: this isn't in NC_AdjustRect? why not? */
528         if ((TWEAK_WineLook == WIN31_LOOK) && (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
529             InflateRect( rect, -1, 0 );
530     }
531     else if (HAS_THINFRAME( wndPtr->dwStyle ))
532     {
533         InflateRect( rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER) );
534     }
535
536     /* We have additional border information if the window
537      * is a child (but not an MDI child) */
538     if (TWEAK_WineLook != WIN31_LOOK)
539     {
540         if ( (wndPtr->dwStyle & WS_CHILD)  &&
541              ( (wndPtr->dwExStyle & WS_EX_MDICHILD) == 0 ) )
542         {
543             if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
544                 InflateRect (rect, -GetSystemMetrics(SM_CXEDGE), -GetSystemMetrics(SM_CYEDGE));
545             if (wndPtr->dwExStyle & WS_EX_STATICEDGE)
546                 InflateRect (rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
547         }
548     }
549
550 END:
551     WIN_ReleaseWndPtr(wndPtr);
552     return;
553 }
554
555
556 /***********************************************************************
557  * NC_DoNCHitTest
558  *
559  * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
560  */
561
562 static LONG NC_DoNCHitTest (WND *wndPtr, POINT pt )
563 {
564     RECT rect;
565
566     TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
567
568     GetWindowRect(wndPtr->hwndSelf, &rect );
569     if (!PtInRect( &rect, pt )) return HTNOWHERE;
570
571     if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
572
573     /* Check borders */
574     if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
575     {
576         InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
577         if (!PtInRect( &rect, pt ))
578         {
579             /* Check top sizing border */
580             if (pt.y < rect.top)
581             {
582                 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
583                 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
584                 return HTTOP;
585             }
586             /* Check bottom sizing border */
587             if (pt.y >= rect.bottom)
588             {
589                 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
590                 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
591                 return HTBOTTOM;
592             }
593             /* Check left sizing border */
594             if (pt.x < rect.left)
595             {
596                 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
597                 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
598                 return HTLEFT;
599             }
600             /* Check right sizing border */
601             if (pt.x >= rect.right)
602             {
603                 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
604                 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
605                 return HTRIGHT;
606             }
607         }
608     }
609     else  /* No thick frame */
610     {
611         if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
612             InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
613         else if (HAS_THINFRAME( wndPtr->dwStyle ))
614             InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
615         if (!PtInRect( &rect, pt )) return HTBORDER;
616     }
617
618     /* Check caption */
619
620     if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
621     {
622         rect.top += GetSystemMetrics(SM_CYCAPTION) - GetSystemMetrics(SM_CYBORDER);
623         if (!PtInRect( &rect, pt ))
624         {
625             /* Check system menu */
626             if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
627                 rect.left += GetSystemMetrics(SM_CXSIZE);
628             if (pt.x <= rect.left) return HTSYSMENU;
629
630             /* Check maximize box */
631             if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
632                 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
633
634             if (pt.x >= rect.right) return HTMAXBUTTON;
635             /* Check minimize box */
636             if (wndPtr->dwStyle & WS_MINIMIZEBOX)
637                 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
638             if (pt.x >= rect.right) return HTMINBUTTON;
639             return HTCAPTION;
640         }
641     }
642
643       /* Check client area */
644
645     ScreenToClient( wndPtr->hwndSelf, &pt );
646     GetClientRect( wndPtr->hwndSelf, &rect );
647     if (PtInRect( &rect, pt )) return HTCLIENT;
648
649       /* Check vertical scroll bar */
650
651     if (wndPtr->dwStyle & WS_VSCROLL)
652     {
653         rect.right += GetSystemMetrics(SM_CXVSCROLL);
654         if (PtInRect( &rect, pt )) return HTVSCROLL;
655     }
656
657       /* Check horizontal scroll bar */
658
659     if (wndPtr->dwStyle & WS_HSCROLL)
660     {
661         rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
662         if (PtInRect( &rect, pt ))
663         {
664               /* Check size box */
665             if ((wndPtr->dwStyle & WS_VSCROLL) &&
666                 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
667                 return HTSIZE;
668             return HTHSCROLL;
669         }
670     }
671
672       /* Check menu bar */
673
674     if (HAS_MENU(wndPtr))
675     {
676         if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
677             return HTMENU;
678     }
679
680     /* Has to return HTNOWHERE if nothing was found  
681        Could happen when a window has a customized non client area */
682     return HTNOWHERE;  
683 }
684
685
686 /***********************************************************************
687  * NC_DoNCHitTest95
688  *
689  * Handle a WM_NCHITTEST message. Called from NC_HandleNCHitTest().
690  *
691  * FIXME:  Just a modified copy of the Win 3.1 version.
692  */
693
694 static LONG NC_DoNCHitTest95 (WND *wndPtr, POINT pt )
695 {
696     RECT rect;
697
698     TRACE("hwnd=%04x pt=%ld,%ld\n", wndPtr->hwndSelf, pt.x, pt.y );
699
700     GetWindowRect(wndPtr->hwndSelf, &rect );
701     if (!PtInRect( &rect, pt )) return HTNOWHERE;
702
703     if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
704
705     /* Check borders */
706     if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
707     {
708         InflateRect( &rect, -GetSystemMetrics(SM_CXFRAME), -GetSystemMetrics(SM_CYFRAME) );
709         if (!PtInRect( &rect, pt ))
710         {
711             /* Check top sizing border */
712             if (pt.y < rect.top)
713             {
714                 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTTOPLEFT;
715                 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTTOPRIGHT;
716                 return HTTOP;
717             }
718             /* Check bottom sizing border */
719             if (pt.y >= rect.bottom)
720             {
721                 if (pt.x < rect.left+GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMLEFT;
722                 if (pt.x >= rect.right-GetSystemMetrics(SM_CXSIZE)) return HTBOTTOMRIGHT;
723                 return HTBOTTOM;
724             }
725             /* Check left sizing border */
726             if (pt.x < rect.left)
727             {
728                 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPLEFT;
729                 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMLEFT;
730                 return HTLEFT;
731             }
732             /* Check right sizing border */
733             if (pt.x >= rect.right)
734             {
735                 if (pt.y < rect.top+GetSystemMetrics(SM_CYSIZE)) return HTTOPRIGHT;
736                 if (pt.y >= rect.bottom-GetSystemMetrics(SM_CYSIZE)) return HTBOTTOMRIGHT;
737                 return HTRIGHT;
738             }
739         }
740     }
741     else  /* No thick frame */
742     {
743         if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
744             InflateRect(&rect, -GetSystemMetrics(SM_CXDLGFRAME), -GetSystemMetrics(SM_CYDLGFRAME));
745         else if (HAS_THINFRAME( wndPtr->dwStyle ))
746             InflateRect(&rect, -GetSystemMetrics(SM_CXBORDER), -GetSystemMetrics(SM_CYBORDER));
747         if (!PtInRect( &rect, pt )) return HTBORDER;
748     }
749
750     /* Check caption */
751
752     if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
753     {
754         if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW)
755             rect.top += GetSystemMetrics(SM_CYSMCAPTION) - 1;
756         else
757             rect.top += GetSystemMetrics(SM_CYCAPTION) - 1;
758         if (!PtInRect( &rect, pt ))
759         {
760             /* Check system menu */
761             if ((wndPtr->dwStyle & WS_SYSMENU) && !(wndPtr->dwExStyle & WS_EX_TOOLWINDOW))
762             {
763                 if (NC_IconForWindow(wndPtr->hwndSelf))
764                     rect.left += GetSystemMetrics(SM_CYCAPTION) - 1;
765             }
766             if (pt.x < rect.left) return HTSYSMENU;
767
768             /* Check close button */
769             if (wndPtr->dwStyle & WS_SYSMENU)
770                 rect.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
771             if (pt.x > rect.right) return HTCLOSE;
772
773             /* Check maximize box */
774             /* In win95 there is automatically a Maximize button when there is a minimize one*/
775             if ((wndPtr->dwStyle & WS_MAXIMIZEBOX)|| (wndPtr->dwStyle & WS_MINIMIZEBOX))
776                 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
777             if (pt.x > rect.right) return HTMAXBUTTON;
778
779             /* Check minimize box */
780             /* In win95 there is automatically a Maximize button when there is a Maximize one*/
781             if ((wndPtr->dwStyle & WS_MINIMIZEBOX)||(wndPtr->dwStyle & WS_MAXIMIZEBOX))
782                 rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
783
784             if (pt.x > rect.right) return HTMINBUTTON;
785             return HTCAPTION;
786         }
787     }
788
789       /* Check client area */
790
791     ScreenToClient( wndPtr->hwndSelf, &pt );
792     GetClientRect( wndPtr->hwndSelf, &rect );
793     if (PtInRect( &rect, pt )) return HTCLIENT;
794
795       /* Check vertical scroll bar */
796
797     if (wndPtr->dwStyle & WS_VSCROLL)
798     {
799         rect.right += GetSystemMetrics(SM_CXVSCROLL);
800         if (PtInRect( &rect, pt )) return HTVSCROLL;
801     }
802
803       /* Check horizontal scroll bar */
804
805     if (wndPtr->dwStyle & WS_HSCROLL)
806     {
807         rect.bottom += GetSystemMetrics(SM_CYHSCROLL);
808         if (PtInRect( &rect, pt ))
809         {
810               /* Check size box */
811             if ((wndPtr->dwStyle & WS_VSCROLL) &&
812                 (pt.x >= rect.right - GetSystemMetrics(SM_CXVSCROLL)))
813                 return HTSIZE;
814             return HTHSCROLL;
815         }
816     }
817
818       /* Check menu bar */
819
820     if (HAS_MENU(wndPtr))
821     {
822         if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
823             return HTMENU;
824     }
825
826     /* Has to return HTNOWHERE if nothing was found  
827        Could happen when a window has a customized non client area */
828     return HTNOWHERE;
829 }
830
831
832 /***********************************************************************
833  * NC_HandleNCHitTest
834  *
835  * Handle a WM_NCHITTEST message. Called from DefWindowProc().
836  */
837 LONG NC_HandleNCHitTest (HWND hwnd , POINT pt)
838 {
839     LONG retvalue;
840     WND *wndPtr = WIN_FindWndPtr (hwnd);
841
842     if (!wndPtr)
843         return HTERROR;
844
845     if (TWEAK_WineLook == WIN31_LOOK)
846         retvalue = NC_DoNCHitTest (wndPtr, pt);
847     else
848         retvalue = NC_DoNCHitTest95 (wndPtr, pt);
849     WIN_ReleaseWndPtr(wndPtr);
850     return retvalue;
851 }
852
853
854 /***********************************************************************
855  *           NC_DrawSysButton
856  */
857 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
858 {
859     RECT rect;
860     HDC hdcMem;
861     HBITMAP hbitmap;
862
863     NC_GetInsideRect( hwnd, &rect );
864     hdcMem = CreateCompatibleDC( hdc );
865     hbitmap = SelectObject( hdcMem, hbitmapClose );
866     BitBlt(hdc, rect.left, rect.top, GetSystemMetrics(SM_CXSIZE), GetSystemMetrics(SM_CYSIZE),
867            hdcMem, (GetWindowLongA(hwnd,GWL_STYLE) & WS_CHILD) ? GetSystemMetrics(SM_CXSIZE) : 0, 0,
868            down ? NOTSRCCOPY : SRCCOPY );
869     SelectObject( hdcMem, hbitmap );
870     DeleteDC( hdcMem );
871 }
872
873
874 /***********************************************************************
875  *           NC_DrawMaxButton
876  */
877 static void NC_DrawMaxButton( HWND hwnd, HDC16 hdc, BOOL down )
878 {
879     RECT rect;
880     HDC hdcMem;
881
882     NC_GetInsideRect( hwnd, &rect );
883     hdcMem = CreateCompatibleDC( hdc );
884     SelectObject( hdcMem,  (IsZoomed(hwnd)
885                             ? (down ? hbitmapRestoreD : hbitmapRestore)
886                             : (down ? hbitmapMaximizeD : hbitmapMaximize)) );
887     BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
888             GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
889             SRCCOPY );
890     DeleteDC( hdcMem );
891
892 }
893
894
895 /***********************************************************************
896  *           NC_DrawMinButton
897  */
898 static void NC_DrawMinButton( HWND hwnd, HDC16 hdc, BOOL down )
899 {
900     RECT rect;
901     HDC hdcMem;
902
903     NC_GetInsideRect( hwnd, &rect );
904     hdcMem = CreateCompatibleDC( hdc );
905     SelectObject( hdcMem, (down ? hbitmapMinimizeD : hbitmapMinimize) );
906     if (GetWindowLongA(hwnd,GWL_STYLE) & WS_MAXIMIZEBOX)
907         rect.right -= GetSystemMetrics(SM_CXSIZE)+1;
908     BitBlt( hdc, rect.right - GetSystemMetrics(SM_CXSIZE) - 1, rect.top,
909             GetSystemMetrics(SM_CXSIZE) + 1, GetSystemMetrics(SM_CYSIZE), hdcMem, 0, 0,
910             SRCCOPY );
911     DeleteDC( hdcMem );
912 }
913
914
915 /******************************************************************************
916  *
917  *   void  NC_DrawSysButton95(
918  *      HWND  hwnd,
919  *      HDC  hdc,
920  *      BOOL  down )
921  *
922  *   Draws the Win95 system icon.
923  *
924  *   Revision history
925  *        05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
926  *             Original implementation from NC_DrawSysButton source.
927  *        11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
928  *             Fixed most bugs.
929  *
930  *****************************************************************************/
931
932 BOOL
933 NC_DrawSysButton95 (HWND hwnd, HDC hdc, BOOL down)
934 {
935     HICON hIcon = NC_IconForWindow( hwnd );
936
937     if (hIcon)
938     {
939         RECT rect;
940         NC_GetInsideRect( hwnd, &rect );
941         DrawIconEx (hdc, rect.left + 2, rect.top + 2, hIcon,
942                     GetSystemMetrics(SM_CXSMICON),
943                     GetSystemMetrics(SM_CYSMICON), 0, 0, DI_NORMAL);
944     }
945     return (hIcon != 0);
946 }
947
948
949 /******************************************************************************
950  *
951  *   void  NC_DrawCloseButton95(
952  *      HWND  hwnd,
953  *      HDC  hdc,
954  *      BOOL  down,
955  *      BOOL    bGrayed )
956  *
957  *   Draws the Win95 close button.
958  *
959  *   If bGrayed is true, then draw a disabled Close button
960  *
961  *   Revision history
962  *        11-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
963  *             Original implementation from NC_DrawSysButton95 source.
964  *
965  *****************************************************************************/
966
967 static void NC_DrawCloseButton95 (HWND hwnd, HDC hdc, BOOL down, BOOL bGrayed)
968 {
969     RECT rect;
970
971     NC_GetInsideRect( hwnd, &rect );
972
973     /* A tool window has a smaller Close button */
974     if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_TOOLWINDOW)
975     {
976         INT iBmpHeight = 11; /* Windows does not use SM_CXSMSIZE and SM_CYSMSIZE   */
977         INT iBmpWidth = 11;  /* it uses 11x11 for  the close button in tool window */
978         INT iCaptionHeight = GetSystemMetrics(SM_CYSMCAPTION);
979
980         rect.top = rect.top + (iCaptionHeight - 1 - iBmpHeight) / 2;
981         rect.left = rect.right - (iCaptionHeight + 1 + iBmpWidth) / 2;
982         rect.bottom = rect.top + iBmpHeight;
983         rect.right = rect.left + iBmpWidth;
984     }
985     else
986     {
987         rect.left = rect.right - GetSystemMetrics(SM_CXSIZE) - 1;
988         rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
989         rect.top += 2;
990         rect.right -= 2;
991     }
992     DrawFrameControl( hdc, &rect, DFC_CAPTION,
993                       (DFCS_CAPTIONCLOSE |
994                        (down ? DFCS_PUSHED : 0) |
995                        (bGrayed ? DFCS_INACTIVE : 0)) );
996 }
997
998 /******************************************************************************
999  *   NC_DrawMaxButton95
1000  *
1001  *   Draws the maximize button for Win95 style windows.
1002  *   If bGrayed is true, then draw a disabled Maximize button
1003  */
1004 static void NC_DrawMaxButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1005 {
1006     RECT rect;
1007     UINT flags = IsZoomed(hwnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX;
1008
1009     NC_GetInsideRect( hwnd, &rect );
1010     if (GetWindowLongA( hwnd, GWL_STYLE) & WS_SYSMENU)
1011         rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1012     rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1013     rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1014     rect.top += 2;
1015     rect.right -= 2;
1016     if (down) flags |= DFCS_PUSHED;
1017     if (bGrayed) flags |= DFCS_INACTIVE;
1018     DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1019 }
1020
1021 /******************************************************************************
1022  *   NC_DrawMinButton95
1023  *
1024  *   Draws the minimize button for Win95 style windows.
1025  *   If bGrayed is true, then draw a disabled Minimize button
1026  */
1027 static void  NC_DrawMinButton95(HWND hwnd,HDC16 hdc,BOOL down, BOOL bGrayed)
1028 {
1029     RECT rect;
1030     UINT flags = DFCS_CAPTIONMIN;
1031     DWORD style = GetWindowLongA( hwnd, GWL_STYLE );
1032
1033     NC_GetInsideRect( hwnd, &rect );
1034     if (style & WS_SYSMENU)
1035         rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1036     if (style & (WS_MAXIMIZEBOX|WS_MINIMIZEBOX))
1037         rect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
1038     rect.left = rect.right - GetSystemMetrics(SM_CXSIZE);
1039     rect.bottom = rect.top + GetSystemMetrics(SM_CYSIZE) - 1;
1040     rect.top += 2;
1041     rect.right -= 2;
1042     if (down) flags |= DFCS_PUSHED;
1043     if (bGrayed) flags |= DFCS_INACTIVE;
1044     DrawFrameControl( hdc, &rect, DFC_CAPTION, flags );
1045 }
1046
1047 /***********************************************************************
1048  *           NC_DrawFrame
1049  *
1050  * Draw a window frame inside the given rectangle, and update the rectangle.
1051  * The correct pen for the frame must be selected in the DC.
1052  */
1053 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame,
1054                           BOOL active )
1055 {
1056     INT width, height;
1057
1058     if (TWEAK_WineLook != WIN31_LOOK)
1059         ERR("Called in Win95 mode. Aiee! Please report this.\n" );
1060
1061     if (dlgFrame)
1062     {
1063         width = GetSystemMetrics(SM_CXDLGFRAME) - 1;
1064         height = GetSystemMetrics(SM_CYDLGFRAME) - 1;
1065         SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1066                                                 COLOR_INACTIVECAPTION) );
1067     }
1068     else
1069     {
1070         width = GetSystemMetrics(SM_CXFRAME) - 2;
1071         height = GetSystemMetrics(SM_CYFRAME) - 2;
1072         SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1073                                                 COLOR_INACTIVEBORDER) );
1074     }
1075
1076       /* Draw frame */
1077     PatBlt( hdc, rect->left, rect->top,
1078               rect->right - rect->left, height, PATCOPY );
1079     PatBlt( hdc, rect->left, rect->top,
1080               width, rect->bottom - rect->top, PATCOPY );
1081     PatBlt( hdc, rect->left, rect->bottom - 1,
1082               rect->right - rect->left, -height, PATCOPY );
1083     PatBlt( hdc, rect->right - 1, rect->top,
1084               -width, rect->bottom - rect->top, PATCOPY );
1085
1086     if (dlgFrame)
1087     {
1088         InflateRect( rect, -width, -height );
1089     } 
1090     else
1091     {
1092         INT decYOff = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXSIZE) - 1;
1093         INT decXOff = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYSIZE) - 1;
1094
1095       /* Draw inner rectangle */
1096
1097         SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1098         Rectangle( hdc, rect->left + width, rect->top + height,
1099                      rect->right - width , rect->bottom - height );
1100
1101       /* Draw the decorations */
1102
1103         MoveToEx( hdc, rect->left, rect->top + decYOff, NULL );
1104         LineTo( hdc, rect->left + width, rect->top + decYOff );
1105         MoveToEx( hdc, rect->right - 1, rect->top + decYOff, NULL );
1106         LineTo( hdc, rect->right - width - 1, rect->top + decYOff );
1107         MoveToEx( hdc, rect->left, rect->bottom - decYOff, NULL );
1108         LineTo( hdc, rect->left + width, rect->bottom - decYOff );
1109         MoveToEx( hdc, rect->right - 1, rect->bottom - decYOff, NULL );
1110         LineTo( hdc, rect->right - width - 1, rect->bottom - decYOff );
1111
1112         MoveToEx( hdc, rect->left + decXOff, rect->top, NULL );
1113         LineTo( hdc, rect->left + decXOff, rect->top + height);
1114         MoveToEx( hdc, rect->left + decXOff, rect->bottom - 1, NULL );
1115         LineTo( hdc, rect->left + decXOff, rect->bottom - height - 1 );
1116         MoveToEx( hdc, rect->right - decXOff, rect->top, NULL );
1117         LineTo( hdc, rect->right - decXOff, rect->top + height );
1118         MoveToEx( hdc, rect->right - decXOff, rect->bottom - 1, NULL );
1119         LineTo( hdc, rect->right - decXOff, rect->bottom - height - 1 );
1120
1121         InflateRect( rect, -width - 1, -height - 1 );
1122     }
1123 }
1124
1125
1126 /******************************************************************************
1127  *
1128  *   void  NC_DrawFrame95(
1129  *      HDC  hdc,
1130  *      RECT  *rect,
1131  *      BOOL  active,
1132  *      DWORD style,
1133  *      DWORD exStyle )
1134  *
1135  *   Draw a window frame inside the given rectangle, and update the rectangle.
1136  *
1137  *   Bugs
1138  *        Many.  First, just what IS a frame in Win95?  Note that the 3D look
1139  *        on the outer edge is handled by NC_DoNCPaint95.  As is the inner
1140  *        edge.  The inner rectangle just inside the frame is handled by the
1141  *        Caption code.
1142  *
1143  *        In short, for most people, this function should be a nop (unless
1144  *        you LIKE thick borders in Win95/NT4.0 -- I've been working with
1145  *        them lately, but just to get this code right).  Even so, it doesn't
1146  *        appear to be so.  It's being worked on...
1147  * 
1148  *   Revision history
1149  *        06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1150  *             Original implementation (based on NC_DrawFrame)
1151  *        02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1152  *             Some minor fixes.
1153  *        29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1154  *             Fixed a fix or something.
1155  *
1156  *****************************************************************************/
1157
1158 static void  NC_DrawFrame95(
1159     HDC  hdc,
1160     RECT  *rect,
1161     BOOL  active,
1162     DWORD style,
1163     DWORD exStyle)
1164 {
1165     INT width, height;
1166
1167     /* Firstly the "thick" frame */
1168     if (style & WS_THICKFRAME)
1169     {
1170         width = GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
1171         height = GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
1172
1173         SelectObject( hdc, GetSysColorBrush(active ? COLOR_ACTIVEBORDER :
1174                       COLOR_INACTIVEBORDER) );
1175         /* Draw frame */
1176         PatBlt( hdc, rect->left, rect->top,
1177                   rect->right - rect->left, height, PATCOPY );
1178         PatBlt( hdc, rect->left, rect->top,
1179                   width, rect->bottom - rect->top, PATCOPY );
1180         PatBlt( hdc, rect->left, rect->bottom - 1,
1181                   rect->right - rect->left, -height, PATCOPY );
1182         PatBlt( hdc, rect->right - 1, rect->top,
1183                   -width, rect->bottom - rect->top, PATCOPY );
1184
1185         InflateRect( rect, -width, -height );
1186     }
1187
1188     /* Now the other bit of the frame */
1189     if ((style & (WS_BORDER|WS_DLGFRAME)) ||
1190         (exStyle & WS_EX_DLGMODALFRAME))
1191     {
1192         width = GetSystemMetrics(SM_CXDLGFRAME) - GetSystemMetrics(SM_CXEDGE);
1193         height = GetSystemMetrics(SM_CYDLGFRAME) - GetSystemMetrics(SM_CYEDGE);
1194         /* This should give a value of 1 that should also work for a border */
1195
1196         SelectObject( hdc, GetSysColorBrush(
1197                       (exStyle & (WS_EX_DLGMODALFRAME|WS_EX_CLIENTEDGE)) ?
1198                           COLOR_3DFACE :
1199                       (exStyle & WS_EX_STATICEDGE) ?
1200                           COLOR_WINDOWFRAME :
1201                       (style & (WS_DLGFRAME|WS_THICKFRAME)) ?
1202                           COLOR_3DFACE :
1203                       /* else */
1204                           COLOR_WINDOWFRAME));
1205
1206         /* Draw frame */
1207         PatBlt( hdc, rect->left, rect->top,
1208                   rect->right - rect->left, height, PATCOPY );
1209         PatBlt( hdc, rect->left, rect->top,
1210                   width, rect->bottom - rect->top, PATCOPY );
1211         PatBlt( hdc, rect->left, rect->bottom - 1,
1212                   rect->right - rect->left, -height, PATCOPY );
1213         PatBlt( hdc, rect->right - 1, rect->top,
1214                   -width, rect->bottom - rect->top, PATCOPY );
1215
1216         InflateRect( rect, -width, -height );
1217     }
1218 }
1219
1220
1221 /***********************************************************************
1222  *           NC_DrawCaption
1223  *
1224  * Draw the window caption.
1225  * The correct pen for the window frame must be selected in the DC.
1226  */
1227 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
1228                             DWORD style, BOOL active )
1229 {
1230     RECT r = *rect;
1231     char buffer[256];
1232
1233     if (!hbitmapClose)
1234     {
1235         if (!(hbitmapClose = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_CLOSE) ))) return;
1236         hbitmapMinimize  = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_REDUCE) );
1237         hbitmapMinimizeD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_REDUCED) );
1238         hbitmapMaximize  = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_ZOOM) );
1239         hbitmapMaximizeD = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_ZOOMD) );
1240         hbitmapRestore   = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_RESTORE) );
1241         hbitmapRestoreD  = LoadBitmapA( 0, MAKEINTRESOURCEA(OBM_RESTORED) );
1242     }
1243     
1244     if (GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_DLGMODALFRAME)
1245     {
1246         HBRUSH hbrushOld = SelectObject(hdc, GetSysColorBrush(COLOR_WINDOW) );
1247         PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
1248         PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
1249         PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
1250         r.left++;
1251         r.right--;
1252         SelectObject( hdc, hbrushOld );
1253     }
1254     MoveToEx( hdc, r.left, r.bottom, NULL );
1255     LineTo( hdc, r.right, r.bottom );
1256
1257     if (style & WS_SYSMENU)
1258     {
1259         NC_DrawSysButton( hwnd, hdc, FALSE );
1260         r.left += GetSystemMetrics(SM_CXSIZE) + 1;
1261         MoveToEx( hdc, r.left - 1, r.top, NULL );
1262         LineTo( hdc, r.left - 1, r.bottom );
1263     }
1264     if (style & WS_MAXIMIZEBOX)
1265     {
1266         NC_DrawMaxButton( hwnd, hdc, FALSE );
1267         r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1268     }
1269     if (style & WS_MINIMIZEBOX)
1270     {
1271         NC_DrawMinButton( hwnd, hdc, FALSE );
1272         r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1273     }
1274
1275     FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1276                                             COLOR_INACTIVECAPTION) );
1277
1278     if (GetWindowTextA( hwnd, buffer, sizeof(buffer) ))
1279     {
1280         if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1281         else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1282         SetBkMode( hdc, TRANSPARENT );
1283         DrawTextA( hdc, buffer, -1, &r,
1284                      DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
1285     }
1286 }
1287
1288
1289 /******************************************************************************
1290  *
1291  *   NC_DrawCaption95(
1292  *      HDC  hdc,
1293  *      RECT *rect,
1294  *      HWND hwnd,
1295  *      DWORD  style,
1296  *      BOOL active )
1297  *
1298  *   Draw the window caption for Win95 style windows.
1299  *   The correct pen for the window frame must be selected in the DC.
1300  *
1301  *   Bugs
1302  *        Hey, a function that finally works!  Well, almost.
1303  *        It's being worked on.
1304  *
1305  *   Revision history
1306  *        05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1307  *             Original implementation.
1308  *        02-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1309  *             Some minor fixes.
1310  *
1311  *****************************************************************************/
1312
1313 static void  NC_DrawCaption95(
1314     HDC  hdc,
1315     RECT *rect,
1316     HWND hwnd,
1317     DWORD  style,
1318     DWORD  exStyle,
1319     BOOL active )
1320 {
1321     RECT  r = *rect;
1322     char    buffer[256];
1323     HPEN  hPrevPen;
1324     HMENU hSysMenu;
1325
1326     hPrevPen = SelectObject( hdc, GetSysColorPen(
1327                      ((exStyle & (WS_EX_STATICEDGE|WS_EX_CLIENTEDGE|
1328                                  WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
1329                       COLOR_WINDOWFRAME : COLOR_3DFACE) );
1330     MoveToEx( hdc, r.left, r.bottom - 1, NULL );
1331     LineTo( hdc, r.right, r.bottom - 1 );
1332     SelectObject( hdc, hPrevPen );
1333     r.bottom--;
1334
1335     FillRect( hdc, &r, GetSysColorBrush(active ? COLOR_ACTIVECAPTION :
1336                                             COLOR_INACTIVECAPTION) );
1337
1338     if ((style & WS_SYSMENU) && !(exStyle & WS_EX_TOOLWINDOW)) {
1339         if (NC_DrawSysButton95 (hwnd, hdc, FALSE))
1340             r.left += GetSystemMetrics(SM_CYCAPTION) - 1;
1341     }
1342
1343     if (style & WS_SYSMENU) 
1344     {
1345         UINT state;
1346
1347         /* Go get the sysmenu */
1348         hSysMenu = GetSystemMenu(hwnd, FALSE);
1349         state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1350
1351         /* Draw a grayed close button if disabled and a normal one if SC_CLOSE is not there */
1352         NC_DrawCloseButton95 (hwnd, hdc, FALSE, 
1353                               ((((state & MF_DISABLED) || (state & MF_GRAYED))) && (state != 0xFFFFFFFF)));
1354         r.right -= GetSystemMetrics(SM_CYCAPTION) - 1;
1355
1356         if ((style & WS_MAXIMIZEBOX) || (style & WS_MINIMIZEBOX))
1357         {
1358             /* In win95 the two buttons are always there */
1359             /* But if the menu item is not in the menu they're disabled*/
1360
1361             NC_DrawMaxButton95( hwnd, hdc, FALSE, (!(style & WS_MAXIMIZEBOX)));
1362             r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1363             
1364             NC_DrawMinButton95( hwnd, hdc, FALSE,  (!(style & WS_MINIMIZEBOX)));
1365             r.right -= GetSystemMetrics(SM_CXSIZE) + 1;
1366         }
1367     }
1368
1369     if (GetWindowTextA( hwnd, buffer, sizeof(buffer) )) {
1370         NONCLIENTMETRICSA nclm;
1371         HFONT hFont, hOldFont;
1372         nclm.cbSize = sizeof(NONCLIENTMETRICSA);
1373         SystemParametersInfoA (SPI_GETNONCLIENTMETRICS, 0, &nclm, 0);
1374         if (exStyle & WS_EX_TOOLWINDOW)
1375             hFont = CreateFontIndirectA (&nclm.lfSmCaptionFont);
1376         else
1377             hFont = CreateFontIndirectA (&nclm.lfCaptionFont);
1378         hOldFont = SelectObject (hdc, hFont);
1379         if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
1380         else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
1381         SetBkMode( hdc, TRANSPARENT );
1382         r.left += 2;
1383         DrawTextA( hdc, buffer, -1, &r,
1384                      DT_SINGLELINE | DT_VCENTER | DT_NOPREFIX | DT_LEFT );
1385         DeleteObject (SelectObject (hdc, hOldFont));
1386     }
1387 }
1388
1389
1390
1391 /***********************************************************************
1392  *           NC_DoNCPaint
1393  *
1394  * Paint the non-client area. clip is currently unused.
1395  */
1396 static void NC_DoNCPaint( WND* wndPtr, HRGN clip, BOOL suppress_menupaint )
1397 {
1398     HDC hdc;
1399     RECT rect;
1400     BOOL active;
1401     HWND hwnd = wndPtr->hwndSelf;
1402
1403     if ( wndPtr->dwStyle & WS_MINIMIZE ||
1404         !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
1405
1406     active  = wndPtr->flags & WIN_NCACTIVATED;
1407
1408     TRACE("%04x %d\n", hwnd, active );
1409
1410     if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1411                               ((clip > 1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN): 0) ))) return;
1412
1413     if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1414                         wndPtr->rectClient.top-wndPtr->rectWindow.top,
1415                         wndPtr->rectClient.right-wndPtr->rectWindow.left,
1416                         wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1417         == NULLREGION)
1418     {
1419         ReleaseDC( hwnd, hdc );
1420         return;
1421     }
1422
1423     rect.top = rect.left = 0;
1424     rect.right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1425     rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1426
1427     SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1428
1429     if (HAS_ANYFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1430     {
1431         SelectObject( hdc, GetStockObject(NULL_BRUSH) );
1432         Rectangle( hdc, 0, 0, rect.right, rect.bottom );
1433         InflateRect( &rect, -1, -1 );
1434     }
1435
1436     if (HAS_THICKFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1437         NC_DrawFrame(hdc, &rect, FALSE, active );
1438     else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1439         NC_DrawFrame( hdc, &rect, TRUE, active );
1440
1441     if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1442     {
1443         RECT r = rect;
1444         r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
1445         rect.top += GetSystemMetrics(SM_CYSIZE) + GetSystemMetrics(SM_CYBORDER);
1446         NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
1447     }
1448
1449     if (HAS_MENU(wndPtr))
1450     {
1451         RECT r = rect;
1452         r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);  /* default height */
1453         rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1454     }
1455
1456       /* Draw the scroll-bars */
1457
1458     if (wndPtr->dwStyle & WS_VSCROLL)
1459         SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1460     if (wndPtr->dwStyle & WS_HSCROLL)
1461         SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1462
1463       /* Draw the "size-box" */
1464
1465     if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1466     {
1467         RECT r = rect;
1468         r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1469         r.top  = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1470         if(wndPtr->dwStyle & WS_BORDER) {
1471           r.left++;
1472           r.top++;
1473         }
1474         FillRect( hdc, &r, GetSysColorBrush(COLOR_SCROLLBAR) );
1475     }    
1476
1477     ReleaseDC( hwnd, hdc );
1478 }
1479
1480
1481 /******************************************************************************
1482  *
1483  *   void  NC_DoNCPaint95(
1484  *      WND  *wndPtr,
1485  *      HRGN  clip,
1486  *      BOOL  suppress_menupaint )
1487  *
1488  *   Paint the non-client area for Win95 windows.  The clip region is
1489  *   currently ignored.
1490  *
1491  *   Bugs
1492  *        grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1493  *           misc/tweak.c controls/menu.c  # :-)
1494  *
1495  *   Revision history
1496  *        03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1497  *             Original implementation
1498  *        10-Jun-1998 Eric Kohl (ekohl@abo.rhein-zeitung.de)
1499  *             Fixed some bugs.
1500  *        29-Jun-1999 Ove Kåven (ovek@arcticnet.no)
1501  *             Streamlined window style checks.
1502  *
1503  *****************************************************************************/
1504
1505 static void  NC_DoNCPaint95(
1506     WND  *wndPtr,
1507     HRGN  clip,
1508     BOOL  suppress_menupaint )
1509 {
1510     HDC hdc;
1511     RECT rfuzz, rect, rectClip;
1512     BOOL active;
1513     HWND hwnd = wndPtr->hwndSelf;
1514
1515     if ( wndPtr->dwStyle & WS_MINIMIZE ||
1516         !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
1517
1518     active  = wndPtr->flags & WIN_NCACTIVATED;
1519
1520     TRACE("%04x %d\n", hwnd, active );
1521
1522     /* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
1523        the call to GetDCEx implying that it is allowed not to use it either.
1524        However, the suggested GetDCEx(    , DCX_WINDOW | DCX_INTERSECTRGN)
1525        will cause clipRgn to be deleted after ReleaseDC().
1526        Now, how is the "system" supposed to tell what happened?
1527      */
1528
1529     if (!(hdc = GetDCEx( hwnd, (clip > 1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
1530                               ((clip > 1) ?(DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0) ))) return;
1531
1532
1533     if (ExcludeVisRect16( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1534                         wndPtr->rectClient.top-wndPtr->rectWindow.top,
1535                         wndPtr->rectClient.right-wndPtr->rectWindow.left,
1536                         wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1537         == NULLREGION)
1538     {
1539         ReleaseDC( hwnd, hdc );
1540         return;
1541     }
1542
1543     rect.top = rect.left = 0;
1544     rect.right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1545     rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1546
1547     if( clip > 1 )
1548         GetRgnBox( clip, &rectClip );
1549     else
1550     {
1551         clip = 0;
1552         rectClip = rect;
1553     }
1554
1555     SelectObject( hdc, GetSysColorPen(COLOR_WINDOWFRAME) );
1556
1557     if (HAS_STATICOUTERFRAME(wndPtr->dwStyle, wndPtr->dwExStyle)) {
1558         DrawEdge (hdc, &rect, BDR_SUNKENOUTER, BF_RECT | BF_ADJUST);
1559     }
1560     else if (HAS_BIGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle)) {
1561         DrawEdge (hdc, &rect, EDGE_RAISED, BF_RECT | BF_ADJUST);
1562     }
1563
1564     NC_DrawFrame95(hdc, &rect, active, wndPtr->dwStyle, wndPtr->dwExStyle );
1565
1566     if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1567     {
1568         RECT  r = rect;
1569         if (wndPtr->dwExStyle & WS_EX_TOOLWINDOW) {
1570             r.bottom = rect.top + GetSystemMetrics(SM_CYSMCAPTION);
1571             rect.top += GetSystemMetrics(SM_CYSMCAPTION);
1572         }
1573         else {
1574             r.bottom = rect.top + GetSystemMetrics(SM_CYCAPTION);
1575             rect.top += GetSystemMetrics(SM_CYCAPTION);
1576         }
1577         if( !clip || IntersectRect( &rfuzz, &r, &rectClip ) )
1578             NC_DrawCaption95 (hdc, &r, hwnd, wndPtr->dwStyle,
1579                               wndPtr->dwExStyle, active);
1580     }
1581
1582     if (HAS_MENU(wndPtr))
1583     {
1584         RECT r = rect;
1585         r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
1586         
1587         TRACE("Calling DrawMenuBar with rect (%d, %d)-(%d, %d)\n",
1588               r.left, r.top, r.right, r.bottom);
1589
1590         rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint ) + 1;
1591     }
1592
1593     TRACE("After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1594           rect.left, rect.top, rect.right, rect.bottom );
1595
1596     if (wndPtr->dwExStyle & WS_EX_CLIENTEDGE)
1597         DrawEdge (hdc, &rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
1598
1599     /* Draw the scroll-bars */
1600
1601     if (wndPtr->dwStyle & WS_VSCROLL)
1602         SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE, TRUE );
1603     if (wndPtr->dwStyle & WS_HSCROLL)
1604         SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE, TRUE );
1605
1606     /* Draw the "size-box" */
1607     if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1608     {
1609         RECT r = rect;
1610         r.left = r.right - GetSystemMetrics(SM_CXVSCROLL) + 1;
1611         r.top  = r.bottom - GetSystemMetrics(SM_CYHSCROLL) + 1;
1612         FillRect( hdc, &r,  GetSysColorBrush(COLOR_SCROLLBAR) );
1613     }    
1614
1615     ReleaseDC( hwnd, hdc );
1616 }
1617
1618
1619
1620
1621 /***********************************************************************
1622  *           NC_HandleNCPaint
1623  *
1624  * Handle a WM_NCPAINT message. Called from DefWindowProc().
1625  */
1626 LONG NC_HandleNCPaint( HWND hwnd , HRGN clip)
1627 {
1628     WND* wndPtr = WIN_FindWndPtr( hwnd );
1629
1630     if( wndPtr && wndPtr->dwStyle & WS_VISIBLE )
1631     {
1632         if( wndPtr->dwStyle & WS_MINIMIZE )
1633             WINPOS_RedrawIconTitle( hwnd );
1634         else if (TWEAK_WineLook == WIN31_LOOK)
1635             NC_DoNCPaint( wndPtr, clip, FALSE );
1636         else
1637             NC_DoNCPaint95( wndPtr, clip, FALSE );
1638     }
1639     WIN_ReleaseWndPtr(wndPtr);
1640     return 0;
1641 }
1642
1643
1644 /***********************************************************************
1645  *           NC_HandleNCActivate
1646  *
1647  * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1648  */
1649 LONG NC_HandleNCActivate( HWND hwnd, WPARAM wParam )
1650 {
1651     WND* wndPtr = WIN_FindWndPtr( hwnd );
1652
1653     /* Lotus Notes draws menu descriptions in the caption of its main
1654      * window. When it wants to restore original "system" view, it just
1655      * sends WM_NCACTIVATE message to itself. Any optimizations here in
1656      * attempt to minimize redrawings lead to a not restored caption.
1657      */
1658     if (wndPtr)
1659     {
1660         if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1661         else wndPtr->flags &= ~WIN_NCACTIVATED;
1662
1663         if (IsIconic(hwnd)) WINPOS_RedrawIconTitle( hwnd );
1664         else if (TWEAK_WineLook == WIN31_LOOK)
1665             NC_DoNCPaint( wndPtr, (HRGN)1, FALSE );
1666         else
1667             NC_DoNCPaint95( wndPtr, (HRGN)1, FALSE );
1668         WIN_ReleaseWndPtr(wndPtr);
1669     }
1670     return TRUE;
1671 }
1672
1673
1674 /***********************************************************************
1675  *           NC_HandleSetCursor
1676  *
1677  * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1678  */
1679 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
1680 {
1681     if (hwnd != WIN_GetFullHandle( (HWND)wParam ))
1682         return 0;  /* Don't set the cursor for child windows */
1683
1684     switch(LOWORD(lParam))
1685     {
1686     case HTERROR:
1687         {
1688             WORD msg = HIWORD( lParam );
1689             if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1690                 (msg == WM_RBUTTONDOWN))
1691                 MessageBeep(0);
1692         }
1693         break;
1694
1695     case HTCLIENT:
1696         {
1697             HCURSOR hCursor = GetClassLongA(hwnd, GCL_HCURSOR);
1698             if(hCursor) {
1699                 SetCursor(hCursor);
1700                 return TRUE;
1701             }
1702             return FALSE;
1703         }
1704
1705     case HTLEFT:
1706     case HTRIGHT:
1707         return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZEWEA ) );
1708
1709     case HTTOP:
1710     case HTBOTTOM:
1711         return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENSA ) );
1712
1713     case HTTOPLEFT:
1714     case HTBOTTOMRIGHT: 
1715         return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENWSEA ) );
1716
1717     case HTTOPRIGHT:
1718     case HTBOTTOMLEFT:
1719         return (LONG)SetCursor( LoadCursorA( 0, IDC_SIZENESWA ) );
1720     }
1721
1722     /* Default cursor: arrow */
1723     return (LONG)SetCursor( LoadCursorA( 0, IDC_ARROWA ) );
1724 }
1725
1726 /***********************************************************************
1727  *           NC_GetSysPopupPos
1728  */
1729 void NC_GetSysPopupPos( HWND hwnd, RECT* rect )
1730 {
1731     if (IsIconic(hwnd)) GetWindowRect( hwnd, rect );
1732     else
1733     {
1734         WND *wndPtr = WIN_FindWndPtr( hwnd );
1735         if (!wndPtr) return;
1736
1737         NC_GetInsideRect( hwnd, rect );
1738         OffsetRect( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1739         if (wndPtr->dwStyle & WS_CHILD)
1740             ClientToScreen( GetParent(hwnd), (POINT *)rect );
1741         if (TWEAK_WineLook == WIN31_LOOK) {
1742             rect->right = rect->left + GetSystemMetrics(SM_CXSIZE);
1743             rect->bottom = rect->top + GetSystemMetrics(SM_CYSIZE);
1744         }
1745         else {
1746             rect->right = rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
1747             rect->bottom = rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
1748         }
1749         WIN_ReleaseWndPtr( wndPtr );
1750     }
1751 }
1752
1753 /***********************************************************************
1754  *           NC_TrackMinMaxBox95
1755  *
1756  * Track a mouse button press on the minimize or maximize box.
1757  *
1758  * The big difference between 3.1 and 95 is the disabled button state.
1759  * In win95 the system button can be disabled, so it can ignore the mouse
1760  * event.
1761  *
1762  */
1763 static void NC_TrackMinMaxBox95( HWND hwnd, WORD wParam )
1764 {
1765     MSG msg;
1766     HDC hdc = GetWindowDC( hwnd );
1767     BOOL pressed = TRUE;
1768     UINT state;
1769     DWORD wndStyle = GetWindowLongA( hwnd, GWL_STYLE);
1770     HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1771
1772     void  (*paintButton)(HWND, HDC16, BOOL, BOOL);
1773
1774     if (wParam == HTMINBUTTON)
1775     {
1776         /* If the style is not present, do nothing */
1777         if (!(wndStyle & WS_MINIMIZEBOX))
1778             return;
1779
1780         /* Check if the sysmenu item for minimize is there  */
1781         state = GetMenuState(hSysMenu, SC_MINIMIZE, MF_BYCOMMAND);
1782         
1783         paintButton = &NC_DrawMinButton95;
1784     }
1785     else
1786     {
1787         /* If the style is not present, do nothing */
1788         if (!(wndStyle & WS_MAXIMIZEBOX))
1789             return;
1790
1791         /* Check if the sysmenu item for maximize is there  */
1792         state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
1793         
1794         paintButton = &NC_DrawMaxButton95;
1795     }
1796
1797     SetCapture( hwnd );
1798
1799     (*paintButton)( hwnd, hdc, TRUE, FALSE);
1800
1801     while(1)
1802     {
1803         BOOL oldstate = pressed;
1804
1805         if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1806         if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1807
1808         if(msg.message == WM_LBUTTONUP)
1809             break;
1810
1811         if(msg.message != WM_MOUSEMOVE)
1812             continue;
1813
1814         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1815         if (pressed != oldstate)
1816            (*paintButton)( hwnd, hdc, pressed, FALSE);
1817     }
1818
1819     if(pressed)
1820         (*paintButton)(hwnd, hdc, FALSE, FALSE);
1821
1822     ReleaseCapture();
1823     ReleaseDC( hwnd, hdc );
1824
1825     /* If the item minimize or maximize of the sysmenu are not there */
1826     /* or if the style is not present, do nothing */
1827     if ((!pressed) || (state == 0xFFFFFFFF))
1828         return;
1829
1830     if (wParam == HTMINBUTTON) 
1831         SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1832     else
1833         SendMessageA( hwnd, WM_SYSCOMMAND,
1834                       IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1835 }
1836
1837 /***********************************************************************
1838  *           NC_TrackMinMaxBox
1839  *
1840  * Track a mouse button press on the minimize or maximize box.
1841  */
1842 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1843 {
1844     MSG msg;
1845     HDC hdc = GetWindowDC( hwnd );
1846     BOOL pressed = TRUE;
1847     void  (*paintButton)(HWND, HDC16, BOOL);
1848
1849     SetCapture( hwnd );
1850
1851     if (wParam == HTMINBUTTON)
1852         paintButton = &NC_DrawMinButton;
1853     else
1854         paintButton = &NC_DrawMaxButton;
1855
1856     (*paintButton)( hwnd, hdc, TRUE);
1857
1858     while(1)
1859     {
1860         BOOL oldstate = pressed;
1861
1862         if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1863         if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1864
1865         if(msg.message == WM_LBUTTONUP)
1866             break;
1867
1868         if(msg.message != WM_MOUSEMOVE)
1869             continue;
1870
1871         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1872         if (pressed != oldstate)
1873            (*paintButton)( hwnd, hdc, pressed);
1874     }
1875
1876     if(pressed)
1877         (*paintButton)( hwnd, hdc, FALSE);
1878
1879     ReleaseCapture();
1880     ReleaseDC( hwnd, hdc );
1881
1882     if (!pressed) return;
1883
1884     if (wParam == HTMINBUTTON) 
1885         SendMessageA( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1886     else
1887         SendMessageA( hwnd, WM_SYSCOMMAND,
1888                       IsZoomed(hwnd) ? SC_RESTORE:SC_MAXIMIZE, MAKELONG(msg.pt.x,msg.pt.y) );
1889 }
1890
1891
1892 /***********************************************************************
1893  * NC_TrackCloseButton95
1894  *
1895  * Track a mouse button press on the Win95 close button.
1896  */
1897 static void
1898 NC_TrackCloseButton95 (HWND hwnd, WORD wParam)
1899 {
1900     MSG msg;
1901     HDC hdc;
1902     BOOL pressed = TRUE;
1903     HMENU hSysMenu = GetSystemMenu(hwnd, FALSE);
1904     UINT state;
1905
1906     if(hSysMenu == 0)
1907         return;
1908
1909     state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
1910             
1911     /* If the item close of the sysmenu is disabled or not there do nothing */
1912     if((state & MF_DISABLED) || (state & MF_GRAYED) || (state == 0xFFFFFFFF))
1913         return;
1914
1915     hdc = GetWindowDC( hwnd );
1916
1917     SetCapture( hwnd );
1918
1919     NC_DrawCloseButton95 (hwnd, hdc, TRUE, FALSE);
1920
1921     while(1)
1922     {
1923         BOOL oldstate = pressed;
1924
1925         if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
1926         if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
1927
1928         if(msg.message == WM_LBUTTONUP)
1929             break;
1930
1931         if(msg.message != WM_MOUSEMOVE)
1932             continue;
1933
1934         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1935         if (pressed != oldstate)
1936            NC_DrawCloseButton95 (hwnd, hdc, pressed, FALSE);
1937     }
1938
1939     if(pressed)
1940         NC_DrawCloseButton95 (hwnd, hdc, FALSE, FALSE);
1941
1942     ReleaseCapture();
1943     ReleaseDC( hwnd, hdc );
1944     if (!pressed) return;
1945
1946     SendMessageA( hwnd, WM_SYSCOMMAND, SC_CLOSE, MAKELONG(msg.pt.x,msg.pt.y) );
1947 }
1948
1949
1950 /***********************************************************************
1951  *           NC_TrackScrollBar
1952  *
1953  * Track a mouse button press on the horizontal or vertical scroll-bar.
1954  */
1955 static void NC_TrackScrollBar( HWND hwnd, WPARAM wParam, POINT pt )
1956 {
1957     MSG msg;
1958     INT scrollbar;
1959     WND *wndPtr = WIN_FindWndPtr( hwnd );
1960
1961     if ((wParam & 0xfff0) == SC_HSCROLL)
1962     {
1963         if ((wParam & 0x0f) != HTHSCROLL) goto END;
1964         scrollbar = SB_HORZ;
1965     }
1966     else  /* SC_VSCROLL */
1967     {
1968         if ((wParam & 0x0f) != HTVSCROLL) goto END;
1969         scrollbar = SB_VERT;
1970     }
1971
1972     pt.x -= wndPtr->rectWindow.left;
1973     pt.y -= wndPtr->rectWindow.top;
1974     SetCapture( hwnd );
1975     SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
1976
1977     do
1978     {
1979         if (!GetMessageW( &msg, 0, 0, 0 )) break;
1980         if (CallMsgFilterW( &msg, MSGF_SCROLLBAR )) continue;
1981         switch(msg.message)
1982         {
1983         case WM_LBUTTONUP:
1984         case WM_MOUSEMOVE:
1985         case WM_SYSTIMER:
1986             pt.x = LOWORD(msg.lParam) + wndPtr->rectClient.left - wndPtr->rectWindow.left;
1987             pt.y = HIWORD(msg.lParam) + wndPtr->rectClient.top - wndPtr->rectWindow.top;
1988             SCROLL_HandleScrollEvent( hwnd, scrollbar, msg.message, pt );
1989             break;
1990         default:
1991             TranslateMessage( &msg );
1992             DispatchMessageW( &msg );
1993             break;
1994         }
1995         if (!IsWindow( hwnd ))
1996         {
1997             ReleaseCapture();
1998             break;
1999         }
2000     } while (msg.message != WM_LBUTTONUP);
2001 END:
2002     WIN_ReleaseWndPtr(wndPtr);
2003 }
2004
2005 /***********************************************************************
2006  *           NC_HandleNCLButtonDown
2007  *
2008  * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
2009  */
2010 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
2011 {
2012     LONG style = GetWindowLongA( hwnd, GWL_STYLE );
2013
2014     switch(wParam)  /* Hit test */
2015     {
2016     case HTCAPTION:
2017         {
2018             HWND top = GetAncestor( hwnd, GA_ROOT );
2019
2020             if( WINPOS_SetActiveWindow(top, TRUE, TRUE) || (GetActiveWindow() == top) )
2021                 SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
2022             break;
2023         }
2024
2025     case HTSYSMENU:
2026          if( style & WS_SYSMENU )
2027          {
2028              if( !(style & WS_MINIMIZE) )
2029              {
2030                 HDC hDC = GetWindowDC(hwnd);
2031                 if (TWEAK_WineLook == WIN31_LOOK)
2032                     NC_DrawSysButton( hwnd, hDC, TRUE );
2033                 else
2034                     NC_DrawSysButton95( hwnd, hDC, TRUE );
2035                 ReleaseDC( hwnd, hDC );
2036              }
2037              SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
2038          }
2039          break;
2040
2041     case HTMENU:
2042         SendMessageW( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
2043         break;
2044
2045     case HTHSCROLL:
2046         SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2047         break;
2048
2049     case HTVSCROLL:
2050         SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2051         break;
2052
2053     case HTMINBUTTON:
2054     case HTMAXBUTTON:
2055         if (TWEAK_WineLook == WIN31_LOOK)
2056             NC_TrackMinMaxBox( hwnd, wParam );
2057         else
2058             NC_TrackMinMaxBox95( hwnd, wParam );            
2059         break;
2060
2061     case HTCLOSE:
2062         if (TWEAK_WineLook >= WIN95_LOOK)
2063             NC_TrackCloseButton95 (hwnd, wParam);
2064         break;
2065         
2066     case HTLEFT:
2067     case HTRIGHT:
2068     case HTTOP:
2069     case HTTOPLEFT:
2070     case HTTOPRIGHT:
2071     case HTBOTTOM:
2072     case HTBOTTOMLEFT:
2073     case HTBOTTOMRIGHT:
2074         /* make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU */
2075         SendMessageW( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
2076         break;
2077
2078     case HTBORDER:
2079         break;
2080     }
2081     return 0;
2082 }
2083
2084
2085 /***********************************************************************
2086  *           NC_HandleNCLButtonDblClk
2087  *
2088  * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
2089  */
2090 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WPARAM wParam, LPARAM lParam )
2091 {
2092     /*
2093      * if this is an icon, send a restore since we are handling
2094      * a double click
2095      */
2096     if (IsIconic(hwnd))
2097     {
2098         SendMessageW( hwnd, WM_SYSCOMMAND, SC_RESTORE, lParam );
2099         return 0;
2100     } 
2101
2102     switch(wParam)  /* Hit test */
2103     {
2104     case HTCAPTION:
2105         /* stop processing if WS_MAXIMIZEBOX is missing */
2106         if (GetWindowLongA( hwnd, GWL_STYLE ) & WS_MAXIMIZEBOX)
2107             SendMessageW( hwnd, WM_SYSCOMMAND,
2108                           IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, lParam );
2109         break;
2110
2111     case HTSYSMENU:
2112         if (!(GetClassLongW(hwnd, GCL_STYLE) & CS_NOCLOSE))
2113             SendMessageW( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
2114         break;
2115
2116     case HTHSCROLL:
2117         SendMessageW( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
2118         break;
2119
2120     case HTVSCROLL:
2121         SendMessageW( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
2122         break;
2123     }
2124     return 0;
2125 }
2126
2127
2128 /***********************************************************************
2129  *           NC_HandleSysCommand
2130  *
2131  * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
2132  */
2133 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, POINT pt )
2134 {
2135     WND *wndPtr = WIN_FindWndPtr( hwnd );
2136     UINT16 uCommand = wParam & 0xFFF0;
2137
2138     TRACE("Handling WM_SYSCOMMAND %x %ld,%ld\n", wParam, pt.x, pt.y );
2139
2140     if (uCommand != SC_KEYMENU)
2141     {
2142         HWND parent = GetAncestor( hwnd, GA_PARENT );
2143         if (parent != GetDesktopWindow()) ScreenToClient( parent, &pt );
2144     }
2145
2146     switch (uCommand)
2147     {
2148     case SC_SIZE:
2149     case SC_MOVE:
2150         if (USER_Driver.pSysCommandSizeMove)
2151             USER_Driver.pSysCommandSizeMove( hwnd, wParam );
2152         break;
2153
2154     case SC_MINIMIZE:
2155         if (hwnd == GetForegroundWindow())
2156             ShowOwnedPopups(hwnd,FALSE);
2157         ShowWindow( hwnd, SW_MINIMIZE ); 
2158         break;
2159
2160     case SC_MAXIMIZE:
2161         if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2162             ShowOwnedPopups(hwnd,TRUE);
2163         ShowWindow( hwnd, SW_MAXIMIZE );
2164         break;
2165
2166     case SC_RESTORE:
2167         if (IsIconic(hwnd) && hwnd == GetForegroundWindow())
2168             ShowOwnedPopups(hwnd,TRUE);
2169         ShowWindow( hwnd, SW_RESTORE );
2170         break;
2171
2172     case SC_CLOSE:
2173         WIN_ReleaseWndPtr(wndPtr);
2174         return SendMessageA( hwnd, WM_CLOSE, 0, 0 );
2175
2176     case SC_VSCROLL:
2177     case SC_HSCROLL:
2178         NC_TrackScrollBar( hwnd, wParam, pt );
2179         break;
2180
2181     case SC_MOUSEMENU:
2182         MENU_TrackMouseMenuBar( hwnd, wParam & 0x000F, pt );
2183         break;
2184
2185     case SC_KEYMENU:
2186         MENU_TrackKbdMenuBar( hwnd, wParam , pt.x );
2187         break;
2188         
2189     case SC_TASKLIST:
2190         WinExec( "taskman.exe", SW_SHOWNORMAL ); 
2191         break;
2192
2193     case SC_SCREENSAVE:
2194         if (wParam == SC_ABOUTWINE)
2195         {
2196             HMODULE hmodule = LoadLibraryA( "shell32.dll" );
2197             if (hmodule)
2198             {
2199                 FARPROC aboutproc = GetProcAddress( hmodule, "ShellAboutA" );
2200                 if (aboutproc) aboutproc( hwnd, "Wine", WINE_RELEASE_INFO, 0 );
2201                 FreeLibrary( hmodule );
2202             }
2203         }
2204         else 
2205           if (wParam == SC_PUTMARK)
2206             TRACE_(shell)("Mark requested by user\n");
2207         break;
2208   
2209     case SC_HOTKEY:
2210     case SC_ARRANGE:
2211     case SC_NEXTWINDOW:
2212     case SC_PREVWINDOW:
2213         FIXME("unimplemented!\n");
2214         break;
2215     }
2216     WIN_ReleaseWndPtr(wndPtr);
2217     return 0;
2218 }
2219
2220 /*************************************************************
2221 *  NC_DrawGrayButton
2222 *
2223 * Stub for the grayed button of the caption
2224 *
2225 *************************************************************/
2226
2227 BOOL NC_DrawGrayButton(HDC hdc, int x, int y)
2228 {
2229     HBITMAP hMaskBmp;
2230     HDC hdcMask = CreateCompatibleDC (0);
2231     HBRUSH hOldBrush;
2232
2233     hMaskBmp = CreateBitmap (12, 10, 1, 1, lpGrayMask);
2234     
2235     if(hMaskBmp == 0)
2236         return FALSE;
2237     
2238     SelectObject (hdcMask, hMaskBmp);
2239     
2240     /* Draw the grayed bitmap using the mask */
2241     hOldBrush = SelectObject (hdc, RGB(128, 128, 128));
2242     BitBlt (hdc, x, y, 12, 10,
2243             hdcMask, 0, 0, 0xB8074A);
2244     
2245     /* Clean up */
2246     SelectObject (hdc, hOldBrush);
2247     DeleteObject(hMaskBmp);
2248     DeleteDC (hdcMask);
2249     
2250     return TRUE;
2251 }