OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / tk8.6.12 / generic / ttk / ttkClamTheme.c
diff --git a/util/src/TclTk/tk8.6.12/generic/ttk/ttkClamTheme.c b/util/src/TclTk/tk8.6.12/generic/ttk/ttkClamTheme.c
new file mode 100644 (file)
index 0000000..733a391
--- /dev/null
@@ -0,0 +1,1032 @@
+/*
+ * Copyright (C) 2004 Joe English
+ *
+ * "clam" theme; inspired by the XFCE family of Gnome themes.
+ */
+
+#include "tkInt.h"
+#include "ttkTheme.h"
+
+/*
+ * Under windows, the Tk-provided XDrawLine and XDrawArc have an
+ * off-by-one error in the end point. This is especially apparent with this
+ * theme. Defining this macro as true handles this case.
+ */
+#if defined(_WIN32) && !defined(WIN32_XDRAWLINE_HACK)
+#      define WIN32_XDRAWLINE_HACK 1
+#else
+#      define WIN32_XDRAWLINE_HACK 0
+#endif
+
+#define STR(x) StR(x)
+#define StR(x) #x
+
+#define SCROLLBAR_THICKNESS 14
+
+#define FRAME_COLOR    "#dcdad5"
+#define LIGHT_COLOR    "#ffffff"
+#define DARK_COLOR     "#cfcdc8"
+#define DARKER_COLOR   "#bab5ab"
+#define DARKEST_COLOR  "#9e9a91"
+
+/*------------------------------------------------------------------------
+ * +++ Utilities.
+ */
+
+static GC Ttk_GCForColor(Tk_Window tkwin, Tcl_Obj* colorObj, Drawable d)
+{
+    GC gc = Tk_GCForColor(Tk_GetColorFromObj(tkwin, colorObj), d);
+
+#ifdef MAC_OSX_TK
+    /*
+     * Workaround for Tk bug under Aqua where the default line width is 0.
+     */
+    Display *display = Tk_Display(tkwin);
+    unsigned long mask = 0ul;
+    XGCValues gcValues;
+
+    gcValues.line_width = 1;
+    mask = GCLineWidth;
+
+    XChangeGC(display, gc, mask, &gcValues);
+#endif
+
+    return gc;
+}
+
+static void DrawSmoothBorder(
+    Tk_Window tkwin, Drawable d, Ttk_Box b,
+    Tcl_Obj *outerColorObj, Tcl_Obj *upperColorObj, Tcl_Obj *lowerColorObj)
+{
+    Display *display = Tk_Display(tkwin);
+    int x1 = b.x, x2 = b.x + b.width - 1;
+    int y1 = b.y, y2 = b.y + b.height - 1;
+    const int w = WIN32_XDRAWLINE_HACK;
+    GC gc;
+
+    if (   outerColorObj
+       && (gc=Ttk_GCForColor(tkwin,outerColorObj,d)))
+    {
+       XDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1); /* N */
+       XDrawLine(display,d,gc, x1+1,y2, x2-1+w,y2); /* S */
+       XDrawLine(display,d,gc, x1,y1+1, x1,y2-1+w); /* E */
+       XDrawLine(display,d,gc, x2,y1+1, x2,y2-1+w); /* W */
+    }
+
+    if (   upperColorObj
+       && (gc=Ttk_GCForColor(tkwin,upperColorObj,d)))
+    {
+       XDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1); /* N */
+       XDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1);   /* E */
+    }
+
+    if (   lowerColorObj
+       && (gc=Ttk_GCForColor(tkwin,lowerColorObj,d)))
+    {
+       XDrawLine(display,d,gc, x2-1,y2-1, x1+1-w,y2-1); /* S */
+       XDrawLine(display,d,gc, x2-1,y2-1, x2-1,y1+1-w); /* W */
+    }
+}
+
+static GC BackgroundGC(Tk_Window tkwin, Tcl_Obj *backgroundObj)
+{
+    Tk_3DBorder bd = Tk_Get3DBorderFromObj(tkwin, backgroundObj);
+    return Tk_3DBorderGC(tkwin, bd, TK_3D_FLAT_GC);
+}
+
+/*------------------------------------------------------------------------
+ * +++ Border element.
+ */
+
+typedef struct {
+    Tcl_Obj    *borderColorObj;
+    Tcl_Obj    *lightColorObj;
+    Tcl_Obj    *darkColorObj;
+    Tcl_Obj    *reliefObj;
+    Tcl_Obj    *borderWidthObj;        /* See <<NOTE-BORDERWIDTH>> */
+} BorderElement;
+
+static Ttk_ElementOptionSpec BorderElementOptions[] = {
+    { "-bordercolor", TK_OPTION_COLOR,
+       Tk_Offset(BorderElement,borderColorObj), DARKEST_COLOR },
+    { "-lightcolor", TK_OPTION_COLOR,
+       Tk_Offset(BorderElement,lightColorObj), LIGHT_COLOR },
+    { "-darkcolor", TK_OPTION_COLOR,
+       Tk_Offset(BorderElement,darkColorObj), DARK_COLOR },
+    { "-relief", TK_OPTION_RELIEF,
+       Tk_Offset(BorderElement,reliefObj), "flat" },
+    { "-borderwidth", TK_OPTION_PIXELS,
+       Tk_Offset(BorderElement,borderWidthObj), "2" },
+    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
+};
+
+/*
+ * <<NOTE-BORDERWIDTH>>: -borderwidth is only partially supported:
+ * in this theme, borders are always exactly 2 pixels thick.
+ * With -borderwidth 0, border is not drawn at all;
+ * otherwise a 2-pixel border is used.  For -borderwidth > 2,
+ * the excess is used as padding.
+ */
+
+static void BorderElementSize(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+    BorderElement *border = (BorderElement*)elementRecord;
+    int borderWidth = 2;
+    (void)dummy;
+    (void)widthPtr;
+    (void)heightPtr;
+
+    Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth);
+    if (borderWidth == 1) ++borderWidth;
+    *paddingPtr = Ttk_UniformPadding((short)borderWidth);
+}
+
+static void BorderElementDraw(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned state)
+{
+    BorderElement *border = (BorderElement *)elementRecord;
+    int relief = TK_RELIEF_FLAT;
+    int borderWidth = 2;
+    Tcl_Obj *outer = 0, *upper = 0, *lower = 0;
+    (void)dummy;
+    (void)state;
+
+    Tk_GetReliefFromObj(NULL, border->reliefObj, &relief);
+    Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth);
+
+    if (borderWidth == 0) return;
+
+    switch (relief) {
+       case TK_RELIEF_GROOVE :
+       case TK_RELIEF_RIDGE :
+       case TK_RELIEF_RAISED :
+           outer = border->borderColorObj;
+           upper = border->lightColorObj;
+           lower = border->darkColorObj;
+           break;
+       case TK_RELIEF_SUNKEN :
+           outer = border->borderColorObj;
+           upper = border->darkColorObj;
+           lower = border->lightColorObj;
+           break;
+       case TK_RELIEF_FLAT :
+           outer = upper = lower = 0;
+           break;
+       case TK_RELIEF_SOLID :
+           outer = upper = lower = border->borderColorObj;
+           break;
+    }
+
+    DrawSmoothBorder(tkwin, d, b, outer, upper, lower);
+}
+
+static Ttk_ElementSpec BorderElementSpec = {
+    TK_STYLE_VERSION_2,
+    sizeof(BorderElement),
+    BorderElementOptions,
+    BorderElementSize,
+    BorderElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Field element.
+ */
+
+typedef struct {
+    Tcl_Obj    *borderColorObj;
+    Tcl_Obj    *lightColorObj;
+    Tcl_Obj    *darkColorObj;
+    Tcl_Obj    *backgroundObj;
+} FieldElement;
+
+static Ttk_ElementOptionSpec FieldElementOptions[] = {
+    { "-bordercolor", TK_OPTION_COLOR,
+       Tk_Offset(FieldElement,borderColorObj), DARKEST_COLOR },
+    { "-lightcolor", TK_OPTION_COLOR,
+       Tk_Offset(FieldElement,lightColorObj), LIGHT_COLOR },
+    { "-darkcolor", TK_OPTION_COLOR,
+       Tk_Offset(FieldElement,darkColorObj), DARK_COLOR },
+    { "-fieldbackground", TK_OPTION_BORDER,
+       Tk_Offset(FieldElement,backgroundObj), "white" },
+    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
+};
+
+static void FieldElementSize(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+    (void)dummy;
+    (void)elementRecord;
+    (void)tkwin;
+    (void)widthPtr;
+    (void)heightPtr;
+
+    *paddingPtr = Ttk_UniformPadding(2);
+}
+
+static void FieldElementDraw(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned state)
+{
+    FieldElement *field = (FieldElement *)elementRecord;
+    Tk_3DBorder bg = Tk_Get3DBorderFromObj(tkwin, field->backgroundObj);
+    Ttk_Box f = Ttk_PadBox(b, Ttk_UniformPadding(2));
+    Tcl_Obj *outer = field->borderColorObj,
+           *inner = field->lightColorObj;
+    (void)dummy;
+    (void)state;
+
+    DrawSmoothBorder(tkwin, d, b, outer, inner, inner);
+    Tk_Fill3DRectangle(
+       tkwin, d, bg, f.x, f.y, f.width, f.height, 0, TK_RELIEF_SUNKEN);
+}
+
+static Ttk_ElementSpec FieldElementSpec = {
+    TK_STYLE_VERSION_2,
+    sizeof(FieldElement),
+    FieldElementOptions,
+    FieldElementSize,
+    FieldElementDraw
+};
+
+/*
+ * Modified field element for comboboxes:
+ *     Right edge is expanded to overlap the dropdown button.
+ */
+static void ComboboxFieldElementDraw(
+    void *clientData, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned state)
+{
+    FieldElement *field = (FieldElement *)elementRecord;
+    GC gc = Ttk_GCForColor(tkwin,field->borderColorObj,d);
+
+    ++b.width;
+    FieldElementDraw(clientData, elementRecord, tkwin, d, b, state);
+
+    XDrawLine(Tk_Display(tkwin), d, gc,
+           b.x + b.width - 1, b.y,
+           b.x + b.width - 1, b.y + b.height - 1 + WIN32_XDRAWLINE_HACK);
+}
+
+static Ttk_ElementSpec ComboboxFieldElementSpec = {
+    TK_STYLE_VERSION_2,
+    sizeof(FieldElement),
+    FieldElementOptions,
+    FieldElementSize,
+    ComboboxFieldElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Indicator elements for check and radio buttons.
+ */
+
+typedef struct {
+    Tcl_Obj *sizeObj;
+    Tcl_Obj *marginObj;
+    Tcl_Obj *backgroundObj;
+    Tcl_Obj *foregroundObj;
+    Tcl_Obj *upperColorObj;
+    Tcl_Obj *lowerColorObj;
+} IndicatorElement;
+
+static Ttk_ElementOptionSpec IndicatorElementOptions[] = {
+    { "-indicatorsize", TK_OPTION_PIXELS,
+       Tk_Offset(IndicatorElement,sizeObj), "10" },
+    { "-indicatormargin", TK_OPTION_STRING,
+       Tk_Offset(IndicatorElement,marginObj), "1" },
+    { "-indicatorbackground", TK_OPTION_COLOR,
+       Tk_Offset(IndicatorElement,backgroundObj), "white" },
+    { "-indicatorforeground", TK_OPTION_COLOR,
+       Tk_Offset(IndicatorElement,foregroundObj), "black" },
+    { "-upperbordercolor", TK_OPTION_COLOR,
+       Tk_Offset(IndicatorElement,upperColorObj), DARKEST_COLOR },
+    { "-lowerbordercolor", TK_OPTION_COLOR,
+       Tk_Offset(IndicatorElement,lowerColorObj), DARK_COLOR },
+    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
+};
+
+static void IndicatorElementSize(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+    IndicatorElement *indicator = (IndicatorElement *)elementRecord;
+    Ttk_Padding margins;
+    int size = 10;
+    (void)dummy;
+    (void)paddingPtr;
+
+    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
+    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
+    *widthPtr = size + Ttk_PaddingWidth(margins);
+    *heightPtr = size + Ttk_PaddingHeight(margins);
+}
+
+static void RadioIndicatorElementDraw(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned state)
+{
+    IndicatorElement *indicator = (IndicatorElement *)elementRecord;
+    GC gcb=Ttk_GCForColor(tkwin,indicator->backgroundObj,d);
+    GC gcf=Ttk_GCForColor(tkwin,indicator->foregroundObj,d);
+    GC gcu=Ttk_GCForColor(tkwin,indicator->upperColorObj,d);
+    GC gcl=Ttk_GCForColor(tkwin,indicator->lowerColorObj,d);
+    Ttk_Padding padding;
+    (void)dummy;
+
+    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
+    b = Ttk_PadBox(b, padding);
+
+    XFillArc(Tk_Display(tkwin),d,gcb, b.x,b.y,b.width,b.height, 0,360*64);
+    XDrawArc(Tk_Display(tkwin),d,gcl, b.x,b.y,b.width,b.height, 225*64,180*64);
+    XDrawArc(Tk_Display(tkwin),d,gcu, b.x,b.y,b.width,b.height, 45*64,180*64);
+
+    if (state & TTK_STATE_SELECTED) {
+       b = Ttk_PadBox(b,Ttk_UniformPadding(3));
+       XFillArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 0,360*64);
+       XDrawArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 0,360*64);
+#if WIN32_XDRAWLINE_HACK
+       XDrawArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 300*64,360*64);
+#endif
+    }
+}
+
+static void CheckIndicatorElementDraw(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned state)
+{
+    Display *display = Tk_Display(tkwin);
+    IndicatorElement *indicator = (IndicatorElement *)elementRecord;
+
+    GC gcb=Ttk_GCForColor(tkwin,indicator->backgroundObj,d);
+    GC gcf=Ttk_GCForColor(tkwin,indicator->foregroundObj,d);
+    GC gcu=Ttk_GCForColor(tkwin,indicator->upperColorObj,d);
+    GC gcl=Ttk_GCForColor(tkwin,indicator->lowerColorObj,d);
+    Ttk_Padding padding;
+    const int w = WIN32_XDRAWLINE_HACK;
+    (void)dummy;
+
+    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
+    b = Ttk_PadBox(b, padding);
+
+    XFillRectangle(display,d,gcb, b.x,b.y,b.width,b.height);
+    XDrawLine(display,d,gcl,b.x,b.y+b.height,b.x+b.width+w,b.y+b.height);/*S*/
+    XDrawLine(display,d,gcl,b.x+b.width,b.y,b.x+b.width,b.y+b.height+w); /*E*/
+    XDrawLine(display,d,gcu,b.x,b.y, b.x,b.y+b.height+w); /*W*/
+    XDrawLine(display,d,gcu,b.x,b.y, b.x+b.width+w,b.y);  /*N*/
+
+    if (state & TTK_STATE_SELECTED) {
+       int p,q,r,s;
+
+       b = Ttk_PadBox(b,Ttk_UniformPadding(2));
+       p = b.x, q = b.y, r = b.x+b.width, s = b.y+b.height;
+
+       r+=w, s+=w;
+       XDrawLine(display, d, gcf, p,   q,   r,   s);
+       XDrawLine(display, d, gcf, p+1, q,   r,   s-1);
+       XDrawLine(display, d, gcf, p,   q+1, r-1, s);
+
+       s-=w, q-=w;
+       XDrawLine(display, d, gcf, p,   s,   r,   q);
+       XDrawLine(display, d, gcf, p+1, s,   r,   q+1);
+       XDrawLine(display, d, gcf, p,   s-1, r-1, q);
+    }
+}
+
+static Ttk_ElementSpec RadioIndicatorElementSpec = {
+    TK_STYLE_VERSION_2,
+    sizeof(IndicatorElement),
+    IndicatorElementOptions,
+    IndicatorElementSize,
+    RadioIndicatorElementDraw
+};
+
+static Ttk_ElementSpec CheckIndicatorElementSpec = {
+    TK_STYLE_VERSION_2,
+    sizeof(IndicatorElement),
+    IndicatorElementOptions,
+    IndicatorElementSize,
+    CheckIndicatorElementDraw
+};
+
+#define MENUBUTTON_ARROW_SIZE 5
+
+typedef struct {
+    Tcl_Obj *sizeObj;
+    Tcl_Obj *colorObj;
+    Tcl_Obj *paddingObj;
+} MenuIndicatorElement;
+
+static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] =
+{
+    { "-arrowsize", TK_OPTION_PIXELS,
+       Tk_Offset(MenuIndicatorElement,sizeObj),
+       STR(MENUBUTTON_ARROW_SIZE)},
+    { "-arrowcolor",TK_OPTION_COLOR,
+       Tk_Offset(MenuIndicatorElement,colorObj),
+       "black" },
+    { "-arrowpadding",TK_OPTION_STRING,
+       Tk_Offset(MenuIndicatorElement,paddingObj),
+       "3" },
+    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
+};
+
+static void MenuIndicatorElementSize(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+    MenuIndicatorElement *indicator = (MenuIndicatorElement *)elementRecord;
+    Ttk_Padding margins;
+    int size = MENUBUTTON_ARROW_SIZE;
+    (void)dummy;
+    (void)paddingPtr;
+
+    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
+    Ttk_GetPaddingFromObj(NULL, tkwin, indicator->paddingObj, &margins);
+    TtkArrowSize(size, ARROW_DOWN, widthPtr, heightPtr);
+    *widthPtr += Ttk_PaddingWidth(margins);
+    *heightPtr += Ttk_PaddingHeight(margins);
+}
+
+static void MenuIndicatorElementDraw(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned int state)
+{
+    MenuIndicatorElement *indicator = (MenuIndicatorElement *)elementRecord;
+    XColor *arrowColor = Tk_GetColorFromObj(tkwin, indicator->colorObj);
+    GC gc = Tk_GCForColor(arrowColor, d);
+    int size = MENUBUTTON_ARROW_SIZE;
+    int width, height;
+    (void)dummy;
+    (void)state;
+
+    Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
+
+    TtkArrowSize(size, ARROW_DOWN, &width, &height);
+    b = Ttk_StickBox(b, width, height, 0);
+    TtkFillArrow(Tk_Display(tkwin), d, gc, b, ARROW_DOWN);
+}
+
+static Ttk_ElementSpec MenuIndicatorElementSpec =
+{
+    TK_STYLE_VERSION_2,
+    sizeof(MenuIndicatorElement),
+    MenuIndicatorElementOptions,
+    MenuIndicatorElementSize,
+    MenuIndicatorElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Grips.
+ *
+ * TODO: factor this with ThumbElementDraw
+ */
+
+static Ttk_Orient GripClientData[] = {
+    TTK_ORIENT_HORIZONTAL, TTK_ORIENT_VERTICAL
+};
+
+typedef struct {
+    Tcl_Obj    *lightColorObj;
+    Tcl_Obj    *borderColorObj;
+    Tcl_Obj    *gripCountObj;
+} GripElement;
+
+static Ttk_ElementOptionSpec GripElementOptions[] = {
+    { "-lightcolor", TK_OPTION_COLOR,
+       Tk_Offset(GripElement,lightColorObj), LIGHT_COLOR },
+    { "-bordercolor", TK_OPTION_COLOR,
+       Tk_Offset(GripElement,borderColorObj), DARKEST_COLOR },
+    { "-gripcount", TK_OPTION_INT,
+       Tk_Offset(GripElement,gripCountObj), "5" },
+    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
+};
+
+static void GripElementSize(
+    void *clientData, void *elementRecord, Tk_Window tkwin,
+    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+    int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
+    GripElement *grip = (GripElement *)elementRecord;
+    int gripCount = 0;
+    (void)tkwin;
+    (void)paddingPtr;
+
+    Tcl_GetIntFromObj(NULL, grip->gripCountObj, &gripCount);
+    if (horizontal) {
+       *widthPtr = 2*gripCount;
+    } else {
+       *heightPtr = 2*gripCount;
+    }
+}
+
+static void GripElementDraw(
+    void *clientData, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned state)
+{
+    const int w = WIN32_XDRAWLINE_HACK;
+    int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
+    GripElement *grip = (GripElement *)elementRecord;
+    GC lightGC = Ttk_GCForColor(tkwin,grip->lightColorObj,d);
+    GC darkGC = Ttk_GCForColor(tkwin,grip->borderColorObj,d);
+    int gripPad = 1, gripCount = 0;
+    int i;
+
+    Tcl_GetIntFromObj(NULL, grip->gripCountObj, &gripCount);
+
+    if (horizontal) {
+       int x = b.x + b.width / 2 - gripCount;
+       int y1 = b.y + gripPad, y2 = b.y + b.height - gripPad - 1 + w;
+       for (i=0; i<gripCount; ++i) {
+           XDrawLine(Tk_Display(tkwin), d, darkGC,  x,y1, x,y2); ++x;
+           XDrawLine(Tk_Display(tkwin), d, lightGC, x,y1, x,y2); ++x;
+       }
+    } else {
+       int y = b.y + b.height / 2 - gripCount;
+       int x1 = b.x + gripPad, x2 = b.x + b.width - gripPad - 1 + w;
+       for (i=0; i<gripCount; ++i) {
+           XDrawLine(Tk_Display(tkwin), d, darkGC,  x1,y, x2,y); ++y;
+           XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y, x2,y); ++y;
+       }
+    }
+}
+
+static Ttk_ElementSpec GripElementSpec = {
+    TK_STYLE_VERSION_2,
+    sizeof(GripElement),
+    GripElementOptions,
+    GripElementSize,
+    GripElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Scrollbar elements: trough, arrows, thumb.
+ *
+ * Notice that the trough element has 0 internal padding;
+ * that way the thumb and arrow borders overlap the trough.
+ */
+
+typedef struct { /* Common element record for scrollbar elements */
+    Tcl_Obj    *orientObj;
+    Tcl_Obj    *backgroundObj;
+    Tcl_Obj    *borderColorObj;
+    Tcl_Obj    *troughColorObj;
+    Tcl_Obj    *lightColorObj;
+    Tcl_Obj    *darkColorObj;
+    Tcl_Obj    *arrowColorObj;
+    Tcl_Obj    *arrowSizeObj;
+    Tcl_Obj    *gripCountObj;
+    Tcl_Obj    *sliderlengthObj;
+} ScrollbarElement;
+
+static Ttk_ElementOptionSpec ScrollbarElementOptions[] = {
+    { "-orient", TK_OPTION_ANY,
+       Tk_Offset(ScrollbarElement, orientObj), "horizontal" },
+    { "-background", TK_OPTION_BORDER,
+       Tk_Offset(ScrollbarElement,backgroundObj), FRAME_COLOR },
+    { "-bordercolor", TK_OPTION_COLOR,
+       Tk_Offset(ScrollbarElement,borderColorObj), DARKEST_COLOR },
+    { "-troughcolor", TK_OPTION_COLOR,
+       Tk_Offset(ScrollbarElement,troughColorObj), DARKER_COLOR },
+    { "-lightcolor", TK_OPTION_COLOR,
+       Tk_Offset(ScrollbarElement,lightColorObj), LIGHT_COLOR },
+    { "-darkcolor", TK_OPTION_COLOR,
+       Tk_Offset(ScrollbarElement,darkColorObj), DARK_COLOR },
+    { "-arrowcolor", TK_OPTION_COLOR,
+       Tk_Offset(ScrollbarElement,arrowColorObj), "#000000" },
+    { "-arrowsize", TK_OPTION_PIXELS,
+       Tk_Offset(ScrollbarElement,arrowSizeObj), STR(SCROLLBAR_THICKNESS) },
+    { "-gripcount", TK_OPTION_INT,
+       Tk_Offset(ScrollbarElement,gripCountObj), "5" },
+    { "-sliderlength", TK_OPTION_INT,
+       Tk_Offset(ScrollbarElement,sliderlengthObj), "30" },
+    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
+};
+
+static void TroughElementDraw(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned state)
+{
+    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
+    GC gcb = Ttk_GCForColor(tkwin,sb->borderColorObj,d);
+    GC gct = Ttk_GCForColor(tkwin,sb->troughColorObj,d);
+    (void)dummy;
+    (void)state;
+
+    XFillRectangle(Tk_Display(tkwin), d, gct, b.x, b.y, b.width-1, b.height-1);
+    XDrawRectangle(Tk_Display(tkwin), d, gcb, b.x, b.y, b.width-1, b.height-1);
+}
+
+static Ttk_ElementSpec TroughElementSpec = {
+    TK_STYLE_VERSION_2,
+    sizeof(ScrollbarElement),
+    ScrollbarElementOptions,
+    TtkNullElementSize,
+    TroughElementDraw
+};
+
+static void ThumbElementSize(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
+    int size = SCROLLBAR_THICKNESS;
+    (void)dummy;
+    (void)tkwin;
+    (void)paddingPtr;
+
+    Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &size);
+    *widthPtr = *heightPtr = size;
+}
+
+static void ThumbElementDraw(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned state)
+{
+    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
+    int gripCount = 0;
+    int orient = TTK_ORIENT_HORIZONTAL;
+    GC lightGC, darkGC;
+    int x1, y1, x2, y2, dx, dy, i;
+    const int w = WIN32_XDRAWLINE_HACK;
+    (void)dummy;
+    (void)state;
+
+    DrawSmoothBorder(tkwin, d, b,
+       sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
+    XFillRectangle(
+       Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj),
+       b.x+2, b.y+2, b.width-4, b.height-4);
+
+    /*
+     * Draw grip:
+     */
+    Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient);
+    Tcl_GetIntFromObj(NULL, sb->gripCountObj, &gripCount);
+    lightGC = Ttk_GCForColor(tkwin,sb->lightColorObj,d);
+    darkGC = Ttk_GCForColor(tkwin,sb->borderColorObj,d);
+
+    if (orient == TTK_ORIENT_HORIZONTAL) {
+       dx = 1; dy = 0;
+       x1 = x2 = b.x + b.width / 2 - gripCount;
+       y1 = b.y + 2;
+       y2 = b.y + b.height - 3 + w;
+    } else {
+       dx = 0; dy = 1;
+       y1 = y2 = b.y + b.height / 2 - gripCount;
+       x1 = b.x + 2;
+       x2 = b.x + b.width - 3 + w;
+    }
+
+    for (i=0; i<gripCount; ++i) {
+       XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y1, x2,y2);
+       x1 += dx; x2 += dx; y1 += dy; y2 += dy;
+       XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y1, x2,y2);
+       x1 += dx; x2 += dx; y1 += dy; y2 += dy;
+    }
+}
+
+static Ttk_ElementSpec ThumbElementSpec = {
+    TK_STYLE_VERSION_2,
+    sizeof(ScrollbarElement),
+    ScrollbarElementOptions,
+    ThumbElementSize,
+    ThumbElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Slider element.
+ */
+static void SliderElementSize(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
+    int length, thickness;
+    int orient;
+    (void)dummy;
+    (void)paddingPtr;
+
+    length = thickness = SCROLLBAR_THICKNESS;
+    Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient);
+    Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &thickness);
+    Tk_GetPixelsFromObj(NULL, tkwin, sb->sliderlengthObj, &length);
+    if (orient == TTK_ORIENT_VERTICAL) {
+       *heightPtr = length;
+       *widthPtr = thickness;
+    } else {
+       *heightPtr = thickness;
+       *widthPtr = length;
+    }
+
+}
+
+static Ttk_ElementSpec SliderElementSpec = {
+    TK_STYLE_VERSION_2,
+    sizeof(ScrollbarElement),
+    ScrollbarElementOptions,
+    SliderElementSize,
+    ThumbElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Progress bar element
+ */
+static void PbarElementSize(
+    void *clientData, void *elementRecord, Tk_Window tkwin,
+    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+    SliderElementSize(clientData, elementRecord, tkwin,
+           widthPtr, heightPtr, paddingPtr);
+    *paddingPtr = Ttk_UniformPadding(2);
+    *widthPtr += 4;
+    *heightPtr += 4;
+}
+
+static void PbarElementDraw(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned state)
+{
+    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
+    (void)dummy;
+    (void)state;
+
+    b = Ttk_PadBox(b, Ttk_UniformPadding(2));
+    if (b.width > 4 && b.height > 4) {
+       DrawSmoothBorder(tkwin, d, b,
+           sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
+       XFillRectangle(Tk_Display(tkwin), d,
+           BackgroundGC(tkwin, sb->backgroundObj),
+           b.x+2, b.y+2, b.width-4, b.height-4);
+    }
+}
+
+static Ttk_ElementSpec PbarElementSpec = {
+    TK_STYLE_VERSION_2,
+    sizeof(ScrollbarElement),
+    ScrollbarElementOptions,
+    PbarElementSize,
+    PbarElementDraw
+};
+
+
+/*------------------------------------------------------------------------
+ * +++ Scrollbar arrows.
+ */
+static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
+
+static void ArrowElementSize(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
+    int size = SCROLLBAR_THICKNESS;
+    (void)dummy;
+    (void)tkwin;
+    (void)paddingPtr;
+
+    Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &size);
+    *widthPtr = *heightPtr = size;
+}
+
+static void ArrowElementDraw(
+    void *clientData, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned state)
+{
+    ArrowDirection direction = *(ArrowDirection*)clientData;
+    ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
+    GC gc = Ttk_GCForColor(tkwin,sb->arrowColorObj, d);
+    int h, cx, cy;
+
+    DrawSmoothBorder(tkwin, d, b,
+       sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
+
+    XFillRectangle(
+       Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj),
+       b.x+2, b.y+2, b.width-4, b.height-4);
+
+    b = Ttk_PadBox(b, Ttk_UniformPadding(3));
+    h = b.width < b.height ? b.width : b.height;
+    TtkArrowSize(h/2, direction, &cx, &cy);
+    b = Ttk_AnchorBox(b, cx, cy, TK_ANCHOR_CENTER);
+
+    TtkFillArrow(Tk_Display(tkwin), d, gc, b, direction);
+}
+
+static Ttk_ElementSpec ArrowElementSpec = {
+    TK_STYLE_VERSION_2,
+    sizeof(ScrollbarElement),
+    ScrollbarElementOptions,
+    ArrowElementSize,
+    ArrowElementDraw
+};
+
+
+/*------------------------------------------------------------------------
+ * +++ Notebook elements.
+ *
+ * Note: Tabs, except for the rightmost, overlap the neighbor to
+ * their right by one pixel.
+ */
+
+typedef struct {
+    Tcl_Obj *backgroundObj;
+    Tcl_Obj *borderColorObj;
+    Tcl_Obj *lightColorObj;
+    Tcl_Obj *darkColorObj;
+} NotebookElement;
+
+static Ttk_ElementOptionSpec NotebookElementOptions[] = {
+    { "-background", TK_OPTION_BORDER,
+       Tk_Offset(NotebookElement,backgroundObj), FRAME_COLOR },
+    { "-bordercolor", TK_OPTION_COLOR,
+       Tk_Offset(NotebookElement,borderColorObj), DARKEST_COLOR },
+    { "-lightcolor", TK_OPTION_COLOR,
+       Tk_Offset(NotebookElement,lightColorObj), LIGHT_COLOR },
+    { "-darkcolor", TK_OPTION_COLOR,
+       Tk_Offset(NotebookElement,darkColorObj), DARK_COLOR },
+    { NULL, TK_OPTION_BOOLEAN, 0, NULL }
+};
+
+static void TabElementSize(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+    int borderWidth = 2;
+    (void)dummy;
+    (void)elementRecord;
+    (void)tkwin;
+    (void)widthPtr;
+    (void)heightPtr;
+
+    paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth;
+    paddingPtr->bottom = 0;
+}
+
+static void TabElementDraw(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned int state)
+{
+    NotebookElement *tab = (NotebookElement *)elementRecord;
+    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj);
+    Display *display = Tk_Display(tkwin);
+    int borderWidth = 2, dh = 0;
+    int x1,y1,x2,y2;
+    GC gc;
+    const int w = WIN32_XDRAWLINE_HACK;
+    (void)dummy;
+
+    if (state & TTK_STATE_SELECTED) {
+       dh = borderWidth;
+    }
+
+    if (state & TTK_STATE_USER2) {     /* Rightmost tab */
+       --b.width;
+    }
+
+    Tk_Fill3DRectangle(tkwin, d, border,
+       b.x+2, b.y+2, b.width-1, b.height-2+dh, borderWidth, TK_RELIEF_FLAT);
+
+    x1 = b.x, x2 = b.x + b.width;
+    y1 = b.y, y2 = b.y + b.height;
+
+
+    gc=Ttk_GCForColor(tkwin,tab->borderColorObj,d);
+    XDrawLine(display,d,gc, x1,y1+1, x1,y2+w);
+    XDrawLine(display,d,gc, x2,y1+1, x2,y2+w);
+    XDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1);
+
+    gc=Ttk_GCForColor(tkwin,tab->lightColorObj,d);
+    XDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1+dh+w);
+    XDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1);
+}
+
+static Ttk_ElementSpec TabElementSpec =
+{
+    TK_STYLE_VERSION_2,
+    sizeof(NotebookElement),
+    NotebookElementOptions,
+    TabElementSize,
+    TabElementDraw
+};
+
+static void ClientElementSize(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
+{
+    int borderWidth = 2;
+    (void)dummy;
+    (void)elementRecord;
+    (void)tkwin;
+    (void)widthPtr;
+    (void)heightPtr;
+
+    *paddingPtr = Ttk_UniformPadding((short)borderWidth);
+}
+
+static void ClientElementDraw(
+    void *dummy, void *elementRecord, Tk_Window tkwin,
+    Drawable d, Ttk_Box b, unsigned int state)
+{
+    NotebookElement *ce = (NotebookElement *)elementRecord;
+    Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, ce->backgroundObj);
+    int borderWidth = 2;
+    (void)dummy;
+    (void)state;
+
+    Tk_Fill3DRectangle(tkwin, d, border,
+       b.x, b.y, b.width, b.height, borderWidth,TK_RELIEF_FLAT);
+    DrawSmoothBorder(tkwin, d, b,
+       ce->borderColorObj, ce->lightColorObj, ce->darkColorObj);
+}
+
+static Ttk_ElementSpec ClientElementSpec =
+{
+    TK_STYLE_VERSION_2,
+    sizeof(NotebookElement),
+    NotebookElementOptions,
+    ClientElementSize,
+    ClientElementDraw
+};
+
+/*------------------------------------------------------------------------
+ * +++ Modified widget layouts.
+ */
+
+TTK_BEGIN_LAYOUT_TABLE(LayoutTable)
+
+TTK_LAYOUT("TCombobox",
+    TTK_NODE("Combobox.downarrow", TTK_PACK_RIGHT|TTK_FILL_Y)
+    TTK_GROUP("Combobox.field", TTK_FILL_BOTH,
+       TTK_GROUP("Combobox.padding", TTK_FILL_BOTH,
+           TTK_NODE("Combobox.textarea", TTK_FILL_BOTH))))
+
+TTK_LAYOUT("Horizontal.Sash",
+    TTK_GROUP("Sash.hsash", TTK_FILL_BOTH,
+       TTK_NODE("Sash.hgrip", TTK_FILL_BOTH)))
+
+TTK_LAYOUT("Vertical.Sash",
+    TTK_GROUP("Sash.vsash", TTK_FILL_BOTH,
+       TTK_NODE("Sash.vgrip", TTK_FILL_BOTH)))
+
+TTK_END_LAYOUT_TABLE
+
+/*------------------------------------------------------------------------
+ * +++ Initialization.
+ */
+
+MODULE_SCOPE int
+TtkClamTheme_Init(Tcl_Interp *interp)
+{
+    Ttk_Theme theme = Ttk_CreateTheme(interp, "clam", 0);
+
+    if (!theme) {
+        return TCL_ERROR;
+    }
+
+    Ttk_RegisterElement(interp,
+       theme, "border", &BorderElementSpec, NULL);
+    Ttk_RegisterElement(interp,
+       theme, "field", &FieldElementSpec, NULL);
+    Ttk_RegisterElement(interp,
+       theme, "Combobox.field", &ComboboxFieldElementSpec, NULL);
+    Ttk_RegisterElement(interp,
+       theme, "trough", &TroughElementSpec, NULL);
+    Ttk_RegisterElement(interp,
+       theme, "thumb", &ThumbElementSpec, NULL);
+    Ttk_RegisterElement(interp,
+       theme, "uparrow", &ArrowElementSpec, &ArrowElements[0]);
+    Ttk_RegisterElement(interp,
+       theme, "downarrow", &ArrowElementSpec, &ArrowElements[1]);
+    Ttk_RegisterElement(interp,
+       theme, "leftarrow", &ArrowElementSpec, &ArrowElements[2]);
+    Ttk_RegisterElement(interp,
+       theme, "rightarrow", &ArrowElementSpec, &ArrowElements[3]);
+
+    Ttk_RegisterElement(interp,
+       theme, "Radiobutton.indicator", &RadioIndicatorElementSpec, NULL);
+    Ttk_RegisterElement(interp,
+       theme, "Checkbutton.indicator", &CheckIndicatorElementSpec, NULL);
+    Ttk_RegisterElement(interp,
+       theme, "Menubutton.indicator", &MenuIndicatorElementSpec, NULL);
+
+    Ttk_RegisterElement(interp, theme, "tab", &TabElementSpec, NULL);
+    Ttk_RegisterElement(interp, theme, "client", &ClientElementSpec, NULL);
+
+    Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
+    Ttk_RegisterElement(interp, theme, "bar", &PbarElementSpec, NULL);
+    Ttk_RegisterElement(interp, theme, "pbar", &PbarElementSpec, NULL);
+
+    Ttk_RegisterElement(interp, theme, "hgrip",
+           &GripElementSpec,  &GripClientData[0]);
+    Ttk_RegisterElement(interp, theme, "vgrip",
+           &GripElementSpec,  &GripClientData[1]);
+
+    Ttk_RegisterLayouts(theme, LayoutTable);
+
+    Tcl_PkgProvide(interp, "ttk::theme::clam", TTK_VERSION);
+
+    return TCL_OK;
+}