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