Sync to trunk revision 61757.
[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 #include <wine/debug.h>
33
34 WINE_DEFAULT_DEBUG_CHANNEL(user32);
35
36 static HBRUSH FrameBrushes[13];
37 static HBITMAP hHatch;
38 const DWORD HatchBitmap[4] = {0x5555AAAA, 0x5555AAAA, 0x5555AAAA, 0x5555AAAA};
39
40 BOOL WINAPI MirrorRgn(HWND hwnd, HRGN hrgn);
41 BOOL WINAPI PolyPatBlt(HDC,DWORD,PPATRECT,INT,ULONG);
42
43 /* FUNCTIONS *****************************************************************/
44
45 INT
46 WINAPI
47 MirrorWindowRect( PWND pWnd, LPRECT lprc)
48 {
49 INT Ret = pWnd->rcWindow.right - pWnd->rcWindow.left - lprc->left;
50 lprc->left = pWnd->rcWindow.right - pWnd->rcWindow.left - lprc->right;
51 lprc->right = Ret;
52 return Ret;
53 }
54
55 VOID
56 CreateFrameBrushes(VOID)
57 {
58 FrameBrushes[0] = CreateSolidBrush(RGB(0,0,0));
59 FrameBrushes[1] = CreateSolidBrush(RGB(0,0,128));
60 FrameBrushes[2] = CreateSolidBrush(RGB(10,36,106));
61 FrameBrushes[3] = CreateSolidBrush(RGB(128,128,128));
62 FrameBrushes[4] = CreateSolidBrush(RGB(181,181,181));
63 FrameBrushes[5] = CreateSolidBrush(RGB(212,208,200));
64 FrameBrushes[6] = CreateSolidBrush(RGB(236,233,216));
65 FrameBrushes[7] = CreateSolidBrush(RGB(255,255,255));
66 FrameBrushes[8] = CreateSolidBrush(RGB(49,106,197));
67 FrameBrushes[9] = CreateSolidBrush(RGB(58,110,165));
68 FrameBrushes[10] = CreateSolidBrush(RGB(64,64,64));
69 FrameBrushes[11] = CreateSolidBrush(RGB(255,255,225));
70 hHatch = CreateBitmap(8, 8, 1, 1, HatchBitmap);
71 FrameBrushes[12] = CreatePatternBrush(hHatch);
72 }
73
74 VOID
75 DeleteFrameBrushes(VOID)
76 {
77 unsigned Brush;
78
79 for (Brush = 0; Brush < sizeof(FrameBrushes) / sizeof(HBRUSH); Brush++)
80 {
81 if (NULL != FrameBrushes[Brush])
82 {
83 DeleteObject(FrameBrushes[Brush]);
84 FrameBrushes[Brush] = NULL;
85 }
86 }
87 if (NULL != hHatch)
88 {
89 DeleteObject(hHatch);
90 hHatch = NULL;
91 }
92 }
93
94
95 /*
96 * @implemented
97 */
98 BOOL
99 WINAPI
100 GetUpdateRect(
101 HWND Wnd,
102 LPRECT Rect,
103 BOOL Erase)
104 {
105 PWND pWnd;
106
107 pWnd = ValidateHwnd(Wnd);
108 if (!pWnd)
109 return FALSE;
110
111 if ( pWnd->hrgnUpdate ||
112 pWnd->state & (WNDS_SENDERASEBACKGROUND|WNDS_SENDNCPAINT|WNDS_UPDATEDIRTY|WNDS_PAINTNOTPROCESSED))
113 {
114 return NtUserGetUpdateRect(Wnd, Rect, Erase);
115 }
116
117 if (Rect)
118 { // Did the Rgn update? No! Back set and shutup!
119 Rect->left = Rect->right = Rect->top = Rect->bottom = 0;
120 }
121 return FALSE; // msdn: "If there is no update region, the return value is zero."
122
123 }
124
125
126 /*
127 * @implemented
128 */
129 int
130 WINAPI
131 GetUpdateRgn(
132 HWND hWnd,
133 HRGN hRgn,
134 BOOL bErase)
135 {
136 PWND pWnd;
137
138 if (!hRgn)
139 {
140 SetLastError(ERROR_INVALID_HANDLE);
141 return ERROR;
142 }
143
144 pWnd = ValidateHwnd(hWnd);
145 if (!pWnd)
146 return ERROR;
147
148 if ( pWnd->hrgnUpdate ||
149 pWnd->state & (WNDS_SENDERASEBACKGROUND|WNDS_SENDNCPAINT|WNDS_UPDATEDIRTY|WNDS_PAINTNOTPROCESSED))
150 {
151 return NtUserGetUpdateRgn(hWnd, hRgn, bErase);
152 }
153 SetRectRgn(hRgn, 0, 0, 0, 0);
154 return NULLREGION;
155 }
156
157
158 /*
159 * @implemented
160 */
161 BOOL WINAPI
162 ScrollDC(
163 HDC hDC,
164 int dx,
165 int dy,
166 CONST RECT *lprcScroll,
167 CONST RECT *lprcClip,
168 HRGN hrgnUpdate,
169 LPRECT lprcUpdate)
170 {
171 if (hDC == NULL) return FALSE;
172
173 if (dx == 0 && dy == 0)
174 {
175 if (hrgnUpdate) SetRectRgn(hrgnUpdate, 0, 0, 0, 0);
176 if (lprcUpdate) lprcUpdate->left = lprcUpdate->right =
177 lprcUpdate->top = lprcUpdate->bottom = 0;
178 return TRUE;
179 }
180
181 return NtUserScrollDC( hDC,
182 dx,
183 dy,
184 lprcScroll,
185 lprcClip,
186 hrgnUpdate,
187 lprcUpdate);
188 }
189
190 /*
191 * @implemented
192 */
193 int
194 WINAPI
195 SetWindowRgn(
196 HWND hWnd,
197 HRGN hRgn,
198 BOOL bRedraw)
199 {
200 BOOL Hook;
201 int Ret = 0;
202
203 LoadUserApiHook();
204
205 Hook = BeginIfHookedUserApiHook();
206
207 /* Bypass SEH and go direct. */
208 if (!Hook)
209 {
210 Ret = NtUserSetWindowRgn(hWnd, hRgn, bRedraw);
211 if (Ret)
212 DeleteObject(hRgn);
213 return Ret;
214 }
215
216 _SEH2_TRY
217 {
218 Ret = guah.SetWindowRgn(hWnd, hRgn, bRedraw);
219 }
220 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
221 {
222 }
223 _SEH2_END;
224
225 EndUserApiHook();
226
227 return Ret;
228 }
229
230 /*
231 * @implemented
232 */
233 BOOL
234 WINAPI
235 UpdateWindow(
236 HWND hWnd)
237 {
238 PWND pWnd = ValidateHwnd(hWnd);
239
240 if (!pWnd)
241 return FALSE;
242
243 if ( pWnd->hrgnUpdate ||
244 pWnd->state & WNDS_INTERNALPAINT ||
245 pWnd->spwndChild )
246 {
247 return NtUserxUpdateWindow(hWnd);
248 }
249 return TRUE;
250 }
251
252 /*
253 * @implemented
254 */
255 BOOL
256 WINAPI
257 ValidateRgn(
258 HWND hWnd,
259 HRGN hRgn)
260 {
261 return NtUserxValidateRgn(hWnd, hRgn);
262 }
263
264 /*
265 * @implemented
266 */
267 int
268 WINAPI
269 GetWindowRgn(
270 HWND hWnd,
271 HRGN hRgn)
272 {
273 PWND pWnd;
274 int Ret;
275
276 if (!hRgn)
277 return ERROR;
278
279 pWnd = ValidateHwnd(hWnd);
280
281 if (!pWnd || !pWnd->hrgnClip || pWnd->state2 & WNDS2_MAXIMIZEDMONITORREGION)
282 return ERROR;
283
284 Ret = CombineRgn(hRgn, pWnd->hrgnClip, NULL, RGN_COPY);
285
286 if (!Ret)
287 return ERROR;
288 /*
289 if (hWnd != GetDesktopWindow()) // pWnd->fnid != FNID_DESKTOP)
290 Ret = OffsetRgn(hRgn, -pWnd->rcWindow.left, -pWnd->rcWindow.top);
291 */
292 if (pWnd->ExStyle & WS_EX_LAYOUTRTL)
293 MirrorRgn(hWnd, hRgn);
294
295 return Ret;
296 }
297
298 /*
299 * @implemented
300 */
301 int
302 WINAPI
303 GetWindowRgnBox(
304 HWND hWnd,
305 LPRECT lprc)
306 {
307 PWND pWnd;
308 int Ret;
309
310 if (!lprc)
311 return ERROR;
312
313 pWnd = ValidateHwnd(hWnd);
314
315 if (!pWnd || !pWnd->hrgnClip || pWnd->state2 & WNDS2_MAXIMIZEDMONITORREGION)
316 return ERROR;
317
318 Ret = GetRgnBox(pWnd->hrgnClip, lprc);
319
320 if (!Ret)
321 return ERROR;
322 /*
323 if (hWnd != GetDesktopWindow()) // pWnd->fnid != FNID_DESKTOP)
324 OffsetRect(lprc, -pWnd->rcWindow.left, -pWnd->rcWindow.top);
325 */
326 if (pWnd->ExStyle & WS_EX_LAYOUTRTL)
327 MirrorWindowRect(pWnd, lprc);
328
329 return Ret;
330 }
331
332
333 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};
334 /*
335 * @implemented
336 */
337 BOOL
338 WINAPI
339 DrawFrame(
340 HDC hDc,
341 RECT *r,
342 DWORD width,
343 DWORD type
344 )
345 {
346 DWORD rop;
347 DWORD brush;
348 HBRUSH hbrFrame;
349 PATRECT p[4];
350 if (NULL == FrameBrushes[0])
351 {
352 CreateFrameBrushes();
353 }
354 if (type & 4)
355 {
356 rop = PATINVERT;
357 }
358 else
359 {
360 rop = PATCOPY;
361 }
362 brush = type / 8;
363 if (brush >= 33)
364 {
365 brush = 32;
366 }
367 brush = MappingTable[brush];
368 hbrFrame = FrameBrushes[brush];
369 p[0].hBrush = hbrFrame;
370 p[1].hBrush = hbrFrame;
371 p[2].hBrush = hbrFrame;
372 p[3].hBrush = hbrFrame;
373 p[0].r.left = r->left;
374 p[0].r.top = r->top;
375 p[0].r.right = r->right - r->left;
376 p[0].r.bottom = width;
377 p[1].r.left = r->left;
378 p[1].r.top = r->bottom - width;
379 p[1].r.right = r->right - r->left;
380 p[1].r.bottom = width;
381 p[2].r.left = r->left;
382 p[2].r.top = r->top + width;
383 p[2].r.right = width;
384 p[2].r.bottom = r->bottom - r->top - (width * 2);
385 p[3].r.left = r->right - width;
386 p[3].r.top = r->top + width;
387 p[3].r.right = width;
388 p[3].r.bottom = r->bottom - r->top - (width * 2);
389 return PolyPatBlt(hDc,rop,p,4,0);
390 }