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