1 /*
2  * Copyright (C) 2004 Joe English
3  *
4  * "clam" theme; inspired by the XFCE family of Gnome themes.
5  */
6 
7 #include "tkInt.h"
8 #include "ttkTheme.h"
9 
10 /*
11  * Under windows, the Tk-provided XDrawLine and XDrawArc have an
12  * off-by-one error in the end point. This is especially apparent with this
13  * theme. Defining this macro as true handles this case.
14  */
15 #if defined(_WIN32) && !defined(WIN32_XDRAWLINE_HACK)
16 #	define WIN32_XDRAWLINE_HACK 1
17 #else
18 #	define WIN32_XDRAWLINE_HACK 0
19 #endif
20 
21 #define STR(x) StR(x)
22 #define StR(x) #x
23 
24 #define SCROLLBAR_THICKNESS 14
25 
26 #define FRAME_COLOR	"#dcdad5"
27 #define LIGHT_COLOR  	"#ffffff"
28 #define DARK_COLOR  	"#cfcdc8"
29 #define DARKER_COLOR 	"#bab5ab"
30 #define DARKEST_COLOR	"#9e9a91"
31 
32 /*------------------------------------------------------------------------
33  * +++ Utilities.
34  */
35 
Ttk_GCForColor(Tk_Window tkwin,Tcl_Obj * colorObj,Drawable d)36 static GC Ttk_GCForColor(Tk_Window tkwin, Tcl_Obj* colorObj, Drawable d)
37 {
38     GC gc = Tk_GCForColor(Tk_GetColorFromObj(tkwin, colorObj), d);
39 
40 #ifdef MAC_OSX_TK
41     /*
42      * Workaround for Tk bug under Aqua where the default line width is 0.
43      */
44     Display *display = Tk_Display(tkwin);
45     unsigned long mask = 0ul;
46     XGCValues gcValues;
47 
48     gcValues.line_width = 1;
49     mask = GCLineWidth;
50 
51     XChangeGC(display, gc, mask, &gcValues);
52 #endif
53 
54     return gc;
55 }
56 
DrawSmoothBorder(Tk_Window tkwin,Drawable d,Ttk_Box b,Tcl_Obj * outerColorObj,Tcl_Obj * upperColorObj,Tcl_Obj * lowerColorObj)57 static void DrawSmoothBorder(
58     Tk_Window tkwin, Drawable d, Ttk_Box b,
59     Tcl_Obj *outerColorObj, Tcl_Obj *upperColorObj, Tcl_Obj *lowerColorObj)
60 {
61     Display *display = Tk_Display(tkwin);
62     int x1 = b.x, x2 = b.x + b.width - 1;
63     int y1 = b.y, y2 = b.y + b.height - 1;
64     const int w = WIN32_XDRAWLINE_HACK;
65     GC gc;
66 
67     if (   outerColorObj
68 	&& (gc=Ttk_GCForColor(tkwin,outerColorObj,d)))
69     {
70 	XDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1); /* N */
71 	XDrawLine(display,d,gc, x1+1,y2, x2-1+w,y2); /* S */
72 	XDrawLine(display,d,gc, x1,y1+1, x1,y2-1+w); /* E */
73 	XDrawLine(display,d,gc, x2,y1+1, x2,y2-1+w); /* W */
74     }
75 
76     if (   upperColorObj
77 	&& (gc=Ttk_GCForColor(tkwin,upperColorObj,d)))
78     {
79 	XDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1); /* N */
80 	XDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1);   /* E */
81     }
82 
83     if (   lowerColorObj
84 	&& (gc=Ttk_GCForColor(tkwin,lowerColorObj,d)))
85     {
86 	XDrawLine(display,d,gc, x2-1,y2-1, x1+1-w,y2-1); /* S */
87 	XDrawLine(display,d,gc, x2-1,y2-1, x2-1,y1+1-w); /* W */
88     }
89 }
90 
BackgroundGC(Tk_Window tkwin,Tcl_Obj * backgroundObj)91 static GC BackgroundGC(Tk_Window tkwin, Tcl_Obj *backgroundObj)
92 {
93     Tk_3DBorder bd = Tk_Get3DBorderFromObj(tkwin, backgroundObj);
94     return Tk_3DBorderGC(tkwin, bd, TK_3D_FLAT_GC);
95 }
96 
97 /*------------------------------------------------------------------------
98  * +++ Border element.
99  */
100 
101 typedef struct {
102     Tcl_Obj 	*borderColorObj;
103     Tcl_Obj 	*lightColorObj;
104     Tcl_Obj 	*darkColorObj;
105     Tcl_Obj 	*reliefObj;
106     Tcl_Obj 	*borderWidthObj;	/* See <<NOTE-BORDERWIDTH>> */
107 } BorderElement;
108 
109 static Ttk_ElementOptionSpec BorderElementOptions[] = {
110     { "-bordercolor", TK_OPTION_COLOR,
111 	Tk_Offset(BorderElement,borderColorObj), DARKEST_COLOR },
112     { "-lightcolor", TK_OPTION_COLOR,
113 	Tk_Offset(BorderElement,lightColorObj), LIGHT_COLOR },
114     { "-darkcolor", TK_OPTION_COLOR,
115 	Tk_Offset(BorderElement,darkColorObj), DARK_COLOR },
116     { "-relief", TK_OPTION_RELIEF,
117 	Tk_Offset(BorderElement,reliefObj), "flat" },
118     { "-borderwidth", TK_OPTION_PIXELS,
119 	Tk_Offset(BorderElement,borderWidthObj), "2" },
120     { NULL, TK_OPTION_BOOLEAN, 0, NULL }
121 };
122 
123 /*
124  * <<NOTE-BORDERWIDTH>>: -borderwidth is only partially supported:
125  * in this theme, borders are always exactly 2 pixels thick.
126  * With -borderwidth 0, border is not drawn at all;
127  * otherwise a 2-pixel border is used.  For -borderwidth > 2,
128  * the excess is used as padding.
129  */
130 
BorderElementSize(void * dummy,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)131 static void BorderElementSize(
132     void *dummy, void *elementRecord, Tk_Window tkwin,
133     int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
134 {
135     BorderElement *border = (BorderElement*)elementRecord;
136     int borderWidth = 2;
137     (void)dummy;
138     (void)widthPtr;
139     (void)heightPtr;
140 
141     Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth);
142     if (borderWidth == 1) ++borderWidth;
143     *paddingPtr = Ttk_UniformPadding((short)borderWidth);
144 }
145 
BorderElementDraw(void * dummy,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned state)146 static void BorderElementDraw(
147     void *dummy, void *elementRecord, Tk_Window tkwin,
148     Drawable d, Ttk_Box b, unsigned state)
149 {
150     BorderElement *border = (BorderElement *)elementRecord;
151     int relief = TK_RELIEF_FLAT;
152     int borderWidth = 2;
153     Tcl_Obj *outer = 0, *upper = 0, *lower = 0;
154     (void)dummy;
155     (void)state;
156 
157     Tk_GetReliefFromObj(NULL, border->reliefObj, &relief);
158     Tk_GetPixelsFromObj(NULL, tkwin, border->borderWidthObj, &borderWidth);
159 
160     if (borderWidth == 0) return;
161 
162     switch (relief) {
163 	case TK_RELIEF_GROOVE :
164 	case TK_RELIEF_RIDGE :
165 	case TK_RELIEF_RAISED :
166 	    outer = border->borderColorObj;
167 	    upper = border->lightColorObj;
168 	    lower = border->darkColorObj;
169 	    break;
170 	case TK_RELIEF_SUNKEN :
171 	    outer = border->borderColorObj;
172 	    upper = border->darkColorObj;
173 	    lower = border->lightColorObj;
174 	    break;
175 	case TK_RELIEF_FLAT :
176 	    outer = upper = lower = 0;
177 	    break;
178 	case TK_RELIEF_SOLID :
179 	    outer = upper = lower = border->borderColorObj;
180 	    break;
181     }
182 
183     DrawSmoothBorder(tkwin, d, b, outer, upper, lower);
184 }
185 
186 static Ttk_ElementSpec BorderElementSpec = {
187     TK_STYLE_VERSION_2,
188     sizeof(BorderElement),
189     BorderElementOptions,
190     BorderElementSize,
191     BorderElementDraw
192 };
193 
194 /*------------------------------------------------------------------------
195  * +++ Field element.
196  */
197 
198 typedef struct {
199     Tcl_Obj 	*borderColorObj;
200     Tcl_Obj 	*lightColorObj;
201     Tcl_Obj 	*darkColorObj;
202     Tcl_Obj 	*backgroundObj;
203 } FieldElement;
204 
205 static Ttk_ElementOptionSpec FieldElementOptions[] = {
206     { "-bordercolor", TK_OPTION_COLOR,
207 	Tk_Offset(FieldElement,borderColorObj), DARKEST_COLOR },
208     { "-lightcolor", TK_OPTION_COLOR,
209 	Tk_Offset(FieldElement,lightColorObj), LIGHT_COLOR },
210     { "-darkcolor", TK_OPTION_COLOR,
211 	Tk_Offset(FieldElement,darkColorObj), DARK_COLOR },
212     { "-fieldbackground", TK_OPTION_BORDER,
213 	Tk_Offset(FieldElement,backgroundObj), "white" },
214     { NULL, TK_OPTION_BOOLEAN, 0, NULL }
215 };
216 
FieldElementSize(void * dummy,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)217 static void FieldElementSize(
218     void *dummy, void *elementRecord, Tk_Window tkwin,
219     int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
220 {
221     (void)dummy;
222     (void)elementRecord;
223     (void)tkwin;
224     (void)widthPtr;
225     (void)heightPtr;
226 
227     *paddingPtr = Ttk_UniformPadding(2);
228 }
229 
FieldElementDraw(void * dummy,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned state)230 static void FieldElementDraw(
231     void *dummy, void *elementRecord, Tk_Window tkwin,
232     Drawable d, Ttk_Box b, unsigned state)
233 {
234     FieldElement *field = (FieldElement *)elementRecord;
235     Tk_3DBorder bg = Tk_Get3DBorderFromObj(tkwin, field->backgroundObj);
236     Ttk_Box f = Ttk_PadBox(b, Ttk_UniformPadding(2));
237     Tcl_Obj *outer = field->borderColorObj,
238 	    *inner = field->lightColorObj;
239     (void)dummy;
240     (void)state;
241 
242     DrawSmoothBorder(tkwin, d, b, outer, inner, inner);
243     Tk_Fill3DRectangle(
244 	tkwin, d, bg, f.x, f.y, f.width, f.height, 0, TK_RELIEF_SUNKEN);
245 }
246 
247 static Ttk_ElementSpec FieldElementSpec = {
248     TK_STYLE_VERSION_2,
249     sizeof(FieldElement),
250     FieldElementOptions,
251     FieldElementSize,
252     FieldElementDraw
253 };
254 
255 /*
256  * Modified field element for comboboxes:
257  * 	Right edge is expanded to overlap the dropdown button.
258  */
ComboboxFieldElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned state)259 static void ComboboxFieldElementDraw(
260     void *clientData, void *elementRecord, Tk_Window tkwin,
261     Drawable d, Ttk_Box b, unsigned state)
262 {
263     FieldElement *field = (FieldElement *)elementRecord;
264     GC gc = Ttk_GCForColor(tkwin,field->borderColorObj,d);
265 
266     ++b.width;
267     FieldElementDraw(clientData, elementRecord, tkwin, d, b, state);
268 
269     XDrawLine(Tk_Display(tkwin), d, gc,
270 	    b.x + b.width - 1, b.y,
271 	    b.x + b.width - 1, b.y + b.height - 1 + WIN32_XDRAWLINE_HACK);
272 }
273 
274 static Ttk_ElementSpec ComboboxFieldElementSpec = {
275     TK_STYLE_VERSION_2,
276     sizeof(FieldElement),
277     FieldElementOptions,
278     FieldElementSize,
279     ComboboxFieldElementDraw
280 };
281 
282 /*------------------------------------------------------------------------
283  * +++ Indicator elements for check and radio buttons.
284  */
285 
286 typedef struct {
287     Tcl_Obj *sizeObj;
288     Tcl_Obj *marginObj;
289     Tcl_Obj *backgroundObj;
290     Tcl_Obj *foregroundObj;
291     Tcl_Obj *upperColorObj;
292     Tcl_Obj *lowerColorObj;
293 } IndicatorElement;
294 
295 static Ttk_ElementOptionSpec IndicatorElementOptions[] = {
296     { "-indicatorsize", TK_OPTION_PIXELS,
297 	Tk_Offset(IndicatorElement,sizeObj), "10" },
298     { "-indicatormargin", TK_OPTION_STRING,
299 	Tk_Offset(IndicatorElement,marginObj), "1" },
300     { "-indicatorbackground", TK_OPTION_COLOR,
301 	Tk_Offset(IndicatorElement,backgroundObj), "white" },
302     { "-indicatorforeground", TK_OPTION_COLOR,
303 	Tk_Offset(IndicatorElement,foregroundObj), "black" },
304     { "-upperbordercolor", TK_OPTION_COLOR,
305 	Tk_Offset(IndicatorElement,upperColorObj), DARKEST_COLOR },
306     { "-lowerbordercolor", TK_OPTION_COLOR,
307 	Tk_Offset(IndicatorElement,lowerColorObj), DARK_COLOR },
308     { NULL, TK_OPTION_BOOLEAN, 0, NULL }
309 };
310 
IndicatorElementSize(void * dummy,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)311 static void IndicatorElementSize(
312     void *dummy, void *elementRecord, Tk_Window tkwin,
313     int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
314 {
315     IndicatorElement *indicator = (IndicatorElement *)elementRecord;
316     Ttk_Padding margins;
317     int size = 10;
318     (void)dummy;
319     (void)paddingPtr;
320 
321     Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &margins);
322     Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
323     *widthPtr = size + Ttk_PaddingWidth(margins);
324     *heightPtr = size + Ttk_PaddingHeight(margins);
325 }
326 
RadioIndicatorElementDraw(void * dummy,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned state)327 static void RadioIndicatorElementDraw(
328     void *dummy, void *elementRecord, Tk_Window tkwin,
329     Drawable d, Ttk_Box b, unsigned state)
330 {
331     IndicatorElement *indicator = (IndicatorElement *)elementRecord;
332     GC gcb=Ttk_GCForColor(tkwin,indicator->backgroundObj,d);
333     GC gcf=Ttk_GCForColor(tkwin,indicator->foregroundObj,d);
334     GC gcu=Ttk_GCForColor(tkwin,indicator->upperColorObj,d);
335     GC gcl=Ttk_GCForColor(tkwin,indicator->lowerColorObj,d);
336     Ttk_Padding padding;
337     (void)dummy;
338 
339     Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
340     b = Ttk_PadBox(b, padding);
341 
342     XFillArc(Tk_Display(tkwin),d,gcb, b.x,b.y,b.width,b.height, 0,360*64);
343     XDrawArc(Tk_Display(tkwin),d,gcl, b.x,b.y,b.width,b.height, 225*64,180*64);
344     XDrawArc(Tk_Display(tkwin),d,gcu, b.x,b.y,b.width,b.height, 45*64,180*64);
345 
346     if (state & TTK_STATE_SELECTED) {
347 	b = Ttk_PadBox(b,Ttk_UniformPadding(3));
348 	XFillArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 0,360*64);
349 	XDrawArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 0,360*64);
350 #if WIN32_XDRAWLINE_HACK
351 	XDrawArc(Tk_Display(tkwin),d,gcf, b.x,b.y,b.width,b.height, 300*64,360*64);
352 #endif
353     }
354 }
355 
CheckIndicatorElementDraw(void * dummy,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned state)356 static void CheckIndicatorElementDraw(
357     void *dummy, void *elementRecord, Tk_Window tkwin,
358     Drawable d, Ttk_Box b, unsigned state)
359 {
360     Display *display = Tk_Display(tkwin);
361     IndicatorElement *indicator = (IndicatorElement *)elementRecord;
362 
363     GC gcb=Ttk_GCForColor(tkwin,indicator->backgroundObj,d);
364     GC gcf=Ttk_GCForColor(tkwin,indicator->foregroundObj,d);
365     GC gcu=Ttk_GCForColor(tkwin,indicator->upperColorObj,d);
366     GC gcl=Ttk_GCForColor(tkwin,indicator->lowerColorObj,d);
367     Ttk_Padding padding;
368     const int w = WIN32_XDRAWLINE_HACK;
369     (void)dummy;
370 
371     Ttk_GetPaddingFromObj(NULL, tkwin, indicator->marginObj, &padding);
372     b = Ttk_PadBox(b, padding);
373 
374     XFillRectangle(display,d,gcb, b.x,b.y,b.width,b.height);
375     XDrawLine(display,d,gcl,b.x,b.y+b.height,b.x+b.width+w,b.y+b.height);/*S*/
376     XDrawLine(display,d,gcl,b.x+b.width,b.y,b.x+b.width,b.y+b.height+w); /*E*/
377     XDrawLine(display,d,gcu,b.x,b.y, b.x,b.y+b.height+w); /*W*/
378     XDrawLine(display,d,gcu,b.x,b.y, b.x+b.width+w,b.y);  /*N*/
379 
380     if (state & TTK_STATE_SELECTED) {
381 	int p,q,r,s;
382 
383 	b = Ttk_PadBox(b,Ttk_UniformPadding(2));
384 	p = b.x, q = b.y, r = b.x+b.width, s = b.y+b.height;
385 
386 	r+=w, s+=w;
387 	XDrawLine(display, d, gcf, p,   q,   r,   s);
388 	XDrawLine(display, d, gcf, p+1, q,   r,   s-1);
389 	XDrawLine(display, d, gcf, p,   q+1, r-1, s);
390 
391 	s-=w, q-=w;
392 	XDrawLine(display, d, gcf, p,   s,   r,   q);
393 	XDrawLine(display, d, gcf, p+1, s,   r,   q+1);
394 	XDrawLine(display, d, gcf, p,   s-1, r-1, q);
395     }
396 }
397 
398 static Ttk_ElementSpec RadioIndicatorElementSpec = {
399     TK_STYLE_VERSION_2,
400     sizeof(IndicatorElement),
401     IndicatorElementOptions,
402     IndicatorElementSize,
403     RadioIndicatorElementDraw
404 };
405 
406 static Ttk_ElementSpec CheckIndicatorElementSpec = {
407     TK_STYLE_VERSION_2,
408     sizeof(IndicatorElement),
409     IndicatorElementOptions,
410     IndicatorElementSize,
411     CheckIndicatorElementDraw
412 };
413 
414 #define MENUBUTTON_ARROW_SIZE 5
415 
416 typedef struct {
417     Tcl_Obj *sizeObj;
418     Tcl_Obj *colorObj;
419     Tcl_Obj *paddingObj;
420 } MenuIndicatorElement;
421 
422 static Ttk_ElementOptionSpec MenuIndicatorElementOptions[] =
423 {
424     { "-arrowsize", TK_OPTION_PIXELS,
425 	Tk_Offset(MenuIndicatorElement,sizeObj),
426 	STR(MENUBUTTON_ARROW_SIZE)},
427     { "-arrowcolor",TK_OPTION_COLOR,
428 	Tk_Offset(MenuIndicatorElement,colorObj),
429 	"black" },
430     { "-arrowpadding",TK_OPTION_STRING,
431 	Tk_Offset(MenuIndicatorElement,paddingObj),
432 	"3" },
433     { NULL, TK_OPTION_BOOLEAN, 0, NULL }
434 };
435 
MenuIndicatorElementSize(void * dummy,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)436 static void MenuIndicatorElementSize(
437     void *dummy, void *elementRecord, Tk_Window tkwin,
438     int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
439 {
440     MenuIndicatorElement *indicator = (MenuIndicatorElement *)elementRecord;
441     Ttk_Padding margins;
442     int size = MENUBUTTON_ARROW_SIZE;
443     (void)dummy;
444     (void)paddingPtr;
445 
446     Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
447     Ttk_GetPaddingFromObj(NULL, tkwin, indicator->paddingObj, &margins);
448     TtkArrowSize(size, ARROW_DOWN, widthPtr, heightPtr);
449     *widthPtr += Ttk_PaddingWidth(margins);
450     *heightPtr += Ttk_PaddingHeight(margins);
451 }
452 
MenuIndicatorElementDraw(void * dummy,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)453 static void MenuIndicatorElementDraw(
454     void *dummy, void *elementRecord, Tk_Window tkwin,
455     Drawable d, Ttk_Box b, unsigned int state)
456 {
457     MenuIndicatorElement *indicator = (MenuIndicatorElement *)elementRecord;
458     XColor *arrowColor = Tk_GetColorFromObj(tkwin, indicator->colorObj);
459     GC gc = Tk_GCForColor(arrowColor, d);
460     int size = MENUBUTTON_ARROW_SIZE;
461     int width, height;
462     (void)dummy;
463     (void)state;
464 
465     Tk_GetPixelsFromObj(NULL, tkwin, indicator->sizeObj, &size);
466 
467     TtkArrowSize(size, ARROW_DOWN, &width, &height);
468     b = Ttk_StickBox(b, width, height, 0);
469     TtkFillArrow(Tk_Display(tkwin), d, gc, b, ARROW_DOWN);
470 }
471 
472 static Ttk_ElementSpec MenuIndicatorElementSpec =
473 {
474     TK_STYLE_VERSION_2,
475     sizeof(MenuIndicatorElement),
476     MenuIndicatorElementOptions,
477     MenuIndicatorElementSize,
478     MenuIndicatorElementDraw
479 };
480 
481 /*------------------------------------------------------------------------
482  * +++ Grips.
483  *
484  * TODO: factor this with ThumbElementDraw
485  */
486 
487 static Ttk_Orient GripClientData[] = {
488     TTK_ORIENT_HORIZONTAL, TTK_ORIENT_VERTICAL
489 };
490 
491 typedef struct {
492     Tcl_Obj 	*lightColorObj;
493     Tcl_Obj 	*borderColorObj;
494     Tcl_Obj 	*gripCountObj;
495 } GripElement;
496 
497 static Ttk_ElementOptionSpec GripElementOptions[] = {
498     { "-lightcolor", TK_OPTION_COLOR,
499 	Tk_Offset(GripElement,lightColorObj), LIGHT_COLOR },
500     { "-bordercolor", TK_OPTION_COLOR,
501 	Tk_Offset(GripElement,borderColorObj), DARKEST_COLOR },
502     { "-gripcount", TK_OPTION_INT,
503 	Tk_Offset(GripElement,gripCountObj), "5" },
504     { NULL, TK_OPTION_BOOLEAN, 0, NULL }
505 };
506 
GripElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)507 static void GripElementSize(
508     void *clientData, void *elementRecord, Tk_Window tkwin,
509     int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
510 {
511     int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
512     GripElement *grip = (GripElement *)elementRecord;
513     int gripCount = 0;
514     (void)tkwin;
515     (void)paddingPtr;
516 
517     Tcl_GetIntFromObj(NULL, grip->gripCountObj, &gripCount);
518     if (horizontal) {
519 	*widthPtr = 2*gripCount;
520     } else {
521 	*heightPtr = 2*gripCount;
522     }
523 }
524 
GripElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned state)525 static void GripElementDraw(
526     void *clientData, void *elementRecord, Tk_Window tkwin,
527     Drawable d, Ttk_Box b, unsigned state)
528 {
529     const int w = WIN32_XDRAWLINE_HACK;
530     int horizontal = *((Ttk_Orient*)clientData) == TTK_ORIENT_HORIZONTAL;
531     GripElement *grip = (GripElement *)elementRecord;
532     GC lightGC = Ttk_GCForColor(tkwin,grip->lightColorObj,d);
533     GC darkGC = Ttk_GCForColor(tkwin,grip->borderColorObj,d);
534     int gripPad = 1, gripCount = 0;
535     int i;
536 
537     Tcl_GetIntFromObj(NULL, grip->gripCountObj, &gripCount);
538 
539     if (horizontal) {
540 	int x = b.x + b.width / 2 - gripCount;
541 	int y1 = b.y + gripPad, y2 = b.y + b.height - gripPad - 1 + w;
542 	for (i=0; i<gripCount; ++i) {
543 	    XDrawLine(Tk_Display(tkwin), d, darkGC,  x,y1, x,y2); ++x;
544 	    XDrawLine(Tk_Display(tkwin), d, lightGC, x,y1, x,y2); ++x;
545 	}
546     } else {
547 	int y = b.y + b.height / 2 - gripCount;
548 	int x1 = b.x + gripPad, x2 = b.x + b.width - gripPad - 1 + w;
549 	for (i=0; i<gripCount; ++i) {
550 	    XDrawLine(Tk_Display(tkwin), d, darkGC,  x1,y, x2,y); ++y;
551 	    XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y, x2,y); ++y;
552 	}
553     }
554 }
555 
556 static Ttk_ElementSpec GripElementSpec = {
557     TK_STYLE_VERSION_2,
558     sizeof(GripElement),
559     GripElementOptions,
560     GripElementSize,
561     GripElementDraw
562 };
563 
564 /*------------------------------------------------------------------------
565  * +++ Scrollbar elements: trough, arrows, thumb.
566  *
567  * Notice that the trough element has 0 internal padding;
568  * that way the thumb and arrow borders overlap the trough.
569  */
570 
571 typedef struct { /* Common element record for scrollbar elements */
572     Tcl_Obj 	*orientObj;
573     Tcl_Obj 	*backgroundObj;
574     Tcl_Obj 	*borderColorObj;
575     Tcl_Obj 	*troughColorObj;
576     Tcl_Obj 	*lightColorObj;
577     Tcl_Obj 	*darkColorObj;
578     Tcl_Obj 	*arrowColorObj;
579     Tcl_Obj 	*arrowSizeObj;
580     Tcl_Obj 	*gripCountObj;
581     Tcl_Obj 	*sliderlengthObj;
582 } ScrollbarElement;
583 
584 static Ttk_ElementOptionSpec ScrollbarElementOptions[] = {
585     { "-orient", TK_OPTION_ANY,
586 	Tk_Offset(ScrollbarElement, orientObj), "horizontal" },
587     { "-background", TK_OPTION_BORDER,
588 	Tk_Offset(ScrollbarElement,backgroundObj), FRAME_COLOR },
589     { "-bordercolor", TK_OPTION_COLOR,
590 	Tk_Offset(ScrollbarElement,borderColorObj), DARKEST_COLOR },
591     { "-troughcolor", TK_OPTION_COLOR,
592 	Tk_Offset(ScrollbarElement,troughColorObj), DARKER_COLOR },
593     { "-lightcolor", TK_OPTION_COLOR,
594 	Tk_Offset(ScrollbarElement,lightColorObj), LIGHT_COLOR },
595     { "-darkcolor", TK_OPTION_COLOR,
596 	Tk_Offset(ScrollbarElement,darkColorObj), DARK_COLOR },
597     { "-arrowcolor", TK_OPTION_COLOR,
598 	Tk_Offset(ScrollbarElement,arrowColorObj), "#000000" },
599     { "-arrowsize", TK_OPTION_PIXELS,
600 	Tk_Offset(ScrollbarElement,arrowSizeObj), STR(SCROLLBAR_THICKNESS) },
601     { "-gripcount", TK_OPTION_INT,
602 	Tk_Offset(ScrollbarElement,gripCountObj), "5" },
603     { "-sliderlength", TK_OPTION_INT,
604 	Tk_Offset(ScrollbarElement,sliderlengthObj), "30" },
605     { NULL, TK_OPTION_BOOLEAN, 0, NULL }
606 };
607 
TroughElementDraw(void * dummy,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned state)608 static void TroughElementDraw(
609     void *dummy, void *elementRecord, Tk_Window tkwin,
610     Drawable d, Ttk_Box b, unsigned state)
611 {
612     ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
613     GC gcb = Ttk_GCForColor(tkwin,sb->borderColorObj,d);
614     GC gct = Ttk_GCForColor(tkwin,sb->troughColorObj,d);
615     (void)dummy;
616     (void)state;
617 
618     XFillRectangle(Tk_Display(tkwin), d, gct, b.x, b.y, b.width-1, b.height-1);
619     XDrawRectangle(Tk_Display(tkwin), d, gcb, b.x, b.y, b.width-1, b.height-1);
620 }
621 
622 static Ttk_ElementSpec TroughElementSpec = {
623     TK_STYLE_VERSION_2,
624     sizeof(ScrollbarElement),
625     ScrollbarElementOptions,
626     TtkNullElementSize,
627     TroughElementDraw
628 };
629 
ThumbElementSize(void * dummy,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)630 static void ThumbElementSize(
631     void *dummy, void *elementRecord, Tk_Window tkwin,
632     int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
633 {
634     ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
635     int size = SCROLLBAR_THICKNESS;
636     (void)dummy;
637     (void)tkwin;
638     (void)paddingPtr;
639 
640     Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &size);
641     *widthPtr = *heightPtr = size;
642 }
643 
ThumbElementDraw(void * dummy,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned state)644 static void ThumbElementDraw(
645     void *dummy, void *elementRecord, Tk_Window tkwin,
646     Drawable d, Ttk_Box b, unsigned state)
647 {
648     ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
649     int gripCount = 0;
650     int orient = TTK_ORIENT_HORIZONTAL;
651     GC lightGC, darkGC;
652     int x1, y1, x2, y2, dx, dy, i;
653     const int w = WIN32_XDRAWLINE_HACK;
654     (void)dummy;
655     (void)state;
656 
657     DrawSmoothBorder(tkwin, d, b,
658 	sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
659     XFillRectangle(
660 	Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj),
661 	b.x+2, b.y+2, b.width-4, b.height-4);
662 
663     /*
664      * Draw grip:
665      */
666     Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient);
667     Tcl_GetIntFromObj(NULL, sb->gripCountObj, &gripCount);
668     lightGC = Ttk_GCForColor(tkwin,sb->lightColorObj,d);
669     darkGC = Ttk_GCForColor(tkwin,sb->borderColorObj,d);
670 
671     if (orient == TTK_ORIENT_HORIZONTAL) {
672 	dx = 1; dy = 0;
673 	x1 = x2 = b.x + b.width / 2 - gripCount;
674 	y1 = b.y + 2;
675 	y2 = b.y + b.height - 3 + w;
676     } else {
677 	dx = 0; dy = 1;
678 	y1 = y2 = b.y + b.height / 2 - gripCount;
679 	x1 = b.x + 2;
680 	x2 = b.x + b.width - 3 + w;
681     }
682 
683     for (i=0; i<gripCount; ++i) {
684 	XDrawLine(Tk_Display(tkwin), d, darkGC, x1,y1, x2,y2);
685 	x1 += dx; x2 += dx; y1 += dy; y2 += dy;
686 	XDrawLine(Tk_Display(tkwin), d, lightGC, x1,y1, x2,y2);
687 	x1 += dx; x2 += dx; y1 += dy; y2 += dy;
688     }
689 }
690 
691 static Ttk_ElementSpec ThumbElementSpec = {
692     TK_STYLE_VERSION_2,
693     sizeof(ScrollbarElement),
694     ScrollbarElementOptions,
695     ThumbElementSize,
696     ThumbElementDraw
697 };
698 
699 /*------------------------------------------------------------------------
700  * +++ Slider element.
701  */
SliderElementSize(void * dummy,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)702 static void SliderElementSize(
703     void *dummy, void *elementRecord, Tk_Window tkwin,
704     int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
705 {
706     ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
707     int length, thickness;
708     int orient;
709     (void)dummy;
710     (void)paddingPtr;
711 
712     length = thickness = SCROLLBAR_THICKNESS;
713     Ttk_GetOrientFromObj(NULL, sb->orientObj, &orient);
714     Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &thickness);
715     Tk_GetPixelsFromObj(NULL, tkwin, sb->sliderlengthObj, &length);
716     if (orient == TTK_ORIENT_VERTICAL) {
717 	*heightPtr = length;
718 	*widthPtr = thickness;
719     } else {
720 	*heightPtr = thickness;
721 	*widthPtr = length;
722     }
723 
724 }
725 
726 static Ttk_ElementSpec SliderElementSpec = {
727     TK_STYLE_VERSION_2,
728     sizeof(ScrollbarElement),
729     ScrollbarElementOptions,
730     SliderElementSize,
731     ThumbElementDraw
732 };
733 
734 /*------------------------------------------------------------------------
735  * +++ Progress bar element
736  */
PbarElementSize(void * clientData,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)737 static void PbarElementSize(
738     void *clientData, void *elementRecord, Tk_Window tkwin,
739     int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
740 {
741     SliderElementSize(clientData, elementRecord, tkwin,
742 	    widthPtr, heightPtr, paddingPtr);
743     *paddingPtr = Ttk_UniformPadding(2);
744     *widthPtr += 4;
745     *heightPtr += 4;
746 }
747 
PbarElementDraw(void * dummy,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned state)748 static void PbarElementDraw(
749     void *dummy, void *elementRecord, Tk_Window tkwin,
750     Drawable d, Ttk_Box b, unsigned state)
751 {
752     ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
753     (void)dummy;
754     (void)state;
755 
756     b = Ttk_PadBox(b, Ttk_UniformPadding(2));
757     if (b.width > 4 && b.height > 4) {
758 	DrawSmoothBorder(tkwin, d, b,
759 	    sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
760 	XFillRectangle(Tk_Display(tkwin), d,
761 	    BackgroundGC(tkwin, sb->backgroundObj),
762 	    b.x+2, b.y+2, b.width-4, b.height-4);
763     }
764 }
765 
766 static Ttk_ElementSpec PbarElementSpec = {
767     TK_STYLE_VERSION_2,
768     sizeof(ScrollbarElement),
769     ScrollbarElementOptions,
770     PbarElementSize,
771     PbarElementDraw
772 };
773 
774 
775 /*------------------------------------------------------------------------
776  * +++ Scrollbar arrows.
777  */
778 static int ArrowElements[] = { ARROW_UP, ARROW_DOWN, ARROW_LEFT, ARROW_RIGHT };
779 
ArrowElementSize(void * dummy,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)780 static void ArrowElementSize(
781     void *dummy, void *elementRecord, Tk_Window tkwin,
782     int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
783 {
784     ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
785     int size = SCROLLBAR_THICKNESS;
786     (void)dummy;
787     (void)tkwin;
788     (void)paddingPtr;
789 
790     Tcl_GetIntFromObj(NULL, sb->arrowSizeObj, &size);
791     *widthPtr = *heightPtr = size;
792 }
793 
ArrowElementDraw(void * clientData,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned state)794 static void ArrowElementDraw(
795     void *clientData, void *elementRecord, Tk_Window tkwin,
796     Drawable d, Ttk_Box b, unsigned state)
797 {
798     ArrowDirection direction = *(ArrowDirection*)clientData;
799     ScrollbarElement *sb = (ScrollbarElement *)elementRecord;
800     GC gc = Ttk_GCForColor(tkwin,sb->arrowColorObj, d);
801     int h, cx, cy;
802 
803     DrawSmoothBorder(tkwin, d, b,
804 	sb->borderColorObj, sb->lightColorObj, sb->darkColorObj);
805 
806     XFillRectangle(
807 	Tk_Display(tkwin), d, BackgroundGC(tkwin, sb->backgroundObj),
808 	b.x+2, b.y+2, b.width-4, b.height-4);
809 
810     b = Ttk_PadBox(b, Ttk_UniformPadding(3));
811     h = b.width < b.height ? b.width : b.height;
812     TtkArrowSize(h/2, direction, &cx, &cy);
813     b = Ttk_AnchorBox(b, cx, cy, TK_ANCHOR_CENTER);
814 
815     TtkFillArrow(Tk_Display(tkwin), d, gc, b, direction);
816 }
817 
818 static Ttk_ElementSpec ArrowElementSpec = {
819     TK_STYLE_VERSION_2,
820     sizeof(ScrollbarElement),
821     ScrollbarElementOptions,
822     ArrowElementSize,
823     ArrowElementDraw
824 };
825 
826 
827 /*------------------------------------------------------------------------
828  * +++ Notebook elements.
829  *
830  * Note: Tabs, except for the rightmost, overlap the neighbor to
831  * their right by one pixel.
832  */
833 
834 typedef struct {
835     Tcl_Obj *backgroundObj;
836     Tcl_Obj *borderColorObj;
837     Tcl_Obj *lightColorObj;
838     Tcl_Obj *darkColorObj;
839 } NotebookElement;
840 
841 static Ttk_ElementOptionSpec NotebookElementOptions[] = {
842     { "-background", TK_OPTION_BORDER,
843 	Tk_Offset(NotebookElement,backgroundObj), FRAME_COLOR },
844     { "-bordercolor", TK_OPTION_COLOR,
845 	Tk_Offset(NotebookElement,borderColorObj), DARKEST_COLOR },
846     { "-lightcolor", TK_OPTION_COLOR,
847 	Tk_Offset(NotebookElement,lightColorObj), LIGHT_COLOR },
848     { "-darkcolor", TK_OPTION_COLOR,
849 	Tk_Offset(NotebookElement,darkColorObj), DARK_COLOR },
850     { NULL, TK_OPTION_BOOLEAN, 0, NULL }
851 };
852 
TabElementSize(void * dummy,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)853 static void TabElementSize(
854     void *dummy, void *elementRecord, Tk_Window tkwin,
855     int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
856 {
857     int borderWidth = 2;
858     (void)dummy;
859     (void)elementRecord;
860     (void)tkwin;
861     (void)widthPtr;
862     (void)heightPtr;
863 
864     paddingPtr->top = paddingPtr->left = paddingPtr->right = borderWidth;
865     paddingPtr->bottom = 0;
866 }
867 
TabElementDraw(void * dummy,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)868 static void TabElementDraw(
869     void *dummy, void *elementRecord, Tk_Window tkwin,
870     Drawable d, Ttk_Box b, unsigned int state)
871 {
872     NotebookElement *tab = (NotebookElement *)elementRecord;
873     Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, tab->backgroundObj);
874     Display *display = Tk_Display(tkwin);
875     int borderWidth = 2, dh = 0;
876     int x1,y1,x2,y2;
877     GC gc;
878     const int w = WIN32_XDRAWLINE_HACK;
879     (void)dummy;
880 
881     if (state & TTK_STATE_SELECTED) {
882 	dh = borderWidth;
883     }
884 
885     if (state & TTK_STATE_USER2) {	/* Rightmost tab */
886 	--b.width;
887     }
888 
889     Tk_Fill3DRectangle(tkwin, d, border,
890 	b.x+2, b.y+2, b.width-1, b.height-2+dh, borderWidth, TK_RELIEF_FLAT);
891 
892     x1 = b.x, x2 = b.x + b.width;
893     y1 = b.y, y2 = b.y + b.height;
894 
895 
896     gc=Ttk_GCForColor(tkwin,tab->borderColorObj,d);
897     XDrawLine(display,d,gc, x1,y1+1, x1,y2+w);
898     XDrawLine(display,d,gc, x2,y1+1, x2,y2+w);
899     XDrawLine(display,d,gc, x1+1,y1, x2-1+w,y1);
900 
901     gc=Ttk_GCForColor(tkwin,tab->lightColorObj,d);
902     XDrawLine(display,d,gc, x1+1,y1+1, x1+1,y2-1+dh+w);
903     XDrawLine(display,d,gc, x1+1,y1+1, x2-1+w,y1+1);
904 }
905 
906 static Ttk_ElementSpec TabElementSpec =
907 {
908     TK_STYLE_VERSION_2,
909     sizeof(NotebookElement),
910     NotebookElementOptions,
911     TabElementSize,
912     TabElementDraw
913 };
914 
ClientElementSize(void * dummy,void * elementRecord,Tk_Window tkwin,int * widthPtr,int * heightPtr,Ttk_Padding * paddingPtr)915 static void ClientElementSize(
916     void *dummy, void *elementRecord, Tk_Window tkwin,
917     int *widthPtr, int *heightPtr, Ttk_Padding *paddingPtr)
918 {
919     int borderWidth = 2;
920     (void)dummy;
921     (void)elementRecord;
922     (void)tkwin;
923     (void)widthPtr;
924     (void)heightPtr;
925 
926     *paddingPtr = Ttk_UniformPadding((short)borderWidth);
927 }
928 
ClientElementDraw(void * dummy,void * elementRecord,Tk_Window tkwin,Drawable d,Ttk_Box b,unsigned int state)929 static void ClientElementDraw(
930     void *dummy, void *elementRecord, Tk_Window tkwin,
931     Drawable d, Ttk_Box b, unsigned int state)
932 {
933     NotebookElement *ce = (NotebookElement *)elementRecord;
934     Tk_3DBorder border = Tk_Get3DBorderFromObj(tkwin, ce->backgroundObj);
935     int borderWidth = 2;
936     (void)dummy;
937     (void)state;
938 
939     Tk_Fill3DRectangle(tkwin, d, border,
940 	b.x, b.y, b.width, b.height, borderWidth,TK_RELIEF_FLAT);
941     DrawSmoothBorder(tkwin, d, b,
942     	ce->borderColorObj, ce->lightColorObj, ce->darkColorObj);
943 }
944 
945 static Ttk_ElementSpec ClientElementSpec =
946 {
947     TK_STYLE_VERSION_2,
948     sizeof(NotebookElement),
949     NotebookElementOptions,
950     ClientElementSize,
951     ClientElementDraw
952 };
953 
954 /*------------------------------------------------------------------------
955  * +++ Modified widget layouts.
956  */
957 
958 TTK_BEGIN_LAYOUT_TABLE(LayoutTable)
959 
960 TTK_LAYOUT("TCombobox",
961     TTK_NODE("Combobox.downarrow", TTK_PACK_RIGHT|TTK_FILL_Y)
962     TTK_GROUP("Combobox.field", TTK_FILL_BOTH,
963 	TTK_GROUP("Combobox.padding", TTK_FILL_BOTH,
964 	    TTK_NODE("Combobox.textarea", TTK_FILL_BOTH))))
965 
966 TTK_LAYOUT("Horizontal.Sash",
967     TTK_GROUP("Sash.hsash", TTK_FILL_BOTH,
968 	TTK_NODE("Sash.hgrip", TTK_FILL_BOTH)))
969 
970 TTK_LAYOUT("Vertical.Sash",
971     TTK_GROUP("Sash.vsash", TTK_FILL_BOTH,
972 	TTK_NODE("Sash.vgrip", TTK_FILL_BOTH)))
973 
974 TTK_END_LAYOUT_TABLE
975 
976 /*------------------------------------------------------------------------
977  * +++ Initialization.
978  */
979 
980 MODULE_SCOPE int
TtkClamTheme_Init(Tcl_Interp * interp)981 TtkClamTheme_Init(Tcl_Interp *interp)
982 {
983     Ttk_Theme theme = Ttk_CreateTheme(interp, "clam", 0);
984 
985     if (!theme) {
986         return TCL_ERROR;
987     }
988 
989     Ttk_RegisterElement(interp,
990 	theme, "border", &BorderElementSpec, NULL);
991     Ttk_RegisterElement(interp,
992 	theme, "field", &FieldElementSpec, NULL);
993     Ttk_RegisterElement(interp,
994 	theme, "Combobox.field", &ComboboxFieldElementSpec, NULL);
995     Ttk_RegisterElement(interp,
996 	theme, "trough", &TroughElementSpec, NULL);
997     Ttk_RegisterElement(interp,
998 	theme, "thumb", &ThumbElementSpec, NULL);
999     Ttk_RegisterElement(interp,
1000 	theme, "uparrow", &ArrowElementSpec, &ArrowElements[0]);
1001     Ttk_RegisterElement(interp,
1002 	theme, "downarrow", &ArrowElementSpec, &ArrowElements[1]);
1003     Ttk_RegisterElement(interp,
1004 	theme, "leftarrow", &ArrowElementSpec, &ArrowElements[2]);
1005     Ttk_RegisterElement(interp,
1006 	theme, "rightarrow", &ArrowElementSpec, &ArrowElements[3]);
1007 
1008     Ttk_RegisterElement(interp,
1009 	theme, "Radiobutton.indicator", &RadioIndicatorElementSpec, NULL);
1010     Ttk_RegisterElement(interp,
1011 	theme, "Checkbutton.indicator", &CheckIndicatorElementSpec, NULL);
1012     Ttk_RegisterElement(interp,
1013 	theme, "Menubutton.indicator", &MenuIndicatorElementSpec, NULL);
1014 
1015     Ttk_RegisterElement(interp, theme, "tab", &TabElementSpec, NULL);
1016     Ttk_RegisterElement(interp, theme, "client", &ClientElementSpec, NULL);
1017 
1018     Ttk_RegisterElement(interp, theme, "slider", &SliderElementSpec, NULL);
1019     Ttk_RegisterElement(interp, theme, "bar", &PbarElementSpec, NULL);
1020     Ttk_RegisterElement(interp, theme, "pbar", &PbarElementSpec, NULL);
1021 
1022     Ttk_RegisterElement(interp, theme, "hgrip",
1023 	    &GripElementSpec,  &GripClientData[0]);
1024     Ttk_RegisterElement(interp, theme, "vgrip",
1025 	    &GripElementSpec,  &GripClientData[1]);
1026 
1027     Ttk_RegisterLayouts(theme, LayoutTable);
1028 
1029     Tcl_PkgProvide(interp, "ttk::theme::clam", TTK_VERSION);
1030 
1031     return TCL_OK;
1032 }
1033