Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

uitools.cpp

Go to the documentation of this file.
00001 /* $Id: uitools.cpp,v 1.32 2001/12/30 16:51:17 sandervl Exp $ */
00002 /*
00003  * User Interface Functions
00004  *
00005  * Copyright 1997 Dimitrie O. Paun
00006  * Copyright 1997 Bertho A. Stultiens
00007  * Copyright 1999 Achim Hasenmueller
00008  * Copyright 1999 Christoph Bratschi
00009  * Copyright 1999 Rene Pronk
00010  *
00011  * WINE version: 990923
00012  */
00013 
00014 #include "winuser.h"
00015 #include "user32.h"
00016 #include "win32wbase.h"
00017 #include "syscolor.h"
00018 
00019 #define DBG_LOCALLOG    DBG_uitools
00020 #include "dbglocal.h"
00021 
00022 /* These tables are used in:
00023  * UITOOLS_DrawDiagEdge()
00024  * UITOOLS_DrawRectEdge()
00025  */
00026 static const signed  LTInnerNormal[] = {
00027     -1,           -1,                 -1,                 -1,
00028     -1,           COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1,
00029     -1,           COLOR_3DDKSHADOW,   COLOR_3DDKSHADOW,   -1,
00030     -1,           -1,                 -1,                 -1
00031 };
00032 
00033 static const signed char LTOuterNormal[] = {
00034     -1,                 COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1,
00035     COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1,
00036     COLOR_3DDKSHADOW,   COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1,
00037     -1,                 COLOR_3DLIGHT,     COLOR_BTNSHADOW, -1
00038 };
00039 
00040 static const signed char RBInnerNormal[] = {
00041     -1,           -1,                -1,              -1,
00042     -1,           COLOR_BTNSHADOW,   COLOR_BTNSHADOW, -1,
00043     -1,           COLOR_3DLIGHT,     COLOR_3DLIGHT,   -1,
00044     -1,           -1,                -1,              -1
00045 };
00046 
00047 static const signed char RBOuterNormal[] = {
00048     -1,              COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1,
00049     COLOR_BTNSHADOW, COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1,
00050     COLOR_3DLIGHT,   COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1,
00051     -1,              COLOR_3DDKSHADOW,  COLOR_BTNHIGHLIGHT, -1
00052 };
00053 
00054 static const signed char LTInnerSoft[] = {
00055     -1,                  -1,                -1,              -1,
00056     -1,                  COLOR_3DLIGHT,     COLOR_3DLIGHT,   -1,
00057     -1,                  COLOR_BTNSHADOW,   COLOR_BTNSHADOW, -1,
00058     -1,                  -1,                -1,              -1
00059 };
00060 
00061 static const signed char LTOuterSoft[] = {
00062     -1,              COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
00063     COLOR_3DLIGHT,   COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
00064     COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1,
00065     -1,              COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1
00066 };
00067 
00068 #define RBInnerSoft RBInnerNormal   /* These are the same */
00069 #define RBOuterSoft RBOuterNormal
00070 
00071 static const signed char LTRBOuterMono[] = {
00072     -1,           COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
00073     COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
00074     COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
00075     COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
00076 };
00077 
00078 static const signed char LTRBInnerMono[] = {
00079     -1, -1,           -1,           -1,
00080     -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
00081     -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
00082     -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW,
00083 };
00084 
00085 static const signed char LTRBOuterFlat[] = {
00086     -1,                COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
00087     COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
00088     COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
00089     COLOR_WINDOWFRAME, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW,
00090 };
00091 
00092 static const signed char LTRBInnerFlat[] = {
00093     -1, -1,              -1,              -1,
00094     -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
00095     -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
00096     -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME,
00097 };
00098 
00099 /***********************************************************************
00100  *           UITOOLS_DrawDiagEdge
00101  *
00102  * Same as DrawEdge invoked with BF_DIAGONAL
00103  *
00104  * 03-Dec-1997: Changed by Bertho Stultiens
00105  *
00106  * See also comments with UITOOLS_DrawRectEdge()
00107  */
00108 static BOOL UITOOLS95_DrawDiagEdge(HDC hdc, LPRECT rc,
00109                                      UINT uType, UINT uFlags)
00110 {
00111     POINT Points[4];
00112     signed char InnerI, OuterI;
00113     HPEN InnerPen, OuterPen;
00114     POINT SavePoint;
00115     HPEN SavePen;
00116     int spx, spy;
00117     int epx, epy;
00118     int Width = rc->right - rc->left;
00119     int Height= rc->bottom - rc->top;
00120     int SmallDiam = Width > Height ? Height : Width;
00121     BOOL retval = !(   ((uType & BDR_INNER) == BDR_INNER
00122                        || (uType & BDR_OUTER) == BDR_OUTER)
00123                       && !(uFlags & (BF_FLAT|BF_MONO)) );
00124     int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
00125             + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
00126 
00127     if (IsRectEmpty(rc)) return retval; //nothing to do
00128 
00129     /* Init some vars */
00130     OuterPen = InnerPen = (HPEN)GetStockObject(NULL_PEN);
00131     SavePen = (HPEN)SelectObject(hdc, InnerPen);
00132     spx = spy = epx = epy = 0; /* Satisfy the compiler... */
00133 
00134     /* Determine the colors of the edges */
00135     if(uFlags & BF_MONO)
00136     {
00137         InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
00138         OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
00139     }
00140     else if(uFlags & BF_FLAT)
00141     {
00142         InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
00143         OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
00144     }
00145     else if(uFlags & BF_SOFT)
00146     {
00147         if(uFlags & BF_BOTTOM)
00148         {
00149             InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
00150             OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
00151         }
00152         else
00153         {
00154             InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
00155             OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
00156         }
00157     }
00158     else
00159     {
00160         if(uFlags & BF_BOTTOM)
00161         {
00162             InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
00163             OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
00164         }
00165         else
00166         {
00167             InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
00168             OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
00169         }
00170     }
00171 
00172     if(InnerI != -1) InnerPen = GetSysColorPen(InnerI);
00173     if(OuterI != -1) OuterPen = GetSysColorPen(OuterI);
00174 
00175     MoveToEx(hdc, 0, 0, &SavePoint);
00176 
00177     /* Don't ask me why, but this is what is visible... */
00178     /* This must be possible to do much simpler, but I fail to */
00179     /* see the logic in the MS implementation (sigh...). */
00180     /* So, this might look a bit brute force here (and it is), but */
00181     /* it gets the job done;) */
00182 
00183     switch(uFlags & BF_RECT)
00184     {
00185     case 0:
00186     case BF_LEFT:
00187     case BF_BOTTOM:
00188     case BF_BOTTOMLEFT:
00189         /* Left bottom endpoint */
00190         epx = rc->left-1;
00191         spx = epx + SmallDiam;
00192         epy = rc->bottom;
00193         spy = epy - SmallDiam;
00194         break;
00195 
00196     case BF_TOPLEFT:
00197     case BF_BOTTOMRIGHT:
00198         /* Left top endpoint */
00199         epx = rc->left-1;
00200         spx = epx + SmallDiam;
00201         epy = rc->top-1;
00202         spy = epy + SmallDiam;
00203         break;
00204 
00205     case BF_TOP:
00206     case BF_RIGHT:
00207     case BF_TOPRIGHT:
00208     case BF_RIGHT|BF_LEFT:
00209     case BF_RIGHT|BF_LEFT|BF_TOP:
00210     case BF_BOTTOM|BF_TOP:
00211     case BF_BOTTOM|BF_TOP|BF_LEFT:
00212     case BF_BOTTOMRIGHT|BF_LEFT:
00213     case BF_BOTTOMRIGHT|BF_TOP:
00214     case BF_RECT:
00215         /* Right top endpoint */
00216         spx = rc->left;
00217         epx = spx + SmallDiam;
00218         spy = rc->bottom-1;
00219         epy = spy - SmallDiam;
00220         break;
00221     }
00222 
00223     MoveToEx(hdc, spx, spy, NULL);
00224     SelectObject(hdc, OuterPen);
00225     LineTo(hdc, epx, epy);
00226 
00227     SelectObject(hdc, InnerPen);
00228 
00229     switch(uFlags & (BF_RECT|BF_DIAGONAL))
00230     {
00231     case BF_DIAGONAL_ENDBOTTOMLEFT:
00232     case (BF_DIAGONAL|BF_BOTTOM):
00233     case BF_DIAGONAL:
00234     case (BF_DIAGONAL|BF_LEFT):
00235         MoveToEx(hdc, spx-1, spy, NULL);
00236         LineTo(hdc, epx, epy-1);
00237         Points[0].x = spx-add;
00238         Points[0].y = spy;
00239         Points[1].x = rc->left;
00240         Points[1].y = rc->top;
00241         Points[2].x = epx+1;
00242         Points[2].y = epy-1-add;
00243         Points[3] = Points[2];
00244         break;
00245 
00246     case BF_DIAGONAL_ENDBOTTOMRIGHT:
00247         MoveToEx(hdc, spx-1, spy, NULL);
00248         LineTo(hdc, epx, epy+1);
00249         Points[0].x = spx-add;
00250         Points[0].y = spy;
00251         Points[1].x = rc->left;
00252         Points[1].y = rc->bottom-1;
00253         Points[2].x = epx+1;
00254         Points[2].y = epy+1+add;
00255         Points[3] = Points[2];
00256         break;
00257 
00258     case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP):
00259     case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT):
00260     case BF_DIAGONAL_ENDTOPRIGHT:
00261     case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT):
00262         MoveToEx(hdc, spx+1, spy, NULL);
00263         LineTo(hdc, epx, epy+1);
00264         Points[0].x = epx-1;
00265         Points[0].y = epy+1+add;
00266         Points[1].x = rc->right-1;
00267         Points[1].y = rc->top+add;
00268         Points[2].x = rc->right-1;
00269         Points[2].y = rc->bottom-1;
00270         Points[3].x = spx+add;
00271         Points[3].y = spy;
00272         break;
00273 
00274     case BF_DIAGONAL_ENDTOPLEFT:
00275         MoveToEx(hdc, spx, spy-1, NULL);
00276         LineTo(hdc, epx+1, epy);
00277         Points[0].x = epx+1+add;
00278         Points[0].y = epy+1;
00279         Points[1].x = rc->right-1;
00280         Points[1].y = rc->top;
00281         Points[2].x = rc->right-1;
00282         Points[2].y = rc->bottom-1-add;
00283         Points[3].x = spx;
00284         Points[3].y = spy-add;
00285         break;
00286 
00287     case (BF_DIAGONAL|BF_TOP):
00288     case (BF_DIAGONAL|BF_BOTTOM|BF_TOP):
00289     case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT):
00290         MoveToEx(hdc, spx+1, spy-1, NULL);
00291         LineTo(hdc, epx, epy);
00292         Points[0].x = epx-1;
00293         Points[0].y = epy+1;
00294         Points[1].x = rc->right-1;
00295         Points[1].y = rc->top;
00296         Points[2].x = rc->right-1;
00297         Points[2].y = rc->bottom-1-add;
00298         Points[3].x = spx+add;
00299         Points[3].y = spy-add;
00300         break;
00301 
00302     case (BF_DIAGONAL|BF_RIGHT):
00303     case (BF_DIAGONAL|BF_RIGHT|BF_LEFT):
00304     case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM):
00305         MoveToEx(hdc, spx, spy, NULL);
00306         LineTo(hdc, epx-1, epy+1);
00307         Points[0].x = spx;
00308         Points[0].y = spy;
00309         Points[1].x = rc->left;
00310         Points[1].y = rc->top+add;
00311         Points[2].x = epx-1-add;
00312         Points[2].y = epy+1+add;
00313         Points[3] = Points[2];
00314         break;
00315     }
00316 
00317     /* Fill the interior if asked */
00318     if((uFlags & BF_MIDDLE) && retval)
00319     {
00320         HBRUSH hbsave;
00321         HBRUSH hb = GetSysColorBrush(uFlags & BF_MONO ? COLOR_WINDOW
00322                                          :COLOR_BTNFACE);
00323         HPEN hpsave;
00324         HPEN hp = GetSysColorPen(uFlags & BF_MONO ? COLOR_WINDOW
00325                                      : COLOR_BTNFACE);
00326         hbsave = (HBRUSH)SelectObject(hdc, hb);
00327         hpsave = (HPEN)SelectObject(hdc, hp);
00328         Polygon(hdc, Points, 4);
00329         SelectObject(hdc, hbsave);
00330         SelectObject(hdc, hpsave);
00331     }
00332 
00333     /* Adjust rectangle if asked */
00334     if(uFlags & BF_ADJUST)
00335     {
00336         if(uFlags & BF_LEFT)   rc->left   += add;
00337         if(uFlags & BF_RIGHT)  rc->right  -= add;
00338         if(uFlags & BF_TOP)    rc->top    += add;
00339         if(uFlags & BF_BOTTOM) rc->bottom -= add;
00340     }
00341 
00342     /* Cleanup */
00343     SelectObject(hdc, SavePen);
00344     MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
00345 
00346     return retval;
00347 }
00348 
00349 /***********************************************************************
00350  *           UITOOLS_DrawRectEdge
00351  *
00352  * Same as DrawEdge invoked without BF_DIAGONAL
00353  *
00354  * 23-Nov-1997: Changed by Bertho Stultiens
00355  *
00356  * Well, I started testing this and found out that there are a few things
00357  * that weren't quite as win95. The following rewrite should reproduce
00358  * win95 results completely.
00359  * The colorselection is table-driven to avoid awfull if-statements.
00360  * The table below show the color settings.
00361  *
00362  * Pen selection table for uFlags = 0
00363  *
00364  * uType |  LTI  |  LTO  |  RBI  |  RBO
00365  * ------+-------+-------+-------+-------
00366  *  0000 |   x   |   x   |   x   |   x
00367  *  0001 |   x   |  22   |   x   |  21
00368  *  0010 |   x   |  16   |   x   |  20
00369  *  0011 |   x   |   x   |   x   |   x
00370  * ------+-------+-------+-------+-------
00371  *  0100 |   x   |  20   |   x   |  16
00372  *  0101 |  20   |  22   |  16   |  21
00373  *  0110 |  20   |  16   |  16   |  20
00374  *  0111 |   x   |   x   |   x   |   x
00375  * ------+-------+-------+-------+-------
00376  *  1000 |   x   |  21   |   x   |  22
00377  *  1001 |  21   |  22   |  22   |  21
00378  *  1010 |  21   |  16   |  22   |  20
00379  *  1011 |   x   |   x   |   x   |   x
00380  * ------+-------+-------+-------+-------
00381  *  1100 |   x   |   x   |   x   |   x
00382  *  1101 |   x   | x (22)|   x   | x (21)
00383  *  1110 |   x   | x (16)|   x   | x (20)
00384  *  1111 |   x   |   x   |   x   |   x
00385  *
00386  * Pen selection table for uFlags = BF_SOFT
00387  *
00388  * uType |  LTI  |  LTO  |  RBI  |  RBO
00389  * ------+-------+-------+-------+-------
00390  *  0000 |   x   |   x   |   x   |   x
00391  *  0001 |   x   |  20   |   x   |  21
00392  *  0010 |   x   |  21   |   x   |  20
00393  *  0011 |   x   |   x   |   x   |   x
00394  * ------+-------+-------+-------+-------
00395  *  0100 |   x   |  22   |   x   |  16
00396  *  0101 |  22   |  20   |  16   |  21
00397  *  0110 |  22   |  21   |  16   |  20
00398  *  0111 |   x   |   x   |   x   |   x
00399  * ------+-------+-------+-------+-------
00400  *  1000 |   x   |  16   |   x   |  22
00401  *  1001 |  16   |  20   |  22   |  21
00402  *  1010 |  16   |  21   |  22   |  20
00403  *  1011 |   x   |   x   |   x   |   x
00404  * ------+-------+-------+-------+-------
00405  *  1100 |   x   |   x   |   x   |   x
00406  *  1101 |   x   | x (20)|   x   | x (21)
00407  *  1110 |   x   | x (21)|   x   | x (20)
00408  *  1111 |   x   |   x   |   x   |   x
00409  *
00410  * x = don't care; (n) = is what win95 actually uses
00411  * LTI = left Top Inner line
00412  * LTO = left Top Outer line
00413  * RBI = Right Bottom Inner line
00414  * RBO = Right Bottom Outer line
00415  * 15 = COLOR_BTNFACE
00416  * 16 = COLOR_BTNSHADOW
00417  * 20 = COLOR_BTNHIGHLIGHT
00418  * 21 = COLOR_3DDKSHADOW
00419  * 22 = COLOR_3DLIGHT
00420  */
00421 
00422 
00423 static BOOL UITOOLS95_DrawRectEdge(HDC hdc, LPRECT rc,
00424                                      UINT uType, UINT uFlags)
00425 {
00426     signed char LTInnerI, LTOuterI;
00427     signed char RBInnerI, RBOuterI;
00428     HPEN LTInnerPen, LTOuterPen;
00429     HPEN RBInnerPen, RBOuterPen;
00430     RECT InnerRect = *rc;
00431     POINT SavePoint;
00432     HPEN SavePen;
00433     int LBpenplus = 0;
00434     int LTpenplus = 0;
00435     int RTpenplus = 0;
00436     int RBpenplus = 0;
00437     BOOL retval = !(   ((uType & BDR_INNER) == BDR_INNER
00438                        || (uType & BDR_OUTER) == BDR_OUTER)
00439                       && !(uFlags & (BF_FLAT|BF_MONO)) );
00440 
00441     if  (IsRectEmpty(rc)) return retval; //nothing to do
00442 
00443     /* Init some vars */
00444     LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN)GetStockObject(NULL_PEN);
00445     SavePen = (HPEN)SelectObject(hdc, LTInnerPen);
00446 
00447     /* Determine the colors of the edges */
00448     if(uFlags & BF_MONO)
00449     {
00450         LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)];
00451         LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)];
00452     }
00453     else if(uFlags & BF_FLAT)
00454     {
00455         LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)];
00456         LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)];
00457 
00458         /* Bertho Stultiens states above that this function exactly matches win95
00459          * In win98 BF_FLAT rectangels have an inner border same color as the
00460          * middle (COLOR_BTNFACE). I believe it's the same for win95 but since
00461          * I don't know I go with Bertho and just sets it for win98 until proven
00462          * otherwise.
00463          *                                          Dennis Björklund, 10 June, 99
00464          */
00465         if(LTInnerI != -1 )
00466             LTInnerI = RBInnerI = COLOR_BTNFACE;
00467     }
00468     else if(uFlags & BF_SOFT)
00469     {
00470         LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
00471         LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
00472         RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)];
00473         RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)];
00474     }
00475     else
00476     {
00477         LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
00478         LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
00479         RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)];
00480         RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)];
00481     }
00482 
00483     if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT)   LBpenplus = 1;
00484     if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT)       RTpenplus = 1;
00485     if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT) RBpenplus = 1;
00486     if((uFlags & BF_TOPLEFT) == BF_TOPLEFT)         LTpenplus = 1;
00487 
00488     if(LTInnerI != -1) LTInnerPen = GetSysColorPen(LTInnerI);
00489     if(LTOuterI != -1) LTOuterPen = GetSysColorPen(LTOuterI);
00490     if(RBInnerI != -1) RBInnerPen = GetSysColorPen(RBInnerI);
00491     if(RBOuterI != -1) RBOuterPen = GetSysColorPen(RBOuterI);
00492 
00493     MoveToEx(hdc, 0, 0, &SavePoint);
00494 
00495     /* Draw the outer edge */
00496     SelectObject(hdc, LTOuterPen);
00497     if(uFlags & BF_TOP)
00498     {
00499         MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
00500         LineTo(hdc, InnerRect.right, InnerRect.top);
00501     }
00502     if(uFlags & BF_LEFT)
00503     {
00504         MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL);
00505         LineTo(hdc, InnerRect.left, InnerRect.bottom);
00506     }
00507 
00508     SelectObject(hdc, RBOuterPen);
00509     if(uFlags & BF_BOTTOM)
00510     {
00511         MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL);
00512         LineTo(hdc, InnerRect.left-1, InnerRect.bottom-1);
00513     }
00514     if(uFlags & BF_RIGHT)
00515     {
00516         MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL);
00517         LineTo(hdc, InnerRect.right-1, InnerRect.top-1);
00518     }
00519 
00520     /* Draw the inner edge */
00521     SelectObject(hdc, LTInnerPen);
00522     if(uFlags & BF_TOP)
00523     {
00524         MoveToEx(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL);
00525         LineTo(hdc, InnerRect.right-RTpenplus, InnerRect.top+1);
00526     }
00527     if(uFlags & BF_LEFT)
00528     {
00529         MoveToEx(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL);
00530         LineTo(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus);
00531     }
00532     SelectObject(hdc, RBInnerPen);
00533     if(uFlags & BF_BOTTOM)
00534     {
00535         MoveToEx(hdc, InnerRect.right-1-RBpenplus, InnerRect.bottom-2, NULL);
00536         LineTo(hdc, InnerRect.left-1+LBpenplus, InnerRect.bottom-2);
00537     }
00538     if(uFlags & BF_RIGHT)
00539     {
00540         MoveToEx(hdc, InnerRect.right-2, InnerRect.bottom-1-RBpenplus, NULL);
00541         LineTo(hdc, InnerRect.right-2, InnerRect.top-1+RTpenplus);
00542     }
00543 
00544     if( ((uFlags & BF_MIDDLE) && retval) || (uFlags & BF_ADJUST) )
00545     {
00546         int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0)
00547                 + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0);
00548 
00549         if(uFlags & BF_LEFT)   InnerRect.left   += add;
00550         if(uFlags & BF_RIGHT)  InnerRect.right  -= add;
00551         if(uFlags & BF_TOP)    InnerRect.top    += add;
00552         if(uFlags & BF_BOTTOM) InnerRect.bottom -= add;
00553 
00554         if((uFlags & BF_MIDDLE) && retval)
00555         {
00556             FillRect(hdc, &InnerRect, GetSysColorBrush(uFlags & BF_MONO ?
00557                                                        COLOR_WINDOW : COLOR_BTNFACE));
00558         }
00559 
00560         if(uFlags & BF_ADJUST)
00561             *rc = InnerRect;
00562     }
00563 
00564     /* Cleanup */
00565     SelectObject(hdc, SavePen);
00566     MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL);
00567     return retval;
00568 }
00569 
00570 
00571 //**********************************************************************
00572 //          DrawEdge   (USER32.155)
00573 //
00574 BOOL WIN32API DrawEdge(HDC hdc, LPRECT rc, UINT edge, UINT flags)
00575 {
00576 
00577     if (flags & BF_DIAGONAL)
00578       return UITOOLS95_DrawDiagEdge(hdc, rc, edge, flags);
00579     else
00580       return UITOOLS95_DrawRectEdge(hdc, rc, edge, flags);
00581 }
00582 
00583 /************************************************************************
00584  *      UITOOLS_MakeSquareRect
00585  *
00586  * Utility to create a square rectangle and returning the width
00587  */
00588 static int UITOOLS_MakeSquareRect(LPRECT src, LPRECT dst)
00589 {
00590     int Width  = src->right - src->left;
00591     int Height = src->bottom - src->top;
00592     int SmallDiam = Width > Height ? Height : Width;
00593 
00594     *dst = *src;
00595 
00596     /* Make it a square box */
00597     if(Width < Height)      /* SmallDiam == Width */
00598     {
00599         dst->top += (Height-Width)/2;
00600         dst->bottom = dst->top + SmallDiam;
00601     }
00602     else if(Width > Height) /* SmallDiam == Height */
00603     {
00604         dst->left += (Width-Height)/2;
00605         dst->right = dst->left + SmallDiam;
00606     }
00607 
00608    return SmallDiam;
00609 }
00610 
00611 
00612 static void UITOOLS_DrawCheckedRect( HDC dc, LPRECT rect )
00613 {
00614     if(GetSysColor(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255))
00615     {
00616       COLORREF bg;
00617       HBRUSH hbsave;
00618 
00619       FillRect(dc, rect, GetSysColorBrush(COLOR_BTNFACE));
00620       bg = SetBkColor(dc, RGB(255, 255, 255));
00621       hbsave = (HBRUSH)SelectObject(dc,GetPattern55AABrush());
00622       PatBlt(dc, rect->left, rect->top, rect->right-rect->left, rect->bottom-rect->top, 0x00FA0089);
00623       SelectObject(dc, hbsave);
00624       SetBkColor(dc, bg);
00625     }
00626     else
00627     {
00628         FillRect(dc, rect, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
00629     }
00630 }
00631 
00632 /************************************************************************
00633  *      UITOOLS_DFC_ButtonPush
00634  *
00635  * Draw a push button coming from DrawFrameControl()
00636  *
00637  * Does a pretty good job in emulating MS behavior. Some quirks are
00638  * however there because MS uses a TrueType font (Marlett) to draw
00639  * the buttons.
00640  */
00641 static BOOL UITOOLS95_DFC_ButtonPush(HDC dc, LPRECT r, UINT uFlags)
00642 {
00643     UINT edge;
00644     RECT myr = *r;
00645 
00646     if(uFlags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT))
00647         edge = EDGE_SUNKEN;
00648     else
00649         edge = EDGE_RAISED;
00650 
00651     if(uFlags & DFCS_CHECKED)
00652     {
00653         if(uFlags & DFCS_MONO)
00654             UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
00655         else
00656             UITOOLS95_DrawRectEdge(dc, &myr, edge, (uFlags&DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST);
00657 
00658         UITOOLS_DrawCheckedRect( dc, &myr );
00659         }
00660         else
00661         {
00662         if(uFlags & DFCS_MONO)
00663         {
00664             UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST);
00665             FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE));
00666         }
00667         else
00668         {
00669             UITOOLS95_DrawRectEdge(dc, r, edge, (uFlags&DFCS_FLAT) | BF_MIDDLE |BF_SOFT| BF_RECT);
00670         }
00671     }
00672 
00673     /* Adjust rectangle if asked */
00674     if(uFlags & DFCS_ADJUSTRECT)
00675     {
00676         r->left   += 2;
00677         r->right  -= 2;
00678         r->top    += 2;
00679         r->bottom -= 2;
00680     }
00681 
00682     return TRUE;
00683 }
00684 
00685 
00686 /************************************************************************
00687  *      UITOOLS_DFC_ButtonCheck
00688  *
00689  * Draw a check/3state button coming from DrawFrameControl()
00690  *
00691  * Does a pretty good job in emulating MS behavior. Some quirks are
00692  * however there because MS uses a TrueType font (Marlett) to draw
00693  * the buttons.
00694  */
00695 #define DFC_CHECKPOINTSMAX      6
00696 
00697 static BOOL UITOOLS95_DFC_ButtonCheck(HDC dc, LPRECT r, UINT uFlags)
00698 {
00699     RECT myr;
00700     int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
00701     UINT flags = BF_RECT | BF_ADJUST;
00702 
00703     if(uFlags & DFCS_FLAT) flags |= BF_FLAT;
00704     else if(uFlags & DFCS_MONO) flags |= BF_MONO;
00705 
00706     UITOOLS95_DrawRectEdge( dc, &myr, EDGE_SUNKEN, flags );
00707 
00708     if(uFlags & (DFCS_INACTIVE|DFCS_PUSHED))
00709         FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE));
00710     else if( (uFlags & DFCS_BUTTON3STATE) && (uFlags & DFCS_CHECKED) )
00711         UITOOLS_DrawCheckedRect( dc, &myr );
00712     else
00713     {
00714         FillRect(dc, &myr, GetSysColorBrush(COLOR_WINDOW));
00715     }
00716 
00717     if(uFlags & DFCS_CHECKED)
00718     {
00719         POINT CheckPoints[DFC_CHECKPOINTSMAX];
00720         int i;
00721         HBRUSH hbsave;
00722         HPEN hpsave;
00723 
00724         /* FIXME: This comes very close to M$'s checkmark, but not */
00725         /* exactly... When small or large there is a few pixels */
00726         /* shift. Not bad, but could be better :) */
00727         UITOOLS_MakeSquareRect(r, &myr);
00728         CheckPoints[0].x = myr.left + 253*SmallDiam/1000;
00729         CheckPoints[0].y = myr.top  + 345*SmallDiam/1000;
00730         CheckPoints[1].x = myr.left + 409*SmallDiam/1000;
00731         CheckPoints[1].y = CheckPoints[0].y + (CheckPoints[1].x-CheckPoints[0].x);
00732         CheckPoints[2].x = myr.left + 690*SmallDiam/1000;
00733         CheckPoints[2].y = CheckPoints[1].y - (CheckPoints[2].x-CheckPoints[1].x);
00734         CheckPoints[3].x = CheckPoints[2].x;
00735         CheckPoints[3].y = CheckPoints[2].y + 3*SmallDiam/16;
00736         CheckPoints[4].x = CheckPoints[1].x;
00737         CheckPoints[4].y = CheckPoints[1].y + 3*SmallDiam/16;
00738         CheckPoints[5].x = CheckPoints[0].x;
00739         CheckPoints[5].y = CheckPoints[0].y + 3*SmallDiam/16;
00740 
00741         i = (uFlags & DFCS_INACTIVE) || (uFlags & 0xff) == DFCS_BUTTON3STATE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT;
00742         hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
00743         hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
00744         Polygon(dc, CheckPoints, DFC_CHECKPOINTSMAX);
00745         SelectObject(dc, hpsave);
00746         SelectObject(dc, hbsave);
00747     }
00748     return TRUE;
00749 }
00750 
00751 
00752 /************************************************************************
00753  *      UITOOLS_DFC_ButtonRadio
00754  *
00755  * Draw a radio/radioimage/radiomask button coming from DrawFrameControl()
00756  *
00757  * Does a pretty good job in emulating MS behavior. Some quirks are
00758  * however there because MS uses a TrueType font (Marlett) to draw
00759  * the buttons.
00760  */
00761 static BOOL UITOOLS95_DFC_ButtonRadio(HDC dc, LPRECT r, UINT uFlags)
00762 {
00763     RECT myr;
00764     int i;
00765     int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
00766     int BorderShrink = SmallDiam / 16;
00767     HPEN hpsave;
00768     HBRUSH hbsave;
00769     int xe, ye;
00770     int xc, yc;
00771 
00772     if(BorderShrink < 1) BorderShrink = 1;
00773 
00774     if((uFlags & 0xff) == DFCS_BUTTONRADIOIMAGE)
00775     {
00776         FillRect(dc, r, (HBRUSH)GetStockObject(BLACK_BRUSH));
00777     }
00778 
00779     xe = myr.left;
00780     ye = myr.top  + SmallDiam - SmallDiam/2;
00781 
00782     xc = myr.left + SmallDiam - SmallDiam/2;
00783     yc = myr.top  + SmallDiam - SmallDiam/2;
00784 
00785     /* Define bounding box */
00786     i = (14*SmallDiam)/16;
00787     myr.left   = xc - i+i/2;
00788     myr.right  = xc + i/2;
00789     myr.top    = yc - i+i/2;
00790     myr.bottom = yc + i/2;
00791 
00792     if((uFlags & 0xff) == DFCS_BUTTONRADIOMASK)
00793     {
00794         hbsave = (HBRUSH)SelectObject(dc, GetStockObject(BLACK_BRUSH));
00795         Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
00796         SelectObject(dc, hbsave);
00797     }
00798     else
00799     {
00800         if(uFlags & (DFCS_FLAT|DFCS_MONO))
00801         {
00802             hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_WINDOWFRAME));
00803             hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_WINDOWFRAME));
00804             Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
00805             SelectObject(dc, hbsave);
00806             SelectObject(dc, hpsave);
00807         }
00808         else
00809         {
00810             hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT));
00811             hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
00812             Pie(dc, myr.left, myr.top, myr.right, myr.bottom, myr.left-1, myr.bottom, myr.right-1, myr.top);
00813 
00814             SelectObject(dc, GetSysColorPen(COLOR_BTNSHADOW));
00815             SelectObject(dc, GetSysColorBrush(COLOR_BTNSHADOW));
00816             Pie(dc, myr.left, myr.top, myr.right, myr.bottom, myr.right+1, myr.top, myr.left+1, myr.bottom);
00817 
00818             myr.left   += BorderShrink;
00819             myr.right  -= BorderShrink;
00820             myr.top    += BorderShrink;
00821             myr.bottom -= BorderShrink;
00822 
00823             SelectObject(dc, GetSysColorPen(COLOR_3DLIGHT));
00824             SelectObject(dc, GetSysColorBrush(COLOR_3DLIGHT));
00825             Pie(dc, myr.left, myr.top, myr.right, myr.bottom, myr.left-1, myr.bottom, myr.right-1, myr.top);
00826 
00827             SelectObject(dc, GetSysColorPen(COLOR_3DDKSHADOW));
00828             SelectObject(dc, GetSysColorBrush(COLOR_3DDKSHADOW));
00829             Pie(dc, myr.left, myr.top, myr.right, myr.bottom, myr.right+1, myr.top, myr.left+1, myr.bottom);
00830             SelectObject(dc, hbsave);
00831             SelectObject(dc, hpsave);
00832         }
00833 
00834         i = (10*SmallDiam)/16,1;
00835         myr.left   = xc - i+i/2;
00836         myr.right  = xc + i/2;
00837         myr.top    = yc - i+i/2;
00838         myr.bottom = yc + i/2;
00839         i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE;
00840         hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
00841         hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
00842         Ellipse(dc,myr.left,myr.top,myr.right,myr.bottom);
00843         SelectObject(dc, hbsave);
00844         SelectObject(dc, hpsave);
00845     }
00846 
00847     if(uFlags & DFCS_CHECKED)
00848     {
00849         i = (6*SmallDiam)/16;
00850         i = i < 1 ? 1 : i;
00851         myr.left   = xc - i+i/2;
00852         myr.right  = xc + i/2;
00853         myr.top    = yc - i+i/2;
00854         myr.bottom = yc + i/2;
00855 
00856         i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT;
00857         hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
00858         hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
00859         Ellipse(dc,myr.left,myr.top,myr.right,myr.bottom);
00860         SelectObject(dc, hpsave);
00861         SelectObject(dc, hbsave);
00862     }
00863 
00864     /* FIXME: M$ has a polygon in the center at relative points: */
00865     /* 0.476, 0.476 (times SmallDiam, SmallDiam) */
00866     /* 0.476, 0.525 */
00867     /* 0.500, 0.500 */
00868     /* 0.500, 0.499 */
00869     /* when the button is unchecked. The reason for it is unknown. The */
00870     /* color is COLOR_BTNHIGHLIGHT, although the polygon gets painted at */
00871     /* least 3 times (it looks like a clip-region when you see it happen). */
00872     /* I do not really see a reason why this should be implemented. If you */
00873     /* have a good reason, let me know. Maybe this is a quirk in the Marlett */
00874     /* font. */
00875 
00876     return TRUE;
00877 }
00878 
00879 /***********************************************************************
00880  *           UITOOLS_DrawFrameButton
00881  */
00882 static BOOL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState)
00883 {
00884     switch(uState & 0xff)
00885     {
00886     case DFCS_BUTTONPUSH:
00887         return UITOOLS95_DFC_ButtonPush(hdc, rc, uState);
00888 
00889     case DFCS_BUTTONCHECK:
00890     case DFCS_BUTTON3STATE:
00891         return UITOOLS95_DFC_ButtonCheck(hdc, rc, uState);
00892 
00893     case DFCS_BUTTONRADIOIMAGE:
00894     case DFCS_BUTTONRADIOMASK:
00895     case DFCS_BUTTONRADIO:
00896         return UITOOLS95_DFC_ButtonRadio(hdc, rc, uState);
00897 
00898 //    default:
00899 //        WARN("Invalid button state=0x%04x\n", uState);
00900     }
00901 
00902     return FALSE;
00903 }
00904 
00905 /***********************************************************************
00906  *           UITOOLS_DrawFrameCaption
00907  *
00908  * Draw caption buttons (win95), coming from DrawFrameControl()
00909  */
00910 
00911 static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags)
00912 {
00913     POINT Line1[10];
00914     POINT Line2[10];
00915     int Line1N;
00916     int Line2N;
00917     RECT myr;
00918     int SmallDiam = UITOOLS_MakeSquareRect(r, &myr)-2;
00919     int i;
00920     HBRUSH hbsave;
00921     HPEN hpsave;
00922     HFONT hfsave, hf;
00923     int xc = (myr.left+myr.right)/2;
00924     int yc = (myr.top+myr.bottom)/2;
00925     int edge, move;
00926     char str[2] = "?";
00927     UINT alignsave;
00928     int bksave;
00929     COLORREF clrsave;
00930     SIZE size;
00931 
00932     UITOOLS95_DFC_ButtonPush(dc, r, uFlags & 0xff00);
00933 
00934     switch(uFlags & 0xff)
00935     {
00936     case DFCS_CAPTIONCLOSE:
00937         edge = 328*SmallDiam/1000;
00938         move = 95*SmallDiam/1000;
00939         Line1[0].x = Line2[0].x = Line1[1].x = Line2[1].x = xc - edge;
00940         Line1[2].y = Line2[5].y = Line1[1].y = Line2[4].y = yc - edge;
00941         Line1[3].x = Line2[3].x = Line1[4].x = Line2[4].x = xc + edge;
00942         Line1[5].y = Line2[2].y = Line1[4].y = Line2[1].y = yc + edge;
00943         Line1[2].x = Line2[2].x = Line1[1].x + move;
00944         Line1[0].y = Line2[3].y = Line1[1].y + move;
00945         Line1[5].x = Line2[5].x = Line1[4].x - move;
00946         Line1[3].y = Line2[0].y = Line1[4].y - move;
00947         Line1N = 6;
00948         Line2N = 6;
00949         break;
00950 
00951     case DFCS_CAPTIONHELP:
00952         /* This one breaks the flow */
00953         /* FIXME: We need the Marlett font in order to get this right. */
00954 
00955         hf = CreateFontA(-SmallDiam, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
00956                         ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
00957                         DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, "System");
00958         alignsave = SetTextAlign(dc, TA_TOP|TA_LEFT);
00959         bksave = SetBkMode(dc, TRANSPARENT);
00960         clrsave = GetTextColor(dc);
00961         hfsave = (HFONT)SelectObject(dc, hf);
00962         GetTextExtentPoint32A(dc, str, 1, &size);
00963 
00964         if(uFlags & DFCS_INACTIVE)
00965         {
00966             SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT));
00967             TextOutA(dc, xc-size.cx/2+1, yc-size.cy/2+1, str, 1);
00968         }
00969         SetTextColor(dc, GetSysColor(uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
00970         TextOutA(dc, xc-size.cx/2, yc-size.cy/2, str, 1);
00971 
00972         SelectObject(dc, hfsave);
00973         SetTextColor(dc, clrsave);
00974         SetBkMode(dc, bksave);
00975         SetTextAlign(dc, alignsave);
00976         DeleteObject(hf);
00977         return TRUE;
00978 
00979     case DFCS_CAPTIONMIN:
00980         Line1[0].x = Line1[3].x = myr.left   +  96*SmallDiam/750+2;
00981         Line1[1].x = Line1[2].x = Line1[0].x + 372*SmallDiam/750;
00982         Line1[0].y = Line1[1].y = myr.top    + 563*SmallDiam/750+1;
00983         Line1[2].y = Line1[3].y = Line1[0].y +  92*SmallDiam/750;
00984         Line1N = 4;
00985         Line2N = 0;
00986         break;
00987 
00988     case DFCS_CAPTIONMAX:
00989         edge = 47*SmallDiam/750;
00990         Line1[0].x = Line1[5].x = myr.left +  57*SmallDiam/750+3;
00991         Line1[0].y = Line1[1].y = myr.top  + 143*SmallDiam/750+1;
00992         Line1[1].x = Line1[2].x = Line1[0].x + 562*SmallDiam/750;
00993         Line1[5].y = Line1[4].y = Line1[0].y +  93*SmallDiam/750;
00994         Line1[2].y = Line1[3].y = Line1[0].y + 513*SmallDiam/750;
00995         Line1[3].x = Line1[4].x = Line1[1].x -  edge;
00996 
00997         Line2[0].x = Line2[5].x = Line1[0].x;
00998         Line2[3].x = Line2[4].x = Line1[1].x;
00999         Line2[1].x = Line2[2].x = Line1[0].x + edge;
01000         Line2[0].y = Line2[1].y = Line1[0].y;
01001         Line2[4].y = Line2[5].y = Line1[2].y;
01002         Line2[2].y = Line2[3].y = Line1[2].y - edge;
01003         Line1N = 6;
01004         Line2N = 6;
01005         break;
01006 
01007     case DFCS_CAPTIONRESTORE:
01008         /* FIXME: this one looks bad at small sizes < 15x15 :( */
01009         edge = 47*SmallDiam/750;
01010         move = 420*SmallDiam/750;
01011         Line1[0].x = Line1[9].x = myr.left + 198*SmallDiam/750+2;
01012         Line1[0].y = Line1[1].y = myr.top  + 169*SmallDiam/750+1;
01013         Line1[6].y = Line1[7].y = Line1[0].y + 93*SmallDiam/750;
01014         Line1[7].x = Line1[8].x = Line1[0].x + edge;
01015         Line1[1].x = Line1[2].x = Line1[0].x + move;
01016         Line1[5].x = Line1[6].x = Line1[1].x - edge;
01017         Line1[9].y = Line1[8].y = Line1[0].y + 187*SmallDiam/750;
01018         Line1[2].y = Line1[3].y = Line1[0].y + 327*SmallDiam/750;
01019         Line1[4].y = Line1[5].y = Line1[2].y - edge;
01020         Line1[3].x = Line1[4].x = Line1[2].x - 140*SmallDiam/750;
01021 
01022         Line2[1].x = Line2[2].x = Line1[3].x;
01023         Line2[7].x = Line2[8].x = Line2[1].x - edge;
01024         Line2[0].x = Line2[9].x = Line2[3].x = Line2[4].x = Line2[1].x - move;
01025         Line2[5].x = Line2[6].x = Line2[0].x + edge;
01026         Line2[0].y = Line2[1].y = Line1[9].y;
01027         Line2[4].y = Line2[5].y = Line2[8].y = Line2[9].y = Line2[0].y + 93*SmallDiam/750;
01028         Line2[2].y = Line2[3].y = Line2[0].y + 327*SmallDiam/750;
01029         Line2[6].y = Line2[7].y = Line2[2].y - edge;
01030         Line1N = 10;
01031         Line2N = 10;
01032         break;
01033 
01034     default:
01035 //        WARN("Invalid caption; flags=0x%04x\n", uFlags);
01036         return FALSE;
01037     }
01038 
01039     /* Here the drawing takes place */
01040     if(uFlags & DFCS_INACTIVE)
01041     {
01042         /* If we have an inactive button, then you see a shadow */
01043         hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
01044         hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT));
01045         Polygon(dc, Line1, Line1N);
01046         if(Line2N > 0)
01047             Polygon(dc, Line2, Line2N);
01048         SelectObject(dc, hpsave);
01049         SelectObject(dc, hbsave);
01050     }
01051 
01052     /* Correct for the shadow shift */
01053     for(i = 0; i < Line1N; i++)
01054     {
01055         Line1[i].x--;
01056         Line1[i].y--;
01057     }
01058     for(i = 0; i < Line2N; i++)
01059     {
01060         Line2[i].x--;
01061         Line2[i].y--;
01062     }
01063 
01064     /* Make the final picture */
01065     i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT;
01066     hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
01067     hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
01068 
01069     Polygon(dc, Line1, Line1N);
01070     if(Line2N > 0)
01071         Polygon(dc, Line2, Line2N);
01072     SelectObject(dc, hpsave);
01073     SelectObject(dc, hbsave);
01074 
01075     return TRUE;
01076 }
01077 
01078 
01079 /************************************************************************
01080  *      UITOOLS_DrawFrameScroll
01081  *
01082  * Draw a scroll-bar control coming from DrawFrameControl()
01083  */
01084 static BOOL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags)
01085 {
01086     POINT Line[4];
01087     RECT myr;
01088     int SmallDiam = UITOOLS_MakeSquareRect(r, &myr) - 2;
01089     int i;
01090     HBRUSH hbsave, hb, hb2;
01091     HPEN hpsave, hp, hp2;
01092     int tri = 290*SmallDiam/1000 -1;
01093     int d46, d93;
01094 
01095     /*
01096      * This fixes a problem with really tiny "scroll" buttons. In particular
01097      * with the updown control.
01098      * Making sure that the arrow is as least 3 pixels wide (or high).
01099      */
01100     if (tri == 0)
01101       tri = 1;
01102 
01103     switch(uFlags & 0xff)
01104     {
01105     case DFCS_SCROLLCOMBOBOX:
01106     case DFCS_SCROLLDOWN:
01107         Line[2].x = myr.left + 470*SmallDiam/1000 + 2;
01108         Line[2].y = myr.top  + 687*SmallDiam/1000 + 1;
01109         Line[0].x = Line[2].x - tri;
01110         Line[1].x = Line[2].x + tri;
01111         Line[0].y = Line[1].y = Line[2].y - tri;
01112         break;
01113 
01114     case DFCS_SCROLLUP:
01115         Line[2].x = myr.left + 470*SmallDiam/1000 + 2;
01116         Line[2].y = myr.bottom - 687*SmallDiam/1000 + 1;
01117         Line[0].x = Line[2].x - tri;
01118         Line[1].x = Line[2].x + tri;
01119         Line[0].y = Line[1].y = Line[2].y + tri;
01120         break;
01121 
01122     case DFCS_SCROLLLEFT:
01123         Line[2].x = myr.right - 687*SmallDiam/1000 + 1;
01124         Line[2].y = myr.top  + 470*SmallDiam/1000 + 2;
01125         Line[0].y = Line[2].y - tri;
01126         Line[1].y = Line[2].y + tri;
01127         Line[0].x = Line[1].x = Line[2].x + tri;
01128         break;
01129 
01130     case DFCS_SCROLLRIGHT:
01131         Line[2].x = myr.left + 687*SmallDiam/1000 + 1;
01132         Line[2].y = myr.top  + 470*SmallDiam/1000 + 2;
01133         Line[0].y = Line[2].y - tri;
01134         Line[1].y = Line[2].y + tri;
01135         Line[0].x = Line[1].x = Line[2].x - tri;
01136         break;
01137 
01138     case DFCS_SCROLLSIZEGRIP:
01139         /* This one breaks the flow... */
01140         UITOOLS95_DrawRectEdge(dc, r, EDGE_BUMP, BF_MIDDLE | ((uFlags&(DFCS_MONO|DFCS_FLAT)) ? BF_MONO : 0));
01141         hpsave = (HPEN)SelectObject(dc, GetStockObject(NULL_PEN));
01142         hbsave = (HBRUSH)SelectObject(dc, GetStockObject(NULL_BRUSH));
01143         if(uFlags & (DFCS_MONO|DFCS_FLAT))
01144         {
01145             hp = hp2 = GetSysColorPen(COLOR_WINDOWFRAME);
01146             hb = hb2 = GetSysColorBrush(COLOR_WINDOWFRAME);
01147         }
01148         else
01149         {
01150             hp  = GetSysColorPen(COLOR_BTNHIGHLIGHT);
01151             hp2 = GetSysColorPen(COLOR_BTNSHADOW);
01152             hb  = GetSysColorBrush(COLOR_BTNHIGHLIGHT);
01153             hb2 = GetSysColorBrush(COLOR_BTNSHADOW);
01154         }
01155         Line[0].x = Line[1].x = r->right-1;
01156         Line[2].y = Line[3].y = r->bottom-1;
01157         d46 = 46*SmallDiam/750;
01158         d93 = 93*SmallDiam/750;
01159 
01160         i = 586*SmallDiam/750;
01161         Line[0].y = r->bottom - i - 1;
01162         Line[3].x = r->right - i - 1;
01163         Line[1].y = Line[0].y + d46;
01164         Line[2].x = Line[3].x + d46;
01165         SelectObject(dc, hb);
01166         SelectObject(dc, hp);
01167         Polygon(dc, Line, 4);
01168 
01169         Line[1].y++; Line[2].x++;
01170         Line[0].y = Line[1].y + d93;
01171         Line[3].x = Line[2].x + d93;
01172         SelectObject(dc, hb2);
01173         SelectObject(dc, hp2);
01174         Polygon(dc, Line, 4);
01175 
01176         i = 398*SmallDiam/750;
01177         Line[0].y = r->bottom - i - 1;
01178         Line[3].x = r->right - i - 1;
01179         Line[1].y = Line[0].y + d46;
01180         Line[2].x = Line[3].x + d46;
01181         SelectObject(dc, hb);
01182         SelectObject(dc, hp);
01183         Polygon(dc, Line, 4);
01184 
01185         Line[1].y++; Line[2].x++;
01186         Line[0].y = Line[1].y + d93;
01187         Line[3].x = Line[2].x + d93;
01188         SelectObject(dc, hb2);
01189         SelectObject(dc, hp2);
01190         Polygon(dc, Line, 4);
01191 
01192         i = 210*SmallDiam/750;
01193         Line[0].y = r->bottom - i - 1;
01194         Line[3].x = r->right - i - 1;
01195         Line[1].y = Line[0].y + d46;
01196         Line[2].x = Line[3].x + d46;
01197         SelectObject(dc, hb);
01198         SelectObject(dc, hp);
01199         Polygon(dc, Line, 4);
01200 
01201         Line[1].y++; Line[2].x++;
01202         Line[0].y = Line[1].y + d93;
01203         Line[3].x = Line[2].x + d93;
01204         SelectObject(dc, hb2);
01205         SelectObject(dc, hp2);
01206         Polygon(dc, Line, 4);
01207 
01208         SelectObject(dc, hpsave);
01209         SelectObject(dc, hbsave);
01210         return TRUE;
01211 
01212     default:
01213 //        WARN("Invalid scroll; flags=0x%04x\n", uFlags);
01214         return FALSE;
01215     }
01216 
01217     /* Here do the real scroll-bar controls end up */
01218     if( ! (uFlags & (0xff00 & ~DFCS_ADJUSTRECT)) )
01219       /* UITOOLS95_DFC_ButtonPush always uses BF_SOFT which we don't */
01220       /* want for the normal scroll-arrow button. */
01221       UITOOLS95_DrawRectEdge( dc, r, EDGE_RAISED, (uFlags&DFCS_ADJUSTRECT) | BF_MIDDLE | BF_RECT);
01222     else
01223       UITOOLS95_DFC_ButtonPush(dc, r, (uFlags & 0xff00) );
01224 
01225     if(uFlags & DFCS_INACTIVE)
01226     {
01227         hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
01228         hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT));
01229         Polygon(dc, Line, 3);
01230         SelectObject(dc, hpsave);
01231         SelectObject(dc, hbsave);
01232     }
01233 
01234     if( (uFlags & DFCS_INACTIVE) || !(uFlags & DFCS_PUSHED) )
01235       for(i = 0; i < 3; i++)
01236       {
01237         Line[i].x--;
01238         Line[i].y--;
01239       }
01240 
01241     i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT;
01242     hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i));
01243     hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i));
01244     Polygon(dc, Line, 3);
01245     SelectObject(dc, hpsave);
01246     SelectObject(dc, hbsave);
01247 
01248     return TRUE;
01249 }
01250 
01251 /************************************************************************
01252  *      UITOOLS_DrawFrameMenu
01253  *
01254  * Draw a menu control coming from DrawFrameControl()
01255  */
01256 static BOOL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
01257 {
01258     POINT Points[6];
01259     RECT myr;
01260     int SmallDiam = UITOOLS_MakeSquareRect(r, &myr);
01261     int i;
01262     HBRUSH hbsave;
01263     HPEN hpsave;
01264     int xe, ye;
01265     int xc, yc;
01266     BOOL retval = TRUE;
01267 
01268     /* Using black and white seems to be utterly wrong, but win95 doesn't */
01269     /* use anything else. I think I tried all sys-colors to change things */
01270     /* without luck. It seems as if this behavior is inherited from the */
01271     /* win31 DFC() implementation... (you remember, B/W menus). */
01272 
01273     FillRect(dc, r, (HBRUSH)GetStockObject(WHITE_BRUSH));
01274 
01275     hbsave = (HBRUSH)SelectObject(dc, GetStockObject(BLACK_BRUSH));
01276     hpsave = (HPEN)SelectObject(dc, GetStockObject(BLACK_PEN));
01277 
01278     switch(uFlags & 0xff)
01279     {
01280     case DFCS_MENUARROW:
01281         i = 187*SmallDiam/750;
01282         Points[2].x = myr.left + 468*SmallDiam/750;
01283         Points[2].y = myr.top  + 352*SmallDiam/750+1;
01284         Points[0].y = Points[2].y - i;
01285         Points[1].y = Points[2].y + i;
01286         Points[0].x = Points[1].x = Points[2].x - i;
01287         Polygon(dc, Points, 3);
01288         break;
01289 
01290     case DFCS_MENUBULLET:
01291         xe = myr.left;
01292         ye = myr.top  + SmallDiam - SmallDiam/2;
01293         xc = myr.left + SmallDiam - SmallDiam/2;
01294         yc = myr.top  + SmallDiam - SmallDiam/2;
01295         i = 234*SmallDiam/750;
01296         i = i < 1 ? 1 : i;
01297         myr.left   = xc - i+i/2;
01298         myr.right  = xc + i/2;
01299         myr.top    = yc - i+i/2;
01300         myr.bottom = yc + i/2;
01301         Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye);
01302         break;
01303 
01304     case DFCS_MENUCHECK:
01305         Points[0].x = myr.left + 253*SmallDiam/1000;
01306         Points[0].y = myr.top  + 445*SmallDiam/1000;
01307         Points[1].x = myr.left + 409*SmallDiam/1000;
01308         Points[1].y = Points[0].y + (Points[1].x-Points[0].x);
01309         Points[2].x = myr.left + 690*SmallDiam/1000;
01310         Points[2].y = Points[1].y - (Points[2].x-Points[1].x);
01311         Points[3].x = Points[2].x;
01312         Points[3].y = Points[2].y + 3*SmallDiam/16;
01313         Points[4].x = Points[1].x;
01314         Points[4].y = Points[1].y + 3*SmallDiam/16;
01315         Points[5].x = Points[0].x;
01316         Points[5].y = Points[0].y + 3*SmallDiam/16;
01317         Polygon(dc, Points, 6);
01318         break;
01319 
01320     default:
01321 //        WARN("Invalid menu; flags=0x%04x\n", uFlags);
01322         retval = FALSE;
01323         break;
01324     }
01325 
01326     SelectObject(dc, hpsave);
01327     SelectObject(dc, hbsave);
01328     return retval;
01329 }
01330 
01331 /**********************************************************************
01332  *          DrawFrameControl  (USER32.158)
01333  */
01334 BOOL WIN32API DrawFrameControl(HDC hdc, LPRECT rc, UINT uType,
01335                                UINT uState )
01336 {
01337     /* Win95 doesn't support drawing in other mapping modes */
01338     if(GetMapMode(hdc) != MM_TEXT)
01339         return FALSE;
01340 
01341     switch(uType)
01342     {
01343     case DFC_BUTTON:
01344       return UITOOLS95_DrawFrameButton(hdc, rc, uState);
01345     case DFC_CAPTION:
01346       return UITOOLS95_DrawFrameCaption(hdc, rc, uState);
01347     case DFC_MENU:
01348       return UITOOLS95_DrawFrameMenu(hdc, rc, uState);
01349     case DFC_SCROLL:
01350       return UITOOLS95_DrawFrameScroll(hdc, rc, uState);
01351 //    default:
01352 //      WARN("(%x,%p,%d,%x), bad type!\n",
01353 //         hdc,rc,uType,uState );
01354     }
01355     return FALSE;
01356 }
01357 /******************************************************************************
01358  *
01359  * This function is used by Paint_DrawState which is inturn used by both
01360  * DrawStateA and DrawStateW. The code is directly borrowed from Wine.
01361  *
01362  ******************************************************************************/
01363 
01364 static BOOL Paint_DrawStateJam(HDC hdc, UINT opcode,
01365                                DRAWSTATEPROC func, LPARAM lp, WPARAM wp,
01366                                LPRECT rc, UINT dtflags, BOOL unicode)
01367 {
01368     HDC memdc;
01369     HBITMAP hbmsave;
01370     BOOL retval;
01371     INT cx = rc->right - rc->left;
01372     INT cy = rc->bottom - rc->top;
01373 
01374     switch(opcode)
01375     {
01376     case DST_TEXT:
01377     case DST_PREFIXTEXT:
01378         if(unicode)
01379             return DrawTextW(hdc, (LPWSTR)lp, (INT)wp, rc, dtflags);
01380         else
01381             return DrawTextA(hdc, (LPSTR)lp, (INT)wp, rc, dtflags);
01382 
01383     case DST_ICON:
01384         return DrawIcon(hdc, rc->left, rc->top, (HICON)lp);
01385 
01386     case DST_BITMAP:
01387         memdc = CreateCompatibleDC(hdc);
01388         if(!memdc) return FALSE;
01389         hbmsave = (HBITMAP)SelectObject(memdc, (HBITMAP)lp);
01390         if(!hbmsave)
01391         {
01392             DeleteDC(memdc);
01393             return FALSE;
01394         }
01395         retval = BitBlt(hdc, rc->left, rc->top, cx, cy, memdc, 0, 0, SRCCOPY);
01396         SelectObject(memdc, hbmsave);
01397         DeleteDC(memdc);
01398         return retval;
01399 
01400     case DST_COMPLEX:
01401         if(func)
01402             return func(hdc, lp, wp, cx, cy);
01403         else
01404             return FALSE;
01405     }
01406     return FALSE;
01407 }
01408 
01409 
01410 /******************************************************************************
01411  *
01412  * This function is used by both DrawStateA and DrawStateW. The code is directly
01413  * borrowed from Wine
01414  *
01415  ******************************************************************************/
01416 BOOL Paint_DrawState (HDC hdc, HBRUSH hbr, DRAWSTATEPROC func, LPARAM lp, WPARAM wp,
01417                       INT x, INT y, INT cx, INT cy, UINT flags, BOOL unicode)
01418 {
01419     HBITMAP hbm, hbmsave;
01420     HFONT hfsave;
01421     HBRUSH hbsave;
01422     HDC memdc;
01423     RECT rc;
01424     UINT dtflags = DT_NOCLIP;
01425     COLORREF fg, bg;
01426     UINT opcode = flags & 0xf;
01427     INT len = wp;
01428     BOOL retval, tmp;
01429 
01430     if((opcode == DST_TEXT || opcode == DST_PREFIXTEXT) && !len)    /* The string is '\0' terminated */
01431     {
01432         if(unicode)
01433             len = lstrlenW((LPWSTR)lp);
01434         else
01435             len = lstrlenA((LPSTR)lp);
01436    }
01437 
01438     /* Find out what size the image has if not given by caller */
01439     if(!cx || !cy)
01440     {
01441         SIZE s;
01442         BITMAP bmp;
01443 
01444         switch(opcode)
01445         {
01446         case DST_TEXT:
01447         case DST_PREFIXTEXT:
01448             if(unicode)
01449                 retval = GetTextExtentPoint32W(hdc, (LPWSTR)lp, len, &s);
01450             else
01451                 retval = GetTextExtentPoint32A(hdc, (LPSTR)lp, len, &s);
01452             if(!retval) return FALSE;
01453             break;
01454 
01455         case DST_ICON:
01456             /* Just assume the icon has the size given by GetSystemMetrics. This should be
01457                valid since both CreateIcon and LoadIcon can't create icons with different
01458                sizes. I wouldn't how else to get the size of the icon. RP
01459             */
01460             s.cx = GetSystemMetrics (SM_CXICON);
01461             s.cy = GetSystemMetrics (SM_CYICON);
01462             break;
01463 
01464         case DST_BITMAP:
01465             retval = GetObjectA ((HBITMAP) lp, sizeof (BITMAP), &bmp);
01466             if(retval == 0) return FALSE;
01467             s.cx = bmp.bmWidth;
01468             s.cy = bmp.bmHeight;
01469             break;
01470 
01471         case DST_COMPLEX: /* cx and cy must be set in this mode */
01472             return FALSE;
01473         }
01474 
01475         if(!cx) cx = s.cx;
01476         if(!cy) cy = s.cy;
01477     }
01478 
01479     rc.left   = x;
01480     rc.top    = y;
01481     rc.right  = x + cx;
01482     rc.bottom = y + cy;
01483 
01484     if(flags & DSS_RIGHT)    /* This one is not documented in the win32.hlp file */
01485         dtflags |= DT_RIGHT;
01486     if(opcode == DST_TEXT)
01487         dtflags |= DT_NOPREFIX;
01488 
01489     /* For DSS_NORMAL we just jam in the image and return */
01490     if((flags & 0x7ff0) == DSS_NORMAL)
01491     {
01492         return Paint_DrawStateJam(hdc, opcode, func, lp, len, &rc, dtflags, unicode);
01493     }
01494 
01495     /* For all other states we need to convert the image to B/W in a local bitmap */
01496     /* before it is displayed */
01497     fg = SetTextColor(hdc, RGB(0, 0, 0));
01498     bg = SetBkColor(hdc, RGB(255, 255, 255));
01499     hbm = (HBITMAP)NULL; hbmsave = (HBITMAP)NULL;
01500     memdc = (HDC)NULL; hbsave = (HBRUSH)NULL;
01501     retval = FALSE; /* assume failure */
01502 
01503     /* From here on we must use "goto cleanup" when something goes wrong */
01504     hbm     = CreateBitmap(cx, cy, 1, 1, NULL);
01505     if(!hbm) goto cleanup;
01506     memdc   = CreateCompatibleDC(hdc);
01507     if(!memdc) goto cleanup;
01508     hbmsave = (HBITMAP)SelectObject(memdc, hbm);
01509     if(!hbmsave) goto cleanup;
01510     rc.left = rc.top = 0;
01511     rc.right = cx;
01512     rc.bottom = cy;
01513     if(!FillRect(memdc, &rc, (HBRUSH)GetStockObject(WHITE_BRUSH))) goto cleanup;
01514     SetBkColor(memdc, RGB(255, 255, 255));
01515     SetTextColor(memdc, RGB(0, 0, 0));
01516     hfsave  = (HFONT)SelectObject(memdc, GetCurrentObject(hdc, OBJ_FONT));
01517     if(!hfsave && (opcode == DST_TEXT || opcode == DST_PREFIXTEXT)) goto cleanup;
01518     tmp = Paint_DrawStateJam(memdc, opcode, func, lp, len, &rc, dtflags, unicode);
01519     if(hfsave) SelectObject(memdc, hfsave);
01520     if(!tmp) goto cleanup;
01521 
01522     /* These states cause the image to be dithered */
01523     if(flags & (DSS_UNION|DSS_DISABLED))
01524     {
01525         hbsave = (HBRUSH)SelectObject(memdc,GetPattern55AABrush());
01526         if(!hbsave) goto cleanup;
01527         tmp = PatBlt(memdc, 0, 0, cx, cy, 0x00FA0089);
01528         if(hbsave) SelectObject(memdc, hbsave);
01529         if(!tmp) goto cleanup;
01530     }
01531 
01532     hbsave = (HBRUSH)SelectObject(hdc, hbr ? hbr : GetStockObject(WHITE_BRUSH));
01533     if(!hbsave) goto cleanup;
01534 
01535     if(!BitBlt(hdc, x, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup;
01536 
01537     /* DSS_DEFAULT makes the image boldface */
01538     if(flags & DSS_DEFAULT)
01539     {
01540         if(!BitBlt(hdc, x+1, y, cx, cy, memdc, 0, 0, 0x00B8074A)) goto cleanup;
01541     }
01542 
01543     retval = TRUE; /* We succeeded */
01544 
01545 cleanup:
01546     SetTextColor(hdc, fg);
01547     SetBkColor(hdc, bg);
01548 
01549     if(hbsave)  SelectObject(hdc, hbsave);
01550     if(hbmsave) SelectObject(memdc, hbmsave);
01551     if(hbm)     DeleteObject(hbm);
01552     if(memdc)   DeleteDC(memdc);
01553 
01554     return retval;
01555 }
01556 
01557 
01558 
01559 /*****************************************************************************
01560  * Name      : BOOL WIN32API DrawStateA
01561  * Purpose   : Draws a bitmap, icon, text or complex object in one of the following
01562  *             states: normal, disabled, union or mono
01563  * Parameters:
01564  * Variables :
01565  * Result    : If the function succeeds, the return value is a handle of the
01566  *               window station associated with the calling process.
01567  *             If the function fails, the return value is NULL. This can occur
01568  *               if the calling process is not an application written for Windows
01569  *               NT. To get extended error information, call GetLastError.
01570  * Remark    : Disabled doesn't look like the Windows implementation, but it does
01571  *             look disabled.
01572  * Status    : PARTIALLY IMPLEMENTED
01573  *
01574  * Author    : Rene Pronk [Sun, 1999/07/25 21:27]
01575  *****************************************************************************/
01576 
01577 BOOL WIN32API DrawStateA(HDC hdc, HBRUSH hbc, DRAWSTATEPROC lpOutputFunc, LPARAM lData,
01578                          WPARAM wData, int x, int y, int cx, int cy, UINT fuFlags)
01579 {
01580   dprintf(("USER32:DrawStateA (%08xh,%08xh,%08xh,%08xh,%08xh,%d,%d,%d,%d,%08x).\n",
01581          hdc, hbc, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags));
01582 
01583   return Paint_DrawState (hdc, hbc, lpOutputFunc, lData, wData, x, y ,cx, cy, fuFlags, FALSE);
01584 }
01585 
01586 
01587 
01588 /*****************************************************************************
01589  * Name      : BOOL WIN32API DrawStateW
01590  * Purpose   : Draws a bitmap, icon, text or complex object in one of the following
01591  *             states: normal, disabled, union or mono
01592  * Parameters:
01593  * Variables :
01594  * Result    : If the function succeeds, the return value is a handle of the
01595  *               window station associated with the calling process.
01596  *             If the function fails, the return value is NULL. This can occur
01597  *               if the calling process is not an application written for Windows
01598  *               NT. To get extended error information, call GetLastError.
01599  * Remark    : Disabled doesn't look like the Windows implementation, but it does
01600  *             look disabled.
01601  * Status    : PARTIALLY IMPLEMENTED
01602  *
01603  * Author    : Rene Pronk [Sun, 1999/07/25 21:27]
01604  *****************************************************************************/
01605 
01606 BOOL WIN32API DrawStateW(HDC hdc, HBRUSH hbc, DRAWSTATEPROC lpOutputFunc, LPARAM lData,
01607                          WPARAM wData, int x, int y, int cx, int cy, UINT fuFlags)
01608 {
01609   dprintf(("USER32:DrawStateW (%08xh,%08xh,%08xh,%08xh,%08xh,%d,%d,%d,%d,%08x).\n",
01610          hdc, hbc, lpOutputFunc, lData, wData, x, y, cx, cy, fuFlags));
01611 
01612   return Paint_DrawState (hdc, hbc, lpOutputFunc, lData, wData, x, y ,cx, cy, fuFlags, TRUE);
01613 }
01614 //******************************************************************************
01615 //******************************************************************************
01616 BOOL WIN32API DrawFocusRect( HDC hdc, const RECT *lpRect)
01617 {
01618 #if 0
01619     //TODO: This doesn't work. Find out why (SetBkMode!)
01620 
01621     HBRUSH hOldBrush;
01622     HPEN hOldPen, hNewPen;
01623     INT oldDrawMode, oldBkMode;
01624 
01625     dprintf(("USER32: DrawFocusRect %x %x", hdc, lpRect));
01626 
01627     hOldBrush = SelectObject(hdc, GetStockObject(NULL_BRUSH));
01628     hNewPen = CreatePen(PS_ALTERNATE, 1, GetSysColor(COLOR_WINDOWTEXT));
01629     hOldPen = SelectObject(hdc, hNewPen);
01630     oldDrawMode = SetROP2(hdc, R2_XORPEN);
01631     oldBkMode = SetBkMode(hdc, TRANSPARENT);
01632 
01633     Rectangle(hdc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom);
01634 
01635     SetBkMode(hdc, oldBkMode);
01636     SetROP2(hdc, oldDrawMode);
01637     SelectObject(hdc, hOldPen);
01638     DeleteObject(hNewPen);
01639     SelectObject(hdc, hOldBrush);
01640 
01641     return TRUE;
01642 #else
01643  BOOL rc;
01644 
01645     rc = O32_DrawFocusRect(hdc, lpRect);
01646     dprintf(("USER32:  DrawFocusRect %x %x returned %d", hdc, lpRect, rc));
01647     return rc;
01648 #endif
01649 }
01650 //******************************************************************************
01651 //******************************************************************************
01652 BOOL WIN32API DrawIcon( HDC hDC, int X, int Y, HICON  hIcon)
01653 {
01654   ICONINFO ii;
01655   HDC hMemDC;
01656   BITMAP bmp;
01657   HBITMAP oldBmp;
01658   COLORREF oldFg,oldBg;
01659 
01660   dprintf(("USER32:  DrawIcon\n"));
01661 
01662   if (!hDC || !hIcon)
01663   {
01664     SetLastError(ERROR_INVALID_PARAMETER);
01665 
01666     return FALSE;
01667   }
01668 
01669   if (!GetIconInfo(hIcon,&ii)) return FALSE;
01670   oldFg = SetTextColor(hDC,RGB(0,0,0));
01671   oldBg = SetBkColor(hDC,RGB(255,255,255));
01672   hMemDC = CreateCompatibleDC(hDC);
01673   oldBmp = SelectObject(hMemDC,ii.hbmMask);
01674   if (ii.hbmColor)
01675   {
01676     GetObjectA(ii.hbmColor,sizeof(BITMAP),(LPVOID)&bmp);
01677     BitBlt(hDC,X,Y,bmp.bmWidth,bmp.bmHeight,hMemDC,0,0,SRCAND);
01678     SelectObject(hMemDC,ii.hbmColor);
01679     BitBlt(hDC,X,Y,bmp.bmWidth,bmp.bmHeight,hMemDC,0,0,SRCINVERT);
01680   } else
01681   {
01682     GetObjectA(ii.hbmMask,sizeof(BITMAP),(LPVOID)&bmp);
01683     BitBlt(hDC,X,Y,bmp.bmWidth,bmp.bmHeight/2,hMemDC,0,0,SRCAND);
01684     BitBlt(hDC,X,Y,bmp.bmWidth,bmp.bmHeight/2,hMemDC,0,bmp.bmHeight/2,SRCINVERT);
01685   }
01686   SelectObject(hMemDC,oldBmp);
01687   DeleteDC(hMemDC);
01688   if (ii.hbmColor) DeleteObject(ii.hbmColor);
01689   if (ii.hbmMask) DeleteObject(ii.hbmMask);
01690   SetTextColor(hDC,oldFg);
01691   SetBkColor(hDC,oldBg);
01692 
01693   return TRUE;
01694 }
01695 //******************************************************************************
01696 //******************************************************************************
01697 BOOL WIN32API DrawIconEx(HDC hdc, int xLeft, int yTop, HICON hIcon,
01698                          int cxWidth, int cyWidth, UINT istepIfAniCur,
01699                          HBRUSH hbrFlickerFreeDraw, UINT diFlags)
01700 {
01701   ICONINFO ii;
01702   HDC hMemDC;
01703   BITMAP bmp;
01704   HBITMAP oldBmp;
01705   COLORREF oldFg,oldBg;
01706   INT oldStretchMode;
01707 
01708   dprintf(("USER32:  DrawIconEx"));
01709 
01710   //CB: istepIfAniCur, DI_COMPAT ignored
01711 
01712   if (!hdc || !hIcon)
01713   {
01714     SetLastError(ERROR_INVALID_PARAMETER);
01715 
01716     return FALSE;
01717   }
01718 
01719   if (!GetIconInfo(hIcon,&ii)) return FALSE;
01720   if (ii.hbmColor)
01721     GetObjectA(ii.hbmColor,sizeof(BITMAP),(LPVOID)&bmp);
01722   else
01723     GetObjectA(ii.hbmMask,sizeof(BITMAP),(LPVOID)&bmp);
01724 
01725   /* Calculate the size of the destination image.  */
01726   if (diFlags & DI_DEFAULTSIZE)
01727   {
01728     cxWidth = GetSystemMetrics(SM_CXICON);
01729     cyWidth = GetSystemMetrics(SM_CYICON);
01730   } else if (cxWidth == 0)
01731   {
01732     cxWidth = bmp.bmWidth;
01733   } else if (cyWidth == 0)
01734   {
01735     cyWidth = ii.hbmColor ? bmp.bmHeight:bmp.bmHeight/2;
01736   }
01737 
01738   if (hbrFlickerFreeDraw)
01739   {
01740     HDC hBmpDC = CreateCompatibleDC(hdc);
01741     HBITMAP oldMemBmp, memBmp = CreateCompatibleBitmap(hdc,cxWidth,cyWidth);
01742     RECT rect;
01743 
01744     oldMemBmp = SelectObject(hBmpDC,memBmp);
01745     rect.left = 0;
01746     rect.top = 0;
01747     rect.right = cxWidth;
01748     rect.bottom = cyWidth;
01749     FillRect(hBmpDC,&rect,hbrFlickerFreeDraw);
01750     oldFg = SetTextColor(hBmpDC,RGB(0,0,0));
01751     oldBg = SetBkColor(hBmpDC,RGB(255,255,255));
01752     hMemDC = CreateCompatibleDC(hdc);
01753     oldBmp = SelectObject(hMemDC,ii.hbmMask);
01754     oldStretchMode = SetStretchBltMode(hBmpDC,STRETCH_DELETESCANS);
01755     if (ii.hbmColor)
01756     {
01757       if (diFlags & DI_MASK)
01758         StretchBlt(hBmpDC,0,0,cxWidth,cyWidth,hMemDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCAND);
01759       if (diFlags & DI_IMAGE)
01760       {
01761         SelectObject(hMemDC,ii.hbmColor);
01762         StretchBlt(hBmpDC,0,0,cxWidth,cyWidth,hMemDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCINVERT);
01763       }
01764     } else if (diFlags & DI_MASK)
01765     {
01766       StretchBlt(hBmpDC,0,0,cxWidth,cyWidth,hMemDC,0,0,bmp.bmWidth,bmp.bmHeight/2,SRCAND);
01767       StretchBlt(hBmpDC,0,0,cxWidth,cyWidth,hMemDC,0,bmp.bmHeight/2,bmp.bmWidth,bmp.bmHeight/2,SRCINVERT);
01768     }
01769     BitBlt(hdc,xLeft,yTop,cxWidth,cyWidth,hBmpDC,0,0,SRCCOPY);
01770     SelectObject(hMemDC,oldBmp);
01771     DeleteDC(hMemDC);
01772     SetTextColor(hdc,oldFg);
01773     SetBkColor(hdc,oldBg);
01774     SetStretchBltMode(hBmpDC,oldStretchMode);
01775     SelectObject(hBmpDC,oldMemBmp);
01776     DeleteDC(hBmpDC);
01777     DeleteObject(memBmp);
01778   } else
01779   {
01780     oldFg = SetTextColor(hdc,RGB(0,0,0));
01781     oldBg = SetBkColor(hdc,RGB(255,255,255));
01782     hMemDC = CreateCompatibleDC(hdc);
01783     oldBmp = SelectObject(hMemDC,ii.hbmMask);
01784     oldStretchMode = SetStretchBltMode(hdc,STRETCH_DELETESCANS);
01785     if (ii.hbmColor)
01786     {
01787       if (diFlags & DI_MASK)
01788         StretchBlt(hdc,xLeft,yTop,cxWidth,cyWidth,hMemDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCAND);
01789       if (diFlags & DI_IMAGE)
01790       {
01791         SelectObject(hMemDC,ii.hbmColor);
01792         StretchBlt(hdc,xLeft,yTop,cxWidth,cyWidth,hMemDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCINVERT);
01793       }
01794     } else if (diFlags & DI_MASK)
01795     {
01796       StretchBlt(hdc,xLeft,yTop,cxWidth,cyWidth,hMemDC,0,0,bmp.bmWidth,bmp.bmHeight,SRCAND);
01797       StretchBlt(hdc,xLeft,yTop,cxWidth,cyWidth,hMemDC,0,bmp.bmHeight/2,bmp.bmWidth,bmp.bmHeight/2,SRCINVERT);
01798     }
01799     SelectObject(hMemDC,oldBmp);
01800     DeleteDC(hMemDC);
01801     SetTextColor(hdc,oldFg);
01802     SetBkColor(hdc,oldBg);
01803     SetStretchBltMode(hdc,oldStretchMode);
01804   }
01805   if (ii.hbmColor) DeleteObject(ii.hbmColor);
01806   if (ii.hbmMask) DeleteObject(ii.hbmMask);
01807 
01808   return TRUE;
01809 }
01810 /*****************************************************************************
01811  * Name      : BOOL WIN32API DrawAnimatedRects
01812  * Purpose   : The DrawAnimatedRects function draws a wire-frame rectangle
01813  *             and animates it to indicate the opening of an icon or the
01814  *             minimizing or maximizing of a window.
01815  * Parameters: HWND hwnd             handle of clipping window
01816  *             int idAni             type of animation
01817  *             CONST RECT * lprcFrom address of rectangle coordinates (minimized)
01818  *             CONST RECT * lprcTo   address of rectangle coordinates (restored)
01819  * Variables :
01820  * Result    : If the function succeeds, the return value is TRUE.
01821  *             If the function fails, the return value is FALSE.
01822  * Remark    :
01823  * Status    : UNTESTED STUB
01824  *
01825  * Author    : Patrick Haller [Thu, 1998/02/26 11:55]
01826  *****************************************************************************/
01827 
01828 BOOL WIN32API DrawAnimatedRects(HWND hwnd,
01829                                    int  idAni,
01830                                    CONST RECT *lprcFrom,
01831                                    CONST RECT *lprcTo)
01832 {
01833   dprintf(("USER32:DrawAnimatedRects (%08xh,%u,%08xh,%08x) not implemented.\n",
01834          hwnd,
01835          idAni,
01836          lprcFrom,
01837          lprcTo));
01838 
01839   return (TRUE);
01840 }
01841 //******************************************************************************
01842 //******************************************************************************

Generated on Wed Jan 23 23:17:44 2002 for ODIN-user32 by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001