diff options
Diffstat (limited to 'tk/generic/tkOption.c')
-rw-r--r-- | tk/generic/tkOption.c | 429 |
1 files changed, 243 insertions, 186 deletions
diff --git a/tk/generic/tkOption.c b/tk/generic/tkOption.c index f3807167edb..54e1f27d75e 100644 --- a/tk/generic/tkOption.c +++ b/tk/generic/tkOption.c @@ -6,7 +6,7 @@ * with windows either by name or by class or both. * * Copyright (c) 1990-1994 The Regents of the University of California. - * Copyright (c) 1994-1996 Sun Microsystems, Inc. + * 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. @@ -141,13 +141,6 @@ typedef struct ElArray { */ #define NUM_STACKS 8 -static ElArray *stacks[NUM_STACKS]; -static TkWindow *cachedWindow = NULL; /* Lowest-level window currently - * loaded in stacks at present. - * NULL means stacks have never - * been used, or have been - * invalidated because of a change - * to the database. */ /* * One of the following structures is used to keep track of each @@ -163,33 +156,41 @@ typedef struct StackLevel { * fields when popping out of a level. */ } StackLevel; -/* - * Information about all of the stack levels that are currently - * active. This array grows dynamically to become as large as needed. - */ +typedef struct ThreadSpecificData { + int initialized; /* 0 means the ThreadSpecific Data structure + * for the current thread needs to be + * initialized. */ + ElArray *stacks[NUM_STACKS]; + TkWindow *cachedWindow; + /* Lowest-level window currently + * loaded in stacks at present. + * NULL means stacks have never + * been used, or have been + * invalidated because of a change + * to the database. */ + /* + * Information about all of the stack levels that are currently + * active. This array grows dynamically to become as large as needed. + */ -static StackLevel *levels = NULL; - /* Array describing current stack. */ -static int numLevels = 0; /* Total space allocated. */ -static int curLevel = -1; /* Highest level currently in use. Note: + StackLevel *levels; /* Array describing current stack. */ + int numLevels; /* Total space allocated. */ + int curLevel; /* Highest level currently in use. Note: * curLevel is never 0! (I don't remember * why anymore...) */ + /* + * The variable below is a serial number for all options entered into + * the database so far. It increments on each addition to the option + * database. It is used in computing option priorities, so that the + * most recent entry wins when choosing between options at the same + * priority level. + */ -/* - * The variable below is a serial number for all options entered into - * the database so far. It increments on each addition to the option - * database. It is used in computing option priorities, so that the - * most recent entry wins when choosing between options at the same - * priority level. - */ - -static int serial = 0; - -/* - * Special "no match" Element to use as default for searches. - */ - -static Element defaultMatch; + int serial; + Element defaultMatch; /* Special "no match" Element to use as + * default for searches.*/ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * Forward declarations for procedures defined in this file: @@ -248,11 +249,13 @@ Tk_AddOption(tkwin, name, value, priority) int count, firstField, length; #define TMP_SIZE 100 char tmp[TMP_SIZE+1]; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr->mainPtr->optionRootPtr == NULL) { OptionInit(winPtr->mainPtr); } - cachedWindow = NULL; /* Invalidate the cache. */ + tsdPtr->cachedWindow = NULL; /* Invalidate the cache. */ /* * Compute the priority for the new element, including both the @@ -265,8 +268,8 @@ Tk_AddOption(tkwin, name, value, priority) } else if (priority > TK_MAX_PRIO) { priority = TK_MAX_PRIO; } - newEl.priority = (priority << 24) + serial; - serial++; + newEl.priority = (priority << 24) + tsdPtr->serial; + tsdPtr->serial++; /* * Parse the option one field at a time. @@ -396,28 +399,30 @@ Tk_GetOption(tkwin, name, className) Tk_Uid nameId, classId; register Element *elPtr, *bestPtr; register int count; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Note: no need to call OptionInit here: it will be done by * the SetupStacks call below (squeeze out those nanoseconds). */ - if (tkwin != (Tk_Window) cachedWindow) { + if (tkwin != (Tk_Window) tsdPtr->cachedWindow) { SetupStacks((TkWindow *) tkwin, 1); } nameId = Tk_GetUid(name); - bestPtr = &defaultMatch; - for (elPtr = stacks[EXACT_LEAF_NAME]->els, - count = stacks[EXACT_LEAF_NAME]->numUsed; count > 0; + bestPtr = &tsdPtr->defaultMatch; + for (elPtr = tsdPtr->stacks[EXACT_LEAF_NAME]->els, + count = tsdPtr->stacks[EXACT_LEAF_NAME]->numUsed; count > 0; elPtr++, count--) { if ((elPtr->nameUid == nameId) && (elPtr->priority > bestPtr->priority)) { bestPtr = elPtr; } } - for (elPtr = stacks[WILDCARD_LEAF_NAME]->els, - count = stacks[WILDCARD_LEAF_NAME]->numUsed; count > 0; + for (elPtr = tsdPtr->stacks[WILDCARD_LEAF_NAME]->els, + count = tsdPtr->stacks[WILDCARD_LEAF_NAME]->numUsed; count > 0; elPtr++, count--) { if ((elPtr->nameUid == nameId) && (elPtr->priority > bestPtr->priority)) { @@ -426,17 +431,17 @@ Tk_GetOption(tkwin, name, className) } if (className != NULL) { classId = Tk_GetUid(className); - for (elPtr = stacks[EXACT_LEAF_CLASS]->els, - count = stacks[EXACT_LEAF_CLASS]->numUsed; count > 0; + for (elPtr = tsdPtr->stacks[EXACT_LEAF_CLASS]->els, + count = tsdPtr->stacks[EXACT_LEAF_CLASS]->numUsed; count > 0; elPtr++, count--) { if ((elPtr->nameUid == classId) && (elPtr->priority > bestPtr->priority)) { bestPtr = elPtr; } } - for (elPtr = stacks[WILDCARD_LEAF_CLASS]->els, - count = stacks[WILDCARD_LEAF_CLASS]->numUsed; count > 0; - elPtr++, count--) { + for (elPtr = tsdPtr->stacks[WILDCARD_LEAF_CLASS]->els, + count = tsdPtr->stacks[WILDCARD_LEAF_CLASS]->numUsed; + count > 0; elPtr++, count--) { if ((elPtr->nameUid == classId) && (elPtr->priority > bestPtr->priority)) { bestPtr = elPtr; @@ -449,7 +454,7 @@ Tk_GetOption(tkwin, name, className) /* *-------------------------------------------------------------- * - * Tk_OptionCmd -- + * Tk_OptionObjCmd -- * * This procedure is invoked to process the "option" Tcl command. * See the user documentation for details on what it does. @@ -464,98 +469,117 @@ Tk_GetOption(tkwin, name, className) */ int -Tk_OptionCmd(clientData, interp, argc, argv) +Tk_OptionObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Main window associated with * interpreter. */ Tcl_Interp *interp; /* Current interpreter. */ - int argc; /* Number of arguments. */ - char **argv; /* Argument strings. */ + int objc; /* Number of Tcl_Obj arguments. */ + Tcl_Obj *CONST objv[]; /* Tcl_Obj arguments. */ { Tk_Window tkwin = (Tk_Window) clientData; - size_t length; - char c; + int index, result; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + static char *optionCmds[] = { + "add", "clear", "get", "readfile", NULL + }; - if (argc < 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], - " cmd arg ?arg ...?\"", (char *) NULL); + enum optionVals { + OPTION_ADD, OPTION_CLEAR, OPTION_GET, OPTION_READFILE + }; + + if (objc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "cmd arg ?arg ...?"); return TCL_ERROR; } - c = argv[1][0]; - length = strlen(argv[1]); - if ((c == 'a') && (strncmp(argv[1], "add", length) == 0)) { - int priority; - - if ((argc != 4) && (argc != 5)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " add pattern value ?priority?\"", (char *) NULL); - return TCL_ERROR; - } - if (argc == 4) { - priority = TK_INTERACTIVE_PRIO; - } else { - priority = ParsePriority(interp, argv[4]); - if (priority < 0) { + + result = Tcl_GetIndexFromObj(interp, objv[1], optionCmds, "option", 0, + &index); + if (result != TCL_OK) { + return result; + } + + result = TCL_OK; + switch ((enum optionVals) index) { + case OPTION_ADD: { + int priority; + if ((objc != 4) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "pattern value ?priority?"); return TCL_ERROR; } + + if (objc == 4) { + priority = TK_INTERACTIVE_PRIO; + } else { + priority = ParsePriority(interp, Tcl_GetString(objv[4])); + if (priority < 0) { + return TCL_ERROR; + } + } + Tk_AddOption(tkwin, Tcl_GetString(objv[2]), + Tcl_GetString(objv[3]), priority); + break; } - Tk_AddOption(tkwin, argv[2], argv[3], priority); - return TCL_OK; - } else if ((c == 'c') && (strncmp(argv[1], "clear", length) == 0)) { - TkMainInfo *mainPtr; - - if (argc != 2) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " clear\"", (char *) NULL); - return TCL_ERROR; - } - mainPtr = ((TkWindow *) tkwin)->mainPtr; - if (mainPtr->optionRootPtr != NULL) { - ClearOptionTree(mainPtr->optionRootPtr); - mainPtr->optionRootPtr = NULL; - } - cachedWindow = NULL; - return TCL_OK; - } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) { - Tk_Window window; - Tk_Uid value; - - if (argc != 5) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " get window name class\"", (char *) NULL); - return TCL_ERROR; - } - window = Tk_NameToWindow(interp, argv[2], tkwin); - if (window == NULL) { - return TCL_ERROR; - } - value = Tk_GetOption(window, argv[3], argv[4]); - if (value != NULL) { - interp->result = value; + + case OPTION_CLEAR: { + TkMainInfo *mainPtr; + + if (objc != 2) { + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + mainPtr = ((TkWindow *) tkwin)->mainPtr; + if (mainPtr->optionRootPtr != NULL) { + ClearOptionTree(mainPtr->optionRootPtr); + mainPtr->optionRootPtr = NULL; + } + tsdPtr->cachedWindow = NULL; + break; } - return TCL_OK; - } else if ((c == 'r') && (strncmp(argv[1], "readfile", length) == 0)) { - int priority; - if ((argc != 3) && (argc != 4)) { - Tcl_AppendResult(interp, "wrong # args: should be \"", - argv[0], " readfile fileName ?priority?\"", - (char *) NULL); - return TCL_ERROR; + case OPTION_GET: { + Tk_Window window; + Tk_Uid value; + + if (objc != 5) { + Tcl_WrongNumArgs(interp, 2, objv, "window name class"); + return TCL_ERROR; + } + window = Tk_NameToWindow(interp, Tcl_GetString(objv[2]), tkwin); + if (window == NULL) { + return TCL_ERROR; + } + value = Tk_GetOption(window, Tcl_GetString(objv[3]), + Tcl_GetString(objv[4])); + if (value != NULL) { + Tcl_SetResult(interp, value, TCL_STATIC); + } + break; } - if (argc == 4) { - priority = ParsePriority(interp, argv[3]); - if (priority < 0) { + + case OPTION_READFILE: { + int priority; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "fileName ?priority?"); return TCL_ERROR; } - } else { - priority = TK_INTERACTIVE_PRIO; + + if (objc == 4) { + priority = ParsePriority(interp, Tcl_GetString(objv[3])); + if (priority < 0) { + return TCL_ERROR; + } + } else { + priority = TK_INTERACTIVE_PRIO; + } + result = ReadOptionFile(interp, tkwin, Tcl_GetString(objv[2]), + priority); + break; } - return ReadOptionFile(interp, tkwin, argv[2], priority); - } else { - Tcl_AppendResult(interp, "bad option \"", argv[1], - "\": must be add, clear, get, or readfile", (char *) NULL); - return TCL_ERROR; } + return result; } /* @@ -581,6 +605,9 @@ void TkOptionDeadWindow(winPtr) register TkWindow *winPtr; /* Window to be cleaned up. */ { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + /* * If this window is in the option stacks, then clear the stacks. */ @@ -588,11 +615,11 @@ TkOptionDeadWindow(winPtr) if (winPtr->optionLevel != -1) { int i; - for (i = 1; i <= curLevel; i++) { - levels[i].winPtr->optionLevel = -1; + for (i = 1; i <= tsdPtr->curLevel; i++) { + tsdPtr->levels[i].winPtr->optionLevel = -1; } - curLevel = -1; - cachedWindow = NULL; + tsdPtr->curLevel = -1; + tsdPtr->cachedWindow = NULL; } /* @@ -632,6 +659,8 @@ TkOptionClassChanged(winPtr) { int i, j, *basePtr; ElArray *arrayPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr->optionLevel == -1) { return; @@ -642,22 +671,22 @@ TkOptionClassChanged(winPtr) * flush all of the levels above the matching one. */ - for (i = 1; i <= curLevel; i++) { - if (levels[i].winPtr == winPtr) { - for (j = i; j <= curLevel; j++) { - levels[j].winPtr->optionLevel = -1; + for (i = 1; i <= tsdPtr->curLevel; i++) { + if (tsdPtr->levels[i].winPtr == winPtr) { + for (j = i; j <= tsdPtr->curLevel; j++) { + tsdPtr->levels[j].winPtr->optionLevel = -1; } - curLevel = i-1; - basePtr = levels[i].bases; + tsdPtr->curLevel = i-1; + basePtr = tsdPtr->levels[i].bases; for (j = 0; j < NUM_STACKS; j++) { - arrayPtr = stacks[j]; + arrayPtr = tsdPtr->stacks[j]; arrayPtr->numUsed = basePtr[j]; arrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed]; } - if (curLevel <= 0) { - cachedWindow = NULL; + if (tsdPtr->curLevel <= 0) { + tsdPtr->cachedWindow = NULL; } else { - cachedWindow = levels[curLevel].winPtr; + tsdPtr->cachedWindow = tsdPtr->levels[tsdPtr->curLevel].winPtr; } break; } @@ -674,7 +703,7 @@ TkOptionClassChanged(winPtr) * Results: * The return value is the integer priority level corresponding * to string, or -1 if string doesn't point to a valid priority level. - * In this case, an error message is left in interp->result. + * In this case, an error message is left in the interp's result. * * Side effects: * None. @@ -734,7 +763,7 @@ ParsePriority(interp, string) * Results: * The return value is a standard Tcl return code. In the case of * an error in parsing string, TCL_ERROR will be returned and an - * error message will be left in interp->result. The memory at + * error message will be left in the interp's result. The memory at * string is totally trashed by this procedure. If you care about * its contents, make a copy before calling here. * @@ -797,8 +826,10 @@ AddFromString(interp, tkwin, string, priority) dst = name = src; while (*src != ':') { if ((*src == '\0') || (*src == '\n')) { - sprintf(interp->result, "missing colon on line %d", - lineNum); + char buf[32 + TCL_INTEGER_SPACE]; + + sprintf(buf, "missing colon on line %d", lineNum); + Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; } if ((src[0] == '\\') && (src[1] == '\n')) { @@ -830,7 +861,10 @@ AddFromString(interp, tkwin, string, priority) src++; } if (*src == '\0') { - sprintf(interp->result, "missing value on line %d", lineNum); + char buf[32 + TCL_INTEGER_SPACE]; + + sprintf(buf, "missing value on line %d", lineNum); + Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; } @@ -842,8 +876,10 @@ AddFromString(interp, tkwin, string, priority) dst = value = src; while (*src != '\n') { if (*src == '\0') { - sprintf(interp->result, "missing newline on line %d", - lineNum); + char buf[32 + TCL_INTEGER_SPACE]; + + sprintf(buf, "missing newline on line %d", lineNum); + Tcl_SetResult(interp, buf, TCL_VOLATILE); return TCL_ERROR; } if ((src[0] == '\\') && (src[1] == '\n')) { @@ -879,7 +915,7 @@ AddFromString(interp, tkwin, string, priority) * Results: * The return value is a standard Tcl return code. In the case of * an error in parsing string, TCL_ERROR will be returned and an - * error message will be left in interp->result. + * error message will be left in the interp's result. * * Side effects: * None. @@ -1062,6 +1098,8 @@ SetupStacks(winPtr, leaf) int level, i, *iPtr; register StackLevel *levelPtr; register ElArray *arrayPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * The following array defines the order in which the current @@ -1086,7 +1124,7 @@ SetupStacks(winPtr, leaf) if (winPtr->parentPtr != NULL) { level = winPtr->parentPtr->optionLevel; - if ((level == -1) || (cachedWindow == NULL)) { + if ((level == -1) || (tsdPtr->cachedWindow == NULL)) { SetupStacks(winPtr->parentPtr, 0); level = winPtr->parentPtr->optionLevel; } @@ -1100,19 +1138,19 @@ SetupStacks(winPtr, leaf) * mark those windows as no longer having cached information. */ - if (curLevel >= level) { - while (curLevel >= level) { - levels[curLevel].winPtr->optionLevel = -1; - curLevel--; + if (tsdPtr->curLevel >= level) { + while (tsdPtr->curLevel >= level) { + tsdPtr->levels[tsdPtr->curLevel].winPtr->optionLevel = -1; + tsdPtr->curLevel--; } - levelPtr = &levels[level]; + levelPtr = &tsdPtr->levels[level]; for (i = 0; i < NUM_STACKS; i++) { - arrayPtr = stacks[i]; + arrayPtr = tsdPtr->stacks[i]; arrayPtr->numUsed = levelPtr->bases[i]; arrayPtr->nextToUse = &arrayPtr->els[arrayPtr->numUsed]; } } - curLevel = winPtr->optionLevel = level; + tsdPtr->curLevel = winPtr->optionLevel = level; /* * Step 3: if the root database information isn't loaded or @@ -1120,11 +1158,11 @@ SetupStacks(winPtr, leaf) * database root (this only happens if winPtr is a main window). */ - if ((curLevel == 1) - && ((cachedWindow == NULL) - || (cachedWindow->mainPtr != winPtr->mainPtr))) { + if ((tsdPtr->curLevel == 1) + && ((tsdPtr->cachedWindow == NULL) + || (tsdPtr->cachedWindow->mainPtr != winPtr->mainPtr))) { for (i = 0; i < NUM_STACKS; i++) { - arrayPtr = stacks[i]; + arrayPtr = tsdPtr->stacks[i]; arrayPtr->numUsed = 0; arrayPtr->nextToUse = arrayPtr->els; } @@ -1138,33 +1176,41 @@ SetupStacks(winPtr, leaf) * any more). */ - if (curLevel >= numLevels) { + if (tsdPtr->curLevel >= tsdPtr->numLevels) { StackLevel *newLevels; newLevels = (StackLevel *) ckalloc((unsigned) - (numLevels*2*sizeof(StackLevel))); - memcpy((VOID *) newLevels, (VOID *) levels, - (numLevels*sizeof(StackLevel))); - ckfree((char *) levels); - numLevels *= 2; - levels = newLevels; + (tsdPtr->numLevels*2*sizeof(StackLevel))); + memcpy((VOID *) newLevels, (VOID *) tsdPtr->levels, + (tsdPtr->numLevels*sizeof(StackLevel))); + ckfree((char *) tsdPtr->levels); + tsdPtr->numLevels *= 2; + tsdPtr->levels = newLevels; } - levelPtr = &levels[curLevel]; + levelPtr = &tsdPtr->levels[tsdPtr->curLevel]; levelPtr->winPtr = winPtr; - arrayPtr = stacks[EXACT_LEAF_NAME]; + arrayPtr = tsdPtr->stacks[EXACT_LEAF_NAME]; arrayPtr->numUsed = 0; arrayPtr->nextToUse = arrayPtr->els; - arrayPtr = stacks[EXACT_LEAF_CLASS]; + arrayPtr = tsdPtr->stacks[EXACT_LEAF_CLASS]; arrayPtr->numUsed = 0; arrayPtr->nextToUse = arrayPtr->els; - levelPtr->bases[EXACT_LEAF_NAME] = stacks[EXACT_LEAF_NAME]->numUsed; - levelPtr->bases[EXACT_LEAF_CLASS] = stacks[EXACT_LEAF_CLASS]->numUsed; - levelPtr->bases[EXACT_NODE_NAME] = stacks[EXACT_NODE_NAME]->numUsed; - levelPtr->bases[EXACT_NODE_CLASS] = stacks[EXACT_NODE_CLASS]->numUsed; - levelPtr->bases[WILDCARD_LEAF_NAME] = stacks[WILDCARD_LEAF_NAME]->numUsed; - levelPtr->bases[WILDCARD_LEAF_CLASS] = stacks[WILDCARD_LEAF_CLASS]->numUsed; - levelPtr->bases[WILDCARD_NODE_NAME] = stacks[WILDCARD_NODE_NAME]->numUsed; - levelPtr->bases[WILDCARD_NODE_CLASS] = stacks[WILDCARD_NODE_CLASS]->numUsed; + levelPtr->bases[EXACT_LEAF_NAME] = tsdPtr->stacks[EXACT_LEAF_NAME] + ->numUsed; + levelPtr->bases[EXACT_LEAF_CLASS] = tsdPtr->stacks[EXACT_LEAF_CLASS] + ->numUsed; + levelPtr->bases[EXACT_NODE_NAME] = tsdPtr->stacks[EXACT_NODE_NAME] + ->numUsed; + levelPtr->bases[EXACT_NODE_CLASS] = tsdPtr->stacks[EXACT_NODE_CLASS] + ->numUsed; + levelPtr->bases[WILDCARD_LEAF_NAME] = tsdPtr->stacks[WILDCARD_LEAF_NAME] + ->numUsed; + levelPtr->bases[WILDCARD_LEAF_CLASS] = tsdPtr->stacks[WILDCARD_LEAF_CLASS] + ->numUsed; + levelPtr->bases[WILDCARD_NODE_NAME] = tsdPtr->stacks[WILDCARD_NODE_NAME] + ->numUsed; + levelPtr->bases[WILDCARD_NODE_CLASS] = tsdPtr->stacks[WILDCARD_NODE_CLASS] + ->numUsed; /* @@ -1184,7 +1230,7 @@ SetupStacks(winPtr, leaf) } else { id = winPtr->nameUid; } - elPtr = stacks[i]->els; + elPtr = tsdPtr->stacks[i]->els; count = levelPtr->bases[i]; /* @@ -1203,7 +1249,7 @@ SetupStacks(winPtr, leaf) ExtendStacks(elPtr->child.arrayPtr, leaf); } } - cachedWindow = winPtr; + tsdPtr->cachedWindow = winPtr; } /* @@ -1232,13 +1278,16 @@ ExtendStacks(arrayPtr, leaf) { register int count; register Element *elPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (elPtr = arrayPtr->els, count = arrayPtr->numUsed; count > 0; elPtr++, count--) { if (!(elPtr->flags & (NODE|WILDCARD)) && !leaf) { continue; } - stacks[elPtr->flags] = ExtendArray(stacks[elPtr->flags], elPtr); + tsdPtr->stacks[elPtr->flags] = ExtendArray( + tsdPtr->stacks[elPtr->flags], elPtr); } } @@ -1266,24 +1315,32 @@ OptionInit(mainPtr) { int i; Tcl_Interp *interp; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Element *defaultMatchPtr = &tsdPtr->defaultMatch; /* * First, once-only initialization. */ - - if (numLevels == 0) { - - numLevels = 5; - levels = (StackLevel *) ckalloc((unsigned) (5*sizeof(StackLevel))); + + if (tsdPtr->initialized == 0) { + tsdPtr->initialized = 1; + tsdPtr->cachedWindow = NULL; + tsdPtr->numLevels = 5; + tsdPtr->curLevel = -1; + tsdPtr->serial = 0; + + tsdPtr->levels = (StackLevel *) ckalloc((unsigned) + (5*sizeof(StackLevel))); for (i = 0; i < NUM_STACKS; i++) { - stacks[i] = NewArray(10); - levels[0].bases[i] = 0; + tsdPtr->stacks[i] = NewArray(10); + tsdPtr->levels[0].bases[i] = 0; } - defaultMatch.nameUid = NULL; - defaultMatch.child.valueUid = NULL; - defaultMatch.priority = -1; - defaultMatch.flags = 0; + defaultMatchPtr->nameUid = NULL; + defaultMatchPtr->child.valueUid = NULL; + defaultMatchPtr->priority = -1; + defaultMatchPtr->flags = 0; } /* |