xref: /reactos/win32ss/user/ntuser/draw.c (revision 3edf37e2)
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     RECT myr;
670     INT cxy, nBkMode;
671 
672     cxy = UITOOLS_MakeSquareRect(r, &myr);
673     if (Radio)
674     {
675         OutRight = 'j'; // Outer right
676         OutLeft  = 'k'; // Outer left
677         InRight  = 'l'; // inner left
678         InLeft   = 'm'; // inner right
679         Center   = 'n'; // center
680     } else
681     {
682         OutRight = 'c'; // Outer right
683         OutLeft  = 'd'; // Outer left
684         InRight  = 'e'; // inner left
685         InLeft   = 'f'; // inner right
686         Center   = 'g'; // center
687     }
688 
689     RtlZeroMemory(&lf, sizeof(LOGFONTW));
690     lf.lfHeight = cxy;
691     lf.lfWidth = 0;
692     lf.lfWeight = FW_NORMAL;
693     lf.lfCharSet = DEFAULT_CHARSET;
694     RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
695     hFont = GreCreateFontIndirectW(&lf);
696     hOldFont = NtGdiSelectFont(dc, hFont);
697 
698     nBkMode = GreGetBkMode(dc);
699 
700     if(Radio && ((uFlags & 0xff) == DFCS_BUTTONRADIOMASK))
701     {
702         IntGdiSetBkMode(dc, OPAQUE);
703         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
704         GreTextOutW(dc, myr.left, myr.top, &Center, 1);
705         IntGdiSetBkMode(dc, TRANSPARENT);
706         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
707         GreTextOutW(dc, myr.left, myr.top, &OutRight, 1);
708         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
709         GreTextOutW(dc, myr.left, myr.top, &OutLeft, 1);
710     }
711     else
712     {
713         IntGdiSetBkMode(dc, TRANSPARENT);
714 
715         /* Center section, white for active, grey for inactive */
716         i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE;
717         IntGdiSetTextColor(dc, IntGetSysColor(i));
718         GreTextOutW(dc, myr.left, myr.top, &Center, 1);
719 
720         if(uFlags & (DFCS_FLAT | DFCS_MONO))
721         {
722             IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
723             GreTextOutW(dc, myr.left, myr.top, &OutRight, 1);
724             GreTextOutW(dc, myr.left, myr.top, &OutLeft, 1);
725             GreTextOutW(dc, myr.left, myr.top, &InRight, 1);
726             GreTextOutW(dc, myr.left, myr.top, &InLeft, 1);
727         }
728         else
729         {
730             IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNSHADOW));
731             GreTextOutW(dc, myr.left, myr.top, &OutRight, 1);
732             IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
733             GreTextOutW(dc, myr.left, myr.top, &OutLeft, 1);
734             IntGdiSetTextColor(dc, IntGetSysColor(COLOR_3DDKSHADOW));
735             GreTextOutW(dc, myr.left, myr.top, &InRight, 1);
736             IntGdiSetTextColor(dc, IntGetSysColor(COLOR_3DLIGHT));
737             GreTextOutW(dc, myr.left, myr.top, &InLeft, 1);
738         }
739     }
740 
741     if(uFlags & DFCS_CHECKED)
742     {
743         WCHAR Check = (Radio) ? 'i' : 'b';
744 
745         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWTEXT));
746         GreTextOutW(dc, myr.left, myr.top, &Check, 1);
747     }
748 
749     IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWTEXT));
750     NtGdiSelectFont(dc, hOldFont);
751     GreDeleteObject(hFont);
752     IntGdiSetBkMode(dc, nBkMode);
753 
754     return TRUE;
755 }
756 
757 /* Ported from WINE20020904 */
758 BOOL FASTCALL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState)
759 {
760     switch(uState & 0xff)
761     {
762         case DFCS_BUTTONPUSH:
763             return UITOOLS95_DFC_ButtonPush(hdc, rc, uState);
764 
765         case DFCS_BUTTONCHECK:
766         case DFCS_BUTTON3STATE:
767             return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, FALSE);
768 
769         case DFCS_BUTTONRADIOIMAGE:
770         case DFCS_BUTTONRADIOMASK:
771         case DFCS_BUTTONRADIO:
772             return UITOOLS95_DFC_ButtonCheckRadio(hdc, rc, uState, TRUE);
773 
774 /*
775         default:
776             DbgPrint("Invalid button state=0x%04x\n", uState);
777 */
778     }
779     return FALSE;
780 }
781 
782 BOOL FASTCALL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags)
783 {
784     LOGFONTW lf;
785     HFONT hFont, hOldFont;
786     COLORREF clrsave;
787     RECT myr;
788     INT bkmode;
789     WCHAR Symbol;
790     switch(uFlags & 0xff)
791     {
792         case DFCS_CAPTIONCLOSE:
793 		Symbol = 'r';
794 		break;
795         case DFCS_CAPTIONHELP:
796 		Symbol = 's';
797 		break;
798         case DFCS_CAPTIONMIN:
799 		Symbol = '0';
800 		break;
801         case DFCS_CAPTIONMAX:
802 		Symbol = '1';
803 		break;
804         case DFCS_CAPTIONRESTORE:
805 		Symbol = '2';
806 		break;
807         default:
808              return FALSE;
809     }
810     IntDrawRectEdge(dc,r,(uFlags&DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, BF_RECT | BF_MIDDLE | BF_SOFT);
811     RtlZeroMemory(&lf, sizeof(LOGFONTW));
812     UITOOLS_MakeSquareRect(r, &myr);
813     myr.left += 1;
814     myr.top += 1;
815     myr.right -= 1;
816     myr.bottom -= 1;
817     if(uFlags & DFCS_PUSHED)
818        RECTL_vOffsetRect(&myr,1,1);
819     lf.lfHeight = myr.bottom - myr.top;
820     lf.lfWidth = 0;
821     lf.lfWeight = FW_NORMAL;
822     lf.lfCharSet = DEFAULT_CHARSET;
823     lf.lfQuality = NONANTIALIASED_QUALITY;
824     RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
825     hFont = GreCreateFontIndirectW(&lf);
826     /* save font and text color */
827     hOldFont = NtGdiSelectFont(dc, hFont);
828     clrsave = GreGetTextColor(dc);
829     bkmode = GreGetBkMode(dc);
830     /* set color and drawing mode */
831     IntGdiSetBkMode(dc, TRANSPARENT);
832     if(uFlags & DFCS_INACTIVE)
833     {
834         /* draw shadow */
835         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
836         GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
837     }
838     IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
839     /* draw selected symbol */
840     GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
841     /* restore previous settings */
842     IntGdiSetTextColor(dc, clrsave);
843     NtGdiSelectFont(dc, hOldFont);
844     IntGdiSetBkMode(dc, bkmode);
845     GreDeleteObject(hFont);
846     return TRUE;
847 }
848 
849 BOOL FASTCALL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags)
850 {
851     LOGFONTW lf;
852     HFONT hFont, hOldFont;
853     COLORREF clrsave;
854     RECT myr;
855     INT bkmode;
856     WCHAR Symbol;
857     switch(uFlags & 0xff)
858     {
859         case DFCS_SCROLLCOMBOBOX:
860         case DFCS_SCROLLDOWN:
861 		Symbol = '6';
862 		break;
863 
864 	case DFCS_SCROLLUP:
865 		Symbol = '5';
866 		break;
867 
868 	case DFCS_SCROLLLEFT:
869 		Symbol = '3';
870 		break;
871 
872 	case DFCS_SCROLLRIGHT:
873 		Symbol = '4';
874 		break;
875 
876 	case DFCS_SCROLLSIZEGRIP:
877 	case DFCS_SCROLLSIZEGRIPRIGHT:
878 		RtlZeroMemory(&lf, sizeof(LOGFONTW));
879 		UITOOLS_MakeSquareRect(r, &myr);
880 		lf.lfHeight = myr.bottom - myr.top;
881 		lf.lfWidth = 0;
882 		lf.lfWeight = FW_NORMAL;
883 		lf.lfCharSet = DEFAULT_CHARSET;
884 		RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
885 		hFont = GreCreateFontIndirectW(&lf);
886 		/* save font and text color */
887 		hOldFont = NtGdiSelectFont(dc, hFont);
888 		clrsave = GreGetTextColor(dc);
889 		bkmode = GreGetBkMode(dc);
890 		/* set color and drawing mode */
891 		IntGdiSetBkMode(dc, TRANSPARENT);
892 		if (!(uFlags & (DFCS_MONO | DFCS_FLAT)))
893 		{
894 			IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
895 			/* draw selected symbol */
896 			Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'o' : 'x';
897 			GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
898 			IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNSHADOW));
899 		} else
900 			IntGdiSetTextColor(dc, IntGetSysColor(COLOR_WINDOWFRAME));
901 		/* draw selected symbol */
902 		Symbol = ((uFlags & 0xff) == DFCS_SCROLLSIZEGRIP) ? 'p' : 'y';
903 		GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
904 		/* restore previous settings */
905 		IntGdiSetTextColor(dc, clrsave);
906 		NtGdiSelectFont(dc, hOldFont);
907 		IntGdiSetBkMode(dc, bkmode);
908 		GreDeleteObject(hFont);
909             return TRUE;
910 	default:
911             return FALSE;
912     }
913     IntDrawRectEdge(dc, r, (uFlags & DFCS_PUSHED) ? EDGE_SUNKEN : EDGE_RAISED, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT);
914     RtlZeroMemory(&lf, sizeof(LOGFONTW));
915     UITOOLS_MakeSquareRect(r, &myr);
916     myr.left += 1;
917     myr.top += 1;
918     myr.right -= 1;
919     myr.bottom -= 1;
920     if(uFlags & DFCS_PUSHED)
921        RECTL_vOffsetRect(&myr,1,1);
922     lf.lfHeight = myr.bottom - myr.top;
923     lf.lfWidth = 0;
924     lf.lfWeight = FW_NORMAL;
925     lf.lfCharSet = DEFAULT_CHARSET;
926     RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
927     hFont = GreCreateFontIndirectW(&lf);
928     /* save font and text color */
929     hOldFont = NtGdiSelectFont(dc, hFont);
930     clrsave = GreGetTextColor(dc);
931     bkmode = GreGetBkMode(dc);
932     /* set color and drawing mode */
933     IntGdiSetBkMode(dc, TRANSPARENT);
934     if(uFlags & DFCS_INACTIVE)
935     {
936         /* draw shadow */
937         IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
938         GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
939     }
940     IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
941     /* draw selected symbol */
942     GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
943     /* restore previous settings */
944     IntGdiSetTextColor(dc, clrsave);
945     NtGdiSelectFont(dc, hOldFont);
946     IntGdiSetBkMode(dc, bkmode);
947     GreDeleteObject(hFont);
948     return TRUE;
949 }
950 
951 BOOL FASTCALL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
952 {
953     // TODO: DFCS_TRANSPARENT upon DFCS_MENUARROWUP or DFCS_MENUARROWDOWN
954     LOGFONTW lf;
955     HFONT hFont, hOldFont;
956     WCHAR Symbol;
957     RECT myr;
958     INT cxy;
959     cxy = UITOOLS_MakeSquareRect(r, &myr);
960     switch(uFlags & 0xff)
961     {
962         case DFCS_MENUARROWUP:
963             Symbol = '5';
964             break;
965 
966         case DFCS_MENUARROWDOWN:
967             Symbol = '6';
968             break;
969 
970         case DFCS_MENUARROW:
971             Symbol = '8';
972             break;
973 
974         case DFCS_MENUARROWRIGHT:
975 	    Symbol = 'w'; // FIXME: needs to confirm
976 	    break;
977 
978         case DFCS_MENUBULLET:
979             Symbol = 'h';
980             break;
981 
982         case DFCS_MENUCHECK:
983             Symbol = 'a';
984             break;
985 
986         default:
987 /*
988             DbgPrint("Invalid menu; flags=0x%04x\n", uFlags);
989 */
990             return FALSE;
991     }
992     /* acquire ressources only if valid menu */
993     RtlZeroMemory(&lf, sizeof(LOGFONTW));
994     lf.lfHeight = cxy;
995     lf.lfWidth = 0;
996     lf.lfWeight = FW_NORMAL;
997     lf.lfCharSet = DEFAULT_CHARSET;
998     RtlCopyMemory(lf.lfFaceName, L"Marlett", sizeof(L"Marlett"));
999     hFont = GreCreateFontIndirectW(&lf);
1000     /* save font */
1001     hOldFont = NtGdiSelectFont(dc, hFont);
1002 
1003     if ((uFlags & 0xff) == DFCS_MENUARROWUP ||
1004         (uFlags & 0xff) == DFCS_MENUARROWDOWN )
1005     {
1006 #if 0
1007        if (uFlags & DFCS_INACTIVE)
1008        {
1009            /* draw shadow */
1010            IntGdiSetTextColor(dc, IntGetSysColor(COLOR_BTNHIGHLIGHT));
1011            GreTextOutW(dc, myr.left + 1, myr.top + 1, &Symbol, 1);
1012        }
1013 #endif
1014        IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
1015     }
1016     /* draw selected symbol */
1017     GreTextOutW(dc, myr.left, myr.top, &Symbol, 1);
1018     /* restore previous settings */
1019     NtGdiSelectFont(dc, hOldFont);
1020     GreDeleteObject(hFont);
1021     return TRUE;
1022 }
1023 
1024 //
1025 //
1026 //	Win32ss API support.
1027 //
1028 //
1029 
1030 
1031 INT WINAPI
1032 FrameRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr)
1033 {
1034     HBRUSH oldbrush;
1035     RECT r = *lprc;
1036 
1037     if ((r.right <= r.left) || (r.bottom <= r.top)) return 0;
1038     if (!(oldbrush = NtGdiSelectBrush(hDC, hbr))) return 0;
1039 
1040     NtGdiPatBlt(hDC, r.left, r.top, 1, r.bottom - r.top, PATCOPY);
1041     NtGdiPatBlt(hDC, r.right - 1, r.top, 1, r.bottom - r.top, PATCOPY);
1042     NtGdiPatBlt(hDC, r.left, r.top, r.right - r.left, 1, PATCOPY);
1043     NtGdiPatBlt(hDC, r.left, r.bottom - 1, r.right - r.left, 1, PATCOPY);
1044 
1045     NtGdiSelectBrush(hDC, oldbrush);
1046     return TRUE;
1047 }
1048 
1049 
1050 INT WINAPI
1051 FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr)
1052 {
1053     BOOL Ret;
1054     HBRUSH prevhbr = NULL;
1055 
1056     /* Select brush if specified */
1057     if (hbr)
1058     {
1059         /* Handle system colors */
1060         if (hbr <= (HBRUSH)(COLOR_MENUBAR + 1))
1061             hbr = IntGetSysColorBrush(PtrToUlong(hbr) - 1);
1062 
1063         prevhbr = NtGdiSelectBrush(hDC, hbr);
1064         if (prevhbr == NULL)
1065             return (INT)FALSE;
1066     }
1067 
1068     Ret = NtGdiPatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left,
1069                  lprc->bottom - lprc->top, PATCOPY);
1070 
1071     /* Select old brush */
1072     if (prevhbr)
1073         NtGdiSelectBrush(hDC, prevhbr);
1074 
1075     return (INT)Ret;
1076 }
1077 
1078 BOOL WINAPI
1079 DrawEdge(HDC hDC, LPRECT rc, UINT edge, UINT flags)
1080 {
1081     if (flags & BF_DIAGONAL)
1082        return IntDrawDiagEdge(hDC, rc, edge, flags);
1083     else
1084        return IntDrawRectEdge(hDC, rc, edge, flags);
1085 }
1086 
1087 BOOL WINAPI
1088 DrawFrameControl(HDC hDC, LPRECT rc, UINT uType, UINT uState)
1089 {
1090     if (GreGetMapMode(hDC) != MM_TEXT)
1091         return FALSE;
1092 
1093     switch(uType)
1094     {
1095         case DFC_BUTTON:
1096             return UITOOLS95_DrawFrameButton(hDC, rc, uState);
1097         case DFC_CAPTION:
1098             return UITOOLS95_DrawFrameCaption(hDC, rc, uState);
1099         case DFC_MENU:
1100             return UITOOLS95_DrawFrameMenu(hDC, rc, uState);
1101 #if 0
1102         case DFC_POPUPMENU:
1103             UNIMPLEMENTED;
1104             break;
1105 #endif
1106         case DFC_SCROLL:
1107             return UITOOLS95_DrawFrameScroll(hDC, rc, uState);
1108     }
1109     return FALSE;
1110 }
1111 
1112