Sync to Wine-20050830:
Kevin Koltzau <kevin@plop.org>
- Fix 'cast to pointer from integer of different size' warnings in
  64bit.
Frank Richter <frank.richter@gmail.com>
- Add support for the BT_NONE background type.
- Better computations to have uniformly sized parts scaled in both
  directions.
- Implement GetThemeBackgroundExtent().
- Implement DrawThemeEdge().
- Implement support for the ST_TILE background stretching mode.
- Implementation for GetThemePartSize() (not entirely equivalent to
  native uxtheme, but sensibly useable).
- Enhance uxtheme to store the themed system metrics in the registry and
  also backup the old metrics. That way, themed system colors are set
  even uxtheme was not loaded and initialized yet, and when a theme is
  deactivated, the colors prior to the activation are restored as well.
- Also, not having to set the system colors in uxtheme startup works
  around weird problems where SetSystemColors() ended up being called
  from inside window creation and this seemingly led to some creation
  message being sent twice.
- Make GetThemeMargins() return default values (0 margin) if the
  function does not succeed.
- More elaborate IsThemeBackgroundPartiallyTransparent() implementation;
  also returns TRUE for theme parts with 32bpp images.
- Since theme images are reused now it's not really a good idea to
  delete them in drawing functions.
- Pass around what kind of transparency an image actually needs. Use
  alpha-blending for 32bpp images.
- Set some default values for truesize sizing that seem closer to
  Windows.
- If a MINSIZEn property is not present, fall back to actual size of nth
  image to determine whether it is suitable.
- EnumThemeColors() and EnumThemeSizes() actually do not return a single
  string with the color/size name, but rather a struct containing three
  strings - name, display name and tooltip.
- The default image layout is HORIZONTAL, not VERTICAL.
- Take a common computation out of two if-branches in
  UXTHEME_LoadImage().
- Compare result of RegQueryValueExW() with ERROR_SUCCESS.
- Another fix to use magenta as the default transparent color.
- Implement "manual" image sharing(as opposed to using LoadImage() with
  LR_SHARED) by keeping the loaded images in a list. This is needed for
  proper alpha support later on since once-per-image preparations will
  be needed then.
- Add support for horizontal & vertical alignment when doing truesize
  sizing.
- Whatever TrueSizeStretchMark is for - it's not what Wine uxtheme used
  it for. Native uxtheme always stretches "truesize" parts when the
  destination is smaller than the part image size, but
  TrueSizeStretchMark doesn't seem to have an influence.
Deleted: trunk/reactos/lib/uxtheme/Makefile.in
Modified: trunk/reactos/lib/uxtheme/draw.c
Modified: trunk/reactos/lib/uxtheme/msstyles.c
Modified: trunk/reactos/lib/uxtheme/msstyles.h
Modified: trunk/reactos/lib/uxtheme/property.c
Modified: trunk/reactos/lib/uxtheme/system.c
Modified: trunk/reactos/lib/uxtheme/uxtheme.spec
Modified: trunk/reactos/lib/uxtheme/uxthemedll.h

Deleted: trunk/reactos/lib/uxtheme/Makefile.in
--- trunk/reactos/lib/uxtheme/Makefile.in	2005-09-07 16:02:32 UTC (rev 17718)
+++ trunk/reactos/lib/uxtheme/Makefile.in	2005-09-07 16:22:51 UTC (rev 17719)
@@ -1,25 +0,0 @@
-TOPSRCDIR = @top_srcdir@
-TOPOBJDIR = ../..
-SRCDIR    = @srcdir@
-VPATH     = @srcdir@
-MODULE    = uxtheme.dll
-IMPORTLIB = libuxtheme.$(IMPLIBEXT)
-IMPORTS   = shlwapi user32 gdi32 advapi32 kernel32 ntdll
-DELAYIMPORTS = msimg32
-EXTRALIBS = $(LIBUNICODE)
-
-C_SRCS = \
-	draw.c \
-	main.c \
-	metric.c \
-	msstyles.c \
-	property.c \
-	stylemap.c \
-	system.c \
-	uxini.c
-
-RC_SRCS = version.rc
-
-@MAKE_DLL_RULES@
-
-### Dependencies:

