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