Merge my current work done on the kd++ branch:
[reactos.git] / reactos / win32ss / user / user32 / windows / draw.c
1 /*
2 * ReactOS User32 Library
3 * - Various drawing functions
4 *
5 * Copyright 2001 Casper S. Hournstroup
6 * Copyright 2003 Andrew Greenwood
7 * Copyright 2003 Filip Navara
8 * Copyright 2009 Matthias Kupfer
9 *
10 * Based on Wine code.
11 *
12 * Copyright 1993, 1994 Alexandre Julliard
13 * Copyright 2002 Bill Medland
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 */
29
30 /* INCLUDES *******************************************************************/
31
32 #include <user32.h>
33
34 #include <wine/debug.h>
35
36 WINE_DEFAULT_DEBUG_CHANNEL(user32);
37
38 /* GLOBALS *******************************************************************/
39
40 static const WORD wPattern_AA55[8] = { 0xaaaa, 0x5555, 0xaaaa, 0x5555,
41 0xaaaa, 0x5555, 0xaaaa, 0x5555 };
42
43 /* These tables are used in:
44 * UITOOLS_DrawDiagEdge()
45 * UITOOLS_DrawRectEdge()
46 */
47 static const signed char LTInnerNormal[] = {
48 -1, -1, -1, -1,
49 -1, COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1,
50 -1, COLOR_3DDKSHADOW, COLOR_3DDKSHADOW, -1,
51 -1, -1, -1, -1
52 };
53
54 static const signed char LTOuterNormal[] = {
55 -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
56 COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
57 COLOR_3DDKSHADOW, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1,
58 -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1
59 };
60
61 static const signed char RBInnerNormal[] = {
62 -1, -1, -1, -1,
63 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1,
64 -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1,
65 -1, -1, -1, -1
66 };
67
68 static const signed char RBOuterNormal[] = {
69 -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
70 COLOR_BTNSHADOW, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
71 COLOR_3DLIGHT, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1,
72 -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1
73 };
74
75 static const signed char LTInnerSoft[] = {
76 -1, -1, -1, -1,
77 -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1,
78 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1,
79 -1, -1, -1, -1
80 };
81
82 static const signed char LTOuterSoft[] = {
83 -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
84 COLOR_3DLIGHT, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
85 COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
86 -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1
87 };
88
89 #define RBInnerSoft RBInnerNormal /* These are the same */
90 #define RBOuterSoft RBOuterNormal
91
92 static const signed char LTRBOuterMono[] = {
93 -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
94 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
95 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
96 COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
97 };
98
99 static const signed char LTRBInnerMono[] = {
100 -1, -1, -1, -1,
101 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
102 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
103 -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
104 };
105
106 static const signed char LTRBOuterFlat[] = {
107 -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
108 COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
109 COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
110 COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
111 };
112
113 static const signed char LTRBInnerFlat[] = {
114 -1, -1, -1, -1,
115 -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE,
116 -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE,
117 -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE,
118 };
119 /* FUNCTIONS *****************************************************************/
120
121
122 HBRUSH WINAPI GetSysColorBrush(int nIndex);
123
124 /* Ported from WINE20020904 */
125 /* Same as DrawEdge invoked with BF_DIAGONAL */
126 static BOOL IntDrawDiagEdge(HDC hdc, LPRECT rc, UINT uType, UINT uFlags)
127 {
128 POINT Points[4];
129 signed char InnerI, OuterI;
130 HPEN InnerPen, OuterPen;
131 POINT SavePoint;
132 HPEN SavePen;
133 int spx, spy;
134 int epx, epy;
135 int Width = rc->right - rc->left;
136 int Height= rc->bottom - rc->top;
137 int SmallDiam = Width > Height ? Height : Width;
138 BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER
139 || (uType & BDR_OUTER) == BDR_OUTER)
140 && !(uFlags & (BF_FLAT|BF_MONO)) );
141 int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
142 + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
143
144 /* Init some vars */
145 OuterPen = InnerPen = (HPEN)GetStockObject(NULL_PEN);
146 SavePen = (HPEN)SelectObject(hdc, InnerPen);
147 spx = spy = epx = epy = 0; /* Satisfy the compiler... */
148
149 /* Determine the colors of the edges */
150 if(uFlags & BF_MONO)
151 {
152 InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
153 OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
154 }
155 else if(uFlags & BF_FLAT)
156 {
157 InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
158 OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
159 }
160 else if(uFlags & BF_SOFT)
161 {
162 if(uFlags & BF_BOTTOM)
163 {
164 InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
165 OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
166 }
167 else
168 {
169 InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
170 OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
171 }
172 }
173 else
174 {
175 if(uFlags & BF_BOTTOM)
176 {
177 InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
178 OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
179 }
180 else
181 {
182 InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
183 OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
184 }
185 }
186
187 if(InnerI != -1)
188 InnerPen = GetStockObject(DC_PEN);
189 if(OuterI != -1)
190 OuterPen = GetStockObject(DC_PEN);
191
192 MoveToEx(hdc, 0, 0, &SavePoint);
193
194 /* Don't ask me why, but this is what is visible... */
195 /* This must be possible to do much simpler, but I fail to */
196 /* see the logic in the MS implementation (sigh...). */
197 /* So, this might look a bit brute force here (and it is), but */
198 /* it gets the job done;) */
199
200 switch(uFlags & BF_RECT)
201 {
202 case 0:
203 case BF_LEFT:
204 case BF_BOTTOM:
205 case BF_BOTTOMLEFT:
206 /* Left bottom endpoint */
207 epx = rc->left-1;
208 spx = epx + SmallDiam;
209 epy = rc->bottom;
210 spy = epy - SmallDiam;
211 break;
212
213 case BF_TOPLEFT:
214 case BF_BOTTOMRIGHT:
215 /* Left top endpoint */
216 epx = rc->left-1;
217 spx = epx + SmallDiam;
218 epy = rc->top-1;
219 spy = epy + SmallDiam;
220 break;
221
222 case BF_TOP:
223 case BF_RIGHT:
224 case BF_TOPRIGHT:
225 case BF_RIGHT|BF_LEFT:
226 case BF_RIGHT|BF_LEFT|BF_TOP:
227 case BF_BOTTOM|BF_TOP:
228 case BF_BOTTOM|BF_TOP|BF_LEFT:
229 case BF_BOTTOMRIGHT|BF_LEFT:
230 case BF_BOTTOMRIGHT|BF_TOP:
231 case BF_RECT:
232 /* Right top endpoint */
233 spx = rc->left;
234 epx = spx + SmallDiam;
235 spy = rc->bottom-1;
236 epy = spy - SmallDiam;
237 break;
238 }
239
240 MoveToEx(hdc, spx, spy, NULL);
241 SelectObject(hdc, OuterPen);
242 SetDCPenColor(hdc, GetSysColor(OuterI));
243 LineTo(hdc, epx, epy);
244
245 SelectObject(hdc, InnerPen);
246 SetDCPenColor(hdc, GetSysColor(InnerI));
247
248 switch(uFlags & (BF_RECT|BF_DIAGONAL))
249 {
250 case BF_DIAGONAL_ENDBOTTOMLEFT:
251 case (BF_DIAGONAL|BF_BOTTOM):
252 case BF_DIAGONAL:
253 case (BF_DIAGONAL|BF_LEFT):
254 MoveToEx(hdc, spx-1, spy, NULL);
255 LineTo(hdc, epx, epy-1);
256 Points[0].x = spx-add;
257 Points[0].y = spy;
258 Points[1].x = rc->left;
259 Points[1].y = rc->top;
260 Points[2].x = epx+1;
261 Points[2].y = epy-1-add;
262 Points[3] = Points[2];
263 break;
264
265 case BF_DIAGONAL_ENDBOTTOMRIGHT:
266 MoveToEx(hdc, spx-1, spy, NULL);
267 LineTo(hdc, epx, epy+1);
268 Points[0].x = spx-add;
269 Points[0].y = spy;
270 Points[1].x = rc->left;
271 Points[1].y = rc->bottom-1;
272 Points[2].x = epx+1;
273 Points[2].y = epy+1+add;
274 Points[3] = Points[2];
275 break;
276
277 case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP):
278 case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT):
279 case BF_DIAGONAL_ENDTOPRIGHT:
280 case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT):
281 MoveToEx(hdc, spx+1, spy, NULL);
282 LineTo(hdc, epx, epy+1);
283 Points[0].x = epx-1;
284 Points[0].y = epy+1+add;
285 Points[1].x = rc->right-1;
286 Points[1].y = rc->top+add;
287 Points[2].x = rc->right-1;
288 Points[2].y = rc->bottom-1;
289 Points[3].x = spx+add;
290 Points[3].y = spy;
291 break;
292
293 case BF_DIAGONAL_ENDTOPLEFT:
294 MoveToEx(hdc, spx, spy-1, NULL);
295 LineTo(hdc, epx+1, epy);
296 Points[0].x = epx+1+add;
297 Points[0].y = epy+1;
298 Points[1].x = rc->right-1;
299 Points[1].y = rc->top;
300 Points[2].x = rc->right-1;
301 Points[2].y = rc->bottom-1-add;
302 Points[3].x = spx;
303 Points[3].y = spy-add;
304 break;
305
306 case (BF_DIAGONAL|BF_TOP):
307 case (BF_DIAGONAL|BF_BOTTOM|BF_TOP):
308 case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT):
309 MoveToEx(hdc, spx+1, spy-1, NULL);
310 LineTo(hdc, epx, epy);
311 Points[0].x = epx-1;
312 Points[0].y = epy+1;
313 Points[1].x = rc->right-1;
314 Points[1].y = rc->top;
315 Points[2].x = rc->right-1;
316 Points[2].y = rc->bottom-1-add;
317 Points[3].x = spx+add;
318 Points[3].y = spy-add;
319 break;
320
321 case (BF_DIAGONAL|BF_RIGHT):
322 case (BF_DIAGONAL|BF_RIGHT|BF_LEFT):
323 case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM):
324 MoveToEx(hdc, spx, spy, NULL);
325 LineTo(hdc, epx-1, epy+1);
326 Points[0].x = spx;
327 Points[0].y = spy;
328 Points[1].x = rc->left;
329 Points[1].y = rc->top+add;
330 Points[2].x = epx-1-add;
331 Points[2].y = epy+1+add;
332 Points[3] = Points[2];
333 break;
334 }
335
336 /* Fill the interior if asked */
337 if((uFlags & BF_MIDDLE) && retval)
338 {
339 HBRUSH hbsave;
340 HPEN hpsave;
341 hbsave = (HBRUSH)SelectObject(hdc, GetStockObject(DC_BRUSH));
342 hpsave = (HPEN)SelectObject(hdc, GetStockObject(DC_PEN));
343 SetDCBrushColor(hdc, GetSysColor(uFlags & BF_MONO ? COLOR_WINDOW : COLOR_BTNFACE));
344 SetDCPenColor(hdc, GetSysColor(uFlags & BF_MONO ? COLOR_WINDOW : COLOR_BTNFACE));
345 Polygon(hdc, Points, 4);
346 SelectObject(hdc, hbsave);
347 SelectObject(hdc, hpsave);
348 }
349
350 /* Adjust rectangle if asked */
351 if(uFlags & BF_ADJUST)
352 {
353 if(uFlags & BF_LEFT)
354 rc->left += add;
355 if(uFlags & BF_RIGHT)
356 rc->right -= add;
357 if(uFlags & BF_TOP)
358 rc->top += add;
359 if(uFlags & BF_BOTTOM)
360 rc->bottom -= add;
361 }
362
363 /* Cleanup */
364 SelectObject(hdc, SavePen);
365 MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
366
367 return retval;
368 }
369
370 /* Ported from WINE20020904 */
371 /* Same as DrawEdge invoked without BF_DIAGONAL
372 *
373 * 23-Nov-1997: Changed by Bertho Stultiens
374 *
375 * Well, I started testing this and found out that there are a few things
376 * that weren't quite as win95. The following rewrite should reproduce
377 * win95 results completely.
378 * The colorselection is table-driven to avoid awfull if-statements.
379 * The table below show the color settings.
380 *
381 * Pen selection table for uFlags = 0
382 *
383 * uType | LTI | LTO | RBI | RBO
384 * ------+-------+-------+-------+-------
385 * 0000 | x | x | x | x
386 * 0001 | x | 22 | x | 21
387 * 0010 | x | 16 | x | 20
388 * 0011 | x | x | x | x
389 * ------+-------+-------+-------+-------
390 * 0100 | x | 20 | x | 16
391 * 0101 | 20 | 22 | 16 | 21
392 * 0110 | 20 | 16 | 16 | 20
393 * 0111 | x | x | x | x
394 * ------+-------+-------+-------+-------
395 * 1000 | x | 21 | x | 22
396 * 1001 | 21 | 22 | 22 | 21
397 * 1010 | 21 | 16 | 22 | 20
398 * 1011 | x | x | x | x
399 * ------+-------+-------+-------+-------
400 * 1100 | x | x | x | x
401 * 1101 | x | x (22)| x | x (21)
402 * 1110 | x | x (16)| x | x (20)
403 * 1111 | x | x | x | x
404 *
405 * Pen selection table for uFlags = BF_SOFT
406 *
407 * uType | LTI | LTO | RBI | RBO
408 * ------+-------+-------+-------+-------
409 * 0000 | x | x | x | x
410 * 0001 | x | 20 | x | 21
411 * 0010 | x | 21 | x | 20
412 * 0011 | x | x | x | x
413 * ------+-------+-------+-------+-------
414 * 0100 | x | 22 | x | 16
415 * 0101 | 22 | 20 | 16 | 21
416 * 0110 | 22 | 21 | 16 | 20
417 * 0111 | x | x | x | x
418 * ------+-------+-------+-------+-------
419 * 1000 | x | 16 | x | 22
420 * 1001 | 16 | 20 | 22 | 21
421 * 1010 | 16 | 21 | 22 | 20
422 * 1011 | x | x | x | x
423 * ------+-------+-------+-------+-------
424 * 1100 | x | x | x | x
425 * 1101 | x | x (20)| x | x (21)
426 * 1110 | x | x (21)| x | x (20)
427 * 1111 | x | x | x | x
428 *
429 * x = don't care; (n) = is what win95 actually uses
430 * LTI = left Top Inner line
431 * LTO = left Top Outer line
432 * RBI = Right Bottom Inner line
433 * RBO = Right Bottom Outer line
434 * 15 = COLOR_BTNFACE
435 * 16 = COLOR_BTNSHADOW
436 * 20 = COLOR_BTNHIGHLIGHT
437 * 21 = COLOR_3DDKSHADOW
438 * 22 = COLOR_3DLIGHT
439 */
440 static BOOL IntDrawRectEdge(HDC hdc, LPRECT rc, UINT uType, UINT uFlags)
441 {
442 signed char LTInnerI, LTOuterI;
443 signed char RBInnerI, RBOuterI;
444 HPEN LTInnerPen, LTOuterPen;
445 HPEN RBInnerPen, RBOuterPen;
446 RECT InnerRect = *rc;
447 POINT SavePoint;
448 HPEN SavePen;
449 int LBpenplus = 0;
450 int LTpenplus = 0;
451 int RTpenplus = 0;
452 int RBpenplus = 0;
453 BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER
454 || (uType & BDR_OUTER) == BDR_OUTER)
455 && !(uFlags & (BF_FLAT|BF_MONO)) );
456 /* Init some vars */
457 LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN)GetStockObject(NULL_PEN);
458 SavePen = (HPEN)SelectObject(hdc, LTInnerPen);
459
460 /* Determine the colors of the edges */
461 if(uFlags & BF_MONO)
462 {
463 LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
464 LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
465 }
466 else if(uFlags & BF_FLAT)
467 {
468 LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
469 LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
470
471 /* Bertho Stultiens states above that this function exactly matches win95
472 * In win98 BF_FLAT rectangles have an inner border same color as the
473 * middle (COLOR_BTNFACE). I believe it's the same for win95 but since
474 * I don't know I go with Bertho and just sets it for win98 until proven
475 * otherwise.
476 * Dennis Björklund, 10 June, 99
477 */
478 if( LTInnerI != -1 )
479 LTInnerI = RBInnerI = COLOR_BTNFACE;
480 }
481 else if(uFlags & BF_SOFT)
482 {
483 LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
484 LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
485 RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
486 RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
487 }
488 else
489 {
490 LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
491 LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
492 RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
493 RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
494 }
495
496 if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT)
497 LBpenplus = 1;
498 if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT)
499 RTpenplus = 1;
500 if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT)
501 RBpenplus = 1;
502 if((uFlags & BF_TOPLEFT) == BF_TOPLEFT)
503 LTpenplus = 1;
504
505 if(LTInnerI != -1)
506 LTInnerPen = GetStockObject(DC_PEN);
507 if(LTOuterI != -1)
508 LTOuterPen = GetStockObject(DC_PEN);
509 if(RBInnerI != -1)
510 RBInnerPen = GetStockObject(DC_PEN);
511 if(RBOuterI != -1)
512 RBOuterPen = GetStockObject(DC_PEN);
513 if((uFlags & BF_MIDDLE) && retval)
514 {
515 FillRect(hdc, &InnerRect, GetSysColorBrush(uFlags & BF_MONO ?
516 COLOR_WINDOW : COLOR_BTNFACE));
517 }
518 MoveToEx(hdc, 0, 0, &SavePoint);
519
520 /* Draw the outer edge */
521 SelectObject(hdc, LTOuterPen);
522 SetDCPenColor(hdc, GetSysColor(LTOuterI));
523 if(uFlags & BF_TOP)
524 {
525 MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
526 LineTo(hdc, InnerRect.right, InnerRect.top);
527 }
528 if(uFlags & BF_LEFT)
529 {
530 MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
531 LineTo(hdc, InnerRect.left, InnerRect.bottom);
532 }
533 SelectObject(hdc, RBOuterPen);
534 SetDCPenColor(hdc, GetSysColor(RBOuterI));
535 if(uFlags & BF_BOTTOM)
536 {
537 MoveToEx(hdc, InnerRect.left, InnerRect.bottom-1, NULL);
538 LineTo(hdc, InnerRect.right, InnerRect.bottom-1);
539 }
540 if(uFlags & BF_RIGHT)
541 {
542 MoveToEx(hdc, InnerRect.right-1, InnerRect.top, NULL);
543 LineTo(hdc, InnerRect.right-1, InnerRect.bottom);
544 }
545
546 /* Draw the inner edge */
547 SelectObject(hdc, LTInnerPen);
548 SetDCPenColor(hdc, GetSysColor(LTInnerI));
549 if(uFlags & BF_TOP)
550 {
551 MoveToEx(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL);
552 LineTo(hdc, InnerRect.right-RTpenplus, InnerRect.top+1);
553 }
554 if(uFlags & BF_LEFT)
555 {
556 MoveToEx(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL);
557 LineTo(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus);
558 }
559 SelectObject(hdc, RBInnerPen);
560 SetDCPenColor(hdc, GetSysColor(RBInnerI));
561 if(uFlags & BF_BOTTOM)
562 {
563 MoveToEx(hdc, InnerRect.left+LBpenplus, InnerRect.bottom-2, NULL);
564 LineTo(hdc, InnerRect.right-RBpenplus, InnerRect.bottom-2);
565 }
566 if(uFlags & BF_RIGHT)
567 {
568 MoveToEx(hdc, InnerRect.right-2, InnerRect.top+RTpenplus, NULL);
569 LineTo(hdc, InnerRect.right-2, InnerRect.bottom-RBpenplus);
570 }
571
572 if( ((uFlags & BF_MIDDLE) && retval) || (uFlags & BF_ADJUST) )
573 {
574 int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
575 + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
576
577 if(uFlags & BF_LEFT)
578 InnerRect.left += add;
579 if(uFlags & BF_RIGHT)
580 InnerRect.right -= add;
581 if(uFlags & BF_TOP)
582 InnerRect.top += add;
583 if(uFlags & BF_BOTTOM)
584 InnerRect.bottom -= add;
585
586 if(uFlags & BF_ADJUST)
587 *rc = InnerRect;
588 }
589
590 /* Cleanup */
591 SelectObject(hdc, SavePen);
592 MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
593 return retval;
594 }
595
596 /* Ported from WINE20020904 */
597 /* Utility to create a square rectangle and returning the width */
598 static int UITOOLS_MakeSquareRect(LPRECT src, LPRECT dst)
599 {
600 int Width = src->right - src->left;
601 int Height = src->bottom - src->top;
602 int SmallDiam = Width > Height ? Height : Width;
603
604 *dst = *src;
605
606 /* Make it a square box */
607 if(Width < Height) /* SmallDiam == Width */
608 {
609 dst->top += (Height-Width)/2;
610 dst->bottom = dst->top + SmallDiam;
611 }
612 else if(Width > Height) /* SmallDiam == Height */
613 {
614 dst->left += (Width-Height)/2;
615 dst->right = dst->left + SmallDiam;
616 }
617
618 return SmallDiam;
619 }
620
621 /* Ported from WINE20020904 */
622 static void UITOOLS_DrawCheckedRect( HDC dc, LPRECT rect )
623 {
624 if(GetSysColor(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255))
625 {
626 // HBITMAP hbm = CreateBitmap(8, 8, 1, 1, wPattern_AA55); gpsi->hbrGray
627 HBRUSH hbsave;
628 // HBRUSH hb = CreatePatternBrush(hbm);
629 COLORREF bg;
630
631 FillRect(dc, rect, GetSysColorBrush(COLOR_BTNFACE));
632 bg = SetBkColor(dc, RGB(255, 255, 255));
633 hbsave = (HBRUSH)SelectObject(dc, gpsi->hbrGray);
634 PatBlt(dc, rect->left, rect->top, rect->right-rect->left, rect->bottom-rect->top, 0x00FA0089);
635 SelectObject(dc, hbsave);
636 SetBkColor(dc, bg);
637 // DeleteObject(hb);
638 // DeleteObject(hbm);
639 }
640 else
641 {
642 FillRect(dc, rect, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
643 }
644 }
645
646 /* Ported from WINE20020904 */
647 /* Draw a push button coming from DrawFrameControl()
648 *
649 * Does a pretty good job in emulating MS behavior. Some quirks are
650 * however there because MS uses a TrueType font (Marlett) to draw
651 * the buttons.
652 *
653 * FIXME: This looks a little bit strange, needs to be rewritten completely
654 * (several quirks with adjust, DFCS_CHECKED aso)
655 */
656 static BOOL UITOOLS95_DFC_ButtonPush(HDC dc, LPRECT r, UINT uFlags)
657 {
658 UINT edge;
659 RECT myr = *r;
660
661 if(uFlags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT))
662 edge = EDGE_SUNKEN;
663 else
664 edge = EDGE_RAISED;
665
666 if(uFlags & DFCS_CHECKED)
667 {
668 if(uFlags & DFCS_MONO)
669 IntDrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
670 else
671 IntDrawRectEdge(dc, &myr, edge, (uFlags&DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST);
672
673 UITOOLS_DrawCheckedRect( dc, &myr );
674 }
675 else
676 {
677 if(uFlags & DFCS_MONO)
678 {
679 IntDrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
680 FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE));
681 }
682 else
683 {
684 IntDrawRectEdge(dc, r, edge, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT | BF_SOFT);
685 }
686 }
687
688 /* Adjust rectangle if asked */
689 if(uFlags & DFCS_ADJUSTRECT)
690 {
691 r->left += 2;
692 r->right -= 2;
693 r->top += 2;
694 r->bottom -= 2;
695 }
696
697 return TRUE;
698 }
699
700 static BOOL UITOOLS95_DFC_ButtonCheckRadio(HDC dc, LPRECT r, UINT uFlags, BOOL Radio)
701 {
702 LOGFONTW lf;
703 HFONT hFont, hOldFont;
704 int i;
705 TCHAR OutRight, OutLeft, InRight, InLeft, Center;
706
707 if (Radio)
708 {
709 OutRight = 'j'; // Outer right
710 OutLeft = 'k'; // Outer left
711 InRight = 'l'; // inner left
712 InLeft = 'm'; // inner right
713 Center = 'n'; // center
714 } else
715 {
716 OutRight = 'c'; // Outer right
717 OutLeft = 'd'; // Outer left
718 InRight = 'e'; // inner left
719 InLeft = 'f'; // inner right
720 Center = 'g'; // center
721 }
722
723 ZeroMemory(&lf, sizeof(LOGFONTW));
724 lf.lfHeight = r->top - r->bottom;
725 lf.lfWidth = 0;
726 lf.lfWeight = FW_NORMAL;
727 lf.lfCharSet = DEFAULT_CHARSET;
728 lstrcpy(lf.lfFaceName, TEXT("Marlett"));
729 hFont = CreateFontIndirect(&lf);
730 hOldFont = SelectObject(dc, hFont);
731
732 if(Radio && ((uFlags & 0xff) == DFCS_BUTTONRADIOMASK))
733 {
734 SetBkMode(dc, OPAQUE);
735 SetTextColor(dc, GetSysColor(COLOR_WINDOWFRAME));
736 TextOut(dc, r->left, r->top, &Center, 1);
737 SetBkMode(dc, TRANSPARENT);
738 SetTextColor(dc, GetSysColor(COLOR_WINDOWFRAME));
739 TextOut(dc, r->left, r->top, &OutRight, 1);
740 SetTextColor(dc, GetSysColor(COLOR_WINDOWFRAME));
741 TextOut(dc, r->left, r->top, &OutLeft, 1);
742 }
743 else
744 {
745 SetBkMode(dc, TRANSPARENT);
746
747 /* Center section, white for active, grey for inactive */
748 i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE;
749 SetTextColor(dc, GetSysColor(i));
750 TextOut(dc, r->left, r->top, &Center, 1);
751
752 if(uFlags & (DFCS_FLAT | DFCS_MONO))
753 {
754 SetTextColor(dc, GetSysColor(COLOR_WINDOWFRAME));
755 TextOut(dc, r->left, r->top, &OutRight, 1);
756 TextOut(dc, r->left, r->top, &OutLeft, 1);
757 TextOut(dc, r->left, r->top, &InRight, 1);
758 TextOut(dc, r->left, r->top, &InLeft, 1);
759 }
760 else
761 {
762 SetTextColor(dc, GetSysColor(COLOR_BTNSHADOW));
763 TextOut(dc, r->left, r->top, &OutRight, 1);
764 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT));
765 TextOut(dc, r->left, r->top, &OutLeft, 1);
766 SetTextColor(dc, GetSysColor(COLOR_3DDKSHADOW));
767 TextOut(dc, r->left, r->top, &InRight, 1);
768 SetTextColor(dc, GetSysColor(COLOR_3DLIGHT));
769 TextOut(dc, r->left, r->top, &InLeft, 1);
770 }
771 }
772
773 if(uFlags & DFCS_CHECKED)
774 {
775 TCHAR Check = (Radio) ? 'i' : 'b';
776
777 SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT));
778 TextOut(dc, r->left, r->top, &Check, 1);
779 }
780
781 SetTextColor(dc, GetSysColor(COLOR_WINDOWTEXT));
782 SelectObject(dc, hOldFont);
783 DeleteObject(hFont);
784
785 return TRUE;
786 }
787
788 /* Ported from WINE20020904 */
789 static BOOL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState)
790 {
791 switch(uState & 0xff)
792 {
793 case DFCS_BUTTONPUSH:
794 return UITOOLS95_DFC_ButtonPush(hdc, rc, uState);
795
796 case DFCS_BUTTONCHECK:
797 case DFCS_BUTTON3STATE:
798 return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, FALSE);
799
800 case DFCS_BUTTONRADIOIMAGE:
801 case DFCS_BUTTONRADIOMASK:
802 case DFCS_BUTTONRADIO:
803 return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, TRUE);
804
805 /*
806 default:
807 DbgPrint("Invalid button state=0x%04x\n", uState);
808 */
809 }
810
811 return FALSE;
812 }
813
814 static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags)
815 {
816 LOGFONTW lf;
817 HFONT hFont, hOldFont;
818 COLORREF clrsave;
819 RECT myr;
820 INT bkmode;
821 TCHAR Symbol;
822 switch(uFlags & 0xff)
823 {
824 case DFCS_CAPTIONCLOSE:
825 Symbol = 'r';
826 break;
827 case DFCS_CAPTIONHELP:
828 Symbol = 's';
829 break;
830 case DFCS_CAPTIONMIN:
831 Symbol = '0';
832 break;
833 case DFCS_CAPTIONMAX:
834 Symbol = '1';
835 break;
836 case DFCS_CAPTIONRESTORE:
837 Symbol = '2';
838 break;
839 default:
840 return FALSE;
841 }
842 IntDrawRectEdge(dc,r,(uFlags&DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT | BF_MIDDLE | BF_SOFT);
843 ZeroMemory(&lf, sizeof(LOGFONTW));
844 UITOOLS_MakeSquareRect(r, &myr);
845 myr.left += 1;
846 myr.top += 1;
847 myr.right -= 1;
848 myr.bottom -= 1;
849 if(uFlags & DFCS_PUSHED)
850 OffsetRect(&myr,1,1);
851 lf.lfHeight = myr.bottom - myr.top;
852 lf.lfWidth = 0;
853 lf.lfWeight = FW_NORMAL;
854 lf.lfCharSet = DEFAULT_CHARSET;
855 lstrcpy(lf.lfFaceName, TEXT("Marlett"));
856 hFont = CreateFontIndirect(&lf);
857 /* save font and text color */
858 hOldFont = SelectObject(dc, hFont);
859 clrsave = GetTextColor(dc);
860 bkmode = GetBkMode(dc);
861 /* set color and drawing mode */
862 SetBkMode(dc, TRANSPARENT);
863 if(uFlags & DFCS_INACTIVE)
864 {
865 /* draw shadow */
866 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT));
867 TextOut(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
868 }
869 SetTextColor(dc, GetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
870 /* draw selected symbol */
871 TextOut(dc, myr.left, myr.top, &Symbol, 1);
872 /* restore previous settings */
873 SetTextColor(dc, clrsave);
874 SelectObject(dc, hOldFont);
875 SetBkMode(dc, bkmode);
876 DeleteObject(hFont);
877 return TRUE;
878 }
879
880 static BOOL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags)
881 {
882 LOGFONTW lf;
883 HFONT hFont, hOldFont;
884 COLORREF clrsave;
885 RECT myr;
886 INT bkmode;
887 TCHAR Symbol;
888 switch(uFlags & 0xff)
889 {
890 case DFCS_SCROLLCOMBOBOX:
891 case DFCS_SCROLLDOWN:
892 Symbol = '6';
893 break;
894
895 case DFCS_SCROLLUP:
896 Symbol = '5';
897 break;
898
899 case DFCS_SCROLLLEFT:
900 Symbol = '3';
901 break;
902
903 case DFCS_SCROLLRIGHT:
904 Symbol = '4';
905 break;
906
907 case DFCS_SCROLLSIZEGRIP:
908 case DFCS_SCROLLSIZEGRIPRIGHT:
909 ZeroMemory(&lf, sizeof(LOGFONTW));
910 UITOOLS_MakeSquareRect(r, &myr);
911 lf.lfHeight = myr.bottom - myr.top;
912 lf.lfWidth = 0;
913 lf.lfWeight = FW_NORMAL;
914 lf.lfCharSet = DEFAULT_CHARSET;
915 lstrcpy(lf.lfFaceName, TEXT("Marlett"));
916 hFont = CreateFontIndirect(&lf);
917 /* save font and text color */
918 hOldFont = SelectObject(dc, hFont);
919 clrsave = GetTextColor(dc);
920 bkmode = GetBkMode(dc);
921 /* set color and drawing mode */
922 SetBkMode(dc, TRANSPARENT);
923 if (!(uFlags & (DFCS_MONO | DFCS_FLAT)))
924 {
925 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT));
926 /* draw selected symbol */
927 Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'o' : 'x';
928 TextOut(dc, myr.left, myr.top, &Symbol, 1);
929 SetTextColor(dc, GetSysColor(COLOR_BTNSHADOW));
930 } else
931 SetTextColor(dc, GetSysColor(COLOR_WINDOWFRAME));
932 /* draw selected symbol */
933 Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'p' : 'y';
934 TextOut(dc, myr.left, myr.top, &Symbol, 1);
935 /* restore previous settings */
936 SetTextColor(dc, clrsave);
937 SelectObject(dc, hOldFont);
938 SetBkMode(dc, bkmode);
939 DeleteObject(hFont);
940 return TRUE;
941 default:
942 return FALSE;
943 }
944 IntDrawRectEdge(dc, r, (uFlags & DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT);
945 ZeroMemory(&lf, sizeof(LOGFONTW));
946 UITOOLS_MakeSquareRect(r, &myr);
947 myr.left += 1;
948 myr.top += 1;
949 myr.right -= 1;
950 myr.bottom -= 1;
951 if(uFlags & DFCS_PUSHED)
952 OffsetRect(&myr,1,1);
953 lf.lfHeight = myr.bottom - myr.top;
954 lf.lfWidth = 0;
955 lf.lfWeight = FW_NORMAL;
956 lf.lfCharSet = DEFAULT_CHARSET;
957 lstrcpy(lf.lfFaceName, TEXT("Marlett"));
958 hFont = CreateFontIndirect(&lf);
959 /* save font and text color */
960 hOldFont = SelectObject(dc, hFont);
961 clrsave = GetTextColor(dc);
962 bkmode = GetBkMode(dc);
963 /* set color and drawing mode */
964 SetBkMode(dc, TRANSPARENT);
965 if(uFlags & DFCS_INACTIVE)
966 {
967 /* draw shadow */
968 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT));
969 TextOut(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
970 }
971 SetTextColor(dc, GetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
972 /* draw selected symbol */
973 TextOut(dc, myr.left, myr.top, &Symbol, 1);
974 /* restore previous settings */
975 SetTextColor(dc, clrsave);
976 SelectObject(dc, hOldFont);
977 SetBkMode(dc, bkmode);
978 DeleteObject(hFont);
979 return TRUE;
980 }
981
982 static BOOL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
983 {
984 LOGFONTW lf;
985 HFONT hFont, hOldFont;
986 TCHAR Symbol;
987 switch(uFlags & 0xff)
988 {
989 case DFCS_MENUARROW:
990 Symbol = '8';
991 break;
992
993 case DFCS_MENUARROWRIGHT:
994 Symbol = 'w'; // FIXME: needs to confirm
995 break;
996
997 case DFCS_MENUBULLET:
998 Symbol = 'h';
999 break;
1000
1001 case DFCS_MENUCHECK:
1002 Symbol = 'a';
1003 break;
1004
1005 default:
1006 /*
1007 DbgPrint("Invalid menu; flags=0x%04x\n", uFlags);
1008 */
1009 return FALSE;
1010 }
1011 /* acquire ressources only if valid menu */
1012 ZeroMemory(&lf, sizeof(LOGFONTW));
1013 lf.lfHeight = r->bottom - r->top;
1014 lf.lfWidth = 0;
1015 lf.lfWeight = FW_NORMAL;
1016 lf.lfCharSet = DEFAULT_CHARSET;
1017 lstrcpy(lf.lfFaceName, TEXT("Marlett"));
1018 hFont = CreateFontIndirect(&lf);
1019 /* save font */
1020 hOldFont = SelectObject(dc, hFont);
1021 // FIXME selecting color doesn't work
1022 #if 0
1023 if(uFlags & DFCS_INACTIVE)
1024 {
1025 /* draw shadow */
1026 SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT));
1027 TextOut(dc, r->left + 1, r->top + 1, &Symbol, 1);
1028 }
1029 SetTextColor(dc, GetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
1030 #endif
1031 /* draw selected symbol */
1032 TextOut(dc, r->left, r->top, &Symbol, 1);
1033 /* restore previous settings */
1034 SelectObject(dc, hOldFont);
1035 DeleteObject(hFont);
1036 return TRUE;
1037 }
1038
1039 BOOL
1040 WINAPI
1041 IntGrayString(
1042 HDC hDC,
1043 HBRUSH hBrush,
1044 GRAYSTRINGPROC lpOutputFunc,
1045 LPARAM lpData,
1046 int nCount,
1047 int X,
1048 int Y,
1049 int nWidth,
1050 int nHeight,
1051 BOOL unicode)
1052 {
1053 // AG: Mostly implemented, but probably won't work properly or return
1054 // correct error codes. I doubt it grays strings either... Untested!
1055
1056 BOOL success = FALSE;
1057 HBRUSH hbsave;
1058 HDC MemDC = NULL;
1059 HBITMAP MemBMP = NULL, OldBMP = NULL;
1060 HBRUSH OldBrush = NULL;
1061 HFONT OldFont = NULL;
1062 RECT r;
1063 COLORREF ForeColor, BackColor;
1064
1065 ForeColor = SetTextColor(hDC, RGB(0, 0, 0));
1066 BackColor = SetBkColor(hDC, RGB(255, 255, 255));
1067
1068 if (! hBrush)
1069 {
1070 // The documentation is a little vague on what exactly should happen
1071 // here. Something about using the same brush for window text???
1072 hBrush = (HBRUSH) GetCurrentObject(hDC, OBJ_BRUSH);
1073 }
1074
1075 if ((nCount == -1) && (! lpOutputFunc))
1076 return FALSE;
1077
1078 if (! nCount)
1079 {
1080 // TODO: calculate the length (easy enough)
1081
1082 if (unicode)
1083 nCount = lstrlenW((WCHAR*)lpData);
1084 else
1085 nCount = lstrlenA((CHAR*)lpData);
1086 }
1087
1088 if (! nWidth || ! nHeight)
1089 {
1090 SIZE s;
1091 // TODO: calculate the rect
1092
1093 if (unicode)
1094 success = GetTextExtentPoint32W(hDC, (WCHAR*) lpData, nCount, &s);
1095 else
1096 success = GetTextExtentPoint32A(hDC, (CHAR*) lpData, nCount, &s);
1097
1098 if (! success) goto cleanup;
1099
1100 if (! nWidth) nWidth = s.cx;
1101 if (! nHeight) nHeight = s.cy;
1102 }
1103
1104 SetRect(&r, X, Y, X + nWidth, Y + nHeight);
1105
1106 MemDC = CreateCompatibleDC(hDC);
1107 if (! MemDC) goto cleanup;
1108 MemBMP = CreateBitmap(nWidth, nHeight, 1, 1, NULL);
1109 if (! MemBMP) goto cleanup;
1110 OldBMP = SelectObject(MemDC, MemBMP);
1111 if (! OldBMP) goto cleanup;
1112 OldFont = SelectObject(MemDC, GetCurrentObject(hDC, OBJ_FONT));
1113 if (! OldFont) goto cleanup;
1114 OldBrush = SelectObject(MemDC, hBrush);
1115 if (! OldBrush) goto cleanup;
1116
1117 if (! BitBlt(MemDC, 0, 0, nWidth, nHeight, hDC, X, Y, SRCCOPY)) goto cleanup;
1118
1119 SetTextColor(MemDC, RGB(255, 255, 255));
1120 SetBkColor(MemDC, RGB(0, 0, 0));
1121
1122 if (lpOutputFunc)
1123 {
1124 success = lpOutputFunc(MemDC, lpData, nCount); // Set brush etc first?
1125
1126 if ((nCount == -1) && (! success))
1127 {
1128 // Don't gray (documented behaviour)
1129 success = (BOOL) BitBlt(hDC, X, Y, nWidth, nHeight, MemDC, 0, 0, SRCCOPY);
1130 goto cleanup;
1131 }
1132 }
1133 else
1134 {
1135 if (unicode)
1136 success = TextOutW(MemDC, 0, 0, (WCHAR*) lpData, nCount);
1137 else
1138 success = TextOutA(MemDC, 0, 0, (CHAR*) lpData, nCount);
1139
1140 if (! success) goto cleanup;
1141
1142 hbsave = (HBRUSH)SelectObject(MemDC, gpsi->hbrGray);
1143 PatBlt(MemDC, 0, 0, nWidth, nHeight, 0x000A0329);
1144 SelectObject(MemDC, hbsave);
1145 }
1146
1147 if (! BitBlt(hDC, X, Y, nWidth, nHeight, MemDC, 0, 0, SRCCOPY)) goto cleanup;
1148
1149 cleanup:
1150 SetTextColor(hDC, ForeColor);
1151 SetBkColor(hDC, BackColor);
1152
1153 if (MemDC)
1154 {
1155 if (OldFont) SelectObject(MemDC, OldFont);
1156 if (OldBrush) SelectObject(MemDC, OldBrush);
1157 if (OldBMP) SelectObject(MemDC, OldBMP);
1158 if (MemBMP) DeleteObject(MemBMP);
1159 DeleteDC(MemDC);
1160 }
1161
1162 return success;
1163 }
1164
1165 /**********************************************************************
1166 * PAINTING_DrawStateJam
1167 *
1168 * Jams in the requested type in the dc
1169 */
1170 static BOOL PAINTING_DrawStateJam(HDC hdc, UINT opcode,
1171 DRAWSTATEPROC func, LPARAM lp, WPARAM wp,
1172 LPRECT rc, UINT dtflags, BOOL unicode )
1173 {
1174 HDC memdc;
1175 HBITMAP hbmsave;
1176 BOOL retval;
1177 INT cx = rc->right - rc->left;
1178 INT cy = rc->bottom - rc->top;
1179
1180 switch(opcode)
1181 {
1182 case DST_TEXT:
1183 case DST_PREFIXTEXT:
1184 if(unicode)
1185 return DrawTextW(hdc, (LPWSTR)lp, (INT)wp, rc, dtflags);
1186 else
1187 return DrawTextA(hdc, (LPSTR)lp, (INT)wp, rc, dtflags);
1188
1189 case DST_ICON:
1190 return DrawIconEx(hdc, rc->left, rc->top, (HICON)lp, cx, cy, 0, NULL, DI_NORMAL);
1191
1192 case DST_BITMAP:
1193 memdc = CreateCompatibleDC(hdc);
1194 if(!memdc)
1195 return FALSE;
1196 hbmsave = (HBITMAP)SelectObject(memdc, (HBITMAP)lp);
1197 if(!hbmsave)
1198 {
1199 DeleteDC(memdc);
1200 return FALSE;
1201 }
1202 retval = BitBlt(hdc, rc->left, rc->top, cx, cy, memdc, 0, 0, SRCCOPY);
1203 SelectObject(memdc, hbmsave);
1204 DeleteDC(memdc);
1205 return retval;
1206
1207 case DST_COMPLEX:
1208 if(func)
1209 {
1210 BOOL bRet;
1211 /* DRAWSTATEPROC assumes that it draws at the center of coordinates */
1212
1213 OffsetViewportOrgEx(hdc, rc->left, rc->top, NULL);
1214 bRet = func(hdc, lp, wp, cx, cy);
1215 /* Restore origin */
1216 OffsetViewportOrgEx(hdc, -rc->left, -rc->top, NULL);
1217 return bRet;
1218 }
1219 else
1220 {
1221 return FALSE;
1222 }
1223 }
1224 return FALSE;
1225 }
1226
1227 static BOOL
1228 IntDrawState(HDC hdc, HBRUSH hbr, DRAWSTATEPROC func, LPARAM lp, WPARAM wp,
1229 INT x, INT y, INT cx, INT cy, UINT flags, BOOL unicode)
1230 {
1231 HBITMAP hbm, hbmsave;
1232 HFONT hfsave;
1233 HBRUSH hbsave, hbrtmp = 0;
1234 HDC memdc;
1235 RECT rc;
1236 UINT dtflags = DT_NOCLIP;
1237 COLORREF fg, bg;
1238 UINT opcode = flags & 0xf;
1239 INT len = wp;
1240 BOOL retval, tmp;
1241
1242 if((opcode == DST_TEXT || opcode == DST_PREFIXTEXT) && !len) /* The string is '\0' terminated */
1243 {
1244 if(unicode)
1245 len = lstrlenW((LPWSTR)lp);
1246 else
1247 len = lstrlenA((LPSTR)lp);
1248 }
1249
1250 /* Find out what size the image has if not given by caller */
1251 if(!cx || !cy)
1252 {
1253 SIZE s;
1254 BITMAP bm;
1255
1256 switch(opcode)
1257 {
1258 case DST_TEXT:
1259 case DST_PREFIXTEXT:
1260 if(unicode)
1261 retval = GetTextExtentPoint32W(hdc, (LPWSTR)lp, len, &s);
1262 else
1263 retval = GetTextExtentPoint32A(hdc, (LPSTR)lp, len, &s);
1264 if(!retval)
1265 return FALSE;
1266 break;
1267
1268 case DST_ICON:
1269 if(!get_icon_size((HICON)lp, &s))
1270 return FALSE;
1271 break;
1272
1273 case DST_BITMAP:
1274 if(!GetObjectW((HBITMAP)lp, sizeof(bm), &bm))
1275 return FALSE;
1276 s.cx = bm.bmWidth;
1277 s.cy = bm.bmHeight;
1278 break;
1279
1280 case DST_COMPLEX: /* cx and cy must be set in this mode */
1281 return FALSE;
1282 }
1283
1284 if(!cx)
1285 cx = s.cx;
1286 if(!cy)
1287 cy = s.cy;
1288 }
1289
1290 rc.left = x;
1291 rc.top = y;
1292 rc.right = x + cx;
1293 rc.bottom = y + cy;
1294
1295 if(flags & DSS_RIGHT) /* This one is not documented in the win32.hlp file */
1296 dtflags |= DT_RIGHT;
1297 if(opcode == DST_TEXT)
1298 dtflags |= DT_NOPREFIX;
1299 else if(opcode == DST_PREFIXTEXT)
1300 {
1301 if (flags & DSS_HIDEPREFIX)
1302 dtflags |= DT_HIDEPREFIX;
1303 if (flags & DSS_PREFIXONLY)
1304 dtflags |= DT_PREFIXONLY;
1305 }
1306
1307 /* For DSS_NORMAL we just jam in the image and return */
1308 if((flags & 0x79f0) == DSS_NORMAL)
1309 {
1310 return PAINTING_DrawStateJam(hdc, opcode, func, lp, len, &rc, dtflags, unicode);
1311 }
1312
1313 /* For all other states we need to convert the image to B/W in a local bitmap */
1314 /* before it is displayed */
1315 fg = SetTextColor(hdc, RGB(0, 0, 0));
1316 bg = SetBkColor(hdc, RGB(255, 255, 255));
1317 hbm = NULL; hbmsave = NULL;
1318 memdc = NULL; hbsave = NULL;
1319 retval = FALSE; /* assume failure */
1320
1321 /* From here on we must use "goto cleanup" when something goes wrong */
1322 hbm = CreateBitmap(cx, cy, 1, 1, NULL);
1323 if(!hbm)
1324 goto cleanup;
1325 memdc = CreateCompatibleDC(hdc);
1326 if(!memdc)
1327 goto cleanup;
1328 hbmsave = (HBITMAP)SelectObject(memdc, hbm);
1329 if(!hbmsave)
1330 goto cleanup;
1331 rc.left = rc.top = 0;
1332 rc.right = cx;
1333 rc.bottom = cy;
1334 if(!FillRect(memdc, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH)))
1335 goto cleanup;
1336 SetBkColor(memdc, RGB(255, 255, 255));
1337 SetTextColor(memdc, RGB(0, 0, 0));
1338 hfsave = (HFONT)SelectObject(memdc, GetCurrentObject(hdc, OBJ_FONT));
1339
1340 /* DST_COMPLEX may draw text as well,
1341 * so we must be sure that correct font is selected
1342 */
1343 if(!hfsave && (opcode <= DST_PREFIXTEXT))
1344 goto cleanup;
1345 tmp = PAINTING_DrawStateJam(memdc, opcode, func, lp, len, &rc, dtflags, unicode);
1346 if(hfsave)
1347 SelectObject(memdc, hfsave);
1348 if(!tmp)
1349 goto cleanup;
1350
1351 /* This state cause the image to be dithered */
1352 if(flags & DSS_UNION)
1353 {
1354 hbsave = (HBRUSH)SelectObject(memdc, gpsi->hbrGray);
1355 if(!hbsave) goto cleanup;
1356 tmp = PatBlt(memdc, 0, 0, cx, cy, 0x00FA0089);
1357 SelectObject(memdc, hbsave);
1358 if(!tmp) goto cleanup;
1359 }
1360
1361 if (flags & DSS_DISABLED)
1362 hbrtmp = GetSysColorBrush(COLOR_3DHILIGHT);
1363 else if (flags & DSS_DEFAULT)
1364 hbrtmp = GetSysColorBrush(COLOR_3DSHADOW);
1365
1366 /* Draw light or dark shadow */
1367 if (flags & (DSS_DISABLED|DSS_DEFAULT))
1368 {
1369 if(!hbrtmp)
1370 goto cleanup;
1371 hbsave = (HBRUSH)SelectObject(hdc, hbrtmp);
1372 if(!hbsave)
1373 goto cleanup;
1374 if(!BitBlt(hdc, x+1, y+1, cx, cy, memdc, 0, 0, 0x00B8074A))
1375 goto cleanup;
1376 SelectObject(hdc, hbsave);
1377 }
1378
1379 if (flags & DSS_DISABLED)
1380 {
1381 hbr = hbrtmp = GetSysColorBrush(COLOR_3DSHADOW);
1382 if(!hbrtmp)
1383 goto cleanup;
1384 }
1385 else if (!hbr)
1386 {
1387 hbr = (HBRUSH)GetStockObject(BLACK_BRUSH);
1388 }
1389
1390 hbsave = (HBRUSH)SelectObject(hdc, hbr);
1391
1392 if(!BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00B8074A))
1393 goto cleanup;
1394
1395 retval = TRUE; /* We succeeded */
1396
1397 cleanup:
1398 SetTextColor(hdc, fg);
1399 SetBkColor(hdc, bg);
1400
1401 if(hbsave)
1402 SelectObject(hdc, hbsave);
1403 if(hbmsave)
1404 SelectObject(memdc, hbmsave);
1405 if(hbm)
1406 DeleteObject(hbm);
1407 if(memdc)
1408 DeleteDC(memdc);
1409
1410 return retval;
1411 }
1412
1413 /*
1414 * @implemented
1415 */
1416 BOOL WINAPI
1417 RealDrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState)
1418 {
1419 if (GetMapMode(hDC) != MM_TEXT)
1420 return FALSE;
1421
1422 switch(uType)
1423 {
1424 case DFC_BUTTON:
1425 return UITOOLS95_DrawFrameButton(hDC, rc, uState);
1426 case DFC_CAPTION:
1427 return UITOOLS95_DrawFrameCaption(hDC, rc, uState);
1428 case DFC_MENU:
1429 return UITOOLS95_DrawFrameMenu(hDC, rc, uState);
1430 #if 0
1431 case DFC_POPUPMENU:
1432 UNIMPLEMENTED;
1433 break;
1434 #endif
1435 case DFC_SCROLL:
1436 return UITOOLS95_DrawFrameScroll(hDC, rc, uState);
1437 }
1438 return FALSE;
1439 }
1440
1441 BOOL WINAPI
1442 DrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState)
1443 {
1444 BOOL Hook, Ret = FALSE;
1445
1446 LoadUserApiHook();
1447
1448 Hook = BeginIfHookedUserApiHook();
1449
1450 /* Bypass SEH and go direct. */
1451 if (!Hook) return RealDrawFrameControl(hDC, rc, uType, uState);
1452
1453 _SEH2_TRY
1454 {
1455 Ret = guah.DrawFrameControl(hDC, rc, uType, uState);
1456 }
1457 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
1458 {
1459 }
1460 _SEH2_END;
1461
1462 EndUserApiHook();
1463
1464 return Ret;
1465 }
1466
1467 /*
1468 * @implemented
1469 */
1470 BOOL WINAPI
1471 DrawEdge(HDC hDC, LPRECT rc, UINT edge, UINT flags)
1472 {
1473 if (flags & BF_DIAGONAL)
1474 return IntDrawDiagEdge(hDC, rc, edge, flags);
1475 else
1476 return IntDrawRectEdge(hDC, rc, edge, flags);
1477 }
1478
1479 /*
1480 * @implemented
1481 */
1482 BOOL WINAPI
1483 GrayStringA(HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData,
1484 int nCount, int X, int Y, int nWidth, int nHeight)
1485 {
1486 return IntGrayString(hDC, hBrush, lpOutputFunc, lpData, nCount, X, Y, nWidth, nHeight, FALSE);
1487 }
1488
1489 /*
1490 * @implemented
1491 */
1492 BOOL WINAPI
1493 GrayStringW(HDC hDC, HBRUSH hBrush, GRAYSTRINGPROC lpOutputFunc, LPARAM lpData,
1494 int nCount, int X, int Y, int nWidth, int nHeight)
1495 {
1496 return IntGrayString(hDC, hBrush, lpOutputFunc, lpData, nCount, X, Y, nWidth, nHeight, TRUE);
1497 }
1498
1499 /*
1500 * @implemented
1501 */
1502 BOOL WINAPI
1503 InvertRect(HDC hDC, CONST RECT *lprc)
1504 {
1505 return PatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left,
1506 lprc->bottom - lprc->top, DSTINVERT);
1507 }
1508
1509 /*
1510 * @implemented
1511 */
1512 INT WINAPI
1513 FrameRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr)
1514 {
1515 HBRUSH oldbrush;
1516 RECT r = *lprc;
1517
1518 if ((r.right <= r.left) || (r.bottom <= r.top)) return 0;
1519 if (!(oldbrush = SelectObject(hDC, hbr))) return 0;
1520
1521 PatBlt(hDC, r.left, r.top, 1, r.bottom - r.top, PATCOPY);
1522 PatBlt(hDC, r.right - 1, r.top, 1, r.bottom - r.top, PATCOPY);
1523 PatBlt(hDC, r.left, r.top, r.right - r.left, 1, PATCOPY);
1524 PatBlt(hDC, r.left, r.bottom - 1, r.right - r.left, 1, PATCOPY);
1525
1526 SelectObject(hDC, oldbrush);
1527 return TRUE;
1528 }
1529
1530 /*
1531 * @implemented
1532 */
1533 BOOL WINAPI
1534 FlashWindow(HWND hWnd, BOOL bInvert)
1535 {
1536 FLASHWINFO FlashWndInfo;
1537
1538 FlashWndInfo.cbSize = sizeof(FLASHWINFO);
1539 FlashWndInfo.hwnd = hWnd;
1540 FlashWndInfo.dwFlags = !bInvert ? 0 : (FLASHW_TRAY | FLASHW_CAPTION);
1541 FlashWndInfo.uCount = 1;
1542 FlashWndInfo.dwTimeout = 0;
1543
1544 return NtUserFlashWindowEx(&FlashWndInfo);
1545 }
1546
1547 /*
1548 * @implemented
1549 */
1550 INT WINAPI
1551 FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr)
1552 {
1553 BOOL Ret;
1554 HBRUSH prevhbr = NULL;
1555
1556 /* Select brush if specified */
1557 if (hbr)
1558 {
1559 /* Handle system colors */
1560 if (hbr <= (HBRUSH)(COLOR_MENUBAR + 1))
1561 hbr = GetSysColorBrush(PtrToUlong(hbr) - 1);
1562
1563 prevhbr = SelectObject(hDC, hbr);
1564 if (prevhbr == NULL)
1565 return (INT)FALSE;
1566 }
1567
1568 Ret = PatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left,
1569 lprc->bottom - lprc->top, PATCOPY);
1570
1571 /* Select old brush */
1572 if (prevhbr)
1573 SelectObject(hDC, prevhbr);
1574
1575 return (INT)Ret;
1576 }
1577
1578 /*
1579 * @implemented
1580 */
1581 BOOL WINAPI
1582 DrawFocusRect(HDC hdc, CONST RECT *rect)
1583 {
1584 HGDIOBJ OldObj;
1585 UINT cx, cy;
1586
1587 NtUserSystemParametersInfo(SPI_GETFOCUSBORDERWIDTH, 0, &cx, 0);
1588 NtUserSystemParametersInfo(SPI_GETFOCUSBORDERHEIGHT, 0, &cy, 0);
1589
1590 OldObj = SelectObject(hdc, gpsi->hbrGray);
1591
1592 /* top */
1593 PatBlt(hdc, rect->left, rect->top, rect->right - rect->left, cy, PATINVERT);
1594 /* bottom */
1595 PatBlt(hdc, rect->left, rect->bottom - cy, rect->right - rect->left, cy, PATINVERT);
1596 /* left */
1597 PatBlt(hdc, rect->left, rect->top + cy, cx, rect->bottom - rect->top - (2 * cy), PATINVERT);
1598 /* right */
1599 PatBlt(hdc, rect->right - cx, rect->top + cy, cx, rect->bottom - rect->top - (2 * cy), PATINVERT);
1600
1601 SelectObject(hdc, OldObj);
1602 return TRUE;
1603 }
1604
1605 /*
1606 * @implemented
1607 */
1608 BOOL WINAPI
1609 DrawStateA(HDC hDC, HBRUSH hBrush, DRAWSTATEPROC lpOutputFunc, LPARAM lData,
1610 WPARAM wData, int x, int y, int cx, int cy, UINT fuFlags)
1611 {
1612 return IntDrawState(hDC, hBrush, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags, FALSE);
1613 }
1614
1615 /*
1616 * @implemented
1617 */
1618 BOOL WINAPI
1619 DrawStateW(HDC hDC, HBRUSH hBrush, DRAWSTATEPROC lpOutputFunc, LPARAM lData,
1620 WPARAM wData, int x, int y, int cx, int cy, UINT fuFlags)
1621 {
1622 return IntDrawState(hDC, hBrush, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags, TRUE);
1623 }