Modified: trunk/reactos/lib/uxtheme/draw.c
--- trunk/reactos/lib/uxtheme/draw.c	2005-09-07 16:02:32 UTC (rev 17718)
+++ trunk/reactos/lib/uxtheme/draw.c	2005-09-07 16:22:51 UTC (rev 17719)
@@ -187,12 +187,42 @@
         POINT size = {pRect->right-pRect->left, pRect->bottom-pRect->top};
         POINT reqsize;
         for(i=4; i>=0; i--) {
-            if(SUCCEEDED(GetThemePosition(hTheme, iPartId, iStateId, i + TMT_MINSIZE1, &reqsize))) {
-                if(reqsize.x >= size.x && reqsize.y >= size.y) {
-                    TRACE("Using image size %ldx%ld, image %d\n", reqsize.x, reqsize.y, i + TMT_IMAGEFILE1);
-                    return MSSTYLES_FindProperty(hTheme, iPartId, iStateId, TMT_FILENAME, i + TMT_IMAGEFILE1);
+            PTHEME_PROPERTY fileProp = 
+                MSSTYLES_FindProperty(hTheme, iPartId, iStateId, TMT_FILENAME, i + TMT_IMAGEFILE1);
+            if (!fileProp) continue;
+            if(FAILED(GetThemePosition(hTheme, iPartId, iStateId, i + TMT_MINSIZE1, &reqsize))) {
+                /* fall back to size of Nth image */
+                WCHAR szPath[MAX_PATH];
+                int imagelayout = IL_HORIZONTAL;
+                int imagecount = 1;
+                int imagenum;
+                BITMAP bmp;
+                HBITMAP hBmp;
+                BOOL hasAlpha;
+
+                lstrcpynW(szPath, fileProp->lpValue, 
+                    min(fileProp->dwValueLen+1, sizeof(szPath)/sizeof(szPath[0])));
+                hBmp = MSSTYLES_LoadBitmap(hTheme, szPath, &hasAlpha);
+                if(!hBmp) continue;
+
+                GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_IMAGELAYOUT, &imagelayout);
+                GetThemeInt(hTheme, iPartId, iStateId, TMT_IMAGECOUNT, &imagecount);
+
+                imagenum = max (min (imagecount, iStateId), 1) - 1;
+                GetObjectW(hBmp, sizeof(bmp), &bmp);
+                if(imagelayout == IL_VERTICAL) {
+                    reqsize.x = bmp.bmWidth;
+                    reqsize.y = bmp.bmHeight/imagecount;
                 }
+                else {
+                    reqsize.x = bmp.bmWidth/imagecount;
+                    reqsize.y = bmp.bmHeight;
+                }
             }
+            if(reqsize.x <= size.x && reqsize.y <= size.y) {
+                TRACE("Using image size %ldx%ld, image %d\n", reqsize.x, reqsize.y, i + TMT_IMAGEFILE1);
+                return fileProp;
+            }
         }
         /* If an image couldnt be selected, choose the smallest one */
         return MSSTYLES_FindProperty(hTheme, iPartId, iStateId, TMT_FILENAME, TMT_IMAGEFILE1);
@@ -206,10 +236,11 @@
  * Load image for part/state
  */
 static HRESULT UXTHEME_LoadImage(HTHEME hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, BOOL glyph,
-                          HBITMAP *hBmp, RECT *bmpRect)
+                          HBITMAP *hBmp, RECT *bmpRect, BOOL* hasImageAlpha)
 {
-    int imagelayout = IL_VERTICAL;
+    int imagelayout = IL_HORIZONTAL;
     int imagecount = 1;
+    int imagenum;
     BITMAP bmp;
     WCHAR szPath[MAX_PATH];
     PTHEME_PROPERTY tp = UXTHEME_SelectImage(hTheme, hdc, iPartId, iStateId, pRect, glyph);
@@ -218,7 +249,7 @@
         return E_PROP_ID_UNSUPPORTED;
     }
     lstrcpynW(szPath, tp->lpValue, min(tp->dwValueLen+1, sizeof(szPath)/sizeof(szPath[0])));
-    *hBmp = MSSTYLES_LoadBitmap(hdc, hTheme, szPath);
+    *hBmp = MSSTYLES_LoadBitmap(hTheme, szPath, hasImageAlpha);
     if(!*hBmp) {
         TRACE("Failed to load bitmap %s\n", debugstr_w(szPath));
         return HRESULT_FROM_WIN32(GetLastError());
@@ -227,17 +258,18 @@
     GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_IMAGELAYOUT, &imagelayout);
     GetThemeInt(hTheme, iPartId, iStateId, TMT_IMAGECOUNT, &imagecount);
 
+    imagenum = max (min (imagecount, iStateId), 1) - 1;
     GetObjectW(*hBmp, sizeof(bmp), &bmp);
     if(imagelayout == IL_VERTICAL) {
         int height = bmp.bmHeight/imagecount;
         bmpRect->left = 0;
         bmpRect->right = bmp.bmWidth;
-        bmpRect->top = (max(min(imagecount, iStateId), 1)-1) * height;
+        bmpRect->top = imagenum * height;
         bmpRect->bottom = bmpRect->top + height;
     }
     else {
         int width = bmp.bmWidth/imagecount;
-        bmpRect->left = (max(min(imagecount, iStateId), 1)-1) * width;
+        bmpRect->left = imagenum * width;
         bmpRect->right = bmpRect->left + width;
         bmpRect->top = 0;
         bmpRect->bottom = bmp.bmHeight;
@@ -248,22 +280,35 @@
 /***********************************************************************
  *      UXTHEME_StretchBlt
  *
- * Psudo TransparentBlt/StretchBlt
+ * Pseudo TransparentBlt/StretchBlt
  */
 static inline BOOL UXTHEME_StretchBlt(HDC hdcDst, int nXOriginDst, int nYOriginDst, int nWidthDst, int nHeightDst,
                                       HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nWidthSrc, int nHeightSrc,
-                                      BOOL transparent, COLORREF transcolor)
+                                      INT transparent, COLORREF transcolor)
 {
-    if(transparent) {
+    static const BLENDFUNCTION blendFunc = 
+    {
+      AC_SRC_OVER, /* BlendOp */
+      0,           /* BlendFlag */
+      255,         /* SourceConstantAlpha */
+      AC_SRC_ALPHA /* AlphaFormat */
+    };
+    if (transparent == ALPHABLEND_BINARY) {
         /* Ensure we don't pass any negative values to TransparentBlt */
         return TransparentBlt(hdcDst, nXOriginDst, nYOriginDst, abs(nWidthDst), abs(nHeightDst),
                               hdcSrc, nXOriginSrc, nYOriginSrc, abs(nWidthSrc), abs(nHeightSrc),
                               transcolor);
     }
-    /* This should be using AlphaBlend */
-    return StretchBlt(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
-                        hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
-                        SRCCOPY);
+    if ((transparent == ALPHABLEND_NONE) ||
+        !AlphaBlend(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+                    hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+                    blendFunc))
+    {
+        return StretchBlt(hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+                          hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+                          SRCCOPY);
+    }
+    return TRUE;
 }
 
 /***********************************************************************
@@ -273,14 +318,88 @@
  */
 static inline BOOL UXTHEME_Blt(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,
                                HDC hdcSrc, int nXOriginSrc, int nYOriginSrc,
-                               BOOL transparent, COLORREF transcolor)
+                               INT transparent, COLORREF transcolor)
 {
     return UXTHEME_StretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
                               hdcSrc, nXOriginSrc, nYOriginSrc, nWidthDest, nHeightDest,
                               transparent, transcolor);
 }
 
