Release 940722
[wine] / windows / nonclient.c
1 /*
2  * Non-client area window functions
3  *
4  * Copyright 1994 Alexandre Julliard
5  */
6
7 static char Copyright[] = "Copyright  Alexandre Julliard, 1994";
8
9 #include "win.h"
10 #include "class.h"
11 #include "message.h"
12 #include "sysmetrics.h"
13 #include "user.h"
14 #include "scroll.h"
15 #include "menu.h"
16 #include "syscolor.h"
17
18 static HBITMAP hbitmapClose = 0;
19 static HBITMAP hbitmapMDIClose = 0;
20 static HBITMAP hbitmapMinimize = 0;
21 static HBITMAP hbitmapMinimizeD = 0;
22 static HBITMAP hbitmapMaximize = 0;
23 static HBITMAP hbitmapMaximizeD = 0;
24 static HBITMAP hbitmapRestore = 0;
25 static HBITMAP hbitmapRestoreD = 0;
26
27 extern void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
28                             POINT *minTrack, POINT *maxTrack );  /* winpos.c */
29 extern void CURSOR_SetWinCursor( HWND hwnd, HCURSOR hcursor );   /* cursor.c */
30 extern WORD MENU_GetMenuBarHeight( HWND hwnd, WORD menubarWidth,
31                                    int orgX, int orgY );         /* menu.c */
32
33
34   /* Some useful macros */
35 #define HAS_DLGFRAME(style,exStyle) \
36     (((style) & WS_DLGFRAME) && \
37      (((exStyle) & WS_EX_DLGMODALFRAME) || !((style) & WS_BORDER)))
38
39 #define HAS_THICKFRAME(style) \
40     (((style) & WS_THICKFRAME) && \
41      !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
42
43 #define HAS_MENU(w)  (!((w)->dwStyle & WS_CHILD) && ((w)->wIDmenu != 0))
44
45 #define ON_LEFT_BORDER(hit) \
46  (((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
47 #define ON_RIGHT_BORDER(hit) \
48  (((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
49 #define ON_TOP_BORDER(hit) \
50  (((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
51 #define ON_BOTTOM_BORDER(hit) \
52  (((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
53
54 /***********************************************************************
55  *           NC_AdjustRect
56  *
57  * Compute the size of the window rectangle from the size of the
58  * client rectangle.
59  */
60 static void NC_AdjustRect( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
61 {
62     if (HAS_DLGFRAME( style, exStyle ))
63         InflateRect( rect, SYSMETRICS_CXDLGFRAME, SYSMETRICS_CYDLGFRAME );
64     else
65     {
66         if (HAS_THICKFRAME(style))
67             InflateRect( rect, SYSMETRICS_CXFRAME, SYSMETRICS_CYFRAME );
68         if (style & WS_BORDER)
69             InflateRect( rect, SYSMETRICS_CXBORDER, SYSMETRICS_CYBORDER );
70     }
71
72     if ((style & WS_CAPTION) == WS_CAPTION)
73         rect->top -= SYSMETRICS_CYCAPTION - 1;
74     if (menu) rect->top -= SYSMETRICS_CYMENU + 1;
75
76     if (style & WS_VSCROLL) rect->right  += SYSMETRICS_CXVSCROLL;
77     if (style & WS_HSCROLL) rect->bottom += SYSMETRICS_CYHSCROLL;
78 }
79
80
81 /***********************************************************************
82  *           AdjustWindowRect    (USER.102)
83  */
84 void AdjustWindowRect( LPRECT rect, DWORD style, BOOL menu )
85 {
86     AdjustWindowRectEx( rect, style, menu, 0 );
87 }
88
89
90 /***********************************************************************
91  *           AdjustWindowRectEx    (USER.454)
92  */
93 void AdjustWindowRectEx( LPRECT rect, DWORD style, BOOL menu, DWORD exStyle )
94 {
95       /* Correct the window style */
96
97     if (!(style & (WS_POPUP | WS_CHILD)))  /* Overlapped window */
98         style |= WS_CAPTION;
99     if (exStyle & WS_EX_DLGMODALFRAME) style &= ~WS_THICKFRAME;
100
101 #ifdef DEBUG_NONCLIENT
102     printf( "AdjustWindowRectEx: (%d,%d)-(%d,%d) %08x %d %08x\n",
103       rect->left, rect->top, rect->right, rect->bottom, style, menu, exStyle );
104 #endif
105
106     NC_AdjustRect( rect, style, menu, exStyle );
107 }
108
109
110 /***********************************************************************
111  *           NC_HandleNCCalcSize
112  *
113  * Handle a WM_NCCALCSIZE message. Called from DefWindowProc().
114  */
115 LONG NC_HandleNCCalcSize( HWND hwnd, NCCALCSIZE_PARAMS *params )
116 {
117     RECT tmpRect = { 0, 0, 0, 0 };
118     WND *wndPtr = WIN_FindWndPtr( hwnd );    
119
120     if (!wndPtr) return 0;
121
122     NC_AdjustRect( &tmpRect, wndPtr->dwStyle, FALSE, wndPtr->dwExStyle );
123     params->rgrc[0].left   -= tmpRect.left;
124     params->rgrc[0].top    -= tmpRect.top;
125     params->rgrc[0].right  -= tmpRect.right;
126     params->rgrc[0].bottom -= tmpRect.bottom;
127
128     if (HAS_MENU(wndPtr))
129     {
130         params->rgrc[0].top += MENU_GetMenuBarHeight( hwnd,
131                                   params->rgrc[0].right - params->rgrc[0].left,
132                                   -tmpRect.left, -tmpRect.top ) + 1;
133     }
134     return 0;
135 }
136
137
138 /***********************************************************************
139  *           NC_GetInsideRect
140  *
141  * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
142  * but without the borders (if any).
143  * The rectangle is in window coordinates (for drawing with GetWindowDC()).
144  */
145 void NC_GetInsideRect( HWND hwnd, RECT *rect )
146 {
147     WND * wndPtr = WIN_FindWndPtr( hwnd );
148
149     rect->top    = rect->left = 0;
150     rect->right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
151     rect->bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
152
153       /* Remove frame from rectangle */
154     if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
155     {
156         InflateRect( rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
157         if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) InflateRect( rect, -1, 0);
158     }
159     else
160     {
161         if (HAS_THICKFRAME( wndPtr->dwStyle ))
162             InflateRect( rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
163         if (wndPtr->dwStyle & WS_BORDER)
164             InflateRect( rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
165     }
166 }
167
168
169 /***********************************************************************
170  *           NC_InternalNCHitTest
171  *
172  * Perform the hit test calculation, but whithout testing the capture
173  * window.
174  */
175 static LONG NC_InternalNCHitTest( HWND hwnd, POINT pt )
176 {
177     RECT rect;
178     WND *wndPtr = WIN_FindWndPtr( hwnd );
179     if (!wndPtr) return HTERROR;
180
181     GetWindowRect( hwnd, &rect );
182     if (!PtInRect( &rect, pt )) return HTNOWHERE;
183
184       /* Check borders */
185
186     if (HAS_THICKFRAME( wndPtr->dwStyle ))
187     {
188         InflateRect( &rect, -SYSMETRICS_CXFRAME, -SYSMETRICS_CYFRAME );
189         if (wndPtr->dwStyle & WS_BORDER)
190             InflateRect( &rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER );
191         if (!PtInRect( &rect, pt ))
192         {
193               /* Check top sizing border */
194             if (pt.y < rect.top)
195             {
196                 if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTTOPLEFT;
197                 if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTTOPRIGHT;
198                 return HTTOP;
199             }
200               /* Check bottom sizing border */
201             if (pt.y >= rect.bottom)
202             {
203                 if (pt.x < rect.left+SYSMETRICS_CXSIZE) return HTBOTTOMLEFT;
204                 if (pt.x >= rect.right-SYSMETRICS_CXSIZE) return HTBOTTOMRIGHT;
205                 return HTBOTTOM;
206             }
207               /* Check left sizing border */
208             if (pt.x < rect.left)
209             {
210                 if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPLEFT;
211                 if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMLEFT;
212                 return HTLEFT;
213             }
214               /* Check right sizing border */
215             if (pt.x >= rect.right)
216             {
217                 if (pt.y < rect.top+SYSMETRICS_CYSIZE) return HTTOPRIGHT;
218                 if (pt.y >= rect.bottom-SYSMETRICS_CYSIZE) return HTBOTTOMRIGHT;
219                 return HTRIGHT;
220             }
221         }
222     }
223     else  /* No thick frame */
224     {
225         if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
226             InflateRect(&rect, -SYSMETRICS_CXDLGFRAME, -SYSMETRICS_CYDLGFRAME);
227         else if (wndPtr->dwStyle & WS_BORDER)
228             InflateRect(&rect, -SYSMETRICS_CXBORDER, -SYSMETRICS_CYBORDER);
229         if (!PtInRect( &rect, pt )) return HTBORDER;
230     }
231
232       /* Check caption */
233
234     if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
235     {
236         rect.top += SYSMETRICS_CYCAPTION - 1;
237         if (!PtInRect( &rect, pt ))
238         {
239               /* Check system menu */
240             if ((wndPtr->dwStyle & WS_SYSMENU) && (pt.x <= SYSMETRICS_CXSIZE))
241                 return HTSYSMENU;
242               /* Check maximize box */
243             if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
244                 rect.right -= SYSMETRICS_CXSIZE + 1;
245             if (pt.x >= rect.right) return HTMAXBUTTON;
246               /* Check minimize box */
247             if (wndPtr->dwStyle & WS_MINIMIZEBOX)
248                 rect.right -= SYSMETRICS_CXSIZE + 1;
249             if (pt.x >= rect.right) return HTMINBUTTON;
250             return HTCAPTION;
251         }
252     }
253
254       /* Check client area */
255
256     ScreenToClient( hwnd, &pt );
257     GetClientRect( hwnd, &rect );
258     if (PtInRect( &rect, pt )) return HTCLIENT;
259
260       /* Check vertical scroll bar */
261
262     if (wndPtr->dwStyle & WS_VSCROLL)
263     {
264         rect.right += SYSMETRICS_CXVSCROLL;
265         if (PtInRect( &rect, pt )) return HTVSCROLL;
266     }
267
268       /* Check horizontal scroll bar */
269
270     if (wndPtr->dwStyle & WS_HSCROLL)
271     {
272         rect.bottom += SYSMETRICS_CYHSCROLL;
273         if (PtInRect( &rect, pt ))
274         {
275               /* Check size box */
276             if ((wndPtr->dwStyle & WS_VSCROLL) &&
277                 (pt.x >= rect.right - SYSMETRICS_CXVSCROLL))
278                 return HTSIZE;
279             return HTHSCROLL;
280         }
281     }
282
283       /* Check menu bar */
284
285     if (HAS_MENU(wndPtr))
286     {
287         if ((pt.y < 0) && (pt.x >= 0) && (pt.x < rect.right))
288             return HTMENU;
289     }
290
291       /* Should never get here */
292     return HTERROR;
293 }
294
295
296 /***********************************************************************
297  *           NC_HandleNCHitTest
298  *
299  * Handle a WM_NCHITTEST message. Called from DefWindowProc().
300  */
301 LONG NC_HandleNCHitTest( HWND hwnd, POINT pt )
302 {
303 #ifdef DEBUG_NONCLIENT
304     printf( "NC_HandleNCHitTest: hwnd=%x pt=%d,%d\n", hwnd, pt.x, pt.y );
305 #endif
306     if (hwnd == GetCapture()) return HTCLIENT;
307     return NC_InternalNCHitTest( hwnd, pt );
308 }
309
310
311 /***********************************************************************
312  *           NC_DrawSysButton
313  */
314 static void NC_DrawSysButton( HWND hwnd, HDC hdc, BOOL down )
315 {
316     RECT rect;
317     WND *wndPtr = WIN_FindWndPtr( hwnd );
318     HDC hdcMem = CreateCompatibleDC( hdc );
319     if (hdcMem)
320     {
321         NC_GetInsideRect( hwnd, &rect );
322         if (wndPtr->dwStyle & WS_CHILD)
323                 SelectObject( hdcMem, hbitmapMDIClose );
324         else
325                 SelectObject( hdcMem, hbitmapClose );
326         BitBlt( hdc, rect.left, rect.top, SYSMETRICS_CXSIZE,
327                SYSMETRICS_CYSIZE, hdcMem, 1, 1, down ? NOTSRCCOPY : SRCCOPY );
328         DeleteDC( hdcMem );
329     }
330 }
331
332
333 /***********************************************************************
334  *           NC_DrawMaxButton
335  */
336 static void NC_DrawMaxButton( HWND hwnd, HDC hdc, BOOL down )
337 {
338     RECT rect;
339     HDC hdcMem = CreateCompatibleDC( hdc );
340     if (hdcMem)
341     {
342         NC_GetInsideRect( hwnd, &rect );
343         if (IsZoomed(hwnd))
344             SelectObject( hdcMem, down ? hbitmapRestoreD : hbitmapRestore );
345         else SelectObject( hdcMem, down ? hbitmapMaximizeD : hbitmapMaximize );
346         BitBlt( hdc, rect.right - SYSMETRICS_CXSIZE - 1, rect.top - 1,
347               SYSMETRICS_CXSIZE+2, SYSMETRICS_CYSIZE+2, hdcMem, 0, 0, SRCCOPY);
348         DeleteDC( hdcMem );
349     }
350 }
351
352
353 /***********************************************************************
354  *           NC_DrawMinButton
355  */
356 static void NC_DrawMinButton( HWND hwnd, HDC hdc, BOOL down )
357 {
358     RECT rect;
359     WND *wndPtr = WIN_FindWndPtr( hwnd );
360     HDC hdcMem = CreateCompatibleDC( hdc );
361     if (hdcMem)
362     {
363         NC_GetInsideRect( hwnd, &rect );
364         if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
365             rect.right -= SYSMETRICS_CXSIZE + 1;        
366         if (down) SelectObject( hdcMem, hbitmapMinimizeD );
367         else SelectObject( hdcMem, hbitmapMinimize );
368         BitBlt( hdc, rect.right - SYSMETRICS_CXSIZE - 1, rect.top - 1,
369               SYSMETRICS_CXSIZE+2, SYSMETRICS_CYSIZE+2, hdcMem, 0, 0, SRCCOPY);
370         DeleteDC( hdcMem );
371     }
372 }
373
374
375 /***********************************************************************
376  *           NC_DrawFrame
377  *
378  * Draw a window frame inside the given rectangle, and update the rectangle.
379  * The correct pen and brush must be selected in the DC.
380  */
381 static void NC_DrawFrame( HDC hdc, RECT *rect, BOOL dlgFrame )
382 {
383     short width, height, tmp;
384
385     if (dlgFrame)
386     {
387         width = SYSMETRICS_CXDLGFRAME - 1;
388         height = SYSMETRICS_CYDLGFRAME - 1;
389     }
390     else
391     {
392         width = SYSMETRICS_CXFRAME - 1;
393         height = SYSMETRICS_CYFRAME - 1;
394     }
395
396       /* Draw frame */
397     PatBlt( hdc, rect->left, rect->top,
398             rect->right - rect->left, height, PATCOPY );
399     PatBlt( hdc, rect->left, rect->top,
400             width, rect->bottom - rect->top, PATCOPY );
401     PatBlt( hdc, rect->left, rect->bottom,
402             rect->right - rect->left, -height, PATCOPY );
403     PatBlt( hdc, rect->right, rect->top,
404             -width, rect->bottom - rect->top, PATCOPY );
405
406     if (dlgFrame)
407     {
408         InflateRect( rect, -width, -height );
409         return;
410     }
411     
412       /* Draw inner rectangle */
413     MoveTo( hdc, rect->left+width, rect->top+height );
414     LineTo( hdc, rect->right-width-1, rect->top+height );
415     LineTo( hdc, rect->right-width-1, rect->bottom-height-1 );
416     LineTo( hdc, rect->left+width, rect->bottom-height-1 );
417     LineTo( hdc, rect->left+width, rect->top+height );
418
419       /* Draw the decorations */
420     tmp = rect->top + SYSMETRICS_CYFRAME + SYSMETRICS_CYSIZE;
421     MoveTo( hdc, rect->left, tmp);
422     LineTo( hdc, rect->left+width, tmp );
423     MoveTo( hdc, rect->right-width-1, tmp );
424     LineTo( hdc, rect->right-1, tmp );
425
426     tmp = rect->bottom - 1 - SYSMETRICS_CYFRAME - SYSMETRICS_CYSIZE;
427     MoveTo( hdc, rect->left, tmp );
428     LineTo( hdc, rect->left+width, tmp );
429     MoveTo( hdc, rect->right-width-1, tmp );
430     LineTo( hdc, rect->right-1, tmp );
431
432     tmp = rect->left + SYSMETRICS_CXFRAME + SYSMETRICS_CXSIZE;
433     MoveTo( hdc, tmp, rect->top );
434     LineTo( hdc, tmp, rect->top+height );
435     MoveTo( hdc, tmp, rect->bottom-height-1 );
436     LineTo( hdc, tmp, rect->bottom-1 );
437
438     tmp = rect->right - 1 - SYSMETRICS_CXFRAME - SYSMETRICS_CYSIZE;
439     MoveTo( hdc, tmp, rect->top );
440     LineTo( hdc, tmp, rect->top+height );
441     MoveTo( hdc, tmp, rect->bottom-height-1 );
442     LineTo( hdc, tmp, rect->bottom-1 );
443
444     InflateRect( rect, -width-1, -height-1 );
445 }
446
447
448 /***********************************************************************
449  *           NC_DrawMovingFrame
450  *
451  * Draw the frame used when moving or resizing window.
452  */
453 static void NC_DrawMovingFrame( HDC hdc, RECT *rect, BOOL thickframe )
454 {
455     if (thickframe)
456     {
457         SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
458         PatBlt( hdc, rect->left, rect->top,
459                 rect->right - rect->left - SYSMETRICS_CXFRAME,
460                 SYSMETRICS_CYFRAME, PATINVERT );
461         PatBlt( hdc, rect->left, rect->top + SYSMETRICS_CYFRAME,
462                 SYSMETRICS_CXFRAME, 
463                 rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
464         PatBlt( hdc, rect->left + SYSMETRICS_CXFRAME, rect->bottom,
465                 rect->right - rect->left - SYSMETRICS_CXFRAME,
466                 -SYSMETRICS_CYFRAME, PATINVERT );
467         PatBlt( hdc, rect->right, rect->top, -SYSMETRICS_CXFRAME, 
468                 rect->bottom - rect->top - SYSMETRICS_CYFRAME, PATINVERT );
469     }
470     else DrawFocusRect( hdc, rect );
471 }
472
473
474 /***********************************************************************
475  *           NC_DrawCaption
476  *
477  * Draw the window caption.
478  * The correct pen for the window frame must be selected in the DC.
479  */
480 static void NC_DrawCaption( HDC hdc, RECT *rect, HWND hwnd,
481                             DWORD style, BOOL active )
482 {
483     RECT r = *rect;
484     WND * wndPtr = WIN_FindWndPtr( hwnd );
485     char buffer[256];
486
487     if (!hbitmapClose)
488     {
489         if (!(hbitmapClose = LoadBitmap( 0, MAKEINTRESOURCE(OBM_CLOSE) )))
490             return;
491         if (!(hbitmapMDIClose = LoadBitmap( 0, MAKEINTRESOURCE(OBM_OLD_CLOSE) )))
492             return;
493         hbitmapMinimize  = LoadBitmap( 0, MAKEINTRESOURCE(OBM_REDUCE) );
494         hbitmapMinimizeD = LoadBitmap( 0, MAKEINTRESOURCE(OBM_REDUCED) );
495         hbitmapMaximize  = LoadBitmap( 0, MAKEINTRESOURCE(OBM_ZOOM) );
496         hbitmapMaximizeD = LoadBitmap( 0, MAKEINTRESOURCE(OBM_ZOOMD) );
497         hbitmapRestore   = LoadBitmap( 0, MAKEINTRESOURCE(OBM_RESTORE) );
498         hbitmapRestoreD  = LoadBitmap( 0, MAKEINTRESOURCE(OBM_RESTORED) );
499     }
500     
501     if (wndPtr->dwExStyle & WS_EX_DLGMODALFRAME)
502     {
503         HBRUSH hbrushOld = SelectObject( hdc, sysColorObjects.hbrushWindow );
504         PatBlt( hdc, r.left, r.top, 1, r.bottom-r.top+1,PATCOPY );
505         PatBlt( hdc, r.right-1, r.top, 1, r.bottom-r.top+1, PATCOPY );
506         PatBlt( hdc, r.left, r.top-1, r.right-r.left, 1, PATCOPY );
507         r.left++;
508         r.right--;
509         SelectObject( hdc, hbrushOld );
510     }
511
512     MoveTo( hdc, r.left, r.bottom );
513     LineTo( hdc, r.right-1, r.bottom );
514
515     if (style & WS_SYSMENU)
516     {
517         NC_DrawSysButton( hwnd, hdc, FALSE );
518         r.left += SYSMETRICS_CXSIZE + 1;
519         MoveTo( hdc, r.left - 1, r.top );
520         LineTo( hdc, r.left - 1, r.bottom );
521     }
522     if (style & WS_MAXIMIZEBOX)
523     {
524         NC_DrawMaxButton( hwnd, hdc, FALSE );
525         r.right -= SYSMETRICS_CXSIZE + 1;
526     }
527     if (style & WS_MINIMIZEBOX)
528     {
529         NC_DrawMinButton( hwnd, hdc, FALSE );
530         r.right -= SYSMETRICS_CXSIZE + 1;
531     }
532
533     FillRect( hdc, &r, active ? sysColorObjects.hbrushActiveCaption : 
534                                 sysColorObjects.hbrushInactiveCaption );
535
536     if (GetWindowText( hwnd, buffer, 256 ))
537     {
538         if (active) SetTextColor( hdc, GetSysColor( COLOR_CAPTIONTEXT ) );
539         else SetTextColor( hdc, GetSysColor( COLOR_INACTIVECAPTIONTEXT ) );
540         SetBkMode( hdc, TRANSPARENT );
541         DrawText( hdc, buffer, -1, &r, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
542     }
543 }
544
545
546 /***********************************************************************
547  *           NC_DoNCPaint
548  *
549  * Paint the non-client area.
550  * 'hrgn' is the update rgn to use (in client coords) or 1 if no update rgn.
551  */
552 void NC_DoNCPaint( HWND hwnd, HRGN hrgn, BOOL active, BOOL suppress_menupaint )
553 {
554     HDC hdc;
555     RECT rect, rect2;
556
557     WND *wndPtr = WIN_FindWndPtr( hwnd );
558
559 #ifdef DEBUG_NONCLIENT
560     printf( "NC_DoNCPaint: %d %d\n", hwnd, hrgn );
561 #endif
562     if (!wndPtr || !hrgn) return;
563     if ((!(wndPtr->dwStyle & (WS_BORDER | WS_DLGFRAME | WS_THICKFRAME))) ||
564         (!(wndPtr->dwStyle & WS_VISIBLE)))
565         return;  /* Nothing to do! */
566
567     if (hrgn == 1) hdc = GetDCEx( hwnd, 0, DCX_CACHE | DCX_WINDOW );
568     else
569     {
570           /* Make region relative to window area */
571         int xoffset = wndPtr->rectWindow.left - wndPtr->rectClient.left;
572         int yoffset = wndPtr->rectWindow.top - wndPtr->rectClient.top;
573         OffsetRgn( hrgn, -xoffset, -yoffset );
574         hdc = GetDCEx( hwnd, hrgn, DCX_CACHE | DCX_WINDOW | DCX_INTERSECTRGN);
575         OffsetRgn( hrgn, xoffset, yoffset );  /* Restore region */
576     }
577     if (!hdc) return;
578     if (ExcludeVisRect( hdc, wndPtr->rectClient.left-wndPtr->rectWindow.left,
579                         wndPtr->rectClient.top-wndPtr->rectWindow.top,
580                         wndPtr->rectClient.right-wndPtr->rectWindow.left,
581                         wndPtr->rectClient.bottom-wndPtr->rectWindow.top )
582         == NULLREGION)
583     {
584         ReleaseDC( hwnd, hdc );
585         return;
586     }
587
588     rect.top = rect.left = 0;
589     rect.right  = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
590     rect.bottom = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
591
592     SelectObject( hdc, sysColorObjects.hpenWindowFrame );
593     SelectObject( hdc, active ? sysColorObjects.hbrushActiveBorder :
594                                 sysColorObjects.hbrushInactiveBorder );
595
596     if ((wndPtr->dwStyle & WS_BORDER) || (wndPtr->dwStyle & WS_DLGFRAME))
597     {
598         MoveTo( hdc, 0, 0 );
599         LineTo( hdc, rect.right-1, 0 );
600         LineTo( hdc, rect.right-1, rect.bottom-1 );
601         LineTo( hdc, 0, rect.bottom-1 );
602         LineTo( hdc, 0, 0 );
603         InflateRect( &rect, -1, -1 );
604     }
605
606     if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle )) 
607         NC_DrawFrame( hdc, &rect, TRUE );
608     else if (wndPtr->dwStyle & WS_THICKFRAME)
609         NC_DrawFrame(hdc, &rect, FALSE);
610
611     if ((wndPtr->dwStyle & WS_CAPTION) == WS_CAPTION)
612     {
613         RECT r = rect;
614         rect.top += SYSMETRICS_CYSIZE + 1;
615         r.bottom = rect.top - 1;
616         NC_DrawCaption( hdc, &r, hwnd, wndPtr->dwStyle, active );
617     }
618
619     if (HAS_MENU(wndPtr))
620     {
621         LPPOPUPMENU lpMenu = (LPPOPUPMENU) GlobalLock( wndPtr->wIDmenu );
622         RECT r = rect;
623         r.bottom = rect.top + lpMenu->Height;
624         rect.top += lpMenu->Height;
625         StdDrawMenuBar( hdc, &r, lpMenu, suppress_menupaint );
626         GlobalUnlock( wndPtr->wIDmenu );
627     }
628
629     if (wndPtr->dwStyle & (WS_VSCROLL | WS_HSCROLL)) {
630         if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->VScroll != NULL) &&
631             (wndPtr->scroll_flags & 0x0001)) {
632             int bottom = rect.bottom;
633             if ((wndPtr->dwStyle & WS_HSCROLL) && (wndPtr->scroll_flags & 0x0001))
634                         bottom -= SYSMETRICS_CYHSCROLL;
635             SetRect(&rect2, rect.right - SYSMETRICS_CXVSCROLL, 
636                 rect.top, rect.right, bottom); 
637             StdDrawScrollBar(hwnd, hdc, SB_VERT, &rect2, (LPHEADSCROLL)wndPtr->VScroll);
638             }
639         if ((wndPtr->dwStyle & WS_HSCROLL) && wndPtr->HScroll != NULL &&
640             (wndPtr->scroll_flags & 0x0002)) {
641             int right = rect.right;
642             if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->scroll_flags & 0x0001))
643                         right -= SYSMETRICS_CYVSCROLL;
644             SetRect(&rect2, rect.left, rect.bottom - SYSMETRICS_CYHSCROLL,
645                     right, rect.bottom);
646             StdDrawScrollBar(hwnd, hdc, SB_HORZ, &rect2, (LPHEADSCROLL)wndPtr->HScroll);
647             }
648
649         if ((wndPtr->dwStyle & WS_VSCROLL) && (wndPtr->dwStyle & WS_HSCROLL) &&
650             (wndPtr->scroll_flags & 0x0003) == 0x0003) {
651                 RECT r = rect;
652                 r.left = r.right - SYSMETRICS_CXVSCROLL;
653                 r.top  = r.bottom - SYSMETRICS_CYHSCROLL;
654                 FillRect( hdc, &r, sysColorObjects.hbrushScrollbar );
655                 }
656     }    
657
658     ReleaseDC( hwnd, hdc );
659 }
660
661
662 NC_DoNCPaintIcon(HWND hwnd)
663 {
664       WND *wndPtr = WIN_FindWndPtr(hwnd);
665       PAINTSTRUCT ps;
666       HDC hdc;
667       int ret;
668       DC *dc;
669       GC testgc;
670       int s;
671       char buffer[256];
672
673       printf("painting icon\n");
674       if (wndPtr == NULL) {
675               printf("argh, can't find an icon to draw\n");
676               return;
677       }
678       hdc = BeginPaint(hwnd, &ps);
679
680       ret = DrawIcon(hdc, 100/2 - 16, 0, wndPtr->hIcon);
681       printf("ret is %d\n", ret);
682
683       if (s=GetWindowText(hwnd, buffer, 256))
684       {
685           /*SetBkColor(hdc, TRANSPARENT); */
686           TextOut(hdc, 0, 32, buffer, s);
687       }
688       EndPaint(hwnd, &ps);
689
690       printf("done painting icon\n");
691       
692 }
693
694
695 LONG NC_HandleNCPaintIcon( HWND hwnd )
696 {
697     NC_DoNCPaintIcon(hwnd);
698     return 0;
699 }
700
701
702
703 /***********************************************************************
704  *           NC_HandleNCPaint
705  *
706  * Handle a WM_NCPAINT message. Called from DefWindowProc().
707  */
708 LONG NC_HandleNCPaint( HWND hwnd, HRGN hrgn )
709 {
710     NC_DoNCPaint( hwnd, hrgn, hwnd == GetActiveWindow(), FALSE );
711     return 0;
712 }
713
714
715 /***********************************************************************
716  *           NC_HandleNCActivate
717  *
718  * Handle a WM_NCACTIVATE message. Called from DefWindowProc().
719  */
720 LONG NC_HandleNCActivate( HWND hwnd, WORD wParam )
721 {
722     NC_DoNCPaint( hwnd, (HRGN)1, wParam, FALSE );
723     return TRUE;
724 }
725
726
727 /***********************************************************************
728  *           NC_HandleSetCursor
729  *
730  * Handle a WM_SETCURSOR message. Called from DefWindowProc().
731  */
732 LONG NC_HandleSetCursor( HWND hwnd, WORD wParam, LONG lParam )
733 {
734     if (hwnd != wParam) return 0;  /* Don't set the cursor for child windows */
735
736     switch(LOWORD(lParam))
737     {
738     case HTERROR:
739         {
740             WORD msg = HIWORD( lParam );
741             if ((msg == WM_LBUTTONDOWN) || (msg == WM_MBUTTONDOWN) ||
742                 (msg == WM_RBUTTONDOWN))
743                 MessageBeep(0);
744         }
745         break;
746
747     case HTCLIENT:
748         {
749             WND *wndPtr;
750             CLASS *classPtr;
751             if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
752             if (!(classPtr = CLASS_FindClassPtr( wndPtr->hClass ))) break;
753             if (classPtr->wc.hCursor)
754             {
755                 CURSOR_SetWinCursor( hwnd, classPtr->wc.hCursor );
756                 return TRUE;
757             }
758         }
759         break;
760
761     case HTLEFT:
762     case HTRIGHT:
763         CURSOR_SetWinCursor( hwnd, LoadCursor( 0, IDC_SIZEWE ) );
764         return TRUE;
765
766     case HTTOP:
767     case HTBOTTOM:
768         CURSOR_SetWinCursor( hwnd, LoadCursor( 0, IDC_SIZENS ) );
769         return TRUE;
770
771     case HTTOPLEFT:
772     case HTBOTTOMRIGHT: 
773         CURSOR_SetWinCursor( hwnd, LoadCursor( 0, IDC_SIZENWSE ) );
774         return TRUE;
775
776     case HTTOPRIGHT:
777     case HTBOTTOMLEFT:
778         CURSOR_SetWinCursor( hwnd, LoadCursor( 0, IDC_SIZENESW ) );
779         return TRUE;
780     }
781
782     /* Default cursor: arrow */
783     CURSOR_SetWinCursor( hwnd, LoadCursor( 0, IDC_ARROW ) );
784     return TRUE;
785 }
786
787
788 /***********************************************************************
789  *           NC_StartSizeMove
790  *
791  * Initialisation of a move or resize, when initiatied from a menu choice.
792  * Return hit test code for caption or sizing border.
793  */
794 static LONG NC_StartSizeMove( HWND hwnd, WORD wParam, POINT *capturePoint )
795 {
796     LONG hittest = 0;
797     POINT pt;
798     MSG msg;
799     WND * wndPtr = WIN_FindWndPtr( hwnd );
800
801     if ((wParam & 0xfff0) == SC_MOVE)
802     {
803           /* Move pointer at the center of the caption */
804         RECT rect;
805         NC_GetInsideRect( hwnd, &rect );
806         if (wndPtr->dwStyle & WS_SYSMENU)
807             rect.left += SYSMETRICS_CXSIZE + 1;
808         if (wndPtr->dwStyle & WS_MINIMIZEBOX)
809             rect.right -= SYSMETRICS_CXSIZE + 1;
810         if (wndPtr->dwStyle & WS_MAXIMIZEBOX)
811             rect.right -= SYSMETRICS_CXSIZE + 1;
812         pt.x = wndPtr->rectWindow.left + (rect.right - rect.left) / 2;
813         pt.y = wndPtr->rectWindow.top + rect.top + SYSMETRICS_CYSIZE/2;
814         if (wndPtr->dwStyle & WS_CHILD)
815             ClientToScreen( wndPtr->hwndParent, &pt );
816         hittest = HTCAPTION;
817     }
818     else  /* SC_SIZE */
819     {
820         SetCapture(hwnd);
821         while(!hittest)
822         {
823             MSG_GetHardwareMessage( &msg );
824             switch(msg.message)
825             {
826             case WM_MOUSEMOVE:
827                 hittest = NC_InternalNCHitTest( hwnd, msg.pt );
828                 pt = msg.pt;
829                 if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
830                     hittest = 0;
831                 break;
832
833             case WM_LBUTTONUP:
834                 return 0;
835
836             case WM_KEYDOWN:
837                 switch(msg.wParam)
838                 {
839                 case VK_UP:
840                     hittest = HTTOP;
841                     pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
842                     pt.y = wndPtr->rectWindow.top + SYSMETRICS_CYFRAME / 2;
843                     break;
844                 case VK_DOWN:
845                     hittest = HTBOTTOM;
846                     pt.x =(wndPtr->rectWindow.left+wndPtr->rectWindow.right)/2;
847                     pt.y = wndPtr->rectWindow.bottom - SYSMETRICS_CYFRAME / 2;
848                     break;
849                 case VK_LEFT:
850                     hittest = HTLEFT;
851                     pt.x = wndPtr->rectWindow.left + SYSMETRICS_CXFRAME / 2;
852                     pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
853                     break;
854                 case VK_RIGHT:
855                     hittest = HTRIGHT;
856                     pt.x = wndPtr->rectWindow.right - SYSMETRICS_CXFRAME / 2;
857                     pt.y =(wndPtr->rectWindow.top+wndPtr->rectWindow.bottom)/2;
858                     break;
859                 case VK_RETURN:
860                 case VK_ESCAPE: return 0;
861                 }
862             }
863         }
864     }
865     *capturePoint = pt;
866     SetCursorPos( capturePoint->x, capturePoint->y );
867     NC_HandleSetCursor( hwnd, hwnd, MAKELONG( hittest, WM_MOUSEMOVE ));
868     return hittest;
869 }
870
871
872 /***********************************************************************
873  *           NC_DoSizeMove
874  *
875  * Perform SC_MOVE and SC_SIZE commands.
876  */
877 static void NC_DoSizeMove( HWND hwnd, WORD wParam, POINT pt )
878 {
879     MSG msg;
880     LONG hittest;
881     RECT sizingRect, mouseRect;
882     HDC hdc;
883     BOOL thickframe;
884     POINT minTrack, maxTrack, capturePoint = pt;
885     WND * wndPtr = WIN_FindWndPtr( hwnd );
886
887     if (IsZoomed(hwnd) || IsIconic(hwnd) || !IsWindowVisible(hwnd)) return;
888     hittest = wParam & 0x0f;
889     thickframe = HAS_THICKFRAME( wndPtr->dwStyle );
890
891     if ((wParam & 0xfff0) == SC_MOVE)
892     {
893         if (!(wndPtr->dwStyle & WS_CAPTION)) return;
894         if (!hittest) hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
895         if (!hittest) return;
896     }
897     else  /* SC_SIZE */
898     {
899         if (!thickframe) return;
900         if (hittest) hittest += HTLEFT-1;
901         else
902         {
903             SetCapture(hwnd);
904             hittest = NC_StartSizeMove( hwnd, wParam, &capturePoint );
905             if (!hittest)
906             {
907                 ReleaseCapture();
908                 return;
909             }
910         }
911     }
912
913       /* Get min/max info */
914
915     WINPOS_GetMinMaxInfo( hwnd, NULL, NULL, &minTrack, &maxTrack );
916     sizingRect = wndPtr->rectWindow;
917     if (wndPtr->dwStyle & WS_CHILD)
918         GetClientRect( wndPtr->hwndParent, &mouseRect );
919     else SetRect( &mouseRect, 0, 0, SYSMETRICS_CXSCREEN, SYSMETRICS_CYSCREEN );
920     if (ON_LEFT_BORDER(hittest))
921     {
922         mouseRect.left  = max( mouseRect.left, sizingRect.right-maxTrack.x );
923         mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
924     }
925     else if (ON_RIGHT_BORDER(hittest))
926     {
927         mouseRect.left  = max( mouseRect.left, sizingRect.left+minTrack.x );
928         mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
929     }
930     if (ON_TOP_BORDER(hittest))
931     {
932         mouseRect.top    = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
933         mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
934     }
935     else if (ON_BOTTOM_BORDER(hittest))
936     {
937         mouseRect.top    = max( mouseRect.top, sizingRect.top+minTrack.y );
938         mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
939     }
940     SendMessage( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
941
942     if (GetCapture() != hwnd) SetCapture( hwnd );    
943
944     if (wndPtr->dwStyle & WS_CHILD) hdc = GetDC( wndPtr->hwndParent );
945     else
946     {  /* Grab the server only when moving top-level windows without desktop */
947         hdc = GetDC( 0 );
948         if (rootWindow == DefaultRootWindow(display)) XGrabServer( display );
949     }
950     NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
951
952     while(1)
953     {
954         int dx = 0, dy = 0;
955
956         MSG_GetHardwareMessage( &msg );
957
958           /* Exit on button-up, Return, or Esc */
959         if ((msg.message == WM_LBUTTONUP) ||
960             ((msg.message == WM_KEYDOWN) && 
961              ((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
962
963         if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
964             continue;  /* We are not interested in other messages */
965
966         pt = msg.pt;
967         if (wndPtr->dwStyle & WS_CHILD)
968             ScreenToClient( wndPtr->hwndParent, &pt );
969
970         
971         if (msg.message == WM_KEYDOWN) switch(msg.wParam)
972         {
973             case VK_UP:    pt.y -= 8; break;
974             case VK_DOWN:  pt.y += 8; break;
975             case VK_LEFT:  pt.x -= 8; break;
976             case VK_RIGHT: pt.x += 8; break;            
977         }
978
979         pt.x = max( pt.x, mouseRect.left );
980         pt.x = min( pt.x, mouseRect.right );
981         pt.y = max( pt.y, mouseRect.top );
982         pt.y = min( pt.y, mouseRect.bottom );
983
984         dx = pt.x - capturePoint.x;
985         dy = pt.y - capturePoint.y;
986
987         if (dx || dy)
988         {
989             if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
990             else
991             {
992                 RECT newRect = sizingRect;
993
994                 if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
995                 if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
996                 else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
997                 if (ON_TOP_BORDER(hittest)) newRect.top += dy;
998                 else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
999                 NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1000                 NC_DrawMovingFrame( hdc, &newRect, thickframe );
1001                 capturePoint = pt;
1002                 sizingRect = newRect;
1003             }
1004         }
1005     }
1006
1007     NC_DrawMovingFrame( hdc, &sizingRect, thickframe );
1008     ReleaseCapture();
1009     if (wndPtr->dwStyle & WS_CHILD) ReleaseDC( wndPtr->hwndParent, hdc );
1010     else
1011     {
1012         ReleaseDC( 0, hdc );
1013         if (rootWindow == DefaultRootWindow(display)) XUngrabServer( display );
1014     }
1015     SendMessage( hwnd, WM_EXITSIZEMOVE, 0, 0 );
1016
1017       /* If Esc key, don't move the window */
1018     if ((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) return;
1019
1020     if (hittest != HTCAPTION)
1021         SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
1022                      sizingRect.right - sizingRect.left,
1023                      sizingRect.bottom - sizingRect.top,
1024                      SWP_NOACTIVATE | SWP_NOZORDER );
1025     else SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top, 0, 0,
1026                       SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER );
1027 }
1028
1029
1030 /***********************************************************************
1031  *           NC_TrackMinMaxBox
1032  *
1033  * Track a mouse button press on the minimize or maximize box.
1034  */
1035 static void NC_TrackMinMaxBox( HWND hwnd, WORD wParam )
1036 {
1037     MSG msg;
1038     HDC hdc = GetWindowDC( hwnd );
1039     BOOL pressed = TRUE;
1040
1041     SetCapture( hwnd );
1042     if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, TRUE );
1043     else NC_DrawMaxButton( hwnd, hdc, TRUE );
1044
1045     do
1046     {
1047         BOOL oldstate = pressed;
1048         MSG_GetHardwareMessage( &msg );
1049
1050         pressed = (NC_InternalNCHitTest( hwnd, msg.pt ) == wParam);
1051         if (pressed != oldstate)
1052         {
1053             if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, pressed );
1054             else NC_DrawMaxButton( hwnd, hdc, pressed );            
1055         }
1056     } while (msg.message != WM_LBUTTONUP);
1057
1058     if (wParam == HTMINBUTTON) NC_DrawMinButton( hwnd, hdc, FALSE );
1059     else NC_DrawMaxButton( hwnd, hdc, FALSE );
1060
1061     ReleaseCapture();
1062     ReleaseDC( hwnd, hdc );
1063     if (!pressed) return;
1064
1065     if (wParam == HTMINBUTTON) 
1066         SendMessage( hwnd, WM_SYSCOMMAND, SC_MINIMIZE, *(LONG*)&msg.pt );
1067     else
1068         SendMessage( hwnd, WM_SYSCOMMAND, 
1069                   IsZoomed(hwnd) ? SC_RESTORE : SC_MAXIMIZE, *(LONG*)&msg.pt );
1070 }
1071
1072
1073 /***********************************************************************
1074  *           NC_TrackScrollBar
1075  *
1076  * Track a mouse button press on the horizontal or vertical scroll-bar.
1077  */
1078 static void NC_TrackScrollBar( HWND hwnd, WORD wParam, POINT pt )
1079 {
1080     MSG         msg;
1081     WORD        scrollbar;
1082     if ((wParam & 0xfff0) == SC_HSCROLL)
1083     {
1084         if ((wParam & 0x0f) != HTHSCROLL) return;
1085         scrollbar = SB_HORZ;
1086     }
1087     else  /* SC_VSCROLL */
1088     {
1089         if ((wParam & 0x0f) != HTVSCROLL) return;
1090         scrollbar = SB_VERT;
1091     }
1092
1093     ScreenToClient( hwnd, &pt );
1094     ScrollBarButtonDown( hwnd, scrollbar, pt.x, pt.y );
1095     SetCapture( hwnd );
1096
1097     do
1098     {
1099         MSG_GetHardwareMessage( &msg );
1100         ScreenToClient( msg.hwnd, &msg.pt );
1101         switch(msg.message)
1102         {
1103         case WM_LBUTTONUP:
1104             ScrollBarButtonUp( hwnd, scrollbar, msg.pt.x, msg.pt.y );
1105             break;
1106         case WM_MOUSEMOVE:
1107             ScrollBarMouseMove(hwnd, scrollbar, msg.wParam, msg.pt.x,msg.pt.y);
1108             break;
1109         }
1110     } while (msg.message != WM_LBUTTONUP);
1111     ReleaseCapture();
1112 }
1113
1114
1115 /***********************************************************************
1116  *           NC_TrackMouseMenuBar
1117  *
1118  * Track a mouse events for the MenuBar.
1119  */
1120 static void NC_TrackMouseMenuBar( HWND hwnd, WORD wParam, POINT pt )
1121 {
1122     WND         *wndPtr;
1123     LPPOPUPMENU lppop;
1124     MSG         msg;
1125     wndPtr = WIN_FindWndPtr(hwnd);
1126     lppop = (LPPOPUPMENU)GlobalLock(wndPtr->wIDmenu);
1127 #ifdef DEBUG_MENU
1128     printf("NC_TrackMouseMenuBar // wndPtr=%08X lppop=%08X !\n", wndPtr, lppop);
1129 #endif
1130     ScreenToClient(hwnd, &pt);
1131     pt.y += lppop->rect.bottom;
1132     SetCapture(hwnd);
1133     MenuButtonDown(hwnd, lppop, pt.x, pt.y);
1134     GlobalUnlock(wndPtr->wIDmenu);
1135 }
1136
1137
1138 /***********************************************************************
1139  *           NC_HandleNCLButtonDown
1140  *
1141  * Handle a WM_NCLBUTTONDOWN message. Called from DefWindowProc().
1142  */
1143 LONG NC_HandleNCLButtonDown( HWND hwnd, WORD wParam, LONG lParam )
1144 {
1145     HDC hdc = GetWindowDC( hwnd );
1146
1147     switch(wParam)  /* Hit test */
1148     {
1149     case HTCAPTION:
1150         SendMessage( hwnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam );
1151         break;
1152
1153     case HTSYSMENU:
1154         NC_DrawSysButton( hwnd, hdc, TRUE );
1155         NC_TrackSysMenu(hwnd);
1156         break;
1157
1158     case HTMENU:
1159         SendMessage( hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, lParam );
1160         break;
1161
1162     case HTHSCROLL:
1163         SendMessage( hwnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam );
1164         break;
1165
1166     case HTVSCROLL:
1167         SendMessage( hwnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam );
1168         break;
1169
1170     case HTMINBUTTON:
1171     case HTMAXBUTTON:
1172         NC_TrackMinMaxBox( hwnd, wParam );
1173         break;
1174
1175     case HTLEFT:
1176     case HTRIGHT:
1177     case HTTOP:
1178     case HTTOPLEFT:
1179     case HTTOPRIGHT:
1180     case HTBOTTOM:
1181     case HTBOTTOMLEFT:
1182     case HTBOTTOMRIGHT:
1183         SendMessage( hwnd, WM_SYSCOMMAND, SC_SIZE + wParam - HTLEFT+1, lParam);
1184         break;
1185
1186     case HTBORDER:
1187         break;
1188     }
1189
1190     ReleaseDC( hwnd, hdc );
1191     return 0;
1192 }
1193
1194
1195 /***********************************************************************
1196  *           NC_HandleNCLButtonDblClk
1197  *
1198  * Handle a WM_NCLBUTTONDBLCLK message. Called from DefWindowProc().
1199  */
1200 LONG NC_HandleNCLButtonDblClk( HWND hwnd, WORD wParam, LONG lParam )
1201 {
1202     switch(wParam)  /* Hit test */
1203     {
1204     case HTCAPTION:
1205         SendMessage( hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, lParam );
1206         break;
1207
1208     case HTSYSMENU:
1209         SendMessage( hwnd, WM_SYSCOMMAND, SC_CLOSE, lParam );
1210         break;
1211     }
1212     return 0;
1213 }
1214
1215
1216 /***********************************************************************
1217  *           NC_HandleSysCommand
1218  *
1219  * Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
1220  */
1221 LONG NC_HandleSysCommand( HWND hwnd, WORD wParam, POINT pt )
1222 {
1223     WND *wndPtr = WIN_FindWndPtr( hwnd );
1224
1225 #ifdef DEBUG_NONCLIENT
1226     printf( "Handling WM_SYSCOMMAND %x %d,%d\n", wParam, pt.x, pt.y );
1227 #endif
1228
1229     if (wndPtr->dwStyle & WS_CHILD) ScreenToClient( wndPtr->hwndParent, &pt );
1230
1231     switch (wParam & 0xfff0)
1232     {
1233     case SC_SIZE:
1234     case SC_MOVE:
1235         NC_DoSizeMove( hwnd, wParam, pt );
1236         break;
1237
1238     case SC_MINIMIZE:
1239         ICON_Iconify( hwnd );
1240         /*ShowWindow( hwnd, SW_MINIMIZE );*/
1241         break;
1242
1243     case SC_MAXIMIZE:
1244         ShowWindow( hwnd, SW_MAXIMIZE );
1245         break;
1246
1247     case SC_RESTORE:
1248         ICON_Deiconify(hwnd);
1249         ShowWindow( hwnd, SW_RESTORE );
1250         break;
1251
1252     case SC_NEXTWINDOW:
1253     case SC_PREVWINDOW:
1254         break;
1255
1256     case SC_CLOSE:
1257         return SendMessage( hwnd, WM_CLOSE, 0, 0 );
1258
1259     case SC_VSCROLL:
1260     case SC_HSCROLL:
1261     if (wndPtr->dwStyle & WS_CHILD) ClientToScreen(wndPtr->hwndParent, &pt);
1262         NC_TrackScrollBar( hwnd, wParam, pt );
1263         break;
1264
1265     case SC_MOUSEMENU:
1266         NC_TrackMouseMenuBar( hwnd, wParam, pt );
1267         break;
1268
1269     case SC_KEYMENU:
1270 /*      NC_KeyMenuBar( hwnd, wParam, pt ); */
1271         break;
1272         
1273     case SC_ARRANGE:
1274         break;
1275
1276     case SC_TASKLIST:
1277     case SC_SCREENSAVE:
1278     case SC_HOTKEY:
1279         break;
1280     }
1281     return 0;
1282 }
1283
1284