xref: /reactos/win32ss/user/ntuser/draw.c (revision 1734f297)
1 /*
2  * COPYRIGHT:        See COPYING in the top level directory
3  * PROJECT:          ReactOS Win32k subsystem
4  * PURPOSE:          Win32ss internal drawing support.
5  * FILE:             win32ss/user/ntuser/draw.c
6  * PROGRAMER:
7  */
8 
9 //
10 //	Original code from Wine see user32/windows/draw.c.
11 //
12 //
13 
14 #include <win32k.h>
15 DBG_DEFAULT_CHANNEL(UserDefwnd);
16 
17 /* These tables are used in:
18  * UITOOLS_DrawDiagEdge()
19  * UITOOLS_DrawRectEdge()
20  */
21 static const signed char LTInnerNormal[] = {
22             -1,           -1,                 -1,                 -1,
23             -1,           COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1,
24             -1,           COLOR_3DDKSHADOW,   COLOR_3DDKSHADOW,   -1,
25             -1,           -1,                 -1,                 -1
26 };
27 
28 static const signed char LTOuterNormal[] = {
29             -1,                 COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1,
30             COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1,
31             COLOR_3DDKSHADOW,   COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1,
32             -1,                 COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1
33 };
34 
35 static const signed char RBInnerNormal[] = {
36             -1,           -1,                -1,              -1,
37             -1,           COLOR_BTNSHADOW,   COLOR_BTNSHADOW, -1,
38             -1,           COLOR_3DLIGHT,     COLOR_3DLIGHT,   -1,
39             -1,           -1,                -1,              -1
40 };
41 
42 static const signed char RBOuterNormal[] = {
43             -1,              COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1,
44             COLOR_BTNSHADOW, COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1,
45             COLOR_3DLIGHT,   COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1,
46             -1,              COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1
47 };
48 
49 static const signed char LTInnerSoft[] = {
50             -1,                  -1,                -1,              -1,
51             -1,                  COLOR_3DLIGHT,     COLOR_3DLIGHT,   -1,
52             -1,                  COLOR_BTNSHADOW,   COLOR_BTNSHADOW, -1,
53             -1,                  -1,                -1,              -1
54 };
55 
56 static const signed char LTOuterSoft[] = {
57             -1,              COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
58             COLOR_3DLIGHT,   COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
59             COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
60             -1,              COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1
61 };
62 
63 #define RBInnerSoft RBInnerNormal   /* These are the same */
64 #define RBOuterSoft RBOuterNormal
65 
66 static const signed char LTRBOuterMono[] = {
67             -1,           COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
68             COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
69             COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
70             COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
71 };
72 
73 static const signed char LTRBInnerMono[] = {
74             -1, -1,           -1,           -1,
75             -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
76             -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
77             -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
78 };
79 
80 static const signed char LTRBOuterFlat[] = {
81             -1,                COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
82             COLOR_BTNFACE,     COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
83             COLOR_BTNFACE,     COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
84             COLOR_BTNFACE,     COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
85 };
86 
87 static const signed char LTRBInnerFlat[] = {
88             -1, -1,              -1,              -1,
89             -1, COLOR_BTNFACE,     COLOR_BTNFACE,     COLOR_BTNFACE,
90             -1, COLOR_BTNFACE,     COLOR_BTNFACE,     COLOR_BTNFACE,
91             -1, COLOR_BTNFACE,     COLOR_BTNFACE,     COLOR_BTNFACE,
92 };
93 
94 /* Ported from WINE20020904 */
95 /* Same as DrawEdge invoked with BF_DIAGONAL */
96 BOOL FASTCALL IntDrawDiagEdge(HDC hdc, LPRECT rc, UINT uType, UINT uFlags)
97 {
98     POINT Points[4];
99     signed char InnerI, OuterI;
100     HPEN InnerPen, OuterPen;
101     POINT SavePoint;
102     HPEN SavePen;
103     int spx, spy;
104     int epx, epy;
105     int Width = rc->right - rc->left;
106     int Height= rc->bottom - rc->top;
107     int SmallDiam = Width > Height ? Height : Width;
108     BOOL retval = !(   ((uType & BDR_INNER) == BDR_INNER
109                         || (uType & BDR_OUTER) == BDR_OUTER)
110                        && !(uFlags & (BF_FLAT|BF_MONO)) );
111     int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
112                   + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
113 
114     /* Init some vars */
115     OuterPen = InnerPen = (HPEN)NtGdiGetStockObject(NULL_PEN);
116     SavePen = (HPEN)NtGdiSelectPen(hdc, InnerPen);
117     spx = spy = epx = epy = 0; /* Satisfy the compiler... */
118 
119     /* Determine the colors of the edges */
120     if(uFlags & BF_MONO)
121     {
122         InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
123         OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
124     }
125     else if(uFlags & BF_FLAT)
126     {
127         InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
128         OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
129     }
130     else if(uFlags & BF_SOFT)
131     {
132         if(uFlags & BF_BOTTOM)
133         {
134             InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
135             OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
136         }
137         else
138         {
139             InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
140             OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
141         }
142     }
143     else
144     {
145         if(uFlags & BF_BOTTOM)
146         {
147             InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
148             OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
149         }
150         else
151         {
152             InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
153             OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
154         }
155     }
156 
157     if(InnerI != -1)
158         InnerPen = NtGdiGetStockObject(DC_PEN);
159     if(OuterI != -1)
160         OuterPen = NtGdiGetStockObject(DC_PEN);
161 
162     GreMoveTo(hdc, 0, 0, &SavePoint);
163 
164     /* Don't ask me why, but this is what is visible... */
165     /* This must be possible to do much simpler, but I fail to */
166     /* see the logic in the MS implementation (sigh...). */
167     /* So, this might look a bit brute force here (and it is), but */
168     /* it gets the job done;) */
169 
170     switch(uFlags & BF_RECT)
171     {
172         case 0:
173         case BF_LEFT:
174         case BF_BOTTOM:
175         case BF_BOTTOMLEFT:
176             /* Left bottom endpoint */
177             epx = rc->left-1;
178             spx = epx + SmallDiam;
179             epy = rc->bottom;
180             spy = epy - SmallDiam;
181             break;
182 
183         case BF_TOPLEFT:
184         case BF_BOTTOMRIGHT:
185             /* Left top endpoint */
186             epx = rc->left-1;
187             spx = epx + SmallDiam;
188             epy = rc->top-1;
189             spy = epy + SmallDiam;
190             break;
191 
192         case BF_TOP:
193         case BF_RIGHT:
194         case BF_TOPRIGHT:
195         case BF_RIGHT|BF_LEFT:
196         case BF_RIGHT|BF_LEFT|BF_TOP:
197         case BF_BOTTOM|BF_TOP:
198         case BF_BOTTOM|BF_TOP|BF_LEFT:
199         case BF_BOTTOMRIGHT|BF_LEFT:
200         case BF_BOTTOMRIGHT|BF_TOP:
201         case BF_RECT:
202             /* Right top endpoint */
203             spx = rc->left;
204             epx = spx + SmallDiam;
205             spy = rc->bottom-1;
206             epy = spy - SmallDiam;
207             break;
208     }
209 
210     GreMoveTo(hdc, spx, spy, NULL);
211     NtGdiSelectPen(hdc, OuterPen);
212     IntSetDCPenColor(hdc, IntGetSysColor(OuterI));
213     NtGdiLineTo(hdc, epx, epy);
214 
215     NtGdiSelectPen(hdc, InnerPen);
216     IntSetDCPenColor(hdc, IntGetSysColor(InnerI));
217 
218     switch(uFlags & (BF_RECT|BF_DIAGONAL))
219     {
220         case BF_DIAGONAL_ENDBOTTOMLEFT:
221         case (BF_DIAGONAL|BF_BOTTOM):
222                     case BF_DIAGONAL:
223                         case (BF_DIAGONAL|BF_LEFT):
224                                 GreMoveTo(hdc, spx-1, spy, NULL);
225             NtGdiLineTo(hdc, epx, epy-1);
226             Points[0].x = spx-add;
227             Points[0].y = spy;
228             Points[1].x = rc->left;
229             Points[1].y = rc->top;
230             Points[2].x = epx+1;
231             Points[2].y = epy-1-add;
232             Points[3] = Points[2];
233             break;
234 
235         case BF_DIAGONAL_ENDBOTTOMRIGHT:
236             GreMoveTo(hdc, spx-1, spy, NULL);
237             NtGdiLineTo(hdc, epx, epy+1);
238             Points[0].x = spx-add;
239             Points[0].y = spy;
240             Points[1].x = rc->left;
241             Points[1].y = rc->bottom-1;
242             Points[2].x = epx+1;
243             Points[2].y = epy+1+add;
244             Points[3] = Points[2];
245             break;
246 
247         case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP):
248                     case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT):
249                         case BF_DIAGONAL_ENDTOPRIGHT:
250                             case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT):
251                                     GreMoveTo(hdc, spx+1, spy, NULL);
252             NtGdiLineTo(hdc, epx, epy+1);
253             Points[0].x = epx-1;
254             Points[0].y = epy+1+add;
255             Points[1].x = rc->right-1;
256             Points[1].y = rc->top+add;
257             Points[2].x = rc->right-1;
258             Points[2].y = rc->bottom-1;
259             Points[3].x = spx+add;
260             Points[3].y = spy;
261             break;
262 
263         case BF_DIAGONAL_ENDTOPLEFT:
264             GreMoveTo(hdc, spx, spy-1, NULL);
265             NtGdiLineTo(hdc, epx+1, epy);
266             Points[0].x = epx+1+add;
267             Points[0].y = epy+1;
268             Points[1].x = rc->right-1;
269             Points[1].y = rc->top;
270             Points[2].x = rc->right-1;
271             Points[2].y = rc->bottom-1-add;
272             Points[3].x = spx;
273             Points[3].y = spy-add;
274             break;
275 
276         case (BF_DIAGONAL|BF_TOP):
277                     case (BF_DIAGONAL|BF_BOTTOM|BF_TOP):
278                         case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT):
279                                 GreMoveTo(hdc, spx+1, spy-1, NULL);
280             NtGdiLineTo(hdc, epx, epy);
281             Points[0].x = epx-1;
282             Points[0].y = epy+1;
283             Points[1].x = rc->right-1;
284             Points[1].y = rc->top;
285             Points[2].x = rc->right-1;
286             Points[2].y = rc->bottom-1-add;
287             Points[3].x = spx+add;
288             Points[3].y = spy-add;
289             break;
290 
291         case (BF_DIAGONAL|BF_RIGHT):
292                     case (BF_DIAGONAL|BF_RIGHT|BF_LEFT):
293                         case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM):
294                                 GreMoveTo(hdc, spx, spy, NULL);
295             NtGdiLineTo(hdc, epx-1, epy+1);
296             Points[0].x = spx;
297             Points[0].y = spy;
298             Points[1].x = rc->left;
299             Points[1].y = rc->top+add;
300             Points[2].x = epx-1-add;
301             Points[2].y = epy+1+add;
302             Points[3] = Points[2];
303             break;
304     }
305 
306     /* Fill the interior if asked */
307     if((uFlags & BF_MIDDLE) && retval)
308     {
309         HBRUSH hbsave;
310         HPEN hpsave;
311         hbsave = (HBRUSH)NtGdiSelectBrush(hdc, NtGdiGetStockObject(DC_BRUSH));
312         hpsave = (HPEN)NtGdiSelectPen(hdc, NtGdiGetStockObject(DC_PEN));
313         IntSetDCBrushColor(hdc, IntGetSysColor(uFlags & BF_MONO ? COLOR_WINDOW : COLOR_BTNFACE));
314         IntSetDCPenColor(hdc, IntGetSysColor(uFlags & BF_MONO ? COLOR_WINDOW : COLOR_BTNFACE));
315         IntPolygon(hdc, Points, 4);
316         NtGdiSelectBrush(hdc, hbsave);
317         NtGdiSelectPen(hdc, hpsave);
318     }
319 
320     /* Adjust rectangle if asked */
321     if(uFlags & BF_ADJUST)
322     {
323         if(uFlags & BF_LEFT)
324             rc->left   += add;
325         if(uFlags & BF_RIGHT)
326             rc->right  -= add;
327         if(uFlags & BF_TOP)
328             rc->top    += add;
329         if(uFlags & BF_BOTTOM)
330             rc->bottom -= add;
331     }
332 
333     /* Cleanup */
334     NtGdiSelectPen(hdc, SavePen);
335     GreMoveTo(hdc, SavePoint.x, SavePoint.y, NULL);
336 
337     return retval;
338 }
339 
340 /* Ported from WINE20020904 */
341 /* Same as DrawEdge invoked without BF_DIAGONAL
342  *
343  * 23-Nov-1997: Changed by Bertho Stultiens
344  *
345  * Well, I started testing this and found out that there are a few things
346  * that weren't quite as win95. The following rewrite should reproduce
347  * win95 results completely.
348  * The colorselection is table-driven to avoid awfull if-statements.
349  * The table below show the color settings.
350  *
351  * Pen selection table for uFlags = 0
352  *
353  * uType |  LTI  |  LTO  |  RBI  |  RBO
354  * ------+-------+-------+-------+-------
355  *  0000 |   x   |   x   |   x   |   x
356  *  0001 |   x   |  22   |   x   |  21
357  *  0010 |   x   |  16   |   x   |  20
358  *  0011 |   x   |   x   |   x   |   x
359  * ------+-------+-------+-------+-------
360  *  0100 |   x   |  20   |   x   |  16
361  *  0101 |  20   |  22   |  16   |  21
362  *  0110 |  20   |  16   |  16   |  20
363  *  0111 |   x   |   x   |   x   |   x
364  * ------+-------+-------+-------+-------
365  *  1000 |   x   |  21   |   x   |  22
366  *  1001 |  21   |  22   |  22   |  21
367  *  1010 |  21   |  16   |  22   |  20
368  *  1011 |   x   |   x   |   x   |   x
369  * ------+-------+-------+-------+-------
370  *  1100 |   x   |   x   |   x   |   x
371  *  1101 |   x   | x (22)|   x   | x (21)
372  *  1110 |   x   | x (16)|   x   | x (20)
373  *  1111 |   x   |   x   |   x   |   x
374  *
375  * Pen selection table for uFlags = BF_SOFT
376  *
377  * uType |  LTI  |  LTO  |  RBI  |  RBO
378  * ------+-------+-------+-------+-------
379  *  0000 |   x   |   x   |   x   |   x
380  *  0001 |   x   |  20   |   x   |  21
381  *  0010 |   x   |  21   |   x   |  20
382  *  0011 |   x   |   x   |   x   |   x
383  * ------+-------+-------+-------+-------
384  *  0100 |   x   |  22   |   x   |  16
385  *  0101 |  22   |  20   |  16   |  21
386  *  0110 |  22   |  21   |  16   |  20
387  *  0111 |   x   |   x   |   x   |   x
388  * ------+-------+-------+-------+-------
389  *  1000 |   x   |  16   |   x   |  22
390  *  1001 |  16   |  20   |  22   |  21
391  *  1010 |  16   |  21   |  22   |  20
392  *  1011 |   x   |   x   |   x   |   x
393  * ------+-------+-------+-------+-------
394  *  1100 |   x   |   x   |   x   |   x
395  *  1101 |   x   | x (20)|   x   | x (21)
396  *  1110 |   x   | x (21)|   x   | x (20)
397  *  1111 |   x   |   x   |   x   |   x
398  *
399  * x = don't care; (n) = is what win95 actually uses
400  * LTI = left Top Inner line
401  * LTO = left Top Outer line
402  * RBI = Right Bottom Inner line
403  * RBO = Right Bottom Outer line
404  * 15 = COLOR_BTNFACE
405  * 16 = COLOR_BTNSHADOW
406  * 20 = COLOR_BTNHIGHLIGHT
407  * 21 = COLOR_3DDKSHADOW
408  * 22 = COLOR_3DLIGHT
409  */
410 BOOL FASTCALL IntDrawRectEdge(HDC hdc, LPRECT rc, UINT uType, UINT uFlags)
411 {
412     signed char LTInnerI, LTOuterI;
413     signed char RBInnerI, RBOuterI;
414     HPEN LTInnerPen, LTOuterPen;
415     HPEN RBInnerPen, RBOuterPen;
416     RECT InnerRect = *rc;
417     POINT SavePoint;
418     HPEN SavePen;
419     int LBpenplus = 0;
420     int LTpenplus = 0;
421     int RTpenplus = 0;
422     int RBpenplus = 0;
423     BOOL retval = !(   ((uType & BDR_INNER) == BDR_INNER
424                         || (uType & BDR_OUTER) == BDR_OUTER)
425                        && !(uFlags & (BF_FLAT|BF_MONO)) );
426     /* Init some vars */
427     LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN)NtGdiGetStockObject(NULL_PEN);
428     SavePen = (HPEN)NtGdiSelectPen(hdc, LTInnerPen);
429 
430     /* Determine the colors of the edges */
431     if(uFlags & BF_MONO)
432     {
433         LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
434         LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
435     }
436     else if(uFlags & BF_FLAT)
437     {
438         LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
439         LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
440 
441         /* Bertho Stultiens states above that this function exactly matches win95
442          * In win98 BF_FLAT rectangles have an inner border same color as the
443         * middle (COLOR_BTNFACE). I believe it's the same for win95 but since
444         * I don't know I go with Bertho and just sets it for win98 until proven
445         * otherwise.
446         *                                          Dennis Björklund, 10 June, 99
447         */
448         if( LTInnerI != -1 )
449             LTInnerI = RBInnerI = COLOR_BTNFACE;
450     }
451     else if(uFlags & BF_SOFT)
452     {
453         LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
454         LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
455         RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
456         RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
457     }
458     else
459     {
460         LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
461         LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
462         RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
463         RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
464     }
465 
466     if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT)
467         LBpenplus = 1;
468     if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT)
469         RTpenplus = 1;
470     if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT)
471         RBpenplus = 1;
472     if((uFlags & BF_TOPLEFT) == BF_TOPLEFT)
473         LTpenplus = 1;
474 
475     if(LTInnerI != -1)
476         LTInnerPen = NtGdiGetStockObject(DC_PEN);
477     if(LTOuterI != -1)
478         LTOuterPen = NtGdiGetStockObject(DC_PEN);
479     if(RBInnerI != -1)
480         RBInnerPen = NtGdiGetStockObject(DC_PEN);
481     if(RBOuterI != -1)
482         RBOuterPen = NtGdiGetStockObject(DC_PEN);
483     if((uFlags & BF_MIDDLE) && retval)
484     {
485         FillRect(hdc, &InnerRect, IntGetSysColorBrush(uFlags & BF_MONO ?
486                  COLOR_WINDOW : COLOR_BTNFACE));
487     }
488     GreMoveTo(hdc, 0, 0, &SavePoint);
489 
490     /* Draw the outer edge */
491     NtGdiSelectPen(hdc, LTOuterPen);
492     IntSetDCPenColor(hdc, IntGetSysColor(LTOuterI));
493     if(uFlags & BF_TOP)
494     {
495         GreMoveTo(hdc, InnerRect.left, InnerRect.top, NULL);
496         NtGdiLineTo(hdc, InnerRect.right, InnerRect.top);
497     }
498     if(uFlags & BF_LEFT)
499     {
500         GreMoveTo(hdc, InnerRect.left, InnerRect.top, NULL);
501         NtGdiLineTo(hdc, InnerRect.left, InnerRect.bottom);
502     }
503     NtGdiSelectPen(hdc, RBOuterPen);
504     IntSetDCPenColor(hdc, IntGetSysColor(RBOuterI));
505     if(uFlags & BF_BOTTOM)
506     {
507         GreMoveTo(hdc, InnerRect.left, InnerRect.bottom-1, NULL);
508         NtGdiLineTo(hdc, InnerRect.right, InnerRect.bottom-1);
509     }
510     if(uFlags & BF_RIGHT)
511     {
512         GreMoveTo(hdc, InnerRect.right-1, InnerRect.top, NULL);
513         NtGdiLineTo(hdc, InnerRect.right-1, InnerRect.bottom);
514     }
515 
516     /* Draw the inner edge */
517     NtGdiSelectPen(hdc, LTInnerPen);
518     IntSetDCPenColor(hdc, IntGetSysColor(LTInnerI));
519     if(uFlags & BF_TOP)
520     {
521         GreMoveTo(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL);
522         NtGdiLineTo(hdc, InnerRect.right-RTpenplus, InnerRect.top+1);
523     }
524     if(uFlags & BF_LEFT)
525     {
526         GreMoveTo(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL);
527         NtGdiLineTo(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus);
528     }
529     NtGdiSelectPen(hdc, RBInnerPen);
530     IntSetDCPenColor(hdc, IntGetSysColor(RBInnerI));
531     if(uFlags & BF_BOTTOM)
532     {
533         GreMoveTo(hdc, InnerRect.left+LBpenplus, InnerRect.bottom-2, NULL);
534         NtGdiLineTo(hdc, InnerRect.right-RBpenplus, InnerRect.bottom-2);
535     }
536     if(uFlags & BF_RIGHT)
537     {
538         GreMoveTo(hdc, InnerRect.right-2, InnerRect.top+RTpenplus, NULL);
539         NtGdiLineTo(hdc, InnerRect.right-2, InnerRect.bottom-RBpenplus);
540     }
541 
542     if( ((uFlags & BF_MIDDLE) && retval) || (uFlags & BF_ADJUST) )
543     {
544         int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
545                       + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
546 
547         if(uFlags & BF_LEFT)
548             InnerRect.left += add;
549         if(uFlags & BF_RIGHT)
550             InnerRect.right -= add;
551         if(uFlags & BF_TOP)
552             InnerRect.top += add;
553         if(uFlags & BF_BOTTOM)
554             InnerRect.bottom -= add;
555 
556         if(uFlags & BF_ADJUST)
557             *rc = InnerRect;
558     }
559 
560     /* Cleanup */
561     NtGdiSelectPen(hdc, SavePen);
562     GreMoveTo(hdc, SavePoint.x, SavePoint.y, NULL);
563     return retval;
564 }
565 
566 int FASTCALL UITOOLS_MakeSquareRect(LPRECT src, LPRECT dst)
567 {
568     int Width  = src->right - src->left;
569     int Height = src->bottom - src->top;
570     int SmallDiam = Width > Height ? Height : Width;
571 
572     *dst = *src;
573 
574     /* Make it a square box */
575     if(Width < Height)      /* SmallDiam == Width */
576     {
577         dst->top += (Height-Width)/2;
578         dst->bottom = dst->top + SmallDiam;
579     }
580     else if(Width > Height) /* SmallDiam == Height */
581     {
582         dst->left += (Width-Height)/2;
583         dst->right = dst->left + SmallDiam;
584     }
585 
586     return SmallDiam;
587 }
588 
589 /* Ported from WINE20020904 */
590 void FASTCALL UITOOLS_DrawCheckedRect( HDC dc, LPRECT rect )
591 {
592     if(IntGetSysColor(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255))
593     {
594         HBRUSH hbsave;
595         COLORREF bg;
596 
597         FillRect(dc, rect, IntGetSysColorBrush(COLOR_BTNFACE));
598         bg = IntGdiSetBkColor(dc, RGB(255, 255, 255));
599         hbsave = NtGdiSelectBrush(dc, gpsi->hbrGray);
600         NtGdiPatBlt(dc, rect->left, rect->top, rect->right-rect->left, rect->bottom-rect->top, 0x00FA0089);
601         NtGdiSelectBrush(dc, hbsave);
602         IntGdiSetBkColor(dc, bg);
603     }
604     else
605     {
606         FillRect(dc, rect, IntGetSysColorBrush(COLOR_BTNHIGHLIGHT));
607     }
608 }
609 
610 /* Ported from WINE20020904 */
611 /* Draw a push button coming from DrawFrameControl()
612  *
613  * Does a pretty good job in emulating MS behavior. Some quirks are
614  * however there because MS uses a TrueType font (Marlett) to draw
615  * the buttons.
616  *
617  * FIXME: This looks a little bit strange, needs to be rewritten completely
618  * (several quirks with adjust, DFCS_CHECKED aso)
619  */
620 BOOL FASTCALL UITOOLS95_DFC_ButtonPush(HDC dc, LPRECT r, UINT uFlags)
621 {
622     UINT edge;
623     RECT myr = *r;
624 
625     if(uFlags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT))
626         edge = EDGE_SUNKEN;
627     else
628         edge = EDGE_RAISED;
629 
630     if(uFlags & DFCS_CHECKED)
631     {
632         if(uFlags & DFCS_MONO)
633             IntDrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
634         else
635             IntDrawRectEdge(dc, &myr, edge, (uFlags&DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST);
636 
637         UITOOLS_DrawCheckedRect( dc, &myr );
638     }
639     else
640     {
641         if(uFlags & DFCS_MONO)
642         {
643             IntDrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
644             FillRect(dc, &myr, IntGetSysColorBrush(COLOR_BTNFACE));
645         }
646         else
647         {
648             IntDrawRectEdge(dc, r, edge, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT | BF_SOFT);
649         }
650     }
651 
652     /* Adjust rectangle if asked */
653     if(uFlags & DFCS_ADJUSTRECT)
654     {
655         r->left   += 2;
656         r->right  -= 2;
657         r->top    += 2;
658         r->bottom -= 2;
659     }
660 
661     return TRUE;
662 }
663 
664 BOOL FASTCALL UITOOLS95_DFC_ButtonCheckRadio(HDC dc, LPRECT r, UINT uFlags, BOOL Radio)
665 {
666     LOGFONTW lf;
667     HFONT hFont, hOldFont;
668     int i;
669     WCHAR OutRight, OutLeft, InRight, InLeft, Center;
670     RECT myr;
671     INT cxy, nBkMode;
672 
673     cxy = UITOOLS_MakeSquareRect(r, &myr);
674     if (Radio)
675     {
676         OutRight = 'j'; // Outer right
677         OutLeft  = 'k'; // Outer left
678         InRight  = 'l'; // inner left
679         InLeft   = 'm'; // inner right
680         Center   = 'n'; // center
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     RtlZeroMemory(&lf, sizeof(LOGFONTW));
691     lf.lfHeight = cxy;
692     lf.lfWidth = 0;
693     lf.lfWeight = FW_NORMAL;
694     lf.lfCharSet = DEFAULT_CHARSET;
695     RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
696     hFont = GreCreateFontIndirectW(&lf);
697     hOldFont = NtGdiSelectFont(dc, hFont);
698 
699     nBkMode = GreGetBkMode(dc);
700 
701     if(Radio && ((uFlags & 0xff) == DFCS_BUTTONRADIOMASK))
702     {
703         IntGdiSetBkMode(dc, OPAQUE);
704         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
705         GreTextOutW(dc, myr.left, myr.top, &Center, 1);
706         IntGdiSetBkMode(dc, TRANSPARENT);
707         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
708         GreTextOutW(dc, myr.left, myr.top, &OutRight, 1);
709         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
710         GreTextOutW(dc, myr.left, myr.top, &OutLeft, 1);
711     }
712     else
713     {
714         IntGdiSetBkMode(dc, TRANSPARENT);
715 
716         /* Center section, white for active, grey for inactive */
717         i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE;
718         IntGdiSetTextColor(dc, IntGetSysColor(i));
719         GreTextOutW(dc, myr.left, myr.top, &Center, 1);
720 
721         if(uFlags & (DFCS_FLAT | DFCS_MONO))
722         {
723             IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
724             GreTextOutW(dc, myr.left, myr.top, &OutRight, 1);
725             GreTextOutW(dc, myr.left, myr.top, &OutLeft, 1);
726             GreTextOutW(dc, myr.left, myr.top, &InRight, 1);
727             GreTextOutW(dc, myr.left, myr.top, &InLeft, 1);
728         }
729         else
730         {
731             IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNSHADOW));
732             GreTextOutW(dc, myr.left, myr.top, &OutRight, 1);
733             IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
734             GreTextOutW(dc, myr.left, myr.top, &OutLeft, 1);
735             IntGdiSetTextColor(dc, IntGetSysColor(COLOR_3DDKSHADOW));
736             GreTextOutW(dc, myr.left, myr.top, &InRight, 1);
737             IntGdiSetTextColor(dc, IntGetSysColor(COLOR_3DLIGHT));
738             GreTextOutW(dc, myr.left, myr.top, &InLeft, 1);
739         }
740     }
741 
742     if(uFlags & DFCS_CHECKED)
743     {
744         WCHAR Check = (Radio) ? 'i' : 'b';
745 
746         IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT));
747         GreTextOutW(dc, myr.left, myr.top, &Check, 1);
748     }
749 
750     IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWTEXT));
751     NtGdiSelectFont(dc, hOldFont);
752     GreDeleteObject(hFont);
753     IntGdiSetBkMode(dc, nBkMode);
754 
755     return TRUE;
756 }
757 
758 /* Ported from WINE20020904 */
759 BOOL FASTCALL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState)
760 {
761     switch(uState & 0x1f)
762     {
763         case DFCS_BUTTONPUSH:
764             return UITOOLS95_DFC_ButtonPush(hdc, rc, uState);
765 
766         case DFCS_BUTTONCHECK:
767         case DFCS_BUTTON3STATE:
768             return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, FALSE);
769 
770         case DFCS_BUTTONRADIOIMAGE:
771         case DFCS_BUTTONRADIOMASK:
772             if (uState & DFCS_BUTTONRADIOIMAGE)
773                 FillRect(hdc, rc, (HBRUSH)NtGdiGetStockObject(BLACK_BRUSH)); /* Fill by black */
774             else
775                 FillRect(hdc, rc, (HBRUSH)NtGdiGetStockObject(WHITE_BRUSH)); /* Fill by white */
776 
777             return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, TRUE);
778 
779         case DFCS_BUTTONRADIO:
780             return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, TRUE);
781 
782         default:
783             ERR("Invalid button state=0x%04x\n", uState);
784     }
785     return FALSE;
786 }
787 
788 BOOL FASTCALL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags)
789 {
790     LOGFONTW lf;
791     HFONT hFont, hOldFont;
792     COLORREF clrsave;
793     RECT myr;
794     INT bkmode;
795     WCHAR Symbol;
796     switch(uFlags & 0xf)
797     {
798         case DFCS_CAPTIONCLOSE:
799 		Symbol = 'r';
800 		break;
801         case DFCS_CAPTIONHELP:
802 		Symbol = 's';
803 		break;
804         case DFCS_CAPTIONMIN:
805 		Symbol = '0';
806 		break;
807         case DFCS_CAPTIONMAX:
808 		Symbol = '1';
809 		break;
810         case DFCS_CAPTIONRESTORE:
811 		Symbol = '2';
812 		break;
813         default:
814              ERR("Invalid caption; flags=0x%04x\n", uFlags);
815              return FALSE;
816     }
817     IntDrawRectEdge(dc,r,(uFlags&DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT | BF_MIDDLE | BF_SOFT);
818     RtlZeroMemory(&lf, sizeof(LOGFONTW));
819     UITOOLS_MakeSquareRect(r, &myr);
820     myr.left += 1;
821     myr.top += 1;
822     myr.right -= 1;
823     myr.bottom -= 1;
824     if(uFlags & DFCS_PUSHED)
825        RECTL_vOffsetRect(&myr,1,1);
826     lf.lfHeight = myr.bottom - myr.top;
827     lf.lfWidth = 0;
828     lf.lfWeight = FW_NORMAL;
829     lf.lfCharSet = DEFAULT_CHARSET;
830     lf.lfQuality = NONANTIALIASED_QUALITY;
831     RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
832     hFont = GreCreateFontIndirectW(&lf);
833     /* save font and text color */
834     hOldFont = NtGdiSelectFont(dc, hFont);
835     clrsave = GreGetTextColor(dc);
836     bkmode = GreGetBkMode(dc);
837     /* set color and drawing mode */
838     IntGdiSetBkMode(dc, TRANSPARENT);
839     if(uFlags & DFCS_INACTIVE)
840     {
841         /* draw shadow */
842         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
843         GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
844     }
845     IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
846     /* draw selected symbol */
847     GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
848     /* restore previous settings */
849     IntGdiSetTextColor(dc, clrsave);
850     NtGdiSelectFont(dc, hOldFont);
851     IntGdiSetBkMode(dc, bkmode);
852     GreDeleteObject(hFont);
853     return TRUE;
854 }
855 
856 BOOL FASTCALL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags)
857 {
858     LOGFONTW lf;
859     HFONT hFont, hOldFont;
860     COLORREF clrsave;
861     RECT myr;
862     INT bkmode;
863     WCHAR Symbol;
864     switch(uFlags & 0x1f)
865     {
866         case DFCS_SCROLLCOMBOBOX:
867         case DFCS_SCROLLDOWN:
868 		Symbol = '6';
869 		break;
870 
871 	case DFCS_SCROLLUP:
872 		Symbol = '5';
873 		break;
874 
875 	case DFCS_SCROLLLEFT:
876 		Symbol = '3';
877 		break;
878 
879 	case DFCS_SCROLLRIGHT:
880 		Symbol = '4';
881 		break;
882 
883 	case DFCS_SCROLLSIZEGRIP:
884 	case DFCS_SCROLLSIZEGRIPRIGHT:
885 		RtlZeroMemory(&lf, sizeof(LOGFONTW));
886 		UITOOLS_MakeSquareRect(r, &myr);
887 		lf.lfHeight = myr.bottom - myr.top;
888 		lf.lfWidth = 0;
889 		lf.lfWeight = FW_NORMAL;
890 		lf.lfCharSet = DEFAULT_CHARSET;
891 		RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
892 		hFont = GreCreateFontIndirectW(&lf);
893 		/* save font and text color */
894 		hOldFont = NtGdiSelectFont(dc, hFont);
895 		clrsave = GreGetTextColor(dc);
896 		bkmode = GreGetBkMode(dc);
897 		/* set color and drawing mode */
898 		IntGdiSetBkMode(dc, TRANSPARENT);
899 		if (!(uFlags & (DFCS_MONO | DFCS_FLAT)))
900 		{
901 			IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
902 			/* draw selected symbol */
903 			Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'o' : 'x';
904 			GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
905 			IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNSHADOW));
906 		} else
907 			IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
908 		/* draw selected symbol */
909 		Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'p' : 'y';
910 		GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
911 		/* restore previous settings */
912 		IntGdiSetTextColor(dc, clrsave);
913 		NtGdiSelectFont(dc, hOldFont);
914 		IntGdiSetBkMode(dc, bkmode);
915 		GreDeleteObject(hFont);
916             return TRUE;
917 	default:
918 	    ERR("Invalid scroll; flags=0x%04x\n", uFlags);
919             return FALSE;
920     }
921     IntDrawRectEdge(dc, r, (uFlags & DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT);
922     RtlZeroMemory(&lf, sizeof(LOGFONTW));
923     UITOOLS_MakeSquareRect(r, &myr);
924     myr.left += 1;
925     myr.top += 1;
926     myr.right -= 1;
927     myr.bottom -= 1;
928     if(uFlags & DFCS_PUSHED)
929        RECTL_vOffsetRect(&myr,1,1);
930     lf.lfHeight = myr.bottom - myr.top;
931     lf.lfWidth = 0;
932     lf.lfWeight = FW_NORMAL;
933     lf.lfCharSet = DEFAULT_CHARSET;
934     RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
935     hFont = GreCreateFontIndirectW(&lf);
936     /* save font and text color */
937     hOldFont = NtGdiSelectFont(dc, hFont);
938     clrsave = GreGetTextColor(dc);
939     bkmode = GreGetBkMode(dc);
940     /* set color and drawing mode */
941     IntGdiSetBkMode(dc, TRANSPARENT);
942     if(uFlags & DFCS_INACTIVE)
943     {
944         /* draw shadow */
945         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
946         GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
947     }
948     IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
949     /* draw selected symbol */
950     GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
951     /* restore previous settings */
952     IntGdiSetTextColor(dc, clrsave);
953     NtGdiSelectFont(dc, hOldFont);
954     IntGdiSetBkMode(dc, bkmode);
955     GreDeleteObject(hFont);
956     return TRUE;
957 }
958 
959 BOOL FASTCALL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
960 {
961     LOGFONTW lf;
962     HFONT hFont, hOldFont;
963     WCHAR Symbol;
964     RECT myr;
965     INT cxy;
966     cxy = UITOOLS_MakeSquareRect(r, &myr);
967     switch(uFlags & 0x1f)
968     {
969         case DFCS_MENUARROWUP:
970             Symbol = '5';
971             break;
972 
973         case DFCS_MENUARROWDOWN:
974             Symbol = '6';
975             break;
976 
977         case DFCS_MENUARROW:
978             Symbol = '8';
979             break;
980 
981         case DFCS_MENUARROWRIGHT:
982 	    Symbol = 'w'; // FIXME: needs to confirm
983 	    break;
984 
985         case DFCS_MENUBULLET:
986             Symbol = 'h';
987             break;
988 
989         case DFCS_MENUCHECK:
990         case DFCS_MENUCHECK | DFCS_MENUBULLET:
991             Symbol = 'a';
992             break;
993 
994         default:
995             ERR("Invalid menu; flags=0x%04x\n", uFlags);
996             return FALSE;
997     }
998     /* acquire ressources only if valid menu */
999     RtlZeroMemory(&lf, sizeof(LOGFONTW));
1000     lf.lfHeight = cxy;
1001     lf.lfWidth = 0;
1002     lf.lfWeight = FW_NORMAL;
1003     lf.lfCharSet = DEFAULT_CHARSET;
1004     RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
1005     hFont = GreCreateFontIndirectW(&lf);
1006     /* save font */
1007     hOldFont = NtGdiSelectFont(dc, hFont);
1008 
1009     if ((uFlags & 0x1f) == DFCS_MENUARROWUP ||
1010         (uFlags & 0x1f) == DFCS_MENUARROWDOWN )
1011     {
1012 #if 0
1013        if (uFlags & DFCS_INACTIVE)
1014        {
1015            /* draw shadow */
1016            IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
1017            GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
1018        }
1019 #endif
1020        IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
1021     }
1022     /* draw selected symbol */
1023     GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
1024     /* restore previous settings */
1025     NtGdiSelectFont(dc, hOldFont);
1026     GreDeleteObject(hFont);
1027     return TRUE;
1028 }
1029 
1030 //
1031 //
1032 //	Win32ss API support.
1033 //
1034 //
1035 
1036 
1037 INT WINAPI
1038 FrameRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr)
1039 {
1040     HBRUSH oldbrush;
1041     RECT r = *lprc;
1042 
1043     if ((r.right <= r.left) || (r.bottom <= r.top)) return 0;
1044     if (!(oldbrush = NtGdiSelectBrush(hDC, hbr))) return 0;
1045 
1046     NtGdiPatBlt(hDC, r.left, r.top, 1, r.bottom - r.top, PATCOPY);
1047     NtGdiPatBlt(hDC, r.right - 1, r.top, 1, r.bottom - r.top, PATCOPY);
1048     NtGdiPatBlt(hDC, r.left, r.top, r.right - r.left, 1, PATCOPY);
1049     NtGdiPatBlt(hDC, r.left, r.bottom - 1, r.right - r.left, 1, PATCOPY);
1050 
1051     NtGdiSelectBrush(hDC, oldbrush);
1052     return TRUE;
1053 }
1054 
1055 
1056 INT WINAPI
1057 FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr)
1058 {
1059     BOOL Ret;
1060     HBRUSH prevhbr = NULL;
1061 
1062     /* Select brush if specified */
1063     if (hbr)
1064     {
1065         /* Handle system colors */
1066         if (hbr <= (HBRUSH)(COLOR_MENUBAR + 1))
1067             hbr = IntGetSysColorBrush(PtrToUlong(hbr) - 1);
1068 
1069         prevhbr = NtGdiSelectBrush(hDC, hbr);
1070         if (prevhbr == NULL)
1071             return (INT)FALSE;
1072     }
1073 
1074     Ret = NtGdiPatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left,
1075                  lprc->bottom - lprc->top, PATCOPY);
1076 
1077     /* Select old brush */
1078     if (prevhbr)
1079         NtGdiSelectBrush(hDC, prevhbr);
1080 
1081     return (INT)Ret;
1082 }
1083 
1084 BOOL WINAPI
1085 DrawEdge(HDC hDC, LPRECT rc, UINT edge, UINT flags)
1086 {
1087     if (flags & BF_DIAGONAL)
1088        return IntDrawDiagEdge(hDC, rc, edge, flags);
1089     else
1090        return IntDrawRectEdge(hDC, rc, edge, flags);
1091 }
1092 
1093 BOOL WINAPI
1094 DrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState)
1095 {
1096     if (GreGetMapMode(hDC) != MM_TEXT)
1097         return FALSE;
1098 
1099     switch(uType)
1100     {
1101         case DFC_BUTTON:
1102             return UITOOLS95_DrawFrameButton(hDC, rc, uState);
1103         case DFC_CAPTION:
1104             return UITOOLS95_DrawFrameCaption(hDC, rc, uState);
1105         case DFC_MENU:
1106         {
1107             BOOL ret;
1108             COLORREF rgbOldText;
1109             INT iOldBackMode;
1110 
1111             if (uState & (DFCS_MENUARROWUP | DFCS_MENUARROWDOWN))
1112             {
1113                 if (!(uState & DFCS_TRANSPARENT))
1114                     FillRect(hDC, rc, IntGetSysColorBrush(COLOR_MENU)); /* Fill by menu color */
1115             }
1116             else
1117             {
1118                 FillRect(hDC, rc, (HBRUSH)NtGdiGetStockObject(WHITE_BRUSH)); /* Fill by white */
1119             }
1120 
1121             rgbOldText = IntGdiSetTextColor(hDC, RGB(0, 0, 0)); /* Draw by black */
1122             iOldBackMode = IntGdiSetBkMode(hDC, TRANSPARENT);
1123             ret = UITOOLS95_DrawFrameMenu(hDC, rc, uState);
1124             IntGdiSetBkMode(hDC, iOldBackMode);
1125             IntGdiSetTextColor(hDC, rgbOldText);
1126             return ret;
1127         }
1128 #if 0
1129         case DFC_POPUPMENU:
1130             UNIMPLEMENTED;
1131             break;
1132 #endif
1133         case DFC_SCROLL:
1134             return UITOOLS95_DrawFrameScroll(hDC, rc, uState);
1135     }
1136     return FALSE;
1137 }
1138 
1139