+/***********************************************************************
+ *      UXTHEME_SizedBlt
+ *
+ * Stretches or tiles, depending on sizingtype.
+ */
+static inline BOOL UXTHEME_SizedBlt (HDC hdcDst, int nXOriginDst, int nYOriginDst, 
+                                     int nWidthDst, int nHeightDst,
+                                     HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, 
+                                     int nWidthSrc, int nHeightSrc,
+                                     int sizingtype, 
+                                     INT transparent, COLORREF transcolor)
+{
+    if (sizingtype == ST_TILE)
+    {
+        int yOfs = nYOriginDst;
+        int yRemaining = nHeightDst;
+        while (yRemaining > 0)
+        {
+            int bltHeight = min (yRemaining, nHeightSrc);
+            int xOfs = nXOriginDst;
+            int xRemaining = nWidthDst;
+            while (xRemaining > 0)
+            {
+                int bltWidth = min (xRemaining, nWidthSrc);
+                if (!UXTHEME_Blt (hdcDst, xOfs, yOfs, bltWidth, bltHeight,
+                                  hdcSrc, nXOriginSrc, nYOriginSrc, 
+                                  transparent, transcolor))
+                    return FALSE;
+                xOfs += nWidthSrc;
+                xRemaining -= nWidthSrc;
+            }
+            yOfs += nHeightSrc;
+            yRemaining -= nHeightSrc;
+        }
+        return TRUE;
+    }
+    else
+    {
+        return UXTHEME_StretchBlt (hdcDst, nXOriginDst, nYOriginDst, nWidthDst, nHeightDst,
+                                   hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc,
+                                   transparent, transcolor);
+    }
+}
 
+/* Get transparency parameters passed to UXTHEME_StretchBlt() - the parameters 
+ * depend on whether the image has full alpha  or whether it is 
+ * color-transparent or just opaque. */
+static inline void get_transparency (HTHEME hTheme, int iPartId, int iStateId, 
+                                     BOOL hasImageAlpha, INT* transparent,
+                                     COLORREF* transparentcolor, BOOL glyph)
+{
+    if (hasImageAlpha)
+    {
+        *transparent = ALPHABLEND_FULL;
+        *transparentcolor = RGB (255, 0, 255);
+    }
+    else
+    {
+        BOOL trans = FALSE;
+        GetThemeBool(hTheme, iPartId, iStateId, 
+            glyph ? TMT_GLYPHTRANSPARENT : TMT_TRANSPARENT, &trans);
+        if(trans) {
+            *transparent = ALPHABLEND_BINARY;
+            if(FAILED(GetThemeColor(hTheme, iPartId, iStateId, 
+                glyph ? TMT_GLYPHTRANSPARENTCOLOR : TMT_TRANSPARENTCOLOR, 
+                transparentcolor))) {
+                /* If image is transparent, but no color was specified, use magenta */
+                *transparentcolor = RGB(255, 0, 255);
+            }
+        }
+        else
+            *transparent = ALPHABLEND_NONE;
+    }
+}
+
 /***********************************************************************
  *      UXTHEME_DrawImageGlyph
  *
@@ -295,20 +414,21 @@
     HDC hdcSrc = NULL;
     HGDIOBJ oldSrc = NULL;
     RECT rcSrc;
-    BOOL transparent = FALSE;
-    COLORREF transparentcolor = 0;
+    INT transparent = FALSE;
+    COLORREF transparentcolor;
     int valign = VA_CENTER;
     int halign = HA_CENTER;
     POINT dstSize;
     POINT srcSize;
     POINT topleft;
+    BOOL hasAlpha;
 
-    hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, TRUE, &bmpSrc, &rcSrc);
+    hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, TRUE, 
+        &bmpSrc, &rcSrc, &hasAlpha);
     if(FAILED(hr)) return hr;
     hdcSrc = CreateCompatibleDC(hdc);
     if(!hdcSrc) {
         hr = HRESULT_FROM_WIN32(GetLastError());
-        DeleteObject(bmpSrc);
         return hr;
     }
     oldSrc = SelectObject(hdcSrc, bmpSrc);
@@ -318,13 +438,8 @@
     srcSize.x = rcSrc.right-rcSrc.left;
     srcSize.y = rcSrc.bottom-rcSrc.top;
 
-    GetThemeBool(hTheme, iPartId, iStateId, TMT_GLYPHTRANSPARENT, &transparent);
-    if(transparent) {
-        if(FAILED(GetThemeColor(hTheme, iPartId, iStateId, TMT_GLYPHTRANSPARENTCOLOR, &transparentcolor))) {
-            /* If image is transparent, but no color was specified, use magenta */
-            transparentcolor = RGB(255, 0, 255);
-        }
-    }
+    get_transparency (hTheme, iPartId, iStateId, hasAlpha, &transparent,
+        &transparentcolor, TRUE);
     GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_VALIGN, &valign);
     GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_HALIGN, &halign);
 
