6713bbc1ceb88524407993aed30f360c17250ad6
[reactos.git] / lib / user32 / windows / draw.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /* $Id$
20  *
21  * PROJECT:         ReactOS user32.dll
22  * FILE:            lib/user32/windows/input.c
23  * PURPOSE:         Input
24  * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
25  * UPDATE HISTORY:
26  *      09-05-2001  CSH  Created
27  */
28
29 /* INCLUDES ******************************************************************/
30
31 #include <windows.h>
32 #include <user32.h>
33 #include <debug.h>
34
35 /* GLOBALS *******************************************************************/
36
37 #define COLOR_MAX (28)
38
39 /* HPEN STDCALL W32kGetSysColorPen(int nIndex); */
40
41 static const WORD wPattern_AA55[8] = { 0xaaaa, 0x5555, 0xaaaa, 0x5555,
42                                        0xaaaa, 0x5555, 0xaaaa, 0x5555 };
43
44 /* These tables are used in:
45  * UITOOLS_DrawDiagEdge()
46  * UITOOLS_DrawRectEdge()
47  */
48 static const signed char LTInnerNormal[] = {
49     -1,           -1,                 -1,                 -1,
50     -1,           COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1,
51     -1,           COLOR_3DDKSHADOW,   COLOR_3DDKSHADOW,   -1,
52     -1,           -1,                 -1,                 -1
53 };
54
55 static const signed char LTOuterNormal[] = {
56     -1,                 COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1,
57     COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1,
58     COLOR_3DDKSHADOW,   COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1,
59     -1,                 COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1
60 };
61
62 static const signed char RBInnerNormal[] = {
63     -1,           -1,                -1,              -1,
64     -1,           COLOR_BTNSHADOW,   COLOR_BTNSHADOW, -1,
65     -1,           COLOR_3DLIGHT,     COLOR_3DLIGHT,   -1,
66     -1,           -1,                -1,              -1
67 };
68
69 static const signed char RBOuterNormal[] = {
70     -1,              COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1,
71     COLOR_BTNSHADOW, COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1,
72     COLOR_3DLIGHT,   COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1,
73     -1,              COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1
74 };
75
76 static const signed char LTInnerSoft[] = {
77     -1,                  -1,                -1,              -1,
78     -1,                  COLOR_3DLIGHT,     COLOR_3DLIGHT,   -1,
79     -1,                  COLOR_BTNSHADOW,   COLOR_BTNSHADOW, -1,
80     -1,                  -1,                -1,              -1
81 };
82
83 static const signed char LTOuterSoft[] = {
84     -1,              COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
85     COLOR_3DLIGHT,   COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
86     COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
87     -1,              COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1
88 };
89
90 #define RBInnerSoft RBInnerNormal   /* These are the same */
91 #define RBOuterSoft RBOuterNormal
92
93 static const signed char LTRBOuterMono[] = {
94     -1,           COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
95     COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
96     COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
97     COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
98 };
99
100 static const signed char LTRBInnerMono[] = {
101     -1, -1,           -1,           -1,
102     -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
103     -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
104     -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
105 };
106
107 static const signed char LTRBOuterFlat[] = {
108     -1,                COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
109     COLOR_BTNFACE,     COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
110     COLOR_BTNFACE,     COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
111     COLOR_BTNFACE,     COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
112 };
113
114 static const signed char LTRBInnerFlat[] = {
115     -1, -1,              -1,              -1,
116     -1, COLOR_BTNFACE,     COLOR_BTNFACE,     COLOR_BTNFACE,
117     -1, COLOR_BTNFACE,     COLOR_BTNFACE,     COLOR_BTNFACE,
118     -1, COLOR_BTNFACE,     COLOR_BTNFACE,     COLOR_BTNFACE,
119 };
120 /* FUNCTIONS *****************************************************************/
121
122
123 HPEN STDCALL GetSysColorPen(int nIndex);
124 HBRUSH STDCALL GetSysColorBrush(int nIndex);
125
126 /* Ported from WINE20020904 */
127 /* Same as DrawEdge invoked with BF_DIAGONAL */
128 static BOOL UITOOLS95_DrawDiagEdge(HDC hdc, LPRECT rc,
129                                      UINT uType, UINT uFlags)
130 {
131     POINT Points[4];
132     signed char InnerI, OuterI;
133     HPEN InnerPen, OuterPen;
134     POINT SavePoint;
135     HPEN SavePen;
136     int spx, spy;
137     int epx, epy;
138     int Width = rc->right - rc->left;
139     int Height= rc->bottom - rc->top;
140     int SmallDiam = Width > Height ? Height : Width;
141     BOOL retval = !(   ((uType & BDR_INNER) == BDR_INNER
142                        || (uType & BDR_OUTER) == BDR_OUTER)
143                       && !(uFlags & (BF_FLAT|BF_MONO)) );
144     int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
145             + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
146
147     /* Init some vars */
148     OuterPen = InnerPen = (HPEN)GetStockObject(NULL_PEN);
149     SavePen = (HPEN)SelectObject(hdc, InnerPen);
150     spx = spy = epx = epy = 0; /* Satisfy the compiler... */
151
152     /* Determine the colors of the edges */
153     if(uFlags & BF_MONO)
154     {
155         InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
156         OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
157     }
158     else if(uFlags & BF_FLAT)
159     {
160         InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
161         OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
162     }
163     else if(uFlags & BF_SOFT)
164     {
165         if(uFlags & BF_BOTTOM)
166         {
167             InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
168             OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
169         }
170         else
171         {
172             InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
173             OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
174         }
175     }
176     else
177     {
178         if(uFlags & BF_BOTTOM)
179         {
180             InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
181             OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
182         }
183         else
184         {
185             InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
186             OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
187         }
188     }
189
190     if(InnerI != -1) InnerPen = GetSysColorPen(InnerI);
191     if(OuterI != -1) OuterPen = GetSysColorPen(OuterI);
192
193     MoveToEx(hdc, 0, 0, &SavePoint);
194
195     /* Don't ask me why, but this is what is visible... */
196     /* This must be possible to do much simpler, but I fail to */
197     /* see the logic in the MS implementation (sigh...). */
198     /* So, this might look a bit brute force here (and it is), but */
199     /* it gets the job done;) */
200
201     switch(uFlags & BF_RECT)
202     {
203     case 0:
204     case BF_LEFT:
205     case BF_BOTTOM:
206     case BF_BOTTOMLEFT:
207         /* Left bottom endpoint */
208         epx = rc->left-1;
209         spx = epx + SmallDiam;
210         epy = rc->bottom;
211         spy = epy - SmallDiam;
212         break;
213
214     case BF_TOPLEFT:
215     case BF_BOTTOMRIGHT:
216         /* Left top endpoint */
217         epx = rc->left-1;
218         spx = epx + SmallDiam;
219         epy = rc->top-1;
220         spy = epy + SmallDiam;
221         break;
222
223     case BF_TOP:
224     case BF_RIGHT:
225     case BF_TOPRIGHT:
226     case BF_RIGHT|BF_LEFT:
227     case BF_RIGHT|BF_LEFT|BF_TOP:
228     case BF_BOTTOM|BF_TOP:
229     case BF_BOTTOM|BF_TOP|BF_LEFT:
230     case BF_BOTTOMRIGHT|BF_LEFT:
231     case BF_BOTTOMRIGHT|BF_TOP:
232     case BF_RECT:
233         /* Right top endpoint */
234         spx = rc->left;
235         epx = spx + SmallDiam;
236         spy = rc->bottom-1;
237         epy = spy - SmallDiam;
238         break;
239     }
240
241     MoveToEx(hdc, spx, spy, NULL);
242     SelectObject(hdc, OuterPen);
243     LineTo(hdc, epx, epy);
244
245     SelectObject(hdc, InnerPen);
246
247     switch(uFlags & (BF_RECT|BF_DIAGONAL))
248     {
249     case BF_DIAGONAL_ENDBOTTOMLEFT:
250     case (BF_DIAGONAL|BF_BOTTOM):
251     case BF_DIAGONAL:
252     case (BF_DIAGONAL|BF_LEFT):
253         MoveToEx(hdc, spx-1, spy, NULL);
254         LineTo(hdc, epx, epy-1);
255         Points[0].x = spx-add;
256         Points[0].y = spy;
257         Points[1].x = rc->left;
258         Points[1].y = rc->top;
259         Points[2].x = epx+1;
260         Points[2].y = epy-1-add;
261         Points[3] = Points[2];
262         break;
263
264     case BF_DIAGONAL_ENDBOTTOMRIGHT:
265         MoveToEx(hdc, spx-1, spy, NULL);
266         LineTo(hdc, epx, epy+1);
267         Points[0].x = spx-add;
268         Points[0].y = spy;
269         Points[1].x = rc->left;
270         Points[1].y = rc->bottom-1;
271         Points[2].x = epx+1;
272         Points[2].y = epy+1+add;
273         Points[3] = Points[2];
274         break;
275
276     case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP):
277     case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT):
278     case BF_DIAGONAL_ENDTOPRIGHT:
279     case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT):
280         MoveToEx(hdc, spx+1, spy, NULL);
281         LineTo(hdc, epx, epy+1);
282         Points[0].x = epx-1;
283         Points[0].y = epy+1+add;
284         Points[1].x = rc->right-1;
285         Points[1].y = rc->top+add;
286         Points[2].x = rc->right-1;
287         Points[2].y = rc->bottom-1;
288         Points[3].x = spx+add;
289         Points[3].y = spy;
290         break;
291
292     case BF_DIAGONAL_ENDTOPLEFT:
293         MoveToEx(hdc, spx, spy-1, NULL);
294         LineTo(hdc, epx+1, epy);
295         Points[0].x = epx+1+add;
296         Points[0].y = epy+1;
297         Points[1].x = rc->right-1;
298         Points[1].y = rc->top;
299         Points[2].x = rc->right-1;
300         Points[2].y = rc->bottom-1-add;
301         Points[3].x = spx;
302         Points[3].y = spy-add;
303         break;
304
305     case (BF_DIAGONAL|BF_TOP):
306     case (BF_DIAGONAL|BF_BOTTOM|BF_TOP):
307     case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT):
308         MoveToEx(hdc, spx+1, spy-1, NULL);
309         LineTo(hdc, epx, epy);
310         Points[0].x = epx-1;
311         Points[0].y = epy+1;
312         Points[1].x = rc->right-1;
313         Points[1].y = rc->top;
314         Points[2].x = rc->right-1;
315         Points[2].y = rc->bottom-1-add;
316         Points[3].x = spx+add;
317         Points[3].y = spy-add;
318         break;
319
320     case (BF_DIAGONAL|BF_RIGHT):
321     case (BF_DIAGONAL|BF_RIGHT|BF_LEFT):
322     case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM):
323         MoveToEx(hdc, spx, spy, NULL);
324         LineTo(hdc, epx-1, epy+1);
325         Points[0].x = spx;
326         Points[0].y = spy;
327         Points[1].x = rc->left;
328         Points[1].y = rc->top+add;
329         Points[2].x = epx-1-add;
330         Points[2].y = epy+1+add;
331         Points[3] = Points[2];
332         break;
333     }
334
335     /* Fill the interior if asked */
336     if((uFlags & BF_MIDDLE) && retval)
337     {
338         HBRUSH hbsave;
339         HBRUSH hb = GetSysColorBrush(uFlags & BF_MONO ? COLOR_WINDOW : COLOR_BTNFACE);
340         HPEN hpsave;
341         HPEN hp = GetSysColorPen(uFlags & BF_MONO ? COLOR_WINDOW : COLOR_BTNFACE);
342         hbsave = (HBRUSH)SelectObject(hdc, hb);
343         hpsave = (HPEN)SelectObject(hdc, hp);
344         Polygon(hdc, Points, 4);
345         SelectObject(hdc, hbsave);
346         SelectObject(hdc, hpsave);
347     }
348
349     /* Adjust rectangle if asked */
350     if(uFlags & BF_ADJUST)
351     {
352         if(uFlags & BF_LEFT)   rc->left   += add;
353         if(uFlags & BF_RIGHT)  rc->right  -= add;
354         if(uFlags & BF_TOP)    rc->top    += add;
355         if(uFlags & BF_BOTTOM) rc->bottom -= add;
356     }
357
358     /* Cleanup */
359     SelectObject(hdc, SavePen);
360     MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
361
362     return retval;
363 }
364
365 /* Ported from WINE20020904 */
366 /* Same as DrawEdge invoked without BF_DIAGONAL
367  *
368  * 23-Nov-1997: Changed by Bertho Stultiens
369  *
370  * Well, I started testing this and found out that there are a few things
371  * that weren't quite as win95. The following rewrite should reproduce
372  * win95 results completely.
373  * The colorselection is table-driven to avoid awfull if-statements.
374  * The table below show the color settings.
375  *
376  * Pen selection table for uFlags = 0
377  *
378  * uType |  LTI  |  LTO  |  RBI  |  RBO
379  * ------+-------+-------+-------+-------
380  *  0000 |   x   |   x   |   x   |   x
381  *  0001 |   x   |  22   |   x   |  21
382  *  0010 |   x   |  16   |   x   |  20
383  *  0011 |   x   |   x   |   x   |   x
384  * ------+-------+-------+-------+-------
385  *  0100 |   x   |  20   |   x   |  16
386  *  0101 |  20   |  22   |  16   |  21
387  *  0110 |  20   |  16   |  16   |  20
388  *  0111 |   x   |   x   |   x   |   x
389  * ------+-------+-------+-------+-------
390  *  1000 |   x   |  21   |   x   |  22
391  *  1001 |  21   |  22   |  22   |  21
392  *  1010 |  21   |  16   |  22   |  20
393  *  1011 |   x   |   x   |   x   |   x
394  * ------+-------+-------+-------+-------
395  *  1100 |   x   |   x   |   x   |   x
396  *  1101 |   x   | x (22)|   x   | x (21)
397  *  1110 |   x   | x (16)|   x   | x (20)
398  *  1111 |   x   |   x   |   x   |   x
399  *
400  * Pen selection table for uFlags = BF_SOFT
401  *
402  * uType |  LTI  |  LTO  |  RBI  |  RBO
403  * ------+-------+-------+-------+-------
404  *  0000 |   x   |   x   |   x   |   x
405  *  0001 |   x   |  20   |   x   |  21
406  *  0010 |   x   |  21   |   x   |  20
407  *  0011 |   x   |   x   |   x   |   x
408  * ------+-------+-------+-------+-------
409  *  0100 |   x   |  22   |   x   |  16
410  *  0101 |  22   |  20   |  16   |  21
411  *  0110 |  22   |  21   |  16   |  20
412  *  0111 |   x   |   x   |   x   |   x
413  * ------+-------+-------+-------+-------
414  *  1000 |   x   |  16   |   x   |  22
415  *  1001 |  16   |  20   |  22   |  21
416  *  1010 |  16   |  21   |  22   |  20
417  *  1011 |   x   |   x   |   x   |   x
418  * ------+-------+-------+-------+-------
419  *  1100 |   x   |   x   |   x   |   x
420  *  1101 |   x   | x (20)|   x   | x (21)
421  *  1110 |   x   | x (21)|   x   | x (20)
422  *  1111 |   x   |   x   |   x   |   x
423  *
424  * x = don't care; (n) = is what win95 actually uses
425  * LTI = left Top Inner line
426  * LTO = left Top Outer line
427  * RBI = Right Bottom Inner line
428  * RBO = Right Bottom Outer line
429  * 15 = COLOR_BTNFACE
430  * 16 = COLOR_BTNSHADOW
431  * 20 = COLOR_BTNHIGHLIGHT
432  * 21 = COLOR_3DDKSHADOW
433  * 22 = COLOR_3DLIGHT
434  */
435 static BOOL UITOOLS95_DrawRectEdge(HDC hdc, LPRECT rc,
436                                      UINT uType, UINT uFlags)
437 {
438     signed char LTInnerI, LTOuterI;
439     signed char RBInnerI, RBOuterI;
440     HPEN LTInnerPen, LTOuterPen;
441     HPEN RBInnerPen, RBOuterPen;
442     RECT InnerRect = *rc;
443     POINT SavePoint;
444     HPEN SavePen;
445     int LBpenplus = 0;
446     int LTpenplus = 0;
447     int RTpenplus = 0;
448     int RBpenplus = 0;
449     BOOL retval = !(   ((uType & BDR_INNER) == BDR_INNER
450                        || (uType & BDR_OUTER) == BDR_OUTER)
451                       && !(uFlags & (BF_FLAT|BF_MONO)) );
452     /* Init some vars */
453     LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN)GetStockObject(NULL_PEN);
454     SavePen = (HPEN)SelectObject(hdc, LTInnerPen);
455
456     /* Determine the colors of the edges */
457     if(uFlags & BF_MONO)
458     {
459         LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
460         LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
461     }
462     else if(uFlags & BF_FLAT)
463     {
464         LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
465         LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
466
467         /* Bertho Stultiens states above that this function exactly matches win95
468          * In win98 BF_FLAT rectangles have an inner border same color as the
469          * middle (COLOR_BTNFACE). I believe it's the same for win95 but since
470          * I don't know I go with Bertho and just sets it for win98 until proven
471          * otherwise.
472          *                                          Dennis Björklund, 10 June, 99
473          */
474 /*      if( TWEAK_WineLook == WIN98_LOOK && LTInnerI != -1 ) */
475             LTInnerI = RBInnerI = COLOR_BTNFACE;
476     }
477     else if(uFlags & BF_SOFT)
478     {
479         LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
480         LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
481         RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
482         RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
483     }
484     else
485     {
486         LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
487         LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
488         RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
489         RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
490     }
491
492     if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT)   LBpenplus = 1;
493     if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT)       RTpenplus = 1;
494     if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT) RBpenplus = 1;
495     if((uFlags & BF_TOPLEFT) == BF_TOPLEFT)         LTpenplus = 1;
496
497     if(LTInnerI != -1) LTInnerPen = GetSysColorPen(LTInnerI);
498     if(LTOuterI != -1) LTOuterPen = GetSysColorPen(LTOuterI);
499     if(RBInnerI != -1) RBInnerPen = GetSysColorPen(RBInnerI);
500     if(RBOuterI != -1) RBOuterPen = GetSysColorPen(RBOuterI);
501     if((uFlags & BF_MIDDLE) && retval)
502         {
503             FillRect(hdc, &InnerRect, GetSysColorBrush(uFlags & BF_MONO ?
504                          COLOR_WINDOW : COLOR_BTNFACE));
505         }
506     MoveToEx(hdc, 0, 0, &SavePoint);
507
508     /* Draw the outer edge */
509     SelectObject(hdc, LTOuterPen);
510     if(uFlags & BF_TOP)
511     {
512         MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
513         LineTo(hdc, InnerRect.right, InnerRect.top);
514     }
515     if(uFlags & BF_LEFT)
516     {
517         MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
518         LineTo(hdc, InnerRect.left, InnerRect.bottom);
519     }
520     SelectObject(hdc, RBOuterPen);
521     if(uFlags & BF_BOTTOM)
522     {
523         MoveToEx(hdc, InnerRect.right, InnerRect.bottom-1, NULL);
524         LineTo(hdc, InnerRect.left, InnerRect.bottom-1);
525     }
526     if(uFlags & BF_RIGHT)
527     {
528         MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom, NULL);
529         LineTo(hdc, InnerRect.right-1, InnerRect.top);
530     }
531
532     /* Draw the inner edge */
533     SelectObject(hdc, LTInnerPen);
534     if(uFlags & BF_TOP)
535     {
536         MoveToEx(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL);
537         LineTo(hdc, InnerRect.right-RTpenplus, InnerRect.top+1);
538     }
539     if(uFlags & BF_LEFT)
540     {
541         MoveToEx(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL);
542         LineTo(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus);
543     }
544     SelectObject(hdc, RBInnerPen);
545     if(uFlags & BF_BOTTOM)
546     {
547         MoveToEx(hdc, InnerRect.right-RBpenplus, InnerRect.bottom-2, NULL);
548         LineTo(hdc, InnerRect.left+LBpenplus, InnerRect.bottom-2);
549     }
550     if(uFlags & BF_RIGHT)
551     {
552         MoveToEx(hdc, InnerRect.right-2, InnerRect.bottom-RBpenplus, NULL);
553         LineTo(hdc, InnerRect.right-2, InnerRect.top+RTpenplus);
554     }
555
556     if( ((uFlags & BF_MIDDLE) && retval) || (uFlags & BF_ADJUST) )
557     {
558         int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
559                 + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
560
561         if(uFlags & BF_LEFT)   InnerRect.left   += add;
562         if(uFlags & BF_RIGHT)  InnerRect.right  -= add;
563         if(uFlags & BF_TOP)    InnerRect.top    += add;
564         if(uFlags & BF_BOTTOM) InnerRect.bottom -= add;
565
566         if(uFlags & BF_ADJUST)
567             *rc = InnerRect;
568     }
569
570     /* Cleanup */
571     SelectObject(hdc, SavePen);
572     MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
573     return retval;
574 }
575
576 /* Ported from WINE20020904 */
577 /* Utility to create a square rectangle and returning the width */
578 static int UITOOLS_MakeSquareRect(LPRECT src, LPRECT dst)
579 {
580     int Width  = src->right - src->left;
581     int Height = src->bottom - src->top;
582     int SmallDiam = Width > Height ? Height : Width;
583
584     *dst = *src;
585
586     /* Make it a square box */
587     if(Width < Height)      /* SmallDiam == Width */
588     {
589         dst->top += (Height-Width)/2;
590         dst->bottom = dst->top + SmallDiam;
591     }
592     else if(Width > Height) /* SmallDiam == Height */
593     {
594         dst->left += (Width-Height)/2;
595         dst->right = dst->left + SmallDiam;
596     }
597
598    return SmallDiam;
599 }
600
601 /* Ported from WINE20020904 */
602 static void UITOOLS_DrawCheckedRect( HDC dc, LPRECT rect )
603 {
604     if(GetSysColor(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255))
605     {
606       HBITMAP hbm = CreateBitmap(8, 8, 1, 1, wPattern_AA55);
607       HBRUSH hbsave;
608       HBRUSH hb = CreatePatternBrush(hbm);
609       COLORREF bg;
610
611       FillRect(dc, rect, GetSysColorBrush(COLOR_BTNFACE));
612       bg = SetBkColor(dc, RGB(255, 255, 255));
613       hbsave = (HBRUSH)SelectObject(dc, hb);
614       PatBlt(dc, rect->left, rect->top, rect->right-rect->left, rect->bottom-rect->top, 0x00FA0089);
615       SelectObject(dc, hbsave);
616       SetBkColor(dc, bg);
617       DeleteObject(hb);
618       DeleteObject(hbm);
619     }
620     else
621     {
622         FillRect(dc, rect, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
623     }
624 }
625
626 /* Ported from WINE20020904 */
627 /* Draw a push button coming from DrawFrameControl()
628  *
629  * Does a pretty good job in emulating MS behavior. Some quirks are
630  * however there because MS uses a TrueType font (Marlett) to draw
631  * the buttons.
632  */
633 static BOOL UITOOLS95_DFC_ButtonPush(HDC dc, LPRECT r, UINT uFlags)
634 {
635     UINT edge;
636     RECT myr = *r;
637
638     if(uFlags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT))
639         edge = EDGE_SUNKEN;
640     else
641         edge = EDGE_RAISED;
642
643     if(uFlags & DFCS_CHECKED)
644     {
645         if(uFlags & DFCS_MONO)
646             UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
647         else
648             UITOOLS95_DrawRectEdge(dc, &myr, edge, (uFlags&DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST);
649
650         UITOOLS_DrawCheckedRect( dc, &myr );
651         }
652         else
653         {
654         if(uFlags & DFCS_MONO)
655         {
656             UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
657             FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE));
658         }
659         else
660         {
661             UITOOLS95_DrawRectEdge(dc, r, edge, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT);
662         }
663     }
664
665     /* Adjust rectangle if asked */
666     if(uFlags & DFCS_ADJUSTRECT)
667     {
668         r->left   += 2;
669         r->right  -= 2;
670         r->top    += 2;
671         r->bottom -= 2;
672     }
673
674     return TRUE;
675 }
676
677 /* Ported from WINE20020904 */
678 /* Draw a check/3state button coming from DrawFrameControl()
679  *
680  * Does a pretty good job in emulating MS behavior. Some quirks are
681  * however there because MS uses a TrueType font (Marlett) to draw
682  * the buttons.
683  */
684 static BOOL UITOOLS95_DFC_ButtonCheck(HDC dc, LPRECT r, UINT uFlags)
685 {
686     RECT myr, bar;
687     UINT flags = BF_RECT | BF_ADJUST;
688     UITOOLS_MakeSquareRect(r, &myr);
689
690     if(uFlags & DFCS_FLAT) flags |= BF_FLAT;
691     else if(uFlags & DFCS_MONO) flags |= BF_MONO;
692
693     UITOOLS95_DrawRectEdge( dc, &myr, EDGE_SUNKEN, flags );
694
695     if(uFlags & (DFCS_INACTIVE|DFCS_PUSHED))
696         FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE));
697     else if( (uFlags & DFCS_BUTTON3STATE) && (uFlags & DFCS_CHECKED) )
698         UITOOLS_DrawCheckedRect( dc, &myr );
699     else
700     {
701         FillRect(dc, &myr, GetSysColorBrush(COLOR_WINDOW));
702     }
703
704     if(uFlags & DFCS_CHECKED)
705     {
706         int i, k;
707         i = (uFlags & DFCS_INACTIVE) || (uFlags & 0xff) == DFCS_BUTTON3STATE ?
708                 COLOR_BTNSHADOW : COLOR_WINDOWTEXT;
709
710         /* draw 7 bars, with h=3w to form the check */
711         bar.left = myr.left;
712         bar.top = myr.top + 2;
713         for (k = 0; k < 7; k++) {
714             bar.left = bar.left + 1;
715             bar.top = (k < 3) ? bar.top + 1 : bar.top - 1;
716             bar.bottom = bar.top + 3;
717             bar.right = bar.left + 1;
718             FillRect(dc, &bar, GetSysColorBrush(i));
719         }
720     }
721     return TRUE;
722 }
723
724 /* Ported from WINE20020904 */
725 /* Draw a radio/radioimage/radiomask button coming from DrawFrameControl()
726  *
727  * Does a pretty good job in emulating MS behavior. Some quirks are
728  * however there because MS uses a TrueType font (Marlett) to draw
729  * the buttons.
730  */
731 static BOOL UITOOLS95_DFC_ButtonRadio(HDC dc, LPRECT r, UINT uFlags)
732 {
733     RECT myr;
734     int i;
735     int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
736     int BorderShrink = SmallDiam / 16;
737     HPEN hpsave;
738     HBRUSH hbsave;
739     int xc, yc;
740
741     if(BorderShrink < 1) BorderShrink = 1;
742
743     if((uFlags & 0xff) == DFCS_BUTTONRADIOIMAGE)
744     {
745         FillRect(dc, r, (HBRUSH)GetStockObject(BLACK_BRUSH));
746     }
747
748     xc = myr.left + SmallDiam - SmallDiam/2;
749     yc = myr.top  + SmallDiam - SmallDiam/2;
750
751     /* Define bounding box */
752     i = 14*SmallDiam/16;
753     myr.left   = xc - i+i/2;
754     myr.right  = xc + i/2;
755     myr.top    = yc - i+i/2;
756     myr.bottom = yc + i/2;
757
758     if((uFlags & 0xff) == DFCS_BUTTONRADIOMASK)
759     {
760         hbsave = (HBRUSH)SelectObject(dc, GetStockObject(BLACK_BRUSH));
761         Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom);
762         SelectObject(dc, hbsave);
763     }
764     else
765     {
766         if(uFlags & (DFCS_FLAT|DFCS_MONO))
767         {
768             hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_WINDOWFRAME));
769             hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_WINDOWFRAME));
770             Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom);
771             SelectObject(dc, hbsave);
772             SelectObject(dc, hpsave);
773         }
774         else
775         {
776             hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT));
777             hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
778             Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.left-1, myr.bottom, myr.right+1, myr.top);
779
780             SelectObject(dc, GetSysColorPen(COLOR_BTNSHADOW));
781             SelectObject(dc, GetSysColorBrush(COLOR_BTNSHADOW));
782             Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.right+1, myr.top, myr.left-1, myr.bottom);
783
784             myr.left   += BorderShrink;
785             myr.right  -= BorderShrink;
786             myr.top    += BorderShrink;
787             myr.bottom -= BorderShrink;
788
789             SelectObject(dc, GetSysColorPen(COLOR_3DLIGHT));
790             SelectObject(dc, GetSysColorBrush(COLOR_3DLIGHT));
791             Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.left-1, myr.bottom, myr.right+1, myr.top);
792
793             SelectObject(dc, GetSysColorPen(COLOR_3DDKSHADOW));
794             SelectObject(dc, GetSysColorBrush(COLOR_3DDKSHADOW));
795             Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.right+1, myr.top, myr.left-1, myr.bottom);
796             SelectObject(dc, hbsave);
797             SelectObject(dc, hpsave);
798         }
799
800         i = 10*SmallDiam/16;
801         myr.left   = xc - i+i/2;
802         myr.right  = xc + i/2;
803         myr.top    = yc - i+i/2;
804         myr.bottom = yc + i/2;
805         i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE;
806         hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
807         hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
808         Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom);
809         SelectObject(dc, hbsave);
810         SelectObject(dc, hpsave);
811     }
812
813     if(uFlags & DFCS_CHECKED)
814     {
815         i = 6*SmallDiam/16;
816         i = i < 1 ? 1 : i;
817         myr.left   = xc - i+i/2;
818         myr.right  = xc + i/2;
819         myr.top    = yc - i+i/2;
820         myr.bottom = yc + i/2;
821
822         i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT;
823         hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
824         hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
825         Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom);
826         SelectObject(dc, hpsave);
827         SelectObject(dc, hbsave);
828     }
829
830     /* FIXME: M$ has a Polygon in the center at relative points: */
831     /* 0.476, 0.476 (times SmallDiam, SmallDiam) */
832     /* 0.476, 0.525 */
833     /* 0.500, 0.500 */
834     /* 0.500, 0.499 */
835     /* when the button is unchecked. The reason for it is unknown. The */
836     /* color is COLOR_BTNHIGHLIGHT, although the Polygon gets painted at */
837     /* least 3 times (it looks like a clip-region when you see it happen). */
838     /* I do not really see a reason why this should be implemented. If you */
839     /* have a good reason, let me know. Maybe this is a quirk in the Marlett */
840     /* font. */
841
842     return TRUE;
843 }
844
845 /* Ported from WINE20020904 */
846 static BOOL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState)
847 {
848     switch(uState & 0xff)
849     {
850     case DFCS_BUTTONPUSH:
851         return UITOOLS95_DFC_ButtonPush(hdc, rc, uState);
852
853     case DFCS_BUTTONCHECK:
854     case DFCS_BUTTON3STATE:
855         return UITOOLS95_DFC_ButtonCheck(hdc, rc, uState);
856
857     case DFCS_BUTTONRADIOIMAGE:
858     case DFCS_BUTTONRADIOMASK:
859     case DFCS_BUTTONRADIO:
860         return UITOOLS95_DFC_ButtonRadio(hdc, rc, uState);
861
862     default:
863         DbgPrint("Invalid button state=0x%04x\n", uState);
864     }
865
866     return FALSE;
867 }
868
869 /* Ported from WINE20020904 */
870 /* Draw caption buttons (win95), coming from DrawFrameControl() */
871 static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags)
872 {
873     POINT Line1[10];
874     POINT Line2[10];
875     int Line1N;
876     int Line2N;
877     RECT myr;
878     int SmallDiam = UITOOLS_MakeSquareRect(r, &myr)-2;
879     int i;
880     HBRUSH hbsave;
881     HPEN hpsave;
882     HFONT hfsave, hf;
883     int colorIdx = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT;
884     int xc = (myr.left+myr.right)/2;
885     int yc = (myr.top+myr.bottom)/2;
886     int edge, move;
887     char str[2] = "?";
888     UINT alignsave;
889     int bksave;
890     COLORREF clrsave;
891     SIZE size;
892
893     //UITOOLS95_DFC_ButtonPush(dc, r, uFlags & 0xff00);
894     if(uFlags & DFCS_PUSHED)
895       UITOOLS95_DrawRectEdge(dc,r,EDGE_SUNKEN, BF_RECT | BF_MIDDLE | BF_SOFT);
896     else
897       UITOOLS95_DrawRectEdge(dc,r,BDR_RAISEDINNER | BDR_RAISEDOUTER, BF_RECT |
898                                BF_SOFT | BF_MIDDLE);
899
900     switch(uFlags & 0xff)
901     {
902     case DFCS_CAPTIONCLOSE:
903     {
904         /* The "X" is made by drawing a series of lines.
905          * The number of lines drawn depends on the size
906          * of the bounding rect.  e.g. For a 6x5 inside rect,
907          * two lines are drawn from top-left to bottom-right,
908          * and two lines from top-right to bottom-left.
909          *
910          * 0 1 2 3 4 5       0 1 2 3 4 5
911          * 1 * *                     * *
912          * 2   * *                 * *
913          * 3     * *             * *
914          * 4       * *         * *
915          *
916          * Drawing one line for every 6 pixels in width
917          * seems to provide the best proportions.
918          */
919
920         POINT start, oldPos;
921         INT width = myr.right - myr.left - 5;
922         INT height = myr.bottom - myr.top - 6;
923         INT numLines = (width / 6) + 1;
924
925         hpsave = (HPEN)SelectObject(dc, GetSysColorPen(colorIdx));
926
927         start.x = myr.left + 2;
928         start.y = myr.top + 2;
929
930         if (width < 6)
931             height = width;
932         else
933             start.y++;
934
935         if (uFlags & DFCS_PUSHED)
936         {
937             start.x++;
938                         start.y++;
939         }
940
941         width -= numLines - 1;
942
943         for (i = 0; i < numLines; i++)
944         {
945             MoveToEx(dc, start.x + i, start.y, &oldPos);
946             LineTo(dc, start.x + i + width, start.y + height);
947
948             MoveToEx(dc, start.x + i, start.y + height, &oldPos);
949             LineTo(dc, start.x + i + width, start.y);
950         }
951
952         SelectObject(dc, hpsave);
953         
954         return TRUE;
955     }
956
957     case DFCS_CAPTIONHELP:
958         /* This one breaks the flow */
959         /* FIXME: We need the Marlett font in order to get this right. */
960
961         hf = CreateFontA(-SmallDiam, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
962                          ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
963                          DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, "System");
964         alignsave = SetTextAlign(dc, TA_TOP|TA_LEFT);
965         bksave = SetBkMode(dc, TRANSPARENT);
966         clrsave = GetTextColor(dc);
967         hfsave = (HFONT)SelectObject(dc, hf);
968         GetTextExtentPoint32A(dc, str, 1, &size);
969
970         if(uFlags & DFCS_INACTIVE)
971         {
972             SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT));
973             TextOutA(dc, xc-size.cx/2+1, yc-size.cy/2+1, str, 1);
974         }
975         SetTextColor(dc, GetSysColor(colorIdx));
976         TextOutA(dc, xc-size.cx/2, yc-size.cy/2, str, 1);
977
978         SelectObject(dc, hfsave);
979         SetTextColor(dc, clrsave);
980         SetBkMode(dc, bksave);
981         SetTextAlign(dc, alignsave);
982         DeleteObject(hf);
983         return TRUE;
984
985     case DFCS_CAPTIONMIN:
986         Line1[0].x = Line1[3].x = myr.left   +  96*SmallDiam/750+2;
987         Line1[1].x = Line1[2].x = Line1[0].x + 372*SmallDiam/750;
988         Line1[0].y = Line1[1].y = myr.top    + 563*SmallDiam/750+1;
989         Line1[2].y = Line1[3].y = Line1[0].y +  92*SmallDiam/750;
990         Line1N = 4;
991         Line2N = 0;
992         break;
993
994     case DFCS_CAPTIONMAX:
995         edge = 47*SmallDiam/750;
996         Line1[0].x = Line1[5].x = myr.left +  57*SmallDiam/750+3;
997         Line1[0].y = Line1[1].y = myr.top  + 143*SmallDiam/750+1;
998         Line1[1].x = Line1[2].x = Line1[0].x + 562*SmallDiam/750;
999         Line1[5].y = Line1[4].y = Line1[0].y +  93*SmallDiam/750;
1000         Line1[2].y = Line1[3].y = Line1[0].y + 513*SmallDiam/750;
1001         Line1[3].x = Line1[4].x = Line1[1].x -  edge;
1002
1003         Line2[0].x = Line2[5].x = Line1[0].x;
1004         Line2[3].x = Line2[4].x = Line1[1].x;
1005         Line2[1].x = Line2[2].x = Line1[0].x + edge;
1006         Line2[0].y = Line2[1].y = Line1[0].y;
1007         Line2[4].y = Line2[5].y = Line1[2].y;
1008         Line2[2].y = Line2[3].y = Line1[2].y - edge;
1009         Line1N = 6;
1010         Line2N = 6;
1011         break;
1012
1013     case DFCS_CAPTIONRESTORE:
1014         /* FIXME: this one looks bad at small sizes < 15x15 :( */
1015         edge = 47*SmallDiam/750;
1016         move = 420*SmallDiam/750;
1017         Line1[0].x = Line1[9].x = myr.left + 198*SmallDiam/750+2;
1018         Line1[0].y = Line1[1].y = myr.top  + 169*SmallDiam/750+1;
1019         Line1[6].y = Line1[7].y = Line1[0].y + 93*SmallDiam/750;
1020         Line1[7].x = Line1[8].x = Line1[0].x + edge;
1021         Line1[1].x = Line1[2].x = Line1[0].x + move;
1022         Line1[5].x = Line1[6].x = Line1[1].x - edge;
1023         Line1[9].y = Line1[8].y = Line1[0].y + 187*SmallDiam/750;
1024         Line1[2].y = Line1[3].y = Line1[0].y + 327*SmallDiam/750;
1025         Line1[4].y = Line1[5].y = Line1[2].y - edge;
1026         Line1[3].x = Line1[4].x = Line1[2].x - 140*SmallDiam/750;
1027
1028         Line2[1].x = Line2[2].x = Line1[3].x;
1029         Line2[7].x = Line2[8].x = Line2[1].x - edge;
1030         Line2[0].x = Line2[9].x = Line2[3].x = Line2[4].x = Line2[1].x - move;
1031         Line2[5].x = Line2[6].x = Line2[0].x + edge;
1032         Line2[0].y = Line2[1].y = Line1[9].y;
1033         Line2[4].y = Line2[5].y = Line2[8].y = Line2[9].y = Line2[0].y + 93*SmallDiam/750;
1034         Line2[2].y = Line2[3].y = Line2[0].y + 327*SmallDiam/750;
1035         Line2[6].y = Line2[7].y = Line2[2].y - edge;
1036         Line1N = 10;
1037         Line2N = 10;
1038         break;
1039
1040     default:
1041         DbgPrint("Invalid caption; flags=0x%04x\n", uFlags);
1042         return FALSE;
1043     }
1044
1045     if(uFlags & DFCS_INACTIVE)
1046     {
1047         hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
1048         hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT));
1049         Polygon(dc, Line1, Line1N);
1050         if(Line2N > 0)
1051             Polygon(dc, Line2, Line2N);
1052         SelectObject(dc, hpsave);
1053         SelectObject(dc, hbsave);
1054     }
1055
1056     if (!(uFlags & DFCS_PUSHED))
1057     {
1058         for(i = 0; i < Line1N; i++)
1059         {
1060             Line1[i].x--;
1061             Line1[i].y--;
1062         }
1063         for(i = 0; i < Line2N; i++)
1064         {
1065             Line2[i].x--;
1066             Line2[i].y--;
1067         }
1068     }
1069
1070     hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(colorIdx));
1071     hpsave = (HPEN)SelectObject(dc, GetSysColorPen(colorIdx));
1072
1073     Polygon(dc, Line1, Line1N);
1074     if(Line2N > 0)
1075         Polygon(dc, Line2, Line2N);
1076     SelectObject(dc, hpsave);
1077     SelectObject(dc, hbsave);
1078
1079     return TRUE;
1080 }
1081
1082 /* Ported from WINE20020904 */
1083 /* Draw a scroll-bar control coming from DrawFrameControl() */
1084 static BOOL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags)
1085 {
1086     POINT Line[4];
1087     RECT myr;
1088     int SmallDiam = UITOOLS_MakeSquareRect(r, &myr) - 2;
1089     int i;
1090     HBRUSH hbsave, hb, hb2;
1091     HPEN hpsave, hp, hp2;
1092     int tri = 290*SmallDiam/1000 - 1;
1093     int d46, d93;
1094
1095     /*
1096      * This fixes a problem with really tiny "scroll" buttons. In particular
1097      * with the updown control.
1098      * Making sure that the arrow is as least 3 pixels wide (or high).
1099      */
1100     if (tri == 0)
1101       tri = 1;
1102
1103     switch(uFlags & 0xff)
1104     {
1105     case DFCS_SCROLLCOMBOBOX:
1106     case DFCS_SCROLLDOWN:
1107         Line[2].x = myr.left + 470*SmallDiam/1000 + 2;
1108         Line[2].y = myr.top  + 687*SmallDiam/1000 + 1;
1109         Line[0].x = Line[2].x - tri;
1110         Line[1].x = Line[2].x + tri;
1111         Line[0].y = Line[1].y = Line[2].y - tri;
1112         break;
1113
1114     case DFCS_SCROLLUP:
1115         Line[2].x = myr.left + 470*SmallDiam/1000 + 2;
1116         Line[2].y = myr.bottom - (687*SmallDiam/1000 + 1);
1117         Line[0].x = Line[2].x - tri;
1118         Line[1].x = Line[2].x + tri;
1119         Line[0].y = Line[1].y = Line[2].y + tri;
1120         break;
1121
1122     case DFCS_SCROLLLEFT:
1123         Line[2].x = myr.right - (687*SmallDiam/1000 + 1);
1124         Line[2].y = myr.top  + 470*SmallDiam/1000 + 2;
1125         Line[0].y = Line[2].y - tri;
1126         Line[1].y = Line[2].y + tri;
1127         Line[0].x = Line[1].x = Line[2].x + tri;
1128         break;
1129
1130     case DFCS_SCROLLRIGHT:
1131         Line[2].x = myr.left + 687*SmallDiam/1000 + 1;
1132         Line[2].y = myr.top  + 470*SmallDiam/1000 + 2;
1133         Line[0].y = Line[2].y - tri;
1134         Line[1].y = Line[2].y + tri;
1135         Line[0].x = Line[1].x = Line[2].x - tri;
1136         break;
1137
1138     case DFCS_SCROLLSIZEGRIP:
1139         /* This one breaks the flow... */
1140         UITOOLS95_DrawRectEdge(dc, r, EDGE_BUMP, BF_MIDDLE | ((uFlags&(DFCS_MONO|DFCS_FLAT)) ? BF_MONO : 0));
1141         hpsave = (HPEN)SelectObject(dc, GetStockObject(NULL_PEN));
1142         hbsave = (HBRUSH)SelectObject(dc, GetStockObject(NULL_BRUSH));
1143         if(uFlags & (DFCS_MONO|DFCS_FLAT))
1144         {
1145             hp = hp2 = GetSysColorPen(COLOR_WINDOWFRAME);
1146             hb = hb2 = GetSysColorBrush(COLOR_WINDOWFRAME);
1147         }
1148         else
1149         {
1150             hp  = GetSysColorPen(COLOR_BTNHIGHLIGHT);
1151             hp2 = GetSysColorPen(COLOR_BTNSHADOW);
1152             hb  = GetSysColorBrush(COLOR_BTNHIGHLIGHT);
1153             hb2 = GetSysColorBrush(COLOR_BTNSHADOW);
1154         }
1155         Line[0].x = Line[1].x = r->right-1;
1156         Line[2].y = Line[3].y = r->bottom-1;
1157         d46 = 46*SmallDiam/750;
1158         d93 = 93*SmallDiam/750;
1159
1160         i = 586*SmallDiam/750;
1161         Line[0].y = r->bottom - i - 1;
1162         Line[3].x = r->right - i - 1;
1163         Line[1].y = Line[0].y + d46;
1164         Line[2].x = Line[3].x + d46;
1165         SelectObject(dc, hb);
1166         SelectObject(dc, hp);
1167         Polygon(dc, Line, 4);
1168
1169         Line[1].y++; Line[2].x++;
1170         Line[0].y = Line[1].y + d93;
1171         Line[3].x = Line[2].x + d93;
1172         SelectObject(dc, hb2);
1173         SelectObject(dc, hp2);
1174         Polygon(dc, Line, 4);
1175
1176         i = 398*SmallDiam/750;
1177         Line[0].y = r->bottom - i - 1;
1178         Line[3].x = r->right - i - 1;
1179         Line[1].y = Line[0].y + d46;
1180         Line[2].x = Line[3].x + d46;
1181         SelectObject(dc, hb);
1182         SelectObject(dc, hp);
1183         Polygon(dc, Line, 4);
1184
1185         Line[1].y++; Line[2].x++;
1186         Line[0].y = Line[1].y + d93;
1187         Line[3].x = Line[2].x + d93;
1188         SelectObject(dc, hb2);
1189         SelectObject(dc, hp2);
1190         Polygon(dc, Line, 4);
1191
1192         i = 210*SmallDiam/750;
1193         Line[0].y = r->bottom - i - 1;
1194         Line[3].x = r->right - i - 1;
1195         Line[1].y = Line[0].y + d46;
1196         Line[2].x = Line[3].x + d46;
1197         SelectObject(dc, hb);
1198         SelectObject(dc, hp);
1199         Polygon(dc, Line, 4);
1200
1201         Line[1].y++; Line[2].x++;
1202         Line[0].y = Line[1].y + d93;
1203         Line[3].x = Line[2].x + d93;
1204         SelectObject(dc, hb2);
1205         SelectObject(dc, hp2);
1206         Polygon(dc, Line, 4);
1207
1208         SelectObject(dc, hpsave);
1209         SelectObject(dc, hbsave);
1210         return TRUE;
1211
1212     default:
1213         DbgPrint("Invalid scroll; flags=0x%04x\n", uFlags);
1214         return FALSE;
1215     }
1216
1217     /* Here do the real scroll-bar controls end up */
1218     if( ! (uFlags & (0xff00 & ~DFCS_ADJUSTRECT)) )
1219       /* UITOOLS95_DFC_ButtonPush always uses BF_SOFT which we don't */
1220       /* want for the normal scroll-arrow button. */
1221       UITOOLS95_DrawRectEdge( dc, r, EDGE_RAISED, (uFlags&DFCS_ADJUSTRECT) | BF_MIDDLE | BF_RECT);
1222     else
1223       UITOOLS95_DFC_ButtonPush(dc, r, (uFlags & 0xff00) );
1224
1225     if(uFlags & DFCS_INACTIVE)
1226     {
1227         hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
1228         hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT));
1229         Polygon(dc, Line, 3);
1230         SelectObject(dc, hpsave);
1231         SelectObject(dc, hbsave);
1232     }
1233
1234     if( (uFlags & DFCS_INACTIVE) || !(uFlags & DFCS_PUSHED) )
1235       for(i = 0; i < 3; i++)
1236       {
1237         Line[i].x--;
1238         Line[i].y--;
1239       }
1240
1241     i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT;
1242     hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
1243     hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
1244     Polygon(dc, Line, 3);
1245     SelectObject(dc, hpsave);
1246     SelectObject(dc, hbsave);
1247
1248     return TRUE;
1249 }
1250
1251 /* Ported from WINE20020904 */
1252 /* Draw a menu control coming from DrawFrameControl() */
1253 static BOOL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
1254 {
1255     POINT Points[6];
1256     RECT myr;
1257     int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
1258     int i;
1259     HBRUSH hbsave;
1260     HPEN hpsave;
1261     int xe, ye;
1262     int xc, yc;
1263     BOOL retval = TRUE;
1264
1265     /* Using black and white seems to be utterly wrong, but win95 doesn't */
1266     /* use anything else. I think I tried all sys-colors to change things */
1267     /* without luck. It seems as if this behavior is inherited from the */
1268     /* win31 DFC() implementation... (you remember, B/W menus). */
1269
1270     FillRect(dc, r, (HBRUSH)GetStockObject(WHITE_BRUSH));
1271
1272     hbsave = (HBRUSH)SelectObject(dc, GetStockObject(BLACK_BRUSH));
1273     hpsave = (HPEN)SelectObject(dc, GetStockObject(BLACK_PEN));
1274
1275     switch(uFlags & 0xff)
1276     {
1277     case DFCS_MENUARROW:
1278         i = 187*SmallDiam/750;
1279         Points[2].x = myr.left + 468*SmallDiam/750;
1280         Points[2].y = myr.top  + 352*SmallDiam/750+1;
1281         Points[0].y = Points[2].y - i;
1282         Points[1].y = Points[2].y + i;
1283         Points[0].x = Points[1].x = Points[2].x - i;
1284         Polygon(dc, Points, 3);
1285         break;
1286
1287     case DFCS_MENUBULLET:
1288         xe = myr.left;
1289         ye = myr.top  + SmallDiam - SmallDiam/2;
1290         xc = myr.left + SmallDiam - SmallDiam/2;
1291         yc = myr.top  + SmallDiam - SmallDiam/2;
1292         i = 234*SmallDiam/750;
1293         i = i < 1 ? 1 : i;
1294         myr.left   = xc - i+i/2;
1295         myr.right  = xc + i/2;
1296         myr.top    = yc - i+i/2;
1297         myr.bottom = yc + i/2;
1298         Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
1299         break;
1300
1301     case DFCS_MENUCHECK:
1302         Points[0].x = myr.left + 253*SmallDiam/1000;
1303         Points[0].y = myr.top  + 445*SmallDiam/1000;
1304         Points[1].x = myr.left + 409*SmallDiam/1000;
1305         Points[1].y = Points[0].y + (Points[1].x-Points[0].x);
1306         Points[2].x = myr.left + 690*SmallDiam/1000;
1307         Points[2].y = Points[1].y - (Points[2].x-Points[1].x);
1308         Points[3].x = Points[2].x;
1309         Points[3].y = Points[2].y + 3*SmallDiam/16;
1310         Points[4].x = Points[1].x;
1311         Points[4].y = Points[1].y + 3*SmallDiam/16;
1312         Points[5].x = Points[0].x;
1313         Points[5].y = Points[0].y + 3*SmallDiam/16;
1314         Polygon(dc, Points, 6);
1315         break;
1316
1317     default:
1318         DbgPrint("Invalid menu; flags=0x%04x\n", uFlags);
1319         retval = FALSE;
1320         break;
1321     }
1322
1323     SelectObject(dc, hpsave);
1324     SelectObject(dc, hbsave);
1325     return retval;
1326 }
1327
1328 /* Ported from WINE20020904 */
1329 BOOL WINAPI DrawFrameControl( HDC hdc, LPRECT rc, UINT uType,
1330                                   UINT uState )
1331 {
1332    /* Win95 doesn't support drawing in other mapping modes
1333     if(GetMapMode(hdc) != MM_TEXT)
1334         return FALSE;
1335     */
1336     switch(uType)
1337     {
1338     case DFC_BUTTON:
1339       return UITOOLS95_DrawFrameButton(hdc, rc, uState);
1340     case DFC_CAPTION:
1341       return UITOOLS95_DrawFrameCaption(hdc, rc, uState);
1342     case DFC_MENU:
1343       return UITOOLS95_DrawFrameMenu(hdc, rc, uState);
1344     /*
1345     case DFC_POPUPMENU:
1346       break;
1347     */
1348     case DFC_SCROLL:
1349       return UITOOLS95_DrawFrameScroll(hdc, rc, uState);
1350     default:
1351       DbgPrint("(%p,%p,%d,%x), bad type!\n", hdc,rc,uType,uState );
1352     }
1353     return FALSE;
1354 }
1355 /* Ported from WINE20020904 */
1356 BOOL WINAPI DrawEdge( HDC hdc, LPRECT rc, UINT edge, UINT flags )
1357 {
1358     if(flags & BF_DIAGONAL)
1359       return UITOOLS95_DrawDiagEdge(hdc, rc, edge, flags);
1360     else
1361       return UITOOLS95_DrawRectEdge(hdc, rc, edge, flags);
1362 }
1363
1364 WINBOOL
1365 STDCALL
1366 GrayStringA(
1367   HDC hDC,
1368   HBRUSH hBrush,
1369   GRAYSTRINGPROC lpOutputFunc,
1370   LPARAM lpData,
1371   int nCount,
1372   int X,
1373   int Y,
1374   int nWidth,
1375   int nHeight)
1376 {
1377   return FALSE;
1378 }
1379
1380 WINBOOL
1381 STDCALL
1382 GrayStringW(
1383   HDC hDC,
1384   HBRUSH hBrush,
1385   GRAYSTRINGPROC lpOutputFunc,
1386   LPARAM lpData,
1387   int nCount,
1388   int X,
1389   int Y,
1390   int nWidth,
1391   int nHeight)
1392 {
1393   return FALSE;
1394 }
1395 WINBOOL
1396 STDCALL
1397 InvertRect(
1398   HDC hDC,
1399   CONST RECT *lprc)
1400 {
1401   return FALSE;
1402 }
1403 LONG
1404 STDCALL
1405 TabbedTextOutA(
1406   HDC hDC,
1407   int X,
1408   int Y,
1409   LPCSTR lpString,
1410   int nCount,
1411   int nTabPositions,
1412   CONST LPINT lpnTabStopPositions,
1413   int nTabOrigin)
1414 {
1415   return 0;
1416 }
1417
1418 LONG
1419 STDCALL
1420 TabbedTextOutW(
1421   HDC hDC,
1422   int X,
1423   int Y,
1424   LPCWSTR lpString,
1425   int nCount,
1426   int nTabPositions,
1427   CONST LPINT lpnTabStopPositions,
1428   int nTabOrigin)
1429 {
1430   return 0;
1431 }
1432 int
1433 STDCALL
1434 FrameRect(
1435   HDC hDC,
1436   CONST RECT *lprc,
1437   HBRUSH hbr)
1438 {
1439   return 0;
1440 }
1441 WINBOOL
1442 STDCALL
1443 FlashWindow(
1444   HWND hWnd,
1445   WINBOOL bInvert)
1446 {
1447   return FALSE;
1448 }
1449
1450 WINBOOL
1451 STDCALL
1452 FlashWindowEx(
1453   PFLASHWINFO pfwi)
1454 {
1455   return FALSE;
1456 }
1457
1458 int STDCALL
1459 FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr)
1460 {
1461   HBRUSH prevhbr;
1462   /*if (hbr <= (HBRUSH)(COLOR_MAX + 1))
1463     {
1464       hbr = GetSysColorBrush((INT)hbr - 1);
1465       }*/
1466   if ((prevhbr = SelectObject(hDC, hbr)) == NULL)
1467     {
1468       return(FALSE);
1469     }
1470   PatBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left,
1471          lprc->bottom - lprc->top, PATCOPY);
1472   SelectObject(hDC, prevhbr);
1473   return(TRUE);
1474 }
1475
1476 WINBOOL
1477 STDCALL
1478 DrawAnimatedRects(
1479   HWND hwnd,
1480   int idAni,
1481   CONST RECT *lprcFrom,
1482   CONST RECT *lprcTo)
1483 {
1484   return FALSE;
1485 }
1486
1487 WINBOOL
1488 STDCALL
1489 DrawCaption(
1490   HWND hwnd,
1491   HDC hdc,
1492   LPRECT lprc,
1493   UINT uFlags)
1494 {
1495   return FALSE;
1496 }
1497
1498 WINBOOL
1499 STDCALL
1500 DrawFocusRect(
1501   HDC hDC,
1502   CONST RECT *lprc)
1503 {
1504   return FALSE;
1505 }
1506
1507
1508 WINBOOL
1509 STDCALL
1510 DrawStateA(
1511   HDC hdc,
1512   HBRUSH hbr,
1513   DRAWSTATEPROC lpOutputFunc,
1514   LPARAM lData,
1515   WPARAM wData,
1516   int x,
1517   int y,
1518   int cx,
1519   int cy,
1520   UINT fuFlags)
1521 {
1522   return FALSE;
1523 }
1524
1525 WINBOOL
1526 STDCALL
1527 DrawStateW(
1528   HDC hdc,
1529   HBRUSH hbr,
1530   DRAWSTATEPROC lpOutputFunc,
1531   LPARAM lData,
1532   WPARAM wData,
1533   int x,
1534   int y,
1535   int cx,
1536   int cy,
1537   UINT fuFlags)
1538 {
1539   return FALSE;
1540 }