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