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