Release 961201
[wine] / windows / painting.c
1 /*
2  * Window painting functions
3  *
4  * Copyright 1993, 1994, 1995 Alexandre Julliard
5  */
6
7 #include <stdio.h>
8 #include <X11/Xlib.h>
9
10 #include "win.h"
11 #include "queue.h"
12 #include "gdi.h"
13 #include "dce.h"
14 #include "stddebug.h"
15 /* #define DEBUG_WIN */
16 #include "debug.h"
17
18   /* Last CTLCOLOR id */
19 #define CTLCOLOR_MAX   CTLCOLOR_STATIC
20
21 /***********************************************************************
22  *           WIN_UpdateNCArea
23  *
24  */
25 void WIN_UpdateNCArea(WND* wnd, BOOL bUpdate)
26 {
27     POINT16 pt = {0, 0}; 
28     HRGN32 hClip = 1;
29
30     dprintf_nonclient(stddeb,"NCUpdate: hwnd %04x, hrgnUpdate %04x\n", 
31                       wnd->hwndSelf, wnd->hrgnUpdate );
32
33     /* desktop window doesn't have nonclient area */
34     if(wnd == WIN_GetDesktop()) 
35     {
36         wnd->flags &= ~WIN_NEEDS_NCPAINT;
37         return;
38     }
39
40     if( wnd->hrgnUpdate > 1 )
41     {
42         ClientToScreen16(wnd->hwndSelf, &pt);
43
44         hClip = CreateRectRgn32( 0, 0, 0, 0 );
45         if (!CombineRgn32( hClip, wnd->hrgnUpdate, 0, RGN_COPY ))
46         {
47             DeleteObject32(hClip);
48             hClip = 1;
49         }
50         else
51             OffsetRgn32( hClip, pt.x, pt.y );
52
53         if (bUpdate)
54         {
55             /* exclude non-client area from update region */
56             HRGN32 hrgn = CreateRectRgn32( 0, 0,
57                                  wnd->rectClient.right - wnd->rectClient.left,
58                                  wnd->rectClient.bottom - wnd->rectClient.top);
59
60             if (hrgn && (CombineRgn32( wnd->hrgnUpdate, wnd->hrgnUpdate,
61                                        hrgn, RGN_AND) == NULLREGION))
62             {
63                 DeleteObject32( wnd->hrgnUpdate );
64                 wnd->hrgnUpdate = 1;
65             }
66
67             DeleteObject32( hrgn );
68         }
69     }
70
71     wnd->flags &= ~WIN_NEEDS_NCPAINT;
72
73     if ((wnd->hwndSelf == GetActiveWindow()) &&
74         !(wnd->flags & WIN_NCACTIVATED))
75     {
76         wnd->flags |= WIN_NCACTIVATED;
77         if( hClip > 1) DeleteObject32( hClip );
78         hClip = 1;
79     }
80
81     if (hClip) SendMessage16( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
82
83     if (hClip > 1) DeleteObject32( hClip );
84 }
85
86
87 /***********************************************************************
88  *           BeginPaint16    (USER.39)
89  */
90 HDC16 BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps ) 
91 {
92     BOOL32 bIcon;
93     HRGN32 hrgnUpdate;
94     WND *wndPtr = WIN_FindWndPtr( hwnd );
95     if (!wndPtr) return 0;
96
97     bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
98
99     wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
100
101     if (wndPtr->flags & WIN_NEEDS_NCPAINT) WIN_UpdateNCArea( wndPtr, TRUE );
102
103     if (((hrgnUpdate = wndPtr->hrgnUpdate) != 0) ||
104         (wndPtr->flags & WIN_INTERNAL_PAINT))
105         QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
106
107     wndPtr->hrgnUpdate = 0;
108     wndPtr->flags &= ~WIN_INTERNAL_PAINT;
109
110     HideCaret( hwnd );
111
112     dprintf_win(stddeb,"hrgnUpdate = %04x, ", hrgnUpdate);
113
114     /* When bIcon is TRUE hrgnUpdate is automatically in window coordinates
115      * (because rectClient == rectWindow for WS_MINIMIZE windows).
116      */
117
118     if (wndPtr->class->style & CS_PARENTDC)
119         /* Don't clip the output to the update region for CS_PARENTDC window */
120         lps->hdc = GetDCEx16( hwnd, 0, DCX_WINDOWPAINT | DCX_USESTYLE |
121                               (bIcon ? DCX_WINDOW : 0) );
122     else
123         lps->hdc = GetDCEx16(hwnd, hrgnUpdate, DCX_INTERSECTRGN |
124                              DCX_WINDOWPAINT | DCX_USESTYLE |
125                              (bIcon ? DCX_WINDOW : 0) );
126
127     dprintf_win(stddeb,"hdc = %04x\n", lps->hdc);
128
129     if (!lps->hdc)
130     {
131         fprintf(stderr, "GetDCEx() failed in BeginPaint(), hwnd=%04x\n", hwnd);
132         return 0;
133     }
134
135     GetRgnBox16( InquireVisRgn(lps->hdc), &lps->rcPaint );
136     DPtoLP16( lps->hdc, (LPPOINT16)&lps->rcPaint, 2 );
137
138     if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
139     {
140         wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
141         lps->fErase = !SendMessage16(hwnd, (bIcon) ? WM_ICONERASEBKGND
142                                                    : WM_ERASEBKGND,
143                                      (WPARAM16)lps->hdc, 0 );
144     }
145     else lps->fErase = TRUE;
146
147     return lps->hdc;
148 }
149
150
151 /***********************************************************************
152  *           BeginPaint32    (USER32.9)
153  */
154 HDC32 BeginPaint32( HWND32 hwnd, PAINTSTRUCT32 *lps )
155 {
156     PAINTSTRUCT16 ps;
157
158     BeginPaint16( hwnd, &ps );
159     lps->hdc            = (HDC32)ps.hdc;
160     lps->fErase         = ps.fErase;
161     lps->rcPaint.top    = ps.rcPaint.top;
162     lps->rcPaint.left   = ps.rcPaint.left;
163     lps->rcPaint.right  = ps.rcPaint.right;
164     lps->rcPaint.bottom = ps.rcPaint.bottom;
165     lps->fRestore       = ps.fRestore;
166     lps->fIncUpdate     = ps.fIncUpdate;
167     return lps->hdc;
168 }
169
170
171 /***********************************************************************
172  *           EndPaint16    (USER.40)
173  */
174 BOOL16 EndPaint16( HWND16 hwnd, const PAINTSTRUCT16* lps )
175 {
176     ReleaseDC16( hwnd, lps->hdc );
177     ShowCaret( hwnd );
178     return TRUE;
179 }
180
181
182 /***********************************************************************
183  *           EndPaint32    (USER32.175)
184  */
185 BOOL32 EndPaint32( HWND32 hwnd, const PAINTSTRUCT32 *lps )
186 {
187     ReleaseDC32( hwnd, lps->hdc );
188     ShowCaret( hwnd );
189     return TRUE;
190 }
191
192
193 /***********************************************************************
194  *           FillWindow    (USER.324)
195  */
196 void FillWindow( HWND16 hwndParent, HWND16 hwnd, HDC16 hdc, HBRUSH16 hbrush )
197 {
198     RECT16 rect;
199     GetClientRect16( hwnd, &rect );
200     DPtoLP16( hdc, (LPPOINT16)&rect, 2 );
201     PaintRect( hwndParent, hwnd, hdc, hbrush, &rect );
202 }
203
204
205 /***********************************************************************
206  *           PaintRect    (USER.325)
207  */
208 void PaintRect( HWND16 hwndParent, HWND16 hwnd, HDC16 hdc,
209                 HBRUSH16 hbrush, const RECT16 *rect)
210 {
211       /* Send WM_CTLCOLOR message if needed */
212
213     if ((UINT32)hbrush <= CTLCOLOR_MAX)
214     {
215         if (!hwndParent) return;
216         hbrush = (HBRUSH16)SendMessage32A( hwndParent, 
217                                            WM_CTLCOLORMSGBOX + (UINT32)hbrush,
218                                            (WPARAM32)hdc, (LPARAM)hwnd );
219     }
220     if (hbrush) FillRect16( hdc, rect, hbrush );
221 }
222
223
224 /***********************************************************************
225  *           GetControlBrush    (USER.326)
226  */
227 HBRUSH16 GetControlBrush( HWND hwnd, HDC16 hdc, WORD control )
228 {
229     return (HBRUSH16)SendMessage32A( GetParent32(hwnd), WM_CTLCOLOR+control,
230                                      (WPARAM32)hdc, (LPARAM)hwnd );
231 }
232
233
234 /***********************************************************************
235  *           PAINT_RedrawWindow
236  *
237  * Note: Windows uses WM_SYNCPAINT to cut down the number of intertask
238  * SendMessage() calls. From SDK:
239  *   This message avoids lots of inter-app message traffic
240  *   by switching to the other task and continuing the
241  *   recursion there.
242  * 
243  * wParam         = flags
244  * LOWORD(lParam) = hrgnClip
245  * HIWORD(lParam) = hwndSkip  (not used; always NULL)
246  */
247 BOOL32 PAINT_RedrawWindow( HWND32 hwnd, const RECT32 *rectUpdate,
248                            HRGN32 hrgnUpdate, UINT32 flags, UINT32 control )
249 {
250     BOOL32 bIcon;
251     HRGN32 hrgn;
252     RECT32 rectClient;
253     WND* wndPtr;
254
255     if (!hwnd) hwnd = GetDesktopWindow32();
256     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
257     if (!IsWindowVisible(hwnd) || (wndPtr->flags & WIN_NO_REDRAW))
258         return TRUE;  /* No redraw needed */
259
260     bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
261     if (rectUpdate)
262     {
263         dprintf_win(stddeb, "RedrawWindow: %04x %d,%d-%d,%d %04x flags=%04x\n",
264                     hwnd, rectUpdate->left, rectUpdate->top,
265                     rectUpdate->right, rectUpdate->bottom, hrgnUpdate, flags );
266     }
267     else
268     {
269         dprintf_win(stddeb, "RedrawWindow: %04x NULL %04x flags=%04x\n",
270                      hwnd, hrgnUpdate, flags);
271     }
272
273     GetClientRect32( hwnd, &rectClient );
274
275     if (flags & RDW_INVALIDATE)  /* Invalidate */
276     {
277         int rgnNotEmpty = COMPLEXREGION;
278
279         if (wndPtr->hrgnUpdate > 1)  /* Is there already an update region? */
280         {
281             if ((hrgn = hrgnUpdate) == 0)
282                 hrgn = CreateRectRgnIndirect32( rectUpdate ? rectUpdate :
283                                                 &rectClient );
284             rgnNotEmpty = CombineRgn32( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate,
285                                         hrgn, RGN_OR );
286             if (!hrgnUpdate) DeleteObject32( hrgn );
287         }
288         else  /* No update region yet */
289         {
290             if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
291                 QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
292             if (hrgnUpdate)
293             {
294                 wndPtr->hrgnUpdate = CreateRectRgn32( 0, 0, 0, 0 );
295                 rgnNotEmpty = CombineRgn32( wndPtr->hrgnUpdate, hrgnUpdate,
296                                             0, RGN_COPY );
297             }
298             else wndPtr->hrgnUpdate = CreateRectRgnIndirect32( rectUpdate ?
299                                                     rectUpdate : &rectClient );
300         }
301         
302         if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
303
304         /* check for bogus update region */ 
305         if ( rgnNotEmpty == NULLREGION )
306            {
307              wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
308              DeleteObject32( wndPtr->hrgnUpdate );
309              wndPtr->hrgnUpdate=0;
310              if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
311                    QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
312            }
313         else
314              if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
315         flags |= RDW_FRAME;  /* Force children frame invalidation */
316     }
317     else if (flags & RDW_VALIDATE)  /* Validate */
318     {
319           /* We need an update region in order to validate anything */
320         if (wndPtr->hrgnUpdate > 1)
321         {
322             if (!hrgnUpdate && !rectUpdate)
323             {
324                   /* Special case: validate everything */
325                 DeleteObject32( wndPtr->hrgnUpdate );
326                 wndPtr->hrgnUpdate = 0;
327             }
328             else
329             {
330                 if ((hrgn = hrgnUpdate) == 0)
331                     hrgn = CreateRectRgnIndirect32( rectUpdate );
332                 if (CombineRgn32( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate,
333                                   hrgn, RGN_DIFF ) == NULLREGION)
334                 {
335                     DeleteObject32( wndPtr->hrgnUpdate );
336                     wndPtr->hrgnUpdate = 0;
337                 }
338                 if (!hrgnUpdate) DeleteObject32( hrgn );
339             }
340             if (!wndPtr->hrgnUpdate)  /* No more update region */
341                 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
342                     QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
343         }
344         if (flags & RDW_NOFRAME) wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
345         if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
346     }
347
348       /* Set/clear internal paint flag */
349
350     if (flags & RDW_INTERNALPAINT)
351     {
352         if ( wndPtr->hrgnUpdate <= 1 && !(wndPtr->flags & WIN_INTERNAL_PAINT))
353             QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
354         wndPtr->flags |= WIN_INTERNAL_PAINT;        
355     }
356     else if (flags & RDW_NOINTERNALPAINT)
357     {
358         if ( wndPtr->hrgnUpdate <= 1 && (wndPtr->flags & WIN_INTERNAL_PAINT))
359             QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
360         wndPtr->flags &= ~WIN_INTERNAL_PAINT;
361     }
362
363       /* Erase/update window */
364
365     if (flags & RDW_UPDATENOW)
366     {
367         if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */
368             SendMessage16( hwnd, (bIcon) ? WM_PAINTICON : WM_PAINT, bIcon, 0 );
369     }
370     else if (flags & RDW_ERASENOW)
371     {
372         if (wndPtr->flags & WIN_NEEDS_NCPAINT)
373             WIN_UpdateNCArea( wndPtr, FALSE);
374
375         if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
376         {
377             HDC32 hdc = GetDCEx32( hwnd, wndPtr->hrgnUpdate,
378                                    DCX_INTERSECTRGN | DCX_USESTYLE |
379                                    DCX_KEEPCLIPRGN | DCX_WINDOWPAINT |
380                                    (bIcon ? DCX_WINDOW : 0) );
381             if (hdc)
382             {
383                if (SendMessage16( hwnd, (bIcon) ? WM_ICONERASEBKGND
384                                                 : WM_ERASEBKGND,
385                                   (WPARAM16)hdc, 0 ))
386                   wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
387                ReleaseDC32( hwnd, hdc );
388             }
389         }
390     }
391
392       /* Recursively process children */
393
394     if (!(flags & RDW_NOCHILDREN) &&
395         ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) &&
396         !(wndPtr->dwStyle & WS_MINIMIZE) )
397     {
398         if ( hrgnUpdate || rectUpdate )
399         {
400            if (!(hrgn = CreateRectRgn32( 0, 0, 0, 0 ))) return TRUE;
401            if( !hrgnUpdate )
402              {
403                 control |= (RDW_C_DELETEHRGN | RDW_C_USEHRGN);
404                 if( !(hrgnUpdate = CreateRectRgnIndirect32( rectUpdate )) )
405                 {
406                     DeleteObject32( hrgn );
407                     return TRUE;
408                 }
409              }
410            for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
411              if( wndPtr->dwStyle & WS_VISIBLE )
412                {
413                    SetRectRgn( hrgn, wndPtr->rectWindow.left,
414                                wndPtr->rectWindow.top,
415                                wndPtr->rectWindow.right,
416                                wndPtr->rectWindow.bottom );
417                    if (!CombineRgn32( hrgn, hrgn, hrgnUpdate, RGN_AND ))
418                        continue;
419                    OffsetRgn32( hrgn, -wndPtr->rectClient.left,
420                                       -wndPtr->rectClient.top );
421                    PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, hrgn, flags,
422                                        RDW_C_USEHRGN );
423                }
424            DeleteObject32( hrgn );
425            if (control & RDW_C_DELETEHRGN) DeleteObject32( hrgnUpdate );
426         }
427         else for (wndPtr = wndPtr->child; wndPtr; wndPtr = wndPtr->next)
428                   PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, flags, 0 );
429
430     }
431     return TRUE;
432 }
433
434
435 /***********************************************************************
436  *           RedrawWindow32    (USER32.425)
437  */
438 BOOL32 RedrawWindow32( HWND32 hwnd, const RECT32 *rectUpdate,
439                        HRGN32 hrgnUpdate, UINT32 flags )
440 {
441     WND* wnd = WIN_FindWndPtr( hwnd );
442
443     /* check if there is something to redraw */
444
445     return ( wnd && WIN_IsWindowDrawable( wnd, !(flags & RDW_FRAME) ) )
446            ? PAINT_RedrawWindow( hwnd, rectUpdate, hrgnUpdate, flags, 0 )
447            : 1;
448 }
449
450
451 /***********************************************************************
452  *           RedrawWindow16    (USER.290)
453  */
454 BOOL16 RedrawWindow16( HWND16 hwnd, const RECT16 *rectUpdate,
455                        HRGN16 hrgnUpdate, UINT16 flags )
456 {
457     if (rectUpdate)
458     {
459         RECT32 r;
460         CONV_RECT16TO32( rectUpdate, &r );
461         return (BOOL16)RedrawWindow32( (HWND32)hwnd, &r, hrgnUpdate, flags );
462     }
463     return (BOOL16)RedrawWindow32( (HWND32)hwnd, NULL, hrgnUpdate, flags );
464 }
465
466
467 /***********************************************************************
468  *           UpdateWindow   (USER.124) (USER32.566)
469  */
470 void UpdateWindow( HWND32 hwnd )
471 {
472     RedrawWindow32( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN );
473 }
474
475
476 /***********************************************************************
477  *           InvalidateRgn   (USER.126) (USER32.328)
478  */
479 void InvalidateRgn( HWND32 hwnd, HRGN32 hrgn, BOOL32 erase )
480 {
481     RedrawWindow32(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
482 }
483
484
485 /***********************************************************************
486  *           InvalidateRect16   (USER.125)
487  */
488 void InvalidateRect16( HWND16 hwnd, const RECT16 *rect, BOOL16 erase )
489 {
490     RedrawWindow16( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
491 }
492
493
494 /***********************************************************************
495  *           InvalidateRect32   (USER32.327)
496  */
497 void InvalidateRect32( HWND32 hwnd, const RECT32 *rect, BOOL32 erase )
498 {
499     RedrawWindow32( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
500 }
501
502
503 /***********************************************************************
504  *           ValidateRgn   (USER.128) (USER32.571)
505  */
506 void ValidateRgn( HWND32 hwnd, HRGN32 hrgn )
507 {
508     RedrawWindow32( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
509 }
510
511
512 /***********************************************************************
513  *           ValidateRect16   (USER.127)
514  */
515 void ValidateRect16( HWND16 hwnd, const RECT16 *rect )
516 {
517     RedrawWindow16( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
518 }
519
520
521 /***********************************************************************
522  *           ValidateRect32   (USER32.570)
523  */
524 void ValidateRect32( HWND32 hwnd, const RECT32 *rect )
525 {
526     RedrawWindow32( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
527 }
528
529
530 /***********************************************************************
531  *           GetUpdateRect16   (USER.190)
532  */
533 BOOL16 GetUpdateRect16( HWND16 hwnd, LPRECT16 rect, BOOL16 erase )
534 {
535     RECT32 r;
536     BOOL16 ret;
537
538     if (!rect) return GetUpdateRect32( hwnd, NULL, erase );
539     ret = GetUpdateRect32( hwnd, &r, erase );
540     CONV_RECT32TO16( &r, rect );
541     return ret;
542 }
543
544
545 /***********************************************************************
546  *           GetUpdateRect32   (USER32.296)
547  */
548 BOOL32 GetUpdateRect32( HWND32 hwnd, LPRECT32 rect, BOOL32 erase )
549 {
550     WND * wndPtr = WIN_FindWndPtr( hwnd );
551     if (!wndPtr) return FALSE;
552
553     if (rect)
554     {
555         if (wndPtr->hrgnUpdate > 1)
556         {
557             HRGN32 hrgn = CreateRectRgn32( 0, 0, 0, 0 );
558             if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR) return FALSE;
559             GetRgnBox32( hrgn, rect );
560             DeleteObject32( hrgn );
561         }
562         else SetRectEmpty32( rect );
563     }
564     return (wndPtr->hrgnUpdate > 1);
565 }
566
567
568 /***********************************************************************
569  *           GetUpdateRgn   (USER.237) (USER32.297)
570  */
571 INT16 GetUpdateRgn( HWND32 hwnd, HRGN32 hrgn, BOOL32 erase )
572 {
573     INT32 retval;
574     WND * wndPtr = WIN_FindWndPtr( hwnd );
575     if (!wndPtr) return ERROR;
576
577     if (wndPtr->hrgnUpdate <= 1)
578     {
579         SetRectRgn( hrgn, 0, 0, 0, 0 );
580         return NULLREGION;
581     }
582     retval = CombineRgn32( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
583     if (erase) RedrawWindow32( hwnd, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN );
584     return retval;
585 }
586
587
588 /***********************************************************************
589  *           ExcludeUpdateRgn   (USER.238) (USER32.194)
590  */
591 INT16 ExcludeUpdateRgn( HDC32 hdc, HWND32 hwnd )
592 {
593     RECT16 rect;
594     WND * wndPtr;
595
596     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
597
598     if (wndPtr->hrgnUpdate)
599     {
600         INT16  ret;
601         HRGN32 hrgn = CreateRectRgn32(wndPtr->rectWindow.left - wndPtr->rectClient.left,
602                                       wndPtr->rectWindow.top - wndPtr->rectClient.top,
603                                       wndPtr->rectClient.right - wndPtr->rectClient.left,
604                                       wndPtr->rectClient.bottom - wndPtr->rectClient.top);
605         if( wndPtr->hrgnUpdate > 1 )
606             CombineRgn32(hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY);
607
608         /* do ugly coordinate translations in dce.c */
609
610         ret = DCE_ExcludeRgn( hdc, wndPtr, hrgn );
611         DeleteObject32( hrgn );
612         return ret;
613     } 
614     return GetClipBox16(hdc, &rect);
615 }
616
617