Release 961013
[wine] / windows / nonclient.c
1 /*
2  * Non-client area window functions
3  *
4  * Copyright 1994 Alexandre Julliard
5  *
6  */
7
8 #include "win.h"
9 #include "message.h"
10 #include "sysmetrics.h"
11 #include "user.h"
12 #include "heap.h"
13 #include "shell.h"
14 #include "dialog.h"
15 #include "syscolor.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 "stddebug.h"
25 #include "debug.h"
26 #include "options.h"
27
28
29 static HBITMAP16 hbitmapClose = 0;
30 static HBITMAP16 hbitmapMinimize = 0;
31 static HBITMAP16 hbitmapMinimizeD = 0;
32 static HBITMAP16 hbitmapMaximize = 0;
33 static HBITMAP16 hbitmapMaximizeD = 0;
34 static HBITMAP16 hbitmapRestore = 0;
35 static HBITMAP16 hbitmapRestoreD = 0;
36
37 #define SC_ABOUTWINE            (SC_SCREENSAVE+1)
38
39   /* Some useful macros */
40 #define HAS_DLGFRAME(style,exStyle) \
41     (((exStyle) & WS_EX_DLGMODALFRAME) || \
42      (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
43
44 #define HAS_THICKFRAME(style) \
45     (((style) & WS_THICKFRAME) && \
46      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
47
48 #define HAS_MENU(w)  (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
49
50 #define ON_LEFT_BORDER(hit) \
51  (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
52 #define ON_RIGHT_BORDER(hit) \
53  (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
54 #define ON_TOP_BORDER(hit) \
55  (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
56 #define ON_BOTTOM_BORDER(hit) \
57  (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
58
59 /***********************************************************************
60  *           NC_AdjustRect
61  *
62  * Compute the size of the window rectangle from the size of the
63  * client rectangle.
64  */
65 static void NC_AdjustRect(LPRECT16 rect, DWORD style, BOOL menu, DWORD exStyle)
66 {
67     if(style & WS_ICONIC) return;
68     /* Decide if the window will be managed (see CreateWindowEx) */
69     if (!(Options.managed && !(style & WS_CHILD) &&
70           ((style & (WS_DLGFRAME | WS_THICKFRAME)) ||
71            (exStyle & WS_EX_DLGMODALFRAME))))
72     {
73         if (HAS_DLGFRAME( style, exStyle ))
74             InflateRect16(rect, SYSMETRICS_CXDLGFRAME, SYSMETRICS_CYDLGFRAME );
75         else
76         {
77             if (HAS_THICKFRAME(style))
78                 InflateRect16( rect, SYSMETRICS_CXFRAME, SYSMETRICS_CYFRAME );
79             if (style & WS_BORDER)
80                 InflateRect16( rect, SYSMETRICS_CXBORDER, SYSMETRICS_CYBORDER);
81         }
82
83         if ((style & WS_CAPTION) == WS_CAPTION)
84             rect->top -= SYSMETRICS_CYCAPTION - SYSMETRICS_CYBORDER;
85     }
86     if (menu) rect->top -= SYSMETRICS_CYMENU + SYSMETRICS_CYBORDER;
87
88     if (style & WS_VSCROLL) rect->right  += SYSMETRICS_CXVSCROLL;
89     if (style & WS_HSCROLL) rect->bottom += SYSMETRICS_CYHSCROLL;
90 }
91
92
93 /***********************************************************************
94  *           AdjustWindowRect16    (USER.102)
95  */
96 BOOL16 AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
97 {
98     return AdjustWindowRectEx16( rect, style, menu, 0 );
99 }
100
101
102 /***********************************************************************
103  *           AdjustWindowRect32    (USER32.)
104  */
105 BOOL32 AdjustWindowRect32( LPRECT32 rect, DWORD style, BOOL32 menu )
106 {
107     return AdjustWindowRectEx32( rect, style, menu, 0 );
108 }
109
110
111 /***********************************************************************
112  *           AdjustWindowRectEx16    (USER.454)
113  */
114 BOOL16 AdjustWindowRectEx16( LPRECT16 rect, DWORD style,
115                              BOOL16 menu, DWORD exStyle )
116 {
117       /* Correct the window style */
118
119     if (!(style & (WS_POPUP | WS_CHILD)))  /* Overlapped window */
120         style |= WS_CAPTION;
121     style &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME);
122     exStyle &= WS_EX_DLGMODALFRAME;
123     if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
124
125     dprintf_nonclient(stddeb, "AdjustWindowRectEx: (%d,%d)-(%d,%d) %08lx %d %08lx\n",
126                       rect->left, rect->top, rect->right, rect->bottom,
127                       style, menu, exStyle );
128
129     NC_AdjustRect( rect, style, menu, exStyle );
130     return TRUE;
131 }
132
133
134 /***********************************************************************
135  *           AdjustWindowRectEx32    (USER32.)
136  */
137 BOOL32 AdjustWindowRectEx32( LPRECT32 rect, DWORD style,
138                              BOOL32 menu, DWORD exStyle )
139 {
140     RECT16 rect16;
141     BOOL32 ret;
142
143     CONV_RECT32TO16( rect, &rect16 );
144     ret = AdjustWindowRectEx16( &rect16, style, (BOOL16)menu, exStyle );
145     CONV_RECT16TO32( &rect16, rect );
146     return ret;
147 }
148
149
150 /*******************************************************************
151  *         NC_GetMinMaxInfo
152  *
153  * Get the minimized and maximized information for a window.
154  */
155 void NC_GetMinMaxInfo( HWND hwnd, POINT16 *maxSize, POINT16 *maxPos,
156                        POINT16 *minTrack, POINT16 *maxTrack )
157 {
158     MINMAXINFO16 *MinMax;
159     short xinc, yinc;
160     WND *wndPtr = WIN_FindWndPtr( hwnd );
161
162     if (!(MinMax = SEGPTR_NEW(MINMAXINFO16))) return;
163
164       /* Compute default values */
165
166     MinMax->ptMaxSize.x = SYSMETRICS_CXSCREEN;
167     MinMax->ptMaxSize.y = SYSMETRICS_CYSCREEN;
168     MinMax->ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
169     MinMax->ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
170     MinMax->ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
171     MinMax->ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
172
173     if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
174     else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
175     {
176         xinc = SYSMETRICS_CXDLGFRAME;
177         yinc = SYSMETRICS_CYDLGFRAME;
178     }
179     else
180     {
181         xinc = yinc = 0;
182         if (HAS_THICKFRAME(wndPtr->dwStyle))
183         {
184             xinc += SYSMETRICS_CXFRAME;
185             yinc += SYSMETRICS_CYFRAME;
186         }
187         if (wndPtr->dwStyle & WS_BORDER)
188         {
189             xinc += SYSMETRICS_CXBORDER;
190             yinc += SYSMETRICS_CYBORDER;
191         }
192     }
193     MinMax->ptMaxSize.x += 2 * xinc;
194     MinMax->ptMaxSize.y += 2 * yinc;
195
196     /* Note: The '+' in the following test should really be a ||, but
197      * that would cause gcc-2.7.0 to generate incorrect code.
198      */
199     if ((wndPtr->ptMaxPos.x != -1) + (wndPtr->ptMaxPos.y != -1))
200         MinMax->ptMaxPosition = wndPtr->ptMaxPos;
201     else
202     {
203         MinMax->ptMaxPosition.x = -xinc;
204         MinMax->ptMaxPosition.y = -yinc;
205     }
206
207     SendMessage16( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)SEGPTR_GET(MinMax) );
208
209       /* Some sanity checks */
210
211     dprintf_nonclient(stddeb, 
212                       "NC_GetMinMaxInfo: %d %d / %d %d / %d %d / %d %d\n",
213                       MinMax->ptMaxSize.x, MinMax->ptMaxSize.y,
214                       MinMax->ptMaxPosition.x, MinMax->ptMaxPosition.y,
215                       MinMax->ptMaxTrackSize.x, MinMax->ptMaxTrackSize.y,
216                       MinMax->ptMinTrackSize.x, MinMax->ptMinTrackSize.y);
217     MinMax->ptMaxTrackSize.x = MAX( MinMax->ptMaxTrackSize.x,
218                                    MinMax->ptMinTrackSize.x );
219     MinMax->ptMaxTrackSize.y = MAX( MinMax->ptMaxTrackSize.y,
220                                    MinMax->ptMinTrackSize.y );
221     
222     if (maxSize) *maxSize = MinMax->ptMaxSize;
223     if (maxPos) *maxPos = MinMax->ptMaxPosition;
224     if (minTrack) *minTrack = MinMax->ptMinTrackSize;
225     if (maxTrack) *maxTrack = MinMax->ptMaxTrackSize;
226     SEGPTR_FREE(MinMax);
227 }
228
229
230 /***********************************************************************
231  *           NC_HandleNCCalcSize
232  *
233  * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
234  */
235 LONG NC_HandleNCCalcSize( WND *pWnd, RECT16 *winRect )
236 {
237     RECT16 tmpRect = { 0, 0, 0, 0 };
238     LONG result = 0;
239
240     if (pWnd->class->style & CS_VREDRAW) result |= WVR_VREDRAW;
241     if (pWnd->class->style & CS_HREDRAW) result |= WVR_HREDRAW;
242
243     if( !( pWnd->dwStyle & WS_MINIMIZE ) )
244     {
245       NC_AdjustRect( &tmpRect, pWnd->dwStyle, FALSE, pWnd->dwExStyle );
246       winRect->left   -= tmpRect.left;
247       winRect->top    -= tmpRect.top;
248       winRect->right  -= tmpRect.right;
249       winRect->bottom -= tmpRect.bottom;
250
251       if (HAS_MENU(pWnd))
252       {
253         winRect->top += MENU_GetMenuBarHeight( pWnd->hwndSelf,
254                                                winRect->right - winRect->left,
255                                               -tmpRect.left, -tmpRect.top ) + 1;
256       }
257     }
258     return result;
259 }
260
261
262 /***********************************************************************
263  *           NC_GetInsideRect
264  *
265  * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
266  * but without the borders (if any).
267  * The rectangle is in window coordinates (for drawing with GetWindowDC()).
268  */
269 static void NC_GetInsideRect( HWND hwnd, RECT16 *rect )
270 {
271     WND * wndPtr = WIN_FindWndPtr( hwnd );
272
273     rect->top    = rect->left = 0;
274     rect->right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
275     rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
276
277     if (wndPtr->dwStyle & WS_ICONIC) return;  /* No border to remove */
278     if (wndPtr->flags & WIN_MANAGED) return;
279
280       /* Remove frame from rectangle */
281     if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
282     {
283         InflateRect16( rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
284         if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
285             InflateRect16( rect, -1, 0 );
286     }
287     else
288     {
289         if (HAS_THICKFRAME( wndPtr->dwStyle ))
290             InflateRect16( rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
291         if (wndPtr->dwStyle & WS_BORDER)
292             InflateRect16( rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
293     }
294 }
295
296
297 /***********************************************************************
298  *           NC_HandleNCHitTest
299  *
300  * Handle a WM_NCHITTEST message. Called from DefWindowProc().
301  */
302 LONG NC_HandleNCHitTest( HWND hwnd, POINT16 pt )
303 {
304     RECT16 rect;
305     WND *wndPtr = WIN_FindWndPtr( hwnd );
306     if (!wndPtr) return HTERROR;
307
308     dprintf_nonclient(stddeb, "NC_HandleNCHitTest: hwnd=%04x pt=%d,%d\n",
309                       hwnd, pt.x, pt.y );
310
311     GetWindowRect16( hwnd, &rect );
312     if (!PtInRect16( &rect, pt )) return HTNOWHERE;
313
314     if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
315
316     if (!(wndPtr->flags & WIN_MANAGED))
317     {
318         /* Check borders */
319         if (HAS_THICKFRAME( wndPtr->dwStyle ))
320         {
321             InflateRect16( &rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
322             if (wndPtr->dwStyle & WS_BORDER)
323                 InflateRect16(&rect,-SYSMETRICS_CXBORDER,-SYSMETRICS_CYBORDER);
324             if (!PtInRect16( &rect, pt ))
325             {
326                 /* Check top sizing border */
327                 if (pt.y < rect.top)
328                 {
329                     if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTTOPLEFT;
330                     if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTTOPRIGHT;
331                     return HTTOP;
332                 }
333                 /* Check bottom sizing border */
334                 if (pt.y >= rect.bottom)
335                 {
336                     if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTBOTTOMLEFT;
337                     if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTBOTTOMRIGHT;
338                     return HTBOTTOM;
339                 }
340                 /* Check left sizing border */
341                 if (pt.x < rect.left)
342                 {
343                     if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPLEFT;
344                     if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMLEFT;
345                     return HTLEFT;
346                 }
347                 /* Check right sizing border */
348                 if (pt.x >= rect.right)
349                 {
350                     if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPRIGHT;
351                     if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMRIGHT;
352                     return HTRIGHT;
353                 }
354             }
355         }
356         else  /* No thick frame */
357         {
358             if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
359                 InflateRect16(&rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
360             else if (wndPtr->dwStyle & WS_BORDER)
361                 InflateRect16(&rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER);
362             if (!PtInRect16( &rect, pt )) return HTBORDER;
363         }
364
365         /* Check caption */
366
367         if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
368         {
369             rect.top += SYSMETRICS_CYCAPTION - 1;
370             if (!PtInRect16( &rect, pt ))
371             {
372                 /* Check system menu */
373                 if (wndPtr->dwStyle & WS_SYSMENU)
374                     rect.left += SYSMETRICS_CXSIZE;
375                 if (pt.x <= rect.left) return HTSYSMENU;
376                 /* Check maximize box */
377                 if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
378                     rect.right -= SYSMETRICS_CXSIZE + 1;
379                 if (pt.x >= rect.right) return HTMAXBUTTON;
380                 /* Check minimize box */
381                 if (wndPtr->dwStyle & WS_MINIMIZEBOX)
382                     rect.right -= SYSMETRICS_CXSIZE + 1;
383                 if (pt.x >= rect.right) return HTMINBUTTON;
384                 return HTCAPTION;
385             }
386         }
387     }
388
389       /* Check client area */
390
391     ScreenToClient16( hwnd, &pt );
392     GetClientRect16( hwnd, &rect );
393     if (PtInRect16( &rect, pt )) return HTCLIENT;
394
395       /* Check vertical scroll bar */
396
397     if (wndPtr->dwStyle & WS_VSCROLL)
398     {
399         rect.right += SYSMETRICS_CXVSCROLL;
400         if (PtInRect16( &rect, pt )) return HTVSCROLL;
401     }
402
403       /* Check horizontal scroll bar */
404
405     if (wndPtr->dwStyle & WS_HSCROLL)
406     {
407         rect.bottom += SYSMETRICS_CYHSCROLL;
408         if (PtInRect16( &rect, pt ))
409         {
410               /* Check size box */
411             if ((wndPtr->dwStyle & WS_VSCROLL) &&
412                 (pt.x >= rect.right - SYSMETRICS_CXVSCROLL))
413                 return HTSIZE;
414             return HTHSCROLL;
415         }
416     }
417
418       /* Check menu bar */
419
420     if (HAS_MENU(wndPtr))
421     {
422         if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
423             return HTMENU;
424     }
425
426       /* Should never get here */
427     return HTERROR;
428 }
429
430
431 /***********************************************************************
432  *           NC_DrawSysButton
433  */
434 void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
435 {
436     RECT16 rect;
437     HDC hdcMem;
438     HBITMAP16 hbitmap;
439     WND *wndPtr = WIN_FindWndPtr( hwnd );
440
441     if( !(wndPtr->flags & WIN_MANAGED) )
442     {
443       NC_GetInsideRect( hwnd, &rect );
444       hdcMem = CreateCompatibleDC( hdc );
445       hbitmap = SelectObject( hdcMem, hbitmapClose );
446       BitBlt( hdc, rect.left, rect.top, SYSMETRICS_CXSIZE, SYSMETRICS_CYSIZE,
447               hdcMem, (wndPtr->dwStyle & WS_CHILD) ? SYSMETRICS_CXSIZE : 0, 0,
448               down ? NOTSRCCOPY : SRCCOPY );
449       SelectObject( hdcMem, hbitmap );
450       DeleteDC( hdcMem );
451     }
452 }
453
454
455 /***********************************************************************
456  *           NC_DrawMaxButton
457  */
458 static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
459 {
460     RECT16 rect;
461     WND *wndPtr = WIN_FindWndPtr( hwnd );
462
463     if( !(wndPtr->flags & WIN_MANAGED) )
464     {
465       NC_GetInsideRect( hwnd, &rect );
466       GRAPH_DrawBitmap( hdc, (IsZoomed(hwnd) ?
467                              (down ? hbitmapRestoreD : hbitmapRestore) :
468                              (down ? hbitmapMaximizeD : hbitmapMaximize)),
469                         rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
470                         0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
471     }
472 }
473
474
475 /***********************************************************************
476  *           NC_DrawMinButton
477  */
478 static void NC_DrawMinButton( HWND hwnd, HDC hdc, BOOL down )
479 {
480     RECT16 rect;
481     WND *wndPtr = WIN_FindWndPtr( hwnd );
482
483     if( !(wndPtr->flags & WIN_MANAGED) )
484     {
485       NC_GetInsideRect( hwnd, &rect );
486       if (wndPtr->dwStyle & WS_MAXIMIZEBOX) rect.right -= SYSMETRICS_CXSIZE + 1;
487       GRAPH_DrawBitmap( hdc, (down ? hbitmapMinimizeD : hbitmapMinimize),
488                         rect.right - SYSMETRICS_CXSIZE - 1, rect.top,
489                         0, 0, SYSMETRICS_CXSIZE+1, SYSMETRICS_CYSIZE );
490     }
491 }
492
493
494 /***********************************************************************
495  *           NC_DrawFrame
496  *
497  * Draw a window frame inside the given rectangle, and update the rectangle.
498  * The correct pen for the frame must be selected in the DC.
499  */
500 static void NC_DrawFrame( HDC hdc, RECT16 *rect, BOOL dlgFrame, BOOL active )
501 {
502     short width, height, tmp;
503
504     if (dlgFrame)
505     {
506         width = SYSMETRICS_CXDLGFRAME - 1;
507         height = SYSMETRICS_CYDLGFRAME - 1;
508         SelectObject( hdc, active ? sysColorObjects.hbrushActiveCaption :
509                                     sysColorObjects.hbrushInactiveCaption );
510     }
511     else
512     {
513         width = SYSMETRICS_CXFRAME - 1;
514         height = SYSMETRICS_CYFRAME - 1;
515         SelectObject( hdc, active ? sysColorObjects.hbrushActiveBorder :
516                                     sysColorObjects.hbrushInactiveBorder );
517     }
518
519       /* Draw frame */
520     PatBlt( hdc, rect->left, rect->top,
521             rect->right - rect->left, height, PATCOPY );
522     PatBlt( hdc, rect->left, rect->top,
523             width, rect->bottom - rect->top, PATCOPY );
524     PatBlt( hdc, rect->left, rect->bottom,
525             rect->right - rect->left, -height, PATCOPY );
526     PatBlt( hdc, rect->right, rect->top,
527             -width, rect->bottom - rect->top, PATCOPY );
528
529     if (dlgFrame)
530     {
531         InflateRect16( rect, -width, -height );
532         return;
533     }
534     
535       /* Draw inner rectangle */
536     MoveTo( hdc, rect->left+width, rect->top+height );
537     LineTo( hdc, rect->right-width-1, rect->top+height );
538     LineTo( hdc, rect->right-width-1, rect->bottom-height-1 );
539     LineTo( hdc, rect->left+width, rect->bottom-height-1 );
540     LineTo( hdc, rect->left+width, rect->top+height );
541
542       /* Draw the decorations */
543     tmp = rect->top + SYSMETRICS_CYFRAME + SYSMETRICS_CYSIZE;
544     MoveTo( hdc, rect->left, tmp);
545     LineTo( hdc, rect->left+width, tmp );
546     MoveTo( hdc, rect->right-width-1, tmp );
547     LineTo( hdc, rect->right-1, tmp );
548
549     tmp = rect->bottom - 1 - SYSMETRICS_CYFRAME - SYSMETRICS_CYSIZE;
550     MoveTo( hdc, rect->left, tmp );
551     LineTo( hdc, rect->left+width, tmp );
552     MoveTo( hdc, rect->right-width-1, tmp );
553     LineTo( hdc, rect->right-1, tmp );
554
555     tmp = rect->left + SYSMETRICS_CXFRAME + SYSMETRICS_CXSIZE;
556     MoveTo( hdc, tmp, rect->top );
557     LineTo( hdc, tmp, rect->top+height );
558     MoveTo( hdc, tmp, rect->bottom-height-1 );
559     LineTo( hdc, tmp, rect->bottom-1 );
560
561     tmp = rect->right - 1 - SYSMETRICS_CXFRAME - SYSMETRICS_CYSIZE;
562     MoveTo( hdc, tmp, rect->top );
563     LineTo( hdc, tmp, rect->top+height );
564     MoveTo( hdc, tmp, rect->bottom-height-1 );
565     LineTo( hdc, tmp, rect->bottom-1 );
566
567     InflateRect16( rect, -width-1, -height-1 );
568 }
569
570
571 /***********************************************************************
572  *           NC_DrawMovingFrame
573  *
574  * Draw the frame used when moving or resizing window.
575  */
576 static void NC_DrawMovingFrame( HDC hdc, RECT16 *rect, BOOL thickframe )
577 {
578     if (thickframe)
579     {
580         SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
581         PatBlt( hdc, rect->left, rect->top,
582                 rect->right - rect->left - SYSMETRICS_CXFRAME,
583                 SYSMETRICS_CYFRAME, PATINVERT );
584         PatBlt( hdc, rect->left, rect->top + SYSMETRICS_CYFRAME,
585                 SYSMETRICS_CXFRAME, 
586                 rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
587         PatBlt( hdc, rect->left + SYSMETRICS_CXFRAME, rect->bottom,
588                 rect->right - rect->left - SYSMETRICS_CXFRAME,
589                 -SYSMETRICS_CYFRAME, PATINVERT );
590         PatBlt( hdc, rect->right, rect->top, -SYSMETRICS_CXFRAME, 
591                 rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
592     }
593     else DrawFocusRect16( hdc, rect );
594 }
595
596
597 /***********************************************************************
598  *           NC_DrawCaption
599  *
600  * Draw the window caption.
601  * The correct pen for the window frame must be selected in the DC.
602  */
603 static void NC_DrawCaption( HDC hdc, RECT16 *rect, HWND hwnd,
604                             DWORD style, BOOL active )
605 {
606     RECT16 r = *rect;
607     WND * wndPtr = WIN_FindWndPtr( hwnd );
608     char buffer[256];
609
610     if (wndPtr->flags & WIN_MANAGED) return;
611
612     if (!hbitmapClose)
613     {
614         if (!(hbitmapClose = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_CLOSE) )))
615             return;
616         hbitmapMinimize  = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_REDUCE) );
617         hbitmapMinimizeD = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_REDUCED) );
618         hbitmapMaximize  = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_ZOOM) );
619         hbitmapMaximizeD = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_ZOOMD) );
620         hbitmapRestore   = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_RESTORE) );
621         hbitmapRestoreD  = LoadBitmap16( 0, MAKEINTRESOURCE(OBM_RESTORED) );
622     }
623     
624     if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
625     {
626         HBRUSH16 hbrushOld = SelectObject( hdc, sysColorObjects.hbrushWindow );
627         PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
628         PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
629         PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
630         r.left++;
631         r.right--;
632         SelectObject( hdc, hbrushOld );
633     }
634
635     MoveTo( hdc, r.left, r.bottom );
636     LineTo( hdc, r.right-1, r.bottom );
637
638     if (style & WS_SYSMENU)
639     {
640         NC_DrawSysButton( hwnd, hdc, FALSE );
641         r.left += SYSMETRICS_CXSIZE + 1;
642         MoveTo( hdc, r.left - 1, r.top );
643         LineTo( hdc, r.left - 1, r.bottom );
644     }
645     if (style & WS_MAXIMIZEBOX)
646     {
647         NC_DrawMaxButton( hwnd, hdc, FALSE );
648         r.right -= SYSMETRICS_CXSIZE + 1;
649     }
650     if (style & WS_MINIMIZEBOX)
651     {
652         NC_DrawMinButton( hwnd, hdc, FALSE );
653         r.right -= SYSMETRICS_CXSIZE + 1;
654     }
655
656     FillRect16( hdc, &r, active ? sysColorObjects.hbrushActiveCaption : 
657                                   sysColorObjects.hbrushInactiveCaption );
658
659     if (GetWindowText32A( hwnd, buffer, sizeof(buffer) ))
660     {
661         if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
662         else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
663         SetBkMode( hdc, TRANSPARENT );
664         DrawText16( hdc, buffer, -1, &r,
665                     DT_SINGLELINE | DT_CENTER | DT_VCENTER | DT_NOPREFIX );
666     }
667 }
668
669
670 /***********************************************************************
671  *           NC_DoNCPaint
672  *
673  * Paint the non-client area. clip is currently unused.
674  */
675 void NC_DoNCPaint( HWND hwnd, HRGN32 clip, BOOL suppress_menupaint )
676 {
677     HDC32 hdc;
678     RECT16 rect;
679     BOOL        active;
680
681     WND *wndPtr = WIN_FindWndPtr( hwnd );
682
683     if (!wndPtr || wndPtr->dwStyle & WS_MINIMIZE ||
684         !WIN_IsWindowDrawable( wndPtr, 0 )) return; /* Nothing to do */
685
686     active  = wndPtr->flags & WIN_NCACTIVATED;
687
688     dprintf_nonclient(stddeb, "NC_DoNCPaint: %04x %d\n", hwnd, active );
689
690     if (!(hdc = GetDCEx32( hwnd, 0, DCX_USESTYLE | DCX_WINDOW ))) return;
691
692     if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
693                         wndPtr->rectClient.top-wndPtr->rectWindow.top,
694                         wndPtr->rectClient.right-wndPtr->rectWindow.left,
695                         wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
696         == NULLREGION)
697     {
698         ReleaseDC32( hwnd, hdc );
699         return;
700     }
701
702     rect.top = rect.left = 0;
703     rect.right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
704     rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
705
706     SelectObject( hdc, sysColorObjects.hpenWindowFrame );
707
708     if (!(wndPtr->flags & WIN_MANAGED))
709     {
710         if ((wndPtr->dwStyle & WS_BORDER) || (wndPtr->dwStyle & WS_DLGFRAME) ||
711             (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME))
712         {
713             MoveTo( hdc, 0, 0 );
714             LineTo( hdc, rect.right-1, 0 );
715             LineTo( hdc, rect.right-1, rect.bottom-1 );
716             LineTo( hdc, 0, rect.bottom-1 );
717             LineTo( hdc, 0, 0 );
718             InflateRect16( &rect, -1, -1 );
719         }
720
721         if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle )) 
722             NC_DrawFrame( hdc, &rect, TRUE, active );
723         else if (wndPtr->dwStyle & WS_THICKFRAME)
724             NC_DrawFrame(hdc, &rect, FALSE, active );
725
726         if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
727         {
728             RECT16 r = rect;
729             r.bottom = rect.top + SYSMETRICS_CYSIZE;
730             rect.top += SYSMETRICS_CYSIZE + SYSMETRICS_CYBORDER;
731             NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
732         }
733     }
734
735     if (HAS_MENU(wndPtr))
736     {
737         RECT16 r = rect;
738         r.bottom = rect.top + SYSMETRICS_CYMENU;  /* default height */
739         rect.top += MENU_DrawMenuBar( hdc, &r, hwnd, suppress_menupaint );
740     }
741
742       /* Draw the scroll-bars */
743
744     if (wndPtr->dwStyle & WS_VSCROLL)
745         SCROLL_DrawScrollBar( hwnd, hdc, SB_VERT, TRUE );
746     if (wndPtr->dwStyle & WS_HSCROLL)
747         SCROLL_DrawScrollBar( hwnd, hdc, SB_HORZ, TRUE );
748
749       /* Draw the "size-box" */
750
751     if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL))
752     {
753         RECT16 r = rect;
754         r.left = r.right - SYSMETRICS_CXVSCROLL + 1;
755         r.top  = r.bottom - SYSMETRICS_CYHSCROLL + 1;
756         FillRect16( hdc, &r, sysColorObjects.hbrushScrollbar );
757     }    
758
759     ReleaseDC32( hwnd, hdc );
760 }
761
762
763
764 /***********************************************************************
765  *           NC_HandleNCPaint
766  *
767  * Handle a WM_NCPAINT message. Called from DefWindowProc().
768  */
769 LONG NC_HandleNCPaint( HWND hwnd , HRGN32 clip)
770 {
771     NC_DoNCPaint( hwnd, clip, FALSE );
772     return 0;
773 }
774
775
776 /***********************************************************************
777  *           NC_HandleNCActivate
778  *
779  * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
780  */
781 LONG NC_HandleNCActivate( WND *wndPtr, WPARAM wParam )
782 {
783     WORD wStateChange;
784
785     if( wParam ) wStateChange = !(wndPtr->flags & WIN_NCACTIVATED);
786     else wStateChange = wndPtr->flags & WIN_NCACTIVATED;
787
788     if( wStateChange )
789     {
790       if (wParam) wndPtr->flags |= WIN_NCACTIVATED;
791       else wndPtr->flags &= ~WIN_NCACTIVATED;
792
793       if( wndPtr->dwStyle & WS_MINIMIZE )
794         PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE | RDW_ERASE | RDW_ERASENOW, 0 );
795       else
796         NC_DoNCPaint( wndPtr->hwndSelf, (HRGN32)1, FALSE );
797     }
798     return TRUE;
799 }
800
801
802 /***********************************************************************
803  *           NC_HandleSetCursor
804  *
805  * Handle a WM_SETCURSOR message. Called from DefWindowProc().
806  */
807 LONG NC_HandleSetCursor( HWND hwnd, WPARAM wParam, LPARAM lParam )
808 {
809     if (hwnd != (HWND)wParam) return 0;  /* Don't set the cursor for child windows */
810
811     switch(LOWORD(lParam))
812     {
813     case HTERROR:
814         {
815             WORD msg = HIWORD( lParam );
816             if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
817                 (msg == WM_RBUTTONDOWN))
818                 MessageBeep(0);
819         }
820         break;
821
822     case HTCLIENT:
823         {
824             WND *wndPtr;
825             if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
826             if (wndPtr->class->hCursor)
827             {
828                 SetCursor( wndPtr->class->hCursor );
829                 return TRUE;
830             }
831             else return FALSE;
832         }
833
834     case HTLEFT:
835     case HTRIGHT:
836         return (LONG)SetCursor( LoadCursor16( 0, IDC_SIZEWE ) );
837
838     case HTTOP:
839     case HTBOTTOM:
840         return (LONG)SetCursor( LoadCursor16( 0, IDC_SIZENS ) );
841
842     case HTTOPLEFT:
843     case HTBOTTOMRIGHT: 
844         return (LONG)SetCursor( LoadCursor16( 0, IDC_SIZENWSE ) );
845
846     case HTTOPRIGHT:
847     case HTBOTTOMLEFT:
848         return (LONG)SetCursor( LoadCursor16( 0, IDC_SIZENESW ) );
849     }
850
851     /* Default cursor: arrow */
852     return (LONG)SetCursor( LoadCursor16( 0, IDC_ARROW ) );
853 }
854
855 /***********************************************************************
856  *           NC_GetSysPopupPos
857  */
858 BOOL NC_GetSysPopupPos( WND* wndPtr, RECT16* rect )
859 {
860   if( !wndPtr->hSysMenu ) return FALSE;
861
862   NC_GetInsideRect( wndPtr->hwndSelf, rect );
863   OffsetRect16( rect, wndPtr->rectWindow.left, wndPtr->rectWindow.top );
864   if (wndPtr->dwStyle & WS_CHILD)
865      ClientToScreen16( wndPtr->parent->hwndSelf, (POINT16 *)rect );
866   rect->right = rect->left + SYSMETRICS_CXSIZE;
867   rect->bottom = rect->top + SYSMETRICS_CYSIZE;
868   return TRUE;
869 }
870
871 /***********************************************************************
872  *           NC_TrackSysMenu
873  *
874  * Track a mouse button press on the system menu.
875  */
876 static void NC_TrackSysMenu( HWND hwnd, HDC hdc, POINT16 pt )
877 {
878     RECT16 rect;
879     WND *wndPtr = WIN_FindWndPtr( hwnd );
880     int iconic = wndPtr->dwStyle & WS_MINIMIZE;
881     HMENU16 hmenu;
882     
883     if (!(wndPtr->dwStyle & WS_SYSMENU)) return;
884
885     /* If window has a menu, track the menu bar normally if it not minimized */
886     if (HAS_MENU(wndPtr) && !iconic) MENU_TrackMouseMenuBar( hwnd, pt );
887     else
888     {
889           /* Otherwise track the system menu like a normal popup menu */
890
891         NC_GetSysPopupPos( wndPtr, &rect );
892         if (!iconic) NC_DrawSysButton( hwnd, hdc, TRUE );
893         hmenu = GetSystemMenu(hwnd, 0);
894         MENU_InitSysMenuPopup(hmenu, wndPtr->dwStyle,
895                                     wndPtr->class->style);
896         TrackPopupMenu16( hmenu, TPM_LEFTALIGN | TPM_LEFTBUTTON,
897                           rect.left, rect.bottom, 0, hwnd, &rect );
898         if (!iconic) NC_DrawSysButton( hwnd, hdc, FALSE );
899     }
900 }
901
902
903 /***********************************************************************
904  *           NC_StartSizeMove
905  *
906  * Initialisation of a move or resize, when initiatied from a menu choice.
907  * Return hit test code for caption or sizing border.
908  */
909 static LONG NC_StartSizeMove( HWND hwnd, WPARAM wParam, POINT16 *capturePoint )
910 {
911     LONG hittest = 0;
912     POINT16 pt;
913     MSG16 msg;
914     WND * wndPtr = WIN_FindWndPtr( hwnd );
915
916     if ((wParam & 0xfff0) == SC_MOVE)
917     {
918           /* Move pointer at the center of the caption */
919         RECT16 rect;
920         NC_GetInsideRect( hwnd, &rect );
921         if (wndPtr->dwStyle & WS_SYSMENU)
922             rect.left += SYSMETRICS_CXSIZE + 1;
923         if (wndPtr->dwStyle & WS_MINIMIZEBOX)
924             rect.right -= SYSMETRICS_CXSIZE + 1;
925         if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
926             rect.right -= SYSMETRICS_CXSIZE + 1;
927         pt.x = wndPtr->rectWindow.left + (rect.right - rect.left) / 2;
928         pt.y = wndPtr->rectWindow.top + rect.top + SYSMETRICS_CYSIZE/2;
929         if (wndPtr->dwStyle & WS_CHILD)
930             ClientToScreen16( wndPtr->parent->hwndSelf, &pt );
931         hittest = HTCAPTION;
932     }
933     else  /* SC_SIZE */
934     {
935         SetCapture32(hwnd);
936         while(!hittest)
937         {
938             MSG_InternalGetMessage( &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE );
939             switch(msg.message)
940             {
941             case WM_MOUSEMOVE:
942                 hittest = NC_HandleNCHitTest( hwnd, msg.pt );
943                 pt = msg.pt;
944                 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
945                     hittest = 0;
946                 break;
947
948             case WM_LBUTTONUP:
949                 return 0;
950
951             case WM_KEYDOWN:
952                 switch(msg.wParam)
953                 {
954                 case VK_UP:
955                     hittest = HTTOP;
956                     pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
957                     pt.y = wndPtr->rectWindow.top + SYSMETRICS_CYFRAME / 2;
958                     break;
959                 case VK_DOWN:
960                     hittest = HTBOTTOM;
961                     pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
962                     pt.y = wndPtr->rectWindow.bottom - SYSMETRICS_CYFRAME / 2;
963                     break;
964                 case VK_LEFT:
965                     hittest = HTLEFT;
966                     pt.x = wndPtr->rectWindow.left + SYSMETRICS_CXFRAME / 2;
967                     pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
968                     break;
969                 case VK_RIGHT:
970                     hittest = HTRIGHT;
971                     pt.x = wndPtr->rectWindow.right - SYSMETRICS_CXFRAME / 2;
972                     pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
973                     break;
974                 case VK_RETURN:
975                 case VK_ESCAPE: return 0;
976                 }
977             }
978         }
979     }
980     *capturePoint = pt;
981     SetCursorPos( capturePoint->x, capturePoint->y );
982     NC_HandleSetCursor( hwnd, (WPARAM)hwnd, MAKELONG( hittest, WM_MOUSEMOVE ));
983     return hittest;
984 }
985
986
987 /***********************************************************************
988  *           NC_DoSizeMove
989  *
990  * Perform SC_MOVE and SC_SIZE commands.
991  */
992 static void NC_DoSizeMove( HWND hwnd, WORD wParam, POINT16 pt )
993 {
994     MSG16 msg;
995     LONG hittest;
996     RECT16 sizingRect, mouseRect;
997     HDC32 hdc;
998     BOOL thickframe;
999     POINT16 minTrack, maxTrack, capturePoint = pt;
1000     WND * wndPtr = WIN_FindWndPtr( hwnd );
1001     int moved = 0;
1002
1003     if (IsZoomed(hwnd) || !IsWindowVisible(hwnd) ||
1004         (wndPtr->flags & WIN_MANAGED)) return;
1005     hittest = wParam & 0x0f;
1006     thickframe = HAS_THICKFRAME( wndPtr->dwStyle );
1007
1008     if ((wParam & 0xfff0) == SC_MOVE)
1009     {
1010         if (!(wndPtr->dwStyle & WS_CAPTION)) return;
1011         if (!hittest) hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
1012         if (!hittest) return;
1013     }
1014     else  /* SC_SIZE */
1015     {
1016         if (!thickframe) return;
1017         if (hittest) hittest += HTLEFT-1;
1018         else
1019         {
1020             SetCapture32(hwnd);
1021             hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
1022             if (!hittest)
1023             {
1024                 ReleaseCapture();
1025                 return;
1026             }
1027         }
1028     }
1029
1030       /* Get min/max info */
1031
1032     NC_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
1033     sizingRect = wndPtr->rectWindow;
1034     if (wndPtr->dwStyle & WS_CHILD)
1035         GetClientRect16( wndPtr->parent->hwndSelf, &mouseRect );
1036     else SetRect16(&mouseRect, 0, 0, SYSMETRICS_CXSCREEN, SYSMETRICS_CYSCREEN);
1037     if (ON_LEFT_BORDER(hittest))
1038     {
1039         mouseRect.left  = MAX( mouseRect.left, sizingRect.right-maxTrack.x );
1040         mouseRect.right = MIN( mouseRect.right, sizingRect.right-minTrack.x );
1041     }
1042     else if (ON_RIGHT_BORDER(hittest))
1043     {
1044         mouseRect.left  = MAX( mouseRect.left, sizingRect.left+minTrack.x );
1045         mouseRect.right = MIN( mouseRect.right, sizingRect.left+maxTrack.x );
1046     }
1047     if (ON_TOP_BORDER(hittest))
1048     {
1049         mouseRect.top    = MAX( mouseRect.top, sizingRect.bottom-maxTrack.y );
1050         mouseRect.bottom = MIN( mouseRect.bottom,sizingRect.bottom-minTrack.y);
1051     }
1052     else if (ON_BOTTOM_BORDER(hittest))
1053     {
1054         mouseRect.top    = MAX( mouseRect.top, sizingRect.top+minTrack.y );
1055         mouseRect.bottom = MIN( mouseRect.bottom, sizingRect.top+maxTrack.y );
1056     }
1057     SendMessage16( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
1058
1059     if (GetCapture32() != hwnd) SetCapture32( hwnd );    
1060
1061     if (wndPtr->dwStyle & WS_CHILD)
1062     {
1063           /* Retrieve a default cache DC (without using the window style) */
1064         hdc = GetDCEx32( wndPtr->parent->hwndSelf, 0, DCX_CACHE );
1065     }
1066     else
1067     {  /* Grab the server only when moving top-level windows without desktop */
1068         hdc = GetDC32( 0 );
1069         if (rootWindow == DefaultRootWindow(display)) XGrabServer( display );
1070     }
1071     NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1072
1073     while(1)
1074     {
1075         int dx = 0, dy = 0;
1076
1077         MSG_InternalGetMessage( &msg, 0, 0, MSGF_SIZE, PM_REMOVE, FALSE );
1078
1079           /* Exit on button-up, Return, or Esc */
1080         if ((msg.message == WM_LBUTTONUP) ||
1081             ((msg.message == WM_KEYDOWN) && 
1082              ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
1083
1084         if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
1085             continue;  /* We are not interested in other messages */
1086
1087         pt = msg.pt;
1088         if (wndPtr->dwStyle & WS_CHILD)
1089             ScreenToClient16( wndPtr->parent->hwndSelf, &pt );
1090         
1091         if (msg.message == WM_KEYDOWN) switch(msg.wParam)
1092         {
1093             case VK_UP:    pt.y -= 8; break;
1094             case VK_DOWN:  pt.y += 8; break;
1095             case VK_LEFT:  pt.x -= 8; break;
1096             case VK_RIGHT: pt.x += 8; break;            
1097         }
1098
1099         pt.x = MAX( pt.x, mouseRect.left );
1100         pt.x = MIN( pt.x, mouseRect.right );
1101         pt.y = MAX( pt.y, mouseRect.top );
1102         pt.y = MIN( pt.y, mouseRect.bottom );
1103
1104         dx = pt.x - capturePoint.x;
1105         dy = pt.y - capturePoint.y;
1106
1107         if (dx || dy)
1108         {
1109             moved = 1;
1110             if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
1111             else
1112             {
1113                 RECT16 newRect = sizingRect;
1114
1115                 if (hittest == HTCAPTION) OffsetRect16( &newRect, dx, dy );
1116                 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
1117                 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
1118                 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
1119                 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
1120                 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1121                 NC_DrawMovingFrame( hdc, &newRect, thickframe );
1122                 capturePoint = pt;
1123                 sizingRect = newRect;
1124             }
1125         }
1126     }
1127
1128     NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1129     ReleaseCapture();
1130
1131     if (wndPtr->dwStyle & WS_CHILD)
1132         ReleaseDC32( wndPtr->parent->hwndSelf, hdc );
1133     else
1134     {
1135         ReleaseDC32( 0, hdc );
1136         if (rootWindow == DefaultRootWindow(display)) XUngrabServer( display );
1137     }
1138
1139     if (HOOK_GetHook( WH_CBT, GetTaskQueue(0) ))
1140     {
1141        RECT16* pr = SEGPTR_NEW(RECT16);
1142        if( pr )
1143        {
1144          *pr = sizingRect;
1145           if( HOOK_CallHooks( WH_CBT, HCBT_MOVESIZE, hwnd,
1146                                      (LPARAM)SEGPTR_GET(pr)) )
1147               sizingRect = wndPtr->rectWindow;
1148           else
1149               sizingRect = *pr;
1150           SEGPTR_FREE(pr);
1151        }
1152     }
1153     SendMessage16( hwnd, WM_EXITSIZEMOVE, 0, 0 );
1154     SendMessage16( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
1155
1156     /* Single click brings up the system menu when iconized */
1157
1158     if (!moved && (wndPtr->dwStyle & WS_MINIMIZE))
1159     {
1160         NC_TrackSysMenu( hwnd, hdc, pt );
1161         return;
1162     }
1163
1164       /* If Esc key, don't move the window */
1165     if ((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) return;
1166
1167     if (hittest != HTCAPTION)
1168         SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
1169                      sizingRect.right - sizingRect.left,
1170                      sizingRect.bottom - sizingRect.top,
1171                      SWP_NOACTIVATE | SWP_NOZORDER );
1172     else SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top, 0, 0,
1173                       SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
1174 }
1175
1176
1177 /***********************************************************************
1178  *           NC_TrackMinMaxBox
1179  *
1180  * Track a mouse button press on the minimize or maximize box.
1181  */
1182 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1183 {
1184     MSG16 msg;
1185     HDC32 hdc = GetWindowDC32( hwnd );
1186     BOOL pressed = TRUE;
1187
1188     SetCapture32( hwnd );
1189     if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, TRUE );
1190     else NC_DrawMaxButton( hwnd, hdc, TRUE );
1191
1192     do
1193     {
1194         BOOL oldstate = pressed;
1195         MSG_InternalGetMessage( &msg, 0, 0, 0, PM_REMOVE, FALSE );
1196
1197         pressed = (NC_HandleNCHitTest( hwnd, msg.pt ) == wParam);
1198         if (pressed != oldstate)
1199         {
1200             if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, pressed );
1201             else NC_DrawMaxButton( hwnd, hdc, pressed );            
1202         }
1203     } while (msg.message != WM_LBUTTONUP);
1204
1205     if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, FALSE );
1206     else NC_DrawMaxButton( hwnd, hdc, FALSE );
1207
1208     ReleaseCapture();
1209     ReleaseDC32( hwnd, hdc );
1210     if (!pressed) return;
1211
1212     if (wParam == HTMINBUTTON) 
1213         SendMessage16( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, *(LONG*)&msg.pt );
1214     else
1215         SendMessage16( hwnd, WM_SYSCOMMAND, 
1216                   IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, *(LONG*)&msg.pt );
1217 }
1218
1219
1220 /***********************************************************************
1221  *           NC_TrackScrollBar
1222  *
1223  * Track a mouse button press on the horizontal or vertical scroll-bar.
1224  */
1225 static void NC_TrackScrollBar( HWND32 hwnd, WPARAM32 wParam, POINT32 pt )
1226 {
1227     MSG16 *msg;
1228     INT32 scrollbar;
1229     WND *wndPtr = WIN_FindWndPtr( hwnd );
1230
1231     if ((wParam & 0xfff0) == SC_HSCROLL)
1232     {
1233         if ((wParam & 0x0f) != HTHSCROLL) return;
1234         scrollbar = SB_HORZ;
1235     }
1236     else  /* SC_VSCROLL */
1237     {
1238         if ((wParam & 0x0f) != HTVSCROLL) return;
1239         scrollbar = SB_VERT;
1240     }
1241
1242     if (!(msg = SEGPTR_NEW(MSG16))) return;
1243     pt.x -= wndPtr->rectWindow.left;
1244     pt.y -= wndPtr->rectWindow.top;
1245     SetCapture32( hwnd );
1246     SCROLL_HandleScrollEvent( hwnd, scrollbar, WM_LBUTTONDOWN, pt );
1247
1248     do
1249     {
1250         GetMessage( SEGPTR_GET(msg), 0, 0, 0 );
1251         switch(msg->message)
1252         {
1253         case WM_LBUTTONUP:
1254         case WM_MOUSEMOVE:
1255         case WM_SYSTIMER:
1256             pt.x = LOWORD(msg->lParam) + wndPtr->rectClient.left - 
1257               wndPtr->rectWindow.left;
1258             pt.y = HIWORD(msg->lParam) + wndPtr->rectClient.top - 
1259               wndPtr->rectWindow.top;
1260             SCROLL_HandleScrollEvent( hwnd, scrollbar, msg->message, pt );
1261             break;
1262         default:
1263             TranslateMessage( msg );
1264             DispatchMessage( msg );
1265             break;
1266         }
1267         if (!IsWindow( hwnd ))
1268         {
1269             ReleaseCapture();
1270             break;
1271         }
1272     } while (msg->message != WM_LBUTTONUP);
1273     SEGPTR_FREE(msg);
1274 }
1275
1276 /***********************************************************************
1277  *           NC_HandleNCLButtonDown
1278  *
1279  * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1280  */
1281 LONG NC_HandleNCLButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
1282 {
1283     HDC32 hdc;
1284
1285     switch(wParam)  /* Hit test */
1286     {
1287     case HTCAPTION:
1288         SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1289         break;
1290
1291     case HTSYSMENU:
1292         hdc = GetWindowDC32( hwnd );
1293         NC_TrackSysMenu( hwnd, hdc, MAKEPOINT16(lParam) );
1294         ReleaseDC32( hwnd, hdc );
1295         break;
1296
1297     case HTMENU:
1298         SendMessage16( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1299         break;
1300
1301     case HTHSCROLL:
1302         SendMessage16( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1303         break;
1304
1305     case HTVSCROLL:
1306         SendMessage16( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1307         break;
1308
1309     case HTMINBUTTON:
1310     case HTMAXBUTTON:
1311         NC_TrackMinMaxBox( hwnd, wParam );
1312         break;
1313
1314     case HTLEFT:
1315     case HTRIGHT:
1316     case HTTOP:
1317     case HTTOPLEFT:
1318     case HTTOPRIGHT:
1319     case HTBOTTOM:
1320     case HTBOTTOMLEFT:
1321     case HTBOTTOMRIGHT:
1322         SendMessage16( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - HTLEFT+1, lParam);
1323         break;
1324
1325     case HTBORDER:
1326         break;
1327     }
1328     return 0;
1329 }
1330
1331
1332 /***********************************************************************
1333  *           NC_HandleNCLButtonDblClk
1334  *
1335  * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1336  */
1337 LONG NC_HandleNCLButtonDblClk( WND *pWnd, WPARAM wParam, LPARAM lParam )
1338 {
1339     /*
1340      * if this is an icon, send a restore since we are handling
1341      * a double click
1342      */
1343     if (pWnd->dwStyle & WS_MINIMIZE)
1344     {
1345         SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_RESTORE, lParam );
1346         return 0;
1347     } 
1348
1349     switch(wParam)  /* Hit test */
1350     {
1351     case HTCAPTION:
1352         /* stop processing if WS_MAXIMIZEBOX is missing */
1353         if (pWnd->dwStyle & WS_MAXIMIZEBOX)
1354             SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND,
1355                       (pWnd->dwStyle & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE,
1356                       lParam );
1357         break;
1358
1359     case HTSYSMENU:
1360         if (!(pWnd->class->style & CS_NOCLOSE))
1361             SendMessage16( pWnd->hwndSelf, WM_SYSCOMMAND, SC_CLOSE, lParam );
1362         break;
1363     }
1364     return 0;
1365 }
1366
1367
1368 /***********************************************************************
1369  *           NC_HandleSysCommand
1370  *
1371  * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1372  */
1373 LONG NC_HandleSysCommand( HWND hwnd, WPARAM wParam, POINT16 pt )
1374 {
1375     WND *wndPtr = WIN_FindWndPtr( hwnd );
1376     POINT32 pt32;
1377
1378     dprintf_nonclient(stddeb, "Handling WM_SYSCOMMAND %x %d,%d\n", 
1379                       wParam, pt.x, pt.y );
1380
1381     if (wndPtr->dwStyle & WS_CHILD && wParam != SC_KEYMENU )
1382         ScreenToClient16( wndPtr->parent->hwndSelf, &pt );
1383
1384     switch (wParam & 0xfff0)
1385     {
1386     case SC_SIZE:
1387     case SC_MOVE:
1388         NC_DoSizeMove( hwnd, wParam, pt );
1389         break;
1390
1391     case SC_MINIMIZE:
1392         ShowWindow( hwnd, SW_MINIMIZE ); 
1393         break;
1394
1395     case SC_MAXIMIZE:
1396         ShowWindow( hwnd, SW_MAXIMIZE );
1397         break;
1398
1399     case SC_RESTORE:
1400         ShowWindow( hwnd, SW_RESTORE );
1401         break;
1402
1403     case SC_NEXTWINDOW:
1404     case SC_PREVWINDOW:
1405         break;
1406
1407     case SC_CLOSE:
1408         return SendMessage16( hwnd, WM_CLOSE, 0, 0 );
1409
1410     case SC_VSCROLL:
1411     case SC_HSCROLL:
1412         CONV_POINT16TO32( &pt, &pt32 );
1413         NC_TrackScrollBar( hwnd, wParam, pt32 );
1414         break;
1415
1416     case SC_MOUSEMENU:
1417         MENU_TrackMouseMenuBar( hwnd, pt );
1418         break;
1419
1420     case SC_KEYMENU:
1421         MENU_TrackKbdMenuBar( wndPtr , wParam , pt.x );
1422         break;
1423         
1424     case SC_ARRANGE:
1425         break;
1426
1427     case SC_TASKLIST:
1428         WinExec( "taskman.exe", SW_SHOWNORMAL ); 
1429         break;
1430
1431     case SC_HOTKEY:
1432         break;
1433
1434     case SC_SCREENSAVE:
1435         if (wParam == SC_ABOUTWINE)
1436         {   
1437           extern const char people[];
1438           ShellAbout(hwnd,"WINE",people,0);
1439         }
1440         break;
1441     }
1442     return 0;
1443 }