@@ -343,7 +458,6 @@
 
     SelectObject(hdcSrc, oldSrc);
     DeleteDC(hdcSrc);
-    DeleteObject(bmpSrc);
     return hr;
 }
 
@@ -371,6 +485,110 @@
 }
 
 /***********************************************************************
+ * get_image_part_size
+ *
+ * Used by GetThemePartSize and UXTHEME_DrawImageBackground
+ */
+static HRESULT get_image_part_size (HTHEME hTheme, HDC hdc, int iPartId,
+                                    int iStateId, RECT *prc, THEMESIZE eSize,
+                                    POINT *psz)
+{
+    HRESULT hr = S_OK;
+    HBITMAP bmpSrc;
+    RECT rcSrc;
+    BOOL hasAlpha;
+
+    hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, prc, FALSE, 
+        &bmpSrc, &rcSrc, &hasAlpha);
+    if (FAILED(hr)) return hr;
+
+    switch (eSize)
+    {
+        case TS_DRAW:
+            if (prc != NULL)
+            {
+                RECT rcDst;
+                POINT dstSize;
+                POINT srcSize;
+                int sizingtype = ST_STRETCH;
+                BOOL uniformsizing = FALSE;
+
+                CopyRect(&rcDst, prc);
+
+                dstSize.x = rcDst.right-rcDst.left;
+                dstSize.y = rcDst.bottom-rcDst.top;
+                srcSize.x = rcSrc.right-rcSrc.left;
+                srcSize.y = rcSrc.bottom-rcSrc.top;
+            
+                GetThemeBool(hTheme, iPartId, iStateId, TMT_UNIFORMSIZING, &uniformsizing);
+                if(uniformsizing) {
+                    /* Scale height and width equally */
+                    if (dstSize.x*srcSize.y < dstSize.y*srcSize.x)
+                    {
+                        dstSize.y = MulDiv (srcSize.y, dstSize.x, srcSize.x);
+                        rcDst.bottom = rcDst.top + dstSize.y;
+                    }
+                    else
+                    {
+                        dstSize.x = MulDiv (srcSize.x, dstSize.y, srcSize.y);
+                        rcDst.right = rcDst.left + dstSize.x;
+                    }
+                }
+            
+                GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_SIZINGTYPE, &sizingtype);
+                if(sizingtype == ST_TRUESIZE) {
+                    int truesizestretchmark = 100;
+            
+                    if(dstSize.x < 0 || dstSize.y < 0) {
+                        BOOL mirrorimage = TRUE;
+                        GetThemeBool(hTheme, iPartId, iStateId, TMT_MIRRORIMAGE, &mirrorimage);
+                        if(mirrorimage) {
+                            if(dstSize.x < 0) {
+                                rcDst.left += dstSize.x;
+                                rcDst.right += dstSize.x;
+                            }
+                            if(dstSize.y < 0) {
+                                rcDst.top += dstSize.y;
+                                rcDst.bottom += dstSize.y;
+                            }
+                        }
+                    }
+                    /* Whatever TrueSizeStretchMark does - it does not seem to
+                     * be what's outlined below. It appears as if native 
+                     * uxtheme always stretches if dest is smaller than source
+                     * (ie as if TrueSizeStretchMark==100 with the code below) */
+#if 0
+                    /* Only stretch when target exceeds source by truesizestretchmark percent */
+                    GetThemeInt(hTheme, iPartId, iStateId, TMT_TRUESIZESTRETCHMARK, &truesizestretchmark);
+#endif
+                    if(dstSize.x < 0 || dstSize.y < 0 ||
+                      (MulDiv(srcSize.x, 100, dstSize.x) > truesizestretchmark &&
+                      MulDiv(srcSize.y, 100, dstSize.y) > truesizestretchmark)) {
+                        memcpy (psz, &dstSize, sizeof (SIZE));
+                    }
+                    else {
+                        memcpy (psz, &srcSize, sizeof (SIZE));
+                    }
+                }
+                else
+                {
+                    psz->x = abs(dstSize.x);
+                    psz->y = abs(dstSize.y);
+                }
+                break;
+            }
+            /* else fall through */
+        case TS_MIN:
+            /* FIXME: couldn't figure how native uxtheme computes min size */
+        case TS_TRUE:
+            psz->x = rcSrc.right - rcSrc.left;
+            psz->y = rcSrc.bottom - rcSrc.top;
+            break;
+    }
+    return hr;
+}
+
+/***********************************************************************
  *      UXTHEME_DrawImageBackground
  *
  * Draw an imagefile background
@@ -387,143 +605,101 @@
     RECT rcDst;
     POINT dstSize;
     POINT srcSize;
-    int sizingtype = ST_TRUESIZE;
-    BOOL uniformsizing = FALSE;
-    BOOL transparent = FALSE;
+    POINT drawSize;
+    int sizingtype = ST_STRETCH;
+    INT transparent;
     COLORREF transparentcolor = 0;
+    BOOL hasAlpha;
 
-    hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, FALSE, &bmpSrc, &rcSrc);
+    hr = UXTHEME_LoadImage(hTheme, hdc, iPartId, iStateId, pRect, FALSE, 
+        &bmpSrc, &rcSrc, &hasAlpha);
     if(FAILED(hr)) return hr;
     hdcSrc = CreateCompatibleDC(hdc);
     if(!hdcSrc) {
         hr = HRESULT_FROM_WIN32(GetLastError());
-        DeleteObject(bmpSrc);
         return hr;
     }
     oldSrc = SelectObject(hdcSrc, bmpSrc);
 
     CopyRect(&rcDst, pRect);
     
-    GetThemeBool(hTheme, iPartId, iStateId, TMT_TRANSPARENT, &transparent);
-    if(transparent) {
-        if(FAILED(GetThemeColor(hTheme, iPartId, iStateId, TMT_TRANSPARENTCOLOR, &transparentcolor))) {
-            /* If image is transparent, but no color was specified, get the color of the upper left corner */
-            transparentcolor = GetPixel(hdcSrc, 0, 0);
-        }
-    }
+    get_transparency (hTheme, iPartId, iStateId, hasAlpha, &transparent,
+        &transparentcolor, FALSE);
 
     dstSize.x = rcDst.right-rcDst.left;
     dstSize.y = rcDst.bottom-rcDst.top;
     srcSize.x = rcSrc.right-rcSrc.left;
     srcSize.y = rcSrc.bottom-rcSrc.top;
 
