Converted to the new debugging interface (done with the help of the
[wine] / windows / painting.c
1 /*
2  * Window painting functions
3  *
4  * Copyright 1993, 1994, 1995 Alexandre Julliard
5  *                       1999 Alex Korobka
6  *
7  */
8
9 #include "region.h"
10 #include "win.h"
11 #include "queue.h"
12 #include "dce.h"
13 #include "heap.h"
14 #include "debugtools.h"
15 #include "wine/winuser16.h"
16
17 DECLARE_DEBUG_CHANNEL(nonclient)
18 DECLARE_DEBUG_CHANNEL(win)
19
20 /* client rect in window coordinates */
21
22 #define GETCLIENTRECTW( wnd, r )        (r).left = (wnd)->rectClient.left - (wnd)->rectWindow.left; \
23                                         (r).top = (wnd)->rectClient.top - (wnd)->rectWindow.top; \
24                                         (r).right = (wnd)->rectClient.right - (wnd)->rectWindow.left; \
25                                         (r).bottom = (wnd)->rectClient.bottom - (wnd)->rectWindow.top
26
27   /* Last CTLCOLOR id */
28 #define CTLCOLOR_MAX   CTLCOLOR_STATIC
29
30
31 /***********************************************************************
32  *           WIN_UpdateNCRgn
33  *
34  * NOTE: Caller is responsible for the returned region.
35  */
36 HRGN WIN_UpdateNCRgn(WND* wnd, BOOL bUpdate, BOOL bForceEntire )
37 {
38     HRGN hClip = 0;
39
40     TRACE_(nonclient)("hwnd %04x, hrgnUpdate %04x, ncf %i\n", 
41                       wnd->hwndSelf, wnd->hrgnUpdate, (wnd->flags & WIN_NEEDS_NCPAINT)!=0 );
42
43     /* desktop window doesn't have nonclient area */
44     if(wnd == WIN_GetDesktop()) 
45     {
46         wnd->flags &= ~WIN_NEEDS_NCPAINT;
47         WIN_ReleaseDesktop();
48         return 0;
49     }
50     WIN_ReleaseDesktop();
51
52     if ((wnd->hwndSelf == GetActiveWindow()) &&
53         !(wnd->flags & WIN_NCACTIVATED) )
54     {
55         wnd->flags |= WIN_NCACTIVATED;
56         bForceEntire = TRUE;
57     }
58
59     if( (wnd->flags & WIN_NEEDS_NCPAINT) && wnd->hrgnUpdate )
60     {
61         RECT r, r2, r3;
62
63         GETCLIENTRECTW( wnd, r );
64
65         TRACE_(nonclient)("\tclient box (%i,%i-%i,%i)\n", r.left, r.top, r.right, r.bottom );
66
67         if( wnd->hrgnUpdate > 1 )
68         {
69                 GetRgnBox( wnd->hrgnUpdate, &r2 );
70                 UnionRect( &r3, &r2, &r );
71                 if( r3.left != r.left || r3.top != r.top || 
72                     r3.right != r.right || r3.bottom != r.bottom )
73                 {
74                     hClip = CreateRectRgn( 0, 0, 0, 0 );
75                     CombineRgn( hClip, wnd->hrgnUpdate, 0, RGN_COPY );
76                 }
77         }
78         else 
79                 hClip = wnd->hrgnUpdate;
80
81         if( wnd->hrgnUpdate > 1 )
82         {
83             REGION_CropRgn( wnd->hrgnUpdate, wnd->hrgnUpdate, &r, NULL );
84
85             if( bUpdate )
86             {
87                 GetRgnBox( wnd->hrgnUpdate, &r3 );
88                 if( IsRectEmpty( &r3 ) )
89                 {
90                     /* delete update region since all invalid 
91                      * parts were in the nonclient area */
92
93                     DeleteObject( wnd->hrgnUpdate );
94                     wnd->hrgnUpdate = 0;
95                     if(!(wnd->flags & WIN_INTERNAL_PAINT))
96                         QUEUE_DecPaintCount( wnd->hmemTaskQ );
97                     wnd->flags &= ~WIN_NEEDS_ERASEBKGND;
98                 }
99             }
100         }
101         else /* entire client rect */
102            wnd->hrgnUpdate = CreateRectRgnIndirect( &r );
103     }
104
105     if(!hClip && bForceEntire ) hClip = 1;
106     wnd->flags &= ~WIN_NEEDS_NCPAINT;
107
108     if( hClip )
109         SendMessageA( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
110
111     return hClip;
112 }
113
114
115 /***********************************************************************
116  *           BeginPaint16    (USER.39)
117  */
118 HDC16 WINAPI BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps ) 
119 {
120     BOOL bIcon;
121     HRGN hrgnUpdate;
122     WND *wndPtr = WIN_FindWndPtr( hwnd );
123     if (!wndPtr) return 0;
124
125     bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
126
127     wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
128
129     if( (hrgnUpdate = WIN_UpdateNCRgn( wndPtr, FALSE, FALSE )) > 1 ) 
130         DeleteObject( hrgnUpdate );
131
132     if( ((hrgnUpdate = wndPtr->hrgnUpdate) != 0) || (wndPtr->flags & WIN_INTERNAL_PAINT))
133         QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
134
135     wndPtr->hrgnUpdate = 0;
136     wndPtr->flags &= ~WIN_INTERNAL_PAINT;
137
138     HideCaret( hwnd );
139
140     TRACE_(win)("hrgnUpdate = %04x, \n", hrgnUpdate);
141
142     if (wndPtr->class->style & CS_PARENTDC)
143     {
144         /* Don't clip the output to the update region for CS_PARENTDC window */
145         if( hrgnUpdate > 1 )
146             DeleteObject(hrgnUpdate);
147         lps->hdc = GetDCEx16( hwnd, 0, DCX_WINDOWPAINT | DCX_USESTYLE |
148                               (bIcon ? DCX_WINDOW : 0) );
149     }
150     else
151     {
152         if( hrgnUpdate )
153             OffsetRgn( hrgnUpdate, wndPtr->rectWindow.left - wndPtr->rectClient.left,
154                                    wndPtr->rectWindow.top - wndPtr->rectClient.top );
155         lps->hdc = GetDCEx16(hwnd, hrgnUpdate, DCX_INTERSECTRGN |
156                              DCX_WINDOWPAINT | DCX_USESTYLE |
157                              (bIcon ? DCX_WINDOW : 0) );
158     }
159
160     TRACE_(win)("hdc = %04x\n", lps->hdc);
161
162     if (!lps->hdc)
163     {
164         WARN_(win)("GetDCEx() failed in BeginPaint(), hwnd=%04x\n", hwnd);
165         WIN_ReleaseWndPtr(wndPtr);
166         return 0;
167     }
168
169     GetClipBox16( lps->hdc, &lps->rcPaint );
170
171     TRACE_(win)("box = (%i,%i - %i,%i)\n", lps->rcPaint.left, lps->rcPaint.top,
172                     lps->rcPaint.right, lps->rcPaint.bottom );
173
174     if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
175     {
176         wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
177         lps->fErase = !SendMessage16(hwnd, (bIcon) ? WM_ICONERASEBKGND
178                                                    : WM_ERASEBKGND,
179                                      (WPARAM16)lps->hdc, 0 );
180     }
181     else lps->fErase = TRUE;
182
183     WIN_ReleaseWndPtr(wndPtr);
184     return lps->hdc;
185 }
186
187
188 /***********************************************************************
189  *           BeginPaint32    (USER32.10)
190  */
191 HDC WINAPI BeginPaint( HWND hwnd, PAINTSTRUCT *lps )
192 {
193     PAINTSTRUCT16 ps;
194
195     BeginPaint16( hwnd, &ps );
196     lps->hdc            = (HDC)ps.hdc;
197     lps->fErase         = ps.fErase;
198     lps->rcPaint.top    = ps.rcPaint.top;
199     lps->rcPaint.left   = ps.rcPaint.left;
200     lps->rcPaint.right  = ps.rcPaint.right;
201     lps->rcPaint.bottom = ps.rcPaint.bottom;
202     lps->fRestore       = ps.fRestore;
203     lps->fIncUpdate     = ps.fIncUpdate;
204     return lps->hdc;
205 }
206
207
208 /***********************************************************************
209  *           EndPaint16    (USER.40)
210  */
211 BOOL16 WINAPI EndPaint16( HWND16 hwnd, const PAINTSTRUCT16* lps )
212 {
213     ReleaseDC16( hwnd, lps->hdc );
214     ShowCaret( hwnd );
215     return TRUE;
216 }
217
218
219 /***********************************************************************
220  *           EndPaint32    (USER32.176)
221  */
222 BOOL WINAPI EndPaint( HWND hwnd, const PAINTSTRUCT *lps )
223 {
224     ReleaseDC( hwnd, lps->hdc );
225     ShowCaret( hwnd );
226     return TRUE;
227 }
228
229
230 /***********************************************************************
231  *           FillWindow    (USER.324)
232  */
233 void WINAPI FillWindow16( HWND16 hwndParent, HWND16 hwnd, HDC16 hdc, HBRUSH16 hbrush )
234 {
235     RECT16 rect;
236     GetClientRect16( hwnd, &rect );
237     DPtoLP16( hdc, (LPPOINT16)&rect, 2 );
238     PaintRect16( hwndParent, hwnd, hdc, hbrush, &rect );
239 }
240
241
242 /***********************************************************************
243  *           PAINT_GetControlBrush
244  */
245 static HBRUSH16 PAINT_GetControlBrush( HWND hParent, HWND hWnd, HDC16 hDC, UINT16 ctlType )
246 {
247     HBRUSH16 bkgBrush = (HBRUSH16)SendMessageA( hParent, WM_CTLCOLORMSGBOX + ctlType, 
248                                                              (WPARAM)hDC, (LPARAM)hWnd );
249     if( !IsGDIObject16(bkgBrush) )
250         bkgBrush = DEFWND_ControlColor( hDC, ctlType );
251     return bkgBrush;
252 }
253
254
255 /***********************************************************************
256  *           PaintRect    (USER.325)
257  */
258 void WINAPI PaintRect16( HWND16 hwndParent, HWND16 hwnd, HDC16 hdc,
259                        HBRUSH16 hbrush, const RECT16 *rect)
260 {
261     if( hbrush <= CTLCOLOR_MAX ) 
262     {
263         if( hwndParent )
264             hbrush = PAINT_GetControlBrush( hwndParent, hwnd, hdc, (UINT16)hbrush );
265         else 
266             return;
267     }
268     if( hbrush ) 
269         FillRect16( hdc, rect, hbrush );
270 }
271
272
273 /***********************************************************************
274  *           GetControlBrush    (USER.326)
275  */
276 HBRUSH16 WINAPI GetControlBrush16( HWND16 hwnd, HDC16 hdc, UINT16 ctlType )
277 {
278     WND* wndPtr = WIN_FindWndPtr( hwnd );
279     HBRUSH16 retvalue;
280
281     if((ctlType <= CTLCOLOR_MAX) && wndPtr )
282     {
283         WND* parent;
284         if( wndPtr->dwStyle & WS_POPUP ) parent = WIN_LockWndPtr(wndPtr->owner);
285         else parent = WIN_LockWndPtr(wndPtr->parent);
286         if( !parent ) parent = wndPtr;
287         retvalue = (HBRUSH16)PAINT_GetControlBrush( parent->hwndSelf, hwnd, hdc, ctlType );
288         WIN_ReleaseWndPtr(parent);
289         goto END;
290     }
291     retvalue = (HBRUSH16)0;
292 END:
293     WIN_ReleaseWndPtr(wndPtr);
294     return retvalue;
295     }
296
297
298 /***********************************************************************
299  *           PAINT_RedrawWindow
300  *
301  * FIXME: Windows uses WM_SYNCPAINT to cut down the number of intertask
302  * SendMessage() calls. This is a comment inside DefWindowProc() source 
303  * from 16-bit SDK:
304  *
305  *   This message avoids lots of inter-app message traffic
306  *   by switching to the other task and continuing the
307  *   recursion there.
308  * 
309  * wParam         = flags
310  * LOWORD(lParam) = hrgnClip
311  * HIWORD(lParam) = hwndSkip  (not used; always NULL)
312  *
313  */
314 BOOL PAINT_RedrawWindow( HWND hwnd, const RECT *rectUpdate,
315                            HRGN hrgnUpdate, UINT flags, UINT ex )
316 {
317     BOOL bIcon;
318     HRGN hrgn = 0, hrgn2 = 0;
319     RECT r, r2;
320     POINT pt;
321     WND* wndPtr;
322     WND **list, **ppWnd;
323
324     if (!hwnd) hwnd = GetDesktopWindow();
325     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
326     if (!WIN_IsWindowDrawable( wndPtr, !(flags & RDW_FRAME) ) )
327     {
328         WIN_ReleaseWndPtr(wndPtr);
329         return TRUE;  /* No redraw needed */
330     }
331
332     bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
333     if (rectUpdate)
334     {
335         TRACE_(win)("%04x (%04x) %d,%d-%d,%d %04x flags=%04x, exflags=%04x\n",
336                     hwnd, wndPtr->hrgnUpdate, rectUpdate->left, rectUpdate->top,
337                     rectUpdate->right, rectUpdate->bottom, hrgnUpdate, flags, ex );
338     }
339     else
340     {
341         if( hrgnUpdate ) GetRgnBox( hrgnUpdate, &r );
342         else SetRectEmpty( &r );
343         TRACE_(win)("%04x (%04x) NULL %04x box (%i,%i-%i,%i) flags=%04x, exflags=%04x\n", 
344               hwnd, wndPtr->hrgnUpdate, hrgnUpdate, r.left, r.top, r.right, r.bottom, flags, ex);
345     }
346
347     if( flags & RDW_FRAME )
348         r = wndPtr->rectWindow;
349     else
350         r = wndPtr->rectClient;
351     if( ex & RDW_EX_XYWINDOW )
352         OffsetRect( &r, -wndPtr->rectWindow.left, -wndPtr->rectWindow.top );
353     else
354         OffsetRect( &r, -wndPtr->rectClient.left, -wndPtr->rectClient.top );
355
356     /* r is the rectangle we crop the supplied update rgn/rect with */
357
358     GETCLIENTRECTW( wndPtr, r2 );
359     pt.x = r2.left; pt.y = r2.top;
360
361     if (flags & RDW_INVALIDATE)  /* ------------------------- Invalidate */
362     {
363         BOOL bHasUpdateRgn = (BOOL)wndPtr->hrgnUpdate;
364
365         /* wndPtr->hrgnUpdate is in window coordinates, parameters are
366          * in client coordinates unless RDW_EX_XYWINDOW is set. 
367          */
368
369         if( hrgnUpdate )
370         {
371             hrgn = REGION_CropRgn( 0, hrgnUpdate, &r, (ex & RDW_EX_XYWINDOW) ? NULL : &pt );
372             GetRgnBox( hrgn, &r2 );
373             if( IsRectEmpty( &r2 ) )
374                 goto END;
375
376             if( wndPtr->hrgnUpdate == 0 )
377             {
378                 wndPtr->hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
379                 CombineRgn( wndPtr->hrgnUpdate, hrgn, 0, RGN_COPY );
380             }
381             else
382                 if( wndPtr->hrgnUpdate > 1 )
383                     CombineRgn( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate, hrgn, RGN_OR );
384         }
385         else if( rectUpdate )
386         {
387             if( !IntersectRect( &r2, &r, rectUpdate ) )
388                 goto END;
389             if( !(ex & RDW_EX_XYWINDOW) )
390                 OffsetRect( &r2, pt.x, pt.y );
391
392 rect2i:     /* r2 contains a rect to add to the update region */
393
394             hrgn = CreateRectRgnIndirect( &r2 );
395             if( wndPtr->hrgnUpdate == 0 )
396                 wndPtr->hrgnUpdate = CreateRectRgnIndirect( &r2 );
397             else
398                 if( wndPtr->hrgnUpdate > 1 )
399                     REGION_UnionRectWithRgn( wndPtr->hrgnUpdate, &r2 );
400         }
401         else /* entire window or client depending on RDW_FRAME */
402         {
403             hrgn = 1;
404             if( flags & RDW_FRAME )
405             {
406                 if( wndPtr->hrgnUpdate )
407                     DeleteObject( wndPtr->hrgnUpdate );
408                 wndPtr->hrgnUpdate = 1;
409             }
410             else /* by default r2 contains client rect in window coordinates */
411                 goto rect2i;
412         }
413
414         if( !bHasUpdateRgn && wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT))
415             QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
416
417         if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
418         if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
419         flags |= RDW_FRAME;  /* Force children frame invalidation */
420     }
421     else if (flags & RDW_VALIDATE)  /* ------------------------- Validate */
422     {
423         if (wndPtr->hrgnUpdate) /* need an update region in order to validate anything */
424         {
425             if( hrgnUpdate || rectUpdate )
426             {
427                 if( hrgnUpdate )
428                 {
429                     hrgn = REGION_CropRgn( hrgn, hrgnUpdate,  &r, (ex & RDW_EX_XYWINDOW) ? NULL : &pt );
430                     GetRgnBox( hrgn, &r2 );
431                     if( IsRectEmpty( &r2 ) )
432                         goto END;
433                 }
434                 else
435                 {
436                     if( !IntersectRect( &r2, &r, rectUpdate ) )
437                         goto END;
438                     if( !(ex & RDW_EX_XYWINDOW) )
439                         OffsetRect( &r2, pt.x, pt.y );
440 rect2v:
441                     hrgn = CreateRectRgnIndirect( &r2 );
442                 }
443
444                 if( wndPtr->hrgnUpdate == 1 )
445                 {
446                     wndPtr->hrgnUpdate = CreateRectRgn( 0, 0,
447                                          wndPtr->rectWindow.right - wndPtr->rectWindow.left,
448                                          wndPtr->rectWindow.bottom - wndPtr->rectWindow.top );
449                 }
450
451                 if( CombineRgn( wndPtr->hrgnUpdate, 
452                                 wndPtr->hrgnUpdate, hrgn, RGN_DIFF ) == NULLREGION )
453                 {
454                     DeleteObject( wndPtr->hrgnUpdate );
455                     wndPtr->hrgnUpdate = 0;
456                 }
457             }
458             else /* entire window or client depending on RDW_FRAME */
459             {
460                 wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
461
462                 hrgn = 1;
463                 if( flags & RDW_FRAME ) 
464                 {
465                     if( wndPtr->hrgnUpdate != 1 )
466                         DeleteObject( wndPtr->hrgnUpdate );
467                     wndPtr->hrgnUpdate = 0;
468                 }
469                 else /* by default r2 contains client rect in window coordinates */
470                     goto rect2v;
471             }
472
473             if (!wndPtr->hrgnUpdate &&  /* No more update region */
474                 !(wndPtr->flags & WIN_INTERNAL_PAINT) )
475                     QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
476         }
477         if (flags & RDW_NOFRAME) wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
478         if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
479     }
480
481     /* At this point hrgn contains new update region in window coordinates */
482
483     /* Set/clear internal paint flag */
484
485     if (flags & RDW_INTERNALPAINT)
486     {
487         if ( !wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT))
488             QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
489         wndPtr->flags |= WIN_INTERNAL_PAINT;        
490     }
491     else if (flags & RDW_NOINTERNALPAINT)
492     {
493         if ( !wndPtr->hrgnUpdate && (wndPtr->flags & WIN_INTERNAL_PAINT))
494             QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
495         wndPtr->flags &= ~WIN_INTERNAL_PAINT;
496     }
497
498       /* Erase/update window */
499
500     if (flags & RDW_UPDATENOW)
501     {
502         if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */
503             SendMessage16( hwnd, (bIcon) ? WM_PAINTICON : WM_PAINT, bIcon, 0 );
504     }
505     else if ((flags & RDW_ERASENOW) || (ex & RDW_EX_TOPFRAME))
506     {
507         hrgn2 = WIN_UpdateNCRgn( wndPtr, TRUE, (ex & RDW_EX_TOPFRAME) );
508
509         if( wndPtr->flags & WIN_NEEDS_ERASEBKGND )
510         {
511             HDC hdc;
512
513             if( hrgn2 > 1 )
514             {
515                 OffsetRgn( hrgn2, -pt.x, -pt.y );
516                 GetRgnBox( hrgn2, &r2 );
517             }
518             else
519             {
520                 hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
521                 CombineRgn( hrgn2, wndPtr->hrgnUpdate, 0, RGN_COPY );
522                 OffsetRgn( hrgn2, -pt.x, -pt.y );
523             }
524             hdc = GetDCEx( hwnd, hrgn2,
525                                  DCX_INTERSECTRGN | DCX_USESTYLE |
526                                  DCX_KEEPCLIPRGN | DCX_WINDOWPAINT |
527                                  (bIcon ? DCX_WINDOW : 0) );
528             if (hdc)
529             {
530                if (SendMessage16( hwnd, (bIcon) ? WM_ICONERASEBKGND
531                                                 : WM_ERASEBKGND,
532                                   (WPARAM16)hdc, 0 ))
533                   wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
534                ReleaseDC( hwnd, hdc );
535             }
536         }
537     }
538
539     if ( !IsWindow( hwnd ) )
540     {
541         WIN_ReleaseWndPtr(wndPtr);
542         return TRUE;
543     }
544
545       /* Recursively process children */
546
547     if (!(flags & RDW_NOCHILDREN) &&
548         ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) &&
549         !(wndPtr->dwStyle & WS_MINIMIZE) )
550     {
551         if( hrgnUpdate || rectUpdate )
552         {
553            if( hrgn2 <= 1 )
554                hrgn2 = (ex & RDW_EX_USEHRGN) ? hrgnUpdate : 0;
555
556            if( (list = WIN_BuildWinArray( wndPtr, 0, NULL )) )
557            {
558                 POINT   delta = pt;
559
560                 for (ppWnd = list; *ppWnd; ppWnd++)
561                 {
562                     WIN_UpdateWndPtr(&wndPtr,*ppWnd);
563                     if (!IsWindow(wndPtr->hwndSelf)) continue;
564                     if (wndPtr->dwStyle & WS_VISIBLE)
565                     {
566                         r.left = wndPtr->rectWindow.left + delta.x;
567                         r.top = wndPtr->rectWindow.top + delta.y;
568                         r.right = wndPtr->rectWindow.right + delta.x;
569                         r.bottom = wndPtr->rectWindow.bottom + delta.y;
570
571                         pt.x = -r.left; pt.y = -r.top;
572
573                         hrgn2 = REGION_CropRgn( hrgn2, hrgn, &r, &pt );
574
575                         GetRgnBox( hrgn2, &r2 );
576                         if( !IsRectEmpty( &r2 ) )
577                         {
578                             PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, hrgn2, flags,
579                                                 RDW_EX_USEHRGN | RDW_EX_XYWINDOW );
580                         }
581                     }
582                 }
583                 WIN_ReleaseWinArray(list);
584            }
585         }
586         else
587         {
588             if( (list = WIN_BuildWinArray( wndPtr, 0, NULL )) )
589             {
590                 for (ppWnd = list; *ppWnd; ppWnd++)
591                 {
592                     WIN_UpdateWndPtr(&wndPtr,*ppWnd);
593                     if (IsWindow( wndPtr->hwndSelf ))
594                         PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, flags, 0 );
595                 }
596                 WIN_ReleaseWinArray(list);
597             }
598         }
599
600     }
601
602 END:
603     if( hrgn2 > 1 && (hrgn2 != hrgnUpdate) )
604         DeleteObject( hrgn2 );
605     if( hrgn > 1 && (hrgn != hrgnUpdate) )
606         DeleteObject( hrgn );
607     WIN_ReleaseWndPtr(wndPtr);
608     return TRUE;
609 }
610
611
612 /***********************************************************************
613  *           RedrawWindow32    (USER32.426)
614  */
615 BOOL WINAPI RedrawWindow( HWND hwnd, const RECT *rectUpdate,
616                               HRGN hrgnUpdate, UINT flags )
617 {
618     return PAINT_RedrawWindow( hwnd, rectUpdate, hrgnUpdate, flags, 0 );
619 }
620
621
622 /***********************************************************************
623  *           RedrawWindow16    (USER.290)
624  */
625 BOOL16 WINAPI RedrawWindow16( HWND16 hwnd, const RECT16 *rectUpdate,
626                               HRGN16 hrgnUpdate, UINT16 flags )
627 {
628     if (rectUpdate)
629     {
630         RECT r;
631         CONV_RECT16TO32( rectUpdate, &r );
632         return (BOOL16)RedrawWindow( (HWND)hwnd, &r, hrgnUpdate, flags );
633     }
634     return (BOOL16)PAINT_RedrawWindow( (HWND)hwnd, NULL, 
635                                        (HRGN)hrgnUpdate, flags, 0 );
636 }
637
638
639 /***********************************************************************
640  *           UpdateWindow16   (USER.124)
641  */
642 void WINAPI UpdateWindow16( HWND16 hwnd )
643 {
644     PAINT_RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN, 0 );
645 }
646
647 /***********************************************************************
648  *           UpdateWindow32   (USER32.567)
649  */
650 void WINAPI UpdateWindow( HWND hwnd )
651 {
652     PAINT_RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN, 0 );
653 }
654
655 /***********************************************************************
656  *           InvalidateRgn16   (USER.126)
657  */
658 void WINAPI InvalidateRgn16( HWND16 hwnd, HRGN16 hrgn, BOOL16 erase )
659 {
660     PAINT_RedrawWindow((HWND)hwnd, NULL, (HRGN)hrgn, 
661                        RDW_INVALIDATE | (erase ? RDW_ERASE : 0), 0 );
662 }
663
664
665 /***********************************************************************
666  *           InvalidateRgn32   (USER32.329)
667  */
668 BOOL WINAPI InvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
669 {
670     return PAINT_RedrawWindow(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0), 0 );
671 }
672
673
674 /***********************************************************************
675  *           InvalidateRect16   (USER.125)
676  */
677 void WINAPI InvalidateRect16( HWND16 hwnd, const RECT16 *rect, BOOL16 erase )
678 {
679     RedrawWindow16( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
680 }
681
682
683 /***********************************************************************
684  *           InvalidateRect32   (USER32.328)
685  */
686 BOOL WINAPI InvalidateRect( HWND hwnd, const RECT *rect, BOOL erase )
687 {
688     return PAINT_RedrawWindow( hwnd, rect, 0, 
689                                RDW_INVALIDATE | (erase ? RDW_ERASE : 0), 0 );
690 }
691
692
693 /***********************************************************************
694  *           ValidateRgn16   (USER.128)
695  */
696 void WINAPI ValidateRgn16( HWND16 hwnd, HRGN16 hrgn )
697 {
698     PAINT_RedrawWindow( (HWND)hwnd, NULL, (HRGN)hrgn, 
699                         RDW_VALIDATE | RDW_NOCHILDREN, 0 );
700 }
701
702
703 /***********************************************************************
704  *           ValidateRgn32   (USER32.572)
705  */
706 void WINAPI ValidateRgn( HWND hwnd, HRGN hrgn )
707 {
708     PAINT_RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN, 0 );
709 }
710
711
712 /***********************************************************************
713  *           ValidateRect16   (USER.127)
714  */
715 void WINAPI ValidateRect16( HWND16 hwnd, const RECT16 *rect )
716 {
717     RedrawWindow16( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
718 }
719
720
721 /***********************************************************************
722  *           ValidateRect32   (USER32.571)
723  */
724 void WINAPI ValidateRect( HWND hwnd, const RECT *rect )
725 {
726     PAINT_RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN, 0 );
727 }
728
729
730 /***********************************************************************
731  *           GetUpdateRect16   (USER.190)
732  */
733 BOOL16 WINAPI GetUpdateRect16( HWND16 hwnd, LPRECT16 rect, BOOL16 erase )
734 {
735     RECT r;
736     BOOL16 ret;
737
738     if (!rect) return GetUpdateRect( hwnd, NULL, erase );
739     ret = GetUpdateRect( hwnd, &r, erase );
740     CONV_RECT32TO16( &r, rect );
741     return ret;
742 }
743
744
745 /***********************************************************************
746  *           GetUpdateRect32   (USER32.297)
747  */
748 BOOL WINAPI GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
749 {
750     BOOL retvalue;
751     WND * wndPtr = WIN_FindWndPtr( hwnd );
752     if (!wndPtr) return FALSE;
753
754     if (rect)
755     {
756         if (wndPtr->hrgnUpdate > 1)
757         {
758             HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
759             if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR)
760             {
761                 retvalue = FALSE;
762                 goto END;
763             }
764             GetRgnBox( hrgn, rect );
765             DeleteObject( hrgn );
766             if (wndPtr->class->style & CS_OWNDC)
767             {
768                 if (GetMapMode(wndPtr->dce->hDC) != MM_TEXT)
769                 {
770                     DPtoLP (wndPtr->dce->hDC, (LPPOINT)rect,  2);
771                 }
772             }
773         }
774         else
775         if( wndPtr->hrgnUpdate == 1 )
776         {
777             GetClientRect( hwnd, rect );
778             if (erase) RedrawWindow( hwnd, NULL, 0, RDW_FRAME | RDW_ERASENOW | RDW_NOCHILDREN );
779         }
780         else 
781             SetRectEmpty( rect );
782     }
783     retvalue = (wndPtr->hrgnUpdate >= 1);
784 END:
785     WIN_ReleaseWndPtr(wndPtr);
786     return retvalue;
787 }
788
789
790 /***********************************************************************
791  *           GetUpdateRgn16   (USER.237)
792  */
793 INT16 WINAPI GetUpdateRgn16( HWND16 hwnd, HRGN16 hrgn, BOOL16 erase )
794 {
795     return GetUpdateRgn( hwnd, hrgn, erase );
796 }
797
798
799 /***********************************************************************
800  *           GetUpdateRgn    (USER32.298)
801  */
802 INT WINAPI GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
803 {
804     INT retval;
805     WND * wndPtr = WIN_FindWndPtr( hwnd );
806     if (!wndPtr) return ERROR;
807
808     if (wndPtr->hrgnUpdate == 0)
809     {
810         SetRectRgn( hrgn, 0, 0, 0, 0 );
811         retval = NULLREGION;
812         goto END;
813     }
814     else
815     if (wndPtr->hrgnUpdate == 1)
816     {
817         SetRectRgn( hrgn, 0, 0, wndPtr->rectClient.right - wndPtr->rectClient.left,
818                                 wndPtr->rectClient.bottom - wndPtr->rectClient.top );
819         retval = SIMPLEREGION;
820     }
821     else
822     {
823         retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
824         OffsetRgn( hrgn, wndPtr->rectWindow.left - wndPtr->rectClient.left,
825                          wndPtr->rectWindow.top - wndPtr->rectClient.top );
826     }
827     if (erase) RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN );
828 END:
829     WIN_ReleaseWndPtr(wndPtr);
830     return retval;
831 }
832
833
834 /***********************************************************************
835  *           ExcludeUpdateRgn16   (USER.238)
836  */
837 INT16 WINAPI ExcludeUpdateRgn16( HDC16 hdc, HWND16 hwnd )
838 {
839     return ExcludeUpdateRgn( hdc, hwnd );
840 }
841
842
843 /***********************************************************************
844  *           ExcludeUpdateRgn32   (USER32.195)
845  */
846 INT WINAPI ExcludeUpdateRgn( HDC hdc, HWND hwnd )
847 {
848     RECT rect;
849     WND * wndPtr;
850
851     if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
852
853     if (wndPtr->hrgnUpdate)
854     {
855         INT ret;
856         HRGN hrgn = CreateRectRgn(wndPtr->rectWindow.left - wndPtr->rectClient.left,
857                                       wndPtr->rectWindow.top - wndPtr->rectClient.top,
858                                       wndPtr->rectWindow.right - wndPtr->rectClient.left,
859                                       wndPtr->rectWindow.bottom - wndPtr->rectClient.top);
860         if( wndPtr->hrgnUpdate > 1 )
861         {
862             CombineRgn(hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY);
863             OffsetRgn(hrgn, wndPtr->rectWindow.left - wndPtr->rectClient.left, 
864                             wndPtr->rectWindow.top - wndPtr->rectClient.top );
865         }
866
867         /* do ugly coordinate translations in dce.c */
868
869         ret = DCE_ExcludeRgn( hdc, wndPtr, hrgn );
870         DeleteObject( hrgn );
871         WIN_ReleaseWndPtr(wndPtr);
872         return ret;
873     } 
874     WIN_ReleaseWndPtr(wndPtr);
875     return GetClipBox( hdc, &rect );
876 }
877
878