Release 980601
[wine] / windows / nonclient.c
1 /*
2  * Non-client area window functions
3  *
4  * Copyright 1994 Alexandre Julliard
5  *
6  */
7
8 #include "version.h"
9 #include "win.h"
10 #include "message.h"
11 #include "sysmetrics.h"
12 #include "user.h"
13 #include "heap.h"
14 #include "cursoricon.h"
15 #include "dialog.h"
16 #include "menu.h"
17 #include "winpos.h"
18 #include "hook.h"
19 #include "scroll.h"
20 #include "nonclient.h"
21 #include "graphics.h"
22 #include "queue.h"
23 #include "selectors.h"
24 #include "tweak.h"
25 #include "debug.h"
26 #include "options.h"
27
28
29 int  NC_CaptionLeftNudge;
30 int  NC_CaptionTopNudge;
31 int  NC_SysControlNudge;
32 int  NC_MaxControlNudge;
33 int  NC_MinControlNudge;
34 UINT32  NC_CaptionTextFlags;
35 HBRUSH32  NC_WinHighlight95;
36 HBRUSH32  NC_WinShadow95;
37
38 static HBITMAP16 hbitmapClose = 0;
39 static HBITMAP16 hbitmapMinimize = 0;
40 static HBITMAP16 hbitmapMinimizeD = 0;
41 static HBITMAP16 hbitmapMaximize = 0;
42 static HBITMAP16 hbitmapMaximizeD = 0;
43 static HBITMAP16 hbitmapRestore = 0;
44 static HBITMAP16 hbitmapRestoreD = 0;
45
46 #define SC_ABOUTWINE            (SC_SCREENSAVE+1)
47
48   /* Some useful macros */
49 #define HAS_DLGFRAME(style,exStyle) \
50     (((exStyle) & WS_EX_DLGMODALFRAME) || \
51      (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
52
53 #define HAS_THICKFRAME(style) \
54     (((style) & WS_THICKFRAME) && \
55      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
56
57 #define HAS_MENU(w)  (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
58
59 #define ON_LEFT_BORDER(hit) \
60  (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
61 #define ON_RIGHT_BORDER(hit) \
62  (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
63 #define ON_TOP_BORDER(hit) \
64  (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
65 #define ON_BOTTOM_BORDER(hit) \
66  (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
67
68 /***********************************************************************
69  *           NC_AdjustRect
70  *
71  * Compute the size of the window rectangle from the size of the
72  * client rectangle.
73  */
74 static void NC_AdjustRect( LPRECT16 rect, DWORD style, BOOL32 menu,
75                            DWORD exStyle )
76 {
77     if(TWEAK_Win95Look)
78         ERR(nonclient, "Called in Win95 mode. Aiee! Please report this.\n" );
79
80     if(style & WS_ICONIC) return;
81     /* Decide if the window will be managed (see CreateWindowEx) */
82     if (!(Options.managed && !(style & WS_CHILD) &&
83           ((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
84            (exStyle & WS_EX_DLGMODALFRAME))))
85     {
86         if (HAS_DLGFRAME( style, exStyle ))
87             InflateRect16(rect, SYSMETRICS_CXDLGFRAME, SYSMETRICS_CYDLGFRAME );
88         else
89         {
90             if (HAS_THICKFRAME(style))
91                 InflateRect16( rect, SYSMETRICS_CXFRAME, SYSMETRICS_CYFRAME );
92             if (style & WS_BORDER)
93                 InflateRect16( rect, SYSMETRICS_CXBORDER, SYSMETRICS_CYBORDER);
94         }
95
96         if ((style & WS_CAPTION) == WS_CAPTION)
97             rect->top -= SYSMETRICS_CYCAPTION - SYSMETRICS_CYBORDER;
98     }
99     if (menu) rect->top -= SYSMETRICS_CYMENU + SYSMETRICS_CYBORDER;
100
101     if (style & WS_VSCROLL) rect->right  += SYSMETRICS_CXVSCROLL - 1;
102     if (style & WS_HSCROLL) rect->bottom += SYSMETRICS_CYHSCROLL - 1;
103 }
104
105
106 /******************************************************************************
107  *
108  *   NC_AdjustRect95(
109  *      LPRECT16  rect,
110  *      DWORD  style,
111  *      BOOL32  menu,
112  *      DWORD  exStyle )
113  *
114  *   Computes the size of the window based on the parameters of the client
115  *   area.
116  *
117  *   Bugs
118  *        Most of this code is copied from NC_AdjustRect.  It shouldn't be.
119  *        There are some unique things about Win 95 that are being horribly
120  *        neglected here.  I don't know what they are, either.  :-\
121  *
122  *   Revision history
123  *        05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
124  *             Original cut & paste from NC_AdjustRect
125  *
126  *****************************************************************************/
127
128 static void NC_AdjustRect95( LPRECT16 rect, DWORD style, BOOL32 menu,
129                              DWORD exStyle )
130 {
131     if(style & WS_ICONIC) return;
132
133     /* Decide if the window will be managed (see CreateWindowEx) */
134     if (!(Options.managed && !(style & WS_CHILD) &&
135           ((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
136            (exStyle & WS_EX_DLGMODALFRAME))))
137     {
138         if (HAS_DLGFRAME( style, exStyle ))
139             InflateRect16(rect, SYSMETRICS_CXDLGFRAME, SYSMETRICS_CYDLGFRAME );
140         else
141         {
142             if (HAS_THICKFRAME(style))
143                 InflateRect16( rect, SYSMETRICS_CXFRAME, SYSMETRICS_CYFRAME );
144             if (style & WS_BORDER)
145                 InflateRect16( rect, SYSMETRICS_CXBORDER, SYSMETRICS_CYBORDER);
146         }
147
148         if ((style & WS_CAPTION) == WS_CAPTION)
149             rect->top -= SYSMETRICS_CYCAPTION - SYSMETRICS_CYBORDER;
150     }
151     if (menu) rect->top -= SYSMETRICS_CYMENU + SYSMETRICS_CYBORDER + 2;
152     else  if (!(style & WS_CHILD)) rect->top += SYSMETRICS_CYBORDER;
153
154     if (style & WS_VSCROLL) rect->right  += SYSMETRICS_CXVSCROLL;
155     if (style & WS_HSCROLL) rect->bottom += SYSMETRICS_CYHSCROLL;
156 }
157
158
159 /***********************************************************************
160  *           DrawCaptionTempA    (USER32.599)
161  */
162 DWORD DrawCaptionTemp32A(HWND32 hwnd,HDC32 hdc,LPRECT32 rect,
163     HFONT32 hfont,DWORD x1,LPCSTR str,DWORD x2)
164 {
165     FIXME(nonclient,"(%08x,%08x,%p,%08x,%08lx,\"%s\",%08lx): stub\n",
166         hwnd,hdc,rect,hfont,x1,str,x2);
167     return 0;
168 }
169
170
171 /***********************************************************************
172  *           AdjustWindowRect16    (USER.102)
173  */
174 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
175 {
176     return AdjustWindowRectEx16( rect, style, menu, 0 );
177 }
178
179
180 /***********************************************************************
181  *           AdjustWindowRect32    (USER32.2)
182  */
183 BOOL32 WINAPI AdjustWindowRect32( LPRECT32 rect, DWORD style, BOOL32 menu )
184 {
185     return AdjustWindowRectEx32( rect, style, menu, 0 );
186 }
187
188
189 /***********************************************************************
190  *           AdjustWindowRectEx16    (USER.454)
191  */
192 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
193                                     BOOL16 menu, DWORD exStyle )
194 {
195       /* Correct the window style */
196
197     if (!(style & (WS_POPUP | WS_CHILD)))  /* Overlapped window */
198         style |= WS_CAPTION;
199     style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
200     exStyle &= WS_EX_DLGMODALFRAME;
201     if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
202
203     TRACE(nonclient, "(%d,%d)-(%d,%d) %08lx %d %08lx\n",
204                       rect->left, rect->top, rect->right, rect->bottom,
205                       style, menu, exStyle );
206
207     if(TWEAK_Win95Look)
208         NC_AdjustRect95( rect, style, menu, exStyle );
209     else
210         NC_AdjustRect( rect, style, menu, exStyle );
211
212     return TRUE;
213 }
214
215
216 /***********************************************************************
217  *           AdjustWindowRectEx32    (USER32.3)
218  */
219 BOOL32 WINAPI AdjustWindowRectEx32( LPRECT32 rect, DWORD style,
220                                     BOOL32 menu, DWORD exStyle )
221 {
222     RECT16 rect16;
223     BOOL32 ret;
224
225     CONV_RECT32TO16( rect, &rect16 );
226     ret = AdjustWindowRectEx16( &rect16, style, (BOOL16)menu, exStyle );
227     CONV_RECT16TO32( &rect16, rect );
228     return ret;
229 }
230
231
232 /***********************************************************************
233  *           NC_HandleNCCalcSize
234  *
235  * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
236  */
237 LONG NC_HandleNCCalcSize( WND *pWnd, RECT32 *winRect )
238 {
239     RECT16 tmpRect = { 0, 0, 0, 0 };
240     LONG result = 0;
241
242     if (pWnd->class->style & CS_VREDRAW) result |= WVR_VREDRAW;
243     if (pWnd->class->style & CS_HREDRAW) result |= WVR_HREDRAW;
244
245     if( !( pWnd->dwStyle & WS_MINIMIZE ) ) {
246         if(TWEAK_Win95Look)
247             NC_AdjustRect95( &tmpRect, pWnd->dwStyle, FALSE, pWnd->dwExStyle );
248         else
249             NC_AdjustRect( &tmpRect, pWnd->dwStyle, FALSE, pWnd->dwExStyle );
250
251         winRect->left   -= tmpRect.left;
252         winRect->top    -= tmpRect.top;
253         winRect->right  -= tmpRect.right;
254         winRect->bottom -= tmpRect.bottom;
255
256         if (HAS_MENU(pWnd)) {
257             TRACE(nonclient, "Calling "
258                                "GetMenuBarHeight with HWND 0x%x, width %d, "
259                                "at (%d, %d).\n", pWnd->hwndSelf,
260                                winRect->right - winRect->left,
261                                -tmpRect.left, -tmpRect.top );
262
263             winRect->top +=
264                 MENU_GetMenuBarHeight( pWnd->hwndSelf,
265                                        winRect->right - winRect->left,
266                                        -tmpRect.left, -tmpRect.top ) + 1;
267         }
268     }
269     return result;
270 }
271
272
273 /***********************************************************************
274  *           NC_GetInsideRect
275  *
276  * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
277  * but without the borders (if any).
278  * The rectangle is in window coordinates (for drawing with GetWindowDC()).
279  *
280  * FIXME:  A Win95 version of this function is needed.
281  */
282 static void NC_GetInsideRect( HWND32 hwnd, RECT32 *rect )
283 {
284     WND * wndPtr = WIN_FindWndPtr( hwnd );
285
286     rect->top    = rect->left = 0;
287     rect->right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
288     rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
289
290     if ((wndPtr->dwStyle & WS_ICONIC) || (wndPtr->flags & WIN_MANAGED)) return;
291
292       /* Remove frame from rectangle */
293     if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
294     {
295         InflateRect32( rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
296         if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
297             InflateRect32( rect, -1, 0 );
298     }
299     else
300     {
301         if (HAS_THICKFRAME( wndPtr->dwStyle ))
302             InflateRect32( rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
303         if (wndPtr->dwStyle & WS_BORDER)
304             InflateRect32( rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
305     }
306
307     return;
308 }
309
310
311 /***********************************************************************
312  *           NC_HandleNCHitTest
313  *
314  * Handle a WM_NCHITTEST message. Called from DefWindowProc().
315  *
316  * FIXME:  A Win95 version of this function is needed.
317  */
318 LONG NC_HandleNCHitTest( HWND32 hwnd, POINT16 pt )
319 {
320     RECT16 rect;
321     WND *wndPtr = WIN_FindWndPtr( hwnd );
322     if (!wndPtr) return HTERROR;
323
324     TRACE(nonclient, "hwnd=%04x pt=%d,%d\n",
325                       hwnd, pt.x, pt.y );
326
327     GetWindowRect16( hwnd, &rect );
328     if (!PtInRect16( &rect, pt )) return HTNOWHERE;
329
330     if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
331
332     if (!(wndPtr->flags & WIN_MANAGED))
333     {
334         /* Check borders */
335         if (HAS_THICKFRAME( wndPtr->dwStyle ))
336         {
337             InflateRect16( &rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
338             if (wndPtr->dwStyle & WS_BORDER)
339                 InflateRect16(&rect,-SYSMETRICS_CXBORDER,-SYSMETRICS_CYBORDER);
340             if (!PtInRect16( &rect, pt ))
341             {
342                 /* Check top sizing border */
343                 if (pt.y < rect.top)
344                 {
345                     if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTTOPLEFT;
346                     if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTTOPRIGHT;
347                     return HTTOP;
348                 }
349                 /* Check bottom sizing border */
350                 if (pt.y >= rect.bottom)
351                 {
352                     if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTBOTTOMLEFT;
353                     if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTBOTTOMRIGHT;
354                     return HTBOTTOM;
355                 }
356                 /* Check left sizing border */
357                 if (pt.x < rect.left)
358                 {
359                     if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPLEFT;
360                     if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMLEFT;
361                     return HTLEFT;
362                 }
363                 /* Check right sizing border */
364                 if (pt.x >= rect.right)
365                 {
366                     if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPRIGHT;
367                     if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMRIGHT;
368                     return HTRIGHT;
369                 }
370             }
371         }
372         else  /* No thick frame */
373         {
374             if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
375                 InflateRect16(&rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
376             else if (wndPtr->dwStyle & WS_BORDER)
377                 InflateRect16(&rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER);
378             if (!PtInRect16( &rect, pt )) return HTBORDER;
379         }
380
381         /* Check caption */
382
383         if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
384         {
385             rect.top += SYSMETRICS_CYCAPTION - 1;
386             if (!PtInRect16( &rect, pt ))
387             {
388                 /* Check system menu */
389                 if (wndPtr->dwStyle & WS_SYSMENU)
390                     rect.left += SYSMETRICS_CXSIZE;
391                 if (pt.x <= rect.left) return HTSYSMENU;
392                 /* Check maximize box */
393                 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
394                     rect.right -= SYSMETRICS_CXSIZE + 1;
395                 if (pt.x >= rect.right) return HTMAXBUTTON;
396                 /* Check minimize box */
397                 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
398                     rect.right -= SYSMETRICS_CXSIZE + 1;
399                 if (pt.x >= rect.right) return HTMINBUTTON;
400                 return HTCAPTION;
401             }
402         }
403     }
404
405       /* Check client area */
406
407     ScreenToClient16( hwnd, &pt );
408     GetClientRect16( hwnd, &rect );
409     if (PtInRect16( &rect, pt )) return HTCLIENT;
410
411       /* Check vertical scroll bar */
412
413     if (wndPtr->dwStyle & WS_VSCROLL)
414     {
415         rect.right += SYSMETRICS_CXVSCROLL;
416         if (PtInRect16( &rect, pt )) return HTVSCROLL;
417     }
418
419       /* Check horizontal scroll bar */
420
421     if (wndPtr->dwStyle & WS_HSCROLL)
422     {
423         rect.bottom += SYSMETRICS_CYHSCROLL;
424         if (PtInRect16( &rect, pt ))
425         {
426               /* Check size box */
427             if ((wndPtr->dwStyle & WS_VSCROLL) &&
428                 (pt.x >= rect.right - SYSMETRICS_CXVSCROLL))
429                 return HTSIZE;
430             return HTHSCROLL;
431         }
432     }
433
434       /* Check menu bar */
435
436     if (HAS_MENU(wndPtr))
437     {
438         if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
439             return HTMENU;
440     }
441
442       /* Should never get here */
443     return HTERROR;
444 }
445
446
447 /***********************************************************************
448  *           NC_DrawSysButton
449  */
450 void NC_DrawSysButton( HWND32 hwnd, HDC32 hdc, BOOL32 down )
451 {
452     RECT32 rect;
453     HDC32 hdcMem;
454     HBITMAP32 hbitmap;
455     WND *wndPtr = WIN_FindWndPtr( hwnd );
456
457     if( !(wndPtr->flags & WIN_MANAGED) )
458     {
459       NC_GetInsideRect( hwnd, &rect );
460       hdcMem = CreateCompatibleDC32( hdc );
461       hbitmap = SelectObject32( hdcMem, hbitmapClose );
462       BitBlt32(hdc, rect.left, rect.top, SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
463                hdcMem, (wndPtr->dwStyle & WS_CHILD) ? SYSMETRICS_CXSIZE : 0, 0,
464                down ? NOTSRCCOPY : SRCCOPY );
465       SelectObject32( hdcMem, hbitmap );
466       DeleteDC32( hdcMem );
467     }
468 }
469
470
471 /***********************************************************************
472  *           NC_DrawMaxButton
473  */
474 static void NC_DrawMaxButton( HWND32 hwnd, HDC16 hdc, BOOL32 down )
475 {
476     RECT32 rect;
477     WND *wndPtr = WIN_FindWndPtr( hwnd );
478
479     if( !(wndPtr->flags & WIN_MANAGED) )
480     {
481       NC_GetInsideRect( hwnd, &rect );
482       GRAPH_DrawBitmap( hdc, (IsZoomed32(hwnd) 
483                              ? (down ? hbitmapRestoreD : hbitmapRestore)
484                              : (down ? hbitmapMaximizeD : hbitmapMaximize)),
485                         rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
486                         0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE, FALSE );
487     }
488 }
489
490
491 /***********************************************************************
492  *           NC_DrawMinButton
493  */
494 static void NC_DrawMinButton( HWND32 hwnd, HDC16 hdc, BOOL32 down )
495 {
496     RECT32 rect;
497     WND *wndPtr = WIN_FindWndPtr( hwnd );
498
499     if( !(wndPtr->flags & WIN_MANAGED) )
500     {
501       NC_GetInsideRect( hwnd, &rect );
502       if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= SYSMETRICS_CXSIZE+1;
503       GRAPH_DrawBitmap( hdc, (down ? hbitmapMinimizeD : hbitmapMinimize),
504                         rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
505                         0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE, FALSE );
506     }
507 }
508
509
510 /******************************************************************************
511  *
512  *   void  NC_DrawSysButton95(
513  *      HWND32  hwnd,
514  *      HDC32  hdc,
515  *      BOOL32  down )
516  *
517  *   Draws a fake Win95 system button.  Horribly broken.  We should be drawing
518  *   an icon, not the X.  (This will require some thought)
519  *
520  *   Bugs
521  *        Plain and simply doesn't work.  Fails miserably for child windows.
522  *
523  *   Revision history
524  *        05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
525  *             Original implementation from NC_DrawSysButton source.
526  *
527  *****************************************************************************/
528
529 void  NC_DrawSysButton95(
530     HWND32  hwnd,
531     HDC32  hdc,
532     BOOL32  down )
533 {
534     RECT32 rect;
535     HDC32 hdcMem;
536     HBITMAP32 hbitmap;
537     WND *wndPtr = WIN_FindWndPtr( hwnd );
538     SIZE32  bmsz;
539
540     if( !(wndPtr->flags & WIN_MANAGED) )
541     {
542         NC_GetInsideRect( hwnd, &rect );
543         hdcMem = CreateCompatibleDC32( hdc );
544         hbitmap = SelectObject32( hdcMem, hbitmapClose );
545         if(GetBitmapDimensionEx32( hbitmapClose, &bmsz )) {
546             BitBlt32(hdc, rect.left + (sysMetrics[SM_CXSIZE] - bmsz.cx) / 2 +
547                      NC_SysControlNudge,
548                      rect.top + (sysMetrics[SM_CYSIZE] - bmsz.cy - 1) / 2,
549                      bmsz.cx, bmsz.cy,
550                      hdcMem, 0, 0, down ? NOTSRCCOPY : SRCCOPY );
551         }
552         SelectObject32( hdcMem, hbitmap );
553         DeleteDC32( hdcMem );
554         
555     }
556     return;
557 }
558
559
560 /******************************************************************************
561  *
562  *   NC_DrawMaxButton95(
563  *      HWND32  hwnd,
564  *      HDC16  hdc,
565  *      BOOL32  down )
566  *
567  *   Draws the maximize button for Win95 style windows.
568  *
569  *   Bugs
570  *        Many.  Spacing might still be incorrect.  Need to fit a close
571  *        button between the max button and the edge.  Draws the wrong thing
572  *        (a Win31 up-down) when maximized.  Should scale the image with the
573  *        title bar.  And more...
574  *
575  *   Revision history
576  *        05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
577  *             Original implementation.
578  *
579  *****************************************************************************/
580
581 static void  NC_DrawMaxButton95(
582     HWND32 hwnd,
583     HDC16 hdc,
584     BOOL32 down )
585 {
586     RECT32 rect;
587     WND *wndPtr = WIN_FindWndPtr( hwnd );
588     SIZE32  bmsz;
589     HBITMAP32  bm;
590
591     if( !(wndPtr->flags & WIN_MANAGED) &&
592         GetBitmapDimensionEx32((bm = IsZoomed32(hwnd) ?
593                                 (down ? hbitmapRestoreD : hbitmapRestore ) :
594                                 (down ? hbitmapMaximizeD : hbitmapMaximize)),
595                                &bmsz)) {
596
597         NC_GetInsideRect( hwnd, &rect );
598         
599         GRAPH_DrawBitmap( hdc, bm,
600                           rect.right + NC_MaxControlNudge -
601                           (sysMetrics[SM_CXSIZE] + bmsz.cx) / 2,
602                           rect.top + (sysMetrics[SM_CYSIZE] - bmsz.cy - 1) / 2,
603                           0, 0, bmsz.cx, bmsz.cy, FALSE );
604     }
605
606     return;
607 }
608
609
610 /******************************************************************************
611  *
612  *   NC_DrawMinButton95(
613  *      HWND32  hwnd,
614  *      HDC16  hdc,
615  *      BOOL32  down )
616  *
617  *   Draws the minimize button for Win95 style windows.
618  *
619  *   Bugs
620  *        Many.  Spacing is still incorrect.  Should scale the image with the
621  *        title bar.  And more...
622  *
623  *   Revision history
624  *        05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
625  *             Original implementation.
626  *
627  *****************************************************************************/
628
629 static void  NC_DrawMinButton95(
630     HWND32 hwnd,
631     HDC16 hdc,
632     BOOL32 down )
633 {
634     RECT32 rect;
635     WND *wndPtr = WIN_FindWndPtr( hwnd );
636     SIZE32  bmsz;
637     HBITMAP32  bm;
638
639     if( !(wndPtr->flags & WIN_MANAGED) &&
640         GetBitmapDimensionEx32((bm = down ? hbitmapMinimizeD :
641                                 hbitmapMinimize), &bmsz)) {
642         
643         NC_GetInsideRect( hwnd, &rect );
644
645         if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
646             rect.right += -1 + NC_MaxControlNudge -
647                 (sysMetrics[SM_CXSIZE] + bmsz.cx) / 2;
648
649         GRAPH_DrawBitmap( hdc, bm, rect.right + NC_MinControlNudge -
650                           (sysMetrics[SM_CXSIZE] + bmsz.cx) / 2,
651                           rect.top + (sysMetrics[SM_CYSIZE] - bmsz.cy - 1) / 2,
652                           0, 0, bmsz.cx, bmsz.cy, FALSE );
653     }
654
655     return;
656 }
657
658
659 /***********************************************************************
660  *           NC_DrawFrame
661  *
662  * Draw a window frame inside the given rectangle, and update the rectangle.
663  * The correct pen for the frame must be selected in the DC.
664  */
665 static void NC_DrawFrame( HDC32 hdc, RECT32 *rect, BOOL32 dlgFrame,
666                           BOOL32 active )
667 {
668     INT32 width, height;
669
670     if(TWEAK_Win95Look)
671         ERR(nonclient, "Called in Win95 mode. Aiee! Please report this.\n" );
672
673     if (dlgFrame)
674     {
675         width = SYSMETRICS_CXDLGFRAME - 1;
676         height = SYSMETRICS_CYDLGFRAME - 1;
677         SelectObject32( hdc, GetSysColorBrush32(active ? COLOR_ACTIVECAPTION :
678                                                 COLOR_INACTIVECAPTION) );
679     }
680     else
681     {
682         width = SYSMETRICS_CXFRAME - 1;
683         height = SYSMETRICS_CYFRAME - 1;
684         SelectObject32( hdc, GetSysColorBrush32(active ? COLOR_ACTIVEBORDER :
685                                                 COLOR_INACTIVEBORDER) );
686     }
687
688       /* Draw frame */
689     PatBlt32( hdc, rect->left, rect->top,
690               rect->right - rect->left, height, PATCOPY );
691     PatBlt32( hdc, rect->left, rect->top,
692               width, rect->bottom - rect->top, PATCOPY );
693     PatBlt32( hdc, rect->left, rect->bottom,
694               rect->right - rect->left, -height, PATCOPY );
695     PatBlt32( hdc, rect->right, rect->top,
696               -width, rect->bottom - rect->top, PATCOPY );
697
698     if (dlgFrame)
699     {
700         InflateRect32( rect, -width, -height );
701     } 
702     else
703     {
704         POINT32 lpt[16];
705     
706       /* Draw inner rectangle */
707
708         GRAPH_DrawRectangle( hdc, rect->left + width,
709                                   rect->top + height,
710                                   rect->right - rect->left - 2*width ,
711                                   rect->bottom - rect->top - 2*height,
712                                   (HPEN32)0 );
713
714       /* Draw the decorations */
715
716         lpt[4].x = lpt[0].x = rect->left;
717         lpt[5].x = lpt[1].x = rect->left + width;
718         lpt[6].x = lpt[2].x = rect->right - 1;
719         lpt[7].x = lpt[3].x = rect->right - width - 1;
720
721         lpt[0].y = lpt[1].y = lpt[2].y = lpt[3].y = 
722                   rect->top + SYSMETRICS_CYFRAME + SYSMETRICS_CYSIZE;
723         lpt[4].y = lpt[5].y = lpt[6].y = lpt[7].y =
724                   rect->bottom - SYSMETRICS_CYFRAME - SYSMETRICS_CYSIZE;
725
726         lpt[8].x = lpt[9].x = lpt[10].x = lpt[11].x =
727                   rect->left + SYSMETRICS_CXFRAME + SYSMETRICS_CXSIZE;
728         lpt[12].x = lpt[13].x = lpt[14].x = lpt[15].x = 
729                   rect->right - SYSMETRICS_CXFRAME - SYSMETRICS_CYSIZE;
730
731         lpt[12].y = lpt[8].y = rect->top; 
732         lpt[13].y = lpt[9].y = rect->top + height;
733         lpt[14].y = lpt[10].y = rect->bottom - 1;
734         lpt[15].y = lpt[11].y = rect->bottom - height - 1;
735
736         GRAPH_DrawLines( hdc, lpt, 8, (HPEN32)0 );      /* 8 is the maximum */
737         InflateRect32( rect, -width - 1, -height - 1 );
738     }
739 }
740
741
742 /******************************************************************************
743  *
744  *   void  NC_DrawFrame95(
745  *      HDC32  hdc,
746  *      RECT32  *rect,
747  *      BOOL32  dlgFrame,
748  *      BOOL32  active )
749  *
750  *   Draw a window frame inside the given rectangle, and update the rectangle.
751  *   The correct pen for the frame must be selected in the DC.
752  *
753  *   Bugs
754  *        Many.  First, just what IS a frame in Win95?  Note that the 3D look
755  *        on the outer edge is handled by NC_DoNCPaint95.  As is the inner
756  *        edge.  The inner rectangle just inside the frame is handled by the
757  *        Caption code.
758  *
759  *        In short, for most people, this function should be a nop (unless
760  *        you LIKE thick borders in Win95/NT4.0 -- I've been working with
761  *        them lately, but just to get this code right).  Even so, it doesn't
762  *        appear to be so.  It's being worked on...
763  * 
764  *   Revision history
765  *        06-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
766  *             Original implementation (based on NC_DrawFrame)
767  *
768  *****************************************************************************/
769
770 static void  NC_DrawFrame95(
771     HDC32  hdc,
772     RECT32  *rect,
773     BOOL32  dlgFrame,
774     BOOL32  active )
775 {
776     INT32 width, height;
777
778     if (dlgFrame)
779     {
780         width = SYSMETRICS_CXDLGFRAME - 1;
781         height = SYSMETRICS_CYDLGFRAME - 1;
782         SelectObject32( hdc, GetSysColorBrush32(active ? COLOR_ACTIVECAPTION :
783                                                 COLOR_INACTIVECAPTION) );
784     }
785     else
786     {
787         width = sysMetrics[SM_CXFRAME] - sysMetrics[SM_CXEDGE] - 1;
788         height = sysMetrics[SM_CYFRAME] - sysMetrics[SM_CYEDGE] - 1;
789         SelectObject32( hdc, GetSysColorBrush32(active ? COLOR_ACTIVEBORDER :
790                                                 COLOR_INACTIVEBORDER) );
791     }
792
793     /* Draw frame */
794     PatBlt32( hdc, rect->left, rect->top,
795               rect->right - rect->left, height, PATCOPY );
796     PatBlt32( hdc, rect->left, rect->top,
797               width, rect->bottom - rect->top, PATCOPY );
798     PatBlt32( hdc, rect->left, rect->bottom,
799               rect->right - rect->left, -height, PATCOPY );
800     PatBlt32( hdc, rect->right, rect->top,
801               -width, rect->bottom - rect->top, PATCOPY );
802
803     InflateRect32( rect, -width, -height );
804
805     if(!dlgFrame) {
806         /* Draw inner rectangle */
807         GRAPH_DrawRectangle( hdc, rect->left, rect->top,
808                              rect->right - rect->left,
809                              rect->bottom - rect->top,
810                              TWEAK_PenC095 );
811
812         InflateRect32( rect, -1, -1 );
813     }
814 }
815
816
817
818 /***********************************************************************
819  *           NC_DrawMovingFrame
820  *
821  * Draw the frame used when moving or resizing window.
822  *
823  * FIXME:  This causes problems in Win95 mode.  (why?)
824  */
825 static void NC_DrawMovingFrame( HDC32 hdc, RECT32 *rect, BOOL32 thickframe )
826 {
827     if (thickframe)
828     {
829         RECT16 r16;
830         CONV_RECT32TO16( rect, &r16 );
831         FastWindowFrame( hdc, &r16, SYSMETRICS_CXFRAME,
832                          SYSMETRICS_CYFRAME, PATINVERT );
833     }
834     else DrawFocusRect32( hdc, rect );
835 }
836
837
838 /***********************************************************************
839  *           NC_DrawCaption
840  *
841  * Draw the window caption.
842  * The correct pen for the window frame must be selected in the DC.
843  */
844 static void NC_DrawCaption( HDC32 hdc, RECT32 *rect, HWND32 hwnd,
845                             DWORD style, BOOL32 active )
846 {
847     RECT32 r = *rect;
848     WND * wndPtr = WIN_FindWndPtr( hwnd );
849     char buffer[256];
850
851     if (wndPtr->flags & WIN_MANAGED) return;
852
853     if (!hbitmapClose)
854     {
855         if (!(hbitmapClose = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_CLOSE) )))
856             return;
857         hbitmapMinimize  = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_REDUCE) );
858         hbitmapMinimizeD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_REDUCED) );
859         hbitmapMaximize  = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_ZOOM) );
860         hbitmapMaximizeD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_ZOOMD) );
861         hbitmapRestore   = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORE) );
862         hbitmapRestoreD  = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORED) );
863     }
864     
865     if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
866     {
867         HBRUSH32 hbrushOld = SelectObject32(hdc, GetSysColorBrush32(COLOR_WINDOW) );
868         PatBlt32( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
869         PatBlt32( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
870         PatBlt32( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
871         r.left++;
872         r.right--;
873         SelectObject32( hdc, hbrushOld );
874     }
875
876     MoveTo( hdc, r.left, r.bottom );
877     LineTo32( hdc, r.right, r.bottom );
878
879     if (style & WS_SYSMENU)
880     {
881         NC_DrawSysButton( hwnd, hdc, FALSE );
882         r.left += SYSMETRICS_CXSIZE + 1;
883         MoveTo( hdc, r.left - 1, r.top );
884         LineTo32( hdc, r.left - 1, r.bottom );
885     }
886     if (style & WS_MAXIMIZEBOX)
887     {
888         NC_DrawMaxButton( hwnd, hdc, FALSE );
889         r.right -= SYSMETRICS_CXSIZE + 1;
890     }
891     if (style & WS_MINIMIZEBOX)
892     {
893         NC_DrawMinButton( hwnd, hdc, FALSE );
894         r.right -= SYSMETRICS_CXSIZE + 1;
895     }
896
897     FillRect32( hdc, &r, GetSysColorBrush32(active ? COLOR_ACTIVECAPTION :
898                                             COLOR_INACTIVECAPTION) );
899
900     if (GetWindowText32A( hwnd, buffer, sizeof(buffer) ))
901     {
902         if (active) SetTextColor32( hdc, GetSysColor32( COLOR_CAPTIONTEXT ) );
903         else SetTextColor32( hdc, GetSysColor32( COLOR_INACTIVECAPTIONTEXT ) );
904         SetBkMode32( hdc, TRANSPARENT );
905         DrawText32A( hdc, buffer, -1, &r,
906                      DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
907     }
908 }
909
910
911 /******************************************************************************
912  *
913  *   NC_DrawCaption95(
914  *      HDC32  hdc,
915  *      RECT32  *rect,
916  *      HWND32  hwnd,
917  *      DWORD  style,
918  *      BOOL32  active )
919  *
920  *   Draw the window caption for Win95 style windows.
921  *   The correct pen for the window frame must be selected in the DC.
922  *
923  *   Bugs
924  *        Hey, a function that finally works!  Well, almost.  In Win95, the
925  *        title has its own font -- not the system font.  It's being worked
926  *        on.
927  *
928  *   Revision history
929  *        05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
930  *             Original implementation.
931  *
932  *****************************************************************************/
933
934 static void  NC_DrawCaption95(
935     HDC32  hdc,
936     RECT32  *rect,
937     HWND32 hwnd,
938     DWORD  style,
939     BOOL32  active )
940 {
941     RECT32  r = *rect;
942     WND   *wndPtr = WIN_FindWndPtr( hwnd );
943     char  buffer[256];
944
945     if (wndPtr->flags & WIN_MANAGED) return;
946
947     FillRect32( hdc, &r, GetSysColorBrush32(active ? COLOR_ACTIVECAPTION :
948                                             COLOR_INACTIVECAPTION) );
949
950     if (!hbitmapClose) {
951         if (!(hbitmapClose = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_CLOSE) )))
952             return;
953         hbitmapMinimize  = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_REDUCE) );
954         hbitmapMinimizeD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_REDUCED) );
955         hbitmapMaximize  = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_ZOOM) );
956         hbitmapMaximizeD = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_ZOOMD) );
957         hbitmapRestore   = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORE) );
958         hbitmapRestoreD  = LoadBitmap16( 0, MAKEINTRESOURCE16(OBM_RESTORED) );
959     }
960     
961     if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) {
962         HBRUSH32 hbrushOld = SelectObject32(hdc, GetSysColorBrush32(COLOR_WINDOW) );
963         PatBlt32( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
964         PatBlt32( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
965         PatBlt32( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
966         r.left++;
967         r.right--;
968         SelectObject32( hdc, hbrushOld );
969     }
970
971     if (style & WS_SYSMENU) {
972         NC_DrawSysButton95( hwnd, hdc, FALSE );
973         r.left += SYSMETRICS_CXSIZE + 1;
974     }
975     if (style & WS_MAXIMIZEBOX) {
976         NC_DrawMaxButton95( hwnd, hdc, FALSE );
977         r.right -= SYSMETRICS_CXSIZE + 1;
978     }
979     if (style & WS_MINIMIZEBOX) {
980         NC_DrawMinButton95( hwnd, hdc, FALSE );
981         r.right -= SYSMETRICS_CXSIZE + 1;
982     }
983
984     if (GetWindowText32A( hwnd, buffer, sizeof(buffer) )) {
985         if (active) SetTextColor32( hdc, GetSysColor32( COLOR_CAPTIONTEXT ) );
986         else SetTextColor32( hdc, GetSysColor32( COLOR_INACTIVECAPTIONTEXT ) );
987         SetBkMode32( hdc, TRANSPARENT );
988         r.top += NC_CaptionTopNudge - 2;
989         r.left += NC_CaptionLeftNudge;
990         DrawText32A( hdc, buffer, -1, &r, NC_CaptionTextFlags );
991     }
992 }
993
994
995
996 /***********************************************************************
997  *           NC_DoNCPaint
998  *
999  * Paint the non-client area. clip is currently unused.
1000  */
1001 void NC_DoNCPaint( WND* wndPtr, HRGN32 clip, BOOL32 suppress_menupaint )
1002 {
1003     HDC32 hdc;
1004     RECT32 rect;
1005     BOOL32 active;
1006     HWND32 hwnd = wndPtr->hwndSelf;
1007
1008     if ( wndPtr->dwStyle & WS_MINIMIZE ||
1009         !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
1010
1011     active  = wndPtr->flags & WIN_NCACTIVATED;
1012
1013     TRACE(nonclient, "%04x %d\n", hwnd, active );
1014
1015     if (!(hdc = GetDCEx32( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
1016
1017     if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1018                         wndPtr->rectClient.top-wndPtr->rectWindow.top,
1019                         wndPtr->rectClient.right-wndPtr->rectWindow.left,
1020                         wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1021         == NULLREGION)
1022     {
1023         ReleaseDC32( hwnd, hdc );
1024         return;
1025     }
1026
1027     rect.top = rect.left = 0;
1028     rect.right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1029     rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1030
1031     SelectObject32( hdc, GetSysColorPen32(COLOR_WINDOWFRAME) );
1032
1033     if (!(wndPtr->flags & WIN_MANAGED))
1034     {
1035         if ((wndPtr->dwStyle & WS_BORDER) || (wndPtr->dwStyle & WS_DLGFRAME) ||
1036             (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
1037         {
1038             GRAPH_DrawRectangle( hdc, 0, 0,
1039                                  rect.right, rect.bottom, (HPEN32)0 );
1040             InflateRect32( &rect, -1, -1 );
1041         }
1042
1043         if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle )) 
1044             NC_DrawFrame( hdc, &rect, TRUE, active );
1045         else if (wndPtr->dwStyle & WS_THICKFRAME)
1046             NC_DrawFrame(hdc, &rect, FALSE, active );
1047
1048         if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1049         {
1050             RECT32 r = rect;
1051             r.bottom = rect.top + SYSMETRICS_CYSIZE;
1052             rect.top += SYSMETRICS_CYSIZE + SYSMETRICS_CYBORDER;
1053             NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
1054         }
1055     }
1056
1057     if (HAS_MENU(wndPtr))
1058     {
1059         RECT32 r = rect;
1060         r.bottom = rect.top + SYSMETRICS_CYMENU;  /* default height */
1061         rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1062     }
1063
1064       /* Draw the scroll-bars */
1065
1066     if (wndPtr->dwStyle & WS_VSCROLL)
1067         SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE );
1068     if (wndPtr->dwStyle & WS_HSCROLL)
1069         SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE );
1070
1071       /* Draw the "size-box" */
1072
1073     if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1074     {
1075         RECT32 r = rect;
1076         r.left = r.right - SYSMETRICS_CXVSCROLL + 1;
1077         r.top  = r.bottom - SYSMETRICS_CYHSCROLL + 1;
1078         FillRect32( hdc, &r, GetSysColorBrush32(COLOR_SCROLLBAR) );
1079     }    
1080
1081     ReleaseDC32( hwnd, hdc );
1082 }
1083
1084
1085 /******************************************************************************
1086  *
1087  *   void  NC_DoNCPaint95(
1088  *      WND  *wndPtr,
1089  *      HRGN32  clip,
1090  *      BOOL32  suppress_menupaint )
1091  *
1092  *   Paint the non-client area for Win95 windows.  The clip region is
1093  *   currently ignored.
1094  *
1095  *   Bugs
1096  *        grep -E -A10 -B5 \(95\)\|\(Bugs\)\|\(FIXME\) windows/nonclient.c \
1097  *           misc/tweak.c controls/menu.c  # :-)
1098  *
1099  *   Revision history
1100  *        03-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1101  *             Original implementation
1102  *
1103  *****************************************************************************/
1104
1105 void  NC_DoNCPaint95(
1106     WND  *wndPtr,
1107     HRGN32  clip,
1108     BOOL32  suppress_menupaint )
1109 {
1110     HDC32 hdc;
1111     RECT32 rect;
1112     BOOL32 active;
1113     HWND32 hwnd = wndPtr->hwndSelf;
1114
1115     if ( wndPtr->dwStyle & WS_MINIMIZE ||
1116         !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
1117
1118     active  = wndPtr->flags & WIN_NCACTIVATED;
1119
1120     TRACE(nonclient, "%04x %d\n", hwnd, active );
1121
1122     if (!(hdc = GetDCEx32( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
1123
1124     if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
1125                         wndPtr->rectClient.top-wndPtr->rectWindow.top,
1126                         wndPtr->rectClient.right-wndPtr->rectWindow.left,
1127                         wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
1128         == NULLREGION)
1129     {
1130         ReleaseDC32( hwnd, hdc );
1131         return;
1132     }
1133
1134     rect.top = rect.left = 0;
1135     rect.right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
1136     rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
1137
1138     SelectObject32( hdc, GetSysColorPen32(COLOR_WINDOWFRAME) );
1139
1140     if(!(wndPtr->flags & WIN_MANAGED)) {
1141         if((wndPtr->dwStyle & WS_BORDER) || (wndPtr->dwStyle & WS_DLGFRAME) ||
1142            (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)) {
1143             TWEAK_DrawReliefRect95(hdc, &rect);
1144             InflateRect32(&rect, -2, -2);
1145         }
1146
1147         if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle )) 
1148             NC_DrawFrame95( hdc, &rect, TRUE, active );
1149         else if (wndPtr->dwStyle & WS_THICKFRAME)
1150             NC_DrawFrame95(hdc, &rect, FALSE, active );
1151
1152         if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
1153         {
1154             RECT32  r = rect;
1155             POINT32  sep[2] = { { rect.left,
1156                                   rect.top + sysMetrics[SM_CYCAPTION] - 2 },
1157                                 { rect.right,
1158                                   rect.top + sysMetrics[SM_CYCAPTION] - 2 } };
1159
1160             r.bottom = rect.top + sysMetrics[SM_CYCAPTION] - 2;
1161             rect.top += sysMetrics[SM_CYCAPTION] - 2 + sysMetrics[SM_CYBORDER];
1162             NC_DrawCaption95( hdc, &r, hwnd, wndPtr->dwStyle, active );
1163             GRAPH_DrawLines( hdc, sep, 1, TWEAK_PenC095 );
1164         }
1165     }
1166
1167     if (HAS_MENU(wndPtr))
1168     {
1169         RECT32 r = rect;
1170         r.bottom = rect.top + sysMetrics[SM_CYMENU] - sysMetrics[SM_CYBORDER];
1171         r.top -= sysMetrics[SM_CYBORDER];
1172         
1173         TRACE(nonclient, "Calling DrawMenuBar with "
1174                           "rect (%d, %d)-(%d, %d)\n", r.left, r.top,
1175                           r.right, r.bottom);
1176
1177         rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
1178     }
1179
1180     TRACE(nonclient, "After MenuBar, rect is (%d, %d)-(%d, %d).\n",
1181                        rect.left, rect.top, rect.right, rect.bottom );
1182
1183     /* Draw the inner frames */
1184     GRAPH_DrawRectangle( hdc, rect.left, rect.top, rect.right - rect.left,
1185                          rect.bottom - rect.top, TWEAK_PenC095 );
1186     InflateRect32(&rect, -1, -1);
1187     GRAPH_DrawGenericReliefRect( hdc, &rect, 1, 1, NC_WinShadow95,
1188                                  NC_WinHighlight95 );
1189
1190     InflateRect32(&rect, -1, -1);
1191
1192     /* Draw the scroll-bars */
1193
1194     if (wndPtr->dwStyle & WS_VSCROLL)
1195         SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE );
1196     if (wndPtr->dwStyle & WS_HSCROLL)
1197         SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE );
1198
1199     /* Draw the "size-box" */
1200     if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
1201     {
1202         RECT32 r = rect;
1203         r.left = r.right - SYSMETRICS_CXVSCROLL + 1;
1204         r.top  = r.bottom - SYSMETRICS_CYHSCROLL + 1;
1205         FillRect32( hdc, &r,  GetSysColorBrush32(COLOR_SCROLLBAR) );
1206     }    
1207
1208     ReleaseDC32( hwnd, hdc );
1209 }
1210
1211
1212
1213
1214 /***********************************************************************
1215  *           NC_HandleNCPaint
1216  *
1217  * Handle a WM_NCPAINT message. Called from DefWindowProc().
1218  */
1219 LONG NC_HandleNCPaint( HWND32 hwnd , HRGN32 clip)
1220 {
1221     WND* wndPtr = WIN_FindWndPtr( hwnd );
1222
1223     if( wndPtr && wndPtr->dwStyle & WS_VISIBLE )
1224     {
1225         if( wndPtr->dwStyle & WS_MINIMIZE )
1226             WINPOS_RedrawIconTitle( hwnd );
1227         else if(TWEAK_Win95Look)
1228             NC_DoNCPaint95( wndPtr, clip, FALSE );
1229         else
1230             NC_DoNCPaint( wndPtr, clip, FALSE );
1231     }
1232     return 0;
1233 }
1234
1235
1236 /***********************************************************************
1237  *           NC_HandleNCActivate
1238  *
1239  * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
1240  */
1241 LONG NC_HandleNCActivate( WND *wndPtr, WPARAM16 wParam )
1242 {
1243     WORD wStateChange;
1244
1245     if( wParam ) wStateChange = !(wndPtr->flags & WIN_NCACTIVATED);
1246     else wStateChange = wndPtr->flags & WIN_NCACTIVATED;
1247
1248     if( wStateChange )
1249     {
1250         if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
1251         else wndPtr->flags &= ~WIN_NCACTIVATED;
1252
1253         if( wndPtr->dwStyle & WS_MINIMIZE ) 
1254             WINPOS_RedrawIconTitle( wndPtr->hwndSelf );
1255         else if( TWEAK_Win95Look )
1256             NC_DoNCPaint95( wndPtr, (HRGN32)1, FALSE );
1257         else
1258             NC_DoNCPaint( wndPtr, (HRGN32)1, FALSE );
1259     }
1260     return TRUE;
1261 }
1262
1263
1264 /***********************************************************************
1265  *           NC_HandleSetCursor
1266  *
1267  * Handle a WM_SETCURSOR message. Called from DefWindowProc().
1268  */
1269 LONG NC_HandleSetCursor( HWND32 hwnd, WPARAM16 wParam, LPARAM lParam )
1270 {
1271     if (hwnd != (HWND32)wParam) return 0;  /* Don't set the cursor for child windows */
1272
1273     switch(LOWORD(lParam))
1274     {
1275     case HTERROR:
1276         {
1277             WORD msg = HIWORD( lParam );
1278             if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
1279                 (msg == WM_RBUTTONDOWN))
1280                 MessageBeep32(0);
1281         }
1282         break;
1283
1284     case HTCLIENT:
1285         {
1286             WND *wndPtr;
1287             if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
1288             if (wndPtr->class->hCursor)
1289             {
1290                 SetCursor16( wndPtr->class->hCursor );
1291                 return TRUE;
1292             }
1293             else return FALSE;
1294         }
1295
1296     case HTLEFT:
1297     case HTRIGHT:
1298         return (LONG)SetCursor16( LoadCursor16( 0, IDC_SIZEWE16 ) );
1299
1300     case HTTOP:
1301     case HTBOTTOM:
1302         return (LONG)SetCursor16( LoadCursor16( 0, IDC_SIZENS16 ) );
1303
1304     case HTTOPLEFT:
1305     case HTBOTTOMRIGHT: 
1306         return (LONG)SetCursor16( LoadCursor16( 0, IDC_SIZENWSE16 ) );
1307
1308     case HTTOPRIGHT:
1309     case HTBOTTOMLEFT:
1310         return (LONG)SetCursor16( LoadCursor16( 0, IDC_SIZENESW16 ) );
1311     }
1312
1313     /* Default cursor: arrow */
1314     return (LONG)SetCursor16( LoadCursor16( 0, IDC_ARROW16 ) );
1315 }
1316
1317 /***********************************************************************
1318  *           NC_GetSysPopupPos
1319  */
1320 BOOL32 NC_GetSysPopupPos( WND* wndPtr, RECT32* rect )
1321 {
1322   if( wndPtr->hSysMenu )
1323   {
1324       if( wndPtr->dwStyle & WS_MINIMIZE )
1325           GetWindowRect32( wndPtr->hwndSelf, rect );
1326       else
1327       {
1328           NC_GetInsideRect( wndPtr->hwndSelf, rect );
1329           OffsetRect32( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top);
1330           if (wndPtr->dwStyle & WS_CHILD)
1331               ClientToScreen32( wndPtr->parent->hwndSelf, (POINT32 *)rect );
1332           rect->right = rect->left + SYSMETRICS_CXSIZE;
1333           rect->bottom = rect->top + SYSMETRICS_CYSIZE;
1334       }
1335       return TRUE;
1336   }
1337   return FALSE;
1338 }
1339
1340 /***********************************************************************
1341  *           NC_StartSizeMove
1342  *
1343  * Initialisation of a move or resize, when initiatied from a menu choice.
1344  * Return hit test code for caption or sizing border.
1345  */
1346 static LONG NC_StartSizeMove( WND* wndPtr, WPARAM16 wParam,
1347                               POINT16 *capturePoint )
1348 {
1349     LONG hittest = 0;
1350     POINT16 pt;
1351     MSG16 msg;
1352
1353     if ((wParam & 0xfff0) == SC_MOVE)
1354     {
1355           /* Move pointer at the center of the caption */
1356         RECT32 rect;
1357         NC_GetInsideRect( wndPtr->hwndSelf, &rect );
1358         if (wndPtr->dwStyle & WS_SYSMENU)
1359             rect.left += SYSMETRICS_CXSIZE + 1;
1360         if (wndPtr->dwStyle & WS_MINIMIZEBOX)
1361             rect.right -= SYSMETRICS_CXSIZE + 1;
1362         if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
1363             rect.right -= SYSMETRICS_CXSIZE + 1;
1364         pt.x = wndPtr->rectWindow.left + (rect.right - rect.left) / 2;
1365         pt.y = wndPtr->rectWindow.top + rect.top + SYSMETRICS_CYSIZE/2;
1366         hittest = HTCAPTION;
1367         *capturePoint = pt;
1368
1369         if (wndPtr->dwStyle & WS_CHILD)
1370             ClientToScreen16( wndPtr->parent->hwndSelf, &pt );
1371     }
1372     else  /* SC_SIZE */
1373     {
1374         while(!hittest)
1375         {
1376             MSG_InternalGetMessage( &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE );
1377             switch(msg.message)
1378             {
1379             case WM_MOUSEMOVE:
1380                 hittest = NC_HandleNCHitTest( wndPtr->hwndSelf, msg.pt );
1381                 pt = msg.pt;
1382                 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
1383                     hittest = 0;
1384                 break;
1385
1386             case WM_LBUTTONUP:
1387                 return 0;
1388
1389             case WM_KEYDOWN:
1390                 switch(msg.wParam)
1391                 {
1392                 case VK_UP:
1393                     hittest = HTTOP;
1394                     pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
1395                     pt.y = wndPtr->rectWindow.top + SYSMETRICS_CYFRAME / 2;
1396                     break;
1397                 case VK_DOWN:
1398                     hittest = HTBOTTOM;
1399                     pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
1400                     pt.y = wndPtr->rectWindow.bottom - SYSMETRICS_CYFRAME / 2;
1401                     break;
1402                 case VK_LEFT:
1403                     hittest = HTLEFT;
1404                     pt.x = wndPtr->rectWindow.left + SYSMETRICS_CXFRAME / 2;
1405                     pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
1406                     break;
1407                 case VK_RIGHT:
1408                     hittest = HTRIGHT;
1409                     pt.x = wndPtr->rectWindow.right - SYSMETRICS_CXFRAME / 2;
1410                     pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
1411                     break;
1412                 case VK_RETURN:
1413                 case VK_ESCAPE: return 0;
1414                 }
1415             }
1416         }
1417         *capturePoint = pt;
1418     }
1419     SetCursorPos32( pt.x, pt.y );
1420     NC_HandleSetCursor( wndPtr->hwndSelf, 
1421                         wndPtr->hwndSelf, MAKELONG( hittest, WM_MOUSEMOVE ));
1422     return hittest;
1423 }
1424
1425
1426 /***********************************************************************
1427  *           NC_DoSizeMove
1428  *
1429  * Perform SC_MOVE and SC_SIZE commands.
1430  */
1431 static void NC_DoSizeMove( HWND32 hwnd, WORD wParam, POINT16 pt )
1432 {
1433     MSG16 msg;
1434     RECT32 sizingRect, mouseRect;
1435     HDC32 hdc;
1436     LONG hittest = (LONG)(wParam & 0x0f);
1437     HCURSOR16 hDragCursor = 0, hOldCursor = 0;
1438     POINT32 minTrack, maxTrack;
1439     POINT16 capturePoint = pt;
1440     WND *     wndPtr = WIN_FindWndPtr( hwnd );
1441     BOOL32    thickframe = HAS_THICKFRAME( wndPtr->dwStyle );
1442     BOOL32    iconic = wndPtr->dwStyle & WS_MINIMIZE;
1443     BOOL32    moved = FALSE;
1444
1445     if (IsZoomed32(hwnd) || !IsWindowVisible32(hwnd) ||
1446         (wndPtr->flags & WIN_MANAGED)) return;
1447
1448     if ((wParam & 0xfff0) == SC_MOVE)
1449     {
1450         if (!(wndPtr->dwStyle & WS_CAPTION)) return;
1451         if (!hittest) 
1452              hittest = NC_StartSizeMove( wndPtr, wParam, &capturePoint );
1453         if (!hittest) return;
1454     }
1455     else  /* SC_SIZE */
1456     {
1457         if (!thickframe) return;
1458         if ( hittest && hittest != HTSYSMENU ) hittest += 2;
1459         else
1460         {
1461             SetCapture32(hwnd);
1462             hittest = NC_StartSizeMove( wndPtr, wParam, &capturePoint );
1463             if (!hittest)
1464             {
1465                 ReleaseCapture();
1466                 return;
1467             }
1468         }
1469     }
1470
1471       /* Get min/max info */
1472
1473     WINPOS_GetMinMaxInfo( wndPtr, NULL, NULL, &minTrack, &maxTrack );
1474     sizingRect = wndPtr->rectWindow;
1475     if (wndPtr->dwStyle & WS_CHILD)
1476         GetClientRect32( wndPtr->parent->hwndSelf, &mouseRect );
1477     else 
1478         SetRect32(&mouseRect, 0, 0, SYSMETRICS_CXSCREEN, SYSMETRICS_CYSCREEN);
1479     if (ON_LEFT_BORDER(hittest))
1480     {
1481         mouseRect.left  = MAX( mouseRect.left, sizingRect.right-maxTrack.x );
1482         mouseRect.right = MIN( mouseRect.right, sizingRect.right-minTrack.x );
1483     }
1484     else if (ON_RIGHT_BORDER(hittest))
1485     {
1486         mouseRect.left  = MAX( mouseRect.left, sizingRect.left+minTrack.x );
1487         mouseRect.right = MIN( mouseRect.right, sizingRect.left+maxTrack.x );
1488     }
1489     if (ON_TOP_BORDER(hittest))
1490     {
1491         mouseRect.top    = MAX( mouseRect.top, sizingRect.bottom-maxTrack.y );
1492         mouseRect.bottom = MIN( mouseRect.bottom,sizingRect.bottom-minTrack.y);
1493     }
1494     else if (ON_BOTTOM_BORDER(hittest))
1495     {
1496         mouseRect.top    = MAX( mouseRect.top, sizingRect.top+minTrack.y );
1497         mouseRect.bottom = MIN( mouseRect.bottom, sizingRect.top+maxTrack.y );
1498     }
1499     SendMessage16( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
1500
1501     if (GetCapture32() != hwnd) SetCapture32( hwnd );    
1502
1503     if (wndPtr->dwStyle & WS_CHILD)
1504     {
1505           /* Retrieve a default cache DC (without using the window style) */
1506         hdc = GetDCEx32( wndPtr->parent->hwndSelf, 0, DCX_CACHE );
1507     }
1508     else
1509     {  /* Grab the server only when moving top-level windows without desktop */
1510         hdc = GetDC32( 0 );
1511         if (rootWindow == DefaultRootWindow(display)) TSXGrabServer( display );
1512     }
1513
1514     if( iconic ) /* create a cursor for dragging */
1515     {
1516         HICON16 hIcon = (wndPtr->class->hIcon) ? wndPtr->class->hIcon
1517                       : (HICON16)SendMessage16( hwnd, WM_QUERYDRAGICON, 0, 0L);
1518         if( hIcon ) hDragCursor =  CURSORICON_IconToCursor( hIcon, TRUE );
1519         if( !hDragCursor ) iconic = FALSE;
1520     }
1521
1522     if( !iconic ) NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1523
1524     while(1)
1525     {
1526         int dx = 0, dy = 0;
1527
1528         MSG_InternalGetMessage( &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE );
1529
1530           /* Exit on button-up, Return, or Esc */
1531         if ((msg.message == WM_LBUTTONUP) ||
1532             ((msg.message == WM_KEYDOWN) && 
1533              ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
1534
1535         if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
1536             continue;  /* We are not interested in other messages */
1537
1538         pt = msg.pt;
1539         if (wndPtr->dwStyle & WS_CHILD)
1540             ScreenToClient16( wndPtr->parent->hwndSelf, &pt );
1541         
1542         if (msg.message == WM_KEYDOWN) switch(msg.wParam)
1543         {
1544             case VK_UP:    pt.y -= 8; break;
1545             case VK_DOWN:  pt.y += 8; break;
1546             case VK_LEFT:  pt.x -= 8; break;
1547             case VK_RIGHT: pt.x += 8; break;            
1548         }
1549
1550         pt.x = MAX( pt.x, mouseRect.left );
1551         pt.x = MIN( pt.x, mouseRect.right );
1552         pt.y = MAX( pt.y, mouseRect.top );
1553         pt.y = MIN( pt.y, mouseRect.bottom );
1554
1555         dx = pt.x - capturePoint.x;
1556         dy = pt.y - capturePoint.y;
1557
1558         if (dx || dy)
1559         {
1560             if( !moved )
1561             {
1562                 moved = TRUE;
1563                 if( iconic ) /* ok, no system popup tracking */
1564                 {
1565                     hOldCursor = SetCursor32(hDragCursor);
1566                     ShowCursor32( TRUE );
1567                     WINPOS_ShowIconTitle( wndPtr, FALSE );
1568                 }
1569             }
1570
1571             if (msg.message == WM_KEYDOWN) SetCursorPos32( pt.x, pt.y );
1572             else
1573             {
1574                 RECT32 newRect = sizingRect;
1575
1576                 if (hittest == HTCAPTION) OffsetRect32( &newRect, dx, dy );
1577                 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
1578                 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
1579                 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
1580                 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
1581                 if( !iconic )
1582                 {
1583                     NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1584                     NC_DrawMovingFrame( hdc, &newRect, thickframe );
1585                 }
1586                 capturePoint = pt;
1587                 sizingRect = newRect;
1588             }
1589         }
1590     }
1591
1592     ReleaseCapture();
1593     if( iconic )
1594     {
1595         if( moved ) /* restore cursors, show icon title later on */
1596         {
1597             ShowCursor32( FALSE );
1598             SetCursor32( hOldCursor );
1599         }
1600         DestroyCursor32( hDragCursor );
1601     }
1602     else
1603         NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1604
1605     if (wndPtr->dwStyle & WS_CHILD)
1606         ReleaseDC32( wndPtr->parent->hwndSelf, hdc );
1607     else
1608     {
1609         ReleaseDC32( 0, hdc );
1610         if (rootWindow == DefaultRootWindow(display)) TSXUngrabServer( display );
1611     }
1612
1613     if (HOOK_IsHooked( WH_CBT ))
1614     {
1615         RECT16* pr = SEGPTR_NEW(RECT16);
1616         if( pr )
1617         {
1618             CONV_RECT32TO16( &sizingRect, pr );
1619             if( HOOK_CallHooks16( WH_CBT, HCBT_MOVESIZE, hwnd,
1620                                 (LPARAM)SEGPTR_GET(pr)) )
1621                 sizingRect = wndPtr->rectWindow;
1622             else
1623                 CONV_RECT16TO32( pr, &sizingRect );
1624             SEGPTR_FREE(pr);
1625         }
1626     }
1627     SendMessage16( hwnd, WM_EXITSIZEMOVE, 0, 0 );
1628     SendMessage16( hwnd, WM_SETVISIBLE, !IsIconic16(hwnd), 0L);
1629
1630     if( moved && !((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
1631     {
1632         /* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
1633         SetWindowPos32( hwnd, 0, sizingRect.left, sizingRect.top,
1634                         sizingRect.right - sizingRect.left,
1635                         sizingRect.bottom - sizingRect.top,
1636                       ( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
1637     }
1638
1639     if( IsWindow32(hwnd) )
1640         if( wndPtr->dwStyle & WS_MINIMIZE )
1641         {
1642             /* Single click brings up the system menu when iconized */
1643
1644             if( !moved ) 
1645             {
1646                  if( wndPtr->dwStyle & WS_SYSMENU ) 
1647                      SendMessage16( hwnd, WM_SYSCOMMAND,
1648                                     SC_MOUSEMENU + HTSYSMENU, *((LPARAM*)&pt));
1649             }
1650             else WINPOS_ShowIconTitle( wndPtr, TRUE );
1651         }
1652 }
1653
1654
1655 /***********************************************************************
1656  *           NC_TrackMinMaxBox
1657  *
1658  * Track a mouse button press on the minimize or maximize box.
1659  */
1660 static void NC_TrackMinMaxBox( HWND32 hwnd, WORD wParam )
1661 {
1662     MSG16 msg;
1663     HDC32 hdc = GetWindowDC32( hwnd );
1664     BOOL32 pressed = TRUE;
1665     void  (*paintButton)(HWND32, HDC16, BOOL32);
1666
1667     SetCapture32( hwnd );
1668     if (wParam == HTMINBUTTON)
1669         paintButton = (TWEAK_Win95Look) ? &NC_DrawMinButton95 : &NC_DrawMinButton;
1670     else
1671         paintButton = (TWEAK_Win95Look) ? &NC_DrawMaxButton95 : &NC_DrawMaxButton;
1672
1673     (*paintButton)( hwnd, hdc, TRUE );
1674
1675     do
1676     {
1677         BOOL32 oldstate = pressed;
1678         MSG_InternalGetMessage( &msg, 0, 0, 0, PM_REMOVE, FALSE );
1679
1680         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1681         if (pressed != oldstate)
1682            (*paintButton)( hwnd, hdc, pressed );
1683     } while (msg.message != WM_LBUTTONUP);
1684
1685     (*paintButton)( hwnd, hdc, FALSE );
1686
1687     ReleaseCapture();
1688     ReleaseDC32( hwnd, hdc );
1689     if (!pressed) return;
1690
1691     if (wParam == HTMINBUTTON) 
1692         SendMessage16( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, *(LONG*)&msg.pt );
1693     else
1694         SendMessage16( hwnd, WM_SYSCOMMAND, 
1695                   IsZoomed32(hwnd) ? SC_RESTORE:SC_MAXIMIZE, *(LONG*)&msg.pt );
1696 }
1697
1698
1699 /***********************************************************************
1700  *           NC_TrackScrollBar
1701  *
1702  * Track a mouse button press on the horizontal or vertical scroll-bar.
1703  */
1704 static void NC_TrackScrollBar( HWND32 hwnd, WPARAM32 wParam, POINT32 pt )
1705 {
1706     MSG16 *msg;
1707     INT32 scrollbar;
1708     WND *wndPtr = WIN_FindWndPtr( hwnd );
1709
1710     if ((wParam & 0xfff0) == SC_HSCROLL)
1711     {
1712         if ((wParam & 0x0f) != HTHSCROLL) return;
1713         scrollbar = SB_HORZ;
1714     }
1715     else  /* SC_VSCROLL */
1716     {
1717         if ((wParam & 0x0f) != HTVSCROLL) return;
1718         scrollbar = SB_VERT;
1719     }
1720
1721     if (!(msg = SEGPTR_NEW(MSG16))) return;
1722     pt.x -= wndPtr->rectWindow.left;
1723     pt.y -= wndPtr->rectWindow.top;
1724     SetCapture32( hwnd );
1725     SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
1726
1727     do
1728     {
1729         GetMessage16( SEGPTR_GET(msg), 0, 0, 0 );
1730         switch(msg->message)
1731         {
1732         case WM_LBUTTONUP:
1733         case WM_MOUSEMOVE:
1734         case WM_SYSTIMER:
1735             pt.x = LOWORD(msg->lParam) + wndPtr->rectClient.left - 
1736               wndPtr->rectWindow.left;
1737             pt.y = HIWORD(msg->lParam) + wndPtr->rectClient.top - 
1738               wndPtr->rectWindow.top;
1739             SCROLL_HandleScrollEvent( hwnd, scrollbar, msg->message, pt );
1740             break;
1741         default:
1742             TranslateMessage16( msg );
1743             DispatchMessage16( msg );
1744             break;
1745         }
1746         if (!IsWindow32( hwnd ))
1747         {
1748             ReleaseCapture();
1749             break;
1750         }
1751     } while (msg->message != WM_LBUTTONUP);
1752     SEGPTR_FREE(msg);
1753 }
1754
1755 /***********************************************************************
1756  *           NC_HandleNCLButtonDown
1757  *
1758  * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1759  */
1760 LONG NC_HandleNCLButtonDown( WND* pWnd, WPARAM16 wParam, LPARAM lParam )
1761 {
1762     HWND32 hwnd = pWnd->hwndSelf;
1763
1764     switch(wParam)  /* Hit test */
1765     {
1766     case HTCAPTION:
1767          hwnd = WIN_GetTopParent(hwnd);
1768
1769          if( WINPOS_SetActiveWindow(hwnd, TRUE, TRUE) || (GetActiveWindow32() == hwnd) )
1770                 SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1771          break;
1772
1773     case HTSYSMENU:
1774          if( pWnd->dwStyle & WS_SYSMENU )
1775          {
1776              if( !(pWnd->dwStyle & WS_MINIMIZE) )
1777              {
1778                 HDC32 hDC = GetWindowDC32(hwnd);
1779                 if( TWEAK_Win95Look)
1780                     NC_DrawSysButton95( hwnd, hDC, TRUE );
1781                 else
1782                     NC_DrawSysButton( hwnd, hDC, TRUE );
1783                 ReleaseDC32( hwnd, hDC );
1784              }
1785              SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam );
1786          }
1787          break;
1788
1789     case HTMENU:
1790         SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1791         break;
1792
1793     case HTHSCROLL:
1794         SendMessage16( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1795         break;
1796
1797     case HTVSCROLL:
1798         SendMessage16( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1799         break;
1800
1801     case HTMINBUTTON:
1802     case HTMAXBUTTON:
1803         NC_TrackMinMaxBox( hwnd, wParam );
1804         break;
1805
1806     case HTLEFT:
1807     case HTRIGHT:
1808     case HTTOP:
1809     case HTTOPLEFT:
1810     case HTTOPRIGHT:
1811     case HTBOTTOM:
1812     case HTBOTTOMLEFT:
1813     case HTBOTTOMRIGHT:
1814         /* make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU */
1815         SendMessage16( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
1816         break;
1817
1818     case HTBORDER:
1819         break;
1820     }
1821     return 0;
1822 }
1823
1824
1825 /***********************************************************************
1826  *           NC_HandleNCLButtonDblClk
1827  *
1828  * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1829  */
1830 LONG NC_HandleNCLButtonDblClk( WND *pWnd, WPARAM16 wParam, LPARAM lParam )
1831 {
1832     /*
1833      * if this is an icon, send a restore since we are handling
1834      * a double click
1835      */
1836     if (pWnd->dwStyle & WS_MINIMIZE)
1837     {
1838         SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_RESTORE, lParam );
1839         return 0;
1840     } 
1841
1842     switch(wParam)  /* Hit test */
1843     {
1844     case HTCAPTION:
1845         /* stop processing if WS_MAXIMIZEBOX is missing */
1846         if (pWnd->dwStyle & WS_MAXIMIZEBOX)
1847             SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND,
1848                       (pWnd->dwStyle & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE,
1849                       lParam );
1850         break;
1851
1852     case HTSYSMENU:
1853         if (!(pWnd->class->style & CS_NOCLOSE))
1854             SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, lParam );
1855         break;
1856
1857     case HTHSCROLL:
1858         SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL,
1859                        lParam );
1860         break;
1861
1862     case HTVSCROLL:
1863         SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL,
1864                        lParam );
1865         break;
1866     }
1867     return 0;
1868 }
1869
1870
1871 /***********************************************************************
1872  *           NC_HandleSysCommand
1873  *
1874  * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1875  */
1876 LONG NC_HandleSysCommand( HWND32 hwnd, WPARAM16 wParam, POINT16 pt )
1877 {
1878     WND *wndPtr = WIN_FindWndPtr( hwnd );
1879     POINT32 pt32;
1880     UINT16 uCommand = wParam & 0xFFF0;
1881
1882     TRACE(nonclient, "Handling WM_SYSCOMMAND %x %d,%d\n", 
1883                       wParam, pt.x, pt.y );
1884
1885     if (wndPtr->dwStyle & WS_CHILD && uCommand != SC_KEYMENU )
1886         ScreenToClient16( wndPtr->parent->hwndSelf, &pt );
1887
1888     switch (uCommand)
1889     {
1890     case SC_SIZE:
1891     case SC_MOVE:
1892         NC_DoSizeMove( hwnd, wParam, pt );
1893         break;
1894
1895     case SC_MINIMIZE:
1896         ShowWindow32( hwnd, SW_MINIMIZE ); 
1897         break;
1898
1899     case SC_MAXIMIZE:
1900         ShowWindow32( hwnd, SW_MAXIMIZE );
1901         break;
1902
1903     case SC_RESTORE:
1904         ShowWindow32( hwnd, SW_RESTORE );
1905         break;
1906
1907     case SC_CLOSE:
1908         return SendMessage16( hwnd, WM_CLOSE, 0, 0 );
1909
1910     case SC_VSCROLL:
1911     case SC_HSCROLL:
1912         CONV_POINT16TO32( &pt, &pt32 );
1913         NC_TrackScrollBar( hwnd, wParam, pt32 );
1914         break;
1915
1916     case SC_MOUSEMENU:
1917         CONV_POINT16TO32( &pt, &pt32 );
1918         MENU_TrackMouseMenuBar( wndPtr, wParam & 0x000F, pt32 );
1919         break;
1920
1921     case SC_KEYMENU:
1922         MENU_TrackKbdMenuBar( wndPtr , wParam , pt.x );
1923         break;
1924         
1925     case SC_TASKLIST:
1926         WinExec32( "taskman.exe", SW_SHOWNORMAL ); 
1927         break;
1928
1929     case SC_SCREENSAVE:
1930         if (wParam == SC_ABOUTWINE)
1931             ShellAbout32A(hwnd,"Wine", WINE_RELEASE_INFO, 0);
1932         break;
1933   
1934     case SC_HOTKEY:
1935     case SC_ARRANGE:
1936     case SC_NEXTWINDOW:
1937     case SC_PREVWINDOW:
1938         /* FIXME: unimplemented */
1939         break;
1940     }
1941     return 0;
1942 }