Commit | Line | Data |
---|---|---|
77b9918e AJ |
1 | /* |
2 | * User Interface Functions | |
3 | * | |
4 | * Copyright 1997 Dimitrie O. Paun | |
44ed71f5 | 5 | * Copyright 1997 Bertho A. Stultiens |
0799c1a7 AJ |
6 | * |
7 | * This library is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * This library is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with this library; if not, write to the Free Software | |
360a3f91 | 19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
77b9918e AJ |
20 | */ |
21 | ||
e37c6e18 AJ |
22 | #include <stdarg.h> |
23 | ||
d3e22d9d | 24 | #include "windef.h" |
62ac036b | 25 | #include "winbase.h" |
d3e22d9d | 26 | #include "wingdi.h" |
ff5ae3dd | 27 | #include "winuser.h" |
6a78c16a | 28 | #include "user_private.h" |
f56c6fb9 | 29 | #include "wine/unicode.h" |
0799c1a7 | 30 | #include "wine/debug.h" |
77b9918e | 31 | |
0799c1a7 | 32 | WINE_DEFAULT_DEBUG_CHANNEL(graphics); |
b4b9fae6 | 33 | |
44ed71f5 AJ |
34 | /* These tables are used in: |
35 | * UITOOLS_DrawDiagEdge() | |
36 | * UITOOLS_DrawRectEdge() | |
37 | */ | |
d661dbdd | 38 | static const signed char LTInnerNormal[] = { |
44ed71f5 AJ |
39 | -1, -1, -1, -1, |
40 | -1, COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1, | |
41 | -1, COLOR_3DDKSHADOW, COLOR_3DDKSHADOW, -1, | |
42 | -1, -1, -1, -1 | |
43 | }; | |
44 | ||
d661dbdd | 45 | static const signed char LTOuterNormal[] = { |
44ed71f5 | 46 | -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, |
31b15c6a | 47 | COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, |
44ed71f5 AJ |
48 | COLOR_3DDKSHADOW, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, |
49 | -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1 | |
50 | }; | |
51 | ||
d661dbdd | 52 | static const signed char RBInnerNormal[] = { |
44ed71f5 AJ |
53 | -1, -1, -1, -1, |
54 | -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1, | |
55 | -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1, | |
56 | -1, -1, -1, -1 | |
57 | }; | |
58 | ||
d661dbdd | 59 | static const signed char RBOuterNormal[] = { |
44ed71f5 AJ |
60 | -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, |
61 | COLOR_BTNSHADOW, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, | |
62 | COLOR_3DLIGHT, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, | |
63 | -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1 | |
64 | }; | |
65 | ||
d661dbdd | 66 | static const signed char LTInnerSoft[] = { |
44ed71f5 AJ |
67 | -1, -1, -1, -1, |
68 | -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1, | |
69 | -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1, | |
70 | -1, -1, -1, -1 | |
71 | }; | |
72 | ||
d661dbdd | 73 | static const signed char LTOuterSoft[] = { |
44ed71f5 AJ |
74 | -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1, |
75 | COLOR_3DLIGHT, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1, | |
76 | COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1, | |
77 | -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1 | |
78 | }; | |
79 | ||
80 | #define RBInnerSoft RBInnerNormal /* These are the same */ | |
81 | #define RBOuterSoft RBOuterNormal | |
82 | ||
d661dbdd | 83 | static const signed char LTRBOuterMono[] = { |
44ed71f5 AJ |
84 | -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, |
85 | COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, | |
86 | COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, | |
87 | COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, | |
88 | }; | |
89 | ||
d661dbdd | 90 | static const signed char LTRBInnerMono[] = { |
44ed71f5 AJ |
91 | -1, -1, -1, -1, |
92 | -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, | |
93 | -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, | |
94 | -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, | |
95 | }; | |
96 | ||
d661dbdd | 97 | static const signed char LTRBOuterFlat[] = { |
44ed71f5 | 98 | -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, |
31b15c6a BM |
99 | COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, |
100 | COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, | |
101 | COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, | |
44ed71f5 AJ |
102 | }; |
103 | ||
d661dbdd | 104 | static const signed char LTRBInnerFlat[] = { |
44ed71f5 | 105 | -1, -1, -1, -1, |
9a624916 VB |
106 | -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE, |
107 | -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE, | |
108 | -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE, | |
44ed71f5 AJ |
109 | }; |
110 | ||
f56c6fb9 | 111 | /* last COLOR id */ |
cb259593 | 112 | #define COLOR_MAX COLOR_MENUBAR |
f56c6fb9 AJ |
113 | |
114 | ||
77b9918e AJ |
115 | /*********************************************************************** |
116 | * UITOOLS_DrawDiagEdge | |
117 | * | |
54c2711f AJ |
118 | * Same as DrawEdge invoked with BF_DIAGONAL |
119 | * | |
44ed71f5 AJ |
120 | * 03-Dec-1997: Changed by Bertho Stultiens |
121 | * | |
122 | * See also comments with UITOOLS_DrawRectEdge() | |
123 | */ | |
9a624916 | 124 | static BOOL UITOOLS95_DrawDiagEdge(HDC hdc, LPRECT rc, |
a3960292 | 125 | UINT uType, UINT uFlags) |
77b9918e | 126 | { |
a3960292 | 127 | POINT Points[4]; |
d661dbdd | 128 | signed char InnerI, OuterI; |
a3960292 AJ |
129 | HPEN InnerPen, OuterPen; |
130 | POINT SavePoint; | |
131 | HPEN SavePen; | |
44ed71f5 AJ |
132 | int spx, spy; |
133 | int epx, epy; | |
134 | int Width = rc->right - rc->left; | |
135 | int Height= rc->bottom - rc->top; | |
136 | int SmallDiam = Width > Height ? Height : Width; | |
a3960292 | 137 | BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER |
44ed71f5 AJ |
138 | || (uType & BDR_OUTER) == BDR_OUTER) |
139 | && !(uFlags & (BF_FLAT|BF_MONO)) ); | |
140 | int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0) | |
141 | + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0); | |
142 | ||
143 | /* Init some vars */ | |
4fc84eaf MS |
144 | OuterPen = InnerPen = GetStockObject(NULL_PEN); |
145 | SavePen = SelectObject(hdc, InnerPen); | |
44ed71f5 | 146 | spx = spy = epx = epy = 0; /* Satisfy the compiler... */ |
9a624916 | 147 | |
44ed71f5 AJ |
148 | /* Determine the colors of the edges */ |
149 | if(uFlags & BF_MONO) | |
150 | { | |
151 | InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)]; | |
152 | OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)]; | |
153 | } | |
154 | else if(uFlags & BF_FLAT) | |
155 | { | |
156 | InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)]; | |
157 | OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)]; | |
158 | } | |
159 | else if(uFlags & BF_SOFT) | |
160 | { | |
161 | if(uFlags & BF_BOTTOM) | |
162 | { | |
163 | InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
164 | OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
165 | } | |
166 | else | |
167 | { | |
168 | InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
169 | OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
170 | } | |
171 | } | |
172 | else | |
173 | { | |
174 | if(uFlags & BF_BOTTOM) | |
175 | { | |
176 | InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
177 | OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
178 | } | |
179 | else | |
180 | { | |
181 | InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
182 | OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
183 | } | |
184 | } | |
185 | ||
4344c368 AJ |
186 | if(InnerI != -1) InnerPen = SYSCOLOR_GetPen(InnerI); |
187 | if(OuterI != -1) OuterPen = SYSCOLOR_GetPen(OuterI); | |
44ed71f5 | 188 | |
a3960292 | 189 | MoveToEx(hdc, 0, 0, &SavePoint); |
44ed71f5 AJ |
190 | |
191 | /* Don't ask me why, but this is what is visible... */ | |
192 | /* This must be possible to do much simpler, but I fail to */ | |
193 | /* see the logic in the MS implementation (sigh...). */ | |
194 | /* So, this might look a bit brute force here (and it is), but */ | |
195 | /* it gets the job done;) */ | |
196 | ||
197 | switch(uFlags & BF_RECT) | |
198 | { | |
199 | case 0: | |
200 | case BF_LEFT: | |
201 | case BF_BOTTOM: | |
202 | case BF_BOTTOMLEFT: | |
203 | /* Left bottom endpoint */ | |
204 | epx = rc->left-1; | |
205 | spx = epx + SmallDiam; | |
206 | epy = rc->bottom; | |
207 | spy = epy - SmallDiam; | |
208 | break; | |
209 | ||
210 | case BF_TOPLEFT: | |
211 | case BF_BOTTOMRIGHT: | |
212 | /* Left top endpoint */ | |
213 | epx = rc->left-1; | |
214 | spx = epx + SmallDiam; | |
215 | epy = rc->top-1; | |
216 | spy = epy + SmallDiam; | |
217 | break; | |
218 | ||
219 | case BF_TOP: | |
220 | case BF_RIGHT: | |
221 | case BF_TOPRIGHT: | |
222 | case BF_RIGHT|BF_LEFT: | |
223 | case BF_RIGHT|BF_LEFT|BF_TOP: | |
224 | case BF_BOTTOM|BF_TOP: | |
225 | case BF_BOTTOM|BF_TOP|BF_LEFT: | |
226 | case BF_BOTTOMRIGHT|BF_LEFT: | |
227 | case BF_BOTTOMRIGHT|BF_TOP: | |
228 | case BF_RECT: | |
229 | /* Right top endpoint */ | |
230 | spx = rc->left; | |
231 | epx = spx + SmallDiam; | |
232 | spy = rc->bottom-1; | |
233 | epy = spy - SmallDiam; | |
234 | break; | |
235 | } | |
236 | ||
a3960292 AJ |
237 | MoveToEx(hdc, spx, spy, NULL); |
238 | SelectObject(hdc, OuterPen); | |
239 | LineTo(hdc, epx, epy); | |
77b9918e | 240 | |
a3960292 | 241 | SelectObject(hdc, InnerPen); |
44ed71f5 AJ |
242 | |
243 | switch(uFlags & (BF_RECT|BF_DIAGONAL)) | |
244 | { | |
245 | case BF_DIAGONAL_ENDBOTTOMLEFT: | |
246 | case (BF_DIAGONAL|BF_BOTTOM): | |
247 | case BF_DIAGONAL: | |
248 | case (BF_DIAGONAL|BF_LEFT): | |
a3960292 AJ |
249 | MoveToEx(hdc, spx-1, spy, NULL); |
250 | LineTo(hdc, epx, epy-1); | |
44ed71f5 AJ |
251 | Points[0].x = spx-add; |
252 | Points[0].y = spy; | |
253 | Points[1].x = rc->left; | |
254 | Points[1].y = rc->top; | |
255 | Points[2].x = epx+1; | |
256 | Points[2].y = epy-1-add; | |
257 | Points[3] = Points[2]; | |
258 | break; | |
259 | ||
260 | case BF_DIAGONAL_ENDBOTTOMRIGHT: | |
a3960292 AJ |
261 | MoveToEx(hdc, spx-1, spy, NULL); |
262 | LineTo(hdc, epx, epy+1); | |
44ed71f5 AJ |
263 | Points[0].x = spx-add; |
264 | Points[0].y = spy; | |
265 | Points[1].x = rc->left; | |
266 | Points[1].y = rc->bottom-1; | |
267 | Points[2].x = epx+1; | |
268 | Points[2].y = epy+1+add; | |
269 | Points[3] = Points[2]; | |
270 | break; | |
271 | ||
272 | case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP): | |
273 | case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT): | |
274 | case BF_DIAGONAL_ENDTOPRIGHT: | |
275 | case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT): | |
a3960292 AJ |
276 | MoveToEx(hdc, spx+1, spy, NULL); |
277 | LineTo(hdc, epx, epy+1); | |
44ed71f5 AJ |
278 | Points[0].x = epx-1; |
279 | Points[0].y = epy+1+add; | |
280 | Points[1].x = rc->right-1; | |
281 | Points[1].y = rc->top+add; | |
282 | Points[2].x = rc->right-1; | |
283 | Points[2].y = rc->bottom-1; | |
284 | Points[3].x = spx+add; | |
285 | Points[3].y = spy; | |
286 | break; | |
287 | ||
288 | case BF_DIAGONAL_ENDTOPLEFT: | |
a3960292 AJ |
289 | MoveToEx(hdc, spx, spy-1, NULL); |
290 | LineTo(hdc, epx+1, epy); | |
44ed71f5 AJ |
291 | Points[0].x = epx+1+add; |
292 | Points[0].y = epy+1; | |
293 | Points[1].x = rc->right-1; | |
294 | Points[1].y = rc->top; | |
295 | Points[2].x = rc->right-1; | |
296 | Points[2].y = rc->bottom-1-add; | |
297 | Points[3].x = spx; | |
298 | Points[3].y = spy-add; | |
299 | break; | |
300 | ||
301 | case (BF_DIAGONAL|BF_TOP): | |
302 | case (BF_DIAGONAL|BF_BOTTOM|BF_TOP): | |
303 | case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT): | |
a3960292 AJ |
304 | MoveToEx(hdc, spx+1, spy-1, NULL); |
305 | LineTo(hdc, epx, epy); | |
44ed71f5 AJ |
306 | Points[0].x = epx-1; |
307 | Points[0].y = epy+1; | |
308 | Points[1].x = rc->right-1; | |
309 | Points[1].y = rc->top; | |
310 | Points[2].x = rc->right-1; | |
311 | Points[2].y = rc->bottom-1-add; | |
312 | Points[3].x = spx+add; | |
313 | Points[3].y = spy-add; | |
314 | break; | |
315 | ||
316 | case (BF_DIAGONAL|BF_RIGHT): | |
317 | case (BF_DIAGONAL|BF_RIGHT|BF_LEFT): | |
318 | case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM): | |
a3960292 AJ |
319 | MoveToEx(hdc, spx, spy, NULL); |
320 | LineTo(hdc, epx-1, epy+1); | |
44ed71f5 AJ |
321 | Points[0].x = spx; |
322 | Points[0].y = spy; | |
323 | Points[1].x = rc->left; | |
324 | Points[1].y = rc->top+add; | |
325 | Points[2].x = epx-1-add; | |
326 | Points[2].y = epy+1+add; | |
327 | Points[3] = Points[2]; | |
328 | break; | |
329 | } | |
330 | ||
331 | /* Fill the interior if asked */ | |
332 | if((uFlags & BF_MIDDLE) && retval) | |
333 | { | |
a3960292 AJ |
334 | HBRUSH hbsave; |
335 | HBRUSH hb = GetSysColorBrush(uFlags & BF_MONO ? COLOR_WINDOW | |
02e90087 | 336 | :COLOR_BTNFACE); |
a3960292 | 337 | HPEN hpsave; |
4344c368 | 338 | HPEN hp = SYSCOLOR_GetPen(uFlags & BF_MONO ? COLOR_WINDOW |
02e90087 | 339 | : COLOR_BTNFACE); |
4fc84eaf MS |
340 | hbsave = SelectObject(hdc, hb); |
341 | hpsave = SelectObject(hdc, hp); | |
a3960292 AJ |
342 | Polygon(hdc, Points, 4); |
343 | SelectObject(hdc, hbsave); | |
344 | SelectObject(hdc, hpsave); | |
44ed71f5 AJ |
345 | } |
346 | ||
347 | /* Adjust rectangle if asked */ | |
348 | if(uFlags & BF_ADJUST) | |
349 | { | |
350 | if(uFlags & BF_LEFT) rc->left += add; | |
351 | if(uFlags & BF_RIGHT) rc->right -= add; | |
352 | if(uFlags & BF_TOP) rc->top += add; | |
353 | if(uFlags & BF_BOTTOM) rc->bottom -= add; | |
354 | } | |
355 | ||
356 | /* Cleanup */ | |
a3960292 AJ |
357 | SelectObject(hdc, SavePen); |
358 | MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL); | |
44ed71f5 AJ |
359 | |
360 | return retval; | |
361 | } | |
77b9918e AJ |
362 | |
363 | /*********************************************************************** | |
364 | * UITOOLS_DrawRectEdge | |
365 | * | |
54c2711f AJ |
366 | * Same as DrawEdge invoked without BF_DIAGONAL |
367 | * | |
44ed71f5 AJ |
368 | * 23-Nov-1997: Changed by Bertho Stultiens |
369 | * | |
370 | * Well, I started testing this and found out that there are a few things | |
371 | * that weren't quite as win95. The following rewrite should reproduce | |
372 | * win95 results completely. | |
6e59cd2c | 373 | * The colorselection is table-driven to avoid awful if-statements. |
44ed71f5 AJ |
374 | * The table below show the color settings. |
375 | * | |
376 | * Pen selection table for uFlags = 0 | |
377 | * | |
378 | * uType | LTI | LTO | RBI | RBO | |
379 | * ------+-------+-------+-------+------- | |
380 | * 0000 | x | x | x | x | |
381 | * 0001 | x | 22 | x | 21 | |
382 | * 0010 | x | 16 | x | 20 | |
383 | * 0011 | x | x | x | x | |
384 | * ------+-------+-------+-------+------- | |
385 | * 0100 | x | 20 | x | 16 | |
386 | * 0101 | 20 | 22 | 16 | 21 | |
387 | * 0110 | 20 | 16 | 16 | 20 | |
388 | * 0111 | x | x | x | x | |
389 | * ------+-------+-------+-------+------- | |
390 | * 1000 | x | 21 | x | 22 | |
391 | * 1001 | 21 | 22 | 22 | 21 | |
392 | * 1010 | 21 | 16 | 22 | 20 | |
393 | * 1011 | x | x | x | x | |
394 | * ------+-------+-------+-------+------- | |
395 | * 1100 | x | x | x | x | |
396 | * 1101 | x | x (22)| x | x (21) | |
397 | * 1110 | x | x (16)| x | x (20) | |
398 | * 1111 | x | x | x | x | |
399 | * | |
400 | * Pen selection table for uFlags = BF_SOFT | |
401 | * | |
402 | * uType | LTI | LTO | RBI | RBO | |
403 | * ------+-------+-------+-------+------- | |
404 | * 0000 | x | x | x | x | |
405 | * 0001 | x | 20 | x | 21 | |
406 | * 0010 | x | 21 | x | 20 | |
407 | * 0011 | x | x | x | x | |
408 | * ------+-------+-------+-------+------- | |
409 | * 0100 | x | 22 | x | 16 | |
410 | * 0101 | 22 | 20 | 16 | 21 | |
411 | * 0110 | 22 | 21 | 16 | 20 | |
412 | * 0111 | x | x | x | x | |
413 | * ------+-------+-------+-------+------- | |
414 | * 1000 | x | 16 | x | 22 | |
415 | * 1001 | 16 | 20 | 22 | 21 | |
416 | * 1010 | 16 | 21 | 22 | 20 | |
417 | * 1011 | x | x | x | x | |
418 | * ------+-------+-------+-------+------- | |
419 | * 1100 | x | x | x | x | |
420 | * 1101 | x | x (20)| x | x (21) | |
421 | * 1110 | x | x (21)| x | x (20) | |
422 | * 1111 | x | x | x | x | |
423 | * | |
424 | * x = don't care; (n) = is what win95 actually uses | |
425 | * LTI = left Top Inner line | |
426 | * LTO = left Top Outer line | |
427 | * RBI = Right Bottom Inner line | |
428 | * RBO = Right Bottom Outer line | |
429 | * 15 = COLOR_BTNFACE | |
430 | * 16 = COLOR_BTNSHADOW | |
431 | * 20 = COLOR_BTNHIGHLIGHT | |
432 | * 21 = COLOR_3DDKSHADOW | |
433 | * 22 = COLOR_3DLIGHT | |
434 | */ | |
435 | ||
436 | ||
9a624916 | 437 | static BOOL UITOOLS95_DrawRectEdge(HDC hdc, LPRECT rc, |
a3960292 | 438 | UINT uType, UINT uFlags) |
77b9918e | 439 | { |
d661dbdd JD |
440 | signed char LTInnerI, LTOuterI; |
441 | signed char RBInnerI, RBOuterI; | |
a3960292 AJ |
442 | HPEN LTInnerPen, LTOuterPen; |
443 | HPEN RBInnerPen, RBOuterPen; | |
444 | RECT InnerRect = *rc; | |
445 | POINT SavePoint; | |
446 | HPEN SavePen; | |
44ed71f5 AJ |
447 | int LBpenplus = 0; |
448 | int LTpenplus = 0; | |
449 | int RTpenplus = 0; | |
450 | int RBpenplus = 0; | |
a3960292 | 451 | BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER |
44ed71f5 AJ |
452 | || (uType & BDR_OUTER) == BDR_OUTER) |
453 | && !(uFlags & (BF_FLAT|BF_MONO)) ); | |
9a624916 | 454 | |
44ed71f5 | 455 | /* Init some vars */ |
4fc84eaf MS |
456 | LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = GetStockObject(NULL_PEN); |
457 | SavePen = SelectObject(hdc, LTInnerPen); | |
44ed71f5 AJ |
458 | |
459 | /* Determine the colors of the edges */ | |
460 | if(uFlags & BF_MONO) | |
461 | { | |
462 | LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)]; | |
463 | LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)]; | |
464 | } | |
465 | else if(uFlags & BF_FLAT) | |
466 | { | |
467 | LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)]; | |
468 | LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)]; | |
b49b4117 | 469 | |
abe9c975 | 470 | if( LTInnerI != -1 ) LTInnerI = RBInnerI = COLOR_BTNFACE; |
44ed71f5 AJ |
471 | } |
472 | else if(uFlags & BF_SOFT) | |
473 | { | |
474 | LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
475 | LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
476 | RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
477 | RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; | |
478 | } | |
479 | else | |
480 | { | |
481 | LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
482 | LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
483 | RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
484 | RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; | |
485 | } | |
486 | ||
487 | if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT) LBpenplus = 1; | |
488 | if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT) RTpenplus = 1; | |
489 | if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT) RBpenplus = 1; | |
490 | if((uFlags & BF_TOPLEFT) == BF_TOPLEFT) LTpenplus = 1; | |
491 | ||
4344c368 AJ |
492 | if(LTInnerI != -1) LTInnerPen = SYSCOLOR_GetPen(LTInnerI); |
493 | if(LTOuterI != -1) LTOuterPen = SYSCOLOR_GetPen(LTOuterI); | |
494 | if(RBInnerI != -1) RBInnerPen = SYSCOLOR_GetPen(RBInnerI); | |
495 | if(RBOuterI != -1) RBOuterPen = SYSCOLOR_GetPen(RBOuterI); | |
44ed71f5 | 496 | |
a3960292 | 497 | MoveToEx(hdc, 0, 0, &SavePoint); |
44ed71f5 AJ |
498 | |
499 | /* Draw the outer edge */ | |
a3960292 | 500 | SelectObject(hdc, LTOuterPen); |
44ed71f5 AJ |
501 | if(uFlags & BF_TOP) |
502 | { | |
a3960292 AJ |
503 | MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL); |
504 | LineTo(hdc, InnerRect.right, InnerRect.top); | |
44ed71f5 AJ |
505 | } |
506 | if(uFlags & BF_LEFT) | |
507 | { | |
a3960292 AJ |
508 | MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL); |
509 | LineTo(hdc, InnerRect.left, InnerRect.bottom); | |
44ed71f5 | 510 | } |
a3960292 | 511 | SelectObject(hdc, RBOuterPen); |
44ed71f5 AJ |
512 | if(uFlags & BF_BOTTOM) |
513 | { | |
61052164 JR |
514 | MoveToEx(hdc, InnerRect.left, InnerRect.bottom-1, NULL); |
515 | LineTo(hdc, InnerRect.right-1, InnerRect.bottom-1); | |
44ed71f5 AJ |
516 | } |
517 | if(uFlags & BF_RIGHT) | |
518 | { | |
61052164 JR |
519 | MoveToEx(hdc, InnerRect.right-1, InnerRect.top, NULL); |
520 | LineTo(hdc, InnerRect.right-1, InnerRect.bottom); | |
44ed71f5 AJ |
521 | } |
522 | ||
523 | /* Draw the inner edge */ | |
a3960292 | 524 | SelectObject(hdc, LTInnerPen); |
44ed71f5 AJ |
525 | if(uFlags & BF_TOP) |
526 | { | |
a3960292 AJ |
527 | MoveToEx(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL); |
528 | LineTo(hdc, InnerRect.right-RTpenplus, InnerRect.top+1); | |
44ed71f5 AJ |
529 | } |
530 | if(uFlags & BF_LEFT) | |
531 | { | |
a3960292 AJ |
532 | MoveToEx(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL); |
533 | LineTo(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus); | |
44ed71f5 | 534 | } |
a3960292 | 535 | SelectObject(hdc, RBInnerPen); |
44ed71f5 AJ |
536 | if(uFlags & BF_BOTTOM) |
537 | { | |
61052164 JR |
538 | MoveToEx(hdc, InnerRect.left+LBpenplus, InnerRect.bottom-2, NULL); |
539 | LineTo(hdc, InnerRect.right-1-RBpenplus, InnerRect.bottom-2); | |
44ed71f5 AJ |
540 | } |
541 | if(uFlags & BF_RIGHT) | |
542 | { | |
61052164 JR |
543 | MoveToEx(hdc, InnerRect.right-2, InnerRect.top+2-RBpenplus, NULL); |
544 | LineTo(hdc, InnerRect.right-2, InnerRect.bottom-2+RTpenplus); | |
44ed71f5 AJ |
545 | } |
546 | ||
b49b4117 | 547 | if( ((uFlags & BF_MIDDLE) && retval) || (uFlags & BF_ADJUST) ) |
44ed71f5 AJ |
548 | { |
549 | int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0) | |
550 | + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0); | |
b49b4117 DB |
551 | |
552 | if(uFlags & BF_LEFT) InnerRect.left += add; | |
553 | if(uFlags & BF_RIGHT) InnerRect.right -= add; | |
554 | if(uFlags & BF_TOP) InnerRect.top += add; | |
555 | if(uFlags & BF_BOTTOM) InnerRect.bottom -= add; | |
556 | ||
557 | if((uFlags & BF_MIDDLE) && retval) | |
9a624916 VB |
558 | { |
559 | FillRect(hdc, &InnerRect, GetSysColorBrush(uFlags & BF_MONO ? | |
b49b4117 DB |
560 | COLOR_WINDOW : COLOR_BTNFACE)); |
561 | } | |
562 | ||
563 | if(uFlags & BF_ADJUST) | |
564 | *rc = InnerRect; | |
44ed71f5 AJ |
565 | } |
566 | ||
567 | /* Cleanup */ | |
a3960292 AJ |
568 | SelectObject(hdc, SavePen); |
569 | MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL); | |
44ed71f5 | 570 | return retval; |
77b9918e AJ |
571 | } |
572 | ||
573 | ||
77b9918e | 574 | /********************************************************************** |
0c610287 | 575 | * DrawEdge (USER32.@) |
77b9918e | 576 | */ |
a3960292 | 577 | BOOL WINAPI DrawEdge( HDC hdc, LPRECT rc, UINT edge, UINT flags ) |
77b9918e | 578 | { |
6c1cdc71 | 579 | TRACE("%p %s %04x %04x\n", hdc, wine_dbgstr_rect(rc), edge, flags ); |
77b9918e AJ |
580 | |
581 | if(flags & BF_DIAGONAL) | |
54c2711f | 582 | return UITOOLS95_DrawDiagEdge(hdc, rc, edge, flags); |
77b9918e | 583 | else |
54c2711f | 584 | return UITOOLS95_DrawRectEdge(hdc, rc, edge, flags); |
77b9918e AJ |
585 | } |
586 | ||
587 | ||
44ed71f5 AJ |
588 | /************************************************************************ |
589 | * UITOOLS_MakeSquareRect | |
590 | * | |
591 | * Utility to create a square rectangle and returning the width | |
592 | */ | |
a3960292 | 593 | static int UITOOLS_MakeSquareRect(LPRECT src, LPRECT dst) |
44ed71f5 AJ |
594 | { |
595 | int Width = src->right - src->left; | |
596 | int Height = src->bottom - src->top; | |
597 | int SmallDiam = Width > Height ? Height : Width; | |
598 | ||
599 | *dst = *src; | |
600 | ||
601 | /* Make it a square box */ | |
602 | if(Width < Height) /* SmallDiam == Width */ | |
603 | { | |
604 | dst->top += (Height-Width)/2; | |
605 | dst->bottom = dst->top + SmallDiam; | |
606 | } | |
607 | else if(Width > Height) /* SmallDiam == Height */ | |
608 | { | |
609 | dst->left += (Width-Height)/2; | |
610 | dst->right = dst->left + SmallDiam; | |
611 | } | |
612 | ||
613 | return SmallDiam; | |
614 | } | |
615 | ||
9af3ebaa DB |
616 | static void UITOOLS_DrawCheckedRect( HDC dc, LPRECT rect ) |
617 | { | |
618 | if(GetSysColor(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255)) | |
619 | { | |
9af3ebaa | 620 | HBRUSH hbsave; |
9af3ebaa DB |
621 | COLORREF bg; |
622 | ||
623 | FillRect(dc, rect, GetSysColorBrush(COLOR_BTNFACE)); | |
624 | bg = SetBkColor(dc, RGB(255, 255, 255)); | |
eea41530 | 625 | hbsave = SelectObject(dc, SYSCOLOR_55AABrush); |
9af3ebaa DB |
626 | PatBlt(dc, rect->left, rect->top, rect->right-rect->left, rect->bottom-rect->top, 0x00FA0089); |
627 | SelectObject(dc, hbsave); | |
628 | SetBkColor(dc, bg); | |
9af3ebaa DB |
629 | } |
630 | else | |
631 | { | |
632 | FillRect(dc, rect, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); | |
633 | } | |
634 | } | |
44ed71f5 AJ |
635 | |
636 | /************************************************************************ | |
637 | * UITOOLS_DFC_ButtonPush | |
638 | * | |
639 | * Draw a push button coming from DrawFrameControl() | |
640 | * | |
641 | * Does a pretty good job in emulating MS behavior. Some quirks are | |
642 | * however there because MS uses a TrueType font (Marlett) to draw | |
643 | * the buttons. | |
644 | */ | |
a3960292 | 645 | static BOOL UITOOLS95_DFC_ButtonPush(HDC dc, LPRECT r, UINT uFlags) |
44ed71f5 | 646 | { |
a3960292 AJ |
647 | UINT edge; |
648 | RECT myr = *r; | |
44ed71f5 AJ |
649 | |
650 | if(uFlags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT)) | |
651 | edge = EDGE_SUNKEN; | |
652 | else | |
653 | edge = EDGE_RAISED; | |
654 | ||
655 | if(uFlags & DFCS_CHECKED) | |
656 | { | |
657 | if(uFlags & DFCS_MONO) | |
54c2711f | 658 | UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST); |
44ed71f5 | 659 | else |
54c2711f | 660 | UITOOLS95_DrawRectEdge(dc, &myr, edge, (uFlags&DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST); |
44ed71f5 | 661 | |
8fce1a4c DP |
662 | if (!(uFlags & DFCS_TRANSPARENT)) |
663 | UITOOLS_DrawCheckedRect( dc, &myr ); | |
664 | } | |
665 | else | |
666 | { | |
44ed71f5 AJ |
667 | if(uFlags & DFCS_MONO) |
668 | { | |
54c2711f | 669 | UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST); |
8fce1a4c DP |
670 | if (!(uFlags & DFCS_TRANSPARENT)) |
671 | FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE)); | |
44ed71f5 AJ |
672 | } |
673 | else | |
674 | { | |
cb259593 | 675 | UITOOLS95_DrawRectEdge(dc, r, edge, (uFlags & DFCS_FLAT) | ((uFlags & DFCS_TRANSPARENT) ? 0 : BF_MIDDLE) | BF_RECT | BF_SOFT); |
44ed71f5 AJ |
676 | } |
677 | } | |
678 | ||
679 | /* Adjust rectangle if asked */ | |
680 | if(uFlags & DFCS_ADJUSTRECT) | |
681 | { | |
682 | r->left += 2; | |
683 | r->right -= 2; | |
684 | r->top += 2; | |
685 | r->bottom -= 2; | |
686 | } | |
687 | ||
688 | return TRUE; | |
689 | } | |
690 | ||
691 | ||
692 | /************************************************************************ | |
693 | * UITOOLS_DFC_ButtonChcek | |
694 | * | |
695 | * Draw a check/3state button coming from DrawFrameControl() | |
696 | * | |
697 | * Does a pretty good job in emulating MS behavior. Some quirks are | |
698 | * however there because MS uses a TrueType font (Marlett) to draw | |
699 | * the buttons. | |
700 | */ | |
44ed71f5 | 701 | |
a3960292 | 702 | static BOOL UITOOLS95_DFC_ButtonCheck(HDC dc, LPRECT r, UINT uFlags) |
44ed71f5 | 703 | { |
b09c6ef5 | 704 | RECT myr, bar; |
9af3ebaa | 705 | UINT flags = BF_RECT | BF_ADJUST; |
8fce1a4c | 706 | |
b09c6ef5 | 707 | UITOOLS_MakeSquareRect(r, &myr); |
44ed71f5 | 708 | |
9af3ebaa DB |
709 | if(uFlags & DFCS_FLAT) flags |= BF_FLAT; |
710 | else if(uFlags & DFCS_MONO) flags |= BF_MONO; | |
44ed71f5 | 711 | |
9af3ebaa | 712 | UITOOLS95_DrawRectEdge( dc, &myr, EDGE_SUNKEN, flags ); |
44ed71f5 | 713 | |
8fce1a4c | 714 | if (!(uFlags & DFCS_TRANSPARENT)) |
44ed71f5 | 715 | { |
8fce1a4c DP |
716 | if(uFlags & (DFCS_INACTIVE | DFCS_PUSHED)) |
717 | FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE)); | |
718 | else if( (uFlags & DFCS_BUTTON3STATE) && (uFlags & DFCS_CHECKED) ) | |
719 | UITOOLS_DrawCheckedRect( dc, &myr ); | |
720 | else | |
721 | FillRect(dc, &myr, GetSysColorBrush(COLOR_WINDOW)); | |
44ed71f5 AJ |
722 | } |
723 | ||
724 | if(uFlags & DFCS_CHECKED) | |
725 | { | |
b09c6ef5 SF |
726 | int i, k; |
727 | i = (uFlags & DFCS_INACTIVE) || (uFlags & 0xff) == DFCS_BUTTON3STATE ? | |
728 | COLOR_BTNSHADOW : COLOR_WINDOWTEXT; | |
729 | ||
730 | /* draw 7 bars, with h=3w to form the check */ | |
731 | bar.left = myr.left; | |
732 | bar.top = myr.top + 2; | |
733 | for (k = 0; k < 7; k++) { | |
734 | bar.left = bar.left + 1; | |
735 | bar.top = (k < 3) ? bar.top + 1 : bar.top - 1; | |
736 | bar.bottom = bar.top + 3; | |
737 | bar.right = bar.left + 1; | |
738 | FillRect(dc, &bar, GetSysColorBrush(i)); | |
739 | } | |
44ed71f5 AJ |
740 | } |
741 | return TRUE; | |
742 | } | |
743 | ||
744 | ||
745 | /************************************************************************ | |
746 | * UITOOLS_DFC_ButtonRadio | |
747 | * | |
748 | * Draw a radio/radioimage/radiomask button coming from DrawFrameControl() | |
749 | * | |
750 | * Does a pretty good job in emulating MS behavior. Some quirks are | |
751 | * however there because MS uses a TrueType font (Marlett) to draw | |
752 | * the buttons. | |
753 | */ | |
a3960292 | 754 | static BOOL UITOOLS95_DFC_ButtonRadio(HDC dc, LPRECT r, UINT uFlags) |
44ed71f5 | 755 | { |
a3960292 | 756 | RECT myr; |
44ed71f5 AJ |
757 | int i; |
758 | int SmallDiam = UITOOLS_MakeSquareRect(r, &myr); | |
759 | int BorderShrink = SmallDiam / 16; | |
a3960292 AJ |
760 | HPEN hpsave; |
761 | HBRUSH hbsave; | |
44ed71f5 AJ |
762 | int xc, yc; |
763 | ||
764 | if(BorderShrink < 1) BorderShrink = 1; | |
765 | ||
766 | if((uFlags & 0xff) == DFCS_BUTTONRADIOIMAGE) | |
214b40b1 | 767 | FillRect(dc, r, GetStockObject(BLACK_BRUSH)); |
44ed71f5 | 768 | |
44ed71f5 AJ |
769 | xc = myr.left + SmallDiam - SmallDiam/2; |
770 | yc = myr.top + SmallDiam - SmallDiam/2; | |
771 | ||
772 | /* Define bounding box */ | |
773 | i = 14*SmallDiam/16; | |
774 | myr.left = xc - i+i/2; | |
775 | myr.right = xc + i/2; | |
776 | myr.top = yc - i+i/2; | |
777 | myr.bottom = yc + i/2; | |
778 | ||
779 | if((uFlags & 0xff) == DFCS_BUTTONRADIOMASK) | |
780 | { | |
4fc84eaf | 781 | hbsave = SelectObject(dc, GetStockObject(BLACK_BRUSH)); |
b09c6ef5 | 782 | Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom); |
a3960292 | 783 | SelectObject(dc, hbsave); |
44ed71f5 AJ |
784 | } |
785 | else | |
786 | { | |
787 | if(uFlags & (DFCS_FLAT|DFCS_MONO)) | |
788 | { | |
4fc84eaf MS |
789 | hpsave = SelectObject(dc, SYSCOLOR_GetPen(COLOR_WINDOWFRAME)); |
790 | hbsave = SelectObject(dc, GetSysColorBrush(COLOR_WINDOWFRAME)); | |
b09c6ef5 | 791 | Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom); |
a3960292 AJ |
792 | SelectObject(dc, hbsave); |
793 | SelectObject(dc, hpsave); | |
44ed71f5 AJ |
794 | } |
795 | else | |
796 | { | |
4fc84eaf MS |
797 | hpsave = SelectObject(dc, SYSCOLOR_GetPen(COLOR_BTNHIGHLIGHT)); |
798 | hbsave = SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); | |
b09c6ef5 | 799 | Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.left-1, myr.bottom, myr.right+1, myr.top); |
44ed71f5 | 800 | |
4344c368 | 801 | SelectObject(dc, SYSCOLOR_GetPen(COLOR_BTNSHADOW)); |
a3960292 | 802 | SelectObject(dc, GetSysColorBrush(COLOR_BTNSHADOW)); |
b09c6ef5 | 803 | Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.right+1, myr.top, myr.left-1, myr.bottom); |
44ed71f5 AJ |
804 | |
805 | myr.left += BorderShrink; | |
806 | myr.right -= BorderShrink; | |
807 | myr.top += BorderShrink; | |
808 | myr.bottom -= BorderShrink; | |
809 | ||
4344c368 | 810 | SelectObject(dc, SYSCOLOR_GetPen(COLOR_3DLIGHT)); |
a3960292 | 811 | SelectObject(dc, GetSysColorBrush(COLOR_3DLIGHT)); |
b09c6ef5 | 812 | Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.left-1, myr.bottom, myr.right+1, myr.top); |
44ed71f5 | 813 | |
4344c368 | 814 | SelectObject(dc, SYSCOLOR_GetPen(COLOR_3DDKSHADOW)); |
a3960292 | 815 | SelectObject(dc, GetSysColorBrush(COLOR_3DDKSHADOW)); |
b09c6ef5 | 816 | Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.right+1, myr.top, myr.left-1, myr.bottom); |
a3960292 AJ |
817 | SelectObject(dc, hbsave); |
818 | SelectObject(dc, hpsave); | |
44ed71f5 AJ |
819 | } |
820 | ||
821 | i = 10*SmallDiam/16; | |
822 | myr.left = xc - i+i/2; | |
823 | myr.right = xc + i/2; | |
824 | myr.top = yc - i+i/2; | |
825 | myr.bottom = yc + i/2; | |
826 | i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE; | |
4fc84eaf MS |
827 | hpsave = SelectObject(dc, SYSCOLOR_GetPen(i)); |
828 | hbsave = SelectObject(dc, GetSysColorBrush(i)); | |
b09c6ef5 | 829 | Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom); |
a3960292 AJ |
830 | SelectObject(dc, hbsave); |
831 | SelectObject(dc, hpsave); | |
44ed71f5 AJ |
832 | } |
833 | ||
834 | if(uFlags & DFCS_CHECKED) | |
835 | { | |
836 | i = 6*SmallDiam/16; | |
837 | i = i < 1 ? 1 : i; | |
838 | myr.left = xc - i+i/2; | |
839 | myr.right = xc + i/2; | |
840 | myr.top = yc - i+i/2; | |
841 | myr.bottom = yc + i/2; | |
842 | ||
843 | i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT; | |
4fc84eaf MS |
844 | hbsave = SelectObject(dc, GetSysColorBrush(i)); |
845 | hpsave = SelectObject(dc, SYSCOLOR_GetPen(i)); | |
b09c6ef5 | 846 | Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom); |
a3960292 AJ |
847 | SelectObject(dc, hpsave); |
848 | SelectObject(dc, hbsave); | |
44ed71f5 AJ |
849 | } |
850 | ||
851 | /* FIXME: M$ has a polygon in the center at relative points: */ | |
852 | /* 0.476, 0.476 (times SmallDiam, SmallDiam) */ | |
853 | /* 0.476, 0.525 */ | |
854 | /* 0.500, 0.500 */ | |
855 | /* 0.500, 0.499 */ | |
856 | /* when the button is unchecked. The reason for it is unknown. The */ | |
857 | /* color is COLOR_BTNHIGHLIGHT, although the polygon gets painted at */ | |
858 | /* least 3 times (it looks like a clip-region when you see it happen). */ | |
859 | /* I do not really see a reason why this should be implemented. If you */ | |
860 | /* have a good reason, let me know. Maybe this is a quirk in the Marlett */ | |
861 | /* font. */ | |
862 | ||
863 | return TRUE; | |
864 | } | |
865 | ||
77b9918e AJ |
866 | /*********************************************************************** |
867 | * UITOOLS_DrawFrameButton | |
868 | */ | |
a3960292 | 869 | static BOOL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState) |
77b9918e | 870 | { |
44ed71f5 AJ |
871 | switch(uState & 0xff) |
872 | { | |
873 | case DFCS_BUTTONPUSH: | |
54c2711f | 874 | return UITOOLS95_DFC_ButtonPush(hdc, rc, uState); |
44ed71f5 AJ |
875 | |
876 | case DFCS_BUTTONCHECK: | |
877 | case DFCS_BUTTON3STATE: | |
54c2711f | 878 | return UITOOLS95_DFC_ButtonCheck(hdc, rc, uState); |
44ed71f5 AJ |
879 | |
880 | case DFCS_BUTTONRADIOIMAGE: | |
881 | case DFCS_BUTTONRADIOMASK: | |
882 | case DFCS_BUTTONRADIO: | |
54c2711f | 883 | return UITOOLS95_DFC_ButtonRadio(hdc, rc, uState); |
44ed71f5 AJ |
884 | |
885 | default: | |
9fe7a254 | 886 | WARN("Invalid button state=0x%04x\n", uState); |
44ed71f5 AJ |
887 | } |
888 | ||
77b9918e AJ |
889 | return FALSE; |
890 | } | |
891 | ||
892 | /*********************************************************************** | |
893 | * UITOOLS_DrawFrameCaption | |
44ed71f5 AJ |
894 | * |
895 | * Draw caption buttons (win95), coming from DrawFrameControl() | |
77b9918e | 896 | */ |
44ed71f5 | 897 | |
a3960292 | 898 | static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags) |
77b9918e | 899 | { |
a3960292 | 900 | RECT myr; |
44ed71f5 | 901 | int SmallDiam = UITOOLS_MakeSquareRect(r, &myr)-2; |
a3960292 | 902 | HFONT hfsave, hf; |
63c06aa0 | 903 | int colorIdx = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT; |
44ed71f5 AJ |
904 | int xc = (myr.left+myr.right)/2; |
905 | int yc = (myr.top+myr.bottom)/2; | |
0ee1f711 FR |
906 | WCHAR str[2] = {0, 0}; |
907 | static const WCHAR glyphFontName[] = { 'M','a','r','l','e','t','t',0 }; | |
a3960292 | 908 | UINT alignsave; |
44ed71f5 AJ |
909 | int bksave; |
910 | COLORREF clrsave; | |
a3960292 | 911 | SIZE size; |
44ed71f5 | 912 | |
54c2711f | 913 | UITOOLS95_DFC_ButtonPush(dc, r, uFlags & 0xff00); |
44ed71f5 AJ |
914 | |
915 | switch(uFlags & 0xff) | |
916 | { | |
0ee1f711 FR |
917 | case DFCS_CAPTIONCLOSE: str[0] = 0x72; break; |
918 | case DFCS_CAPTIONHELP: str[0] = 0x73; break; | |
919 | case DFCS_CAPTIONMIN: str[0] = 0x30; break; | |
920 | case DFCS_CAPTIONMAX: str[0] = 0x31; break; | |
921 | case DFCS_CAPTIONRESTORE: str[0] = 0x32; break; | |
44ed71f5 | 922 | default: |
9fe7a254 | 923 | WARN("Invalid caption; flags=0x%04x\n", uFlags); |
44ed71f5 AJ |
924 | return FALSE; |
925 | } | |
0ee1f711 FR |
926 | |
927 | hf = CreateFontW(-SmallDiam, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, | |
928 | SYMBOL_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, | |
929 | DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, glyphFontName); | |
930 | alignsave = SetTextAlign(dc, TA_TOP|TA_LEFT); | |
931 | bksave = SetBkMode(dc, TRANSPARENT); | |
932 | clrsave = GetTextColor(dc); | |
4fc84eaf | 933 | hfsave = SelectObject(dc, hf); |
0ee1f711 | 934 | GetTextExtentPoint32W(dc, str, 1, &size); |
44ed71f5 | 935 | |
44ed71f5 AJ |
936 | if(uFlags & DFCS_INACTIVE) |
937 | { | |
0ee1f711 FR |
938 | SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); |
939 | TextOutW(dc, xc-size.cx/2+1, yc-size.cy/2+1, str, 1); | |
44ed71f5 | 940 | } |
0ee1f711 FR |
941 | SetTextColor(dc, GetSysColor(colorIdx)); |
942 | TextOutW(dc, xc-size.cx/2, yc-size.cy/2, str, 1); | |
44ed71f5 | 943 | |
0ee1f711 FR |
944 | SelectObject(dc, hfsave); |
945 | SetTextColor(dc, clrsave); | |
946 | SetBkMode(dc, bksave); | |
947 | SetTextAlign(dc, alignsave); | |
948 | DeleteObject(hf); | |
949 | ||
44ed71f5 | 950 | return TRUE; |
77b9918e AJ |
951 | } |
952 | ||
44ed71f5 AJ |
953 | |
954 | /************************************************************************ | |
955 | * UITOOLS_DrawFrameScroll | |
956 | * | |
957 | * Draw a scroll-bar control coming from DrawFrameControl() | |
77b9918e | 958 | */ |
a3960292 | 959 | static BOOL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags) |
77b9918e | 960 | { |
a3960292 AJ |
961 | POINT Line[4]; |
962 | RECT myr; | |
44ed71f5 AJ |
963 | int SmallDiam = UITOOLS_MakeSquareRect(r, &myr) - 2; |
964 | int i; | |
a3960292 AJ |
965 | HBRUSH hbsave, hb, hb2; |
966 | HPEN hpsave, hp, hp2; | |
b49b4117 | 967 | int tri = 290*SmallDiam/1000 - 1; |
44ed71f5 AJ |
968 | int d46, d93; |
969 | ||
742e1354 FB |
970 | /* |
971 | * This fixes a problem with really tiny "scroll" buttons. In particular | |
9a624916 | 972 | * with the updown control. |
742e1354 FB |
973 | * Making sure that the arrow is as least 3 pixels wide (or high). |
974 | */ | |
975 | if (tri == 0) | |
976 | tri = 1; | |
977 | ||
44ed71f5 AJ |
978 | switch(uFlags & 0xff) |
979 | { | |
980 | case DFCS_SCROLLCOMBOBOX: | |
981 | case DFCS_SCROLLDOWN: | |
982 | Line[2].x = myr.left + 470*SmallDiam/1000 + 2; | |
983 | Line[2].y = myr.top + 687*SmallDiam/1000 + 1; | |
984 | Line[0].x = Line[2].x - tri; | |
985 | Line[1].x = Line[2].x + tri; | |
986 | Line[0].y = Line[1].y = Line[2].y - tri; | |
987 | break; | |
988 | ||
989 | case DFCS_SCROLLUP: | |
990 | Line[2].x = myr.left + 470*SmallDiam/1000 + 2; | |
b49b4117 | 991 | Line[2].y = myr.bottom - (687*SmallDiam/1000 + 1); |
44ed71f5 AJ |
992 | Line[0].x = Line[2].x - tri; |
993 | Line[1].x = Line[2].x + tri; | |
994 | Line[0].y = Line[1].y = Line[2].y + tri; | |
995 | break; | |
996 | ||
997 | case DFCS_SCROLLLEFT: | |
b49b4117 | 998 | Line[2].x = myr.right - (687*SmallDiam/1000 + 1); |
44ed71f5 AJ |
999 | Line[2].y = myr.top + 470*SmallDiam/1000 + 2; |
1000 | Line[0].y = Line[2].y - tri; | |
1001 | Line[1].y = Line[2].y + tri; | |
1002 | Line[0].x = Line[1].x = Line[2].x + tri; | |
1003 | break; | |
1004 | ||
1005 | case DFCS_SCROLLRIGHT: | |
1006 | Line[2].x = myr.left + 687*SmallDiam/1000 + 1; | |
1007 | Line[2].y = myr.top + 470*SmallDiam/1000 + 2; | |
1008 | Line[0].y = Line[2].y - tri; | |
1009 | Line[1].y = Line[2].y + tri; | |
1010 | Line[0].x = Line[1].x = Line[2].x - tri; | |
1011 | break; | |
1012 | ||
1013 | case DFCS_SCROLLSIZEGRIP: | |
1014 | /* This one breaks the flow... */ | |
54c2711f | 1015 | UITOOLS95_DrawRectEdge(dc, r, EDGE_BUMP, BF_MIDDLE | ((uFlags&(DFCS_MONO|DFCS_FLAT)) ? BF_MONO : 0)); |
4fc84eaf MS |
1016 | hpsave = SelectObject(dc, GetStockObject(NULL_PEN)); |
1017 | hbsave = SelectObject(dc, GetStockObject(NULL_BRUSH)); | |
44ed71f5 AJ |
1018 | if(uFlags & (DFCS_MONO|DFCS_FLAT)) |
1019 | { | |
4344c368 | 1020 | hp = hp2 = SYSCOLOR_GetPen(COLOR_WINDOWFRAME); |
a3960292 | 1021 | hb = hb2 = GetSysColorBrush(COLOR_WINDOWFRAME); |
44ed71f5 AJ |
1022 | } |
1023 | else | |
1024 | { | |
4344c368 AJ |
1025 | hp = SYSCOLOR_GetPen(COLOR_BTNHIGHLIGHT); |
1026 | hp2 = SYSCOLOR_GetPen(COLOR_BTNSHADOW); | |
a3960292 AJ |
1027 | hb = GetSysColorBrush(COLOR_BTNHIGHLIGHT); |
1028 | hb2 = GetSysColorBrush(COLOR_BTNSHADOW); | |
44ed71f5 AJ |
1029 | } |
1030 | Line[0].x = Line[1].x = r->right-1; | |
1031 | Line[2].y = Line[3].y = r->bottom-1; | |
1032 | d46 = 46*SmallDiam/750; | |
1033 | d93 = 93*SmallDiam/750; | |
1034 | ||
1035 | i = 586*SmallDiam/750; | |
1036 | Line[0].y = r->bottom - i - 1; | |
1037 | Line[3].x = r->right - i - 1; | |
1038 | Line[1].y = Line[0].y + d46; | |
1039 | Line[2].x = Line[3].x + d46; | |
a3960292 AJ |
1040 | SelectObject(dc, hb); |
1041 | SelectObject(dc, hp); | |
1042 | Polygon(dc, Line, 4); | |
44ed71f5 AJ |
1043 | |
1044 | Line[1].y++; Line[2].x++; | |
1045 | Line[0].y = Line[1].y + d93; | |
1046 | Line[3].x = Line[2].x + d93; | |
a3960292 AJ |
1047 | SelectObject(dc, hb2); |
1048 | SelectObject(dc, hp2); | |
1049 | Polygon(dc, Line, 4); | |
44ed71f5 AJ |
1050 | |
1051 | i = 398*SmallDiam/750; | |
1052 | Line[0].y = r->bottom - i - 1; | |
1053 | Line[3].x = r->right - i - 1; | |
1054 | Line[1].y = Line[0].y + d46; | |
1055 | Line[2].x = Line[3].x + d46; | |
a3960292 AJ |
1056 | SelectObject(dc, hb); |
1057 | SelectObject(dc, hp); | |
1058 | Polygon(dc, Line, 4); | |
44ed71f5 AJ |
1059 | |
1060 | Line[1].y++; Line[2].x++; | |
1061 | Line[0].y = Line[1].y + d93; | |
1062 | Line[3].x = Line[2].x + d93; | |
a3960292 AJ |
1063 | SelectObject(dc, hb2); |
1064 | SelectObject(dc, hp2); | |
1065 | Polygon(dc, Line, 4); | |
44ed71f5 AJ |
1066 | |
1067 | i = 210*SmallDiam/750; | |
1068 | Line[0].y = r->bottom - i - 1; | |
1069 | Line[3].x = r->right - i - 1; | |
1070 | Line[1].y = Line[0].y + d46; | |
1071 | Line[2].x = Line[3].x + d46; | |
a3960292 AJ |
1072 | SelectObject(dc, hb); |
1073 | SelectObject(dc, hp); | |
1074 | Polygon(dc, Line, 4); | |
44ed71f5 AJ |
1075 | |
1076 | Line[1].y++; Line[2].x++; | |
1077 | Line[0].y = Line[1].y + d93; | |
1078 | Line[3].x = Line[2].x + d93; | |
a3960292 AJ |
1079 | SelectObject(dc, hb2); |
1080 | SelectObject(dc, hp2); | |
1081 | Polygon(dc, Line, 4); | |
44ed71f5 | 1082 | |
a3960292 AJ |
1083 | SelectObject(dc, hpsave); |
1084 | SelectObject(dc, hbsave); | |
44ed71f5 AJ |
1085 | return TRUE; |
1086 | ||
1087 | default: | |
9fe7a254 | 1088 | WARN("Invalid scroll; flags=0x%04x\n", uFlags); |
44ed71f5 AJ |
1089 | return FALSE; |
1090 | } | |
1091 | ||
1092 | /* Here do the real scroll-bar controls end up */ | |
b49b4117 DB |
1093 | if( ! (uFlags & (0xff00 & ~DFCS_ADJUSTRECT)) ) |
1094 | /* UITOOLS95_DFC_ButtonPush always uses BF_SOFT which we don't */ | |
1095 | /* want for the normal scroll-arrow button. */ | |
1096 | UITOOLS95_DrawRectEdge( dc, r, EDGE_RAISED, (uFlags&DFCS_ADJUSTRECT) | BF_MIDDLE | BF_RECT); | |
1097 | else | |
1098 | UITOOLS95_DFC_ButtonPush(dc, r, (uFlags & 0xff00) ); | |
44ed71f5 AJ |
1099 | |
1100 | if(uFlags & DFCS_INACTIVE) | |
1101 | { | |
4fc84eaf MS |
1102 | hbsave = SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); |
1103 | hpsave = SelectObject(dc, SYSCOLOR_GetPen(COLOR_BTNHIGHLIGHT)); | |
a3960292 AJ |
1104 | Polygon(dc, Line, 3); |
1105 | SelectObject(dc, hpsave); | |
1106 | SelectObject(dc, hbsave); | |
44ed71f5 AJ |
1107 | } |
1108 | ||
b49b4117 DB |
1109 | if( (uFlags & DFCS_INACTIVE) || !(uFlags & DFCS_PUSHED) ) |
1110 | for(i = 0; i < 3; i++) | |
1111 | { | |
44ed71f5 AJ |
1112 | Line[i].x--; |
1113 | Line[i].y--; | |
b49b4117 | 1114 | } |
44ed71f5 | 1115 | |
02e90087 | 1116 | i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT; |
4fc84eaf MS |
1117 | hbsave = SelectObject(dc, GetSysColorBrush(i)); |
1118 | hpsave = SelectObject(dc, SYSCOLOR_GetPen(i)); | |
a3960292 AJ |
1119 | Polygon(dc, Line, 3); |
1120 | SelectObject(dc, hpsave); | |
1121 | SelectObject(dc, hbsave); | |
44ed71f5 AJ |
1122 | |
1123 | return TRUE; | |
77b9918e AJ |
1124 | } |
1125 | ||
44ed71f5 AJ |
1126 | /************************************************************************ |
1127 | * UITOOLS_DrawFrameMenu | |
1128 | * | |
1129 | * Draw a menu control coming from DrawFrameControl() | |
77b9918e | 1130 | */ |
a3960292 | 1131 | static BOOL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags) |
77b9918e | 1132 | { |
a3960292 AJ |
1133 | POINT Points[6]; |
1134 | RECT myr; | |
44ed71f5 AJ |
1135 | int SmallDiam = UITOOLS_MakeSquareRect(r, &myr); |
1136 | int i; | |
a3960292 AJ |
1137 | HBRUSH hbsave; |
1138 | HPEN hpsave; | |
44ed71f5 AJ |
1139 | int xe, ye; |
1140 | int xc, yc; | |
a3960292 | 1141 | BOOL retval = TRUE; |
44ed71f5 AJ |
1142 | |
1143 | /* Using black and white seems to be utterly wrong, but win95 doesn't */ | |
1144 | /* use anything else. I think I tried all sys-colors to change things */ | |
1145 | /* without luck. It seems as if this behavior is inherited from the */ | |
1146 | /* win31 DFC() implementation... (you remember, B/W menus). */ | |
1147 | ||
214b40b1 | 1148 | FillRect(dc, r, GetStockObject(WHITE_BRUSH)); |
44ed71f5 | 1149 | |
4fc84eaf MS |
1150 | hbsave = SelectObject(dc, GetStockObject(BLACK_BRUSH)); |
1151 | hpsave = SelectObject(dc, GetStockObject(BLACK_PEN)); | |
44ed71f5 AJ |
1152 | |
1153 | switch(uFlags & 0xff) | |
1154 | { | |
1155 | case DFCS_MENUARROW: | |
1156 | i = 187*SmallDiam/750; | |
1157 | Points[2].x = myr.left + 468*SmallDiam/750; | |
1158 | Points[2].y = myr.top + 352*SmallDiam/750+1; | |
1159 | Points[0].y = Points[2].y - i; | |
1160 | Points[1].y = Points[2].y + i; | |
1161 | Points[0].x = Points[1].x = Points[2].x - i; | |
a3960292 | 1162 | Polygon(dc, Points, 3); |
44ed71f5 AJ |
1163 | break; |
1164 | ||
1165 | case DFCS_MENUBULLET: | |
1166 | xe = myr.left; | |
1167 | ye = myr.top + SmallDiam - SmallDiam/2; | |
1168 | xc = myr.left + SmallDiam - SmallDiam/2; | |
1169 | yc = myr.top + SmallDiam - SmallDiam/2; | |
1170 | i = 234*SmallDiam/750; | |
1171 | i = i < 1 ? 1 : i; | |
1172 | myr.left = xc - i+i/2; | |
1173 | myr.right = xc + i/2; | |
1174 | myr.top = yc - i+i/2; | |
1175 | myr.bottom = yc + i/2; | |
a3960292 | 1176 | Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye); |
44ed71f5 AJ |
1177 | break; |
1178 | ||
1179 | case DFCS_MENUCHECK: | |
1180 | Points[0].x = myr.left + 253*SmallDiam/1000; | |
1181 | Points[0].y = myr.top + 445*SmallDiam/1000; | |
1182 | Points[1].x = myr.left + 409*SmallDiam/1000; | |
1183 | Points[1].y = Points[0].y + (Points[1].x-Points[0].x); | |
1184 | Points[2].x = myr.left + 690*SmallDiam/1000; | |
1185 | Points[2].y = Points[1].y - (Points[2].x-Points[1].x); | |
1186 | Points[3].x = Points[2].x; | |
1187 | Points[3].y = Points[2].y + 3*SmallDiam/16; | |
1188 | Points[4].x = Points[1].x; | |
1189 | Points[4].y = Points[1].y + 3*SmallDiam/16; | |
1190 | Points[5].x = Points[0].x; | |
1191 | Points[5].y = Points[0].y + 3*SmallDiam/16; | |
a3960292 | 1192 | Polygon(dc, Points, 6); |
44ed71f5 AJ |
1193 | break; |
1194 | ||
1195 | default: | |
9fe7a254 | 1196 | WARN("Invalid menu; flags=0x%04x\n", uFlags); |
44ed71f5 AJ |
1197 | retval = FALSE; |
1198 | break; | |
1199 | } | |
1200 | ||
a3960292 AJ |
1201 | SelectObject(dc, hpsave); |
1202 | SelectObject(dc, hbsave); | |
44ed71f5 | 1203 | return retval; |
77b9918e AJ |
1204 | } |
1205 | ||
1206 | ||
77b9918e | 1207 | /********************************************************************** |
0c610287 | 1208 | * DrawFrameControl (USER32.@) |
77b9918e | 1209 | */ |
a3960292 AJ |
1210 | BOOL WINAPI DrawFrameControl( HDC hdc, LPRECT rc, UINT uType, |
1211 | UINT uState ) | |
77b9918e | 1212 | { |
44ed71f5 | 1213 | /* Win95 doesn't support drawing in other mapping modes */ |
a3960292 | 1214 | if(GetMapMode(hdc) != MM_TEXT) |
44ed71f5 | 1215 | return FALSE; |
9a624916 | 1216 | |
77b9918e AJ |
1217 | switch(uType) |
1218 | { | |
1219 | case DFC_BUTTON: | |
54c2711f | 1220 | return UITOOLS95_DrawFrameButton(hdc, rc, uState); |
77b9918e | 1221 | case DFC_CAPTION: |
54c2711f | 1222 | return UITOOLS95_DrawFrameCaption(hdc, rc, uState); |
77b9918e | 1223 | case DFC_MENU: |
54c2711f | 1224 | return UITOOLS95_DrawFrameMenu(hdc, rc, uState); |
8fce1a4c DP |
1225 | /*case DFC_POPUPMENU: |
1226 | FIXME("DFC_POPUPMENU: not implemented\n"); | |
1227 | break;*/ | |
77b9918e | 1228 | case DFC_SCROLL: |
54c2711f | 1229 | return UITOOLS95_DrawFrameScroll(hdc, rc, uState); |
77b9918e | 1230 | default: |
aff7ddae | 1231 | WARN("(%p,%p,%d,%x), bad type!\n", hdc,rc,uType,uState ); |
77b9918e AJ |
1232 | } |
1233 | return FALSE; | |
1234 | } | |
f56c6fb9 AJ |
1235 | |
1236 | ||
d54db191 AJ |
1237 | /*********************************************************************** |
1238 | * SetRect (USER32.@) | |
1239 | */ | |
1240 | BOOL WINAPI SetRect( LPRECT rect, INT left, INT top, | |
1241 | INT right, INT bottom ) | |
1242 | { | |
1243 | if (!rect) return FALSE; | |
1244 | rect->left = left; | |
1245 | rect->right = right; | |
1246 | rect->top = top; | |
1247 | rect->bottom = bottom; | |
1248 | return TRUE; | |
1249 | } | |
1250 | ||
1251 | ||
1252 | /*********************************************************************** | |
1253 | * SetRectEmpty (USER32.@) | |
1254 | */ | |
1255 | BOOL WINAPI SetRectEmpty( LPRECT rect ) | |
1256 | { | |
1257 | if (!rect) return FALSE; | |
1258 | rect->left = rect->right = rect->top = rect->bottom = 0; | |
1259 | return TRUE; | |
1260 | } | |
1261 | ||
1262 | ||
1263 | /*********************************************************************** | |
1264 | * CopyRect (USER32.@) | |
1265 | */ | |
1266 | BOOL WINAPI CopyRect( RECT *dest, const RECT *src ) | |
1267 | { | |
1268 | if (!dest || !src) return FALSE; | |
1269 | *dest = *src; | |
1270 | return TRUE; | |
1271 | } | |
1272 | ||
1273 | ||
1274 | /*********************************************************************** | |
1275 | * IsRectEmpty (USER32.@) | |
1276 | * | |
1277 | * Bug compat: Windows checks for 0 or negative width/height. | |
1278 | */ | |
1279 | BOOL WINAPI IsRectEmpty( const RECT *rect ) | |
1280 | { | |
1281 | if (!rect) return TRUE; | |
1282 | return ((rect->left >= rect->right) || (rect->top >= rect->bottom)); | |
1283 | } | |
1284 | ||
1285 | ||
1286 | /*********************************************************************** | |
1287 | * PtInRect (USER32.@) | |
1288 | */ | |
1289 | BOOL WINAPI PtInRect( const RECT *rect, POINT pt ) | |
1290 | { | |
1291 | if (!rect) return FALSE; | |
1292 | return ((pt.x >= rect->left) && (pt.x < rect->right) && | |
1293 | (pt.y >= rect->top) && (pt.y < rect->bottom)); | |
1294 | } | |
1295 | ||
1296 | ||
1297 | /*********************************************************************** | |
1298 | * OffsetRect (USER32.@) | |
1299 | */ | |
1300 | BOOL WINAPI OffsetRect( LPRECT rect, INT x, INT y ) | |
1301 | { | |
1302 | if (!rect) return FALSE; | |
1303 | rect->left += x; | |
1304 | rect->right += x; | |
1305 | rect->top += y; | |
1306 | rect->bottom += y; | |
1307 | return TRUE; | |
1308 | } | |
1309 | ||
1310 | ||
1311 | /*********************************************************************** | |
1312 | * InflateRect (USER32.@) | |
1313 | */ | |
1314 | BOOL WINAPI InflateRect( LPRECT rect, INT x, INT y ) | |
1315 | { | |
1316 | if (!rect) return FALSE; | |
1317 | rect->left -= x; | |
1318 | rect->top -= y; | |
1319 | rect->right += x; | |
1320 | rect->bottom += y; | |
1321 | return TRUE; | |
1322 | } | |
1323 | ||
1324 | ||
1325 | /*********************************************************************** | |
1326 | * IntersectRect (USER32.@) | |
1327 | */ | |
1328 | BOOL WINAPI IntersectRect( LPRECT dest, const RECT *src1, const RECT *src2 ) | |
1329 | { | |
1330 | if (!dest || !src1 || !src2) return FALSE; | |
1331 | if (IsRectEmpty(src1) || IsRectEmpty(src2) || | |
1332 | (src1->left >= src2->right) || (src2->left >= src1->right) || | |
1333 | (src1->top >= src2->bottom) || (src2->top >= src1->bottom)) | |
1334 | { | |
1335 | SetRectEmpty( dest ); | |
1336 | return FALSE; | |
1337 | } | |
1338 | dest->left = max( src1->left, src2->left ); | |
1339 | dest->right = min( src1->right, src2->right ); | |
1340 | dest->top = max( src1->top, src2->top ); | |
1341 | dest->bottom = min( src1->bottom, src2->bottom ); | |
1342 | return TRUE; | |
1343 | } | |
1344 | ||
1345 | ||
1346 | /*********************************************************************** | |
1347 | * UnionRect (USER32.@) | |
1348 | */ | |
1349 | BOOL WINAPI UnionRect( LPRECT dest, const RECT *src1, const RECT *src2 ) | |
1350 | { | |
1351 | if (!dest) return FALSE; | |
1352 | if (IsRectEmpty(src1)) | |
1353 | { | |
1354 | if (IsRectEmpty(src2)) | |
1355 | { | |
1356 | SetRectEmpty( dest ); | |
1357 | return FALSE; | |
1358 | } | |
1359 | else *dest = *src2; | |
1360 | } | |
1361 | else | |
1362 | { | |
1363 | if (IsRectEmpty(src2)) *dest = *src1; | |
1364 | else | |
1365 | { | |
1366 | dest->left = min( src1->left, src2->left ); | |
1367 | dest->right = max( src1->right, src2->right ); | |
1368 | dest->top = min( src1->top, src2->top ); | |
1369 | dest->bottom = max( src1->bottom, src2->bottom ); | |
1370 | } | |
1371 | } | |
1372 | return TRUE; | |
1373 | } | |
1374 | ||
1375 | ||
1376 | /*********************************************************************** | |
1377 | * EqualRect (USER32.@) | |
1378 | */ | |
1379 | BOOL WINAPI EqualRect( const RECT* rect1, const RECT* rect2 ) | |
1380 | { | |
1381 | if (!rect1 || !rect2) return FALSE; | |
1382 | return ((rect1->left == rect2->left) && (rect1->right == rect2->right) && | |
1383 | (rect1->top == rect2->top) && (rect1->bottom == rect2->bottom)); | |
1384 | } | |
1385 | ||
1386 | ||
1387 | /*********************************************************************** | |
1388 | * SubtractRect (USER32.@) | |
1389 | */ | |
1390 | BOOL WINAPI SubtractRect( LPRECT dest, const RECT *src1, const RECT *src2 ) | |
1391 | { | |
1392 | RECT tmp; | |
1393 | ||
1394 | if (!dest) return FALSE; | |
1395 | if (IsRectEmpty( src1 )) | |
1396 | { | |
1397 | SetRectEmpty( dest ); | |
1398 | return FALSE; | |
1399 | } | |
1400 | *dest = *src1; | |
1401 | if (IntersectRect( &tmp, src1, src2 )) | |
1402 | { | |
1403 | if (EqualRect( &tmp, dest )) | |
1404 | { | |
1405 | SetRectEmpty( dest ); | |
1406 | return FALSE; | |
1407 | } | |
1408 | if ((tmp.top == dest->top) && (tmp.bottom == dest->bottom)) | |
1409 | { | |
1410 | if (tmp.left == dest->left) dest->left = tmp.right; | |
1411 | else if (tmp.right == dest->right) dest->right = tmp.left; | |
1412 | } | |
1413 | else if ((tmp.left == dest->left) && (tmp.right == dest->right)) | |
1414 | { | |
1415 | if (tmp.top == dest->top) dest->top = tmp.bottom; | |
1416 | else if (tmp.bottom == dest->bottom) dest->bottom = tmp.top; | |
1417 | } | |
1418 | } | |
1419 | return TRUE; | |
1420 | } | |
1421 | ||
1422 | ||
f56c6fb9 AJ |
1423 | /*********************************************************************** |
1424 | * FillRect (USER32.@) | |
1425 | */ | |
1426 | INT WINAPI FillRect( HDC hdc, const RECT *rect, HBRUSH hbrush ) | |
1427 | { | |
ff12594a | 1428 | HBRUSH prev_brush; |
f56c6fb9 | 1429 | |
9a295e7f | 1430 | if (hbrush <= (HBRUSH) (COLOR_MAX + 1)) hbrush = GetSysColorBrush( HandleToULong(hbrush) - 1 ); |
f56c6fb9 | 1431 | |
ff12594a | 1432 | prev_brush = SelectObject( hdc, hbrush ); |
f56c6fb9 AJ |
1433 | PatBlt( hdc, rect->left, rect->top, |
1434 | rect->right - rect->left, rect->bottom - rect->top, PATCOPY ); | |
ff12594a | 1435 | if (prev_brush) SelectObject( hdc, prev_brush ); |
f56c6fb9 AJ |
1436 | return 1; |
1437 | } | |
1438 | ||
1439 | ||
1440 | /*********************************************************************** | |
1441 | * InvertRect (USER32.@) | |
1442 | */ | |
1443 | BOOL WINAPI InvertRect( HDC hdc, const RECT *rect ) | |
1444 | { | |
1445 | return PatBlt( hdc, rect->left, rect->top, | |
1446 | rect->right - rect->left, rect->bottom - rect->top, DSTINVERT ); | |
1447 | } | |
1448 | ||
1449 | ||
1450 | /*********************************************************************** | |
1451 | * FrameRect (USER32.@) | |
1452 | */ | |
1453 | INT WINAPI FrameRect( HDC hdc, const RECT *rect, HBRUSH hbrush ) | |
1454 | { | |
1455 | HBRUSH prevBrush; | |
1456 | RECT r = *rect; | |
1457 | ||
1458 | if ( (r.right <= r.left) || (r.bottom <= r.top) ) return 0; | |
1459 | if (!(prevBrush = SelectObject( hdc, hbrush ))) return 0; | |
1460 | ||
1461 | PatBlt( hdc, r.left, r.top, 1, r.bottom - r.top, PATCOPY ); | |
1462 | PatBlt( hdc, r.right - 1, r.top, 1, r.bottom - r.top, PATCOPY ); | |
1463 | PatBlt( hdc, r.left, r.top, r.right - r.left, 1, PATCOPY ); | |
1464 | PatBlt( hdc, r.left, r.bottom - 1, r.right - r.left, 1, PATCOPY ); | |
1465 | ||
1466 | SelectObject( hdc, prevBrush ); | |
1467 | return TRUE; | |
1468 | } | |
1469 | ||
1470 | ||
1471 | /*********************************************************************** | |
1472 | * DrawFocusRect (USER32.@) | |
1473 | * | |
1474 | * FIXME: PatBlt(PATINVERT) with background brush. | |
1475 | */ | |
1476 | BOOL WINAPI DrawFocusRect( HDC hdc, const RECT* rc ) | |
1477 | { | |
1478 | HBRUSH hOldBrush; | |
1479 | HPEN hOldPen, hNewPen; | |
1480 | INT oldDrawMode, oldBkMode; | |
6b76244b | 1481 | LOGBRUSH lb; |
f56c6fb9 AJ |
1482 | |
1483 | hOldBrush = SelectObject(hdc, GetStockObject(NULL_BRUSH)); | |
6b76244b AJ |
1484 | lb.lbStyle = BS_SOLID; |
1485 | lb.lbColor = GetSysColor(COLOR_WINDOWTEXT); | |
1486 | hNewPen = ExtCreatePen(PS_COSMETIC|PS_ALTERNATE, 1, &lb, 0, NULL); | |
f56c6fb9 AJ |
1487 | hOldPen = SelectObject(hdc, hNewPen); |
1488 | oldDrawMode = SetROP2(hdc, R2_XORPEN); | |
1489 | oldBkMode = SetBkMode(hdc, TRANSPARENT); | |
1490 | ||
1491 | Rectangle(hdc, rc->left, rc->top, rc->right, rc->bottom); | |
1492 | ||
1493 | SetBkMode(hdc, oldBkMode); | |
1494 | SetROP2(hdc, oldDrawMode); | |
1495 | SelectObject(hdc, hOldPen); | |
1496 | DeleteObject(hNewPen); | |
1497 | SelectObject(hdc, hOldBrush); | |
1498 | ||
1499 | return TRUE; | |
1500 | } | |
1501 | ||
1502 | ||
1503 | /********************************************************************** | |
1504 | * DrawAnimatedRects (USER32.@) | |
1505 | */ | |
1506 | BOOL WINAPI DrawAnimatedRects( HWND hwnd, INT idAni, const RECT* lprcFrom, const RECT* lprcTo ) | |
1507 | { | |
1508 | FIXME("(%p,%d,%p,%p): stub\n",hwnd,idAni,lprcFrom,lprcTo); | |
1509 | return TRUE; | |
1510 | } | |
1511 | ||
1512 | ||
1513 | /********************************************************************** | |
1514 | * UITOOLS_DrawStateJam | |
1515 | * | |
1516 | * Jams in the requested type in the dc | |
1517 | */ | |
1518 | static BOOL UITOOLS_DrawStateJam( HDC hdc, UINT opcode, DRAWSTATEPROC func, LPARAM lp, WPARAM wp, | |
1519 | LPRECT rc, UINT dtflags, BOOL unicode ) | |
1520 | { | |
1521 | HDC memdc; | |
1522 | HBITMAP hbmsave; | |
1523 | BOOL retval; | |
1524 | INT cx = rc->right - rc->left; | |
1525 | INT cy = rc->bottom - rc->top; | |
1526 | ||
1527 | switch(opcode) | |
1528 | { | |
1529 | case DST_TEXT: | |
1530 | case DST_PREFIXTEXT: | |
1531 | if(unicode) | |
1532 | return DrawTextW(hdc, (LPWSTR)lp, (INT)wp, rc, dtflags); | |
1533 | else | |
1534 | return DrawTextA(hdc, (LPSTR)lp, (INT)wp, rc, dtflags); | |
1535 | ||
1536 | case DST_ICON: | |
2326f3d4 | 1537 | return DrawIconEx(hdc, rc->left, rc->top, (HICON)lp, 0, 0, 0, NULL, DI_NORMAL); |
f56c6fb9 AJ |
1538 | |
1539 | case DST_BITMAP: | |
1540 | memdc = CreateCompatibleDC(hdc); | |
1541 | if(!memdc) return FALSE; | |
4fc84eaf | 1542 | hbmsave = SelectObject(memdc, (HBITMAP)lp); |
f56c6fb9 AJ |
1543 | if(!hbmsave) |
1544 | { | |
1545 | DeleteDC(memdc); | |
1546 | return FALSE; | |
1547 | } | |
1548 | retval = BitBlt(hdc, rc->left, rc->top, cx, cy, memdc, 0, 0, SRCCOPY); | |
1549 | SelectObject(memdc, hbmsave); | |
1550 | DeleteDC(memdc); | |
1551 | return retval; | |
1552 | ||
1553 | case DST_COMPLEX: | |
1554 | if(func) { | |
1555 | BOOL bRet; | |
1556 | /* DRAWSTATEPROC assumes that it draws at the center of coordinates */ | |
1557 | ||
1558 | OffsetViewportOrgEx(hdc, rc->left, rc->top, NULL); | |
1559 | bRet = func(hdc, lp, wp, cx, cy); | |
1560 | /* Restore origin */ | |
1561 | OffsetViewportOrgEx(hdc, -rc->left, -rc->top, NULL); | |
1562 | return bRet; | |
1563 | } else | |
1564 | return FALSE; | |
1565 | } | |
1566 | return FALSE; | |
1567 | } | |
1568 | ||
1569 | /********************************************************************** | |
1570 | * UITOOLS_DrawState() | |
1571 | */ | |
1572 | static BOOL UITOOLS_DrawState(HDC hdc, HBRUSH hbr, DRAWSTATEPROC func, LPARAM lp, WPARAM wp, | |
1573 | INT x, INT y, INT cx, INT cy, UINT flags, BOOL unicode ) | |
1574 | { | |
1575 | HBITMAP hbm, hbmsave; | |
1576 | HFONT hfsave; | |
1577 | HBRUSH hbsave, hbrtmp = 0; | |
1578 | HDC memdc; | |
1579 | RECT rc; | |
1580 | UINT dtflags = DT_NOCLIP; | |
1581 | COLORREF fg, bg; | |
1582 | UINT opcode = flags & 0xf; | |
1583 | INT len = wp; | |
1584 | BOOL retval, tmp; | |
1585 | ||
1586 | if((opcode == DST_TEXT || opcode == DST_PREFIXTEXT) && !len) /* The string is '\0' terminated */ | |
1587 | { | |
f097da9f DT |
1588 | if (!lp) return FALSE; |
1589 | ||
f56c6fb9 AJ |
1590 | if(unicode) |
1591 | len = strlenW((LPWSTR)lp); | |
1592 | else | |
1593 | len = strlen((LPSTR)lp); | |
1594 | } | |
1595 | ||
1596 | /* Find out what size the image has if not given by caller */ | |
1597 | if(!cx || !cy) | |
1598 | { | |
1599 | SIZE s; | |
f56c6fb9 AJ |
1600 | BITMAP bm; |
1601 | ||
1602 | switch(opcode) | |
1603 | { | |
1604 | case DST_TEXT: | |
1605 | case DST_PREFIXTEXT: | |
1606 | if(unicode) | |
1607 | retval = GetTextExtentPoint32W(hdc, (LPWSTR)lp, len, &s); | |
1608 | else | |
1609 | retval = GetTextExtentPoint32A(hdc, (LPSTR)lp, len, &s); | |
1610 | if(!retval) return FALSE; | |
1611 | break; | |
1612 | ||
1613 | case DST_ICON: | |
62ac036b | 1614 | if (!get_icon_size( (HICON)lp, &s )) return FALSE; |
f56c6fb9 AJ |
1615 | break; |
1616 | ||
1617 | case DST_BITMAP: | |
1618 | if(!GetObjectA((HBITMAP)lp, sizeof(bm), &bm)) return FALSE; | |
1619 | s.cx = bm.bmWidth; | |
1620 | s.cy = bm.bmHeight; | |
1621 | break; | |
1622 | ||
1623 | case DST_COMPLEX: /* cx and cy must be set in this mode */ | |
1624 | return FALSE; | |
1625 | } | |
1626 | ||
1627 | if(!cx) cx = s.cx; | |
1628 | if(!cy) cy = s.cy; | |
1629 | } | |
1630 | ||
1631 | rc.left = x; | |
1632 | rc.top = y; | |
1633 | rc.right = x + cx; | |
1634 | rc.bottom = y + cy; | |
1635 | ||
1636 | if(flags & DSS_RIGHT) /* This one is not documented in the win32.hlp file */ | |
1637 | dtflags |= DT_RIGHT; | |
1638 | if(opcode == DST_TEXT) | |
1639 | dtflags |= DT_NOPREFIX; | |
1640 | ||
1641 | /* For DSS_NORMAL we just jam in the image and return */ | |
1642 | if((flags & 0x7ff0) == DSS_NORMAL) | |
1643 | { | |
1644 | return UITOOLS_DrawStateJam(hdc, opcode, func, lp, len, &rc, dtflags, unicode); | |
1645 | } | |
1646 | ||
1647 | /* For all other states we need to convert the image to B/W in a local bitmap */ | |
1648 | /* before it is displayed */ | |
1649 | fg = SetTextColor(hdc, RGB(0, 0, 0)); | |
1650 | bg = SetBkColor(hdc, RGB(255, 255, 255)); | |
1651 | hbm = NULL; hbmsave = NULL; | |
1652 | memdc = NULL; hbsave = NULL; | |
1653 | retval = FALSE; /* assume failure */ | |
1654 | ||
1655 | /* From here on we must use "goto cleanup" when something goes wrong */ | |
1656 | hbm = CreateBitmap(cx, cy, 1, 1, NULL); | |
1657 | if(!hbm) goto cleanup; | |
1658 | memdc = CreateCompatibleDC(hdc); | |
1659 | if(!memdc) goto cleanup; | |
4fc84eaf | 1660 | hbmsave = SelectObject(memdc, hbm); |
f56c6fb9 AJ |
1661 | if(!hbmsave) goto cleanup; |
1662 | rc.left = rc.top = 0; | |
1663 | rc.right = cx; | |
1664 | rc.bottom = cy; | |
214b40b1 | 1665 | if(!FillRect(memdc, &rc, GetStockObject(WHITE_BRUSH))) goto cleanup; |
f56c6fb9 AJ |
1666 | SetBkColor(memdc, RGB(255, 255, 255)); |
1667 | SetTextColor(memdc, RGB(0, 0, 0)); | |
4fc84eaf | 1668 | hfsave = SelectObject(memdc, GetCurrentObject(hdc, OBJ_FONT)); |
f56c6fb9 AJ |
1669 | |
1670 | /* DST_COMPLEX may draw text as well, | |
1671 | * so we must be sure that correct font is selected | |
1672 | */ | |
1673 | if(!hfsave && (opcode <= DST_PREFIXTEXT)) goto cleanup; | |
1674 | tmp = UITOOLS_DrawStateJam(memdc, opcode, func, lp, len, &rc, dtflags, unicode); | |
1675 | if(hfsave) SelectObject(memdc, hfsave); | |
1676 | if(!tmp) goto cleanup; | |
1677 | ||
1678 | /* This state cause the image to be dithered */ | |
1679 | if(flags & DSS_UNION) | |
1680 | { | |
4fc84eaf | 1681 | hbsave = SelectObject(memdc, SYSCOLOR_55AABrush); |
f56c6fb9 AJ |
1682 | if(!hbsave) goto cleanup; |
1683 | tmp = PatBlt(memdc, 0, 0, cx, cy, 0x00FA0089); | |
1684 | SelectObject(memdc, hbsave); | |
1685 | if(!tmp) goto cleanup; | |
1686 | } | |
1687 | ||
1688 | if (flags & DSS_DISABLED) | |
1689 | hbrtmp = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT)); | |
1690 | else if (flags & DSS_DEFAULT) | |
1691 | hbrtmp = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW)); | |
1692 | ||
1693 | /* Draw light or dark shadow */ | |
1694 | if (flags & (DSS_DISABLED|DSS_DEFAULT)) | |
1695 | { | |
1696 | if(!hbrtmp) goto cleanup; | |
4fc84eaf | 1697 | hbsave = SelectObject(hdc, hbrtmp); |
f56c6fb9 AJ |
1698 | if(!hbsave) goto cleanup; |
1699 | if(!BitBlt(hdc, x+1, y+1, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup; | |
1700 | SelectObject(hdc, hbsave); | |
1701 | DeleteObject(hbrtmp); | |
1702 | hbrtmp = 0; | |
1703 | } | |
1704 | ||
1705 | if (flags & DSS_DISABLED) | |
1706 | { | |
1707 | hbr = hbrtmp = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW)); | |
1708 | if(!hbrtmp) goto cleanup; | |
1709 | } | |
1710 | else if (!hbr) | |
1711 | { | |
4fc84eaf | 1712 | hbr = GetStockObject(BLACK_BRUSH); |
f56c6fb9 AJ |
1713 | } |
1714 | ||
4fc84eaf | 1715 | hbsave = SelectObject(hdc, hbr); |
f56c6fb9 AJ |
1716 | |
1717 | if(!BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup; | |
1718 | ||
1719 | retval = TRUE; /* We succeeded */ | |
1720 | ||
1721 | cleanup: | |
1722 | SetTextColor(hdc, fg); | |
1723 | SetBkColor(hdc, bg); | |
1724 | ||
1725 | if(hbsave) SelectObject(hdc, hbsave); | |
1726 | if(hbmsave) SelectObject(memdc, hbmsave); | |
1727 | if(hbrtmp) DeleteObject(hbrtmp); | |
1728 | if(hbm) DeleteObject(hbm); | |
1729 | if(memdc) DeleteDC(memdc); | |
1730 | ||
1731 | return retval; | |
1732 | } | |
1733 | ||
1734 | /********************************************************************** | |
1735 | * DrawStateA (USER32.@) | |
1736 | */ | |
1737 | BOOL WINAPI DrawStateA(HDC hdc, HBRUSH hbr, | |
1738 | DRAWSTATEPROC func, LPARAM ldata, WPARAM wdata, | |
1739 | INT x, INT y, INT cx, INT cy, UINT flags) | |
1740 | { | |
1741 | return UITOOLS_DrawState(hdc, hbr, func, ldata, wdata, x, y, cx, cy, flags, FALSE); | |
1742 | } | |
1743 | ||
1744 | /********************************************************************** | |
1745 | * DrawStateW (USER32.@) | |
1746 | */ | |
1747 | BOOL WINAPI DrawStateW(HDC hdc, HBRUSH hbr, | |
1748 | DRAWSTATEPROC func, LPARAM ldata, WPARAM wdata, | |
1749 | INT x, INT y, INT cx, INT cy, UINT flags) | |
1750 | { | |
1751 | return UITOOLS_DrawState(hdc, hbr, func, ldata, wdata, x, y, cx, cy, flags, TRUE); | |
1752 | } |