xref: /reactos/win32ss/user/ntuser/draw.c (revision 40462c92)
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(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         case DFCS_BUTTONRADIO:
773             return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, TRUE);
774 
775 
776         default:
777             ERR("Invalid button state=0x%04x\n", uState);
778 
779     }
780     return FALSE;
781 }
782 
783 BOOL FASTCALL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags)
784 {
785     LOGFONTW lf;
786     HFONT hFont, hOldFont;
787     COLORREF clrsave;
788     RECT myr;
789     INT bkmode;
790     WCHAR Symbol;
791     switch(uFlags & 0xf)
792     {
793         case DFCS_CAPTIONCLOSE:
794 		Symbol = 'r';
795 		break;
796         case DFCS_CAPTIONHELP:
797 		Symbol = 's';
798 		break;
799         case DFCS_CAPTIONMIN:
800 		Symbol = '0';
801 		break;
802         case DFCS_CAPTIONMAX:
803 		Symbol = '1';
804 		break;
805         case DFCS_CAPTIONRESTORE:
806 		Symbol = '2';
807 		break;
808         default:
809              ERR("Invalid caption; flags=0x%04x\n", uFlags);
810              return FALSE;
811     }
812     IntDrawRectEdge(dc,r,(uFlags&DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT | BF_MIDDLE | BF_SOFT);
813     RtlZeroMemory(&lf, sizeof(LOGFONTW));
814     UITOOLS_MakeSquareRect(r, &myr);
815     myr.left += 1;
816     myr.top += 1;
817     myr.right -= 1;
818     myr.bottom -= 1;
819     if(uFlags & DFCS_PUSHED)
820        RECTL_vOffsetRect(&myr,1,1);
821     lf.lfHeight = myr.bottom - myr.top;
822     lf.lfWidth = 0;
823     lf.lfWeight = FW_NORMAL;
824     lf.lfCharSet = DEFAULT_CHARSET;
825     lf.lfQuality = NONANTIALIASED_QUALITY;
826     RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
827     hFont = GreCreateFontIndirectW(&lf);
828     /* save font and text color */
829     hOldFont = NtGdiSelectFont(dc, hFont);
830     clrsave = GreGetTextColor(dc);
831     bkmode = GreGetBkMode(dc);
832     /* set color and drawing mode */
833     IntGdiSetBkMode(dc, TRANSPARENT);
834     if(uFlags & DFCS_INACTIVE)
835     {
836         /* draw shadow */
837         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
838         GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
839     }
840     IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
841     /* draw selected symbol */
842     GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
843     /* restore previous settings */
844     IntGdiSetTextColor(dc, clrsave);
845     NtGdiSelectFont(dc, hOldFont);
846     IntGdiSetBkMode(dc, bkmode);
847     GreDeleteObject(hFont);
848     return TRUE;
849 }
850 
851 BOOL FASTCALL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags)
852 {
853     LOGFONTW lf;
854     HFONT hFont, hOldFont;
855     COLORREF clrsave;
856     RECT myr;
857     INT bkmode;
858     WCHAR Symbol;
859     switch(uFlags & 0x1f)
860     {
861         case DFCS_SCROLLCOMBOBOX:
862         case DFCS_SCROLLDOWN:
863 		Symbol = '6';
864 		break;
865 
866 	case DFCS_SCROLLUP:
867 		Symbol = '5';
868 		break;
869 
870 	case DFCS_SCROLLLEFT:
871 		Symbol = '3';
872 		break;
873 
874 	case DFCS_SCROLLRIGHT:
875 		Symbol = '4';
876 		break;
877 
878 	case DFCS_SCROLLSIZEGRIP:
879 	case DFCS_SCROLLSIZEGRIPRIGHT:
880 		RtlZeroMemory(&lf, sizeof(LOGFONTW));
881 		UITOOLS_MakeSquareRect(r, &myr);
882 		lf.lfHeight = myr.bottom - myr.top;
883 		lf.lfWidth = 0;
884 		lf.lfWeight = FW_NORMAL;
885 		lf.lfCharSet = DEFAULT_CHARSET;
886 		RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
887 		hFont = GreCreateFontIndirectW(&lf);
888 		/* save font and text color */
889 		hOldFont = NtGdiSelectFont(dc, hFont);
890 		clrsave = GreGetTextColor(dc);
891 		bkmode = GreGetBkMode(dc);
892 		/* set color and drawing mode */
893 		IntGdiSetBkMode(dc, TRANSPARENT);
894 		if (!(uFlags & (DFCS_MONO | DFCS_FLAT)))
895 		{
896 			IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
897 			/* draw selected symbol */
898 			Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'o' : 'x';
899 			GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
900 			IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNSHADOW));
901 		} else
902 			IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
903 		/* draw selected symbol */
904 		Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'p' : 'y';
905 		GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
906 		/* restore previous settings */
907 		IntGdiSetTextColor(dc, clrsave);
908 		NtGdiSelectFont(dc, hOldFont);
909 		IntGdiSetBkMode(dc, bkmode);
910 		GreDeleteObject(hFont);
911             return TRUE;
912 	default:
913 	    ERR("Invalid scroll; flags=0x%04x\n", uFlags);
914             return FALSE;
915     }
916     IntDrawRectEdge(dc, r, (uFlags & DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT);
917     RtlZeroMemory(&lf, sizeof(LOGFONTW));
918     UITOOLS_MakeSquareRect(r, &myr);
919     myr.left += 1;
920     myr.top += 1;
921     myr.right -= 1;
922     myr.bottom -= 1;
923     if(uFlags & DFCS_PUSHED)
924        RECTL_vOffsetRect(&myr,1,1);
925     lf.lfHeight = myr.bottom - myr.top;
926     lf.lfWidth = 0;
927     lf.lfWeight = FW_NORMAL;
928     lf.lfCharSet = DEFAULT_CHARSET;
929     RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
930     hFont = GreCreateFontIndirectW(&lf);
931     /* save font and text color */
932     hOldFont = NtGdiSelectFont(dc, hFont);
933     clrsave = GreGetTextColor(dc);
934     bkmode = GreGetBkMode(dc);
935     /* set color and drawing mode */
936     IntGdiSetBkMode(dc, TRANSPARENT);
937     if(uFlags & DFCS_INACTIVE)
938     {
939         /* draw shadow */
940         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
941         GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
942     }
943     IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
944     /* draw selected symbol */
945     GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
946     /* restore previous settings */
947     IntGdiSetTextColor(dc, clrsave);
948     NtGdiSelectFont(dc, hOldFont);
949     IntGdiSetBkMode(dc, bkmode);
950     GreDeleteObject(hFont);
951     return TRUE;
952 }
953 
954 BOOL FASTCALL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
955 {
956     // TODO: DFCS_TRANSPARENT upon DFCS_MENUARROWUP or DFCS_MENUARROWDOWN
957     LOGFONTW lf;
958     HFONT hFont, hOldFont;
959     WCHAR Symbol;
960     RECT myr;
961     INT cxy;
962     cxy = UITOOLS_MakeSquareRect(r, &myr);
963     switch(uFlags & 0x1f)
964     {
965         case DFCS_MENUARROWUP:
966             Symbol = '5';
967             break;
968 
969         case DFCS_MENUARROWDOWN:
970             Symbol = '6';
971             break;
972 
973         case DFCS_MENUARROW:
974             Symbol = '8';
975             break;
976 
977         case DFCS_MENUARROWRIGHT:
978 	    Symbol = 'w'; // FIXME: needs to confirm
979 	    break;
980 
981         case DFCS_MENUBULLET:
982             Symbol = 'h';
983             break;
984 
985         case DFCS_MENUCHECK:
986             Symbol = 'a';
987             break;
988 
989         default:
990             ERR("Invalid menu; flags=0x%04x\n", uFlags);
991             return FALSE;
992     }
993     /* acquire ressources only if valid menu */
994     RtlZeroMemory(&lf, sizeof(LOGFONTW));
995     lf.lfHeight = cxy;
996     lf.lfWidth = 0;
997     lf.lfWeight = FW_NORMAL;
998     lf.lfCharSet = DEFAULT_CHARSET;
999     RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
1000     hFont = GreCreateFontIndirectW(&lf);
1001     /* save font */
1002     hOldFont = NtGdiSelectFont(dc, hFont);
1003 
1004     if ((uFlags & 0x1f) == DFCS_MENUARROWUP ||
1005         (uFlags & 0x1f) == DFCS_MENUARROWDOWN )
1006     {
1007 #if 0
1008        if (uFlags & DFCS_INACTIVE)
1009        {
1010            /* draw shadow */
1011            IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
1012            GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
1013        }
1014 #endif
1015        IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
1016     }
1017     /* draw selected symbol */
1018     GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
1019     /* restore previous settings */
1020     NtGdiSelectFont(dc, hOldFont);
1021     GreDeleteObject(hFont);
1022     return TRUE;
1023 }
1024 
1025 //
1026 //
1027 //	Win32ss API support.
1028 //
1029 //
1030 
1031 
1032 INT WINAPI
1033 FrameRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr)
1034 {
1035     HBRUSH oldbrush;
1036     RECT r = *lprc;
1037 
1038     if ((r.right <= r.left) || (r.bottom <= r.top)) return 0;
1039     if (!(oldbrush = NtGdiSelectBrush(hDC, hbr))) return 0;
1040 
1041     NtGdiPatBlt(hDC, r.left, r.top, 1, r.bottom - r.top, PATCOPY);
1042     NtGdiPatBlt(hDC, r.right - 1, r.top, 1, r.bottom - r.top, PATCOPY);
1043     NtGdiPatBlt(hDC, r.left, r.top, r.right - r.left, 1, PATCOPY);
1044     NtGdiPatBlt(hDC, r.left, r.bottom - 1, r.right - r.left, 1, PATCOPY);
1045 
1046     NtGdiSelectBrush(hDC, oldbrush);
1047     return TRUE;
1048 }
1049 
1050 
1051 INT WINAPI
1052 FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr)
1053 {
1054     BOOL Ret;
1055     HBRUSH prevhbr = NULL;
1056 
1057     /* Select brush if specified */
1058     if (hbr)
1059     {
1060         /* Handle system colors */
1061         if (hbr <= (HBRUSH)(COLOR_MENUBAR + 1))
1062             hbr = IntGetSysColorBrush(PtrToUlong(hbr) - 1);
1063 
1064         prevhbr = NtGdiSelectBrush(hDC, hbr);
1065         if (prevhbr == NULL)
1066             return (INT)FALSE;
1067     }
1068 
1069     Ret = NtGdiPatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left,
1070                  lprc->bottom - lprc->top, PATCOPY);
1071 
1072     /* Select old brush */
1073     if (prevhbr)
1074         NtGdiSelectBrush(hDC, prevhbr);
1075 
1076     return (INT)Ret;
1077 }
1078 
1079 BOOL WINAPI
1080 DrawEdge(HDC hDC, LPRECT rc, UINT edge, UINT flags)
1081 {
1082     if (flags & BF_DIAGONAL)
1083        return IntDrawDiagEdge(hDC, rc, edge, flags);
1084     else
1085        return IntDrawRectEdge(hDC, rc, edge, flags);
1086 }
1087 
1088 BOOL WINAPI
1089 DrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState)
1090 {
1091     if (GreGetMapMode(hDC) != MM_TEXT)
1092         return FALSE;
1093 
1094     switch(uType)
1095     {
1096         case DFC_BUTTON:
1097             return UITOOLS95_DrawFrameButton(hDC, rc, uState);
1098         case DFC_CAPTION:
1099             return UITOOLS95_DrawFrameCaption(hDC, rc, uState);
1100         case DFC_MENU:
1101             return UITOOLS95_DrawFrameMenu(hDC, rc, uState);
1102 #if 0
1103         case DFC_POPUPMENU:
1104             UNIMPLEMENTED;
1105             break;
1106 #endif
1107         case DFC_SCROLL:
1108             return UITOOLS95_DrawFrameScroll(hDC, rc, uState);
1109     }
1110     return FALSE;
1111 }
1112 
1113