1 /*
2  * bltConfig.c --
3  *
4  *	This module implements custom configuration options for the BLT
5  *	toolkit.
6  *
7  * Copyright 1991-1998 Lucent Technologies, Inc.
8  *
9  * Permission to use, copy, modify, and distribute this software and
10  * its documentation for any purpose and without fee is hereby
11  * granted, provided that the above copyright notice appear in all
12  * copies and that both that the copyright notice and warranty
13  * disclaimer appear in supporting documentation, and that the names
14  * of Lucent Technologies any of their entities not be used in
15  * advertising or publicity pertaining to distribution of the software
16  * without specific, written prior permission.
17  *
18  * Lucent Technologies disclaims all warranties with regard to this
19  * software, including all implied warranties of merchantability and
20  * fitness.  In no event shall Lucent Technologies be liable for any
21  * special, indirect or consequential damages or any damages
22  * whatsoever resulting from loss of use, data or profits, whether in
23  * an action of contract, negligence or other tortuous action, arising
24  * out of or in connection with the use or performance of this
25  * software.
26  */
27 
28 #include "bltInt.h"
29 #if defined(__STDC__)
30 #include <stdarg.h>
31 #else
32 #include <varargs.h>
33 #endif
34 
35 #include "bltTile.h"
36 
37 static int StringToFill _ANSI_ARGS_((ClientData clientData,
38 	Tcl_Interp *interp, Tk_Window tkwin, char *string, char *widgRec,
39 	int flags));
40 static char *FillToString _ANSI_ARGS_((ClientData, Tk_Window, char *, int,
41 	Tcl_FreeProc **));
42 
43 Tk_CustomOption bltFillOption =
44 {
45     StringToFill, FillToString, (ClientData)0
46 };
47 
48 static int StringToPad _ANSI_ARGS_((ClientData clientData,
49 	Tcl_Interp *interp, Tk_Window tkwin, char *string, char *widgRec,
50 	int offset));
51 static char *PadToString _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin,
52 	char *widgRec, int offset, Tcl_FreeProc **freeProcPtr));
53 
54 Tk_CustomOption bltPadOption =
55 {
56     StringToPad, PadToString, (ClientData)0
57 };
58 
59 static int StringToDistance _ANSI_ARGS_((ClientData clientData,
60 	Tcl_Interp *interp, Tk_Window tkwin, char *string, char *widgRec,
61 	int flags));
62 static char *DistanceToString _ANSI_ARGS_((ClientData, Tk_Window, char *, int,
63 	Tcl_FreeProc **));
64 
65 Tk_CustomOption bltDistanceOption =
66 {
67     StringToDistance, DistanceToString, (ClientData)PIXELS_NONNEGATIVE
68 };
69 
70 Tk_CustomOption bltPositiveDistanceOption =
71 {
72     StringToDistance, DistanceToString, (ClientData)PIXELS_POSITIVE
73 };
74 
75 Tk_CustomOption bltAnyDistanceOption =
76 {
77     StringToDistance, DistanceToString, (ClientData)PIXELS_ANY
78 };
79 
80 static int StringToCount _ANSI_ARGS_((ClientData clientData,
81 	Tcl_Interp *interp, Tk_Window tkwin, char *string, char *widgRec,
82 	int flags));
83 static char *CountToString _ANSI_ARGS_((ClientData, Tk_Window, char *, int,
84 	Tcl_FreeProc **));
85 
86 Tk_CustomOption bltCountOption =
87 {
88     StringToCount, CountToString, (ClientData)COUNT_NONNEGATIVE
89 };
90 
91 Tk_CustomOption bltPositiveCountOption =
92 {
93     StringToCount, CountToString, (ClientData)COUNT_POSITIVE
94 };
95 
96 static int StringToDashes _ANSI_ARGS_((ClientData, Tcl_Interp *, Tk_Window,
97 	char *, char *, int));
98 static char *DashesToString _ANSI_ARGS_((ClientData, Tk_Window, char *, int,
99 	Tcl_FreeProc **));
100 
101 Tk_CustomOption bltDashesOption =
102 {
103     StringToDashes, DashesToString, (ClientData)0
104 };
105 
106 static int StringToShadow _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
107 	Tk_Window tkwin, char *string, char *widgRec, int offset));
108 static char *ShadowToString _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin,
109 	char *widgRec, int offset, Tcl_FreeProc **freeProcPtr));
110 
111 Tk_CustomOption bltShadowOption =
112 {
113     StringToShadow, ShadowToString, (ClientData)0
114 };
115 
116 static int StringToGradient _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
117 	Tk_Window tkwin, char *string, char *widgRec, int offset));
118 static char *GradientToString _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin,
119 	char *widgRec, int offset, Tcl_FreeProc **freeProcPtr));
120 
121 Tk_CustomOption bltGradientOption =
122 {
123     StringToGradient, GradientToString, (ClientData)0
124 };
125 
126 static int StringToUid _ANSI_ARGS_((ClientData clientData,
127 	Tcl_Interp *interp, Tk_Window tkwin, char *string, char *widgRec,
128 	int flags));
129 static char *UidToString _ANSI_ARGS_((ClientData, Tk_Window, char *, int,
130 	Tcl_FreeProc **));
131 
132 Tk_CustomOption bltUidOption =
133 {
134     StringToUid, UidToString, (ClientData)0
135 };
136 
137 static int StringToState _ANSI_ARGS_((ClientData clientData,
138 	Tcl_Interp *interp, Tk_Window tkwin, char *string, char *widgRec,
139 	int flags));
140 static char *StateToString _ANSI_ARGS_((ClientData, Tk_Window, char *, int,
141 	Tcl_FreeProc **));
142 
143 Tk_CustomOption bltStateOption =
144 {
145     StringToState, StateToString, (ClientData)0
146 };
147 
148 static int StringToList _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
149 	Tk_Window tkwin, char *string, char *widgRec, int flags));
150 static char *ListToString _ANSI_ARGS_((ClientData, Tk_Window, char *, int,
151 	Tcl_FreeProc **));
152 
153 Tk_CustomOption bltListOption =
154 {
155     StringToList, ListToString, (ClientData)0
156 };
157 
158 static int StringToTile _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp,
159 	Tk_Window tkwin, char *value, char *widgRec, int flags));
160 static char *TileToString _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin,
161 	char *widgRec, int offset, Tcl_FreeProc **freeProcPtr));
162 
163 Tk_CustomOption bltTileOption =
164 {
165     StringToTile, TileToString, (ClientData)0
166 };
167 
168 static int	SetObjTile _ANSI_ARGS_((ClientData clientData,
169 			Tcl_Interp *interp, Tk_Window tkwin,
170 			Tcl_Obj **value, char *recordPtr, int internalOffset,
171 			char *oldInternalPtr, int flags));
172 static Tcl_Obj *GetObjTile _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin,
173 			char *recordPtr, int internalOffset));
174 static void	RestoreObjTile _ANSI_ARGS_((ClientData clientData,
175 			Tk_Window tkwin, char *internalPtr,
176 			char *oldInternalPtr));
177 static void	FreeObjTile _ANSI_ARGS_((ClientData clientData, Tk_Window tkwin,
178 			char *internalPtr));
179 
180 Tk_ObjCustomOption bltCustomTileOption = {
181     "tile",				/* name */
182     SetObjTile,				/* setProc */
183     GetObjTile,				/* getProc */
184     RestoreObjTile,			/* restoreProc */
185     FreeObjTile,               	        /* freeProc */
186     0
187 };
188 
189 
190 static void
FreeObjTile(clientData,tkwin,internalPtr)191 FreeObjTile(clientData, tkwin, internalPtr)
192 ClientData clientData;
193 Tk_Window tkwin;
194 char *internalPtr;
195 {
196     Blt_Tile tilePtr = (Blt_Tile)internalPtr;
197     if (tilePtr != NULL) Blt_FreeTile(tilePtr);
198 }
199 
200 /*
201  *----------------------------------------------------------------------
202  *
203  * GetObjTile -
204  *
205  *	Converts an internal boolean combination of "tile"into a
206  *	a Tcl string obj.
207  *
208  * Results:
209  *	Tcl_Obj containing the string representation of the tile value.
210  *
211  * Side effects:
212  *	Creates a new Tcl_Obj.
213  *
214  *----------------------------------------------------------------------
215  */
216 
217 static Tcl_Obj *
GetObjTile(clientData,tkwin,recordPtr,internalOffset)218 GetObjTile(clientData, tkwin, recordPtr, internalOffset)
219     ClientData clientData;
220     Tk_Window tkwin;
221     char *recordPtr;		/* Pointer to widget record. */
222     int internalOffset;		/* Offset within *recordPtr containing the
223 				 * tile value. */
224 {
225     Blt_Tile tile = *(Blt_Tile *)(recordPtr + internalOffset);
226     char * name;
227     name = Blt_NameOfTile(tile);
228     return Tcl_NewStringObj(name?name:"", -1);
229 }
230 
231 /*
232  *----------------------------------------------------------------------
233  *
234  * SetObjTile --
235  *
236  *	Converts a Tcl_Obj representing a widgets tile.
237  *
238  * Results:
239  *	Standard Tcl result.
240  *
241  * Side effects:
242  *	May store the integer value into the internal representation
243  *	pointer.  May change the pointer to the Tcl_Obj to NULL to indicate
244  *	that the specified string was empty and that is acceptable.
245  *
246  *----------------------------------------------------------------------
247  */
248 
249 static int
SetObjTile(clientData,interp,tkwin,value,recordPtr,internalOffset,oldInternalPtr,flags)250 SetObjTile(clientData, interp, tkwin, value, recordPtr, internalOffset,
251 	oldInternalPtr, flags)
252     ClientData clientData;
253     Tcl_Interp *interp;		/* Current interp; may be used for errors. */
254     Tk_Window tkwin;		/* Window for which option is being set. */
255     Tcl_Obj **value;		/* Pointer to the pointer to the value object.
256 				 * We use a pointer to the pointer because
257 				 * we may need to return a value (NULL). */
258     char *recordPtr;		/* Pointer to storage for the widget record. */
259     int internalOffset;		/* Offset within *recordPtr at which the
260 				   internal value is to be stored. */
261     char *oldInternalPtr;	/* Pointer to storage for the old value. */
262     int flags;			/* Flags for the option, set Tk_SetOptions. */
263 {
264     int length = 0;
265     char *string, *internalPtr;
266     Blt_Tile *tilePtr;
267     Blt_Tile tile, oldTile;
268 
269     if (internalOffset<0 || *value == NULL) { return TCL_ERROR; }
270     string = Tcl_GetStringFromObj(*value, &length);
271 
272     internalPtr = recordPtr+internalOffset;
273 
274     if (length<=0 && (!(flags & TK_OPTION_NULL_OK))) {
275         return TCL_ERROR;
276     }
277     tilePtr = (Blt_Tile*)internalPtr;
278 
279     oldTile = *tilePtr;
280     tile = NULL;
281     if ((string != NULL) && (*string != '\0')) {
282         if (Blt_GetTile(interp, tkwin, string, &tile) != TCL_OK) {
283             return TCL_ERROR;
284         }
285     }
286     if (oldTile != NULL && oldTile != *((Blt_Tile*)oldInternalPtr)) {
287         /* multiple -tile options. */
288         Blt_FreeTile(oldTile);
289     }
290     *tilePtr = tile;
291 
292     return TCL_OK;
293 }
294 
295 /*
296  *----------------------------------------------------------------------
297  *
298  * RestoreObjTile --
299  *
300  *	Restore a tile option value from a saved value.
301  *
302  * Results:
303  *	None.
304  *
305  * Side effects:
306  *	Restores the old value.
307  *
308  *----------------------------------------------------------------------
309  */
310 
311 static void
RestoreObjTile(clientData,tkwin,internalPtr,oldInternalPtr)312 RestoreObjTile(clientData, tkwin, internalPtr, oldInternalPtr)
313     ClientData clientData;
314     Tk_Window tkwin;
315     char *internalPtr;		/* Pointer to storage for value. */
316     char *oldInternalPtr;	/* Pointer to old value. */
317 {
318     Blt_Tile *tilePtr = (Blt_Tile *)internalPtr;
319     Blt_Tile *oldTilePtr = (Blt_Tile *)oldInternalPtr;
320     if (*tilePtr != NULL && *oldTilePtr != *tilePtr) {
321         Blt_FreeTile(*tilePtr);
322     }
323     *tilePtr = *oldTilePtr;
324 }
325 /*
326  *----------------------------------------------------------------------
327  *
328  * Blt_NameOfFill --
329  *
330  *	Converts the integer representing the fill direction into a string.
331  *
332  *----------------------------------------------------------------------
333  */
334 char *
Blt_NameOfFill(fill)335 Blt_NameOfFill(fill)
336     int fill;
337 {
338     switch (fill) {
339     case FILL_X:
340 	return "x";
341     case FILL_Y:
342 	return "y";
343     case FILL_NONE:
344 	return "none";
345     case FILL_BOTH:
346 	return "both";
347     default:
348 	return "unknown value";
349     }
350 }
351 
352 /*
353  *----------------------------------------------------------------------
354  *
355  * StringToFill --
356  *
357  *	Converts the fill style string into its numeric representation.
358  *
359  *	Valid style strings are:
360  *
361  *	  "none"   Use neither plane.
362  * 	  "x"	   X-coordinate plane.
363  *	  "y"	   Y-coordinate plane.
364  *	  "both"   Use both coordinate planes.
365  *
366  *----------------------------------------------------------------------
367  */
368 /*ARGSUSED*/
369 static int
StringToFill(clientData,interp,tkwin,string,widgRec,offset)370 StringToFill(clientData, interp, tkwin, string, widgRec, offset)
371     ClientData clientData;	/* Not used. */
372     Tcl_Interp *interp;		/* Interpreter to send results back to */
373     Tk_Window tkwin;		/* Not used. */
374     char *string;		/* Fill style string */
375     char *widgRec;		/* Cubicle structure record */
376     int offset;			/* Offset of style in record */
377 {
378     int *fillPtr = (int *)(widgRec + offset);
379     unsigned int length;
380     char c;
381 
382     c = string[0];
383     length = strlen(string);
384     if ((c == 'n') && (strncmp(string, "none", length) == 0)) {
385 	*fillPtr = FILL_NONE;
386     } else if ((c == 'x') && (strncmp(string, "x", length) == 0)) {
387 	*fillPtr = FILL_X;
388     } else if ((c == 'y') && (strncmp(string, "y", length) == 0)) {
389 	*fillPtr = FILL_Y;
390     } else if ((c == 'b') && (strncmp(string, "both", length) == 0)) {
391 	*fillPtr = FILL_BOTH;
392     } else {
393 	Tcl_AppendResult(interp, "bad argument \"", string,
394 	    "\": should be \"none\", \"x\", \"y\", or \"both\"", (char *)NULL);
395 	return TCL_ERROR;
396     }
397     return TCL_OK;
398 }
399 
400 /*
401  *----------------------------------------------------------------------
402  *
403  * FillToString --
404  *
405  *	Returns the fill style string based upon the fill flags.
406  *
407  * Results:
408  *	The fill style string is returned.
409  *
410  *----------------------------------------------------------------------
411  */
412 /*ARGSUSED*/
413 static char *
FillToString(clientData,tkwin,widgRec,offset,freeProcPtr)414 FillToString(clientData, tkwin, widgRec, offset, freeProcPtr)
415     ClientData clientData;	/* Not used. */
416     Tk_Window tkwin;		/* Not used. */
417     char *widgRec;		/* Widget structure record */
418     int offset;			/* Offset of fill in widget record */
419     Tcl_FreeProc **freeProcPtr;	/* Not used. */
420 {
421     int fill = *(int *)(widgRec + offset);
422 
423     return Blt_NameOfFill(fill);
424 }
425 
426 /*
427  *----------------------------------------------------------------------
428  *
429  * Blt_StringToFlag --
430  *
431  *	Converts the fill style string into its numeric representation.
432  *
433  *----------------------------------------------------------------------
434  */
435 /*ARGSUSED*/
436 int
Blt_StringToFlag(clientData,interp,tkwin,string,widgRec,offset)437 Blt_StringToFlag(clientData, interp, tkwin, string, widgRec, offset)
438     ClientData clientData;	/* Bit mask to be tested in status word */
439     Tcl_Interp *interp;		/* Interpreter to send results back to */
440     Tk_Window tkwin;		/* Not used. */
441     char *string;		/* Fill style string */
442     char *widgRec;		/* Cubicle structure record */
443     int offset;			/* Offset of style in record */
444 {
445     unsigned int mask = (unsigned int)clientData;	/* Bit to be tested */
446     int *flagPtr = (int *)(widgRec + offset);
447     int bool;
448 
449     if (Tcl_GetBoolean(interp, string, &bool) != TCL_OK) {
450 	return TCL_ERROR;
451     }
452     if (bool) {
453 	*flagPtr |= mask;
454     } else {
455 	*flagPtr &= ~mask;
456     }
457     return TCL_OK;
458 }
459 
460 /*
461  *----------------------------------------------------------------------
462  *
463  * Blt_FlagToString --
464  *
465  *	Returns the fill style string based upon the fill flags.
466  *
467  * Results:
468  *	The fill style string is returned.
469  *
470  *----------------------------------------------------------------------
471  */
472 /*ARGSUSED*/
473 char *
Blt_FlagToString(clientData,tkwin,widgRec,offset,freeProcPtr)474 Blt_FlagToString(clientData, tkwin, widgRec, offset, freeProcPtr)
475     ClientData clientData;	/* Bit mask to be test in status word */
476     Tk_Window tkwin;		/* Not used. */
477     char *widgRec;		/* Widget structure record */
478     int offset;			/* Offset of fill in widget record */
479     Tcl_FreeProc **freeProcPtr;	/* Not Used. */
480 {
481     unsigned int mask = (unsigned int)clientData;	/* Bit to be tested */
482     unsigned int bool = *(unsigned int *)(widgRec + offset);
483 
484     return (bool & mask) ? "1" : "0";
485 }
486 
487 
488 /*
489  *----------------------------------------------------------------------
490  *
491  * Blt_GetPixels --
492  *
493  *	Like Tk_GetPixels, but checks for negative, zero.
494  *
495  * Results:
496  *	A standard Tcl result.
497  *
498  *----------------------------------------------------------------------
499  */
500 int
Blt_GetPixels(interp,tkwin,string,check,valuePtr)501 Blt_GetPixels(interp, tkwin, string, check, valuePtr)
502     Tcl_Interp *interp;
503     Tk_Window tkwin;
504     char *string;
505     int check;			/* Can be PIXELS_POSITIVE, PIXELS_NONNEGATIVE,
506 				 * or PIXELS_ANY, */
507     int *valuePtr;
508 {
509     int length;
510 
511     if (Tk_GetPixels(interp, tkwin, string, &length) != TCL_OK) {
512 	return TCL_ERROR;
513     }
514     if (length >= SHRT_MAX) {
515 	Tcl_AppendResult(interp, "bad distance \"", string, "\": ",
516 	    "too big to represent", (char *)NULL);
517 	return TCL_ERROR;
518     }
519     switch (check) {
520     case PIXELS_NONNEGATIVE:
521 	if (length < 0) {
522 	    Tcl_AppendResult(interp, "bad distance \"", string, "\": ",
523 		"can't be negative", (char *)NULL);
524 	    return TCL_ERROR;
525 	}
526 	break;
527     case PIXELS_POSITIVE:
528 	if (length <= 0) {
529 	    Tcl_AppendResult(interp, "bad distance \"", string, "\": ",
530 		"must be positive", (char *)NULL);
531 	    return TCL_ERROR;
532 	}
533 	break;
534     case PIXELS_ANY:
535 	break;
536     }
537     *valuePtr = length;
538     return TCL_OK;
539 }
540 
541 /*
542  *----------------------------------------------------------------------
543  *
544  * StringToDistance --
545  *
546  *	Like TK_CONFIG_PIXELS, but adds an extra check for negative
547  *	values.
548  *
549  *----------------------------------------------------------------------
550  */
551 /*ARGSUSED*/
552 static int
StringToDistance(clientData,interp,tkwin,string,widgRec,offset)553 StringToDistance(clientData, interp, tkwin, string, widgRec, offset)
554     ClientData clientData;	/* Indicated how to check distance */
555     Tcl_Interp *interp;		/* Interpreter to send results back to */
556     Tk_Window tkwin;		/* Window */
557     char *string;		/* Pixel value string */
558     char *widgRec;		/* Widget record */
559     int offset;			/* Offset of pixel size in record */
560 {
561     int *valuePtr = (int *)(widgRec + offset);
562     return Blt_GetPixels(interp, tkwin, string, (int)clientData, valuePtr);
563 }
564 
565 /*
566  *----------------------------------------------------------------------
567  *
568  * DistanceToString --
569  *
570  *	Returns the string representing the positive pixel size.
571  *
572  * Results:
573  *	The pixel size string is returned.
574  *
575  *----------------------------------------------------------------------
576  */
577 /*ARGSUSED*/
578 static char *
DistanceToString(clientData,tkwin,widgRec,offset,freeProcPtr)579 DistanceToString(clientData, tkwin, widgRec, offset, freeProcPtr)
580     ClientData clientData;	/* Not used. */
581     Tk_Window tkwin;		/* Not used. */
582     char *widgRec;		/* Widget structure record */
583     int offset;			/* Offset in widget record */
584     Tcl_FreeProc **freeProcPtr;	/* Not used. */
585 {
586     int value = *(int *)(widgRec + offset);
587     char *result;
588 
589     result = Blt_Strdup(Blt_Itoa(value));
590     assert(result);
591     *freeProcPtr = (Tcl_FreeProc *)Blt_Free;
592     return result;
593 }
594 
595 int
Blt_GetInt(interp,string,check,valuePtr)596 Blt_GetInt(interp, string, check, valuePtr)
597     Tcl_Interp *interp;
598     char *string;
599     int check;			/* Can be COUNT_POSITIVE, COUNT_NONNEGATIVE,
600 				 * or COUNT_ANY, */
601     int *valuePtr;
602 {
603     int count;
604 
605     if (Tcl_GetInt(interp, string, &count) != TCL_OK) {
606 	return TCL_ERROR;
607     }
608     switch (check) {
609     case COUNT_NONNEGATIVE:
610 	if (count < 0) {
611 	    Tcl_AppendResult(interp, "bad value \"", string, "\": ",
612 		"can't be negative", (char *)NULL);
613 	    return TCL_ERROR;
614 	}
615 	break;
616     case COUNT_POSITIVE:
617 	if (count <= 0) {
618 	    Tcl_AppendResult(interp, "bad value \"", string, "\": ",
619 		"must be positive", (char *)NULL);
620 	    return TCL_ERROR;
621 	}
622 	break;
623     case COUNT_ANY:
624 	break;
625     }
626     *valuePtr = count;
627     return TCL_OK;
628 }
629 
630 /*
631  *----------------------------------------------------------------------
632  *
633  * StringToCount --
634  *
635  *	Like TK_CONFIG_PIXELS, but adds an extra check for negative
636  *	values.
637  *
638  *----------------------------------------------------------------------
639  */
640 /*ARGSUSED*/
641 static int
StringToCount(clientData,interp,tkwin,string,widgRec,offset)642 StringToCount(clientData, interp, tkwin, string, widgRec, offset)
643     ClientData clientData;	/* Indicated how to check distance */
644     Tcl_Interp *interp;		/* Interpreter to send results back to */
645     Tk_Window tkwin;		/* Not used. */
646     char *string;		/* Pixel value string */
647     char *widgRec;		/* Widget record */
648     int offset;			/* Offset of pixel size in record */
649 {
650     int *valuePtr = (int *)(widgRec + offset);
651     return Blt_GetInt(interp, string, (int)clientData, valuePtr);
652 }
653 
654 /*
655  *----------------------------------------------------------------------
656  *
657  * CountToString --
658  *
659  *	Returns the string representing the positive pixel size.
660  *
661  * Results:
662  *	The pixel size string is returned.
663  *
664  *----------------------------------------------------------------------
665  */
666 /*ARGSUSED*/
667 static char *
CountToString(clientData,tkwin,widgRec,offset,freeProcPtr)668 CountToString(clientData, tkwin, widgRec, offset, freeProcPtr)
669     ClientData clientData;	/* Not used. */
670     Tk_Window tkwin;		/* Not used. */
671     char *widgRec;		/* Widget structure record */
672     int offset;			/* Offset in widget record */
673     Tcl_FreeProc **freeProcPtr;	/* Not used. */
674 {
675     int value = *(int *)(widgRec + offset);
676     char *result;
677 
678     result = Blt_Strdup(Blt_Itoa(value));
679     assert(result);
680     *freeProcPtr = (Tcl_FreeProc *)Blt_Free;
681     return result;
682 }
683 
684 /*
685  *----------------------------------------------------------------------
686  *
687  * StringToPad --
688  *
689  *	Convert a string into two pad values.  The string may be in one of
690  *	the following forms:
691  *
692  *	    n    - n is a non-negative integer. This sets both
693  *		   pad values to n.
694  *	  {n m}  - both n and m are non-negative integers. side1
695  *		   is set to n, side2 is set to m.
696  *
697  * Results:
698  *	If the string is successfully converted, TCL_OK is returned.
699  *	Otherwise, TCL_ERROR is returned and an error message is left in
700  *	interp->result.
701  *
702  * Side Effects:
703  *	The padding structure passed is updated with the new values.
704  *
705  *----------------------------------------------------------------------
706  */
707 /*ARGSUSED*/
708 static int
StringToPad(clientData,interp,tkwin,string,widgRec,offset)709 StringToPad(clientData, interp, tkwin, string, widgRec, offset)
710     ClientData clientData;	/* Not used. */
711     Tcl_Interp *interp;		/* Interpreter to send results back to */
712     Tk_Window tkwin;		/* Window */
713     char *string;		/* Pixel value string */
714     char *widgRec;		/* Widget record */
715     int offset;			/* Offset of pad in widget */
716 {
717     Blt_Pad *padPtr = (Blt_Pad *)(widgRec + offset);
718     int nElem;
719     int pad, result;
720     char **padArr;
721 
722     if (Tcl_SplitList(interp, string, &nElem, &padArr) != TCL_OK) {
723 	return TCL_ERROR;
724     }
725     result = TCL_ERROR;
726     if ((nElem < 1) || (nElem > 2)) {
727 	Tcl_AppendResult(interp, "wrong # elements in padding list",
728 	    (char *)NULL);
729 	goto error;
730     }
731     if (Blt_GetPixels(interp, tkwin, padArr[0], PIXELS_NONNEGATIVE, &pad)
732 	!= TCL_OK) {
733 	goto error;
734     }
735     padPtr->side1 = pad;
736     if ((nElem > 1) &&
737 	(Blt_GetPixels(interp, tkwin, padArr[1], PIXELS_NONNEGATIVE, &pad)
738 	    != TCL_OK)) {
739 	goto error;
740     }
741     padPtr->side2 = pad;
742     result = TCL_OK;
743 
744   error:
745     Blt_Free(padArr);
746     return result;
747 }
748 
749 /*
750  *----------------------------------------------------------------------
751  *
752  * PadToString --
753  *
754  *	Converts the two pad values into a Tcl list.  Each pad has two
755  *	pixel values.  For vertical pads, they represent the top and bottom
756  *	margins.  For horizontal pads, they're the left and right margins.
757  *	All pad values are non-negative integers.
758  *
759  * Results:
760  *	The padding list is returned.
761  *
762  *----------------------------------------------------------------------
763  */
764 /*ARGSUSED*/
765 static char *
PadToString(clientData,tkwin,widgRec,offset,freeProcPtr)766 PadToString(clientData, tkwin, widgRec, offset, freeProcPtr)
767     ClientData clientData;	/* Not used. */
768     Tk_Window tkwin;		/* Not used. */
769     char *widgRec;		/* Structure record */
770     int offset;			/* Offset of pad in record */
771     Tcl_FreeProc **freeProcPtr;	/* Not used. */
772 {
773     Blt_Pad *padPtr = (Blt_Pad *)(widgRec + offset);
774     char *result;
775     char string[200];
776 
777     sprintf(string, "%d %d", padPtr->side1, padPtr->side2);
778     result = Blt_Strdup(string);
779     if (result == NULL) {
780 	return "out of memory";
781     }
782     *freeProcPtr = (Tcl_FreeProc *)Blt_Free;
783     return result;
784 }
785 
786 /*
787  *----------------------------------------------------------------------
788  *
789  * StringToShadow --
790  *
791  *	Convert a string into two pad values.  The string may be in one of
792  *	the following forms:
793  *
794  *	    n    - n is a non-negative integer. This sets both
795  *		   pad values to n.
796  *	  {n m}  - both n and m are non-negative integers. side1
797  *		   is set to n, side2 is set to m.
798  *
799  * Results:
800  *	If the string is successfully converted, TCL_OK is returned.
801  *	Otherwise, TCL_ERROR is returned and an error message is left in
802  *	interp->result.
803  *
804  * Side Effects:
805  *	The padding structure passed is updated with the new values.
806  *
807  *      TODO: all users of this need to free color on widget exit.
808  *----------------------------------------------------------------------
809  */
810 /*ARGSUSED*/
811 static int
StringToShadow(clientData,interp,tkwin,string,widgRec,offset)812 StringToShadow(clientData, interp, tkwin, string, widgRec, offset)
813     ClientData clientData;	/* Not used. */
814     Tcl_Interp *interp;		/* Interpreter to send results back to */
815     Tk_Window tkwin;		/* Window */
816     char *string;		/* Pixel value string */
817     char *widgRec;		/* Widget record */
818     int offset;			/* Offset of pad in widget */
819 {
820     Shadow *shadowPtr = (Shadow *) (widgRec + offset);
821     XColor *colorPtr;
822     int dropOffset;
823 
824     colorPtr = NULL;
825     dropOffset = 0;
826     if ((string != NULL) && (string[0] != '\0')) {
827 	int nElem;
828 	char **elemArr;
829 
830 	if (Tcl_SplitList(interp, string, &nElem, &elemArr) != TCL_OK) {
831 	    return TCL_ERROR;
832 	}
833 	if ((nElem < 1) || (nElem > 2)) {
834 	    Tcl_AppendResult(interp, "wrong # elements in drop shadow value",
835 		(char *)NULL);
836 	    Blt_Free(elemArr);
837 	    return TCL_ERROR;
838 	}
839 	colorPtr = Tk_GetColor(interp, tkwin, Tk_GetUid(elemArr[0]));
840 	if (colorPtr == NULL) {
841 	    Blt_Free(elemArr);
842 	    return TCL_ERROR;
843 	}
844 	dropOffset = 1;
845 	if (nElem == 2) {
846 	    if (Blt_GetPixels(interp, tkwin, elemArr[1], PIXELS_NONNEGATIVE,
847 		    &dropOffset) != TCL_OK) {
848 		Tk_FreeColor(colorPtr);
849 		Blt_Free(elemArr);
850 		return TCL_ERROR;
851 	    }
852 	}
853 	Blt_Free(elemArr);
854     }
855     if (shadowPtr->color != NULL) {
856 	Tk_FreeColor(shadowPtr->color);
857     }
858     shadowPtr->color = colorPtr;
859     shadowPtr->offset = dropOffset;
860     return TCL_OK;
861 }
862 
863 
864 /*
865  *----------------------------------------------------------------------
866  *
867  * ShadowToString --
868  *
869  *	Converts the two pad values into a Tcl list.  Each pad has two
870  *	pixel values.  For vertical pads, they represent the top and bottom
871  *	margins.  For horizontal pads, they're the left and right margins.
872  *	All pad values are non-negative integers.
873  *
874  * Results:
875  *	The padding list is returned.
876  *
877  *----------------------------------------------------------------------
878  */
879 /*ARGSUSED*/
880 static char *
ShadowToString(clientData,tkwin,widgRec,offset,freeProcPtr)881 ShadowToString(clientData, tkwin, widgRec, offset, freeProcPtr)
882     ClientData clientData;	/* Not used. */
883     Tk_Window tkwin;		/* Not used. */
884     char *widgRec;		/* Structure record */
885     int offset;			/* Offset of pad in record */
886     Tcl_FreeProc **freeProcPtr;	/* Not used. */
887 {
888     Shadow *shadowPtr = (Shadow *) (widgRec + offset);
889     char *result;
890 
891     result = "";
892     if (shadowPtr->color != NULL) {
893 	char string[200];
894 
895 	sprintf(string, "%s %d", Tk_NameOfColor(shadowPtr->color),
896 	    shadowPtr->offset);
897 	result = Blt_Strdup(string);
898 	*freeProcPtr = (Tcl_FreeProc *)Blt_Free;
899     }
900     return result;
901 }
902 
903 /*
904  *----------------------------------------------------------------------
905  *
906  * GradientToString --
907  *
908  *	Converts the two pad values into a Tcl list.  Each pad has two
909  *	pixel values.  For vertical pads, they represent the top and bottom
910  *	margins.  For horizontal pads, they're the left and right margins.
911  *	All pad values are non-negative integers.
912  *
913  * Results:
914  *	The padding list is returned.
915  *
916  *----------------------------------------------------------------------
917  */
918 /*ARGSUSED*/
919 static char *
GradientToString(clientData,tkwin,widgRec,offset,freeProcPtr)920 GradientToString(clientData, tkwin, widgRec, offset, freeProcPtr)
921     ClientData clientData;	/* Not used. */
922     Tk_Window tkwin;		/* Not used. */
923     char *widgRec;		/* Structure record */
924     int offset;			/* Offset of pad in record */
925     Tcl_FreeProc **freeProcPtr;	/* Not used. */
926 {
927     Gradient *gradientPtr = (Gradient *) (widgRec + offset);
928     char *result;
929 
930     result = "";
931     if (gradientPtr->color != NULL) {
932 	char string[200];
933 
934          sprintf(string, "%s %s %d", Tk_NameOfColor(gradientPtr->color), Tk_NameOfColor(gradientPtr->color2), gradientPtr->width);
935 	result = Blt_Strdup(string);
936 	*freeProcPtr = (Tcl_FreeProc *)Blt_Free;
937     }
938     return result;
939 }
940 
941 
942 /*
943  *----------------------------------------------------------------------
944  *
945  * StringToGradient --
946  *
947  *	Convert a string into two pad values.  The string may be in one of
948  *	the following forms:
949  *
950  *	    n    - n is a non-negative integer. This sets both
951  *		   pad values to n.
952  *	  {n m}  - both n and m are non-negative integers. side1
953  *		   is set to n, side2 is set to m.
954  *
955  * Results:
956  *	If the string is successfully converted, TCL_OK is returned.
957  *	Otherwise, TCL_ERROR is returned and an error message is left in
958  *	interp->result.
959  *
960  * Side Effects:
961  *	The padding structure passed is updated with the new values.
962  *
963  *----------------------------------------------------------------------
964  */
965 /*ARGSUSED*/
966 static int
StringToGradient(clientData,interp,tkwin,string,widgRec,offset)967 StringToGradient(clientData, interp, tkwin, string, widgRec, offset)
968     ClientData clientData;	/* Not used. */
969     Tcl_Interp *interp;		/* Interpreter to send results back to */
970     Tk_Window tkwin;		/* Window */
971     char *string;		/* Pixel value string */
972     char *widgRec;		/* Widget record */
973     int offset;			/* Offset of pad in widget */
974 {
975     Gradient *gradientPtr = (Gradient *) (widgRec + offset);
976     XColor *colorPtr, *color2Ptr;
977     int dropOffset;
978 
979     colorPtr = NULL;
980     dropOffset = 0;
981     if ((string != NULL) && (string[0] != '\0')) {
982 	int nElem;
983 	char **elemArr;
984 
985 	if (Tcl_SplitList(interp, string, &nElem, &elemArr) != TCL_OK) {
986 	    return TCL_ERROR;
987 	}
988 	if (nElem != 3) {
989 	    Tcl_AppendResult(interp, "expected \"color1 color2 length\"  for gradient value",
990 		(char *)NULL);
991 	    Blt_Free(elemArr);
992 	    return TCL_ERROR;
993 	}
994 	colorPtr = Tk_GetColor(interp, tkwin, Tk_GetUid(elemArr[0]));
995 	if (colorPtr == NULL) {
996 	    Blt_Free(elemArr);
997 	    return TCL_ERROR;
998 	}
999 	color2Ptr = Tk_GetColor(interp, tkwin, Tk_GetUid(elemArr[1]));
1000 	if (color2Ptr == NULL) {
1001 	    Blt_Free(elemArr);
1002 	    return TCL_ERROR;
1003 	}
1004 	dropOffset = 1;
1005         if (Blt_GetPixels(interp, tkwin, elemArr[2], PIXELS_NONNEGATIVE,
1006             &dropOffset) != TCL_OK) {
1007              Tk_FreeColor(colorPtr);
1008              Tk_FreeColor(color2Ptr);
1009              Blt_Free(elemArr);
1010              return TCL_ERROR;
1011          }
1012 	Blt_Free(elemArr);
1013     }
1014     if (gradientPtr->color != NULL) {
1015 	Tk_FreeColor(gradientPtr->color);
1016     }
1017     if (gradientPtr->color2 != NULL) {
1018         Tk_FreeColor(gradientPtr->color2);
1019     }
1020     gradientPtr->color = colorPtr;
1021     gradientPtr->color2 = color2Ptr;
1022     gradientPtr->width = dropOffset;
1023     return TCL_OK;
1024 }
1025 
1026 /*
1027  *----------------------------------------------------------------------
1028  *
1029  * GetDashes --
1030  *
1031  *	Converts a Tcl list of dash values into a dash list ready for
1032  *	use with XSetDashes.
1033  *
1034  * 	A valid list dash values can have zero through 11 elements
1035  *	(PostScript limit).  Values must be between 1 and 255. Although
1036  *	a list of 0 (like the empty string) means no dashes.
1037  *
1038  * Results:
1039  *	A standard Tcl result. If the list represented a valid dash
1040  *	list TCL_OK is returned and *dashesPtr* will contain the
1041  *	valid dash list. Otherwise, TCL_ERROR is returned and
1042  *	interp->result will contain an error message.
1043  *
1044  *
1045  *----------------------------------------------------------------------
1046  */
1047 static int
GetDashes(interp,string,dashesPtr)1048 GetDashes(interp, string, dashesPtr)
1049     Tcl_Interp *interp;
1050     char *string;
1051     Blt_Dashes *dashesPtr;
1052 {
1053     if ((string == NULL) || (*string == '\0')) {
1054 	dashesPtr->values[0] = 0;
1055     } else if (strcmp(string, "dash") == 0) {	/* 5 2 */
1056 	dashesPtr->values[0] = 5;
1057 	dashesPtr->values[1] = 2;
1058 	dashesPtr->values[2] = 0;
1059     } else if (strcmp(string, "dot") == 0) {	/* 1 */
1060 	dashesPtr->values[0] = 1;
1061 	dashesPtr->values[1] = 0;
1062     } else if (strcmp(string, "dashdot") == 0) {	/* 2 4 2 */
1063 	dashesPtr->values[0] = 2;
1064 	dashesPtr->values[1] = 4;
1065 	dashesPtr->values[2] = 2;
1066 	dashesPtr->values[3] = 0;
1067     } else if (strcmp(string, "dashdotdot") == 0) {	/* 2 4 2 2 */
1068 	dashesPtr->values[0] = 2;
1069 	dashesPtr->values[1] = 4;
1070 	dashesPtr->values[2] = 2;
1071 	dashesPtr->values[3] = 2;
1072 	dashesPtr->values[4] = 0;
1073     } else {
1074 	int nValues;
1075 	char **strArr;
1076 	long int value;
1077 	register int i;
1078 
1079 	if (Tcl_SplitList(interp, string, &nValues, &strArr) != TCL_OK) {
1080 	    return TCL_ERROR;
1081 	}
1082 	if (nValues > 11) {	/* This is the postscript limit */
1083 	    Tcl_AppendResult(interp, "too many values in dash list \"",
1084 			     string, "\"", (char *)NULL);
1085 	    Blt_Free(strArr);
1086 	    return TCL_ERROR;
1087 	}
1088 	for (i = 0; i < nValues; i++) {
1089 	    if (Tcl_ExprLong(interp, strArr[i], &value) != TCL_OK) {
1090 		Blt_Free(strArr);
1091 		return TCL_ERROR;
1092 	    }
1093 	    /*
1094 	     * Backward compatibility:
1095 	     * Allow list of 0 to turn off dashes
1096 	     */
1097 	    if ((value == 0) && (nValues == 1)) {
1098 		break;
1099 	    }
1100 	    if ((value < 1) || (value > 255)) {
1101 		Tcl_AppendResult(interp, "dash value \"", strArr[i],
1102 		    "\" is out of range", (char *)NULL);
1103 		Blt_Free(strArr);
1104 		return TCL_ERROR;
1105 	    }
1106 	    dashesPtr->values[i] = (unsigned char)value;
1107 	}
1108 	/* Make sure the array ends with a NUL byte  */
1109 	dashesPtr->values[i] = 0;
1110 	Blt_Free(strArr);
1111     }
1112     return TCL_OK;
1113 
1114 }
1115 
1116 /*
1117  *----------------------------------------------------------------------
1118  *
1119  * StringToDashes --
1120  *
1121  *	Convert the list of dash values into a dashes array.
1122  *
1123  * Results:
1124  *	The return value is a standard Tcl result.
1125  *
1126  * Side Effects:
1127  *	The Dashes structure is updated with the new dash list.
1128  *
1129  *----------------------------------------------------------------------
1130  */
1131 /*ARGSUSED*/
1132 static int
StringToDashes(clientData,interp,tkwin,string,widgRec,offset)1133 StringToDashes(clientData, interp, tkwin, string, widgRec, offset)
1134     ClientData clientData;	/* Not used. */
1135     Tcl_Interp *interp;		/* Interpreter to send results back to */
1136     Tk_Window tkwin;		/* Not used. */
1137     char *string;		/* New dash value list */
1138     char *widgRec;		/* Widget record */
1139     int offset;			/* offset to Dashes structure */
1140 {
1141     Blt_Dashes *dashesPtr = (Blt_Dashes *)(widgRec + offset);
1142 
1143     return GetDashes(interp, string, dashesPtr);
1144 }
1145 
1146 /*
1147  *----------------------------------------------------------------------
1148  *
1149  * DashesToString --
1150  *
1151  *	Convert the dashes array into a list of values.
1152  *
1153  * Results:
1154  *	The string representing the dashes returned.
1155  *
1156  *----------------------------------------------------------------------
1157  */
1158 /*ARGSUSED*/
1159 static char *
DashesToString(clientData,tkwin,widgRec,offset,freeProcPtr)1160 DashesToString(clientData, tkwin, widgRec, offset, freeProcPtr)
1161     ClientData clientData;	/* Not used. */
1162     Tk_Window tkwin;		/* Not used. */
1163     char *widgRec;		/* Widget record */
1164     int offset;			/* offset of Dashes in record */
1165     Tcl_FreeProc **freeProcPtr;	/* Memory deallocation scheme to use */
1166 {
1167     Blt_Dashes *dashesPtr = (Blt_Dashes *)(widgRec + offset);
1168     Tcl_DString dString;
1169     unsigned char *p;
1170     char *result;
1171 
1172     if (dashesPtr->values[0] == 0) {
1173 	return "";
1174     }
1175     Tcl_DStringInit(&dString);
1176     for (p = dashesPtr->values; *p != 0; p++) {
1177 	Tcl_DStringAppendElement(&dString, Blt_Itoa(*p));
1178     }
1179     result = Tcl_DStringValue(&dString);
1180     if (result == dString.staticSpace) {
1181 	result = Blt_Strdup(result);
1182     }
1183     *freeProcPtr = (Tcl_FreeProc *)Blt_Free;
1184     return result;
1185 }
1186 
1187 /*
1188  *----------------------------------------------------------------------
1189  *
1190  * StringToUid --
1191  *
1192  *	Converts the string to a BLT Uid. Blt Uid's are hashed, reference
1193  *	counted strings.
1194  *
1195  *----------------------------------------------------------------------
1196  */
1197 /*ARGSUSED*/
1198 static int
StringToUid(clientData,interp,tkwin,string,widgRec,offset)1199 StringToUid(clientData, interp, tkwin, string, widgRec, offset)
1200     ClientData clientData;	/* Not used. */
1201     Tcl_Interp *interp;		/* Interpreter to send results back to */
1202     Tk_Window tkwin;		/* Not used. */
1203     char *string;		/* Fill style string */
1204     char *widgRec;		/* Cubicle structure record */
1205     int offset;			/* Offset of style in record */
1206 {
1207     Blt_Uid *uidPtr = (Blt_Uid *)(widgRec + offset);
1208     Blt_Uid newId;
1209 
1210     newId = NULL;
1211     if ((string != NULL) && (*string != '\0')) {
1212 	newId = Blt_GetUid(string);
1213     }
1214     if (*uidPtr != NULL) {
1215 	Blt_FreeUid(*uidPtr);
1216     }
1217     *uidPtr = newId;
1218     return TCL_OK;
1219 }
1220 
1221 /*
1222  *----------------------------------------------------------------------
1223  *
1224  * UidToString --
1225  *
1226  *	Returns the fill style string based upon the fill flags.
1227  *
1228  * Results:
1229  *	The fill style string is returned.
1230  *
1231  *----------------------------------------------------------------------
1232  */
1233 /*ARGSUSED*/
1234 static char *
UidToString(clientData,tkwin,widgRec,offset,freeProcPtr)1235 UidToString(clientData, tkwin, widgRec, offset, freeProcPtr)
1236     ClientData clientData;	/* Not used. */
1237     Tk_Window tkwin;		/* Not used. */
1238     char *widgRec;		/* Widget structure record */
1239     int offset;			/* Offset of fill in widget record */
1240     Tcl_FreeProc **freeProcPtr;	/* Not used. */
1241 {
1242     Blt_Uid uid = *(Blt_Uid *)(widgRec + offset);
1243 
1244     return (uid == NULL) ? "" : uid;
1245 }
1246 
1247 /*
1248  *----------------------------------------------------------------------
1249  *
1250  * StringToState --
1251  *
1252  *	Converts the string to a state value. Valid states are
1253  *	disabled, normal.
1254  *
1255  *----------------------------------------------------------------------
1256  */
1257 /*ARGSUSED*/
1258 static int
StringToState(clientData,interp,tkwin,string,widgRec,offset)1259 StringToState(clientData, interp, tkwin, string, widgRec, offset)
1260     ClientData clientData;	/* Not used. */
1261     Tcl_Interp *interp;		/* Interpreter to send results back to */
1262     Tk_Window tkwin;		/* Not used. */
1263     char *string;		/* String representation of option value */
1264     char *widgRec;		/* Widget structure record */
1265     int offset;			/* Offset of field in record */
1266 {
1267     int *statePtr = (int *)(widgRec + offset);
1268 
1269     if (strcmp(string, "normal") == 0) {
1270 	*statePtr = STATE_NORMAL;
1271     } else if (strcmp(string, "disabled") == 0) {
1272 	*statePtr = STATE_DISABLED;
1273     } else if (strcmp(string, "active") == 0) {
1274 	*statePtr = STATE_ACTIVE;
1275     } else {
1276 	Tcl_AppendResult(interp, "bad state \"", string,
1277 	    "\": should be normal, active, or disabled", (char *)NULL);
1278 	return TCL_ERROR;
1279     }
1280     return TCL_OK;
1281 }
1282 
1283 /*
1284  *----------------------------------------------------------------------
1285  *
1286  * StateToString --
1287  *
1288  *	Returns the string representation of the state configuration field
1289  *
1290  * Results:
1291  *	The string is returned.
1292  *
1293  *----------------------------------------------------------------------
1294  */
1295 /*ARGSUSED*/
1296 static char *
StateToString(clientData,tkwin,widgRec,offset,freeProcPtr)1297 StateToString(clientData, tkwin, widgRec, offset, freeProcPtr)
1298     ClientData clientData;	/* Not used. */
1299     Tk_Window tkwin;		/* Not used. */
1300     char *widgRec;		/* Widget structure record */
1301     int offset;			/* Offset of fill in widget record */
1302     Tcl_FreeProc **freeProcPtr;	/* Not used. */
1303 {
1304     int state = *(int *)(widgRec + offset);
1305 
1306     switch (state) {
1307     case STATE_ACTIVE:
1308 	return "active";
1309     case STATE_DISABLED:
1310 	return "disabled";
1311     case STATE_NORMAL:
1312 	return "normal";
1313     default:
1314 	return "???";
1315     }
1316 }
1317 
1318 /*
1319  *----------------------------------------------------------------------
1320  *
1321  * StringToList --
1322  *
1323  *	Converts the string to a list.
1324  *
1325  *----------------------------------------------------------------------
1326  */
1327 /*ARGSUSED*/
1328 static int
StringToList(clientData,interp,tkwin,string,widgRec,offset)1329 StringToList(clientData, interp, tkwin, string, widgRec, offset)
1330     ClientData clientData;	/* Not used. */
1331     Tcl_Interp *interp;		/* Interpreter to send results back to */
1332     Tk_Window tkwin;		/* Not used. */
1333     char *string;		/* String representation of option value */
1334     char *widgRec;		/* Widget structure record */
1335     int offset;			/* Offset of field in record */
1336 {
1337     char ***listPtr = (char ***)(widgRec + offset);
1338     char **elemArr;
1339     int nElem;
1340 
1341     if (*listPtr != NULL) {
1342 	Blt_Free(*listPtr);
1343 	*listPtr = NULL;
1344     }
1345     if ((string == NULL) || (*string == '\0')) {
1346 	return TCL_OK;
1347     }
1348     if (Tcl_SplitList(interp, string, &nElem, &elemArr) != TCL_OK) {
1349 	return TCL_ERROR;
1350     }
1351     if (nElem > 0) {
1352 	*listPtr = elemArr;
1353     }
1354     return TCL_OK;
1355 }
1356 
1357 /*
1358  *----------------------------------------------------------------------
1359  *
1360  * ListToString --
1361  *
1362  *	Returns the string representation of the state configuration field
1363  *
1364  * Results:
1365  *	The string is returned.
1366  *
1367  *----------------------------------------------------------------------
1368  */
1369 /*ARGSUSED*/
1370 static char *
ListToString(clientData,tkwin,widgRec,offset,freeProcPtr)1371 ListToString(clientData, tkwin, widgRec, offset, freeProcPtr)
1372     ClientData clientData;	/* Not used. */
1373     Tk_Window tkwin;		/* Not used. */
1374     char *widgRec;		/* Widget structure record. */
1375     int offset;			/* Offset of fill in widget record. */
1376     Tcl_FreeProc **freeProcPtr;	/* Not used. */
1377 {
1378     char **list = *(char ***)(widgRec + offset);
1379     register char **p;
1380     char *result;
1381     Tcl_DString dString;
1382 
1383     if (list == NULL) {
1384 	return "";
1385     }
1386     Tcl_DStringInit(&dString);
1387     for (p = list; *p != NULL; p++) {
1388 	Tcl_DStringAppendElement(&dString, *p);
1389     }
1390     result = Tcl_DStringValue(&dString);
1391     if (result == dString.staticSpace) {
1392 	result = Blt_Strdup(result);
1393     }
1394     Tcl_DStringFree(&dString);
1395     *freeProcPtr = (Tcl_FreeProc *)Blt_Free;
1396     return result;
1397 }
1398 
1399 
1400 /*
1401  *----------------------------------------------------------------------
1402  *
1403  * StringToTile --
1404  *
1405  *	Converts the name of an image into a tile.
1406  *
1407  *----------------------------------------------------------------------
1408  */
1409 /*ARGSUSED*/
1410 static int
StringToTile(clientData,interp,tkwin,string,widgRec,offset)1411 StringToTile(clientData, interp, tkwin, string, widgRec, offset)
1412     ClientData clientData;	/* Not used. */
1413     Tcl_Interp *interp;		/* Interpreter to send results back to */
1414     Tk_Window tkwin;		/* Window on same display as tile */
1415     char *string;		/* Name of image */
1416     char *widgRec;		/* Widget structure record */
1417     int offset;			/* Offset of tile in record */
1418 {
1419     Blt_Tile *tilePtr = (Blt_Tile *)(widgRec + offset);
1420     Blt_Tile tile, oldTile;
1421 
1422     oldTile = *tilePtr;
1423     tile = NULL;
1424     if ((string != NULL) && (*string != '\0')) {
1425 	if (Blt_GetTile(interp, tkwin, string, &tile) != TCL_OK) {
1426 	    return TCL_ERROR;
1427 	}
1428     }
1429     /* Don't delete the information for the old tile, until we know
1430      * that we successfully allocated a new one. */
1431     if (oldTile != NULL) {
1432 	Blt_FreeTile(oldTile);
1433     }
1434     *tilePtr = tile;
1435     return TCL_OK;
1436 }
1437 
1438 /*
1439  *----------------------------------------------------------------------
1440  *
1441  * TileToString --
1442  *
1443  *	Returns the name of the tile.
1444  *
1445  * Results:
1446  *	The name of the tile is returned.
1447  *
1448  *----------------------------------------------------------------------
1449  */
1450 /*ARGSUSED*/
1451 static char *
TileToString(clientData,tkwin,widgRec,offset,freeProcPtr)1452 TileToString(clientData, tkwin, widgRec, offset, freeProcPtr)
1453     ClientData clientData;	/* Not used. */
1454     Tk_Window tkwin;		/* Not used. */
1455     char *widgRec;		/* Widget structure record */
1456     int offset;			/* Offset of tile in record */
1457     Tcl_FreeProc **freeProcPtr;	/* Not used. */
1458 {
1459     Blt_Tile tile = *(Blt_Tile *)(widgRec + offset);
1460 
1461     return Blt_NameOfTile(tile);
1462 }
1463 
1464 /*
1465  *----------------------------------------------------------------------
1466  *
1467  * Blt_ConfigModified --
1468  *
1469  *      Given the configuration specifications and one or more option
1470  *	patterns (terminated by a NULL), indicate if any of the matching
1471  *	configuration options has been reset.
1472  *
1473  * Results:
1474  *      Returns 1 if one of the options has changed, 0 otherwise.
1475  *
1476  *----------------------------------------------------------------------
1477  */
1478 int Blt_ConfigModified
TCL_VARARGS_DEF(Tk_ConfigSpec *,arg1)1479 TCL_VARARGS_DEF(Tk_ConfigSpec *, arg1)
1480 {
1481     va_list argList;
1482     Tk_ConfigSpec *specs;
1483     register Tk_ConfigSpec *specPtr;
1484     register char *option;
1485     Tcl_Interp *interp;
1486 
1487     specs = TCL_VARARGS_START(Tk_ConfigSpec *, arg1, argList);
1488     interp = va_arg(argList, Tcl_Interp *);
1489     specs = Blt_GetCachedSpecs(interp, specs);
1490     while ((option = va_arg(argList, char *)) != NULL) {
1491 	for (specPtr = specs; specPtr->type != TK_CONFIG_END; specPtr++) {
1492 	    if ((Tcl_StringMatch(specPtr->argvName, option)) &&
1493 		(specPtr->specFlags & TK_CONFIG_OPTION_SPECIFIED)) {
1494 		va_end(argList);
1495 		return 1;
1496 	    }
1497 	}
1498     }
1499     va_end(argList);
1500     return 0;
1501 }
1502 
1503 /*
1504  *----------------------------------------------------------------------
1505  *
1506  * Blt_ConfigureWidgetComponent --
1507  *
1508  *	Configures a component of a widget.  This is useful for
1509  *	widgets that have multiple components which aren't uniquely
1510  *	identified by a Tk_Window. It allows us, for example, set
1511  *	resources for axes of the graph widget. The graph really has
1512  *	only one window, but its convenient to specify components in a
1513  *	hierarchy of options.
1514  *
1515  *		*graph.x.logScale yes
1516  *		*graph.Axis.logScale yes
1517  *		*graph.temperature.scaleSymbols yes
1518  *		*graph.Element.scaleSymbols yes
1519  *
1520  *	This is really a hack to work around the limitations of the Tk
1521  *	resource database.  It creates a temporary window, needed to
1522  *	call Tk_ConfigureWidget, using the name of the component.
1523  *
1524  * Results:
1525  *      A standard Tcl result.
1526  *
1527  * Side Effects:
1528  *	A temporary window is created merely to pass to Tk_ConfigureWidget.
1529  *
1530  *----------------------------------------------------------------------
1531  */
1532 int
Blt_ConfigureWidgetComponent(interp,parent,resName,className,specsPtr,argc,argv,widgRec,flags)1533 Blt_ConfigureWidgetComponent(interp, parent, resName, className, specsPtr,
1534 	argc, argv, widgRec, flags)
1535     Tcl_Interp *interp;
1536     Tk_Window parent;		/* Window to associate with component */
1537     char resName[];		/* Name of component */
1538     char className[];
1539     Tk_ConfigSpec *specsPtr;
1540     int argc;
1541     char *argv[];
1542     char *widgRec;
1543     int flags;
1544 {
1545     Tk_Window tkwin;
1546     int result;
1547     char *tempName;
1548     char *oldClass;
1549     int isTemporary = FALSE;
1550 
1551     tempName = Blt_Strdup(resName);
1552 
1553     /* Window name can't start with an upper case letter */
1554     tempName[0] = tolower(resName[0]);
1555 
1556     /*
1557      * Create component if a child window by the component's name
1558      * doesn't already exist.
1559      */
1560     tkwin = Blt_FindChild(parent, tempName);
1561     if (tkwin == NULL) {
1562 	tkwin = Tk_CreateWindow(interp, parent, tempName, (char *)NULL);
1563 	isTemporary = TRUE;
1564      } else {
1565         oldClass = Tk_Class(tkwin);
1566      }
1567     if (tkwin == NULL) {
1568 	Tcl_AppendResult(interp, "can't find window in \"",
1569 		 Tk_PathName(parent), "\"", (char *)NULL);
1570 	return TCL_ERROR;
1571     }
1572     assert(Tk_Depth(tkwin) == Tk_Depth(parent));
1573     Blt_Free(tempName);
1574 
1575     Tk_SetClass(tkwin, className);
1576     result = Tk_ConfigureWidget(interp, tkwin, specsPtr, argc, argv, widgRec,
1577 	flags);
1578     if (isTemporary) {
1579 	Tk_DestroyWindow(tkwin);
1580     } else if (oldClass != NULL) {
1581         Tk_SetClass(tkwin, oldClass);
1582     }
1583     return result;
1584 }
1585 
1586 
1587 /*
1588  *----------------------------------------------------------------------
1589  *
1590  * Blt_StringToEnum --
1591  *
1592  *	Converts the string into its enumerated type.
1593  *
1594  *----------------------------------------------------------------------
1595  */
1596 /*ARGSUSED*/
1597 int
Blt_StringToEnum(clientData,interp,tkwin,string,widgRec,offset)1598 Blt_StringToEnum(clientData, interp, tkwin, string, widgRec, offset)
1599     ClientData clientData;	/* Vectors of valid strings. */
1600     Tcl_Interp *interp;		/* Interpreter to send results back to */
1601     Tk_Window tkwin;		/* Not used. */
1602     char *string;		/* String to match. */
1603     char *widgRec;		/* Widget record. */
1604     int offset;			/* Offset of field in record */
1605 {
1606     int *enumPtr = (int *)(widgRec + offset);
1607     char c;
1608     register char **p;
1609     register int i;
1610     int count;
1611 
1612     c = string[0];
1613     count = 0;
1614     for (p = (char **)clientData; *p != NULL; p++) {
1615 	if ((c == p[0][0]) && (strcmp(string, *p) == 0)) {
1616 	    *enumPtr = count;
1617 	    return TCL_OK;
1618 	}
1619 	count++;
1620     }
1621     *enumPtr = -1;
1622 
1623     Tcl_AppendResult(interp, "bad value \"", string, "\": should be ",
1624 		(char *)NULL);
1625     p = (char **)clientData;
1626     if (count > 0) {
1627 	Tcl_AppendResult(interp, p[0], (char *)NULL);
1628     }
1629     for (i = 1; i < (count - 1); i++) {
1630 	Tcl_AppendResult(interp, " ", p[i], ", ", (char *)NULL);
1631     }
1632     if (count > 1) {
1633 	Tcl_AppendResult(interp, " or ", p[count - 1], ".", (char *)NULL);
1634     }
1635     return TCL_ERROR;
1636 }
1637 
1638 /*
1639  *----------------------------------------------------------------------
1640  *
1641  * Blt_EnumToString --
1642  *
1643  *	Returns the string associated with the enumerated type.
1644  *
1645  *----------------------------------------------------------------------
1646  */
1647 /*ARGSUSED*/
1648 char *
Blt_EnumToString(clientData,tkwin,widgRec,offset,freeProcPtr)1649 Blt_EnumToString(clientData, tkwin, widgRec, offset, freeProcPtr)
1650     ClientData clientData;	/* List of strings. */
1651     Tk_Window tkwin;		/* Not used. */
1652     char *widgRec;		/* Widget record */
1653     int offset;			/* Offset of field in widget record */
1654     Tcl_FreeProc **freeProcPtr;	/* Not used. */
1655 {
1656     int value = *(int *)(widgRec + offset);
1657     char **p;
1658     int count;
1659 
1660     count = 0;
1661     for (p = (char **)clientData; *p != NULL; p++) {
1662 	count++;
1663     }
1664     if ((value >= count) || (value < 0)) {
1665 	return "unknown value";
1666     }
1667     p = (char **)clientData;
1668     return p[value];
1669 }
1670 
1671 #include "bltOldConfig.c"
1672