Release 960218
[wine/testsucceed.git] / windows / painting.c
blob18d6e3c67ba853d14eb59efd4445b7eb00a0cb8a
1 /*
2 * Window painting functions
4 * Copyright 1993, 1994, 1995 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 wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
43 SendMessage( hwnd, WM_NCPAINT, 0, 0 );
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="NPFMT"\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 wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
60 lps->fErase = !SendMessage( hwnd, WM_ERASEBKGND, (WPARAM)lps->hdc, 0 );
62 else lps->fErase = TRUE;
64 return lps->hdc;
68 /***********************************************************************
69 * EndPaint (USER.40)
71 BOOL EndPaint( HWND hwnd, const PAINTSTRUCT* lps )
73 ReleaseDC( hwnd, lps->hdc );
74 return TRUE;
78 /***********************************************************************
79 * FillWindow (USER.324)
81 void FillWindow( HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush )
83 RECT rect;
84 GetClientRect( hwnd, &rect );
85 DPtoLP( hdc, (LPPOINT)&rect, 2 );
86 PaintRect( hwndParent, hwnd, hdc, hbrush, &rect );
90 /***********************************************************************
91 * PaintRect (USER.325)
93 void PaintRect(HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush, LPRECT rect)
95 /* Send WM_CTLCOLOR message if needed */
97 if ((DWORD)hbrush <= CTLCOLOR_MAX)
99 if (!hwndParent) return;
100 #ifdef WINELIB32
101 hbrush = (HBRUSH)SendMessage( hwndParent,
102 WM_CTLCOLORMSGBOX+(DWORD)hbrush,
103 (WPARAM)hdc, (LPARAM)hwnd );
104 #else
105 hbrush = (HBRUSH)SendMessage( hwndParent, WM_CTLCOLOR,
106 hdc, MAKELONG( hwnd, hbrush ) );
107 #endif
109 if (hbrush) FillRect( hdc, rect, hbrush );
113 /***********************************************************************
114 * GetControlBrush (USER.326)
116 HBRUSH GetControlBrush( HWND hwnd, HDC hdc, WORD control )
118 #ifdef WINELIB32
119 return (HBRUSH)SendMessage( GetParent(hwnd), WM_CTLCOLOR+control,
120 (WPARAM)hdc, (LPARAM)hwnd );
121 #else
122 return (HBRUSH)SendMessage( GetParent(hwnd), WM_CTLCOLOR,
123 hdc, MAKELONG( hwnd, control ) );
124 #endif
128 /***********************************************************************
129 * RedrawWindow (USER.290)
131 BOOL RedrawWindow( HWND hwnd, LPRECT rectUpdate, HRGN hrgnUpdate, UINT flags )
133 HRGN tmpRgn, hrgn;
134 RECT rectClient;
135 WND * wndPtr;
137 if (!hwnd) hwnd = GetDesktopWindow();
138 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
139 if (!IsWindowVisible(hwnd) || (wndPtr->flags & WIN_NO_REDRAW))
140 return TRUE; /* No redraw needed */
142 if (rectUpdate)
144 dprintf_win( stddeb, "RedrawWindow: "NPFMT" %ld,%ld-%ld,%ld "NPFMT" flags=%04x\n",
145 hwnd, (LONG)rectUpdate->left, (LONG)rectUpdate->top,
146 (LONG)rectUpdate->right, (LONG)rectUpdate->bottom, hrgnUpdate, flags);
148 else
150 dprintf_win( stddeb, "RedrawWindow: "NPFMT" NULL "NPFMT" flags=%04x\n",
151 hwnd, hrgnUpdate, flags);
153 GetClientRect( hwnd, &rectClient );
155 if (flags & RDW_INVALIDATE) /* Invalidate */
157 if (wndPtr->hrgnUpdate) /* Is there already an update region? */
159 tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
160 if ((hrgn = hrgnUpdate) == 0)
161 hrgn = CreateRectRgnIndirect( rectUpdate ? rectUpdate :
162 &rectClient );
163 CombineRgn( tmpRgn, wndPtr->hrgnUpdate, hrgn, RGN_OR );
164 DeleteObject( wndPtr->hrgnUpdate );
165 wndPtr->hrgnUpdate = tmpRgn;
166 if (!hrgnUpdate) DeleteObject( hrgn );
168 else /* No update region yet */
170 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
171 MSG_IncPaintCount( wndPtr->hmemTaskQ );
172 if (hrgnUpdate)
174 wndPtr->hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
175 CombineRgn( wndPtr->hrgnUpdate, hrgnUpdate, 0, RGN_COPY );
177 else wndPtr->hrgnUpdate = CreateRectRgnIndirect( rectUpdate ?
178 rectUpdate : &rectClient );
180 if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
181 if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
182 flags |= RDW_FRAME; /* Force invalidating the frame of children */
184 else if (flags & RDW_VALIDATE) /* Validate */
186 /* We need an update region in order to validate anything */
187 if (wndPtr->hrgnUpdate)
189 if (!hrgnUpdate && !rectUpdate)
191 /* Special case: validate everything */
192 DeleteObject( wndPtr->hrgnUpdate );
193 wndPtr->hrgnUpdate = 0;
195 else
197 tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
198 if ((hrgn = hrgnUpdate) == 0)
199 hrgn = CreateRectRgnIndirect( rectUpdate );
200 if (CombineRgn( tmpRgn, wndPtr->hrgnUpdate,
201 hrgn, RGN_DIFF ) == NULLREGION)
203 DeleteObject( tmpRgn );
204 tmpRgn = 0;
206 DeleteObject( wndPtr->hrgnUpdate );
207 wndPtr->hrgnUpdate = tmpRgn;
208 if (!hrgnUpdate) DeleteObject( hrgn );
210 if (!wndPtr->hrgnUpdate) /* No more update region */
211 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
212 MSG_DecPaintCount( wndPtr->hmemTaskQ );
214 if (flags & RDW_NOFRAME) wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
215 if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
218 /* Set/clear internal paint flag */
220 if (flags & RDW_INTERNALPAINT)
222 if (!wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT))
223 MSG_IncPaintCount( wndPtr->hmemTaskQ );
224 wndPtr->flags |= WIN_INTERNAL_PAINT;
226 else if (flags & RDW_NOINTERNALPAINT)
228 if (!wndPtr->hrgnUpdate && (wndPtr->flags & WIN_INTERNAL_PAINT))
229 MSG_DecPaintCount( wndPtr->hmemTaskQ );
230 wndPtr->flags &= ~WIN_INTERNAL_PAINT;
233 /* Erase/update window */
235 if (flags & RDW_UPDATENOW) SendMessage( hwnd, WM_PAINT, 0, 0 );
236 else if (flags & RDW_ERASENOW)
238 if (wndPtr->flags & WIN_NEEDS_NCPAINT)
240 wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
241 SendMessage( hwnd, WM_NCPAINT, 0, 0 );
243 if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
245 HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
246 DCX_INTERSECTRGN | DCX_USESTYLE );
247 if (hdc)
249 /* Don't send WM_ERASEBKGND to icons */
250 /* (WM_ICONERASEBKGND is sent during processing of WM_NCPAINT) */
251 if (!(wndPtr->dwStyle & WS_MINIMIZE)
252 || !WIN_CLASS_INFO(wndPtr).hIcon)
254 if (SendMessage( hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0 ))
255 wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
257 ReleaseDC( hwnd, hdc );
262 /* Recursively process children */
264 if (!(flags & RDW_NOCHILDREN) &&
265 ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)))
267 if (hrgnUpdate)
269 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
270 if (!hrgn) return TRUE;
271 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
273 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
274 CombineRgn( hrgn, hrgnUpdate, 0, RGN_COPY );
275 OffsetRgn( hrgn, -wndPtr->rectClient.left,
276 -wndPtr->rectClient.top );
277 RedrawWindow( hwnd, NULL, hrgn, flags );
279 DeleteObject( hrgn );
281 else
283 RECT rect;
284 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
286 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
287 if (rectUpdate)
289 rect = *rectUpdate;
290 OffsetRect( &rect, -wndPtr->rectClient.left,
291 -wndPtr->rectClient.top );
292 RedrawWindow( hwnd, &rect, 0, flags );
294 else RedrawWindow( hwnd, NULL, 0, flags );
298 return TRUE;
302 /***********************************************************************
303 * UpdateWindow (USER.124)
305 void UpdateWindow( HWND hwnd )
307 RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN );
311 /***********************************************************************
312 * InvalidateRgn (USER.126)
314 void InvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
316 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
320 /***********************************************************************
321 * InvalidateRect (USER.125)
323 void InvalidateRect( HWND hwnd, LPRECT rect, BOOL erase )
325 RedrawWindow( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
329 /***********************************************************************
330 * ValidateRgn (USER.128)
332 void ValidateRgn( HWND hwnd, HRGN hrgn )
334 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
338 /***********************************************************************
339 * ValidateRect (USER.127)
341 void ValidateRect( HWND hwnd, LPRECT rect )
343 RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
347 /***********************************************************************
348 * GetUpdateRect (USER.190)
350 BOOL GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
352 WND * wndPtr = WIN_FindWndPtr( hwnd );
353 if (!wndPtr) return FALSE;
355 if (rect)
357 if (wndPtr->hrgnUpdate)
359 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
360 if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR) return FALSE;
361 GetRgnBox( hrgn, rect );
362 DeleteObject( hrgn );
364 else SetRectEmpty( rect );
366 return (wndPtr->hrgnUpdate != 0);
370 /***********************************************************************
371 * GetUpdateRgn (USER.237)
373 int GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
375 int retval;
376 WND * wndPtr = WIN_FindWndPtr( hwnd );
377 if (!wndPtr) return ERROR;
379 if (!wndPtr->hrgnUpdate)
381 SetRectRgn( hrgn, 0, 0, 0, 0 );
382 return NULLREGION;
384 retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
385 if (erase) RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN );
386 return retval;
390 /***********************************************************************
391 * ExcludeUpdateRgn (USER.238)
393 int ExcludeUpdateRgn( HDC hdc, HWND hwnd )
395 int retval = ERROR;
396 HRGN hrgn;
397 WND * wndPtr;
399 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
400 if ((hrgn = CreateRectRgn( 0, 0, 0, 0 )) != 0)
402 retval = CombineRgn( hrgn, InquireVisRgn(hdc),
403 wndPtr->hrgnUpdate, RGN_DIFF );
404 if (retval) SelectVisRgn( hdc, hrgn );
405 DeleteObject( hrgn );
407 return retval;