Release 970329
[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, BOOL32 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 == GetActiveWindow32()) &&
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     HideCaret32( 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     ShowCaret32( 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     ShowCaret32( 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( HWND16 hwnd, HDC16 hdc, UINT16 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  * FIXME: 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 (!WIN_IsWindowDrawable( wndPtr, !(flags & RDW_FRAME) ) 
260         || (wndPtr->flags & WIN_NO_REDRAW)) 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 (!IsWindow32(wndPtr->hwndSelf)) continue;
417                if (wndPtr->dwStyle & WS_VISIBLE)
418                {
419                    SetRectRgn32( 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 (IsWindow32( 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     return PAINT_RedrawWindow( hwnd, rectUpdate, hrgnUpdate, flags, 0 );
459 }
460
461
462 /***********************************************************************
463  *           RedrawWindow16    (USER.290)
464  */
465 BOOL16 RedrawWindow16( HWND16 hwnd, const RECT16 *rectUpdate,
466                        HRGN16 hrgnUpdate, UINT16 flags )
467 {
468     if (rectUpdate)
469     {
470         RECT32 r;
471         CONV_RECT16TO32( rectUpdate, &r );
472         return (BOOL16)RedrawWindow32( (HWND32)hwnd, &r, hrgnUpdate, flags );
473     }
474     return (BOOL16)PAINT_RedrawWindow( (HWND32)hwnd, NULL, 
475                                        (HRGN32)hrgnUpdate, flags, 0 );
476 }
477
478
479 /***********************************************************************
480  *           UpdateWindow16   (USER.124)
481  */
482 void UpdateWindow16( HWND16 hwnd )
483 {
484     PAINT_RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN, 0 );
485 }
486
487 /***********************************************************************
488  *           UpdateWindow32   (USER32.566)
489  */
490 void UpdateWindow32( HWND32 hwnd )
491 {
492     PAINT_RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN, 0 );
493 }
494
495 /***********************************************************************
496  *           InvalidateRgn16   (USER.126)
497  */
498 void InvalidateRgn16( HWND16 hwnd, HRGN16 hrgn, BOOL16 erase )
499 {
500     PAINT_RedrawWindow((HWND32)hwnd, NULL, (HRGN32)hrgn, 
501                        RDW_INVALIDATE | (erase ? RDW_ERASE : 0), 0 );
502 }
503
504
505 /***********************************************************************
506  *           InvalidateRgn32   (USER32.328)
507  */
508 void InvalidateRgn32( HWND32 hwnd, HRGN32 hrgn, BOOL32 erase )
509 {
510     PAINT_RedrawWindow(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0), 0 );
511 }
512
513
514 /***********************************************************************
515  *           InvalidateRect16   (USER.125)
516  */
517 void InvalidateRect16( HWND16 hwnd, const RECT16 *rect, BOOL16 erase )
518 {
519     RedrawWindow16( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
520 }
521
522
523 /***********************************************************************
524  *           InvalidateRect32   (USER32.327)
525  */
526 void InvalidateRect32( HWND32 hwnd, const RECT32 *rect, BOOL32 erase )
527 {
528     PAINT_RedrawWindow( hwnd, rect, 0, 
529                         RDW_INVALIDATE | (erase ? RDW_ERASE : 0), 0 );
530 }
531
532
533 /***********************************************************************
534  *           ValidateRgn16   (USER.128)
535  */
536 void ValidateRgn16( HWND16 hwnd, HRGN16 hrgn )
537 {
538     PAINT_RedrawWindow( (HWND32)hwnd, NULL, (HRGN32)hrgn, 
539                         RDW_VALIDATE | RDW_NOCHILDREN, 0 );
540 }
541
542
543 /***********************************************************************
544  *           ValidateRgn32   (USER32.571)
545  */
546 void ValidateRgn32( HWND32 hwnd, HRGN32 hrgn )
547 {
548     PAINT_RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN, 0 );
549 }
550
551
552 /***********************************************************************
553  *           ValidateRect16   (USER.127)
554  */
555 void ValidateRect16( HWND16 hwnd, const RECT16 *rect )
556 {
557     RedrawWindow16( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
558 }
559
560
561 /***********************************************************************
562  *           ValidateRect32   (USER32.570)
563  */
564 void ValidateRect32( HWND32 hwnd, const RECT32 *rect )
565 {
566     PAINT_RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN, 0 );
567 }
568
569
570 /***********************************************************************
571  *           GetUpdateRect16   (USER.190)
572  */
573 BOOL16 GetUpdateRect16( HWND16 hwnd, LPRECT16 rect, BOOL16 erase )
574 {
575     RECT32 r;
576     BOOL16 ret;
577
578     if (!rect) return GetUpdateRect32( hwnd, NULL, erase );
579     ret = GetUpdateRect32( hwnd, &r, erase );
580     CONV_RECT32TO16( &r, rect );
581     return ret;
582 }
583
584
585 /***********************************************************************
586  *           GetUpdateRect32   (USER32.296)
587  */
588 BOOL32 GetUpdateRect32( HWND32 hwnd, LPRECT32 rect, BOOL32 erase )
589 {
590     WND * wndPtr = WIN_FindWndPtr( hwnd );
591     if (!wndPtr) return FALSE;
592
593     if (rect)
594     {
595         if (wndPtr->hrgnUpdate > 1)
596         {
597             HRGN32 hrgn = CreateRectRgn32( 0, 0, 0, 0 );
598             if (GetUpdateRgn32( hwnd, hrgn, erase ) == ERROR) return FALSE;
599             GetRgnBox32( hrgn, rect );
600             DeleteObject32( hrgn );
601         }
602         else SetRectEmpty32( rect );
603     }
604     return (wndPtr->hrgnUpdate > 1);
605 }
606
607
608 /***********************************************************************
609  *           GetUpdateRgn16   (USER.237)
610  */
611 INT16 GetUpdateRgn16( HWND16 hwnd, HRGN16 hrgn, BOOL16 erase )
612 {
613     return GetUpdateRgn32( hwnd, hrgn, erase );
614 }
615
616
617 /***********************************************************************
618  *           GetUpdateRgn32   (USER32.297)
619  */
620 INT32 GetUpdateRgn32( HWND32 hwnd, HRGN32 hrgn, BOOL32 erase )
621 {
622     INT32 retval;
623     WND * wndPtr = WIN_FindWndPtr( hwnd );
624     if (!wndPtr) return ERROR;
625
626     if (wndPtr->hrgnUpdate <= 1)
627     {
628         SetRectRgn32( hrgn, 0, 0, 0, 0 );
629         return NULLREGION;
630     }
631     retval = CombineRgn32( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
632     if (erase) RedrawWindow32( hwnd, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN );
633     return retval;
634 }
635
636
637 /***********************************************************************
638  *           ExcludeUpdateRgn16   (USER.238)
639  */
640 INT16 ExcludeUpdateRgn16( HDC16 hdc, HWND16 hwnd )
641 {
642     return ExcludeUpdateRgn32( hdc, hwnd );
643 }
644
645
646 /***********************************************************************
647  *           ExcludeUpdateRgn32   (USER32.194)
648  */
649 INT32 ExcludeUpdateRgn32( HDC32 hdc, HWND32 hwnd )
650 {
651     RECT32 rect;
652     WND * wndPtr;
653
654     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
655
656     if (wndPtr->hrgnUpdate)
657     {
658         INT32 ret;
659         HRGN32 hrgn = CreateRectRgn32(wndPtr->rectWindow.left - wndPtr->rectClient.left,
660                                       wndPtr->rectWindow.top - wndPtr->rectClient.top,
661                                       wndPtr->rectClient.right - wndPtr->rectClient.left,
662                                       wndPtr->rectClient.bottom - wndPtr->rectClient.top);
663         if( wndPtr->hrgnUpdate > 1 )
664             CombineRgn32(hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY);
665
666         /* do ugly coordinate translations in dce.c */
667
668         ret = DCE_ExcludeRgn( hdc, wndPtr, hrgn );
669         DeleteObject32( hrgn );
670         return ret;
671     } 
672     return GetClipBox32( hdc, &rect );
673 }
674
675