diff --git a/reactos/lib/user32/windows/draw.c b/reactos/lib/user32/windows/draw.c index ee433e45cd1..0ed4d0943d9 100644 --- a/reactos/lib/user32/windows/draw.c +++ b/reactos/lib/user32/windows/draw.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: draw.c,v 1.4 2002/09/08 10:23:12 chorns Exp $ +/* $Id: draw.c,v 1.5 2002/11/24 20:25:49 jfilby Exp $ * * PROJECT: ReactOS user32.dll * FILE: lib/user32/windows/input.c @@ -36,8 +36,1334 @@ #define COLOR_MAX (28) +/* HPEN STDCALL W32kGetSysColorPen(int nIndex); */ + +static const WORD wPattern_AA55[8] = { 0xaaaa, 0x5555, 0xaaaa, 0x5555, + 0xaaaa, 0x5555, 0xaaaa, 0x5555 }; + +/* These tables are used in: + * UITOOLS_DrawDiagEdge() + * UITOOLS_DrawRectEdge() + */ +static const signed char LTInnerNormal[] = { + -1, -1, -1, -1, + -1, COLOR_BTNHIGHLIGHT, COLOR_BTNHIGHLIGHT, -1, + -1, COLOR_3DDKSHADOW, COLOR_3DDKSHADOW, -1, + -1, -1, -1, -1 +}; + +static const signed char LTOuterNormal[] = { + -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, + COLOR_BTNHIGHLIGHT, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, + COLOR_3DDKSHADOW, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1, + -1, COLOR_3DLIGHT, COLOR_BTNSHADOW, -1 +}; + +static const signed char RBInnerNormal[] = { + -1, -1, -1, -1, + -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1, + -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1, + -1, -1, -1, -1 +}; + +static const signed char RBOuterNormal[] = { + -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, + COLOR_BTNSHADOW, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, + COLOR_3DLIGHT, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1, + -1, COLOR_3DDKSHADOW, COLOR_BTNHIGHLIGHT, -1 +}; + +static const signed char LTInnerSoft[] = { + -1, -1, -1, -1, + -1, COLOR_3DLIGHT, COLOR_3DLIGHT, -1, + -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, -1, + -1, -1, -1, -1 +}; + +static const signed char LTOuterSoft[] = { + -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1, + COLOR_3DLIGHT, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1, + COLOR_BTNSHADOW, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1, + -1, COLOR_BTNHIGHLIGHT, COLOR_3DDKSHADOW, -1 +}; + +#define RBInnerSoft RBInnerNormal /* These are the same */ +#define RBOuterSoft RBOuterNormal + +static const signed char LTRBOuterMono[] = { + -1, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, + COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, + COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, + COLOR_WINDOW, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, COLOR_WINDOWFRAME, +}; + +static const signed char LTRBInnerMono[] = { + -1, -1, -1, -1, + -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, + -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, + -1, COLOR_WINDOW, COLOR_WINDOW, COLOR_WINDOW, +}; + +static const signed char LTRBOuterFlat[] = { + -1, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, + COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, + COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, + COLOR_BTNFACE, COLOR_BTNSHADOW, COLOR_BTNSHADOW, COLOR_BTNSHADOW, +}; + +static const signed char LTRBInnerFlat[] = { + -1, -1, -1, -1, + -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE, + -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE, + -1, COLOR_BTNFACE, COLOR_BTNFACE, COLOR_BTNFACE, +}; + /* FUNCTIONS *****************************************************************/ + +HPEN STDCALL GetSysColorPen(int nIndex); +HBRUSH STDCALL GetSysColorBrush(int nIndex); + +/* Ported from WINE20020904 */ +/* Same as DrawEdge invoked with BF_DIAGONAL */ +static BOOL UITOOLS95_DrawDiagEdge(HDC hdc, LPRECT rc, + UINT uType, UINT uFlags) +{ + POINT Points[4]; + signed char InnerI, OuterI; + HPEN InnerPen, OuterPen; + POINT SavePoint; + HPEN SavePen; + int spx, spy; + int epx, epy; + int Width = rc->right - rc->left; + int Height= rc->bottom - rc->top; + int SmallDiam = Width > Height ? Height : Width; + BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER + || (uType & BDR_OUTER) == BDR_OUTER) + && !(uFlags & (BF_FLAT|BF_MONO)) ); + int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0) + + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0); + + /* Init some vars */ + OuterPen = InnerPen = (HPEN)GetStockObject(NULL_PEN); + SavePen = (HPEN)SelectObject(hdc, InnerPen); + spx = spy = epx = epy = 0; /* Satisfy the compiler... */ + + /* Determine the colors of the edges */ + if(uFlags & BF_MONO) + { + InnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)]; + OuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)]; + } + else if(uFlags & BF_FLAT) + { + InnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)]; + OuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)]; + } + else if(uFlags & BF_SOFT) + { + if(uFlags & BF_BOTTOM) + { + InnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; + OuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; + } + else + { + InnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; + OuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; + } + } + else + { + if(uFlags & BF_BOTTOM) + { + InnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; + OuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; + } + else + { + InnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; + OuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; + } + } + + if(InnerI != -1) InnerPen = GetSysColorPen(InnerI); + if(OuterI != -1) OuterPen = GetSysColorPen(OuterI); + + MoveToEx(hdc, 0, 0, &SavePoint); + + /* Don't ask me why, but this is what is visible... */ + /* This must be possible to do much simpler, but I fail to */ + /* see the logic in the MS implementation (sigh...). */ + /* So, this might look a bit brute force here (and it is), but */ + /* it gets the job done;) */ + + switch(uFlags & BF_RECT) + { + case 0: + case BF_LEFT: + case BF_BOTTOM: + case BF_BOTTOMLEFT: + /* Left bottom endpoint */ + epx = rc->left-1; + spx = epx + SmallDiam; + epy = rc->bottom; + spy = epy - SmallDiam; + break; + + case BF_TOPLEFT: + case BF_BOTTOMRIGHT: + /* Left top endpoint */ + epx = rc->left-1; + spx = epx + SmallDiam; + epy = rc->top-1; + spy = epy + SmallDiam; + break; + + case BF_TOP: + case BF_RIGHT: + case BF_TOPRIGHT: + case BF_RIGHT|BF_LEFT: + case BF_RIGHT|BF_LEFT|BF_TOP: + case BF_BOTTOM|BF_TOP: + case BF_BOTTOM|BF_TOP|BF_LEFT: + case BF_BOTTOMRIGHT|BF_LEFT: + case BF_BOTTOMRIGHT|BF_TOP: + case BF_RECT: + /* Right top endpoint */ + spx = rc->left; + epx = spx + SmallDiam; + spy = rc->bottom-1; + epy = spy - SmallDiam; + break; + } + + MoveToEx(hdc, spx, spy, NULL); + SelectObject(hdc, OuterPen); + LineTo(hdc, epx, epy); + + SelectObject(hdc, InnerPen); + + switch(uFlags & (BF_RECT|BF_DIAGONAL)) + { + case BF_DIAGONAL_ENDBOTTOMLEFT: + case (BF_DIAGONAL|BF_BOTTOM): + case BF_DIAGONAL: + case (BF_DIAGONAL|BF_LEFT): + MoveToEx(hdc, spx-1, spy, NULL); + LineTo(hdc, epx, epy-1); + Points[0].x = spx-add; + Points[0].y = spy; + Points[1].x = rc->left; + Points[1].y = rc->top; + Points[2].x = epx+1; + Points[2].y = epy-1-add; + Points[3] = Points[2]; + break; + + case BF_DIAGONAL_ENDBOTTOMRIGHT: + MoveToEx(hdc, spx-1, spy, NULL); + LineTo(hdc, epx, epy+1); + Points[0].x = spx-add; + Points[0].y = spy; + Points[1].x = rc->left; + Points[1].y = rc->bottom-1; + Points[2].x = epx+1; + Points[2].y = epy+1+add; + Points[3] = Points[2]; + break; + + case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP): + case (BF_DIAGONAL|BF_BOTTOM|BF_RIGHT|BF_TOP|BF_LEFT): + case BF_DIAGONAL_ENDTOPRIGHT: + case (BF_DIAGONAL|BF_RIGHT|BF_TOP|BF_LEFT): + MoveToEx(hdc, spx+1, spy, NULL); + LineTo(hdc, epx, epy+1); + Points[0].x = epx-1; + Points[0].y = epy+1+add; + Points[1].x = rc->right-1; + Points[1].y = rc->top+add; + Points[2].x = rc->right-1; + Points[2].y = rc->bottom-1; + Points[3].x = spx+add; + Points[3].y = spy; + break; + + case BF_DIAGONAL_ENDTOPLEFT: + MoveToEx(hdc, spx, spy-1, NULL); + LineTo(hdc, epx+1, epy); + Points[0].x = epx+1+add; + Points[0].y = epy+1; + Points[1].x = rc->right-1; + Points[1].y = rc->top; + Points[2].x = rc->right-1; + Points[2].y = rc->bottom-1-add; + Points[3].x = spx; + Points[3].y = spy-add; + break; + + case (BF_DIAGONAL|BF_TOP): + case (BF_DIAGONAL|BF_BOTTOM|BF_TOP): + case (BF_DIAGONAL|BF_BOTTOM|BF_TOP|BF_LEFT): + MoveToEx(hdc, spx+1, spy-1, NULL); + LineTo(hdc, epx, epy); + Points[0].x = epx-1; + Points[0].y = epy+1; + Points[1].x = rc->right-1; + Points[1].y = rc->top; + Points[2].x = rc->right-1; + Points[2].y = rc->bottom-1-add; + Points[3].x = spx+add; + Points[3].y = spy-add; + break; + + case (BF_DIAGONAL|BF_RIGHT): + case (BF_DIAGONAL|BF_RIGHT|BF_LEFT): + case (BF_DIAGONAL|BF_RIGHT|BF_LEFT|BF_BOTTOM): + MoveToEx(hdc, spx, spy, NULL); + LineTo(hdc, epx-1, epy+1); + Points[0].x = spx; + Points[0].y = spy; + Points[1].x = rc->left; + Points[1].y = rc->top+add; + Points[2].x = epx-1-add; + Points[2].y = epy+1+add; + Points[3] = Points[2]; + break; + } + + /* Fill the interior if asked */ + if((uFlags & BF_MIDDLE) && retval) + { + HBRUSH hbsave; + HBRUSH hb = GetSysColorBrush(uFlags & BF_MONO ? COLOR_WINDOW : COLOR_BTNFACE); + HPEN hpsave; + HPEN hp = GetSysColorPen(uFlags & BF_MONO ? COLOR_WINDOW : COLOR_BTNFACE); + hbsave = (HBRUSH)SelectObject(hdc, hb); + hpsave = (HPEN)SelectObject(hdc, hp); + Polygon(hdc, Points, 4); + SelectObject(hdc, hbsave); + SelectObject(hdc, hpsave); + } + + /* Adjust rectangle if asked */ + if(uFlags & BF_ADJUST) + { + if(uFlags & BF_LEFT) rc->left += add; + if(uFlags & BF_RIGHT) rc->right -= add; + if(uFlags & BF_TOP) rc->top += add; + if(uFlags & BF_BOTTOM) rc->bottom -= add; + } + + /* Cleanup */ + SelectObject(hdc, SavePen); + MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL); + + return retval; +} + +/* Ported from WINE20020904 */ +/* Same as DrawEdge invoked without BF_DIAGONAL + * + * 23-Nov-1997: Changed by Bertho Stultiens + * + * Well, I started testing this and found out that there are a few things + * that weren't quite as win95. The following rewrite should reproduce + * win95 results completely. + * The colorselection is table-driven to avoid awfull if-statements. + * The table below show the color settings. + * + * Pen selection table for uFlags = 0 + * + * uType | LTI | LTO | RBI | RBO + * ------+-------+-------+-------+------- + * 0000 | x | x | x | x + * 0001 | x | 22 | x | 21 + * 0010 | x | 16 | x | 20 + * 0011 | x | x | x | x + * ------+-------+-------+-------+------- + * 0100 | x | 20 | x | 16 + * 0101 | 20 | 22 | 16 | 21 + * 0110 | 20 | 16 | 16 | 20 + * 0111 | x | x | x | x + * ------+-------+-------+-------+------- + * 1000 | x | 21 | x | 22 + * 1001 | 21 | 22 | 22 | 21 + * 1010 | 21 | 16 | 22 | 20 + * 1011 | x | x | x | x + * ------+-------+-------+-------+------- + * 1100 | x | x | x | x + * 1101 | x | x (22)| x | x (21) + * 1110 | x | x (16)| x | x (20) + * 1111 | x | x | x | x + * + * Pen selection table for uFlags = BF_SOFT + * + * uType | LTI | LTO | RBI | RBO + * ------+-------+-------+-------+------- + * 0000 | x | x | x | x + * 0001 | x | 20 | x | 21 + * 0010 | x | 21 | x | 20 + * 0011 | x | x | x | x + * ------+-------+-------+-------+------- + * 0100 | x | 22 | x | 16 + * 0101 | 22 | 20 | 16 | 21 + * 0110 | 22 | 21 | 16 | 20 + * 0111 | x | x | x | x + * ------+-------+-------+-------+------- + * 1000 | x | 16 | x | 22 + * 1001 | 16 | 20 | 22 | 21 + * 1010 | 16 | 21 | 22 | 20 + * 1011 | x | x | x | x + * ------+-------+-------+-------+------- + * 1100 | x | x | x | x + * 1101 | x | x (20)| x | x (21) + * 1110 | x | x (21)| x | x (20) + * 1111 | x | x | x | x + * + * x = don't care; (n) = is what win95 actually uses + * LTI = left Top Inner line + * LTO = left Top Outer line + * RBI = Right Bottom Inner line + * RBO = Right Bottom Outer line + * 15 = COLOR_BTNFACE + * 16 = COLOR_BTNSHADOW + * 20 = COLOR_BTNHIGHLIGHT + * 21 = COLOR_3DDKSHADOW + * 22 = COLOR_3DLIGHT + */ +static BOOL UITOOLS95_DrawRectEdge(HDC hdc, LPRECT rc, + UINT uType, UINT uFlags) +{ + signed char LTInnerI, LTOuterI; + signed char RBInnerI, RBOuterI; + HPEN LTInnerPen, LTOuterPen; + HPEN RBInnerPen, RBOuterPen; + RECT InnerRect = *rc; + POINT SavePoint; + HPEN SavePen; + int LBpenplus = 0; + int LTpenplus = 0; + int RTpenplus = 0; + int RBpenplus = 0; + BOOL retval = !( ((uType & BDR_INNER) == BDR_INNER + || (uType & BDR_OUTER) == BDR_OUTER) + && !(uFlags & (BF_FLAT|BF_MONO)) ); + + /* Init some vars */ + LTInnerPen = LTOuterPen = RBInnerPen = RBOuterPen = (HPEN)GetStockObject(NULL_PEN); + SavePen = (HPEN)SelectObject(hdc, LTInnerPen); + + /* Determine the colors of the edges */ + if(uFlags & BF_MONO) + { + LTInnerI = RBInnerI = LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)]; + LTOuterI = RBOuterI = LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)]; + } + else if(uFlags & BF_FLAT) + { + LTInnerI = RBInnerI = LTRBInnerFlat[uType & (BDR_INNER|BDR_OUTER)]; + LTOuterI = RBOuterI = LTRBOuterFlat[uType & (BDR_INNER|BDR_OUTER)]; + + /* Bertho Stultiens states above that this function exactly matches win95 + * In win98 BF_FLAT rectangles have an inner border same color as the + * middle (COLOR_BTNFACE). I believe it's the same for win95 but since + * I don't know I go with Bertho and just sets it for win98 until proven + * otherwise. + * Dennis Björklund, 10 June, 99 + */ +/* if( TWEAK_WineLook == WIN98_LOOK && LTInnerI != -1 ) + LTInnerI = RBInnerI = COLOR_BTNFACE; */ + } + else if(uFlags & BF_SOFT) + { + LTInnerI = LTInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; + LTOuterI = LTOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; + RBInnerI = RBInnerSoft[uType & (BDR_INNER|BDR_OUTER)]; + RBOuterI = RBOuterSoft[uType & (BDR_INNER|BDR_OUTER)]; + } + else + { + LTInnerI = LTInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; + LTOuterI = LTOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; + RBInnerI = RBInnerNormal[uType & (BDR_INNER|BDR_OUTER)]; + RBOuterI = RBOuterNormal[uType & (BDR_INNER|BDR_OUTER)]; + } + + if((uFlags & BF_BOTTOMLEFT) == BF_BOTTOMLEFT) LBpenplus = 1; + if((uFlags & BF_TOPRIGHT) == BF_TOPRIGHT) RTpenplus = 1; + if((uFlags & BF_BOTTOMRIGHT) == BF_BOTTOMRIGHT) RBpenplus = 1; + if((uFlags & BF_TOPLEFT) == BF_TOPLEFT) LTpenplus = 1; + + if(LTInnerI != -1) LTInnerPen = GetSysColorPen(LTInnerI); + if(LTOuterI != -1) LTOuterPen = GetSysColorPen(LTOuterI); + if(RBInnerI != -1) RBInnerPen = GetSysColorPen(RBInnerI); + if(RBOuterI != -1) RBOuterPen = GetSysColorPen(RBOuterI); + + MoveToEx(hdc, 0, 0, &SavePoint); + + /* Draw the outer edge */ + SelectObject(hdc, LTOuterPen); + if(uFlags & BF_TOP) + { + MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL); + LineTo(hdc, InnerRect.right, InnerRect.top); + } + if(uFlags & BF_LEFT) + { + MoveToEx(hdc, InnerRect.left, InnerRect.top, NULL); + LineTo(hdc, InnerRect.left, InnerRect.bottom); + } + SelectObject(hdc, RBOuterPen); + if(uFlags & BF_BOTTOM) + { + MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL); + LineTo(hdc, InnerRect.left-1, InnerRect.bottom-1); + } + if(uFlags & BF_RIGHT) + { + MoveToEx(hdc, InnerRect.right-1, InnerRect.bottom-1, NULL); + LineTo(hdc, InnerRect.right-1, InnerRect.top-1); + } + + /* Draw the inner edge */ + SelectObject(hdc, LTInnerPen); + if(uFlags & BF_TOP) + { + MoveToEx(hdc, InnerRect.left+LTpenplus, InnerRect.top+1, NULL); + LineTo(hdc, InnerRect.right-RTpenplus, InnerRect.top+1); + } + if(uFlags & BF_LEFT) + { + MoveToEx(hdc, InnerRect.left+1, InnerRect.top+LTpenplus, NULL); + LineTo(hdc, InnerRect.left+1, InnerRect.bottom-LBpenplus); + } + SelectObject(hdc, RBInnerPen); + if(uFlags & BF_BOTTOM) + { + MoveToEx(hdc, InnerRect.right-1-RBpenplus, InnerRect.bottom-2, NULL); + LineTo(hdc, InnerRect.left-1+LBpenplus, InnerRect.bottom-2); + } + if(uFlags & BF_RIGHT) + { + MoveToEx(hdc, InnerRect.right-2, InnerRect.bottom-1-RBpenplus, NULL); + LineTo(hdc, InnerRect.right-2, InnerRect.top-1+RTpenplus); + } + + if( ((uFlags & BF_MIDDLE) && retval) || (uFlags & BF_ADJUST) ) + { + int add = (LTRBInnerMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0) + + (LTRBOuterMono[uType & (BDR_INNER|BDR_OUTER)] != -1 ? 1 : 0); + + if(uFlags & BF_LEFT) InnerRect.left += add; + if(uFlags & BF_RIGHT) InnerRect.right -= add; + if(uFlags & BF_TOP) InnerRect.top += add; + if(uFlags & BF_BOTTOM) InnerRect.bottom -= add; + + if((uFlags & BF_MIDDLE) && retval) + { + FillRect(hdc, &InnerRect, GetSysColorBrush(uFlags & BF_MONO ? + COLOR_WINDOW : COLOR_BTNFACE)); + } + + if(uFlags & BF_ADJUST) + *rc = InnerRect; + } + + /* Cleanup */ + SelectObject(hdc, SavePen); + MoveToEx(hdc, SavePoint.x, SavePoint.y, NULL); + return retval; +} + +/* Ported from WINE20020904 */ +/* Utility to create a square rectangle and returning the width */ +static int UITOOLS_MakeSquareRect(LPRECT src, LPRECT dst) +{ + int Width = src->right - src->left; + int Height = src->bottom - src->top; + int SmallDiam = Width > Height ? Height : Width; + + *dst = *src; + + /* Make it a square box */ + if(Width < Height) /* SmallDiam == Width */ + { + dst->top += (Height-Width)/2; + dst->bottom = dst->top + SmallDiam; + } + else if(Width > Height) /* SmallDiam == Height */ + { + dst->left += (Width-Height)/2; + dst->right = dst->left + SmallDiam; + } + + return SmallDiam; +} + +/* Ported from WINE20020904 */ +static void UITOOLS_DrawCheckedRect( HDC dc, LPRECT rect ) +{ + if(GetSysColor(COLOR_BTNHIGHLIGHT) == RGB(255, 255, 255)) + { + HBITMAP hbm = CreateBitmap(8, 8, 1, 1, wPattern_AA55); + HBRUSH hbsave; + HBRUSH hb = CreatePatternBrush(hbm); + COLORREF bg; + + FillRect(dc, rect, GetSysColorBrush(COLOR_BTNFACE)); + bg = SetBkColor(dc, RGB(255, 255, 255)); + hbsave = (HBRUSH)SelectObject(dc, hb); + PatBlt(dc, rect->left, rect->top, rect->right-rect->left, rect->bottom-rect->top, 0x00FA0089); + SelectObject(dc, hbsave); + SetBkColor(dc, bg); + DeleteObject(hb); + DeleteObject(hbm); + } + else + { + FillRect(dc, rect, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); + } +} + +/* Ported from WINE20020904 */ +/* Draw a push button coming from DrawFrameControl() + * + * Does a pretty good job in emulating MS behavior. Some quirks are + * however there because MS uses a TrueType font (Marlett) to draw + * the buttons. + */ +static BOOL UITOOLS95_DFC_ButtonPush(HDC dc, LPRECT r, UINT uFlags) +{ + UINT edge; + RECT myr = *r; + + if(uFlags & (DFCS_PUSHED | DFCS_CHECKED | DFCS_FLAT)) + edge = EDGE_SUNKEN; + else + edge = EDGE_RAISED; + + if(uFlags & DFCS_CHECKED) + { + if(uFlags & DFCS_MONO) + UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST); + else + UITOOLS95_DrawRectEdge(dc, &myr, edge, (uFlags&DFCS_FLAT)|BF_RECT|BF_SOFT|BF_ADJUST); + + UITOOLS_DrawCheckedRect( dc, &myr ); + } + else + { + if(uFlags & DFCS_MONO) + { + UITOOLS95_DrawRectEdge(dc, &myr, edge, BF_MONO|BF_RECT|BF_ADJUST); + FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE)); + } + else + { + UITOOLS95_DrawRectEdge(dc, r, edge, (uFlags&DFCS_FLAT) | BF_MIDDLE | BF_RECT); + } + } + + /* Adjust rectangle if asked */ + if(uFlags & DFCS_ADJUSTRECT) + { + r->left += 2; + r->right -= 2; + r->top += 2; + r->bottom -= 2; + } + + return TRUE; +} + +/* Ported from WINE20020904 */ +/* Draw a check/3state button coming from DrawFrameControl() + * + * Does a pretty good job in emulating MS behavior. Some quirks are + * however there because MS uses a TrueType font (Marlett) to draw + * the buttons. + */ +static BOOL UITOOLS95_DFC_ButtonCheck(HDC dc, LPRECT r, UINT uFlags) +{ + RECT myr, bar; + UINT flags = BF_RECT | BF_ADJUST; + UITOOLS_MakeSquareRect(r, &myr); + + if(uFlags & DFCS_FLAT) flags |= BF_FLAT; + else if(uFlags & DFCS_MONO) flags |= BF_MONO; + + UITOOLS95_DrawRectEdge( dc, &myr, EDGE_SUNKEN, flags ); + + if(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) + FillRect(dc, &myr, GetSysColorBrush(COLOR_BTNFACE)); + else if( (uFlags & DFCS_BUTTON3STATE) && (uFlags & DFCS_CHECKED) ) + UITOOLS_DrawCheckedRect( dc, &myr ); + else + { + FillRect(dc, &myr, GetSysColorBrush(COLOR_WINDOW)); + } + + if(uFlags & DFCS_CHECKED) + { + int i, k; + i = (uFlags & DFCS_INACTIVE) || (uFlags & 0xff) == DFCS_BUTTON3STATE ? + COLOR_BTNSHADOW : COLOR_WINDOWTEXT; + + /* draw 7 bars, with h=3w to form the check */ + bar.left = myr.left; + bar.top = myr.top + 2; + for (k = 0; k < 7; k++) { + bar.left = bar.left + 1; + bar.top = (k < 3) ? bar.top + 1 : bar.top - 1; + bar.bottom = bar.top + 3; + bar.right = bar.left + 1; + FillRect(dc, &bar, GetSysColorBrush(i)); + } + } + return TRUE; +} + +/* Ported from WINE20020904 */ +/* Draw a radio/radioimage/radiomask button coming from DrawFrameControl() + * + * Does a pretty good job in emulating MS behavior. Some quirks are + * however there because MS uses a TrueType font (Marlett) to draw + * the buttons. + */ +static BOOL UITOOLS95_DFC_ButtonRadio(HDC dc, LPRECT r, UINT uFlags) +{ + RECT myr; + int i; + int SmallDiam = UITOOLS_MakeSquareRect(r, &myr); + int BorderShrink = SmallDiam / 16; + HPEN hpsave; + HBRUSH hbsave; + int xc, yc; + + if(BorderShrink < 1) BorderShrink = 1; + + if((uFlags & 0xff) == DFCS_BUTTONRADIOIMAGE) + { + FillRect(dc, r, (HBRUSH)GetStockObject(BLACK_BRUSH)); + } + + xc = myr.left + SmallDiam - SmallDiam/2; + yc = myr.top + SmallDiam - SmallDiam/2; + + /* Define bounding box */ + i = 14*SmallDiam/16; + myr.left = xc - i+i/2; + myr.right = xc + i/2; + myr.top = yc - i+i/2; + myr.bottom = yc + i/2; + + if((uFlags & 0xff) == DFCS_BUTTONRADIOMASK) + { + hbsave = (HBRUSH)SelectObject(dc, GetStockObject(BLACK_BRUSH)); + Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom); + SelectObject(dc, hbsave); + } + else + { + if(uFlags & (DFCS_FLAT|DFCS_MONO)) + { + hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_WINDOWFRAME)); + hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_WINDOWFRAME)); + Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom); + SelectObject(dc, hbsave); + SelectObject(dc, hpsave); + } + else + { + hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT)); + hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); + Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.left-1, myr.bottom, myr.right+1, myr.top); + + SelectObject(dc, GetSysColorPen(COLOR_BTNSHADOW)); + SelectObject(dc, GetSysColorBrush(COLOR_BTNSHADOW)); + Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.right+1, myr.top, myr.left-1, myr.bottom); + + myr.left += BorderShrink; + myr.right -= BorderShrink; + myr.top += BorderShrink; + myr.bottom -= BorderShrink; + + SelectObject(dc, GetSysColorPen(COLOR_3DLIGHT)); + SelectObject(dc, GetSysColorBrush(COLOR_3DLIGHT)); + Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.left-1, myr.bottom, myr.right+1, myr.top); + + SelectObject(dc, GetSysColorPen(COLOR_3DDKSHADOW)); + SelectObject(dc, GetSysColorBrush(COLOR_3DDKSHADOW)); + Pie(dc, myr.left, myr.top, myr.right+1, myr.bottom+1, myr.right+1, myr.top, myr.left-1, myr.bottom); + SelectObject(dc, hbsave); + SelectObject(dc, hpsave); + } + + i = 10*SmallDiam/16; + myr.left = xc - i+i/2; + myr.right = xc + i/2; + myr.top = yc - i+i/2; + myr.bottom = yc + i/2; + i= !(uFlags & (DFCS_INACTIVE|DFCS_PUSHED)) ? COLOR_WINDOW : COLOR_BTNFACE; + hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i)); + hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i)); + Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom); + SelectObject(dc, hbsave); + SelectObject(dc, hpsave); + } + + if(uFlags & DFCS_CHECKED) + { + i = 6*SmallDiam/16; + i = i < 1 ? 1 : i; + myr.left = xc - i+i/2; + myr.right = xc + i/2; + myr.top = yc - i+i/2; + myr.bottom = yc + i/2; + + i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_WINDOWTEXT; + hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i)); + hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i)); + Ellipse(dc, myr.left, myr.top, myr.right, myr.bottom); + SelectObject(dc, hpsave); + SelectObject(dc, hbsave); + } + + /* FIXME: M$ has a Polygon in the center at relative points: */ + /* 0.476, 0.476 (times SmallDiam, SmallDiam) */ + /* 0.476, 0.525 */ + /* 0.500, 0.500 */ + /* 0.500, 0.499 */ + /* when the button is unchecked. The reason for it is unknown. The */ + /* color is COLOR_BTNHIGHLIGHT, although the Polygon gets painted at */ + /* least 3 times (it looks like a clip-region when you see it happen). */ + /* I do not really see a reason why this should be implemented. If you */ + /* have a good reason, let me know. Maybe this is a quirk in the Marlett */ + /* font. */ + + return TRUE; +} + +/* Ported from WINE20020904 */ +static BOOL UITOOLS95_DrawFrameButton(HDC hdc, LPRECT rc, UINT uState) +{ + switch(uState & 0xff) + { + case DFCS_BUTTONPUSH: + return UITOOLS95_DFC_ButtonPush(hdc, rc, uState); + + case DFCS_BUTTONCHECK: + case DFCS_BUTTON3STATE: + return UITOOLS95_DFC_ButtonCheck(hdc, rc, uState); + + case DFCS_BUTTONRADIOIMAGE: + case DFCS_BUTTONRADIOMASK: + case DFCS_BUTTONRADIO: + return UITOOLS95_DFC_ButtonRadio(hdc, rc, uState); + + default: + DbgPrint("Invalid button state=0x%04x\n", uState); + } + + return FALSE; +} + +/* Ported from WINE20020904 */ +/* Draw caption buttons (win95), coming from DrawFrameControl() */ +static BOOL UITOOLS95_DrawFrameCaption(HDC dc, LPRECT r, UINT uFlags) +{ + POINT Line1[10]; + POINT Line2[10]; + int Line1N; + int Line2N; + RECT myr; + int SmallDiam = UITOOLS_MakeSquareRect(r, &myr)-2; + int i; + HBRUSH hbsave; + HPEN hpsave; + HFONT hfsave, hf; + int colorIdx = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT; + int xc = (myr.left+myr.right)/2; + int yc = (myr.top+myr.bottom)/2; + int edge, move; + char str[2] = "?"; + UINT alignsave; + int bksave; + COLORREF clrsave; + SIZE size; + + UITOOLS95_DFC_ButtonPush(dc, r, uFlags & 0xff00); + + switch(uFlags & 0xff) + { + case DFCS_CAPTIONCLOSE: + { + /* The "X" is made by drawing a series of lines. + * The number of lines drawn depends on the size + * of the bounding rect. e.g. For a 6x5 inside rect, + * two lines are drawn from top-left to bottom-right, + * and two lines from top-right to bottom-left. + * + * 0 1 2 3 4 5 0 1 2 3 4 5 + * 1 * * * * + * 2 * * * * + * 3 * * * * + * 4 * * * * + * + * Drawing one line for every 6 pixels in width + * seems to provide the best proportions. + */ + + POINT start, oldPos; + INT width = myr.right - myr.left - 5; + INT height = myr.bottom - myr.top - 6; + INT numLines = (width / 6) + 1; + + hpsave = (HPEN)SelectObject(dc, GetSysColorPen(colorIdx)); + + start.x = myr.left + 2; + start.y = myr.top + 2; + + if (width < 6) + height = width; + else + start.y++; + + if (uFlags & DFCS_PUSHED) + { + start.x++; + start.y++; + } + + /* now use the width of each line */ + width -= numLines - 1; + + for (i = 0; i < numLines; i++) + { + MoveToEx(dc, start.x + i, start.y, &oldPos); + LineTo(dc, start.x + i + width, start.y + height); + + MoveToEx(dc, start.x + i, start.y + height - 1, &oldPos); + LineTo(dc, start.x + i + width, start.y - 1); + } + + SelectObject(dc, hpsave); + return TRUE; + } + + case DFCS_CAPTIONHELP: + /* This one breaks the flow */ + /* FIXME: We need the Marlett font in order to get this right. */ + + hf = CreateFontA(-SmallDiam, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, + ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, FIXED_PITCH|FF_DONTCARE, "System"); + alignsave = SetTextAlign(dc, TA_TOP|TA_LEFT); + bksave = SetBkMode(dc, TRANSPARENT); + clrsave = GetTextColor(dc); + hfsave = (HFONT)SelectObject(dc, hf); + GetTextExtentPoint32A(dc, str, 1, &size); + + if(uFlags & DFCS_INACTIVE) + { + SetTextColor(dc, GetSysColor(COLOR_BTNHIGHLIGHT)); + TextOutA(dc, xc-size.cx/2+1, yc-size.cy/2+1, str, 1); + } + SetTextColor(dc, GetSysColor(colorIdx)); + TextOutA(dc, xc-size.cx/2, yc-size.cy/2, str, 1); + + SelectObject(dc, hfsave); + SetTextColor(dc, clrsave); + SetBkMode(dc, bksave); + SetTextAlign(dc, alignsave); + DeleteObject(hf); + return TRUE; + + case DFCS_CAPTIONMIN: + Line1[0].x = Line1[3].x = myr.left + 96*SmallDiam/750+2; + Line1[1].x = Line1[2].x = Line1[0].x + 372*SmallDiam/750; + Line1[0].y = Line1[1].y = myr.top + 563*SmallDiam/750+1; + Line1[2].y = Line1[3].y = Line1[0].y + 92*SmallDiam/750; + Line1N = 4; + Line2N = 0; + break; + + case DFCS_CAPTIONMAX: + edge = 47*SmallDiam/750; + Line1[0].x = Line1[5].x = myr.left + 57*SmallDiam/750+3; + Line1[0].y = Line1[1].y = myr.top + 143*SmallDiam/750+1; + Line1[1].x = Line1[2].x = Line1[0].x + 562*SmallDiam/750; + Line1[5].y = Line1[4].y = Line1[0].y + 93*SmallDiam/750; + Line1[2].y = Line1[3].y = Line1[0].y + 513*SmallDiam/750; + Line1[3].x = Line1[4].x = Line1[1].x - edge; + + Line2[0].x = Line2[5].x = Line1[0].x; + Line2[3].x = Line2[4].x = Line1[1].x; + Line2[1].x = Line2[2].x = Line1[0].x + edge; + Line2[0].y = Line2[1].y = Line1[0].y; + Line2[4].y = Line2[5].y = Line1[2].y; + Line2[2].y = Line2[3].y = Line1[2].y - edge; + Line1N = 6; + Line2N = 6; + break; + + case DFCS_CAPTIONRESTORE: + /* FIXME: this one looks bad at small sizes < 15x15 :( */ + edge = 47*SmallDiam/750; + move = 420*SmallDiam/750; + Line1[0].x = Line1[9].x = myr.left + 198*SmallDiam/750+2; + Line1[0].y = Line1[1].y = myr.top + 169*SmallDiam/750+1; + Line1[6].y = Line1[7].y = Line1[0].y + 93*SmallDiam/750; + Line1[7].x = Line1[8].x = Line1[0].x + edge; + Line1[1].x = Line1[2].x = Line1[0].x + move; + Line1[5].x = Line1[6].x = Line1[1].x - edge; + Line1[9].y = Line1[8].y = Line1[0].y + 187*SmallDiam/750; + Line1[2].y = Line1[3].y = Line1[0].y + 327*SmallDiam/750; + Line1[4].y = Line1[5].y = Line1[2].y - edge; + Line1[3].x = Line1[4].x = Line1[2].x - 140*SmallDiam/750; + + Line2[1].x = Line2[2].x = Line1[3].x; + Line2[7].x = Line2[8].x = Line2[1].x - edge; + Line2[0].x = Line2[9].x = Line2[3].x = Line2[4].x = Line2[1].x - move; + Line2[5].x = Line2[6].x = Line2[0].x + edge; + Line2[0].y = Line2[1].y = Line1[9].y; + Line2[4].y = Line2[5].y = Line2[8].y = Line2[9].y = Line2[0].y + 93*SmallDiam/750; + Line2[2].y = Line2[3].y = Line2[0].y + 327*SmallDiam/750; + Line2[6].y = Line2[7].y = Line2[2].y - edge; + Line1N = 10; + Line2N = 10; + break; + + default: + DbgPrint("Invalid caption; flags=0x%04x\n", uFlags); + return FALSE; + } + + /* Here the drawing takes place */ + if(uFlags & DFCS_INACTIVE) + { + /* If we have an inactive button, then you see a shadow */ + hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); + hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT)); + Polygon(dc, Line1, Line1N); + if(Line2N > 0) + Polygon(dc, Line2, Line2N); + SelectObject(dc, hpsave); + SelectObject(dc, hbsave); + } + + /* Correct for the shadow shift */ + if (!(uFlags & DFCS_PUSHED)) + { + for(i = 0; i < Line1N; i++) + { + Line1[i].x--; + Line1[i].y--; + } + for(i = 0; i < Line2N; i++) + { + Line2[i].x--; + Line2[i].y--; + } + } + + /* Make the final picture */ + hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(colorIdx)); + hpsave = (HPEN)SelectObject(dc, GetSysColorPen(colorIdx)); + + Polygon(dc, Line1, Line1N); + if(Line2N > 0) + Polygon(dc, Line2, Line2N); + SelectObject(dc, hpsave); + SelectObject(dc, hbsave); + + return TRUE; +} + +/* Ported from WINE20020904 */ +/* Draw a scroll-bar control coming from DrawFrameControl() */ +static BOOL UITOOLS95_DrawFrameScroll(HDC dc, LPRECT r, UINT uFlags) +{ + POINT Line[4]; + RECT myr; + int SmallDiam = UITOOLS_MakeSquareRect(r, &myr) - 2; + int i; + HBRUSH hbsave, hb, hb2; + HPEN hpsave, hp, hp2; + int tri = 290*SmallDiam/1000 - 1; + int d46, d93; + + /* + * This fixes a problem with really tiny "scroll" buttons. In particular + * with the updown control. + * Making sure that the arrow is as least 3 pixels wide (or high). + */ + if (tri == 0) + tri = 1; + + switch(uFlags & 0xff) + { + case DFCS_SCROLLCOMBOBOX: + case DFCS_SCROLLDOWN: + Line[2].x = myr.left + 470*SmallDiam/1000 + 2; + Line[2].y = myr.top + 687*SmallDiam/1000 + 1; + Line[0].x = Line[2].x - tri; + Line[1].x = Line[2].x + tri; + Line[0].y = Line[1].y = Line[2].y - tri; + break; + + case DFCS_SCROLLUP: + Line[2].x = myr.left + 470*SmallDiam/1000 + 2; + Line[2].y = myr.bottom - (687*SmallDiam/1000 + 1); + Line[0].x = Line[2].x - tri; + Line[1].x = Line[2].x + tri; + Line[0].y = Line[1].y = Line[2].y + tri; + break; + + case DFCS_SCROLLLEFT: + Line[2].x = myr.right - (687*SmallDiam/1000 + 1); + Line[2].y = myr.top + 470*SmallDiam/1000 + 2; + Line[0].y = Line[2].y - tri; + Line[1].y = Line[2].y + tri; + Line[0].x = Line[1].x = Line[2].x + tri; + break; + + case DFCS_SCROLLRIGHT: + Line[2].x = myr.left + 687*SmallDiam/1000 + 1; + Line[2].y = myr.top + 470*SmallDiam/1000 + 2; + Line[0].y = Line[2].y - tri; + Line[1].y = Line[2].y + tri; + Line[0].x = Line[1].x = Line[2].x - tri; + break; + + case DFCS_SCROLLSIZEGRIP: + /* This one breaks the flow... */ + UITOOLS95_DrawRectEdge(dc, r, EDGE_BUMP, BF_MIDDLE | ((uFlags&(DFCS_MONO|DFCS_FLAT)) ? BF_MONO : 0)); + hpsave = (HPEN)SelectObject(dc, GetStockObject(NULL_PEN)); + hbsave = (HBRUSH)SelectObject(dc, GetStockObject(NULL_BRUSH)); + if(uFlags & (DFCS_MONO|DFCS_FLAT)) + { + hp = hp2 = GetSysColorPen(COLOR_WINDOWFRAME); + hb = hb2 = GetSysColorBrush(COLOR_WINDOWFRAME); + } + else + { + hp = GetSysColorPen(COLOR_BTNHIGHLIGHT); + hp2 = GetSysColorPen(COLOR_BTNSHADOW); + hb = GetSysColorBrush(COLOR_BTNHIGHLIGHT); + hb2 = GetSysColorBrush(COLOR_BTNSHADOW); + } + Line[0].x = Line[1].x = r->right-1; + Line[2].y = Line[3].y = r->bottom-1; + d46 = 46*SmallDiam/750; + d93 = 93*SmallDiam/750; + + i = 586*SmallDiam/750; + Line[0].y = r->bottom - i - 1; + Line[3].x = r->right - i - 1; + Line[1].y = Line[0].y + d46; + Line[2].x = Line[3].x + d46; + SelectObject(dc, hb); + SelectObject(dc, hp); + Polygon(dc, Line, 4); + + Line[1].y++; Line[2].x++; + Line[0].y = Line[1].y + d93; + Line[3].x = Line[2].x + d93; + SelectObject(dc, hb2); + SelectObject(dc, hp2); + Polygon(dc, Line, 4); + + i = 398*SmallDiam/750; + Line[0].y = r->bottom - i - 1; + Line[3].x = r->right - i - 1; + Line[1].y = Line[0].y + d46; + Line[2].x = Line[3].x + d46; + SelectObject(dc, hb); + SelectObject(dc, hp); + Polygon(dc, Line, 4); + + Line[1].y++; Line[2].x++; + Line[0].y = Line[1].y + d93; + Line[3].x = Line[2].x + d93; + SelectObject(dc, hb2); + SelectObject(dc, hp2); + Polygon(dc, Line, 4); + + i = 210*SmallDiam/750; + Line[0].y = r->bottom - i - 1; + Line[3].x = r->right - i - 1; + Line[1].y = Line[0].y + d46; + Line[2].x = Line[3].x + d46; + SelectObject(dc, hb); + SelectObject(dc, hp); + Polygon(dc, Line, 4); + + Line[1].y++; Line[2].x++; + Line[0].y = Line[1].y + d93; + Line[3].x = Line[2].x + d93; + SelectObject(dc, hb2); + SelectObject(dc, hp2); + Polygon(dc, Line, 4); + + SelectObject(dc, hpsave); + SelectObject(dc, hbsave); + return TRUE; + + default: + DbgPrint("Invalid scroll; flags=0x%04x\n", uFlags); + return FALSE; + } + + /* Here do the real scroll-bar controls end up */ + if( ! (uFlags & (0xff00 & ~DFCS_ADJUSTRECT)) ) + /* UITOOLS95_DFC_ButtonPush always uses BF_SOFT which we don't */ + /* want for the normal scroll-arrow button. */ + UITOOLS95_DrawRectEdge( dc, r, EDGE_RAISED, (uFlags&DFCS_ADJUSTRECT) | BF_MIDDLE | BF_RECT); + else + UITOOLS95_DFC_ButtonPush(dc, r, (uFlags & 0xff00) ); + + if(uFlags & DFCS_INACTIVE) + { + hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(COLOR_BTNHIGHLIGHT)); + hpsave = (HPEN)SelectObject(dc, GetSysColorPen(COLOR_BTNHIGHLIGHT)); + Polygon(dc, Line, 3); + SelectObject(dc, hpsave); + SelectObject(dc, hbsave); + } + + if( (uFlags & DFCS_INACTIVE) || !(uFlags & DFCS_PUSHED) ) + for(i = 0; i < 3; i++) + { + Line[i].x--; + Line[i].y--; + } + + i = uFlags & DFCS_INACTIVE ? COLOR_BTNSHADOW : COLOR_BTNTEXT; + hbsave = (HBRUSH)SelectObject(dc, GetSysColorBrush(i)); + hpsave = (HPEN)SelectObject(dc, GetSysColorPen(i)); + Polygon(dc, Line, 3); + SelectObject(dc, hpsave); + SelectObject(dc, hbsave); + + return TRUE; +} + +/* Ported from WINE20020904 */ +/* Draw a menu control coming from DrawFrameControl() */ +static BOOL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags) +{ + POINT Points[6]; + RECT myr; + int SmallDiam = UITOOLS_MakeSquareRect(r, &myr); + int i; + HBRUSH hbsave; + HPEN hpsave; + int xe, ye; + int xc, yc; + BOOL retval = TRUE; + + /* Using black and white seems to be utterly wrong, but win95 doesn't */ + /* use anything else. I think I tried all sys-colors to change things */ + /* without luck. It seems as if this behavior is inherited from the */ + /* win31 DFC() implementation... (you remember, B/W menus). */ + + FillRect(dc, r, (HBRUSH)GetStockObject(WHITE_BRUSH)); + + hbsave = (HBRUSH)SelectObject(dc, GetStockObject(BLACK_BRUSH)); + hpsave = (HPEN)SelectObject(dc, GetStockObject(BLACK_PEN)); + + switch(uFlags & 0xff) + { + case DFCS_MENUARROW: + i = 187*SmallDiam/750; + Points[2].x = myr.left + 468*SmallDiam/750; + Points[2].y = myr.top + 352*SmallDiam/750+1; + Points[0].y = Points[2].y - i; + Points[1].y = Points[2].y + i; + Points[0].x = Points[1].x = Points[2].x - i; + Polygon(dc, Points, 3); + break; + + case DFCS_MENUBULLET: + xe = myr.left; + ye = myr.top + SmallDiam - SmallDiam/2; + xc = myr.left + SmallDiam - SmallDiam/2; + yc = myr.top + SmallDiam - SmallDiam/2; + i = 234*SmallDiam/750; + i = i < 1 ? 1 : i; + myr.left = xc - i+i/2; + myr.right = xc + i/2; + myr.top = yc - i+i/2; + myr.bottom = yc + i/2; + Pie(dc, myr.left, myr.top, myr.right, myr.bottom, xe, ye, xe, ye); + break; + + case DFCS_MENUCHECK: + Points[0].x = myr.left + 253*SmallDiam/1000; + Points[0].y = myr.top + 445*SmallDiam/1000; + Points[1].x = myr.left + 409*SmallDiam/1000; + Points[1].y = Points[0].y + (Points[1].x-Points[0].x); + Points[2].x = myr.left + 690*SmallDiam/1000; + Points[2].y = Points[1].y - (Points[2].x-Points[1].x); + Points[3].x = Points[2].x; + Points[3].y = Points[2].y + 3*SmallDiam/16; + Points[4].x = Points[1].x; + Points[4].y = Points[1].y + 3*SmallDiam/16; + Points[5].x = Points[0].x; + Points[5].y = Points[0].y + 3*SmallDiam/16; + Polygon(dc, Points, 6); + break; + + default: + DbgPrint("Invalid menu; flags=0x%04x\n", uFlags); + retval = FALSE; + break; + } + + SelectObject(dc, hpsave); + SelectObject(dc, hbsave); + return retval; +} + +/* Ported from WINE20020904 */ +BOOL WINAPI DrawFrameControl( HDC hdc, LPRECT rc, UINT uType, + UINT uState ) +{ + /* Win95 doesn't support drawing in other mapping modes */ + if(GetMapMode(hdc) != MM_TEXT) + return FALSE; + + switch(uType) + { + case DFC_BUTTON: + return UITOOLS95_DrawFrameButton(hdc, rc, uState); + case DFC_CAPTION: + return UITOOLS95_DrawFrameCaption(hdc, rc, uState); + case DFC_MENU: + return UITOOLS95_DrawFrameMenu(hdc, rc, uState); + case DFC_SCROLL: + return UITOOLS95_DrawFrameScroll(hdc, rc, uState); + default: + DbgPrint("(%x,%p,%d,%x), bad type!\n", hdc,rc,uType,uState ); + } + return FALSE; +} + +/* Ported from WINE20020904 */ +BOOL WINAPI DrawEdge( HDC hdc, LPRECT rc, UINT edge, UINT flags ) +{ + DbgPrint("%04x %d,%d-%d,%d %04x %04x\n", + hdc, rc->left, rc->top, rc->right, rc->bottom, edge, flags ); + + if(flags & BF_DIAGONAL) + return UITOOLS95_DrawDiagEdge(hdc, rc, edge, flags); + else + return UITOOLS95_DrawRectEdge(hdc, rc, edge, flags); +} + WINBOOL STDCALL GrayStringA( @@ -172,17 +1498,6 @@ DrawCaption( return FALSE; } -WINBOOL -STDCALL -DrawEdge( - HDC hdc, - LPRECT qrc, - UINT edge, - UINT grfFlags) -{ - return FALSE; -} - WINBOOL STDCALL DrawFocusRect(