* Sync up to trunk head (r64959).
[reactos.git] / win32ss / user / user32 / windows / paint.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * PROJECT: ReactOS user32.dll
21 * FILE: dll/win32/user32/windows/paint.c
22 * PURPOSE: Input
23 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
24 * UPDATE HISTORY:
25 * 09-05-2001 CSH Created
26 */
27
28 /* INCLUDES ******************************************************************/
29
30 #include <user32.h>
31
32 static HBRUSH FrameBrushes[13];
33 static HBITMAP hHatch;
34 const DWORD HatchBitmap[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
35
36 BOOL WINAPI MirrorRgn(HWND hwnd, HRGN hrgn);
37 BOOL WINAPI PolyPatBlt(HDC,DWORD,PPATRECT,INT,ULONG);
38
39 /* FUNCTIONS *****************************************************************/
40
41 INT
42 WINAPI
43 MirrorWindowRect( PWND pWnd, LPRECT lprc)
44 {
45 INT Ret = pWnd->rcWindow.right - pWnd->rcWindow.left - lprc->left;
46 lprc->left = pWnd->rcWindow.right - pWnd->rcWindow.left - lprc->right;
47 lprc->right = Ret;
48 return Ret;
49 }
50
51 VOID
52 CreateFrameBrushes(VOID)
53 {
54 FrameBrushes[0] = CreateSolidBrush(RGB(0,0,0));
55 FrameBrushes[1] = CreateSolidBrush(RGB(0,0,128));
56 FrameBrushes[2] = CreateSolidBrush(RGB(10,36,106));
57 FrameBrushes[3] = CreateSolidBrush(RGB(128,128,128));
58 FrameBrushes[4] = CreateSolidBrush(RGB(181,181,181));
59 FrameBrushes[5] = CreateSolidBrush(RGB(212,208,200));
60 FrameBrushes[6] = CreateSolidBrush(RGB(236,233,216));
61 FrameBrushes[7] = CreateSolidBrush(RGB(255,255,255));
62 FrameBrushes[8] = CreateSolidBrush(RGB(49,106,197));
63 FrameBrushes[9] = CreateSolidBrush(RGB(58,110,165));
64 FrameBrushes[10] = CreateSolidBrush(RGB(64,64,64));
65 FrameBrushes[11] = CreateSolidBrush(RGB(255,255,225));
66 hHatch = CreateBitmap(8, 8, 1, 1, HatchBitmap);
67 FrameBrushes[12] = CreatePatternBrush(hHatch);
68 }
69
70 VOID
71 DeleteFrameBrushes(VOID)
72 {
73 unsigned Brush;
74
75 for (Brush = 0; Brush < sizeof(FrameBrushes) / sizeof(HBRUSH); Brush++)
76 {
77 if (NULL != FrameBrushes[Brush])
78 {
79 DeleteObject(FrameBrushes[Brush]);
80 FrameBrushes[Brush] = NULL;
81 }
82 }
83 if (NULL != hHatch)
84 {
85 DeleteObject(hHatch);
86 hHatch = NULL;
87 }
88 }
89
90
91 /*
92 * @implemented
93 */
94 BOOL
95 WINAPI
96 GetUpdateRect(
97 HWND Wnd,
98 LPRECT Rect,
99 BOOL Erase)
100 {
101 PWND pWnd;
102
103 pWnd = ValidateHwnd(Wnd);
104 if (!pWnd)
105 return FALSE;
106
107 if ( pWnd->hrgnUpdate ||
108 pWnd->state & (WNDS_SENDERASEBACKGROUND|WNDS_SENDNCPAINT|WNDS_UPDATEDIRTY|WNDS_PAINTNOTPROCESSED))
109 {
110 return NtUserGetUpdateRect(Wnd, Rect, Erase);
111 }
112
113 if (Rect)
114 { // Did the Rgn update? No! Back set and shutup!
115 Rect->left = Rect->right = Rect->top = Rect->bottom = 0;
116 }
117 return FALSE; // msdn: "If there is no update region, the return value is zero."
118
119 }
120
121
122 /*
123 * @implemented
124 */
125 int
126 WINAPI
127 GetUpdateRgn(
128 HWND hWnd,
129 HRGN hRgn,
130 BOOL bErase)
131 {
132 PWND pWnd;
133
134 if (!hRgn)
135 {
136 SetLastError(ERROR_INVALID_HANDLE);
137 return ERROR;
138 }
139
140 pWnd = ValidateHwnd(hWnd);
141 if (!pWnd)
142 return ERROR;
143
144 if ( pWnd->hrgnUpdate ||
145 pWnd->state & (WNDS_SENDERASEBACKGROUND|WNDS_SENDNCPAINT|WNDS_UPDATEDIRTY|WNDS_PAINTNOTPROCESSED))
146 {
147 return NtUserGetUpdateRgn(hWnd, hRgn, bErase);
148 }
149 SetRectRgn(hRgn, 0, 0, 0, 0);
150 return NULLREGION;
151 }
152
153
154 /*
155 * @implemented
156 */
157 BOOL WINAPI
158 ScrollDC(
159 HDC hDC,
160 int dx,
161 int dy,
162 CONST RECT *lprcScroll,
163 CONST RECT *lprcClip,
164 HRGN hrgnUpdate,
165 LPRECT lprcUpdate)
166 {
167 if (hDC == NULL) return FALSE;
168
169 if (dx == 0 && dy == 0)
170 {
171 if (hrgnUpdate) SetRectRgn(hrgnUpdate, 0, 0, 0, 0);
172 if (lprcUpdate) lprcUpdate->left = lprcUpdate->right =
173 lprcUpdate->top = lprcUpdate->bottom = 0;
174 return TRUE;
175 }
176
177 return NtUserScrollDC( hDC,
178 dx,
179 dy,
180 lprcScroll,
181 lprcClip,
182 hrgnUpdate,
183 lprcUpdate);
184 }
185
186 /*
187 * @implemented
188 */
189 int
190 WINAPI
191 SetWindowRgn(
192 HWND hWnd,
193 HRGN hRgn,
194 BOOL bRedraw)
195 {
196 BOOL Hook;
197 int Ret = 0;
198
199 LoadUserApiHook();
200
201 Hook = BeginIfHookedUserApiHook();
202
203 /* Bypass SEH and go direct. */
204 if (!Hook)
205 {
206 Ret = NtUserSetWindowRgn(hWnd, hRgn, bRedraw);
207 if (Ret)
208 DeleteObject(hRgn);
209 return Ret;
210 }
211
212 _SEH2_TRY
213 {
214 Ret = guah.SetWindowRgn(hWnd, hRgn, bRedraw);
215 }
216 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
217 {
218 }
219 _SEH2_END;
220
221 EndUserApiHook();
222
223 return Ret;
224 }
225
226 /*
227 * @implemented
228 */
229 BOOL
230 WINAPI
231 UpdateWindow(
232 HWND hWnd)
233 {
234 PWND pWnd = ValidateHwnd(hWnd);
235
236 if (!pWnd)
237 return FALSE;
238
239 if ( pWnd->hrgnUpdate ||
240 pWnd->state & WNDS_INTERNALPAINT ||
241 pWnd->spwndChild )
242 {
243 return NtUserxUpdateWindow(hWnd);
244 }
245 return TRUE;
246 }
247
248 /*
249 * @implemented
250 */
251 BOOL
252 WINAPI
253 ValidateRgn(
254 HWND hWnd,
255 HRGN hRgn)
256 {
257 return NtUserxValidateRgn(hWnd, hRgn);
258 }
259
260 /*
261 * @implemented
262 */
263 int
264 WINAPI
265 GetWindowRgn(
266 HWND hWnd,
267 HRGN hRgn)
268 {
269 PWND pWnd;
270 int Ret;
271
272 if (!hRgn)
273 return ERROR;
274
275 pWnd = ValidateHwnd(hWnd);
276
277 if (!pWnd || !pWnd->hrgnClip || pWnd->state2 & WNDS2_MAXIMIZEDMONITORREGION)
278 return ERROR;
279
280 Ret = CombineRgn(hRgn, pWnd->hrgnClip, NULL, RGN_COPY);
281
282 if (!Ret)
283 return ERROR;
284 /*
285 if (hWnd != GetDesktopWindow()) // pWnd->fnid != FNID_DESKTOP)
286 Ret = OffsetRgn(hRgn, -pWnd->rcWindow.left, -pWnd->rcWindow.top);
287 */
288 if (pWnd->ExStyle & WS_EX_LAYOUTRTL)
289 MirrorRgn(hWnd, hRgn);
290
291 return Ret;
292 }
293
294 /*
295 * @implemented
296 */
297 int
298 WINAPI
299 GetWindowRgnBox(
300 HWND hWnd,
301 LPRECT lprc)
302 {
303 PWND pWnd;
304 int Ret;
305
306 if (!lprc)
307 return ERROR;
308
309 pWnd = ValidateHwnd(hWnd);
310
311 if (!pWnd || !pWnd->hrgnClip || pWnd->state2 & WNDS2_MAXIMIZEDMONITORREGION)
312 return ERROR;
313
314 Ret = GetRgnBox(pWnd->hrgnClip, lprc);
315
316 if (!Ret)
317 return ERROR;
318 /*
319 if (hWnd != GetDesktopWindow()) // pWnd->fnid != FNID_DESKTOP)
320 OffsetRect(lprc, -pWnd->rcWindow.left, -pWnd->rcWindow.top);
321 */
322 if (pWnd->ExStyle & WS_EX_LAYOUTRTL)
323 MirrorWindowRect(pWnd, lprc);
324
325 return Ret;
326 }
327
328
329 const BYTE MappingTable[33] = {5,9,2,3,5,7,0,0,0,7,5,5,3,2,7,5,3,3,0,5,7,10,5,0,11,4,1,1,3,8,6,12,7};
330 /*
331 * @implemented
332 */
333 BOOL
334 WINAPI
335 DrawFrame(
336 HDC hDc,
337 RECT *r,
338 DWORD width,
339 DWORD type
340 )
341 {
342 DWORD rop;
343 DWORD brush;
344 HBRUSH hbrFrame;
345 PATRECT p[4];
346 if (NULL == FrameBrushes[0])
347 {
348 CreateFrameBrushes();
349 }
350 if (type & 4)
351 {
352 rop = PATINVERT;
353 }
354 else
355 {
356 rop = PATCOPY;
357 }
358 brush = type / 8;
359 if (brush >= 33)
360 {
361 brush = 32;
362 }
363 brush = MappingTable[brush];
364 hbrFrame = FrameBrushes[brush];
365 p[0].hBrush = hbrFrame;
366 p[1].hBrush = hbrFrame;
367 p[2].hBrush = hbrFrame;
368 p[3].hBrush = hbrFrame;
369 p[0].r.left = r->left;
370 p[0].r.top = r->top;
371 p[0].r.right = r->right - r->left;
372 p[0].r.bottom = width;
373 p[1].r.left = r->left;
374 p[1].r.top = r->bottom - width;
375 p[1].r.right = r->right - r->left;
376 p[1].r.bottom = width;
377 p[2].r.left = r->left;
378 p[2].r.top = r->top + width;
379 p[2].r.right = width;
380 p[2].r.bottom = r->bottom - r->top - (width * 2);
381 p[3].r.left = r->right - width;
382 p[3].r.top = r->top + width;
383 p[3].r.right = width;
384 p[3].r.bottom = r->bottom - r->top - (width * 2);
385 return PolyPatBlt(hDc,rop,p,4,0);
386 }