summaryrefslogtreecommitdiffstats
path: root/src/bltConfig.C
diff options
context:
space:
mode:
authorjoye <joye>2013-08-27 18:44:24 (GMT)
committerjoye <joye>2013-08-27 18:44:24 (GMT)
commit48974a09f23839821ca95f228fc0f3f53bb1cefa (patch)
tree9d5cfa1305ef57b69c9b1dd09dc3ffe536c0777d /src/bltConfig.C
parent05d8c009040abfcb5f62644fbb99c8ff453d4519 (diff)
downloadblt-48974a09f23839821ca95f228fc0f3f53bb1cefa.zip
blt-48974a09f23839821ca95f228fc0f3f53bb1cefa.tar.gz
blt-48974a09f23839821ca95f228fc0f3f53bb1cefa.tar.bz2
*** empty log message ***
Diffstat (limited to 'src/bltConfig.C')
-rw-r--r--src/bltConfig.C2493
1 files changed, 2493 insertions, 0 deletions
diff --git a/src/bltConfig.C b/src/bltConfig.C
new file mode 100644
index 0000000..cf67a23
--- /dev/null
+++ b/src/bltConfig.C
@@ -0,0 +1,2493 @@
+
+/*
+ * bltConfig.c --
+ *
+ * This file contains a Tcl_Obj based replacement for the widget
+ * configuration functions in Tk.
+ *
+ * Copyright (c) 1990-1994 The Regents of the University of California.
+ * Copyright (c) 1994-1997 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * Copyright 2003-2004 George A Howlett.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
+ * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * This is a Tcl_Obj based replacement for the widget configuration
+ * functions in Tk.
+ *
+ * What not use the new Tk_Option interface?
+ *
+ * There were design changes in the new Tk_Option interface that
+ * make it unwieldy.
+ *
+ * o You have to dynamically allocate, store, and deallocate
+ * your option table.
+ * o The Tk_FreeConfigOptions routine requires a tkwin argument.
+ * Unfortunately, most widgets save the display pointer and
+ * de-reference their tkwin when the window is destroyed.
+ * o There's no TK_CONFIG_CUSTOM functionality. This means that
+ * save special options must be saved as strings by
+ * Tk_ConfigureWidget and processed later, thus losing the
+ * benefits of Tcl_Objs. It also make error handling
+ * problematic, since you don't pick up certain errors like
+ *
+ * .widget configure -myoption bad -myoption good
+ *
+ * You will never see the first "bad" value.
+ * o Especially compared to the former Tk_ConfigureWidget calls,
+ * the new interface is overly complex. If there was a big
+ * performance win, it might be worth the effort. But let's
+ * face it, this biggest wins are in processing custom options
+ * values with thousands of elements. Most common resources
+ * (font, color, etc) have string tokens anyways.
+ *
+ * On the other hand, the replacement functions in this file fell
+ * into place quite easily both from the aspect of API writer and
+ * user. The biggest benefit is that you don't need to change lots
+ * of working code just to get the benefits of Tcl_Objs.
+ *
+ */
+
+#include "bltInt.h"
+
+#include <stdarg.h>
+#include "bltFont.h"
+#include "bltPicture.h"
+#include "bltBgStyle.h"
+
+#if (_TK_VERSION < _VERSION(8,1,0))
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_GetAnchorFromObj --
+ *
+ * Return a Tk_Anchor value based on the value of the objPtr.
+ *
+ * Results:
+ * The return value is a standard TCL result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * The object gets converted by Tcl_GetIndexFromObj.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Tk_GetAnchorFromObj(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *objPtr, /* The object we are trying to get the
+ * value from. */
+ Tk_Anchor *anchorPtr) /* Where to place the Tk_Anchor that
+ * corresponds to the string value of
+ * objPtr. */
+{
+ return Tk_GetAnchor(interp, Tcl_GetString(objPtr), anchorPtr);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_GetJustifyFromObj --
+ *
+ * Return a Tk_Justify value based on the value of the objPtr.
+ *
+ * Results:
+ * The return value is a standard TCL result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * The object gets converted by Tcl_GetIndexFromObj.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Tk_GetJustifyFromObj(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *objPtr, /* The object we are trying to get the
+ * value from. */
+ Tk_Justify *justifyPtr) /* Where to place the Tk_Justify that
+ * corresponds to the string value of
+ * objPtr. */
+{
+ return Tk_GetJustify(interp, Tcl_GetString(objPtr), justifyPtr);
+}
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_GetReliefFromObj --
+ *
+ * Return an integer value based on the value of the objPtr.
+ *
+ * Results:
+ * The return value is a standard TCL result. If an error occurs during
+ * conversion, an error message is left in the interpreter's result
+ * unless "interp" is NULL.
+ *
+ * Side effects:
+ * The object gets converted by Tcl_GetIndexFromObj.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Tk_GetReliefFromObj(
+ Tcl_Interp *interp, /* Used for error reporting. */
+ Tcl_Obj *objPtr, /* The object we are trying to get the
+ * value from. */
+ int *reliefPtr) /* Where to place the answer. */
+{
+ return Tk_GetRelief(interp, Tcl_GetString(objPtr), reliefPtr);
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_Alloc3DBorderFromObj --
+ *
+ * Given a Tcl_Obj *, map the value to a corresponding
+ * Tk_3DBorder structure based on the tkwin given.
+ *
+ * Results:
+ * The return value is a token for a data structure describing a
+ * 3-D border. This token may be passed to procedures such as
+ * Blt_Draw3DRectangle and Tk_Free3DBorder. If an error prevented
+ * the border from being created then NULL is returned and an error
+ * message will be left in the interp's result.
+ *
+ * Side effects:
+ * The border is added to an internal database with a reference
+ * count. For each call to this procedure, there should eventually
+ * be a call to FreeBorderObjProc so that the database is
+ * cleaned up when borders aren't in use anymore.
+ *
+ *---------------------------------------------------------------------------
+ */
+Tk_3DBorder
+Tk_Alloc3DBorderFromObj(
+ Tcl_Interp *interp, /* Interp for error results. */
+ Tk_Window tkwin, /* Need the screen the border is used on.*/
+ Tcl_Obj *objPtr) /* Object giving name of color for window
+ * background. */
+{
+ return Tk_Get3DBorder(interp, tkwin, Tcl_GetString(objPtr));
+}
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_AllocBitmapFromObj --
+ *
+ * Given a Tcl_Obj *, map the value to a corresponding
+ * Pixmap structure based on the tkwin given.
+ *
+ * Results:
+ * The return value is the X identifer for the desired bitmap
+ * (i.e. a Pixmap with a single plane), unless string couldn't be
+ * parsed correctly. In this case, None is returned and an error
+ * message is left in the interp's result. The caller should never
+ * modify the bitmap that is returned, and should eventually call
+ * Tk_FreeBitmapFromObj when the bitmap is no longer needed.
+ *
+ * Side effects:
+ * The bitmap is added to an internal database with a reference count.
+ * For each call to this procedure, there should eventually be a call
+ * to Tk_FreeBitmapFromObj, so that the database can be cleaned up
+ * when bitmaps aren't needed anymore.
+ *
+ *---------------------------------------------------------------------------
+ */
+Pixmap
+Tk_AllocBitmapFromObj(
+ Tcl_Interp *interp, /* Interp for error results. This may
+ * be NULL. */
+ Tk_Window tkwin, /* Need the screen the bitmap is used on.*/
+ Tcl_Obj *objPtr) /* Object describing bitmap; see manual
+ * entry for legal syntax of string value. */
+{
+ return Tk_GetBitmap(interp, tkwin, Tcl_GetString(objPtr));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_AllocFontFromObj --
+ *
+ * Given a string description of a font, map the description to a
+ * corresponding Blt_Font that represents the font.
+ *
+ * Results:
+ * The return value is token for the font, or NULL if an error
+ * prevented the font from being created. If NULL is returned, an
+ * error message will be left in interp's result object.
+ *
+ * Side effects:
+ * The font is added to an internal database with a reference
+ * count. For each call to this procedure, there should eventually
+ * be a call to Blt_FreeFont() or Blt_FreeFontFromObj() so that the
+ * database is cleaned up when fonts aren't in use anymore.
+ *
+ *---------------------------------------------------------------------------
+ */
+Tk_Font
+Tk_AllocFontFromObj(
+ Tcl_Interp *interp, /* Interp for database and error return. */
+ Tk_Window tkwin, /* For screen on which font will be used. */
+ Tcl_Obj *objPtr) /* Object describing font, as: named font,
+ * native format, or parseable string. */
+{
+ return Tk_GetFont(interp, tkwin, Tcl_GetString(objPtr));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_AllocCursorFromObj --
+ *
+ * Given a Tcl_Obj *, map the value to a corresponding
+ * Tk_Cursor structure based on the tkwin given.
+ *
+ * Results:
+ * The return value is the X identifer for the desired cursor,
+ * unless objPtr couldn't be parsed correctly. In this case,
+ * None is returned and an error message is left in the interp's result.
+ * The caller should never modify the cursor that is returned, and
+ * should eventually call Tk_FreeCursorFromObj when the cursor is no
+ * longer needed.
+ *
+ * Side effects:
+ * The cursor is added to an internal database with a reference count.
+ * For each call to this procedure, there should eventually be a call
+ * to Tk_FreeCursorFromObj, so that the database can be cleaned up
+ * when cursors aren't needed anymore.
+ *
+ *---------------------------------------------------------------------------
+ */
+Tk_Cursor
+Tk_AllocCursorFromObj(
+ Tcl_Interp *interp, /* Interp for error results. */
+ Tk_Window tkwin, /* Window in which the cursor will be used.*/
+ Tcl_Obj *objPtr) /* Object describing cursor; see manual
+ * entry for description of legal
+ * syntax of this obj's string rep. */
+{
+ return Tk_GetCursor(interp, tkwin, Tcl_GetString(objPtr));
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Tk_AllocColorFromObj --
+ *
+ * Given a Tcl_Obj *, map the value to a corresponding
+ * XColor structure based on the tkwin given.
+ *
+ * Results:
+ * The return value is a pointer to an XColor structure that
+ * indicates the red, blue, and green intensities for the color
+ * given by the string in objPtr, and also specifies a pixel value
+ * to use to draw in that color. If an error occurs, NULL is
+ * returned and an error message will be left in interp's result
+ * (unless interp is NULL).
+ *
+ * Side effects:
+ * The color is added to an internal database with a reference count.
+ * For each call to this procedure, there should eventually be a call
+ * to Tk_FreeColorFromObj so that the database is cleaned up when colors
+ * aren't in use anymore.
+ *
+ *---------------------------------------------------------------------------
+ */
+XColor *
+Tk_AllocColorFromObj(
+ Tcl_Interp *interp, /* Used only for error reporting. If NULL,
+ * then no messages are provided. */
+ Tk_Window tkwin, /* Window in which the color will be used.*/
+ Tcl_Obj *objPtr) /* Object that describes the color; string
+ * value is a color name such as "red" or
+ * "#ff0000".*/
+{
+ const char *string;
+
+ string = Tcl_GetString(objPtr);
+ return Tk_GetColor(interp, tkwin, Tk_GetUid(string));
+}
+#endif
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetPositionFromObj --
+ *
+ * Convert a string representing a numeric position.
+ * A position can be in one of the following forms.
+ *
+ * number - number of the item in the hierarchy, indexed
+ * from zero.
+ * "end" - last position in the hierarchy.
+ *
+ * Results:
+ * A standard TCL result. If "string" is a valid index, then
+ * *indexPtr is filled with the corresponding numeric index.
+ * If "end" was selected then *indexPtr is set to -1.
+ * Otherwise an error message is left in interp->result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_GetPositionFromObj(
+ Tcl_Interp *interp, /* Interpreter to report results back
+ * to. */
+ Tcl_Obj *objPtr, /* Tcl_Obj representation of the index.
+ * Can be an integer or "end" to refer
+ * to the last index. */
+ long *indexPtr) /* Holds the converted index. */
+{
+ const char *string;
+
+ string = Tcl_GetString(objPtr);
+ if ((string[0] == 'e') && (strcmp(string, "end") == 0)) {
+ *indexPtr = -1; /* Indicates last position in hierarchy. */
+ } else {
+ long position;
+
+ if (Tcl_GetLongFromObj(interp, objPtr, &position) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (position < 0) {
+ Tcl_AppendResult(interp, "bad position \"", string, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ *indexPtr = position;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetPixelsFromObj --
+ *
+ * Like Tk_GetPixelsFromObj, but checks for negative, zero.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_GetPixelsFromObj(
+ Tcl_Interp *interp,
+ Tk_Window tkwin,
+ Tcl_Obj *objPtr,
+ int check, /* Can be PIXELS_POS, PIXELS_NNEG,
+ * or PIXELS_ANY, */
+ int *valuePtr)
+{
+ int length;
+
+ if (Tk_GetPixelsFromObj(interp, tkwin, objPtr, &length) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (length >= SHRT_MAX) {
+ Tcl_AppendResult(interp, "bad distance \"", Tcl_GetString(objPtr),
+ "\": too big to represent", (char *)NULL);
+ return TCL_ERROR;
+ }
+ switch (check) {
+ case PIXELS_NNEG:
+ if (length < 0) {
+ Tcl_AppendResult(interp, "bad distance \"", Tcl_GetString(objPtr),
+ "\": can't be negative", (char *)NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case PIXELS_POS:
+ if (length <= 0) {
+ Tcl_AppendResult(interp, "bad distance \"", Tcl_GetString(objPtr),
+ "\": must be positive", (char *)NULL);
+ return TCL_ERROR;
+ }
+ break;
+
+ case PIXELS_ANY:
+ break;
+ }
+ *valuePtr = length;
+ return TCL_OK;
+}
+
+int
+Blt_GetPadFromObj(
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tk_Window tkwin, /* Window */
+ Tcl_Obj *objPtr, /* Pixel value string */
+ Blt_Pad *padPtr)
+{
+ int side1, side2;
+ int objc;
+ Tcl_Obj **objv;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((objc < 1) || (objc > 2)) {
+ Tcl_AppendResult(interp, "wrong # elements in padding list",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (Blt_GetPixelsFromObj(interp, tkwin, objv[0], PIXELS_NNEG,
+ &side1) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ side2 = side1;
+ if ((objc > 1) &&
+ (Blt_GetPixelsFromObj(interp, tkwin, objv[1], PIXELS_NNEG,
+ &side2) != TCL_OK)) {
+ return TCL_ERROR;
+ }
+ /* Don't update the pad structure until we know both values are okay. */
+ padPtr->side1 = side1;
+ padPtr->side2 = side2;
+ return TCL_OK;
+}
+
+int
+Blt_GetStateFromObj(
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tcl_Obj *objPtr, /* Pixel value string */
+ int *statePtr)
+{
+ char c;
+ const char *string;
+ int length;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[0];
+ if ((c == 'n') && (strncmp(string, "normal", length) == 0)) {
+ *statePtr = STATE_NORMAL;
+ } else if ((c == 'd') && (strncmp(string, "disabled", length) == 0)) {
+ *statePtr = STATE_DISABLED;
+ } else if ((c == 'a') && (strncmp(string, "active", length) == 0)) {
+ *statePtr = STATE_ACTIVE;
+ } else {
+ Tcl_AppendResult(interp, "bad state \"", string,
+ "\": should be normal, active, or disabled", (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+const char *
+Blt_NameOfState(int state)
+{
+ switch (state) {
+ case STATE_ACTIVE:
+ return "active";
+ case STATE_DISABLED:
+ return "disabled";
+ case STATE_NORMAL:
+ return "normal";
+ default:
+ return "???";
+ }
+}
+
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_NameOfFill --
+ *
+ * Converts the integer representing the fill style into a string.
+ *
+ *---------------------------------------------------------------------------
+ */
+const char *
+Blt_NameOfFill(int fill)
+{
+ switch (fill) {
+ case FILL_X:
+ return "x";
+ case FILL_Y:
+ return "y";
+ case FILL_NONE:
+ return "none";
+ case FILL_BOTH:
+ return "both";
+ default:
+ return "unknown value";
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetFillFromObj --
+ *
+ * Converts the fill style string into its numeric representation.
+ *
+ * Valid style strings are:
+ *
+ * "none" Use neither plane.
+ * "x" X-coordinate plane.
+ * "y" Y-coordinate plane.
+ * "both" Use both coordinate planes.
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+int
+Blt_GetFillFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *fillPtr)
+{
+ char c;
+ const char *string;
+ int length;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[0];
+ if ((c == 'n') && (strncmp(string, "none", length) == 0)) {
+ *fillPtr = FILL_NONE;
+ } else if ((c == 'x') && (strncmp(string, "x", length) == 0)) {
+ *fillPtr = FILL_X;
+ } else if ((c == 'y') && (strncmp(string, "y", length) == 0)) {
+ *fillPtr = FILL_Y;
+ } else if ((c == 'b') && (strncmp(string, "both", length) == 0)) {
+ *fillPtr = FILL_BOTH;
+ } else {
+ Tcl_AppendResult(interp, "bad argument \"", string,
+ "\": should be \"none\", \"x\", \"y\", or \"both\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_NameOfResize --
+ *
+ * Converts the resize value into its string representation.
+ *
+ * Results:
+ * Returns a pointer to the static name string.
+ *
+ *---------------------------------------------------------------------------
+ */
+const char *
+Blt_NameOfResize(int resize)
+{
+ switch (resize & RESIZE_BOTH) {
+ case RESIZE_NONE:
+ return "none";
+ case RESIZE_EXPAND:
+ return "expand";
+ case RESIZE_SHRINK:
+ return "shrink";
+ case RESIZE_BOTH:
+ return "both";
+ default:
+ return "unknown resize value";
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetResizeFromObj --
+ *
+ * Converts the resize string into its numeric representation.
+ *
+ * Valid style strings are:
+ *
+ * "none"
+ * "expand"
+ * "shrink"
+ * "both"
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED*/
+int
+Blt_GetResizeFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int *resizePtr)
+{
+ char c;
+ const char *string;
+ int length;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[0];
+ if ((c == 'n') && (strncmp(string, "none", length) == 0)) {
+ *resizePtr = RESIZE_NONE;
+ } else if ((c == 'b') && (strncmp(string, "both", length) == 0)) {
+ *resizePtr = RESIZE_BOTH;
+ } else if ((c == 'e') && (strncmp(string, "expand", length) == 0)) {
+ *resizePtr = RESIZE_EXPAND;
+ } else if ((c == 's') && (strncmp(string, "shrink", length) == 0)) {
+ *resizePtr = RESIZE_SHRINK;
+ } else {
+ Tcl_AppendResult(interp, "bad resize argument \"", string,
+ "\": should be \"none\", \"expand\", \"shrink\", or \"both\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetDashesFromObj --
+ *
+ * Converts a TCL list of dash values into a dash list ready for
+ * use with XSetDashes.
+ *
+ * A valid list dash values can have zero through 11 elements
+ * (PostScript limit). Values must be between 1 and 255. Although
+ * a list of 0 (like the empty string) means no dashes.
+ *
+ * Results:
+ * A standard TCL result. If the list represented a valid dash
+ * list TCL_OK is returned and *dashesPtr* will contain the
+ * valid dash list. Otherwise, TCL_ERROR is returned and
+ * interp->result will contain an error message.
+ *
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_GetDashesFromObj(
+ Tcl_Interp *interp,
+ Tcl_Obj *objPtr,
+ Blt_Dashes *dashesPtr)
+{
+ const char *string;
+ char c;
+
+ string = Tcl_GetString(objPtr);
+ if (string == NULL) {
+ dashesPtr->values[0] = 0;
+ return TCL_OK;
+ }
+ c = string[0];
+ if (c == '\0') {
+ dashesPtr->values[0] = 0;
+ } else if ((c == 'd') && (strcmp(string, "dot") == 0)) {
+ /* 1 */
+ dashesPtr->values[0] = 1;
+ dashesPtr->values[1] = 0;
+ } else if ((c == 'd') && (strcmp(string, "dash") == 0)) {
+ /* 5 2 */
+ dashesPtr->values[0] = 5;
+ dashesPtr->values[1] = 2;
+ dashesPtr->values[2] = 0;
+ } else if ((c == 'd') && (strcmp(string, "dashdot") == 0)) {
+ /* 2 4 2 */
+ dashesPtr->values[0] = 2;
+ dashesPtr->values[1] = 4;
+ dashesPtr->values[2] = 2;
+ dashesPtr->values[3] = 0;
+ } else if ((c == 'd') && (strcmp(string, "dashdotdot") == 0)) {
+ /* 2 4 2 2 */
+ dashesPtr->values[0] = 2;
+ dashesPtr->values[1] = 4;
+ dashesPtr->values[2] = 2;
+ dashesPtr->values[3] = 2;
+ dashesPtr->values[4] = 0;
+ } else {
+ int objc;
+ Tcl_Obj **objv;
+ int i;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc > 11) { /* This is the postscript limit */
+ Tcl_AppendResult(interp, "too many values in dash list \"",
+ string, "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ for (i = 0; i < objc; i++) {
+ int value;
+
+ if (Tcl_GetIntFromObj(interp, objv[i], &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ /*
+ * Backward compatibility:
+ * Allow list of 0 to turn off dashes
+ */
+ if ((value == 0) && (objc == 1)) {
+ break;
+ }
+ if ((value < 1) || (value > 255)) {
+ Tcl_AppendResult(interp, "dash value \"",
+ Tcl_GetString(objv[i]), "\" is out of range",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ dashesPtr->values[i] = (unsigned char)value;
+ }
+ /* Make sure the array ends with a NUL byte */
+ dashesPtr->values[i] = 0;
+ }
+ return TCL_OK;
+}
+
+const char *
+Blt_NameOfSide(int side)
+{
+ switch (side) {
+ case SIDE_LEFT:
+ return "left";
+ case SIDE_RIGHT:
+ return "right";
+ case SIDE_BOTTOM:
+ return "bottom";
+ case SIDE_TOP:
+ return "top";
+ }
+ return "unknown side value";
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_GetSideFromObj --
+ *
+ * Converts the fill style string into its numeric representation.
+ *
+ * Valid style strings are "left", "right", "top", or "bottom".
+ *
+ *---------------------------------------------------------------------------
+ */
+/*ARGSUSED */
+int
+Blt_GetSideFromObj(
+ Tcl_Interp *interp, /* Interpreter to send results back to */
+ Tcl_Obj *objPtr, /* Value string */
+ int *sidePtr) /* (out) Token representing side:
+ * either SIDE_LEFT, SIDE_RIGHT,
+ * SIDE_TOP, or SIDE_BOTTOM. */
+{
+ char c;
+ const char *string;
+ int length;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[0];
+ if ((c == 'l') && (strncmp(string, "left", length) == 0)) {
+ *sidePtr = SIDE_LEFT;
+ } else if ((c == 'r') && (strncmp(string, "right", length) == 0)) {
+ *sidePtr = SIDE_RIGHT;
+ } else if ((c == 't') && (strncmp(string, "top", length) == 0)) {
+ *sidePtr = SIDE_TOP;
+ } else if ((c == 'b') && (strncmp(string, "bottom", length) == 0)) {
+ *sidePtr = SIDE_BOTTOM;
+ } else {
+ Tcl_AppendResult(interp, "bad side \"", string,
+ "\": should be left, right, top, or bottom", (char *)NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ResetLimits --
+ *
+ * Resets the limits to their default values.
+ *
+ * Results:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_ResetLimits(Blt_Limits *limitsPtr) /* Limits to be imposed on the value */
+{
+ limitsPtr->flags = 0;
+ limitsPtr->min = LIMITS_MIN;
+ limitsPtr->max = LIMITS_MAX;
+ limitsPtr->nom = LIMITS_NOM;
+}
+
+int
+Blt_GetLimitsFromObj(Tcl_Interp *interp, Tk_Window tkwin, Tcl_Obj *objPtr,
+ Blt_Limits *limitsPtr)
+{
+ int values[3];
+ int nValues;
+ int limitsFlags;
+
+ /* Initialize limits to default values */
+ values[2] = LIMITS_NOM;
+ values[1] = LIMITS_MAX;
+ values[0] = LIMITS_MIN;
+ limitsFlags = 0;
+ nValues = 0;
+ if (objPtr != NULL) {
+ Tcl_Obj **objv;
+ int objc;
+ int i;
+
+ if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (objc > 3) {
+ Tcl_AppendResult(interp, "wrong # limits \"", Tcl_GetString(objPtr),
+ "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ for (i = 0; i < objc; i++) {
+ const char *string;
+ int size;
+
+ string = Tcl_GetString(objv[i]);
+ if (string[0] == '\0') {
+ continue; /* Empty string: use default value */
+ }
+ limitsFlags |= (1 << i);
+ if (Tk_GetPixelsFromObj(interp, tkwin, objv[i], &size) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if ((size < LIMITS_MIN) || (size > LIMITS_MAX)) {
+ Tcl_AppendResult(interp, "bad limit \"", string, "\"",
+ (char *)NULL);
+ return TCL_ERROR;
+ }
+ values[i] = size;
+ }
+ nValues = objc;
+ }
+ /*
+ * Check the limits specified. We can't check the requested size of
+ * widgets.
+ */
+ switch (nValues) {
+ case 1:
+ limitsFlags |= (LIMITS_MIN_SET | LIMITS_MAX_SET);
+ values[1] = values[0]; /* Set minimum and maximum to value */
+ break;
+
+ case 2:
+ if (values[1] < values[0]) {
+ Tcl_AppendResult(interp, "bad range \"", Tcl_GetString(objPtr),
+ "\": min > max", (char *)NULL);
+ return TCL_ERROR; /* Minimum is greater than maximum */
+ }
+ break;
+
+ case 3:
+ if (values[1] < values[0]) {
+ Tcl_AppendResult(interp, "bad range \"", Tcl_GetString(objPtr),
+ "\": min > max", (char *)NULL);
+ return TCL_ERROR; /* Minimum is greater than maximum */
+ }
+ if ((values[2] < values[0]) || (values[2] > values[1])) {
+ Tcl_AppendResult(interp, "nominal value \"", Tcl_GetString(objPtr),
+ "\" out of range", (char *)NULL);
+ return TCL_ERROR; /* Nominal is outside of range defined
+ * by minimum and maximum */
+ }
+ break;
+ }
+ limitsPtr->min = values[0];
+ limitsPtr->max = values[1];
+ limitsPtr->nom = values[2];
+ limitsPtr->flags = limitsFlags;
+ return TCL_OK;
+}
+
+/* Configuration option helper routines */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * DoConfig --
+ *
+ * This procedure applies a single configuration option
+ * to a widget record.
+ *
+ * Results:
+ * A standard TCL return value.
+ *
+ * Side effects:
+ * WidgRec is modified as indicated by specPtr and value.
+ * The old value is recycled, if that is appropriate for
+ * the value type.
+ *
+ *---------------------------------------------------------------------------
+ */
+static int
+DoConfig(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Window containing widget (needed to
+ * set up X resources). */
+ Blt_ConfigSpec *sp, /* Specifier to apply. */
+ Tcl_Obj *objPtr, /* Value to use to fill in widgRec. */
+ char *widgRec) /* Record whose fields are to be
+ * modified. Values must be properly
+ * initialized. */
+{
+ char *ptr;
+ int objIsEmpty;
+
+ objIsEmpty = FALSE;
+ if (objPtr == NULL) {
+ objIsEmpty = TRUE;
+ } else if (sp->specFlags & BLT_CONFIG_NULL_OK) {
+ int length;
+
+ if (objPtr->bytes != NULL) {
+ length = objPtr->length;
+ } else {
+ Tcl_GetStringFromObj(objPtr, &length);
+ }
+ objIsEmpty = (length == 0);
+ }
+ do {
+ ptr = widgRec + sp->offset;
+ switch (sp->type) {
+ case BLT_CONFIG_ANCHOR:
+ {
+ Tk_Anchor anchor;
+
+ if (Tk_GetAnchorFromObj(interp, objPtr, &anchor) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(Tk_Anchor *)ptr = anchor;
+ }
+ break;
+
+ case BLT_CONFIG_BITMAP:
+ {
+ Pixmap bitmap;
+
+ if (objIsEmpty) {
+ bitmap = None;
+ } else {
+ bitmap = Tk_AllocBitmapFromObj(interp, tkwin, objPtr);
+ if (bitmap == None) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(Pixmap *)ptr != None) {
+ Tk_FreeBitmap(Tk_Display(tkwin), *(Pixmap *)ptr);
+ }
+ *(Pixmap *)ptr = bitmap;
+ }
+ break;
+
+ case BLT_CONFIG_BOOLEAN:
+ {
+ int bool;
+
+ if (Tcl_GetBooleanFromObj(interp, objPtr, &bool) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = bool;
+ }
+ break;
+
+ case BLT_CONFIG_BORDER:
+ {
+ Tk_3DBorder border;
+
+ if (objIsEmpty) {
+ border = NULL;
+ } else {
+ border = Tk_Alloc3DBorderFromObj(interp, tkwin, objPtr);
+ if (border == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(Tk_3DBorder *)ptr != NULL) {
+ Tk_Free3DBorder(*(Tk_3DBorder *)ptr);
+ }
+ *(Tk_3DBorder *)ptr = border;
+ }
+ break;
+
+ case BLT_CONFIG_CAP_STYLE:
+ {
+ int cap;
+ Tk_Uid uid;
+
+ uid = Tk_GetUid(Tcl_GetString(objPtr));
+ if (Tk_GetCapStyle(interp, uid, &cap) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = cap;
+ }
+ break;
+
+ case BLT_CONFIG_COLOR:
+ {
+ XColor *color;
+
+ if (objIsEmpty) {
+ color = NULL;
+ } else {
+ color = Tk_GetColor(interp, tkwin,
+ Tk_GetUid(Tcl_GetString(objPtr)));
+ if (color == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(XColor **)ptr != NULL) {
+ Tk_FreeColor(*(XColor **)ptr);
+ }
+ *(XColor **)ptr = color;
+ }
+ break;
+
+ case BLT_CONFIG_CURSOR:
+ case BLT_CONFIG_ACTIVE_CURSOR:
+ {
+ Tk_Cursor cursor;
+
+ if (objIsEmpty) {
+ cursor = None;
+ } else {
+ cursor = Tk_AllocCursorFromObj(interp, tkwin, objPtr);
+ if (cursor == None) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(Tk_Cursor *)ptr != None) {
+ Tk_FreeCursor(Tk_Display(tkwin), *(Tk_Cursor *)ptr);
+ }
+ *(Tk_Cursor *)ptr = cursor;
+ if (sp->type == BLT_CONFIG_ACTIVE_CURSOR) {
+ Tk_DefineCursor(tkwin, cursor);
+ }
+ }
+ break;
+
+ case BLT_CONFIG_CUSTOM:
+ if ((*sp->customPtr->parseProc)(sp->customPtr->clientData, interp,
+ tkwin, objPtr, widgRec, sp->offset, sp->specFlags) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_CONFIG_DOUBLE:
+ {
+ double value;
+
+ if (Tcl_GetDoubleFromObj(interp, objPtr, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(double *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_FONT:
+ {
+ Blt_Font font;
+
+ if (objIsEmpty) {
+ font = NULL;
+ } else {
+ font = Blt_AllocFontFromObj(interp, tkwin, objPtr);
+ if (font == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(Blt_Font *)ptr != NULL) {
+ Blt_FreeFont(*(Blt_Font *)ptr);
+ }
+ *(Blt_Font *)ptr = font;
+ }
+ break;
+
+ case BLT_CONFIG_TK_FONT:
+ {
+ Tk_Font font;
+
+ if (objIsEmpty) {
+ font = NULL;
+ } else {
+ font = Tk_AllocFontFromObj(interp, tkwin, objPtr);
+ if (font == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(Tk_Font *)ptr != NULL) {
+ Tk_FreeFont(*(Tk_Font *)ptr);
+ }
+ *(Tk_Font *)ptr = font;
+ }
+ break;
+
+ case BLT_CONFIG_INT:
+ {
+ int value;
+
+ if (Tcl_GetIntFromObj(interp, objPtr, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_JOIN_STYLE:
+ {
+ int join;
+ Tk_Uid uid;
+
+ uid = Tk_GetUid(Tcl_GetString(objPtr));
+ if (Tk_GetJoinStyle(interp, uid, &join) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = join;
+ }
+ break;
+
+ case BLT_CONFIG_JUSTIFY:
+ {
+ Tk_Justify justify;
+
+ if (Tk_GetJustifyFromObj(interp, objPtr, &justify) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(Tk_Justify *)ptr = justify;
+ }
+ break;
+
+ case BLT_CONFIG_MM:
+ {
+ double value;
+
+ if (Tk_GetMMFromObj(interp, tkwin, objPtr, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(double *)ptr = value;
+ }
+ break;
+
+
+ case BLT_CONFIG_RELIEF:
+ {
+ int relief;
+
+ if (Tk_GetReliefFromObj(interp, objPtr, &relief) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = relief;
+ }
+ break;
+
+ case BLT_CONFIG_STRING:
+ {
+ char *value;
+
+ value = (objIsEmpty) ? NULL :
+ Blt_AssertStrdup(Tcl_GetString(objPtr));
+ if (*(char **)ptr != NULL) {
+ Blt_Free(*(char **)ptr);
+ }
+ *(char **)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_UID:
+ if (*(Blt_Uid *)ptr != NULL) {
+ Blt_FreeUid(*(Blt_Uid *)ptr);
+ }
+ if (objIsEmpty) {
+ *(Blt_Uid *)ptr = NULL;
+ } else {
+ *(Blt_Uid *)ptr = Blt_GetUid(Tcl_GetString(objPtr));
+ }
+ break;
+
+ case BLT_CONFIG_WINDOW:
+ {
+ Tk_Window tkwin2;
+
+ if (objIsEmpty) {
+ tkwin2 = None;
+ } else {
+ const char *path;
+
+ path = Tcl_GetString(objPtr);
+ tkwin2 = Tk_NameToWindow(interp, path, tkwin);
+ if (tkwin2 == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ *(Tk_Window *)ptr = tkwin2;
+ }
+ break;
+
+ case BLT_CONFIG_BITMASK:
+ {
+ int bool;
+ unsigned long mask, flags;
+
+ if (Tcl_GetBooleanFromObj(interp, objPtr, &bool) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ mask = (unsigned long)sp->customPtr;
+ flags = *(int *)ptr;
+ flags &= ~mask;
+ if (bool) {
+ flags |= mask;
+ }
+ *(int *)ptr = flags;
+ }
+ break;
+
+ case BLT_CONFIG_BITMASK_INVERT:
+ {
+ int bool;
+ unsigned long mask, flags;
+
+ if (Tcl_GetBooleanFromObj(interp, objPtr, &bool) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ mask = (unsigned long)sp->customPtr;
+ flags = *(int *)ptr;
+ flags &= ~mask;
+ if (!bool) {
+ flags |= mask;
+ }
+ *(int *)ptr = flags;
+ }
+ break;
+
+ case BLT_CONFIG_DASHES:
+ if (Blt_GetDashesFromObj(interp, objPtr, (Blt_Dashes *)ptr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+
+ case BLT_CONFIG_FILL:
+ if (Blt_GetFillFromObj(interp, objPtr, (int *)ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_CONFIG_RESIZE:
+ if (Blt_GetResizeFromObj(interp, objPtr, (int *)ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_CONFIG_FLOAT:
+ {
+ double value;
+
+ if (Tcl_GetDoubleFromObj(interp, objPtr, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(float *)ptr = (float)value;
+ }
+ break;
+
+ case BLT_CONFIG_INT_NNEG:
+ {
+ long value;
+
+ if (Blt_GetCountFromObj(interp, objPtr, COUNT_NNEG,
+ &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = (int)value;
+ }
+ break;
+
+
+ case BLT_CONFIG_INT_POS:
+ {
+ long value;
+
+ if (Blt_GetCountFromObj(interp, objPtr, COUNT_POS, &value)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = (int)value;
+ }
+ break;
+
+
+ case BLT_CONFIG_LIST:
+ {
+ const char **argv;
+ int argc;
+
+ if (Tcl_SplitList(interp, Tcl_GetString(objPtr), &argc, &argv)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ if (*(char ***)ptr != NULL) {
+ Blt_Free(*(char ***)ptr);
+ }
+ *(const char ***)ptr = argv;
+ }
+ break;
+
+ case BLT_CONFIG_LONG:
+ {
+ long value;
+
+ if (Tcl_GetLongFromObj(interp, objPtr, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(long *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_LONG_NNEG:
+ {
+ long value;
+
+ if (Blt_GetCountFromObj(interp, objPtr, COUNT_NNEG,
+ &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(long *)ptr = value;
+ }
+ break;
+
+
+ case BLT_CONFIG_LONG_POS:
+ {
+ long value;
+
+ if (Blt_GetCountFromObj(interp, objPtr, COUNT_POS, &value)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(long *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_OBJ:
+ {
+ Tcl_IncrRefCount(objPtr);
+ if (*(Tcl_Obj **)ptr != NULL) {
+ Tcl_DecrRefCount(*(Tcl_Obj **)ptr);
+ }
+ *(Tcl_Obj **)ptr = objPtr;
+ }
+ break;
+
+ case BLT_CONFIG_PAD:
+ if (Blt_GetPadFromObj(interp, tkwin, objPtr, (Blt_Pad *)ptr)
+ != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_CONFIG_PIXELS_NNEG:
+ {
+ int value;
+
+ if (Blt_GetPixelsFromObj(interp, tkwin, objPtr,
+ PIXELS_NNEG, &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_PIXELS:
+ {
+ int value;
+
+ if (Blt_GetPixelsFromObj(interp, tkwin, objPtr, PIXELS_ANY,
+ &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_PIXELS_POS:
+ {
+ int value;
+
+ if (Blt_GetPixelsFromObj(interp, tkwin, objPtr, PIXELS_POS,
+ &value) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ *(int *)ptr = value;
+ }
+ break;
+
+ case BLT_CONFIG_STATE:
+ if (Blt_GetStateFromObj(interp, objPtr, (int *)ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_CONFIG_SIDE:
+ if (Blt_GetSideFromObj(interp, objPtr, (int *)ptr) != TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ case BLT_CONFIG_BACKGROUND:
+ {
+ Blt_Background style;
+
+ if (objIsEmpty) {
+ style = NULL;
+ } else {
+ style = Blt_GetBackgroundFromObj(interp, tkwin, objPtr);
+ if (style == NULL) {
+ return TCL_ERROR;
+ }
+ }
+ if (*(Blt_Background *)ptr != NULL) {
+ Blt_FreeBackground(*(Blt_Background *)ptr);
+ }
+ *(Blt_Background *)ptr = style;
+ }
+ break;
+
+ case BLT_CONFIG_PIX32:
+ if (Blt_GetPixelFromObj(interp, objPtr, (Blt_Pixel *)ptr)!=TCL_OK) {
+ return TCL_ERROR;
+ }
+ break;
+
+ default:
+ Tcl_AppendResult(interp, "bad config table: unknown type ",
+ Blt_Itoa(sp->type), (char *)NULL);
+ return TCL_ERROR;
+ }
+ sp++;
+ } while ((sp->switchName == NULL) && (sp->type != BLT_CONFIG_END));
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FormatConfigValue --
+ *
+ * This procedure formats the current value of a configuration
+ * option.
+ *
+ * Results:
+ * The return value is the formatted value of the option given
+ * by specPtr and widgRec. If the value is static, so that it
+ * need not be freed, *freeProcPtr will be set to NULL; otherwise
+ * *freeProcPtr will be set to the address of a procedure to
+ * free the result, and the caller must invoke this procedure
+ * when it is finished with the result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Tcl_Obj *
+FormatConfigValue(
+ Tcl_Interp *interp, /* Interpreter for use in real conversions. */
+ Tk_Window tkwin, /* Window corresponding to widget. */
+ Blt_ConfigSpec *sp, /* Pointer to information describing option.
+ * Must not point to a synonym option. */
+ char *widgRec) /* Pointer to record holding current
+ * values of info for widget. */
+{
+ char *ptr;
+ const char *string;
+
+ ptr = widgRec + sp->offset;
+ string = "";
+ switch (sp->type) {
+ case BLT_CONFIG_ANCHOR:
+ string = Tk_NameOfAnchor(*(Tk_Anchor *)ptr);
+ break;
+
+ case BLT_CONFIG_BITMAP:
+ if (*(Pixmap *)ptr != None) {
+ string = Tk_NameOfBitmap(Tk_Display(tkwin), *(Pixmap *)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_BOOLEAN:
+ return Tcl_NewBooleanObj(*(int *)ptr);
+
+ case BLT_CONFIG_BORDER:
+ if (*(Tk_3DBorder *)ptr != NULL) {
+ string = Tk_NameOf3DBorder(*(Tk_3DBorder *)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_CAP_STYLE:
+ string = Tk_NameOfCapStyle(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_COLOR:
+ if (*(XColor **)ptr != NULL) {
+ string = Tk_NameOfColor(*(XColor **)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_CURSOR:
+ case BLT_CONFIG_ACTIVE_CURSOR:
+ if (*(Tk_Cursor *)ptr != None) {
+ string = Tk_NameOfCursor(Tk_Display(tkwin), *(Tk_Cursor *)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_CUSTOM:
+ return (*sp->customPtr->printProc)
+ (sp->customPtr->clientData, interp, tkwin, widgRec,
+ sp->offset, sp->specFlags);
+
+ case BLT_CONFIG_DOUBLE:
+ return Tcl_NewDoubleObj(*(double *)ptr);
+
+ case BLT_CONFIG_FONT:
+ if (*(Blt_Font *)ptr != NULL) {
+ string = Blt_NameOfFont(*(Blt_Font *)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_TK_FONT:
+ if (*(Tk_Font *)ptr != NULL) {
+ string = Tk_NameOfFont(*(Tk_Font *)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_INT:
+ return Tcl_NewIntObj(*(int *)ptr);
+
+ case BLT_CONFIG_JOIN_STYLE:
+ string = Tk_NameOfJoinStyle(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_JUSTIFY:
+ string = Tk_NameOfJustify(*(Tk_Justify *)ptr);
+ break;
+
+ case BLT_CONFIG_MM:
+ return Tcl_NewDoubleObj(*(double *)ptr);
+
+ case BLT_CONFIG_PIXELS:
+ case BLT_CONFIG_PIXELS_POS:
+ case BLT_CONFIG_PIXELS_NNEG:
+ return Tcl_NewIntObj(*(int *)ptr);
+
+ case BLT_CONFIG_RELIEF:
+ string = Tk_NameOfRelief(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_STRING:
+ case BLT_CONFIG_UID:
+ if (*(char **)ptr != NULL) {
+ string = *(char **)ptr;
+ }
+ break;
+
+ case BLT_CONFIG_BITMASK:
+ {
+ unsigned long flag;
+
+ flag = (*(unsigned long *)ptr) & (unsigned long)sp->customPtr;
+ return Tcl_NewBooleanObj((flag != 0));
+ }
+
+ case BLT_CONFIG_BITMASK_INVERT:
+ {
+ unsigned long flag;
+
+ flag = (*(unsigned long *)ptr) & (unsigned long)sp->customPtr;
+ return Tcl_NewBooleanObj((flag == 0));
+ }
+
+ case BLT_CONFIG_DASHES:
+ {
+ unsigned char *p;
+ Tcl_Obj *listObjPtr;
+ Blt_Dashes *dashesPtr = (Blt_Dashes *)ptr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for(p = dashesPtr->values; *p != 0; p++) {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewIntObj(*p));
+ }
+ return listObjPtr;
+ }
+
+ case BLT_CONFIG_INT_NNEG:
+ case BLT_CONFIG_INT_POS:
+ return Tcl_NewIntObj(*(int *)ptr);
+
+ case BLT_CONFIG_FILL:
+ string = Blt_NameOfFill(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_RESIZE:
+ string = Blt_NameOfResize(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_FLOAT:
+ {
+ double x = *(float *)ptr;
+ return Tcl_NewDoubleObj(x);
+ }
+
+ case BLT_CONFIG_LIST:
+ {
+ Tcl_Obj *objPtr, *listObjPtr;
+ char *const *p;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (p = *(char ***)ptr; *p != NULL; p++) {
+ objPtr = Tcl_NewStringObj(*p, -1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ }
+ return listObjPtr;
+ }
+
+ case BLT_CONFIG_LONG:
+ return Tcl_NewLongObj(*(long *)ptr);
+
+ case BLT_CONFIG_LONG_NNEG:
+ case BLT_CONFIG_LONG_POS:
+ return Tcl_NewLongObj(*(long *)ptr);
+
+ case BLT_CONFIG_OBJ:
+ if (*(Tcl_Obj **)ptr != NULL) {
+ return *(Tcl_Obj **)ptr;
+ }
+ break;
+
+ case BLT_CONFIG_PAD:
+ {
+ Blt_Pad *padPtr = (Blt_Pad *)ptr;
+ Tcl_Obj *objPtr, *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ objPtr = Tcl_NewIntObj(padPtr->side1);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ objPtr = Tcl_NewIntObj(padPtr->side2);
+ Tcl_ListObjAppendElement(interp, listObjPtr, objPtr);
+ return listObjPtr;
+ }
+
+ case BLT_CONFIG_STATE:
+ string = Blt_NameOfState(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_SIDE:
+ string = Blt_NameOfSide(*(int *)ptr);
+ break;
+
+ case BLT_CONFIG_BACKGROUND:
+ if (*(Blt_Background *)ptr != NULL) {
+ string = Blt_NameOfBackground(*(Blt_Background *)ptr);
+ }
+ break;
+
+ case BLT_CONFIG_PIX32:
+ string = Blt_NameOfPixel((Blt_Pixel *)ptr);
+ break;
+
+ default:
+ string = "?? unknown type ??";
+ }
+ return Tcl_NewStringObj(string, -1);
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FormatConfigInfo --
+ *
+ * Create a valid TCL list holding the configuration information
+ * for a single configuration option.
+ *
+ * Results:
+ * A TCL list, dynamically allocated. The caller is expected to
+ * arrange for this list to be freed eventually.
+ *
+ * Side effects:
+ * Memory is allocated.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Tcl_Obj *
+FormatConfigInfo(
+ Tcl_Interp *interp, /* Interpreter to use for things
+ * like floating-point precision. */
+ Tk_Window tkwin, /* Window corresponding to widget. */
+ Blt_ConfigSpec *sp, /* Pointer to information describing
+ * option. */
+ char *widgRec) /* Pointer to record holding current
+ * values of info for widget. */
+{
+ Tcl_Obj *listObjPtr;
+
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ if (sp->switchName != NULL) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(sp->switchName, -1));
+ } else {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("", -1));
+ }
+ if (sp->dbName != NULL) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(sp->dbName, -1));
+ } else {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("", -1));
+ }
+ if (sp->type == BLT_CONFIG_SYNONYM) {
+ return listObjPtr;
+ }
+ if (sp->dbClass != NULL) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(sp->dbClass, -1));
+ } else {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("", -1));
+ }
+ if (sp->defValue != NULL) {
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ Tcl_NewStringObj(sp->defValue, -1));
+ } else {
+ Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj("", -1));
+ }
+ Tcl_ListObjAppendElement(interp, listObjPtr,
+ FormatConfigValue(interp, tkwin, sp, widgRec));
+ return listObjPtr;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * FindConfigSpec --
+ *
+ * Search through a table of configuration specs, looking for
+ * one that matches a given switchName.
+ *
+ * Results:
+ * The return value is a pointer to the matching entry, or NULL
+ * if nothing matched. In that case an error message is left
+ * in the interp's result.
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+static Blt_ConfigSpec *
+FindConfigSpec(
+ Tcl_Interp *interp, /* Used for reporting errors. */
+ Blt_ConfigSpec *specs, /* Pointer to table of configuration
+ * specifications for a widget. */
+ Tcl_Obj *objPtr, /* Name (suitable for use in a "config"
+ * command) identifying particular option. */
+ int needFlags, /* Flags that must be present in matching
+ * entry. */
+ int hateFlags) /* Flags that must NOT be present in
+ * matching entry. */
+{
+ Blt_ConfigSpec *matchPtr; /* Matching spec, or NULL. */
+ Blt_ConfigSpec *sp;
+ const char *string;
+ char c; /* First character of current argument. */
+ int length;
+
+ string = Tcl_GetStringFromObj(objPtr, &length);
+ c = string[1];
+ matchPtr = NULL;
+ for (sp = specs; sp->type != BLT_CONFIG_END; sp++) {
+ if (sp->switchName == NULL) {
+ continue;
+ }
+ if ((sp->switchName[1] != c) ||
+ (strncmp(sp->switchName, string, length) != 0)) {
+ continue;
+ }
+ if (((sp->specFlags & needFlags) != needFlags) ||
+ (sp->specFlags & hateFlags)) {
+ continue;
+ }
+ if (sp->switchName[length] == 0) {
+ matchPtr = sp;
+ goto gotMatch;
+ }
+ if (matchPtr != NULL) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "ambiguous option \"", string, "\"",
+ (char *)NULL);
+ }
+ return (Blt_ConfigSpec *)NULL;
+ }
+ matchPtr = sp;
+ }
+
+ if (matchPtr == NULL) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp, "unknown option \"", string, "\"",
+ (char *)NULL);
+ }
+ return (Blt_ConfigSpec *)NULL;
+ }
+
+ /*
+ * Found a matching entry. If it's a synonym, then find the
+ * entry that it's a synonym for.
+ */
+
+ gotMatch:
+ sp = matchPtr;
+ if (sp->type == BLT_CONFIG_SYNONYM) {
+ for (sp = specs; /*empty*/; sp++) {
+ if (sp->type == BLT_CONFIG_END) {
+ if (interp != NULL) {
+ Tcl_AppendResult(interp,
+ "couldn't find synonym for option \"", string, "\"",
+ (char *)NULL);
+ }
+ return (Blt_ConfigSpec *) NULL;
+ }
+ if ((sp->dbName == matchPtr->dbName) &&
+ (sp->type != BLT_CONFIG_SYNONYM) &&
+ ((sp->specFlags & needFlags) == needFlags) &&
+ !(sp->specFlags & hateFlags)) {
+ break;
+ }
+ }
+ }
+ return sp;
+}
+
+/* Public routines */
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ConfigureWidgetFromObj --
+ *
+ * Process command-line options and database options to
+ * fill in fields of a widget record with resources and
+ * other parameters.
+ *
+ * Results:
+ * A standard TCL return value. In case of an error,
+ * the interp's result will hold an error message.
+ *
+ * Side effects:
+ * The fields of widgRec get filled in with information
+ * from argc/argv and the option database. Old information
+ * in widgRec's fields gets recycled.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ConfigureWidgetFromObj(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Window containing widget (needed to
+ * set up X resources). */
+ Blt_ConfigSpec *specs, /* Describes legal options. */
+ int objc, /* Number of elements in argv. */
+ Tcl_Obj *const *objv, /* Command-line options. */
+ char *widgRec, /* Record whose fields are to be
+ * modified. Values must be properly
+ * initialized. */
+ int flags) /* Used to specify additional flags
+ * that must be present in config specs
+ * for them to be considered. Also,
+ * may have BLT_CONFIG_OBJV_ONLY set. */
+{
+ Blt_ConfigSpec *sp;
+ int needFlags; /* Specs must contain this set of flags
+ * or else they are not considered. */
+ int hateFlags; /* If a spec contains any bits here, it's
+ * not considered. */
+ int result;
+
+ if (tkwin == NULL) {
+ /*
+ * Either we're not really in Tk, or the main window was destroyed and
+ * we're on our way out of the application
+ */
+ Tcl_AppendResult(interp, "NULL main window", (char *)NULL);
+ return TCL_ERROR;
+ }
+
+ needFlags = flags & ~(BLT_CONFIG_USER_BIT - 1);
+ if (Tk_Depth(tkwin) <= 1) {
+ hateFlags = BLT_CONFIG_COLOR_ONLY;
+ } else {
+ hateFlags = BLT_CONFIG_MONO_ONLY;
+ }
+
+ /*
+ * Pass one: scan through all the option specs, replacing strings
+ * with Tk_Uid structs (if this hasn't been done already) and
+ * clearing the BLT_CONFIG_OPTION_SPECIFIED flags.
+ */
+
+ for (sp = specs; sp->type != BLT_CONFIG_END; sp++) {
+ if (!(sp->specFlags & INIT) && (sp->switchName != NULL)) {
+ if (sp->dbName != NULL) {
+ sp->dbName = Tk_GetUid(sp->dbName);
+ }
+ if (sp->dbClass != NULL) {
+ sp->dbClass = Tk_GetUid(sp->dbClass);
+ }
+ if (sp->defValue != NULL) {
+ sp->defValue = Tk_GetUid(sp->defValue);
+ }
+ }
+ sp->specFlags = (sp->specFlags & ~BLT_CONFIG_OPTION_SPECIFIED) | INIT;
+ }
+
+ /*
+ * Pass two: scan through all of the arguments, processing those
+ * that match entries in the specs.
+ */
+ while (objc > 0) {
+ sp = FindConfigSpec(interp, specs, objv[0], needFlags, hateFlags);
+ if (sp == NULL) {
+ return TCL_ERROR;
+ }
+
+ /* Process the entry. */
+ if (objc < 2) {
+ Tcl_AppendResult(interp, "value for \"", Tcl_GetString(objv[0]),
+ "\" missing", (char *)NULL);
+ return TCL_ERROR;
+ }
+ if (DoConfig(interp, tkwin, sp, objv[1], widgRec) != TCL_OK) {
+ char msg[100];
+
+ sprintf_s(msg, 100, "\n (processing \"%.40s\" option)",
+ sp->switchName);
+ Tcl_AddErrorInfo(interp, msg);
+ return TCL_ERROR;
+ }
+ sp->specFlags |= BLT_CONFIG_OPTION_SPECIFIED;
+ objc -= 2, objv += 2;
+ }
+
+ /*
+ * Pass three: scan through all of the specs again; if no
+ * command-line argument matched a spec, then check for info
+ * in the option database. If there was nothing in the
+ * database, then use the default.
+ */
+
+ if ((flags & BLT_CONFIG_OBJV_ONLY) == 0) {
+ Tcl_Obj *objPtr;
+
+ for (sp = specs; sp->type != BLT_CONFIG_END; sp++) {
+ if ((sp->specFlags & BLT_CONFIG_OPTION_SPECIFIED) ||
+ (sp->switchName == NULL) || (sp->type == BLT_CONFIG_SYNONYM)) {
+ continue;
+ }
+ if (((sp->specFlags & needFlags) != needFlags) ||
+ (sp->specFlags & hateFlags)) {
+ continue;
+ }
+ objPtr = NULL;
+ if (sp->dbName != NULL) {
+ Tk_Uid value;
+
+ /* If a resource name was specified, check if there's
+ * also a value was associated with it. This
+ * overrides the default value. */
+ value = Tk_GetOption(tkwin, sp->dbName, sp->dbClass);
+ if (value != NULL) {
+ objPtr = Tcl_NewStringObj(value, -1);
+ }
+ }
+
+ if (objPtr != NULL) {
+ Tcl_IncrRefCount(objPtr);
+ result = DoConfig(interp, tkwin, sp, objPtr, widgRec);
+ Tcl_DecrRefCount(objPtr);
+ if (result != TCL_OK) {
+ char msg[200];
+
+ sprintf_s(msg, 200,
+ "\n (%s \"%.50s\" in widget \"%.50s\")",
+ "database entry for", sp->dbName, Tk_PathName(tkwin));
+ Tcl_AddErrorInfo(interp, msg);
+ return TCL_ERROR;
+ }
+ } else if ((sp->defValue != NULL) &&
+ ((sp->specFlags & BLT_CONFIG_DONT_SET_DEFAULT) == 0)) {
+
+ /* No resource value is found, use the default value. */
+ objPtr = Tcl_NewStringObj(sp->defValue, -1);
+ Tcl_IncrRefCount(objPtr);
+ result = DoConfig(interp, tkwin, sp, objPtr, widgRec);
+ Tcl_DecrRefCount(objPtr);
+ if (result != TCL_OK) {
+ char msg[200];
+
+ sprintf_s(msg, 200,
+ "\n (%s \"%.50s\" in widget \"%.50s\")",
+ "default value for", sp->dbName, Tk_PathName(tkwin));
+ Tcl_AddErrorInfo(interp, msg);
+ return TCL_ERROR;
+ }
+ }
+ }
+ }
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ConfigureInfoFromObj --
+ *
+ * Return information about the configuration options
+ * for a window, and their current values.
+ *
+ * Results:
+ * Always returns TCL_OK. The interp's result will be modified
+ * hold a description of either a single configuration option
+ * available for "widgRec" via "specs", or all the configuration
+ * options available. In the "all" case, the result will
+ * available for "widgRec" via "specs". The result will
+ * be a list, each of whose entries describes one option.
+ * Each entry will itself be a list containing the option's
+ * name for use on command lines, database name, database
+ * class, default value, and current value (empty string
+ * if none). For options that are synonyms, the list will
+ * contain only two values: name and synonym name. If the
+ * "name" argument is non-NULL, then the only information
+ * returned is that for the named argument (i.e. the corresponding
+ * entry in the overall list is returned).
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+
+int
+Blt_ConfigureInfoFromObj(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Window corresponding to widgRec. */
+ Blt_ConfigSpec *specs, /* Describes legal options. */
+ char *widgRec, /* Record whose fields contain current
+ * values for options. */
+ Tcl_Obj *objPtr, /* If non-NULL, indicates a single option
+ * whose info is to be returned. Otherwise
+ * info is returned for all options. */
+ int flags) /* Used to specify additional flags
+ * that must be present in config specs
+ * for them to be considered. */
+{
+ Blt_ConfigSpec *sp;
+ Tcl_Obj *listObjPtr, *valueObjPtr;
+ const char *string;
+ int needFlags, hateFlags;
+
+ needFlags = flags & ~(BLT_CONFIG_USER_BIT - 1);
+ if (Tk_Depth(tkwin) <= 1) {
+ hateFlags = BLT_CONFIG_COLOR_ONLY;
+ } else {
+ hateFlags = BLT_CONFIG_MONO_ONLY;
+ }
+
+ /*
+ * If information is only wanted for a single configuration
+ * spec, then handle that one spec specially.
+ */
+
+ Tcl_SetResult(interp, (char *)NULL, TCL_STATIC);
+ if (objPtr != NULL) {
+ sp = FindConfigSpec(interp, specs, objPtr, needFlags, hateFlags);
+ if (sp == NULL) {
+ return TCL_ERROR;
+ }
+ valueObjPtr = FormatConfigInfo(interp, tkwin, sp, widgRec);
+ Tcl_SetObjResult(interp, valueObjPtr);
+ return TCL_OK;
+ }
+
+ /*
+ * Loop through all the specs, creating a big list with all
+ * their information.
+ */
+ string = NULL; /* Suppress compiler warning. */
+ if (objPtr != NULL) {
+ string = Tcl_GetString(objPtr);
+ }
+ listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **)NULL);
+ for (sp = specs; sp->type != BLT_CONFIG_END; sp++) {
+ if ((objPtr != NULL) && (sp->switchName != string)) {
+ continue;
+ }
+ if (((sp->specFlags & needFlags) != needFlags) ||
+ (sp->specFlags & hateFlags)) {
+ continue;
+ }
+ if (sp->switchName == NULL) {
+ continue;
+ }
+ valueObjPtr = FormatConfigInfo(interp, tkwin, sp, widgRec);
+ Tcl_ListObjAppendElement(interp, listObjPtr, valueObjPtr);
+ }
+ Tcl_SetObjResult(interp, listObjPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ConfigureValueFromObj --
+ *
+ * This procedure returns the current value of a configuration
+ * option for a widget.
+ *
+ * Results:
+ * The return value is a standard TCL completion code (TCL_OK or
+ * TCL_ERROR). The interp's result will be set to hold either the value
+ * of the option given by objPtr (if TCL_OK is returned) or
+ * an error message (if TCL_ERROR is returned).
+ *
+ * Side effects:
+ * None.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ConfigureValueFromObj(
+ Tcl_Interp *interp, /* Interpreter for error reporting. */
+ Tk_Window tkwin, /* Window corresponding to widgRec. */
+ Blt_ConfigSpec *specs, /* Describes legal options. */
+ char *widgRec, /* Record whose fields contain current
+ * values for options. */
+ Tcl_Obj *objPtr, /* Gives the command-line name for the
+ * option whose value is to be returned. */
+ int flags) /* Used to specify additional flags
+ * that must be present in config specs
+ * for them to be considered. */
+{
+ Blt_ConfigSpec *sp;
+ int needFlags, hateFlags;
+
+ needFlags = flags & ~(BLT_CONFIG_USER_BIT - 1);
+ if (Tk_Depth(tkwin) <= 1) {
+ hateFlags = BLT_CONFIG_COLOR_ONLY;
+ } else {
+ hateFlags = BLT_CONFIG_MONO_ONLY;
+ }
+ sp = FindConfigSpec(interp, specs, objPtr, needFlags, hateFlags);
+ if (sp == NULL) {
+ return TCL_ERROR;
+ }
+ objPtr = FormatConfigValue(interp, tkwin, sp, widgRec);
+ Tcl_SetObjResult(interp, objPtr);
+ return TCL_OK;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_FreeOptions --
+ *
+ * Free up all resources associated with configuration options.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Any resource in widgRec that is controlled by a configuration
+ * option (e.g. a Tk_3DBorder or XColor) is freed in the appropriate
+ * fashion.
+ *
+ *---------------------------------------------------------------------------
+ */
+void
+Blt_FreeOptions(
+ Blt_ConfigSpec *specs, /* Describes legal options. */
+ char *widgRec, /* Record whose fields contain current
+ * values for options. */
+ Display *display, /* X display; needed for freeing some
+ * resources. */
+ int needFlags) /* Used to specify additional flags
+ * that must be present in config specs
+ * for them to be considered. */
+{
+ Blt_ConfigSpec *sp;
+
+ for (sp = specs; sp->type != BLT_CONFIG_END; sp++) {
+ char *ptr;
+
+ if ((sp->specFlags & needFlags) != needFlags) {
+ continue;
+ }
+ ptr = widgRec + sp->offset;
+ switch (sp->type) {
+ case BLT_CONFIG_STRING:
+ if (*((char **) ptr) != NULL) {
+ Blt_Free(*((char **) ptr));
+ *((char **) ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_COLOR:
+ if (*((XColor **) ptr) != NULL) {
+ Tk_FreeColor(*((XColor **) ptr));
+ *((XColor **) ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_FONT:
+ if (*((Blt_Font *) ptr) != None) {
+ Blt_FreeFont(*((Blt_Font *) ptr));
+ *((Blt_Font *) ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_TK_FONT:
+ if (*((Tk_Font *) ptr) != None) {
+ Tk_FreeFont(*((Tk_Font *) ptr));
+ *((Tk_Font *) ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_BITMAP:
+ if (*((Pixmap *) ptr) != None) {
+ Tk_FreeBitmap(display, *((Pixmap *) ptr));
+ *((Pixmap *) ptr) = None;
+ }
+ break;
+
+ case BLT_CONFIG_BORDER:
+ if (*((Tk_3DBorder *) ptr) != NULL) {
+ Tk_Free3DBorder(*((Tk_3DBorder *) ptr));
+ *((Tk_3DBorder *) ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_CURSOR:
+ case BLT_CONFIG_ACTIVE_CURSOR:
+ if (*((Tk_Cursor *) ptr) != None) {
+ Tk_FreeCursor(display, *((Tk_Cursor *) ptr));
+ *((Tk_Cursor *) ptr) = None;
+ }
+ break;
+
+ case BLT_CONFIG_OBJ:
+ if (*(Tcl_Obj **)ptr != NULL) {
+ Tcl_DecrRefCount(*(Tcl_Obj **)ptr);
+ *(Tcl_Obj **)ptr = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_LIST:
+ if (*((char ***) ptr) != NULL) {
+ Blt_Free(*((char ***) ptr));
+ *((char ***) ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_UID:
+ if (*(Blt_Uid *)ptr != NULL) {
+ Blt_FreeUid(*(Blt_Uid *)ptr);
+ *(Blt_Uid *)ptr = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_BACKGROUND:
+ if (*((Blt_Background *)ptr) != NULL) {
+ Blt_FreeBackground(*((Blt_Background *)ptr));
+ *((Blt_Background *)ptr) = NULL;
+ }
+ break;
+
+ case BLT_CONFIG_CUSTOM:
+ if ((sp->customPtr->freeProc != NULL) && (*(char **)ptr != NULL)) {
+ (*sp->customPtr->freeProc)(sp->customPtr->clientData,
+ display, widgRec, sp->offset);
+ }
+ break;
+
+ }
+ }
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ConfigModified --
+ *
+ * Given the configuration specifications and one or more option
+ * patterns (terminated by a NULL), indicate if any of the matching
+ * configuration options has been reset.
+ *
+ * Results:
+ * Returns 1 if one of the options has changed, 0 otherwise.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ConfigModified TCL_VARARGS_DEF(Blt_ConfigSpec *, arg1)
+{
+ va_list argList;
+ Blt_ConfigSpec *specs;
+ Blt_ConfigSpec *sp;
+ const char *option;
+
+ specs = TCL_VARARGS_START(Blt_ConfigSpec *, arg1, argList);
+ while ((option = va_arg(argList, const char *)) != NULL) {
+ for (sp = specs; sp->type != BLT_CONFIG_END; sp++) {
+ if ((Tcl_StringMatch(sp->switchName, option)) &&
+ (sp->specFlags & BLT_CONFIG_OPTION_SPECIFIED)) {
+ va_end(argList);
+ return 1;
+ }
+ }
+ }
+ va_end(argList);
+ return 0;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ConfigureComponentFromObj --
+ *
+ * Configures a component of a widget. This is useful for
+ * widgets that have multiple components which aren't uniquely
+ * identified by a Tk_Window. It allows us, for example, set
+ * resources for axes of the graph widget. The graph really has
+ * only one window, but its convenient to specify components in a
+ * hierarchy of options.
+ *
+ * *graph.x.logScale yes
+ * *graph.Axis.logScale yes
+ * *graph.temperature.scaleSymbols yes
+ * *graph.Element.scaleSymbols yes
+ *
+ * This is really a hack to work around the limitations of the Tk
+ * resource database. It creates a temporary window, needed to
+ * call Tk_ConfigureWidget, using the name of the component.
+ *
+ * Results:
+ * A standard TCL result.
+ *
+ * Side Effects:
+ * A temporary window is created merely to pass to Tk_ConfigureWidget.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ConfigureComponentFromObj(
+ Tcl_Interp *interp,
+ Tk_Window parent, /* Window to associate with component */
+ const char *name, /* Name of component */
+ const char *className,
+ Blt_ConfigSpec *sp,
+ int objc,
+ Tcl_Obj *const *objv,
+ char *widgRec,
+ int flags)
+{
+ Tk_Window tkwin;
+ int result;
+ char *tmpName;
+ int isTemporary = FALSE;
+
+ tmpName = Blt_AssertStrdup(name);
+
+ /* Window name can't start with an upper case letter */
+ tmpName[0] = tolower(name[0]);
+
+ /*
+ * Create component if a child window by the component's name
+ * doesn't already exist.
+ */
+ tkwin = Blt_FindChild(parent, tmpName);
+ if (tkwin == NULL) {
+ tkwin = Tk_CreateWindow(interp, parent, tmpName, (char *)NULL);
+ isTemporary = TRUE;
+ }
+ if (tkwin == NULL) {
+ Tcl_AppendResult(interp, "can't find window in \"",
+ Tk_PathName(parent), "\"", (char *)NULL);
+ return TCL_ERROR;
+ }
+ assert(Tk_Depth(tkwin) == Tk_Depth(parent));
+ Blt_Free(tmpName);
+
+ Tk_SetClass(tkwin, className);
+ result = Blt_ConfigureWidgetFromObj(interp, tkwin, sp, objc, objv, widgRec,
+ flags);
+ if (isTemporary) {
+ Tk_DestroyWindow(tkwin);
+ }
+ return result;
+}
+
+/*
+ *---------------------------------------------------------------------------
+ *
+ * Blt_ObjIsOption --
+ *
+ * Indicates whether objPtr is a valid configuration option
+ * such as -background.
+ *
+ * Results:
+ * Returns 1 is a matching option is found and 0 otherwise.
+ *
+ *---------------------------------------------------------------------------
+ */
+int
+Blt_ObjIsOption(
+ Blt_ConfigSpec *specs, /* Describes legal options. */
+ Tcl_Obj *objPtr, /* Command-line option name. */
+ int flags) /* Used to specify additional flags
+ * that must be present in config specs
+ * for them to be considered. Also,
+ * may have BLT_CONFIG_OBJV_ONLY set. */
+{
+ Blt_ConfigSpec *sp;
+ int needFlags; /* Specs must contain this set of flags
+ * or else they are not considered. */
+
+ needFlags = flags & ~(BLT_CONFIG_USER_BIT - 1);
+ sp = FindConfigSpec((Tcl_Interp *)NULL, specs, objPtr, needFlags, 0);
+ return (sp != NULL);
+}