summaryrefslogtreecommitdiff
path: root/tk/generic/tkOption.c
diff options
context:
space:
mode:
Diffstat (limited to 'tk/generic/tkOption.c')
-rw-r--r--tk/generic/tkOption.c429
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;
}
/*