-    GetThemeBool(hTheme, iPartId, iStateId, TMT_UNIFORMSIZING, &uniformsizing);
-    if(uniformsizing) {
-        /* Scale height and width equally */
-        int widthDiff = abs(srcSize.x-dstSize.x);
-        int heightDiff = abs(srcSize.y-dstSize.x);
-        if(widthDiff > heightDiff) {
-            dstSize.y -= widthDiff-heightDiff;
-            rcDst.bottom = rcDst.top + dstSize.y;
-        }
-        else if(heightDiff > widthDiff) {
-            dstSize.x -= heightDiff-widthDiff;
-            rcDst.right = rcDst.left + dstSize.x;
-        }
-    }
-
     GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_SIZINGTYPE, &sizingtype);
     if(sizingtype == ST_TRUESIZE) {
-        int truesizestretchmark = 0;
+        int valign = VA_CENTER, halign = HA_CENTER;
 
-        if(dstSize.x < 0 || dstSize.y < 0) {
-            BOOL mirrorimage = TRUE;
-            GetThemeBool(hTheme, iPartId, iStateId, TMT_MIRRORIMAGE, &mirrorimage);
-            if(mirrorimage) {
-                if(dstSize.x < 0) {
-                    rcDst.left += dstSize.x;
-                    rcDst.right += dstSize.x;
-                }
-                if(dstSize.y < 0) {
-                    rcDst.top += dstSize.y;
-                    rcDst.bottom += dstSize.y;
-                }
-            }
-        }
-        /* Only stretch when target exceeds source by truesizestretchmark percent */
-        GetThemeInt(hTheme, iPartId, iStateId, TMT_TRUESIZESTRETCHMARK, &truesizestretchmark);
-        if(dstSize.x < 0 || dstSize.y < 0 ||
-           MulDiv(srcSize.x, 100, dstSize.x) > truesizestretchmark ||
-           MulDiv(srcSize.y, 100, dstSize.y) > truesizestretchmark) {
-            if(!UXTHEME_StretchBlt(hdc, rcDst.left, rcDst.top, dstSize.x, dstSize.y,
-                                   hdcSrc, rcSrc.left, rcSrc.top, srcSize.x, srcSize.y,
-                                   transparent, transparentcolor))
-                hr = HRESULT_FROM_WIN32(GetLastError());
-        }
-        else {
-            rcDst.left += (dstSize.x/2)-(srcSize.x/2);
-            rcDst.top  += (dstSize.y/2)-(srcSize.y/2);
-            rcDst.right = rcDst.left + srcSize.x;
-            rcDst.bottom = rcDst.top + srcSize.y;
-            if(!UXTHEME_Blt(hdc, rcDst.left, rcDst.top, srcSize.x, srcSize.y,
-                            hdcSrc, rcSrc.left, rcSrc.top,
-                            transparent, transparentcolor))
-                hr = HRESULT_FROM_WIN32(GetLastError());
-        }
+        get_image_part_size (hTheme, hdc, iPartId, iStateId, pRect, TS_DRAW, &drawSize);
+        GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_VALIGN, &valign);
+        GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_HALIGN, &halign);
+
+        if (halign == HA_CENTER)
+            rcDst.left += (dstSize.x/2)-(drawSize.x/2);
+        else if (halign == HA_RIGHT)
+            rcDst.left = rcDst.right - drawSize.x;
+        if (valign == VA_CENTER)
+            rcDst.top  += (dstSize.y/2)-(drawSize.y/2);
+        else if (valign == VA_BOTTOM)
+            rcDst.top = rcDst.bottom - drawSize.y;
+        rcDst.right = rcDst.left + drawSize.x;
+        rcDst.bottom = rcDst.top + drawSize.y;
+        if(!UXTHEME_StretchBlt(hdc, rcDst.left, rcDst.top, drawSize.x, drawSize.y,
+                                hdcSrc, rcSrc.left, rcSrc.top, srcSize.x, srcSize.y,
+                                transparent, transparentcolor))
+            hr = HRESULT_FROM_WIN32(GetLastError());
     }
     else {
         HDC hdcDst = NULL;
-        HBITMAP bmpDst = NULL;
-        HGDIOBJ oldDst = NULL;
         MARGINS sm;
+        POINT org;
 
         dstSize.x = abs(dstSize.x);
         dstSize.y = abs(dstSize.y);
 
         GetThemeMargins(hTheme, hdc, iPartId, iStateId, TMT_SIZINGMARGINS, NULL, &sm);
 
-        hdcDst = CreateCompatibleDC(hdc);
-        if(!hdcDst) {
-            hr = HRESULT_FROM_WIN32(GetLastError());
-            goto draw_error; 
-        }
-        bmpDst = CreateCompatibleBitmap(hdc, dstSize.x, dstSize.y);
-        if(!bmpDst) {
-            hr = HRESULT_FROM_WIN32(GetLastError());
-            goto draw_error; 
-        }
-        oldDst = SelectObject(hdcDst, bmpDst);
+        hdcDst = hdc;
+        OffsetViewportOrgEx(hdcDst, rcDst.left, rcDst.top, &org);
 
         /* Upper left corner */
-        if(!BitBlt(hdcDst, 0, 0, sm.cxLeftWidth, sm.cyTopHeight,
-                   hdcSrc, rcSrc.left, rcSrc.top, SRCCOPY)) {
+        if(!UXTHEME_Blt(hdcDst, 0, 0, sm.cxLeftWidth, sm.cyTopHeight,
+                        hdcSrc, rcSrc.left, rcSrc.top, 
+                        transparent, transparentcolor)) {
             hr = HRESULT_FROM_WIN32(GetLastError());
             goto draw_error; 
         }
         /* Upper right corner */
-        if(!BitBlt(hdcDst, dstSize.x-sm.cxRightWidth, 0, sm.cxRightWidth, sm.cyTopHeight,
-                   hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top, SRCCOPY)) {
+        if(!UXTHEME_Blt (hdcDst, dstSize.x-sm.cxRightWidth, 0, 
+                         sm.cxRightWidth, sm.cyTopHeight,
+                         hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top, 
+                         transparent, transparentcolor)) {
             hr = HRESULT_FROM_WIN32(GetLastError());
             goto draw_error; 
         }
         /* Lower left corner */
-        if(!BitBlt(hdcDst, 0, dstSize.y-sm.cyBottomHeight, sm.cxLeftWidth, sm.cyBottomHeight,
-                   hdcSrc, rcSrc.left, rcSrc.bottom-sm.cyBottomHeight, SRCCOPY)) {
+        if(!UXTHEME_Blt (hdcDst, 0, dstSize.y-sm.cyBottomHeight, 
+                         sm.cxLeftWidth, sm.cyBottomHeight,
+                         hdcSrc, rcSrc.left, rcSrc.bottom-sm.cyBottomHeight, 
+                         transparent, transparentcolor)) {
             hr = HRESULT_FROM_WIN32(GetLastError());
             goto draw_error; 
         }
         /* Lower right corner */
-        if(!BitBlt(hdcDst, dstSize.x-sm.cxRightWidth, dstSize.y-sm.cyBottomHeight, sm.cxRightWidth, sm.cyBottomHeight,
-                   hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.bottom-sm.cyBottomHeight, SRCCOPY)) {
+        if(!UXTHEME_Blt (hdcDst, dstSize.x-sm.cxRightWidth, dstSize.y-sm.cyBottomHeight, 
+                         sm.cxRightWidth, sm.cyBottomHeight,
+                         hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.bottom-sm.cyBottomHeight, 
+                         transparent, transparentcolor)) {
             hr = HRESULT_FROM_WIN32(GetLastError());
             goto draw_error; 
         }
 
-        if(sizingtype == ST_TILE) {
-            FIXME("Tile\n");
-            sizingtype = ST_STRETCH; /* Just use stretch for now */
-        }
-        if(sizingtype == ST_STRETCH) {
+        if ((sizingtype == ST_STRETCH) || (sizingtype == ST_TILE)) {
             int destCenterWidth  = dstSize.x - (sm.cxLeftWidth + sm.cxRightWidth);
             int srcCenterWidth   = srcSize.x - (sm.cxLeftWidth + sm.cxRightWidth);
             int destCenterHeight = dstSize.y - (sm.cyTopHeight + sm.cyBottomHeight);
@@ -531,28 +707,41 @@
 
             if(destCenterWidth > 0) {
                 /* Center top */
-                if(!StretchBlt(hdcDst, sm.cxLeftWidth, 0, destCenterWidth, sm.cyTopHeight,
-                               hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top, srcCenterWidth, sm.cyTopHeight, SRCCOPY)) {
+                if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, 0, 
+                                      destCenterWidth, sm.cyTopHeight,
+                                      hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top, 
+                                      srcCenterWidth, sm.cyTopHeight, 
+                                      sizingtype, transparent, transparentcolor)) {
                     hr = HRESULT_FROM_WIN32(GetLastError());
                     goto draw_error; 
                 }
                 /* Center bottom */
-                if(!StretchBlt(hdcDst, sm.cxLeftWidth, dstSize.y-sm.cyBottomHeight, destCenterWidth, sm.cyBottomHeight,
-                               hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.bottom-sm.cyBottomHeight, srcCenterWidth, sm.cyTopHeight, SRCCOPY)) {
+                if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, dstSize.y-sm.cyBottomHeight, 
+                                      destCenterWidth, sm.cyBottomHeight,
+                                      hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.bottom-sm.cyBottomHeight, 
+                                      srcCenterWidth, sm.cyBottomHeight, 
+                                      sizingtype, transparent, transparentcolor)) {
                     hr = HRESULT_FROM_WIN32(GetLastError());
                     goto draw_error; 
                 }
             }
             if(destCenterHeight > 0) {
                 /* Left center */
-                if(!StretchBlt(hdcDst, 0, sm.cyTopHeight, sm.cxLeftWidth, destCenterHeight,
-                           hdcSrc, rcSrc.left, rcSrc.top+sm.cyTopHeight, sm.cxLeftWidth, srcCenterHeight, SRCCOPY)) {
+                if(!UXTHEME_SizedBlt (hdcDst, 0, sm.cyTopHeight, 
+                                      sm.cxLeftWidth, destCenterHeight,
+                                      hdcSrc, rcSrc.left, rcSrc.top+sm.cyTopHeight, 
+                                      sm.cxLeftWidth, srcCenterHeight, 
+                                      sizingtype, 
+                                      transparent, transparentcolor)) {
                     hr = HRESULT_FROM_WIN32(GetLastError());
                     goto draw_error; 
                 }
                 /* Right center */
-                if(!StretchBlt(hdcDst, dstSize.x-sm.cxRightWidth, sm.cyTopHeight, sm.cxRightWidth, destCenterHeight,
-                               hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top+sm.cyTopHeight, sm.cxRightWidth, srcCenterHeight, SRCCOPY)) {
+                if(!UXTHEME_SizedBlt (hdcDst, dstSize.x-sm.cxRightWidth, sm.cyTopHeight, 
+                                      sm.cxRightWidth, destCenterHeight,
+                                      hdcSrc, rcSrc.right-sm.cxRightWidth, rcSrc.top+sm.cyTopHeight, 
+                                      sm.cxRightWidth, srcCenterHeight, 
+                                      sizingtype, transparent, transparentcolor)) {
                     hr = HRESULT_FROM_WIN32(GetLastError());
                     goto draw_error; 
                 }
@@ -562,8 +751,11 @@
                 GetThemeBool(hTheme, iPartId, iStateId, TMT_BORDERONLY, &borderonly);
                 if(!borderonly) {
                     /* Center */
-                    if(!StretchBlt(hdcDst, sm.cxLeftWidth, sm.cyTopHeight, destCenterWidth, destCenterHeight,
-                                   hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top+sm.cyTopHeight, srcCenterWidth, srcCenterHeight, SRCCOPY)) {
+                    if(!UXTHEME_SizedBlt (hdcDst, sm.cxLeftWidth, sm.cyTopHeight, 
+                                          destCenterWidth, destCenterHeight,
+                                          hdcSrc, rcSrc.left+sm.cxLeftWidth, rcSrc.top+sm.cyTopHeight, 
+                                          srcCenterWidth, srcCenterHeight, 
+                                          sizingtype, transparent, transparentcolor)) {
                         hr = HRESULT_FROM_WIN32(GetLastError());
                         goto draw_error; 
                     }
@@ -571,20 +763,10 @@
             }
         }
 
-        if(!UXTHEME_Blt(hdc, rcDst.left, rcDst.top, dstSize.x, dstSize.y,
-                        hdcDst, 0, 0,
-                        transparent, transparentcolor))
-            hr = HRESULT_FROM_WIN32(GetLastError());
-
 draw_error:
-        if(hdcDst) {
-            SelectObject(hdcDst, oldDst);
-            DeleteDC(hdcDst);
-        }
-        if(bmpDst) DeleteObject(bmpDst);
+        SetViewportOrgEx (hdcDst, org.x, org.y, NULL);
     }
     SelectObject(hdcSrc, oldSrc);
-    DeleteObject(bmpSrc);
     DeleteDC(hdcSrc);
     CopyRect(pRect, &rcDst);
     return hr;
@@ -751,6 +933,9 @@
     if(!hTheme)
         return E_HANDLE;
 
+    GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
+    if (bgtype == BT_NONE) return S_OK;
+
     /* Ensure we have a DTBGOPTS structure available, simplifies some of the code */
     opts = pOptions;
     if(!opts) opts = &defaultOpts;
@@ -765,7 +950,6 @@
     }
     CopyRect(&rt, pRect);
 
-    GetThemeEnumValue(hTheme, iPartId, iStateId, TMT_BGTYPE, &bgtype);
     if(bgtype == BT_IMAGEFILE)
         hr = UXTHEME_DrawImageBackground(hTheme, hdc, iPartId, iStateId, &rt, opts);
     else if(bgtype == BT_BORDERFILL)
@@ -787,19 +971,557 @@
     return hr;
 }
 
+/*
+ * DrawThemeEdge() implementation
+ *
+ * Since it basically is DrawEdge() with different colors, I copied its code
+ * from user32's uitools.c.
+ */
+
+enum
+{
+    EDGE_LIGHT,
+    EDGE_HIGHLIGHT,
+    EDGE_SHADOW,
+    EDGE_DARKSHADOW,
+    EDGE_FILL,
+
+    EDGE_WINDOW,
+    EDGE_WINDOWFRAME,
+
+    EDGE_NUMCOLORS
+};
+
+static const struct 
+{
+    int themeProp;
+    int sysColor;
+} EdgeColorMap[EDGE_NUMCOLORS] = {
+    {TMT_EDGELIGHTCOLOR,                  COLOR_3DLIGHT},
+    {TMT_EDGEHIGHLIGHTCOLOR,              COLOR_BTNHIGHLIGHT},
+    {TMT_EDGESHADOWCOLOR,                 COLOR_BTNSHADOW},
+    {TMT_EDGEDKSHADOWCOLOR,               COLOR_3DDKSHADOW},
+    {TMT_EDGEFILLCOLOR,                   COLOR_BTNFACE},
+    {-1,                                  COLOR_WINDOW},
+    {-1,                                  COLOR_WINDOWFRAME}
+};
+
+static const signed char LTInnerNormal[] = {
+    -1,           -1,                 -1,                 -1,
+    -1,           EDGE_HIGHLIGHT,     EDGE_HIGHLIGHT,     -1,
+    -1,           EDGE_DARKSHADOW,    EDGE_DARKSHADOW,    -1,
+    -1,           -1,                 -1,                 -1
+};
+
+static const signed char LTOuterNormal[] = {
+    -1,                 EDGE_LIGHT,     EDGE_SHADOW, -1,
+    EDGE_HIGHLIGHT,     EDGE_LIGHT,     EDGE_SHADOW, -1,
+    EDGE_DARKSHADOW,    EDGE_LIGHT,     EDGE_SHADOW, -1,
+    -1,                 EDGE_LIGHT,     EDGE_SHADOW, -1
+};
+
+static const signed char RBInnerNormal[] = {
+    -1,           -1,                 -1,               -1,
+    -1,           EDGE_SHADOW,        EDGE_SHADOW,      -1,
+    -1,           EDGE_LIGHT,         EDGE_LIGHT,       -1,
+    -1,           -1,                 -1,               -1
+};
+
+static const signed char RBOuterNormal[] = {
+    -1,               EDGE_DARKSHADOW,  EDGE_HIGHLIGHT, -1,
+    EDGE_SHADOW,      EDGE_DARKSHADOW,  EDGE_HIGHLIGHT, -1,
+    EDGE_LIGHT,       EDGE_DARKSHADOW,  EDGE_HIGHLIGHT, -1,
+    -1,               EDGE_DARKSHADOW,  EDGE_HIGHLIGHT, -1
+};
+
+static const signed char LTInnerSoft[] = {
+    -1,                  -1,                -1,               -1,
+    -1,                  EDGE_LIGHT,        EDGE_LIGHT,       -1,
+    -1,                  EDGE_SHADOW,       EDGE_SHADOW,      -1,
+    -1,                  -1,                -1,               -1
+};
+
+static const signed char LTOuterSoft[] = {
+    -1,               EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1,
+    EDGE_LIGHT,       EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1,
+    EDGE_SHADOW,      EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1,
+    -1,               EDGE_HIGHLIGHT, EDGE_DARKSHADOW, -1
+};
+
+#define RBInnerSoft RBInnerNormal   /* These are the same */
+#define RBOuterSoft RBOuterNormal
+
+static const signed char LTRBOuterMono[] = {
+    -1,           EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,
+    EDGE_WINDOW,  EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,
+    EDGE_WINDOW,  EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,
+    EDGE_WINDOW,  EDGE_WINDOWFRAME, EDGE_WINDOWFRAME, EDGE_WINDOWFRAME,
+};
+
+static const signed char LTRBInnerMono[] = {
+    -1, -1,           -1,           -1,
+    -1, EDGE_WINDOW,  EDGE_WINDOW,  EDGE_WINDOW,
+    -1, EDGE_WINDOW,  EDGE_WINDOW,  EDGE_WINDOW,
+    -1, EDGE_WINDOW,  EDGE_WINDOW,  EDGE_WINDOW,
+};
+
+static const signed char LTRBOuterFlat[] = {
+    -1,                 EDGE_SHADOW, EDGE_SHADOW, EDGE_SHADOW,
+    EDGE_FILL,          EDGE_SHADOW, EDGE_SHADOW, EDGE_SHADOW,
+    EDGE_FILL,          EDGE_SHADOW, EDGE_SHADOW, EDGE_SHADOW,
+    EDGE_FILL,          EDGE_SHADOW, EDGE_SHADOW, EDGE_SHADOW,
+};
+
+static const signed char LTRBInnerFlat[] = {
+    -1, -1,               -1,               -1,
+    -1, EDGE_FILL,        EDGE_FILL,        EDGE_FILL,
+    -1, EDGE_FILL,        EDGE_FILL,        EDGE_FILL,
+    -1, EDGE_FILL,        EDGE_FILL,        EDGE_FILL,
+};
+
+static COLORREF get_edge_color (int edgeType, HTHEME theme, int part, int state)
+{
+    COLORREF col;
+    if ((EdgeColorMap[edgeType].themeProp == -1)
+        || FAILED (GetThemeColor (theme, part, state, 
+            EdgeColorMap[edgeType].themeProp, &col)))
+        col = GetSysColor (EdgeColorMap[edgeType].sysColor);
+    return col;
+}
+
+static inline HPEN get_edge_pen (int edgeType, HTHEME theme, int part, int state)
+{
+    return CreatePen (PS_SOLID, 1, get_edge_color (edgeType, theme, part, state));
+}
+
+static inline HBRUSH get_edge_brush (int edgeType, HTHEME theme, int part, int state)
+{
+    return CreateSolidBrush (get_edge_color (edgeType, theme, part, state));
+}
+
 /***********************************************************************
+ *           draw_diag_edge
+ *
+ * Same as DrawEdge invoked with BF_DIAGONAL
+ */
+static HRESULT draw_diag_edge (HDC hdc, HTHEME theme, int part, int state,
+                               const RECT* rc, UINT uType, 
+                               UINT uFlags, LPRECT contentsRect)
+{
+    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;
+    HRESULT retval = (((uType & BDR_INNER) == BDR_INNER
+                       || (uType & BDR_OUTER) == BDR_OUTER)
+                      && !(uFlags & (BF_FLAT|BF_MONO)) ) ? E_FAIL : S_OK;
+    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 = get_edge_pen (InnerI, theme, part, state);
+    if(OuterI != -1) OuterPen = get_edge_pen (OuterI, theme, part, state);
+
+    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):
[truncated at 1000 lines; 1215 more skipped]