Release 940405
[wine.git] / windows / painting.c
blob36c72e722b54d2a1f13ea6ad63d42387d933e177
1 /*
2 * Window painting functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <X11/Xlib.h>
11 #include "win.h"
12 #include "message.h"
14 /* Last CTLCOLOR id */
15 #define CTLCOLOR_MAX CTLCOLOR_STATIC
18 /***********************************************************************
19 * BeginPaint (USER.39)
21 HDC BeginPaint( HWND hwnd, LPPAINTSTRUCT lps )
23 HRGN hrgnUpdate;
24 WND * wndPtr = WIN_FindWndPtr( hwnd );
25 if (!wndPtr) return 0;
27 hrgnUpdate = wndPtr->hrgnUpdate; /* Save update region */
28 if (!hrgnUpdate) /* Create an empty region */
29 if (!(hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 ))) return 0;
31 if (!(lps->hdc = GetDCEx( hwnd, hrgnUpdate,
32 DCX_INTERSECTRGN | DCX_USESTYLE ))) return 0;
33 GetRgnBox( InquireVisRgn(lps->hdc), &lps->rcPaint );
35 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
36 MSG_DecPaintCount( wndPtr->hmemTaskQ );
38 wndPtr->hrgnUpdate = 0;
39 wndPtr->flags &= ~(WIN_NEEDS_BEGINPAINT | WIN_INTERNAL_PAINT);
41 SendMessage( hwnd, WM_NCPAINT, hrgnUpdate, 0 );
42 DeleteObject( hrgnUpdate );
44 if (!(wndPtr->flags & WIN_ERASE_UPDATERGN)) lps->fErase = TRUE;
45 else lps->fErase = !SendMessage( hwnd, WM_ERASEBKGND, lps->hdc, 0 );
47 return lps->hdc;
51 /***********************************************************************
52 * EndPaint (USER.40)
54 void EndPaint( HWND hwnd, LPPAINTSTRUCT lps )
56 ReleaseDC( hwnd, lps->hdc );
60 /***********************************************************************
61 * FillWindow (USER.324)
63 void FillWindow( HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush )
65 RECT rect;
66 GetClientRect( hwnd, &rect );
67 PaintRect( hwndParent, hwnd, hdc, hbrush, &rect );
71 /***********************************************************************
72 * PaintRect (USER.325)
74 void PaintRect(HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush, LPRECT rect)
76 /* Send WM_CTLCOLOR message if needed */
78 if (hbrush <= CTLCOLOR_MAX)
80 if (!hwndParent) return;
81 hbrush = (HBRUSH)SendMessage( hwndParent, WM_CTLCOLOR,
82 hdc, hwnd | (hbrush << 16) );
84 if (hbrush) FillRect( hdc, rect, hbrush );
88 /***********************************************************************
89 * RedrawWindow (USER.290)
91 BOOL RedrawWindow( HWND hwnd, LPRECT rectUpdate, HRGN hrgnUpdate, UINT flags )
93 HRGN tmpRgn, hrgn = 0;
94 RECT rectClient, rectWindow;
95 WND * wndPtr;
97 if (!hwnd) hwnd = GetDesktopWindow();
98 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
100 GetClientRect( hwnd, &rectClient );
101 rectWindow = wndPtr->rectWindow;
102 OffsetRect(&rectWindow, -wndPtr->rectClient.left, -wndPtr->rectClient.top);
104 if (flags & RDW_INVALIDATE) /* Invalidate */
106 if (flags & RDW_ERASE) wndPtr->flags |= WIN_ERASE_UPDATERGN;
108 if (hrgnUpdate) /* Invalidate a region */
110 if (flags & RDW_FRAME) tmpRgn = CreateRectRgnIndirect(&rectWindow);
111 else tmpRgn = CreateRectRgnIndirect( &rectClient );
112 if (!tmpRgn) return FALSE;
113 hrgn = CreateRectRgn( 0, 0, 0, 0 );
114 if (CombineRgn( hrgn, hrgnUpdate, tmpRgn, RGN_AND ) == NULLREGION)
116 DeleteObject( hrgn );
117 hrgn = 0;
119 DeleteObject( tmpRgn );
121 else /* Invalidate a rectangle */
123 RECT rect;
124 if (flags & RDW_FRAME)
126 if (rectUpdate) IntersectRect( &rect, rectUpdate, &rectWindow);
127 else rect = rectWindow;
129 else
131 if (rectUpdate) IntersectRect( &rect, rectUpdate, &rectClient);
132 else rect = rectClient;
134 if (!IsRectEmpty(&rect)) hrgn = CreateRectRgnIndirect( &rect );
137 /* Set update region */
139 if (hrgn)
141 if (!wndPtr->hrgnUpdate)
143 wndPtr->hrgnUpdate = hrgn;
144 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
145 MSG_IncPaintCount( wndPtr->hmemTaskQ );
147 else
149 tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
150 CombineRgn( tmpRgn, wndPtr->hrgnUpdate, hrgn, RGN_OR );
151 DeleteObject( wndPtr->hrgnUpdate );
152 DeleteObject( hrgn );
153 wndPtr->hrgnUpdate = tmpRgn;
156 flags |= RDW_FRAME; /* Force invalidating the frame of children */
158 else if (flags & RDW_VALIDATE) /* Validate */
160 if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_ERASE_UPDATERGN;
161 if (!(hrgn = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
163 /* Remove frame from update region */
165 if (wndPtr->hrgnUpdate && (flags & RDW_NOFRAME))
167 if (!(tmpRgn = CreateRectRgnIndirect( &rectClient )))
168 return FALSE;
169 if (CombineRgn(hrgn,tmpRgn,wndPtr->hrgnUpdate,RGN_AND) == NULLREGION)
171 DeleteObject( hrgn );
172 hrgn = 0;
174 DeleteObject( tmpRgn );
175 DeleteObject( wndPtr->hrgnUpdate );
176 wndPtr->hrgnUpdate = hrgn;
177 hrgn = CreateRectRgn( 0, 0, 0, 0 );
180 /* Set update region */
182 if (wndPtr->hrgnUpdate)
184 int res;
185 if (hrgnUpdate) /* Validate a region */
187 res = CombineRgn(hrgn,wndPtr->hrgnUpdate,hrgnUpdate,RGN_DIFF);
189 else /* Validate a rectangle */
191 if (rectUpdate) tmpRgn = CreateRectRgnIndirect( rectUpdate );
192 else tmpRgn = CreateRectRgnIndirect( &rectWindow );
193 res = CombineRgn( hrgn, wndPtr->hrgnUpdate, tmpRgn, RGN_DIFF );
194 DeleteObject( tmpRgn );
196 DeleteObject( wndPtr->hrgnUpdate );
197 if (res == NULLREGION)
199 DeleteObject( hrgn );
200 wndPtr->hrgnUpdate = 0;
201 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
202 MSG_DecPaintCount( wndPtr->hmemTaskQ );
204 else wndPtr->hrgnUpdate = hrgn;
208 /* Set/clear internal paint flag */
210 if (flags & RDW_INTERNALPAINT)
212 if (!wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT))
213 MSG_IncPaintCount( wndPtr->hmemTaskQ );
214 wndPtr->flags |= WIN_INTERNAL_PAINT;
216 else if (flags & RDW_NOINTERNALPAINT)
218 if (!wndPtr->hrgnUpdate && (wndPtr->flags & WIN_INTERNAL_PAINT))
219 MSG_DecPaintCount( wndPtr->hmemTaskQ );
220 wndPtr->flags &= ~WIN_INTERNAL_PAINT;
223 /* Erase/update window */
225 if (flags & RDW_UPDATENOW) UpdateWindow( hwnd );
226 else if (flags & RDW_ERASENOW)
228 HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
229 DCX_INTERSECTRGN | DCX_USESTYLE );
230 if (hdc)
232 SendMessage( hwnd, WM_NCPAINT, wndPtr->hrgnUpdate, 0 );
233 SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
234 ReleaseDC( hwnd, hdc );
238 /* Recursively process children */
240 if (!(flags & RDW_NOCHILDREN) &&
241 ((flags && RDW_ALLCHILDREN) || (wndPtr->dwStyle & WS_CLIPCHILDREN)))
243 if (hrgnUpdate)
245 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
246 if (!hrgn) return TRUE;
247 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
249 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
250 CombineRgn( hrgn, hrgnUpdate, 0, RGN_COPY );
251 OffsetRgn( hrgn, -wndPtr->rectClient.left,
252 -wndPtr->rectClient.top );
253 RedrawWindow( hwnd, NULL, hrgn, flags );
255 DeleteObject( hrgn );
257 else
259 RECT rect;
260 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
262 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
263 if (rectUpdate)
265 rect = *rectUpdate;
266 OffsetRect( &rect, -wndPtr->rectClient.left,
267 -wndPtr->rectClient.top );
268 RedrawWindow( hwnd, &rect, 0, flags );
270 else RedrawWindow( hwnd, NULL, 0, flags );
274 return TRUE;
278 /***********************************************************************
279 * UpdateWindow (USER.124)
281 void UpdateWindow( HWND hwnd )
283 if (GetUpdateRect( hwnd, NULL, FALSE ))
285 if (IsWindowVisible( hwnd )) SendMessage( hwnd, WM_PAINT, 0, 0 );
290 /***********************************************************************
291 * InvalidateRgn (USER.126)
293 void InvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
295 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
299 /***********************************************************************
300 * InvalidateRect (USER.125)
302 void InvalidateRect( HWND hwnd, LPRECT rect, BOOL erase )
304 RedrawWindow( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
308 /***********************************************************************
309 * ValidateRgn (USER.128)
311 void ValidateRgn( HWND hwnd, HRGN hrgn )
313 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
317 /***********************************************************************
318 * ValidateRect (USER.127)
320 void ValidateRect( HWND hwnd, LPRECT rect )
322 RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
326 /***********************************************************************
327 * GetUpdateRect (USER.190)
329 BOOL GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
331 WND * wndPtr = WIN_FindWndPtr( hwnd );
332 if (!wndPtr) return FALSE;
334 if (rect)
336 if (wndPtr->hrgnUpdate)
338 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
339 if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR) return FALSE;
340 GetRgnBox( hrgn, rect );
341 DeleteObject( hrgn );
343 else SetRectEmpty( rect );
345 return (wndPtr->hrgnUpdate != 0);
349 /***********************************************************************
350 * GetUpdateRgn (USER.237)
352 int GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
354 HRGN hrgnClip;
355 int retval;
356 WND * wndPtr = WIN_FindWndPtr( hwnd );
357 if (!wndPtr) return ERROR;
359 if (!wndPtr->hrgnUpdate)
361 if (!(hrgnClip = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
362 retval = CombineRgn( hrgn, hrgnClip, 0, RGN_COPY );
364 else
366 hrgnClip = CreateRectRgn( 0, 0,
367 wndPtr->rectClient.right-wndPtr->rectClient.left,
368 wndPtr->rectClient.bottom-wndPtr->rectClient.top );
369 if (!hrgnClip) return ERROR;
370 retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, hrgnClip, RGN_AND );
371 if (erase)
373 HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
374 DCX_INTERSECTRGN | DCX_USESTYLE );
375 if (hdc)
377 SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
378 ReleaseDC( hwnd, hdc );
382 DeleteObject( hrgnClip );
383 return retval;
387 /***********************************************************************
388 * ExcludeUpdateRgn (USER.238)
390 int ExcludeUpdateRgn( HDC hdc, HWND hwnd )
392 int retval;
393 HRGN hrgn;
394 WND * wndPtr;
396 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
397 if ((hrgn = CreateRectRgn( 0, 0, 0, 0 )) != 0)
399 retval = CombineRgn( hrgn, InquireVisRgn(hdc),
400 wndPtr->hrgnUpdate, RGN_DIFF );
401 if (retval) SelectVisRgn( hdc, hrgn );
402 DeleteObject( hrgn );
404 return retval;