Release 950122
[wine/multimedia.git] / windows / painting.c
blobe44110bd070df201b57090c2a13ca5b5ed19e5db
1 /*
2 * Window painting functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include <stdio.h>
8 #include <X11/Xlib.h>
10 #include "win.h"
11 #include "message.h"
12 #include "gdi.h"
13 #include "stddebug.h"
14 /* #define DEBUG_WIN */
15 #include "debug.h"
17 /* Last CTLCOLOR id */
18 #define CTLCOLOR_MAX CTLCOLOR_STATIC
21 /***********************************************************************
22 * BeginPaint (USER.39)
24 HDC BeginPaint( HWND hwnd, LPPAINTSTRUCT lps )
26 HRGN hrgnUpdate;
27 WND * wndPtr = WIN_FindWndPtr( hwnd );
28 if (!wndPtr) return 0;
30 hrgnUpdate = wndPtr->hrgnUpdate; /* Save update region */
31 if (!hrgnUpdate) /* Create an empty region */
32 if (!(hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 ))) return 0;
34 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
35 MSG_DecPaintCount( wndPtr->hmemTaskQ );
37 wndPtr->hrgnUpdate = 0;
38 wndPtr->flags &= ~(WIN_NEEDS_BEGINPAINT | WIN_INTERNAL_PAINT);
40 if (wndPtr->flags & WIN_NEEDS_NCPAINT)
42 SendMessage( hwnd, WM_NCPAINT, 0, 0 );
43 wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
46 lps->hdc = GetDCEx( hwnd, hrgnUpdate, DCX_INTERSECTRGN | DCX_USESTYLE );
47 DeleteObject( hrgnUpdate );
48 if (!lps->hdc)
50 fprintf( stderr, "GetDCEx() failed in BeginPaint(), hwnd=%x\n", hwnd );
51 return 0;
54 GetRgnBox( InquireVisRgn(lps->hdc), &lps->rcPaint );
55 DPtoLP( lps->hdc, (LPPOINT)&lps->rcPaint, 2 );
57 if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
59 lps->fErase = !SendMessage( hwnd, WM_ERASEBKGND, lps->hdc, 0 );
60 wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
62 else lps->fErase = TRUE;
64 return lps->hdc;
68 /***********************************************************************
69 * EndPaint (USER.40)
71 void EndPaint( HWND hwnd, LPPAINTSTRUCT lps )
73 ReleaseDC( hwnd, lps->hdc );
77 /***********************************************************************
78 * FillWindow (USER.324)
80 void FillWindow( HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush )
82 RECT rect;
83 GetClientRect( hwnd, &rect );
84 DPtoLP( hdc, (LPPOINT)&rect, 2 );
85 PaintRect( hwndParent, hwnd, hdc, hbrush, &rect );
89 /***********************************************************************
90 * PaintRect (USER.325)
92 void PaintRect(HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush, LPRECT rect)
94 /* Send WM_CTLCOLOR message if needed */
96 if (hbrush <= CTLCOLOR_MAX)
98 if (!hwndParent) return;
99 hbrush = (HBRUSH)SendMessage( hwndParent, WM_CTLCOLOR,
100 hdc, MAKELONG( hwnd, hbrush ) );
102 if (hbrush) FillRect( hdc, rect, hbrush );
106 /***********************************************************************
107 * RedrawWindow (USER.290)
109 BOOL RedrawWindow( HWND hwnd, LPRECT rectUpdate, HRGN hrgnUpdate, UINT flags )
111 HRGN tmpRgn, hrgn = 0;
112 RECT rectClient, rectWindow;
113 WND * wndPtr;
115 if (!hwnd) hwnd = GetDesktopWindow();
116 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
117 if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
118 return TRUE; /* No redraw needed */
120 if (rectUpdate)
122 dprintf_win( stddeb, "RedrawWindow: %x %d,%d-%d,%d %x flags=%04x\n",
123 hwnd, rectUpdate->left, rectUpdate->top,
124 rectUpdate->right, rectUpdate->bottom, hrgnUpdate, flags);
126 else
128 dprintf_win( stddeb, "RedrawWindow: %x NULL %x flags=%04x\n",
129 hwnd, hrgnUpdate, flags);
131 GetClientRect( hwnd, &rectClient );
132 rectWindow = wndPtr->rectWindow;
133 OffsetRect(&rectWindow, -wndPtr->rectClient.left, -wndPtr->rectClient.top);
135 if (flags & RDW_INVALIDATE) /* Invalidate */
137 if (hrgnUpdate) /* Invalidate a region */
139 if (flags & RDW_FRAME) tmpRgn = CreateRectRgnIndirect(&rectWindow);
140 else tmpRgn = CreateRectRgnIndirect( &rectClient );
141 if (!tmpRgn) return FALSE;
142 hrgn = CreateRectRgn( 0, 0, 0, 0 );
143 if (CombineRgn( hrgn, hrgnUpdate, tmpRgn, RGN_AND ) == NULLREGION)
145 DeleteObject( hrgn );
146 hrgn = 0;
148 DeleteObject( tmpRgn );
150 else /* Invalidate a rectangle */
152 RECT rect;
153 if (flags & RDW_FRAME)
155 if (rectUpdate) IntersectRect( &rect, rectUpdate, &rectWindow);
156 else rect = rectWindow;
158 else
160 if (rectUpdate) IntersectRect( &rect, rectUpdate, &rectClient);
161 else rect = rectClient;
163 if (!IsRectEmpty(&rect)) hrgn = CreateRectRgnIndirect( &rect );
166 /* Set update region */
168 if (hrgn)
170 if (!wndPtr->hrgnUpdate)
172 wndPtr->hrgnUpdate = hrgn;
173 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
174 MSG_IncPaintCount( wndPtr->hmemTaskQ );
176 else
178 tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
179 CombineRgn( tmpRgn, wndPtr->hrgnUpdate, hrgn, RGN_OR );
180 DeleteObject( wndPtr->hrgnUpdate );
181 DeleteObject( hrgn );
182 wndPtr->hrgnUpdate = tmpRgn;
185 if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
186 if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
187 flags |= RDW_FRAME; /* Force invalidating the frame of children */
189 else if (flags & RDW_VALIDATE) /* Validate */
191 if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
192 if (!(hrgn = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
194 /* Remove frame from update region */
196 if (wndPtr->hrgnUpdate && (flags & RDW_NOFRAME))
198 if (!(tmpRgn = CreateRectRgnIndirect( &rectClient )))
199 return FALSE;
200 if (CombineRgn(hrgn,tmpRgn,wndPtr->hrgnUpdate,RGN_AND) == NULLREGION)
202 DeleteObject( hrgn );
203 hrgn = 0;
205 DeleteObject( tmpRgn );
206 DeleteObject( wndPtr->hrgnUpdate );
207 wndPtr->hrgnUpdate = hrgn;
208 hrgn = CreateRectRgn( 0, 0, 0, 0 );
211 /* Set update region */
213 if (wndPtr->hrgnUpdate)
215 int res;
216 if (hrgnUpdate) /* Validate a region */
218 res = CombineRgn(hrgn,wndPtr->hrgnUpdate,hrgnUpdate,RGN_DIFF);
220 else /* Validate a rectangle */
222 if (rectUpdate) tmpRgn = CreateRectRgnIndirect( rectUpdate );
223 else tmpRgn = CreateRectRgnIndirect( &rectWindow );
224 res = CombineRgn( hrgn, wndPtr->hrgnUpdate, tmpRgn, RGN_DIFF );
225 DeleteObject( tmpRgn );
227 DeleteObject( wndPtr->hrgnUpdate );
228 if (res == NULLREGION)
230 DeleteObject( hrgn );
231 wndPtr->hrgnUpdate = 0;
232 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
233 MSG_DecPaintCount( wndPtr->hmemTaskQ );
235 else wndPtr->hrgnUpdate = hrgn;
239 /* Set/clear internal paint flag */
241 if (flags & RDW_INTERNALPAINT)
243 if (!wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT))
244 MSG_IncPaintCount( wndPtr->hmemTaskQ );
245 wndPtr->flags |= WIN_INTERNAL_PAINT;
247 else if (flags & RDW_NOINTERNALPAINT)
249 if (!wndPtr->hrgnUpdate && (wndPtr->flags & WIN_INTERNAL_PAINT))
250 MSG_DecPaintCount( wndPtr->hmemTaskQ );
251 wndPtr->flags &= ~WIN_INTERNAL_PAINT;
254 /* Erase/update window */
256 if (flags & RDW_UPDATENOW) SendMessage( hwnd, WM_PAINT, 0, 0 );
257 else if (flags & RDW_ERASENOW)
259 if (wndPtr->flags & WIN_NEEDS_NCPAINT)
261 SendMessage( hwnd, WM_NCPAINT, 0, 0 );
262 wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
264 if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
266 HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
267 DCX_INTERSECTRGN | DCX_USESTYLE );
268 if (hdc)
270 /* Don't send WM_ERASEBKGND to icons */
271 /* (WM_ICONERASEBKGND is sent during processing of WM_NCPAINT) */
272 if (!(wndPtr->dwStyle & WS_MINIMIZE)
273 || !WIN_CLASS_INFO(wndPtr).hIcon)
275 if (SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 ))
276 wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
278 ReleaseDC( hwnd, hdc );
283 /* Recursively process children */
285 if (!(flags & RDW_NOCHILDREN) &&
286 ((flags && RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)))
288 if (hrgnUpdate)
290 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
291 if (!hrgn) return TRUE;
292 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
294 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
295 CombineRgn( hrgn, hrgnUpdate, 0, RGN_COPY );
296 OffsetRgn( hrgn, -wndPtr->rectClient.left,
297 -wndPtr->rectClient.top );
298 RedrawWindow( hwnd, NULL, hrgn, flags );
300 DeleteObject( hrgn );
302 else
304 RECT rect;
305 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
307 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
308 if (rectUpdate)
310 rect = *rectUpdate;
311 OffsetRect( &rect, -wndPtr->rectClient.left,
312 -wndPtr->rectClient.top );
313 RedrawWindow( hwnd, &rect, 0, flags );
315 else RedrawWindow( hwnd, NULL, 0, flags );
319 return TRUE;
323 /***********************************************************************
324 * UpdateWindow (USER.124)
326 void UpdateWindow( HWND hwnd )
328 RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN );
332 /***********************************************************************
333 * InvalidateRgn (USER.126)
335 void InvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
337 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
341 /***********************************************************************
342 * InvalidateRect (USER.125)
344 void InvalidateRect( HWND hwnd, LPRECT rect, BOOL erase )
346 RedrawWindow( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
350 /***********************************************************************
351 * ValidateRgn (USER.128)
353 void ValidateRgn( HWND hwnd, HRGN hrgn )
355 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
359 /***********************************************************************
360 * ValidateRect (USER.127)
362 void ValidateRect( HWND hwnd, LPRECT rect )
364 RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
368 /***********************************************************************
369 * GetUpdateRect (USER.190)
371 BOOL GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
373 WND * wndPtr = WIN_FindWndPtr( hwnd );
374 if (!wndPtr) return FALSE;
376 if (rect)
378 if (wndPtr->hrgnUpdate)
380 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
381 if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR) return FALSE;
382 GetRgnBox( hrgn, rect );
383 DeleteObject( hrgn );
385 else SetRectEmpty( rect );
387 return (wndPtr->hrgnUpdate != 0);
391 /***********************************************************************
392 * GetUpdateRgn (USER.237)
394 int GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
396 HRGN hrgnClip;
397 int retval;
398 WND * wndPtr = WIN_FindWndPtr( hwnd );
399 if (!wndPtr) return ERROR;
401 if (!wndPtr->hrgnUpdate)
403 SetRectRgn( hrgn, 0, 0, 0, 0 );
404 return NULLREGION;
406 hrgnClip = CreateRectRgn( 0, 0,
407 wndPtr->rectClient.right-wndPtr->rectClient.left,
408 wndPtr->rectClient.bottom-wndPtr->rectClient.top);
409 if (!hrgnClip) return ERROR;
410 retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, hrgnClip, RGN_AND );
411 if (erase) RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN );
412 DeleteObject( hrgnClip );
413 return retval;
417 /***********************************************************************
418 * ExcludeUpdateRgn (USER.238)
420 int ExcludeUpdateRgn( HDC hdc, HWND hwnd )
422 int retval = ERROR;
423 HRGN hrgn;
424 WND * wndPtr;
426 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
427 if ((hrgn = CreateRectRgn( 0, 0, 0, 0 )) != 0)
429 retval = CombineRgn( hrgn, InquireVisRgn(hdc),
430 wndPtr->hrgnUpdate, RGN_DIFF );
431 if (retval) SelectVisRgn( hdc, hrgn );
432 DeleteObject( hrgn );
434 return retval;