diff options
author | lfb <lfb> | 1998-12-13 08:16:00 (GMT) |
---|---|---|
committer | lfb <lfb> | 1998-12-13 08:16:00 (GMT) |
commit | 6a11e0ffdf0b7a302f94f3b38b1f9e751dc8ab8b (patch) | |
tree | 55c9929c38a99b28203b5e5dfb758a9dd1bf303e | |
parent | 2d3a35af140d791de362fc99fe6254312f6f53ed (diff) | |
download | tk-6a11e0ffdf0b7a302f94f3b38b1f9e751dc8ab8b.zip tk-6a11e0ffdf0b7a302f94f3b38b1f9e751dc8ab8b.tar.gz tk-6a11e0ffdf0b7a302f94f3b38b1f9e751dc8ab8b.tar.bz2 |
Tk 8.1 Muti-threading changes.
Moved static and global data elements into thread-local storage,
or introduced locks where not possible, as first stage of adding
thread safety to Tk.
49 files changed, 1932 insertions, 1332 deletions
diff --git a/generic/tk3d.c b/generic/tk3d.c index 014856f..6aae2e2 100644 --- a/generic/tk3d.c +++ b/generic/tk3d.c @@ -10,21 +10,12 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tk3d.c,v 1.1.4.3 1998/11/24 21:43:21 stanton Exp $ + * RCS: @(#) $Id: tk3d.c,v 1.1.4.4 1998/12/13 08:16:00 lfb Exp $ */ #include "tk3d.h" /* - * Hash table to map from a string color name to a TkBorder structure - * that can be used to draw borders with that color. - */ - -static Tcl_HashTable borderTable; - -static int initialized = 0; /* 0 means static structures haven't - * been initialized yet. */ -/* * The following table defines the string values for reliefs, which are * used by Tk_GetReliefFromObj. */ @@ -36,7 +27,7 @@ static char *reliefStrings[] = {"flat", "groove", "raised", "ridge", "solid", * Forward declarations for procedures defined in this file: */ -static void BorderInit _ANSI_ARGS_((void)); +static void BorderInit _ANSI_ARGS_((TkDisplay *dispPtr)); static void DupBorderObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr, Tcl_Obj *dupObjPtr)); static void FreeBorderObjProc _ANSI_ARGS_((Tcl_Obj *objPtr)); @@ -202,12 +193,15 @@ Tk_Get3DBorder(interp, tkwin, colorName) int new; XGCValues gcValues; XColor *bgColorPtr; + TkDisplay *dispPtr; + + dispPtr = ((TkWindow *) tkwin)->dispPtr; - if (!initialized) { - BorderInit(); + if (!dispPtr->borderInit) { + BorderInit(dispPtr); } - hashPtr = Tcl_CreateHashEntry(&borderTable, colorName, &new); + hashPtr = Tcl_CreateHashEntry(&dispPtr->borderTable, colorName, &new); if (!new) { existingBorderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr); for (borderPtr = existingBorderPtr; borderPtr != NULL; @@ -1057,10 +1051,11 @@ Tk_Fill3DPolygon(tkwin, drawable, border, pointPtr, numPoints, */ static void -BorderInit() +BorderInit(dispPtr) + TkDisplay * dispPtr; /* Used to access thread-specific data. */ { - initialized = 1; - Tcl_InitHashTable(&borderTable, TCL_STRING_KEYS); + dispPtr->borderInit = 1; + Tcl_InitHashTable(&dispPtr->borderTable, TCL_STRING_KEYS); } /* @@ -1251,6 +1246,7 @@ Tk_Get3DBorderFromObj(tkwin, objPtr) { TkBorder *borderPtr = NULL; Tcl_HashEntry *hashPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; if (objPtr->typePtr != &borderObjType) { InitBorderObj(objPtr); @@ -1271,7 +1267,8 @@ Tk_Get3DBorderFromObj(tkwin, objPtr) hashPtr = borderPtr->hashPtr; FreeBorderObjProc(objPtr); } else { - hashPtr = Tcl_FindHashEntry(&borderTable, Tcl_GetString(objPtr)); + hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable, + Tcl_GetString(objPtr)); if (hashPtr == NULL) { goto error; } @@ -1367,9 +1364,10 @@ TkDebugBorder(tkwin, name) TkBorder *borderPtr; Tcl_HashEntry *hashPtr; Tcl_Obj *resultPtr, *objPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; resultPtr = Tcl_NewObj(); - hashPtr = Tcl_FindHashEntry(&borderTable, name); + hashPtr = Tcl_FindHashEntry(&dispPtr->borderTable, name); if (hashPtr != NULL) { borderPtr = (TkBorder *) Tcl_GetHashValue(hashPtr); if (borderPtr == NULL) { diff --git a/generic/tkBind.c b/generic/tkBind.c index 484d9f2..0e9c1b8 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkBind.c,v 1.1.4.4 1998/12/10 04:29:42 stanton Exp $ + * RCS: @(#) $Id: tkBind.c,v 1.1.4.5 1998/12/13 08:16:00 lfb Exp $ */ #include "tkPort.h" @@ -376,6 +376,7 @@ static Tcl_HashTable nameTable; /* keyArray hashed by keysym name. */ */ static int initialized = 0; +TCL_DECLARE_MUTEX(bindMutex) /* * A hash table is kept to map from the string names of event @@ -727,37 +728,40 @@ TkBindInit(mainPtr) */ if (!initialized) { - Tcl_HashEntry *hPtr; - ModInfo *modPtr; - EventInfo *eiPtr; - int dummy; + Tcl_MutexLock(bindMutex); + if (!initialized) { + Tcl_HashEntry *hPtr; + ModInfo *modPtr; + EventInfo *eiPtr; + int dummy; #ifdef REDO_KEYSYM_LOOKUP - KeySymInfo *kPtr; - - Tcl_InitHashTable(&keySymTable, TCL_STRING_KEYS); - Tcl_InitHashTable(&nameTable, TCL_ONE_WORD_KEYS); - for (kPtr = keyArray; kPtr->name != NULL; kPtr++) { - hPtr = Tcl_CreateHashEntry(&keySymTable, kPtr->name, &dummy); - Tcl_SetHashValue(hPtr, kPtr->value); - hPtr = Tcl_CreateHashEntry(&nameTable, (char *) kPtr->value, - &dummy); - Tcl_SetHashValue(hPtr, kPtr->name); - } + KeySymInfo *kPtr; + + Tcl_InitHashTable(&keySymTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&nameTable, TCL_ONE_WORD_KEYS); + for (kPtr = keyArray; kPtr->name != NULL; kPtr++) { + hPtr = Tcl_CreateHashEntry(&keySymTable, kPtr->name, &dummy); + Tcl_SetHashValue(hPtr, kPtr->value); + hPtr = Tcl_CreateHashEntry(&nameTable, (char *) kPtr->value, + &dummy); + Tcl_SetHashValue(hPtr, kPtr->name); + } #endif /* REDO_KEYSYM_LOOKUP */ - Tcl_InitHashTable(&modTable, TCL_STRING_KEYS); - for (modPtr = modArray; modPtr->name != NULL; modPtr++) { - hPtr = Tcl_CreateHashEntry(&modTable, modPtr->name, &dummy); - Tcl_SetHashValue(hPtr, modPtr); - } + Tcl_InitHashTable(&modTable, TCL_STRING_KEYS); + for (modPtr = modArray; modPtr->name != NULL; modPtr++) { + hPtr = Tcl_CreateHashEntry(&modTable, modPtr->name, &dummy); + Tcl_SetHashValue(hPtr, modPtr); + } - Tcl_InitHashTable(&eventTable, TCL_STRING_KEYS); - for (eiPtr = eventArray; eiPtr->name != NULL; eiPtr++) { - hPtr = Tcl_CreateHashEntry(&eventTable, eiPtr->name, &dummy); - Tcl_SetHashValue(hPtr, eiPtr); + Tcl_InitHashTable(&eventTable, TCL_STRING_KEYS); + for (eiPtr = eventArray; eiPtr->name != NULL; eiPtr++) { + hPtr = Tcl_CreateHashEntry(&eventTable, eiPtr->name, &dummy); + Tcl_SetHashValue(hPtr, eiPtr); + } + initialized = 1; } - initialized = 1; } mainPtr->bindingTable = Tk_CreateBindingTable(mainPtr->interp); diff --git a/generic/tkBitmap.c b/generic/tkBitmap.c index 02b8c5c..9e7e7bd 100644 --- a/generic/tkBitmap.c +++ b/generic/tkBitmap.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkBitmap.c,v 1.1.4.2 1998/09/30 02:16:39 stanton Exp $ + * RCS: @(#) $Id: tkBitmap.c,v 1.1.4.3 1998/12/13 08:16:01 lfb Exp $ */ #include "tkPort.h" @@ -80,53 +80,34 @@ typedef struct TkBitmap { * nameTable. */ } TkBitmap; -/* - * Hash table to map from a textual name for a bitmap to the - * first TkBitmap record for that name: - */ - -static Tcl_HashTable nameTable; - -/* - * Hash table that maps from <display + bitmap id> to the TkBitmap structure - * for the bitmap. This table is used by Tk_FreeBitmap. - */ - -static Tcl_HashTable idTable; -typedef struct { - Display *display; /* Display for which bitmap was allocated. */ - Pixmap pixmap; /* X identifier for pixmap. */ -} IdKey; - -/* - * Hash table created by Tk_DefineBitmap to map from a name to a - * collection of in-core data about a bitmap. The table is - * indexed by the address of the data for the bitmap, and the entries - * contain pointers to TkPredefBitmap structures. - */ - -Tcl_HashTable tkPredefBitmapTable; - -/* - * Hash table used by Tk_GetBitmapFromData to map from a collection - * of in-core data about a bitmap to a reference giving an automatically- - * generated name for the bitmap: +/* + * Used in bitmapDataTable, stored in the TkDisplay structure, to map + * between in-core data about a bitmap to its TkBitmap structure. */ -static Tcl_HashTable dataTable; typedef struct { char *source; /* Bitmap bits. */ int width, height; /* Dimensions of bitmap. */ } DataKey; -static int initialized = 0; /* 0 means static structures haven't been - * initialized yet. */ +typedef struct ThreadSpecificData { + int initialized; /* 0 means table below needs initializing. */ + Tcl_HashTable predefBitmapTable; + /* Hash table created by Tk_DefineBitmap + * to map from a name to a collection + * of in-core data about a bitmap. The + * table is indexed by the address of the + * data for the bitmap, and the entries + * contain pointers to TkPredefBitmap + * structures. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * Forward declarations for procedures defined in this file: */ -static void BitmapInit _ANSI_ARGS_((void)); +static void BitmapInit _ANSI_ARGS_((TkDisplay *dispPtr)); static void DupBitmapObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr, Tcl_Obj *dupObjPtr)); static void FreeBitmap _ANSI_ARGS_((TkBitmap *bitmapPtr)); @@ -320,7 +301,6 @@ GetBitmap(interp, tkwin, string) char *string; /* Description of bitmap. See manual entry * for details on legal syntax. */ { - IdKey idKey; Tcl_HashEntry *nameHashPtr, *predefHashPtr; TkBitmap *bitmapPtr, *existingBitmapPtr; TkPredefBitmap *predefPtr; @@ -328,12 +308,15 @@ GetBitmap(interp, tkwin, string) Pixmap bitmap; int width, height; int dummy2; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - if (!initialized) { - BitmapInit(); + if (!dispPtr->bitmapInit) { + BitmapInit(dispPtr); } - nameHashPtr = Tcl_CreateHashEntry(&nameTable, string, &new); + nameHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapNameTable, string, &new); if (!new) { existingBitmapPtr = (TkBitmap *) Tcl_GetHashValue(nameHashPtr); for (bitmapPtr = existingBitmapPtr; bitmapPtr != NULL; @@ -383,7 +366,8 @@ GetBitmap(interp, tkwin, string) } Tcl_DStringFree(&buffer); } else { - predefHashPtr = Tcl_FindHashEntry(&tkPredefBitmapTable, string); + predefHashPtr = Tcl_FindHashEntry(&tsdPtr->predefBitmapTable, + string); if (predefHashPtr == NULL) { /* * The following platform specific call allows the user to @@ -431,10 +415,8 @@ GetBitmap(interp, tkwin, string) bitmapPtr->resourceRefCount = 1; bitmapPtr->objRefCount = 0; bitmapPtr->nameHashPtr = nameHashPtr; - idKey.display = bitmapPtr->display; - idKey.pixmap = bitmap; - bitmapPtr->idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey, - &new); + bitmapPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapIdTable, + (char *) bitmap, &new); if (!new) { panic("bitmap already registered in Tk_GetBitmap"); } @@ -482,12 +464,23 @@ Tk_DefineBitmap(interp, name, source, width, height) int new; Tcl_HashEntry *predefHashPtr; TkPredefBitmap *predefPtr; - - if (!initialized) { - BitmapInit(); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + /* + * Initialize the Bitmap module if not initialized already for this + * thread. Since the current TkDisplay structure cannot be + * introspected from here, pass a NULL pointer to BitmapInit, + * which will know to initialize only the data in the + * ThreadSpecificData structure for the current thread. + */ + + if (!tsdPtr->initialized) { + BitmapInit((TkDisplay *) NULL); } - predefHashPtr = Tcl_CreateHashEntry(&tkPredefBitmapTable, name, &new); + predefHashPtr = Tcl_CreateHashEntry(&tsdPtr->predefBitmapTable, + name, &new); if (!new) { Tcl_AppendResult(interp, "bitmap \"", name, "\" is already defined", (char *) NULL); @@ -525,18 +518,16 @@ Tk_NameOfBitmap(display, bitmap) * allocated. */ Pixmap bitmap; /* Bitmap whose name is wanted. */ { - IdKey idKey; Tcl_HashEntry *idHashPtr; TkBitmap *bitmapPtr; + TkDisplay *dispPtr = TkGetDisplay(display); - if (!initialized) { + if (dispPtr == NULL || !dispPtr->bitmapInit) { unknown: panic("Tk_NameOfBitmap received unknown bitmap argument"); } - idKey.display = display; - idKey.pixmap = bitmap; - idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey); + idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap); if (idHashPtr == NULL) { goto unknown; } @@ -571,18 +562,16 @@ Tk_SizeOfBitmap(display, bitmap, widthPtr, heightPtr) int *widthPtr; /* Store bitmap width here. */ int *heightPtr; /* Store bitmap height here. */ { - IdKey idKey; Tcl_HashEntry *idHashPtr; TkBitmap *bitmapPtr; + TkDisplay *dispPtr = TkGetDisplay(display); - if (!initialized) { + if (!dispPtr->bitmapInit) { unknownBitmap: panic("Tk_SizeOfBitmap received unknown bitmap argument"); } - idKey.display = display; - idKey.pixmap = bitmap; - idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey); + idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap); if (idHashPtr == NULL) { goto unknownBitmap; } @@ -666,15 +655,13 @@ Tk_FreeBitmap(display, bitmap) Pixmap bitmap; /* Bitmap to be released. */ { Tcl_HashEntry *idHashPtr; - IdKey idKey; + TkDisplay *dispPtr = TkGetDisplay(display); - if (!initialized) { + if (!dispPtr->bitmapInit) { panic("Tk_FreeBitmap called before Tk_GetBitmap"); } - idKey.display = display; - idKey.pixmap = bitmap; - idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey); + idHashPtr = Tcl_FindHashEntry(&dispPtr->bitmapIdTable, (char *) bitmap); if (idHashPtr == NULL) { panic("Tk_FreeBitmap received unknown bitmap argument"); } @@ -819,21 +806,20 @@ Tk_GetBitmapFromData(interp, tkwin, source, width, height) int new; char string[16 + TCL_INTEGER_SPACE]; char *name; - static int autoNumber = 0; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - if (!initialized) { - BitmapInit(); - } + BitmapInit(dispPtr); nameKey.source = source; nameKey.width = width; nameKey.height = height; - dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &nameKey, &new); + dataHashPtr = Tcl_CreateHashEntry(&dispPtr->bitmapDataTable, + (char *) &nameKey, &new); if (!new) { name = (char *) Tcl_GetHashValue(dataHashPtr); } else { - autoNumber++; - sprintf(string, "_tk%d", autoNumber); + dispPtr->bitmapAutoNumber++; + sprintf(string, "_tk%d", dispPtr->bitmapAutoNumber); name = string; Tcl_SetHashValue(dataHashPtr, name); if (Tk_DefineBitmap(interp, name, source, width, height) != TCL_OK) { @@ -901,6 +887,7 @@ GetBitmapFromObj(tkwin, objPtr) { TkBitmap *bitmapPtr; Tcl_HashEntry *hashPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; if (objPtr->typePtr != &bitmapObjType) { InitBitmapObj(objPtr); @@ -915,7 +902,8 @@ GetBitmapFromObj(tkwin, objPtr) hashPtr = bitmapPtr->nameHashPtr; FreeBitmapObjProc(objPtr); } else { - hashPtr = Tcl_FindHashEntry(&nameTable, Tcl_GetString(objPtr)); + hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable, + Tcl_GetString(objPtr)); if (hashPtr == NULL) { goto error; } @@ -984,12 +972,14 @@ InitBitmapObj(objPtr) *---------------------------------------------------------------------- * * BitmapInit -- - * - * Initialize the structures used for bitmap management. + * Initializes hash tables used by this module. Initializes + * tables stored in TkDisplay structure if a TkDisplay pointer + * is passed in. Iinitializes the thread-local data + * in the current thread's ThreadSpecificData structure. * * Results: - * None. - * + * None. + * * Side effects: * Read the code. * @@ -997,49 +987,71 @@ InitBitmapObj(objPtr) */ static void -BitmapInit() +BitmapInit(dispPtr) + TkDisplay *dispPtr; /* TkDisplay structure encapsulating + * thread-specific data used by this + * module, or NULL if unavailable. */ { Tcl_Interp *dummy; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + /* + * First initialize the data in the ThreadSpecificData strucuture, + * if needed. + */ - dummy = Tcl_CreateInterp(); - initialized = 1; - Tcl_InitHashTable(&nameTable, TCL_STRING_KEYS); - Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int)); - Tcl_InitHashTable(&tkPredefBitmapTable, TCL_STRING_KEYS); + if (!tsdPtr->initialized) { + tsdPtr->initialized = 1; + dummy = Tcl_CreateInterp(); + Tcl_InitHashTable(&tsdPtr->predefBitmapTable, + TCL_STRING_KEYS); + + Tk_DefineBitmap(dummy, Tk_GetUid("error"), (char *) error_bits, + error_width, error_height); + Tk_DefineBitmap(dummy, Tk_GetUid("gray75"), (char *) gray75_bits, + gray75_width, gray75_height); + Tk_DefineBitmap(dummy, Tk_GetUid("gray50"), (char *) gray50_bits, + gray50_width, gray50_height); + Tk_DefineBitmap(dummy, Tk_GetUid("gray25"), (char *) gray25_bits, + gray25_width, gray25_height); + Tk_DefineBitmap(dummy, Tk_GetUid("gray12"), (char *) gray12_bits, + gray12_width, gray12_height); + Tk_DefineBitmap(dummy, Tk_GetUid("hourglass"), (char *) hourglass_bits, + hourglass_width, hourglass_height); + Tk_DefineBitmap(dummy, Tk_GetUid("info"), (char *) info_bits, + info_width, info_height); + Tk_DefineBitmap(dummy, Tk_GetUid("questhead"), (char *) questhead_bits, + questhead_width, questhead_height); + Tk_DefineBitmap(dummy, Tk_GetUid("question"), (char *) question_bits, + question_width, question_height); + Tk_DefineBitmap(dummy, Tk_GetUid("warning"), (char *) warning_bits, + warning_width, warning_height); + + TkpDefineNativeBitmaps(); + Tcl_DeleteInterp(dummy); + } /* - * The call below is tricky: can't use sizeof(IdKey) because it - * gets padded with extra unpredictable bytes on some 64-bit - * machines. + * Was a valid TkDisplay pointer passed? If so, initialize the + * Bitmap module tables in that structure. */ - Tcl_InitHashTable(&idTable, (sizeof(Display *) + sizeof(Pixmap)) - /sizeof(int)); - - Tk_DefineBitmap(dummy, Tk_GetUid("error"), (char *) error_bits, - error_width, error_height); - Tk_DefineBitmap(dummy, Tk_GetUid("gray75"), (char *) gray75_bits, - gray75_width, gray75_height); - Tk_DefineBitmap(dummy, Tk_GetUid("gray50"), (char *) gray50_bits, - gray50_width, gray50_height); - Tk_DefineBitmap(dummy, Tk_GetUid("gray25"), (char *) gray25_bits, - gray25_width, gray25_height); - Tk_DefineBitmap(dummy, Tk_GetUid("gray12"), (char *) gray12_bits, - gray12_width, gray12_height); - Tk_DefineBitmap(dummy, Tk_GetUid("hourglass"), (char *) hourglass_bits, - hourglass_width, hourglass_height); - Tk_DefineBitmap(dummy, Tk_GetUid("info"), (char *) info_bits, - info_width, info_height); - Tk_DefineBitmap(dummy, Tk_GetUid("questhead"), (char *) questhead_bits, - questhead_width, questhead_height); - Tk_DefineBitmap(dummy, Tk_GetUid("question"), (char *) question_bits, - question_width, question_height); - Tk_DefineBitmap(dummy, Tk_GetUid("warning"), (char *) warning_bits, - warning_width, warning_height); - - TkpDefineNativeBitmaps(); - - Tcl_DeleteInterp(dummy); + if (dispPtr != NULL) { + dispPtr->bitmapInit = 1; + Tcl_InitHashTable(&dispPtr->bitmapNameTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&dispPtr->bitmapDataTable, sizeof(DataKey) + /sizeof(int)); + + /* + * The call below is tricky: can't use sizeof(IdKey) because it + * gets padded with extra unpredictable bytes on some 64-bit + * machines. + */ + + Tcl_InitHashTable(&dispPtr->bitmapIdTable, sizeof(Pixmap) + /sizeof(int)); + } } /* @@ -1115,9 +1127,10 @@ TkDebugBitmap(tkwin, name) TkBitmap *bitmapPtr; Tcl_HashEntry *hashPtr; Tcl_Obj *resultPtr, *objPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; resultPtr = Tcl_NewObj(); - hashPtr = Tcl_FindHashEntry(&nameTable, name); + hashPtr = Tcl_FindHashEntry(&dispPtr->bitmapNameTable, name); if (hashPtr != NULL) { bitmapPtr = (TkBitmap *) Tcl_GetHashValue(hashPtr); if (bitmapPtr == NULL) { @@ -1134,3 +1147,32 @@ TkDebugBitmap(tkwin, name) } return resultPtr; } + + +/* + *---------------------------------------------------------------------- + * + * TkGetBitmapPredefTable -- + * This procedure is used by tkMacBitmap.c to access the thread- + * specific predefBitmap table that maps from the names of + * the predefined bitmaps to data associated with those + * bitmaps. It is required because the table is allocated in + * thread-local storage and is not visible outside this file. + + * Results: + * Returns a pointer to the predefined bitmap hash table for + * the current thread. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +Tcl_HashTable * +TkGetBitmapPredefTable() +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + return &tsdPtr->predefBitmapTable; +} diff --git a/generic/tkCanvArc.c b/generic/tkCanvArc.c index d68005c..37e117e 100644 --- a/generic/tkCanvArc.c +++ b/generic/tkCanvArc.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkCanvArc.c,v 1.1.4.2 1998/09/30 02:16:41 stanton Exp $ + * RCS: @(#) $Id: tkCanvArc.c,v 1.1.4.3 1998/12/13 08:16:01 lfb Exp $ */ #include <stdio.h> @@ -176,6 +176,9 @@ Tk_ItemType tkArcType = { static Tk_Uid arcUid = NULL; static Tk_Uid chordUid = NULL; static Tk_Uid pieSliceUid = NULL; + +TCL_DECLARE_MUTEX(arcMutex) /* Used to guard access to Tk_Uids above.*/ + /* *-------------------------------------------------------------- @@ -221,10 +224,14 @@ CreateArc(interp, canvas, itemPtr, argc, argv) * Carry out once-only initialization. */ - if (arcUid == NULL) { - arcUid = Tk_GetUid("arc"); - chordUid = Tk_GetUid("chord"); - pieSliceUid = Tk_GetUid("pieslice"); + if (pieSliceUid == NULL) { + Tcl_MutexLock(&arcMutex); + if (pieSliceUid == NULL) { + arcUid = Tk_GetUid("arc"); + chordUid = Tk_GetUid("chord"); + pieSliceUid = Tk_GetUid("pieslice"); + } + Tcl_MutexUnlock(&arcMutex); } /* diff --git a/generic/tkCanvLine.c b/generic/tkCanvLine.c index e2e49a3..177ffaf 100644 --- a/generic/tkCanvLine.c +++ b/generic/tkCanvLine.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkCanvLine.c,v 1.1.4.2 1998/09/30 02:16:43 stanton Exp $ + * RCS: @(#) $Id: tkCanvLine.c,v 1.1.4.3 1998/12/13 08:16:02 lfb Exp $ */ #include <stdio.h> @@ -188,6 +188,8 @@ static Tk_Uid firstUid = NULL; static Tk_Uid lastUid = NULL; static Tk_Uid bothUid = NULL; +TCL_DECLARE_MUTEX(lineMutex) /* Used to guard access to Tk_Uids above.*/ + /* * The definition below determines how large are static arrays * used to hold spline points (splines larger than this have to @@ -252,11 +254,13 @@ CreateLine(interp, canvas, itemPtr, argc, argv) linePtr->joinStyle = JoinRound; linePtr->gc = None; linePtr->arrowGC = None; - if (noneUid == NULL) { + if (bothUid == NULL) { + Tcl_MutexLock(&lineMutex); noneUid = Tk_GetUid("none"); firstUid = Tk_GetUid("first"); lastUid = Tk_GetUid("last"); bothUid = Tk_GetUid("both"); + Tcl_MutexUnlock(&lineMutex); } linePtr->arrow = noneUid; linePtr->arrowShapeA = (float)8.0; diff --git a/generic/tkCanvas.c b/generic/tkCanvas.c index 20c0e71..601ef15 100644 --- a/generic/tkCanvas.c +++ b/generic/tkCanvas.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkCanvas.c,v 1.1.4.3 1998/11/25 21:16:31 stanton Exp $ + * RCS: @(#) $Id: tkCanvas.c,v 1.1.4.4 1998/12/13 08:16:02 lfb Exp $ */ #include "default.h" @@ -159,13 +159,6 @@ static Tk_Uid allUid = NULL; static Tk_Uid currentUid = NULL; /* - * Statistics counters: - */ - -static int numIdSearches; -static int numSlowSearches; - -/* * Prototypes for procedures defined later in this file: */ @@ -2213,6 +2206,11 @@ StartTagSearch(canvasPtr, tag, searchPtr) Tk_Uid *tagPtr; Tk_Uid uid; int count; + TkWindow *tkwin; + TkDisplay *dispPtr; + + tkwin = (TkWindow *) canvasPtr->tkwin; + dispPtr = tkwin->dispPtr; /* * Initialize the search. @@ -2231,15 +2229,15 @@ StartTagSearch(canvasPtr, tag, searchPtr) if (isdigit(UCHAR(*tag))) { char *end; Tcl_HashEntry *entryPtr; - - numIdSearches++; + + dispPtr->numIdSearches++; id = strtoul(tag, &end, 0); if (*end == 0) { itemPtr = canvasPtr->hotPtr; - lastPtr = canvasPtr->hotPrevPtr; + lastPtr = canvasPtr->hotPrevPtr; if ((itemPtr == NULL) || (itemPtr->id != id) || (lastPtr == NULL) || (lastPtr->nextPtr != itemPtr)) { - numSlowSearches++; + dispPtr->numSlowSearches++; entryPtr = Tcl_FindHashEntry(&canvasPtr->idTable, (char *) id); if (entryPtr != NULL) { itemPtr = (Tk_Item *)Tcl_GetHashValue(entryPtr); diff --git a/generic/tkCmds.c b/generic/tkCmds.c index 2c8c318..216dc1a 100644 --- a/generic/tkCmds.c +++ b/generic/tkCmds.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkCmds.c,v 1.1.4.2 1998/09/30 02:16:50 stanton Exp $ + * RCS: @(#) $Id: tkCmds.c,v 1.1.4.3 1998/12/13 08:16:03 lfb Exp $ */ #include "tkPort.h" @@ -851,7 +851,7 @@ Tk_UpdateObjCmd(clientData, interp, objc, objv) while (Tcl_DoOneEvent(flags) != 0) { /* Empty loop body */ } - for (dispPtr = tkDisplayList; dispPtr != NULL; + for (dispPtr = TkGetDisplayList(); dispPtr != NULL; dispPtr = dispPtr->nextPtr) { XSync(dispPtr->display, False); } diff --git a/generic/tkColor.c b/generic/tkColor.c index 8440bd6..34f175e 100644 --- a/generic/tkColor.c +++ b/generic/tkColor.c @@ -11,26 +11,14 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkColor.c,v 1.1.4.2 1998/09/30 02:16:51 stanton Exp $ + * RCS: @(#) $Id: tkColor.c,v 1.1.4.3 1998/12/13 08:16:03 lfb Exp $ */ #include "tkColor.h" /* - * There are two global hash tables used for managing colors. The - * first one, nameTable, maps from string color names like "red" or - * "#00ff80" to TkColor structures. It is used by Tk_AllocColorFromObj - * Tk_GetColor. The second table, valueTable, maps from integer - * RGB values to TkColor structures. It is used by Tk_GetColorByValue - */ - -static Tcl_HashTable nameTable; -static Tcl_HashTable valueTable; -static int initialized = 0; /* 0 means static structures haven't been - * initialized yet. */ - -/* - * Structures of the following following type are used as keys for valueTable. + * Structures of the following following type are used as keys for + * colorValueTable (in TkDisplay). */ typedef struct { @@ -40,11 +28,21 @@ typedef struct { Display *display; /* Display for colormap. */ } ValueKey; + +/* + * The structure below is used to allocate thread-local data. + */ + +typedef struct ThreadSpecificData { + char rgbString[20]; /* */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + /* * Forward declarations for procedures defined in this file: */ -static void ColorInit _ANSI_ARGS_((void)); +static void ColorInit _ANSI_ARGS_((TkDisplay *dispPtr)); static void DupColorObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr, Tcl_Obj *dupObjPtr)); static void FreeColorObjProc _ANSI_ARGS_((Tcl_Obj *objPtr)); @@ -196,9 +194,10 @@ Tk_GetColor(interp, tkwin, name) int new; TkColor *tkColPtr; TkColor *existingColPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - if (!initialized) { - ColorInit(); + if (!dispPtr->colorInit) { + ColorInit(dispPtr); } /* @@ -206,7 +205,7 @@ Tk_GetColor(interp, tkwin, name) * name. */ - nameHashPtr = Tcl_CreateHashEntry(&nameTable, name, &new); + nameHashPtr = Tcl_CreateHashEntry(&dispPtr->colorNameTable, name, &new); if (!new) { existingColPtr = (TkColor *) Tcl_GetHashValue(nameHashPtr); for (tkColPtr = existingColPtr; tkColPtr != NULL; @@ -244,7 +243,8 @@ Tk_GetColor(interp, tkwin, name) } /* - * Now create a new TkColor structure and add it to nameTable. + * Now create a new TkColor structure and add it to colorNameTable + * (in TkDisplay). */ tkColPtr->magic = COLOR_MAGIC; @@ -254,7 +254,7 @@ Tk_GetColor(interp, tkwin, name) tkColPtr->visual = Tk_Visual(tkwin); tkColPtr->resourceRefCount = 1; tkColPtr->objRefCount = 0; - tkColPtr->tablePtr = &nameTable; + tkColPtr->tablePtr = &dispPtr->colorNameTable; tkColPtr->hashPtr = nameHashPtr; tkColPtr->nextPtr = existingColPtr; Tcl_SetHashValue(nameHashPtr, tkColPtr); @@ -297,9 +297,10 @@ Tk_GetColorByValue(tkwin, colorPtr) int new; TkColor *tkColPtr; Display *display = Tk_Display(tkwin); + TkDisplay *dispPtr = TkGetDisplay(display); - if (!initialized) { - ColorInit(); + if (!dispPtr->colorInit) { + ColorInit(dispPtr); } /* @@ -312,7 +313,8 @@ Tk_GetColorByValue(tkwin, colorPtr) valueKey.blue = colorPtr->blue; valueKey.colormap = Tk_Colormap(tkwin); valueKey.display = display; - valueHashPtr = Tcl_CreateHashEntry(&valueTable, (char *) &valueKey, &new); + valueHashPtr = Tcl_CreateHashEntry(&dispPtr->colorValueTable, + (char *) &valueKey, &new); if (!new) { tkColPtr = (TkColor *) Tcl_GetHashValue(valueHashPtr); tkColPtr->resourceRefCount++; @@ -321,7 +323,7 @@ Tk_GetColorByValue(tkwin, colorPtr) /* * The name isn't currently known. Find a pixel value for this - * color and add a new structure to valueTable. + * color and add a new structure to colorValueTable (in TkDisplay). */ tkColPtr = TkpGetColorByValue(tkwin, colorPtr); @@ -332,7 +334,7 @@ Tk_GetColorByValue(tkwin, colorPtr) tkColPtr->visual = Tk_Visual(tkwin); tkColPtr->resourceRefCount = 1; tkColPtr->objRefCount = 0; - tkColPtr->tablePtr = &valueTable; + tkColPtr->tablePtr = &dispPtr->colorValueTable; tkColPtr->hashPtr = valueHashPtr; tkColPtr->nextPtr = NULL; Tcl_SetHashValue(valueHashPtr, tkColPtr); @@ -366,15 +368,15 @@ Tk_NameOfColor(colorPtr) XColor *colorPtr; /* Color whose name is desired. */ { register TkColor *tkColPtr = (TkColor *) colorPtr; - static char string[20]; - - if ((tkColPtr->magic == COLOR_MAGIC) - && (tkColPtr->tablePtr == &nameTable)) { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (tkColPtr->magic == COLOR_MAGIC) { return tkColPtr->hashPtr->key.string; } - sprintf(string, "#%04x%04x%04x", colorPtr->red, colorPtr->green, - colorPtr->blue); - return string; + sprintf(tsdPtr->rgbString, "#%04x%04x%04x", colorPtr->red, + colorPtr->green, colorPtr->blue); + return tsdPtr->rgbString; } /* @@ -637,6 +639,7 @@ Tk_GetColorFromObj(tkwin, objPtr) { TkColor *tkColPtr; Tcl_HashEntry *hashPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; if (objPtr->typePtr != &colorObjType) { InitColorObj(objPtr); @@ -657,7 +660,8 @@ Tk_GetColorFromObj(tkwin, objPtr) hashPtr = tkColPtr->hashPtr; FreeColorObjProc(objPtr); } else { - hashPtr = Tcl_FindHashEntry(&nameTable, Tcl_GetString(objPtr)); + hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable, + Tcl_GetString(objPtr)); if (hashPtr == NULL) { goto error; } @@ -741,11 +745,15 @@ InitColorObj(objPtr) */ static void -ColorInit() +ColorInit(dispPtr) + TkDisplay *dispPtr; { - initialized = 1; - Tcl_InitHashTable(&nameTable, TCL_STRING_KEYS); - Tcl_InitHashTable(&valueTable, sizeof(ValueKey)/sizeof(int)); + if (!dispPtr->colorInit) { + dispPtr->colorInit = 1; + Tcl_InitHashTable(&dispPtr->colorNameTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&dispPtr->colorValueTable, + sizeof(ValueKey)/sizeof(int)); + } } /* @@ -776,9 +784,10 @@ TkDebugColor(tkwin, name) TkColor *tkColPtr; Tcl_HashEntry *hashPtr; Tcl_Obj *resultPtr, *objPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; resultPtr = Tcl_NewObj(); - hashPtr = Tcl_FindHashEntry(&nameTable, name); + hashPtr = Tcl_FindHashEntry(&dispPtr->colorNameTable, name); if (hashPtr != NULL) { tkColPtr = (TkColor *) Tcl_GetHashValue(hashPtr); if (tkColPtr == NULL) { diff --git a/generic/tkConsole.c b/generic/tkConsole.c index 05d03a4..f4fd75e 100644 --- a/generic/tkConsole.c +++ b/generic/tkConsole.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkConsole.c,v 1.1.4.2 1998/09/30 02:16:52 stanton Exp $ + * RCS: @(#) $Id: tkConsole.c,v 1.1.4.3 1998/12/13 08:16:03 lfb Exp $ */ #include "tk.h" @@ -27,10 +27,13 @@ typedef struct ConsoleInfo { Tcl_Interp *interp; /* Interpreter to send console commands. */ } ConsoleInfo; -static Tcl_Interp *gStdoutInterp = NULL; - EXTERN void TclInitSubsystems _ANSI_ARGS_((CONST char *argv0)); +typedef struct ThreadSpecificData { + Tcl_Interp *gStdoutInterp; +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + /* * Forward declarations for procedures defined later in this file: * @@ -155,6 +158,8 @@ TkConsoleInit(interp) Tcl_Interp *consoleInterp; ConsoleInfo *info; Tk_Window mainWindow = Tk_MainWindow(interp); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); #ifdef MAC_TCL static char initCmd[] = "source -rsrc {Console}"; #else @@ -176,7 +181,7 @@ TkConsoleInit(interp) if (Tk_Init(consoleInterp) != TCL_OK) { goto error; } - gStdoutInterp = interp; + tsdPtr->gStdoutInterp = interp; /* * Add console commands to the interp @@ -232,11 +237,15 @@ ConsoleOutput(instanceData, buf, toWrite, errorCode) int toWrite; /* How many bytes to write? */ int *errorCode; /* Where to store error code. */ { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + *errorCode = 0; Tcl_SetErrno(0); - if (gStdoutInterp != NULL) { - TkConsolePrint(gStdoutInterp, (int) instanceData, buf, toWrite); + if (tsdPtr->gStdoutInterp != NULL) { + TkConsolePrint(tsdPtr->gStdoutInterp, (int) instanceData, buf, + toWrite); } return toWrite; diff --git a/generic/tkCursor.c b/generic/tkCursor.c index 9c22bb0..c3e4a12 100644 --- a/generic/tkCursor.c +++ b/generic/tkCursor.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkCursor.c,v 1.1.4.2 1998/09/30 02:16:53 stanton Exp $ + * RCS: @(#) $Id: tkCursor.c,v 1.1.4.3 1998/12/13 08:16:04 lfb Exp $ */ #include "tkPort.h" @@ -20,23 +20,11 @@ /* * A TkCursor structure exists for each cursor that is currently * active. Each structure is indexed with two hash tables defined - * below. One of the tables is idTable, and the other is either - * nameTable or dataTable, also defined below. + * below. One of the tables is cursorIdTable, and the other is either + * cursorNameTable or cursorDataTable, each of which are stored in the + * TkDisplay structure for the current thread. */ -/* - * Hash table to map from a string name for a cursor to the TkCursor - * record for the cursor: - */ - -static Tcl_HashTable nameTable; - -/* - * Hash table to map from a collection of in-core data about a - * cursor (bitmap contents, etc.) to a TkCursor structure: - */ - -static Tcl_HashTable dataTable; typedef struct { char *source; /* Cursor bits. */ char *mask; /* Mask bits. */ @@ -48,24 +36,10 @@ typedef struct { } DataKey; /* - * Hash table that maps from <display + cursor id> to the TkCursor structure - * for the cursor. This table is used by Tk_FreeCursor. - */ - -static Tcl_HashTable idTable; -typedef struct { - Display *display; /* Display for which cursor was allocated. */ - Tk_Cursor cursor; /* Cursor identifier. */ -} IdKey; - -static int initialized = 0; /* 0 means static structures haven't been - * initialized yet. */ - -/* * Forward declarations for procedures defined in this file: */ -static void CursorInit _ANSI_ARGS_((void)); +static void CursorInit _ANSI_ARGS_((TkDisplay *dispPtr)); static void DupCursorObjProc _ANSI_ARGS_((Tcl_Obj *srcObjPtr, Tcl_Obj *dupObjPtr)); static void FreeCursor _ANSI_ARGS_((TkCursor *cursorPtr)); @@ -259,17 +233,18 @@ GetCursor(interp, tkwin, string) char *string; /* Description of cursor. See manual entry * for details on legal syntax. */ { - IdKey idKey; Tcl_HashEntry *nameHashPtr; register TkCursor *cursorPtr; TkCursor *existingCursorPtr = NULL; int new; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - if (!initialized) { - CursorInit(); + if (!dispPtr->cursorInit) { + CursorInit(dispPtr); } - nameHashPtr = Tcl_CreateHashEntry(&nameTable, string, &new); + nameHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorNameTable, + string, &new); if (!new) { existingCursorPtr = (TkCursor *) Tcl_GetHashValue(nameHashPtr); for (cursorPtr = existingCursorPtr; cursorPtr != NULL; @@ -299,12 +274,10 @@ GetCursor(interp, tkwin, string) cursorPtr->display = Tk_Display(tkwin); cursorPtr->resourceRefCount = 1; cursorPtr->objRefCount = 0; - cursorPtr->otherTable = &nameTable; + cursorPtr->otherTable = &dispPtr->cursorNameTable; cursorPtr->hashPtr = nameHashPtr; - idKey.display = Tk_Display(tkwin); - idKey.cursor = cursorPtr->cursor; - cursorPtr->idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey, - &new); + cursorPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorIdTable, + (char *) cursorPtr->cursor, &new); if (!new) { panic("cursor already registered in Tk_GetCursor"); } @@ -353,14 +326,14 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height, Tk_Uid bg; /* Background color for cursor. */ { DataKey dataKey; - IdKey idKey; Tcl_HashEntry *dataHashPtr; register TkCursor *cursorPtr; int new; XColor fgColor, bgColor; + TkDisplay *dispPtr; - if (!initialized) { - CursorInit(); + if (!dispPtr->cursorInit) { + CursorInit(dispPtr); } dataKey.source = source; @@ -372,7 +345,8 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height, dataKey.fg = fg; dataKey.bg = bg; dataKey.display = Tk_Display(tkwin); - dataHashPtr = Tcl_CreateHashEntry(&dataTable, (char *) &dataKey, &new); + dataHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorDataTable, + (char *) &dataKey, &new); if (!new) { cursorPtr = (TkCursor *) Tcl_GetHashValue(dataHashPtr); cursorPtr->resourceRefCount++; @@ -403,13 +377,11 @@ Tk_GetCursorFromData(interp, tkwin, source, mask, width, height, } cursorPtr->resourceRefCount = 1; - cursorPtr->otherTable = &dataTable; + cursorPtr->otherTable = &dispPtr->cursorDataTable; cursorPtr->hashPtr = dataHashPtr; cursorPtr->objRefCount = 0; - idKey.display = dataKey.display; - idKey.cursor = cursorPtr->cursor; - cursorPtr->idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey, - &new); + cursorPtr->idHashPtr = Tcl_CreateHashEntry(&dispPtr->cursorIdTable, + (char *) cursorPtr->cursor, &new); if (!new) { panic("cursor already registered in Tk_GetCursorFromData"); } @@ -449,24 +421,24 @@ Tk_NameOfCursor(display, cursor) Tk_Cursor cursor; /* Identifier for cursor whose name is * wanted. */ { - IdKey idKey; Tcl_HashEntry *idHashPtr; TkCursor *cursorPtr; - static char string[20]; + TkDisplay *dispPtr; + + dispPtr = TkGetDisplay(display); - if (!initialized) { + if (!dispPtr->cursorInit) { printid: - sprintf(string, "cursor id 0x%x", (unsigned int) cursor); - return string; + sprintf(dispPtr->cursorString, "cursor id 0x%x", + (unsigned int) cursor); + return dispPtr->cursorString; } - idKey.display = display; - idKey.cursor = cursor; - idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey); + idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) cursor); if (idHashPtr == NULL) { goto printid; } cursorPtr = (TkCursor *) Tcl_GetHashValue(idHashPtr); - if (cursorPtr->otherTable != &nameTable) { + if (cursorPtr->otherTable != &dispPtr->cursorNameTable) { goto printid; } return cursorPtr->hashPtr->key.string; @@ -545,16 +517,14 @@ Tk_FreeCursor(display, cursor) Display *display; /* Display for which cursor was allocated. */ Tk_Cursor cursor; /* Identifier for cursor to be released. */ { - IdKey idKey; Tcl_HashEntry *idHashPtr; + TkDisplay *dispPtr = TkGetDisplay(display); - if (!initialized) { + if (!dispPtr->cursorInit) { panic("Tk_FreeCursor called before Tk_GetCursor"); } - idKey.display = display; - idKey.cursor = cursor; - idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey); + idHashPtr = Tcl_FindHashEntry(&dispPtr->cursorIdTable, (char *) cursor); if (idHashPtr == NULL) { panic("Tk_FreeCursor received unknown cursor argument"); } @@ -717,6 +687,7 @@ GetCursorFromObj(tkwin, objPtr) { TkCursor *cursorPtr; Tcl_HashEntry *hashPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; if (objPtr->typePtr != &cursorObjType) { InitCursorObj(objPtr); @@ -729,7 +700,8 @@ GetCursorFromObj(tkwin, objPtr) } hashPtr = cursorPtr->hashPtr; } else { - hashPtr = Tcl_FindHashEntry(&nameTable, Tcl_GetString(objPtr)); + hashPtr = Tcl_FindHashEntry(&dispPtr->cursorNameTable, + Tcl_GetString(objPtr)); if (hashPtr == NULL) { goto error; } @@ -811,11 +783,11 @@ InitCursorObj(objPtr) */ static void -CursorInit() +CursorInit(dispPtr) + TkDisplay *dispPtr; /* Display used to store thread-specific data. */ { - initialized = 1; - Tcl_InitHashTable(&nameTable, TCL_STRING_KEYS); - Tcl_InitHashTable(&dataTable, sizeof(DataKey)/sizeof(int)); + Tcl_InitHashTable(&dispPtr->cursorNameTable, TCL_STRING_KEYS); + Tcl_InitHashTable(&dispPtr->cursorDataTable, sizeof(DataKey)/sizeof(int)); /* * The call below is tricky: can't use sizeof(IdKey) because it @@ -823,8 +795,9 @@ CursorInit() * machines. */ - Tcl_InitHashTable(&idTable, (sizeof(Display *) + sizeof(Tk_Cursor)) + Tcl_InitHashTable(&dispPtr->cursorIdTable, sizeof(Display *) /sizeof(int)); + dispPtr->cursorInit = 1; } /* @@ -855,9 +828,10 @@ TkDebugCursor(tkwin, name) TkCursor *cursorPtr; Tcl_HashEntry *hashPtr; Tcl_Obj *resultPtr, *objPtr; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; resultPtr = Tcl_NewObj(); - hashPtr = Tcl_FindHashEntry(&nameTable, name); + hashPtr = Tcl_FindHashEntry(&dispPtr->cursorNameTable, name); if (hashPtr != NULL) { cursorPtr = (TkCursor *) Tcl_GetHashValue(hashPtr); if (cursorPtr == NULL) { diff --git a/generic/tkEvent.c b/generic/tkEvent.c index 01aa75e..d5f8dd3 100644 --- a/generic/tkEvent.c +++ b/generic/tkEvent.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkEvent.c,v 1.1.4.2 1998/11/25 21:16:31 stanton Exp $ + * RCS: @(#) $Id: tkEvent.c,v 1.1.4.3 1998/12/13 08:16:04 lfb Exp $ */ #include "tkPort.h" @@ -39,10 +39,6 @@ typedef struct InProgress { struct InProgress *nextPtr; /* Next higher nested search. */ } InProgress; -static InProgress *pendingPtr = NULL; - /* Topmost search in progress, or - * NULL if none. */ - /* * For each call to Tk_CreateGenericHandler, an instance of the following * structure will be created. All of the active handlers are linked into a @@ -58,11 +54,6 @@ typedef struct GenericHandler { * handlers, or NULL for end of list. */ } GenericHandler; -static GenericHandler *genericList = NULL; - /* First handler in the list, or NULL. */ -static GenericHandler *lastGenericPtr = NULL; - /* Last handler in list. */ - /* * There's a potential problem if Tk_HandleEvent is entered recursively. * A handler cannot be deleted physically until we have returned from @@ -70,11 +61,8 @@ static GenericHandler *lastGenericPtr = NULL; * its `next' entry. We deal with the problem by using the `delete flag' and * deleting handlers only when it's known that there's no handler active. * - * The following variable has a non-zero value when a handler is active. */ -static int genericHandlersActive = 0; - /* * The following structure is used for queueing X-style events on the * Tcl event queue. @@ -134,15 +122,37 @@ static unsigned long eventMasks[TK_LASTEVENT] = { MouseWheelMask /* MouseWheelEvent */ }; + /* - * If someone has called Tk_RestrictEvents, the information below - * keeps track of it. + * The structure below is used to store Data for the Event module that + * must be kept thread-local. The "dataKey" is used to fetch the + * thread-specific storage for the current thread. */ -static Tk_RestrictProc *restrictProc; +typedef struct ThreadSpecificData { + + int genericHandlersActive; + /* The following variable has a non-zero + * value when a handler is active. */ + InProgress *pendingPtr; + /* Topmost search in progress, or + * NULL if none. */ + GenericHandler *genericList; + /* First handler in the list, or NULL. */ + GenericHandler *lastGenericPtr; + /* Last handler in list. */ + + /* + * If someone has called Tk_RestrictEvents, the information below + * keeps track of it. + */ + + Tk_RestrictProc *restrictProc; /* Procedure to call. NULL means no * restrictProc is currently in effect. */ -static ClientData restrictArg; /* Argument to pass to restrictProc. */ + ClientData restrictArg; /* Argument to pass to restrictProc. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * Prototypes for procedures that are only referenced locally within @@ -266,6 +276,8 @@ Tk_DeleteEventHandler(token, mask, proc, clientData) register InProgress *ipPtr; TkEventHandler *prevPtr; register TkWindow *winPtr = (TkWindow *) token; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Find the event handler to be deleted, or return @@ -288,7 +300,7 @@ Tk_DeleteEventHandler(token, mask, proc, clientData) * process the next one instead. */ - for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { + for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { if (ipPtr->nextHandler == handlerPtr) { ipPtr->nextHandler = handlerPtr->nextPtr; } @@ -337,6 +349,8 @@ Tk_CreateGenericHandler(proc, clientData) ClientData clientData; /* One-word value to pass to proc. */ { GenericHandler *handlerPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); handlerPtr = (GenericHandler *) ckalloc (sizeof (GenericHandler)); @@ -344,12 +358,12 @@ Tk_CreateGenericHandler(proc, clientData) handlerPtr->clientData = clientData; handlerPtr->deleteFlag = 0; handlerPtr->nextPtr = NULL; - if (genericList == NULL) { - genericList = handlerPtr; + if (tsdPtr->genericList == NULL) { + tsdPtr->genericList = handlerPtr; } else { - lastGenericPtr->nextPtr = handlerPtr; + tsdPtr->lastGenericPtr->nextPtr = handlerPtr; } - lastGenericPtr = handlerPtr; + tsdPtr->lastGenericPtr = handlerPtr; } /* @@ -377,8 +391,10 @@ Tk_DeleteGenericHandler(proc, clientData) ClientData clientData; { GenericHandler * handler; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - for (handler = genericList; handler; handler = handler->nextPtr) { + for (handler = tsdPtr->genericList; handler; handler = handler->nextPtr) { if ((handler->proc == proc) && (handler->clientData == clientData)) { handler->deleteFlag = 1; } @@ -388,6 +404,39 @@ Tk_DeleteGenericHandler(proc, clientData) /* *-------------------------------------------------------------- * + * TkEventInit -- + * + * This procedures initializes all the event module + * structures used by the current thread. It must be + * called before any other procedure in this file is + * called. + * + * Results: + * None. + * + * Side Effects: + * None. + * + *-------------------------------------------------------------- + */ + +void +TkEventInit(void) +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + tsdPtr->genericHandlersActive = 0; + tsdPtr->pendingPtr = NULL; + tsdPtr->genericList = NULL; + tsdPtr->lastGenericPtr = NULL; + tsdPtr->restrictProc = NULL; + tsdPtr->restrictArg = NULL; +} + +/* + *-------------------------------------------------------------- + * * Tk_HandleEvent -- * * Given an event, invoke all the handlers that have @@ -415,6 +464,8 @@ Tk_HandleEvent(eventPtr) Window handlerWindow; TkDisplay *dispPtr; Tcl_Interp *interp = (Tcl_Interp *) NULL; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Next, invoke all the generic event handlers (those that are @@ -422,9 +473,10 @@ Tk_HandleEvent(eventPtr) * an event is fully processed, go no further. */ - for (genPrevPtr = NULL, genericPtr = genericList; genericPtr != NULL; ) { + for (genPrevPtr = NULL, genericPtr = tsdPtr->genericList; + genericPtr != NULL; ) { if (genericPtr->deleteFlag) { - if (!genericHandlersActive) { + if (!tsdPtr->genericHandlersActive) { GenericHandler *tmpPtr; /* @@ -435,12 +487,12 @@ Tk_HandleEvent(eventPtr) tmpPtr = genericPtr->nextPtr; if (genPrevPtr == NULL) { - genericList = tmpPtr; + tsdPtr->genericList = tmpPtr; } else { genPrevPtr->nextPtr = tmpPtr; } if (tmpPtr == NULL) { - lastGenericPtr = genPrevPtr; + tsdPtr->lastGenericPtr = genPrevPtr; } (void) ckfree((char *) genericPtr); genericPtr = tmpPtr; @@ -449,9 +501,9 @@ Tk_HandleEvent(eventPtr) } else { int done; - genericHandlersActive++; + tsdPtr->genericHandlersActive++; done = (*genericPtr->proc)(genericPtr->clientData, eventPtr); - genericHandlersActive--; + tsdPtr->genericHandlersActive--; if (done) { return; } @@ -623,8 +675,8 @@ Tk_HandleEvent(eventPtr) ip.eventPtr = eventPtr; ip.winPtr = winPtr; ip.nextHandler = NULL; - ip.nextPtr = pendingPtr; - pendingPtr = &ip; + ip.nextPtr = tsdPtr->pendingPtr; + tsdPtr->pendingPtr = &ip; if (mask == 0) { if ((eventPtr->type == SelectionClear) || (eventPtr->type == SelectionRequest) @@ -657,7 +709,7 @@ Tk_HandleEvent(eventPtr) TkBindEventProc(winPtr, eventPtr); } } - pendingPtr = ip.nextPtr; + tsdPtr->pendingPtr = ip.nextPtr; done: /* @@ -695,6 +747,8 @@ TkEventDeadWindow(winPtr) { register TkEventHandler *handlerPtr; register InProgress *ipPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * While deleting all the handlers, be careful to check for @@ -706,7 +760,8 @@ TkEventDeadWindow(winPtr) while (winPtr->handlerList != NULL) { handlerPtr = winPtr->handlerList; winPtr->handlerList = handlerPtr->nextPtr; - for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { + for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; + ipPtr = ipPtr->nextPtr) { if (ipPtr->nextHandler == handlerPtr) { ipPtr->nextHandler = NULL; } @@ -744,11 +799,13 @@ TkCurrentTime(dispPtr) TkDisplay *dispPtr; /* Display for which the time is desired. */ { register XEvent *eventPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - if (pendingPtr == NULL) { + if (tsdPtr->pendingPtr == NULL) { return dispPtr->lastEventTime; } - eventPtr = pendingPtr->eventPtr; + eventPtr = tsdPtr->pendingPtr->eventPtr; switch (eventPtr->type) { case ButtonPress: case ButtonRelease: @@ -798,11 +855,13 @@ Tk_RestrictEvents(proc, arg, prevArgPtr) * argument. */ { Tk_RestrictProc *prev; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - prev = restrictProc; - *prevArgPtr = restrictArg; - restrictProc = proc; - restrictArg = arg; + prev = tsdPtr->restrictProc; + *prevArgPtr = tsdPtr->restrictArg; + tsdPtr->restrictProc = proc; + tsdPtr->restrictArg = arg; return prev; } @@ -841,7 +900,7 @@ Tk_QueueWindowEvent(eventPtr, position) * Find our display structure for the event's display. */ - for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) { + for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) { if (dispPtr == NULL) { return; } @@ -962,12 +1021,14 @@ WindowEventProc(evPtr, flags) { TkWindowEvent *wevPtr = (TkWindowEvent *) evPtr; Tk_RestrictAction result; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (!(flags & TCL_WINDOW_EVENTS)) { return 0; } - if (restrictProc != NULL) { - result = (*restrictProc)(restrictArg, &wevPtr->event); + if (tsdPtr->restrictProc != NULL) { + result = (*tsdPtr->restrictProc)(tsdPtr->restrictArg, &wevPtr->event); if (result != TK_PROCESS_EVENT) { if (result == TK_DEFER_EVENT) { return 0; diff --git a/generic/tkFocus.c b/generic/tkFocus.c index df6f374..10bfa27 100644 --- a/generic/tkFocus.c +++ b/generic/tkFocus.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkFocus.c,v 1.1.4.2 1998/09/30 02:16:56 stanton Exp $ + * RCS: @(#) $Id: tkFocus.c,v 1.1.4.3 1998/12/13 08:16:04 lfb Exp $ */ #include "tkInt.h" @@ -76,12 +76,6 @@ typedef struct TkDisplayFocusInfo { } DisplayFocusInfo; /* - * Global used for debugging. - */ - -int tclFocusDebug = 0; - -/* * The following magic value is stored in the "send_event" field of * FocusIn and FocusOut events that are generated in this file. This * allows us to separate "real" events coming from the server from @@ -494,7 +488,7 @@ TkFocusFilterEvent(winPtr, eventPtr) if (eventPtr->xcrossing.focus && (displayFocusPtr->focusWinPtr == NULL) && !(winPtr->flags & TK_EMBEDDED)) { - if (tclFocusDebug) { + if (dispPtr->focusDebug) { printf("Focussed implicitly on %s\n", newFocusPtr->pathName); } @@ -519,7 +513,7 @@ TkFocusFilterEvent(winPtr, eventPtr) if ((dispPtr->implicitWinPtr != NULL) && !(winPtr->flags & TK_EMBEDDED)) { - if (tclFocusDebug) { + if (dispPtr->focusDebug) { printf("Defocussed implicit Async\n"); } GenerateFocusEvents(displayFocusPtr->focusWinPtr, @@ -828,7 +822,7 @@ TkFocusDeadWindow(winPtr) */ if (dispPtr->implicitWinPtr == winPtr) { - if (tclFocusDebug) { + if (dispPtr->focusDebug) { printf("releasing focus to root after %s died\n", tlFocusPtr->topLevelPtr->pathName); } @@ -856,7 +850,7 @@ TkFocusDeadWindow(winPtr) tlFocusPtr->focusWinPtr = tlFocusPtr->topLevelPtr; if ((displayFocusPtr->focusWinPtr == winPtr) && !(tlFocusPtr->topLevelPtr->flags & TK_ALREADY_DEAD)) { - if (tclFocusDebug) { + if (dispPtr->focusDebug) { printf("forwarding focus to %s after %s died\n", tlFocusPtr->topLevelPtr->pathName, winPtr->pathName); @@ -951,7 +945,7 @@ FocusMapProc(clientData, eventPtr) if (eventPtr->type == VisibilityNotify) { displayFocusPtr = FindDisplayFocusInfo(winPtr->mainPtr, winPtr->dispPtr); - if (tclFocusDebug) { + if (winPtr->dispPtr->focusDebug) { printf("auto-focussing on %s, force %d\n", winPtr->pathName, displayFocusPtr->forceFocus); } diff --git a/generic/tkGC.c b/generic/tkGC.c index faa3e37..07aaf14 100644 --- a/generic/tkGC.c +++ b/generic/tkGC.c @@ -10,11 +10,11 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkGC.c,v 1.1.4.1 1998/09/30 02:16:59 stanton Exp $ + * RCS: @(#) $Id: tkGC.c,v 1.1.4.2 1998/12/13 08:16:05 lfb Exp $ */ #include "tkPort.h" -#include "tk.h" +#include "tkInt.h" /* * One of the following data structures exists for each GC that is @@ -31,12 +31,6 @@ typedef struct { * this structure). */ } TkGC; -/* - * Hash table to map from a GC's values to a TkGC structure describing - * a GC with those values (used by Tk_GetGC). - */ - -static Tcl_HashTable valueTable; typedef struct { XGCValues values; /* Desired values for GC. */ Display *display; /* Display for which GC is valid. */ @@ -45,24 +39,10 @@ typedef struct { } ValueKey; /* - * Hash table for <display + GC> -> TkGC mapping. This table is used by - * Tk_FreeGC. - */ - -static Tcl_HashTable idTable; -typedef struct { - Display *display; /* Display for which GC was allocated. */ - GC gc; /* X's identifier for GC. */ -} IdKey; - -static int initialized = 0; /* 0 means static structures haven't been - * initialized yet. */ - -/* * Forward declarations for procedures defined in this file: */ -static void GCInit _ANSI_ARGS_((void)); +static void GCInit _ANSI_ARGS_((TkDisplay *dispPtr)); /* *---------------------------------------------------------------------- @@ -98,14 +78,14 @@ Tk_GetGC(tkwin, valueMask, valuePtr) * in valueMask. */ { ValueKey valueKey; - IdKey idKey; Tcl_HashEntry *valueHashPtr, *idHashPtr; register TkGC *gcPtr; int new; Drawable d, freeDrawable; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - if (!initialized) { - GCInit(); + if (!dispPtr->gcInit) { + GCInit(dispPtr); } /* @@ -238,7 +218,8 @@ Tk_GetGC(tkwin, valueMask, valuePtr) valueKey.display = Tk_Display(tkwin); valueKey.screenNum = Tk_ScreenNumber(tkwin); valueKey.depth = Tk_Depth(tkwin); - valueHashPtr = Tcl_CreateHashEntry(&valueTable, (char *) &valueKey, &new); + valueHashPtr = Tcl_CreateHashEntry(&dispPtr->gcValueTable, + (char *) &valueKey, &new); if (!new) { gcPtr = (TkGC *) Tcl_GetHashValue(valueHashPtr); gcPtr->refCount++; @@ -275,9 +256,8 @@ Tk_GetGC(tkwin, valueMask, valuePtr) gcPtr->display = valueKey.display; gcPtr->refCount = 1; gcPtr->valueHashPtr = valueHashPtr; - idKey.display = valueKey.display; - idKey.gc = gcPtr->gc; - idHashPtr = Tcl_CreateHashEntry(&idTable, (char *) &idKey, &new); + idHashPtr = Tcl_CreateHashEntry(&dispPtr->gcIdTable, + (char *) gcPtr->gc, &new); if (!new) { panic("GC already registered in Tk_GetGC"); } @@ -313,17 +293,15 @@ Tk_FreeGC(display, gc) Display *display; /* Display for which gc was allocated. */ GC gc; /* Graphics context to be released. */ { - IdKey idKey; Tcl_HashEntry *idHashPtr; register TkGC *gcPtr; + TkDisplay *dispPtr = TkGetDisplay(display); - if (!initialized) { + if (!dispPtr->gcInit) { panic("Tk_FreeGC called before Tk_GetGC"); } - idKey.display = display; - idKey.gc = gc; - idHashPtr = Tcl_FindHashEntry(&idTable, (char *) &idKey); + idHashPtr = Tcl_FindHashEntry(&dispPtr->gcIdTable, (char *) gc); if (idHashPtr == NULL) { panic("Tk_FreeGC received unknown gc argument"); } @@ -355,9 +333,10 @@ Tk_FreeGC(display, gc) */ static void -GCInit() +GCInit(dispPtr) + TkDisplay *dispPtr; { - initialized = 1; - Tcl_InitHashTable(&valueTable, sizeof(ValueKey)/sizeof(int)); - Tcl_InitHashTable(&idTable, sizeof(IdKey)/sizeof(int)); + dispPtr->gcInit = 1; + Tcl_InitHashTable(&dispPtr->gcValueTable, sizeof(ValueKey)/sizeof(int)); + Tcl_InitHashTable(&dispPtr->gcIdTable, sizeof(GC)/sizeof(int)); } diff --git a/generic/tkGeometry.c b/generic/tkGeometry.c index 5544580..478f059 100644 --- a/generic/tkGeometry.c +++ b/generic/tkGeometry.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkGeometry.c,v 1.1.4.1 1998/09/30 02:16:59 stanton Exp $ + * RCS: @(#) $Id: tkGeometry.c,v 1.1.4.2 1998/12/13 08:16:05 lfb Exp $ */ #include "tkPort.h" @@ -53,19 +53,6 @@ typedef struct MaintainMaster { } MaintainMaster; /* - * Hash table that maps from a master's Tk_Window token to a list of - * Maintains for that master: - */ - -static Tcl_HashTable maintainHashTable; - -/* - * Has maintainHashTable been initialized yet? - */ - -static int initialized = 0; - -/* * Prototypes for static procedures in this file: */ @@ -261,10 +248,11 @@ Tk_MaintainGeometry(slave, master, x, y, width, height) register MaintainSlave *slavePtr; int new, map; Tk_Window ancestor, parent; + TkDisplay *dispPtr = ((TkWindow *) master)->dispPtr; - if (!initialized) { - initialized = 1; - Tcl_InitHashTable(&maintainHashTable, TCL_ONE_WORD_KEYS); + if (!dispPtr->geomInit) { + dispPtr->geomInit = 1; + Tcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS); } /* @@ -273,7 +261,8 @@ Tk_MaintainGeometry(slave, master, x, y, width, height) */ parent = Tk_Parent(slave); - hPtr = Tcl_CreateHashEntry(&maintainHashTable, (char *) master, &new); + hPtr = Tcl_CreateHashEntry(&dispPtr->maintainHashTable, + (char *) master, &new); if (!new) { masterPtr = (MaintainMaster *) Tcl_GetHashValue(hPtr); } else { @@ -383,16 +372,17 @@ Tk_UnmaintainGeometry(slave, master) MaintainMaster *masterPtr; register MaintainSlave *slavePtr, *prevPtr; Tk_Window ancestor; + TkDisplay *dispPtr = ((TkWindow *) slave)->dispPtr; - if (!initialized) { - initialized = 1; - Tcl_InitHashTable(&maintainHashTable, TCL_ONE_WORD_KEYS); + if (!dispPtr->geomInit) { + dispPtr->geomInit = 1; + Tcl_InitHashTable(&dispPtr->maintainHashTable, TCL_ONE_WORD_KEYS); } if (!(((TkWindow *) slave)->flags & TK_ALREADY_DEAD)) { Tk_UnmapWindow(slave); } - hPtr = Tcl_FindHashEntry(&maintainHashTable, (char *) master); + hPtr = Tcl_FindHashEntry(&dispPtr->maintainHashTable, (char *) master); if (hPtr == NULL) { return; } diff --git a/generic/tkGet.c b/generic/tkGet.c index a788419..c6db408 100644 --- a/generic/tkGet.c +++ b/generic/tkGet.c @@ -13,13 +13,26 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkGet.c,v 1.1.4.2 1998/09/30 02:17:00 stanton Exp $ + * RCS: @(#) $Id: tkGet.c,v 1.1.4.3 1998/12/13 08:16:05 lfb Exp $ */ #include "tkInt.h" #include "tkPort.h" /* + * One of these structures is created per thread to store + * thread-specific data. In this case, it is used to house the + * Tk_Uids used by each thread. The "dataKey" below is used to + * locate the ThreadSpecificData for the current thread. + */ + +typedef struct ThreadSpecificData { + int initialized; + Tcl_HashTable uidTable; +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + +/* * The following tables defines the string values for reliefs, which are * used by Tk_GetAnchorFromObj and Tk_GetJustifyFromObj. */ @@ -28,13 +41,6 @@ static char *anchorStrings[] = {"n", "ne", "e", "se", "s", "sw", "w", "nw", "center", (char *) NULL}; static char *justifyStrings[] = {"left", "right", "center", (char *) NULL}; -/* - * The hash table below is used to keep track of all the Tk_Uids created - * so far. - */ - -static Tcl_HashTable uidTable; -static int initialized = 0; /* *---------------------------------------------------------------------- @@ -500,13 +506,16 @@ Tk_GetUid(string) CONST char *string; /* String to convert. */ { int dummy; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tcl_HashTable *tablePtr = &tsdPtr->uidTable; - if (!initialized) { - Tcl_InitHashTable(&uidTable, TCL_STRING_KEYS); - initialized = 1; + if (!tsdPtr->initialized) { + Tcl_InitHashTable(tablePtr, TCL_STRING_KEYS); + tsdPtr->initialized = 1; } - return (Tk_Uid) Tcl_GetHashKey(&uidTable, - Tcl_CreateHashEntry(&uidTable, string, &dummy)); + return (Tk_Uid) Tcl_GetHashKey(tablePtr, + Tcl_CreateHashEntry(tablePtr, string, &dummy)); } /* diff --git a/generic/tkGrab.c b/generic/tkGrab.c index edcf300..cf648b1 100644 --- a/generic/tkGrab.c +++ b/generic/tkGrab.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkGrab.c,v 1.1.4.2 1998/09/30 02:17:00 stanton Exp $ + * RCS: @(#) $Id: tkGrab.c,v 1.1.4.3 1998/12/13 08:16:06 lfb Exp $ */ #include "tkPort.h" @@ -242,7 +242,7 @@ Tk_GrabCmd(clientData, interp, argc, argv) TCL_STATIC); } } else { - for (dispPtr = tkDisplayList; dispPtr != NULL; + for (dispPtr = TkGetDisplayList(); dispPtr != NULL; dispPtr = dispPtr->nextPtr) { if (dispPtr->eventualGrabWinPtr != NULL) { Tcl_AppendElement(interp, diff --git a/generic/tkGrid.c b/generic/tkGrid.c index 05747cf..5184dd0 100644 --- a/generic/tkGrid.c +++ b/generic/tkGrid.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkGrid.c,v 1.1.4.2 1998/09/30 02:17:01 stanton Exp $ + * RCS: @(#) $Id: tkGrid.c,v 1.1.4.3 1998/12/13 08:16:06 lfb Exp $ */ #include "tkInt.h" @@ -222,14 +222,6 @@ typedef struct Gridder { #define DONT_PROPAGATE 2 /* - * Hash table used to map from Tk_Window tokens to corresponding - * Grid structures: - */ - -static Tcl_HashTable gridHashTable; -static int initialized = 0; - -/* * Prototypes for procedures used only in this file: */ @@ -1739,10 +1731,11 @@ GetGrid(tkwin) register Gridder *gridPtr; Tcl_HashEntry *hPtr; int new; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - if (!initialized) { - initialized = 1; - Tcl_InitHashTable(&gridHashTable, TCL_ONE_WORD_KEYS); + if (!dispPtr->gridInit) { + Tcl_InitHashTable(&dispPtr->gridHashTable, TCL_ONE_WORD_KEYS); + dispPtr->gridInit = 1; } /* @@ -1750,7 +1743,7 @@ GetGrid(tkwin) * then create a new one. */ - hPtr = Tcl_CreateHashEntry(&gridHashTable, (char *) tkwin, &new); + hPtr = Tcl_CreateHashEntry(&dispPtr->gridHashTable, (char *) tkwin, &new); if (!new) { return (Gridder *) Tcl_GetHashValue(hPtr); } @@ -2070,6 +2063,7 @@ GridStructureProc(clientData, eventPtr) XEvent *eventPtr; /* Describes what just happened. */ { register Gridder *gridPtr = (Gridder *) clientData; + TkDisplay *dispPtr = ((TkWindow *) gridPtr->tkwin)->dispPtr; if (eventPtr->type == ConfigureNotify) { if (!(gridPtr->flags & REQUESTED_RELAYOUT)) { @@ -2097,7 +2091,7 @@ GridStructureProc(clientData, eventPtr) nextPtr = gridPtr2->nextPtr; gridPtr2->nextPtr = NULL; } - Tcl_DeleteHashEntry(Tcl_FindHashEntry(&gridHashTable, + Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->gridHashTable, (char *) gridPtr->tkwin)); if (gridPtr->flags & REQUESTED_RELAYOUT) { Tk_CancelIdleCall(ArrangeGrid, (ClientData) gridPtr); diff --git a/generic/tkImage.c b/generic/tkImage.c index 90e1b4b..edc42e5 100644 --- a/generic/tkImage.c +++ b/generic/tkImage.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkImage.c,v 1.1.4.2 1998/09/30 02:17:01 stanton Exp $ + * RCS: @(#) $Id: tkImage.c,v 1.1.4.3 1998/12/13 08:16:07 lfb Exp $ */ #include "tkInt.h" @@ -71,12 +71,11 @@ typedef struct ImageMaster { * derived from this name. */ } ImageMaster; -/* - * The following variable points to the first in a list of all known - * image types. - */ - -static Tk_ImageType *imageTypeList = NULL; +typedef struct ThreadSpecificData { + Tk_ImageType *imageTypeList;/* First in a list of all known image + * types. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * Prototypes for local procedures: @@ -110,8 +109,11 @@ Tk_CreateImageType(typePtr) * in by caller. Must not have been passed * to Tk_CreateImageType previously. */ { - typePtr->nextPtr = imageTypeList; - imageTypeList = typePtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + typePtr->nextPtr = tsdPtr->imageTypeList; + tsdPtr->imageTypeList = typePtr; } /* @@ -147,7 +149,9 @@ Tk_ImageCmd(clientData, interp, argc, argv) Tcl_HashEntry *hPtr; Tcl_HashSearch search; char idString[16 + TCL_INTEGER_SPACE], *name; - static int id = 0; + TkDisplay *dispPtr = winPtr->dispPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], @@ -168,7 +172,7 @@ Tk_ImageCmd(clientData, interp, argc, argv) * Look up the image type. */ - for (typePtr = imageTypeList; typePtr != NULL; + for (typePtr = tsdPtr->imageTypeList; typePtr != NULL; typePtr = typePtr->nextPtr) { if ((c == typePtr->name[0]) && (strcmp(argv[2], typePtr->name) == 0)) { @@ -186,8 +190,8 @@ Tk_ImageCmd(clientData, interp, argc, argv) */ if ((argc == 3) || (argv[3][0] == '-')) { - id++; - sprintf(idString, "image%d", id); + dispPtr->imageId++; + sprintf(idString, "image%d", dispPtr->imageId); name = idString; firstOption = 3; } else { @@ -312,7 +316,7 @@ Tk_ImageCmd(clientData, interp, argc, argv) " types\"", (char *) NULL); return TCL_ERROR; } - for (typePtr = imageTypeList; typePtr != NULL; + for (typePtr = tsdPtr->imageTypeList; typePtr != NULL; typePtr = typePtr->nextPtr) { Tcl_AppendElement(interp, typePtr->name); } diff --git a/generic/tkImgGIF.c b/generic/tkImgGIF.c index 53b60cd..6c09fb8 100644 --- a/generic/tkImgGIF.c +++ b/generic/tkImgGIF.c @@ -27,7 +27,7 @@ * | provided "as is" without express or implied warranty. | * +-------------------------------------------------------------------+ * - * RCS: @(#) $Id: tkImgGIF.c,v 1.1.4.2 1998/09/30 02:17:03 stanton Exp $ + * RCS: @(#) $Id: tkImgGIF.c,v 1.1.4.3 1998/12/13 08:16:07 lfb Exp $ */ /* @@ -61,6 +61,17 @@ typedef struct mFile { #include "tkPort.h" /* + * HACK ALERT!! HACK ALERT!! HACK ALERT!! + * This code is hard-wired for reading from files. In order to read + * from a data stream, we'll trick fread so we can reuse the same code + */ + +typedef struct ThreadSpecificData { + int fromData; +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + +/* * The format record for the GIF file format: */ @@ -100,14 +111,6 @@ Tk_PhotoImageFormat tkImgFmtGIF = { #define ReadOK(file,buffer,len) (Fread(buffer, len, 1, file) != 0) /* - * HACK ALERT!! HACK ALERT!! HACK ALERT!! - * This code is hard-wired for reading from files. In order to read - * from a data stream, we'll trick fread so we can reuse the same code - */ - -static int fromData=0; - -/* * Prototypes for local procedures defined in this file: */ @@ -443,15 +446,18 @@ StringReadGIF(interp,string,formatString,imageHandle, int width, height; /* image to copy */ int srcX, srcY; { - int result; - MFile handle; - mInit((unsigned char *)string,&handle); - fromData = 1; - result = FileReadGIF(interp, (Tcl_Channel) &handle, "inline data", - formatString, imageHandle, destX, destY, width, height, - srcX, srcY); - fromData = 0; - return(result); + int result; + MFile handle; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + mInit((unsigned char *)string,&handle); + tsdPtr->fromData = 1; + result = FileReadGIF(interp, (Tcl_Channel) &handle, "inline data", + formatString, imageHandle, destX, destY, width, height, + srcX, srcY); + tsdPtr->fromData = 0; + return(result); } /* @@ -1055,7 +1061,10 @@ Fread(dst, hunk, count, chan) size_t hunk,count; /* how many */ Tcl_Channel chan; { - if (fromData) { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (tsdPtr->fromData) { return(Mread(dst, hunk, count, (MFile *) chan)); } else { return Tcl_Read(chan, (char *) dst, (int) (hunk * count)); diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c index 9455643..701698b 100644 --- a/generic/tkImgPhoto.c +++ b/generic/tkImgPhoto.c @@ -15,7 +15,7 @@ * Department of Computer Science, * Australian National University. * - * RCS: @(#) $Id: tkImgPhoto.c,v 1.1.4.2 1998/09/30 02:17:04 stanton Exp $ + * RCS: @(#) $Id: tkImgPhoto.c,v 1.1.4.3 1998/12/13 08:16:07 lfb Exp $ */ #include "tkInt.h" @@ -290,6 +290,12 @@ Tk_ImageType tkPhotoImageType = { (Tk_ImageType *) NULL /* nextPtr */ }; +typedef struct ThreadSpecificData { + Tk_PhotoImageFormat *formatList; /* Pointer to the first in the + * list of known photo image formats.*/ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + /* * Default configuration */ @@ -331,12 +337,6 @@ static int imgPhotoColorHashInitialized; #define N_COLOR_HASH (sizeof(ColorTableId) / sizeof(int)) /* - * Pointer to the first in the list of known photo image formats. - */ - -static Tk_PhotoImageFormat *formatList = NULL; - -/* * Forward declarations */ @@ -415,13 +415,15 @@ Tk_CreatePhotoImageFormat(formatPtr) * to Tk_CreatePhotoImageFormat previously. */ { Tk_PhotoImageFormat *copyPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); copyPtr = (Tk_PhotoImageFormat *) ckalloc(sizeof(Tk_PhotoImageFormat)); *copyPtr = *formatPtr; copyPtr->name = (char *) ckalloc((unsigned) (strlen(formatPtr->name) + 1)); strcpy(copyPtr->name, formatPtr->name); - copyPtr->nextPtr = formatList; - formatList = copyPtr; + copyPtr->nextPtr = tsdPtr->formatList; + tsdPtr->formatList = copyPtr; } /* @@ -529,6 +531,8 @@ ImgPhotoCmd(clientData, interp, argc, argv) Tcl_Channel chan; Tk_PhotoHandle srcHandle; size_t length; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], @@ -975,7 +979,7 @@ ImgPhotoCmd(clientData, interp, argc, argv) */ matched = 0; - for (imageFormat = formatList; imageFormat != NULL; + for (imageFormat = tsdPtr->formatList; imageFormat != NULL; imageFormat = imageFormat->nextPtr) { if ((options.format == NULL) || (strncasecmp(options.format, imageFormat->name, @@ -3012,6 +3016,8 @@ MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr, { int matched; Tk_PhotoImageFormat *formatPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Scan through the table of file format handlers to find @@ -3019,7 +3025,7 @@ MatchFileFormat(interp, chan, fileName, formatString, imageFormatPtr, */ matched = 0; - for (formatPtr = formatList; formatPtr != NULL; + for (formatPtr = tsdPtr->formatList; formatPtr != NULL; formatPtr = formatPtr->nextPtr) { if (formatString != NULL) { if (strncasecmp(formatString, formatPtr->name, @@ -3102,6 +3108,8 @@ MatchStringFormat(interp, string, formatString, imageFormatPtr, { int matched; Tk_PhotoImageFormat *formatPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Scan through the table of file format handlers to find @@ -3109,7 +3117,7 @@ MatchStringFormat(interp, string, formatString, imageFormatPtr, */ matched = 0; - for (formatPtr = formatList; formatPtr != NULL; + for (formatPtr = tsdPtr->formatList; formatPtr != NULL; formatPtr = formatPtr->nextPtr) { if (formatString != NULL) { if (strncasecmp(formatString, formatPtr->name, diff --git a/generic/tkInt.h b/generic/tkInt.h index cc97d50..ab72990 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: $Id: tkInt.h,v 1.1.4.2 1998/09/30 02:17:05 stanton Exp $ + * RCS: $Id: tkInt.h,v 1.1.4.3 1998/12/13 08:16:08 lfb Exp $ */ #ifndef _TKINT @@ -115,7 +115,9 @@ typedef struct TkCursor { /* * One of the following structures is maintained for each display - * containing a window managed by Tk: + * containing a window managed by Tk. In part, the structure is + * used to store thread-specific data, since each thread will have + * its own TkDisplay structure. */ typedef struct TkDisplay { @@ -127,6 +129,23 @@ typedef struct TkDisplay { * display. */ /* + * Information used primarily by tk3d.c: + */ + + int borderInit; /* 0 means borderTable needs initializing. */ + Tcl_HashTable borderTable; /* Maps from color name to TkBorder + * structure. */ + + /* + * Information used by tkAtom.c only: + */ + + int atomInit; /* 0 means stuff below hasn't been + * initialized yet. */ + Tcl_HashTable nameTable; /* Maps from names to Atom's. */ + Tcl_HashTable atomTable; /* Maps from Atom's back to names. */ + + /* * Information used primarily by tkBind.c: */ @@ -152,6 +171,63 @@ typedef struct TkDisplay { * may be NULL. */ /* + * Information used by tkBitmap.c only: + */ + + int bitmapInit; /* 0 means tables above need initializing. */ + int bitmapAutoNumber; /* Used to number bitmaps. */ + Tcl_HashTable bitmapNameTable; + /* Maps from name of bitmap to the first + * TkBitmap record for that name. */ + Tcl_HashTable bitmapIdTable;/* Maps from bitmap id to the TkBitmap + * structure for the bitmap. */ + Tcl_HashTable bitmapDataTable; + /* Used by Tk_GetBitmapFromData to map from + * a collection of in-core data about a + * bitmap to a reference giving an auto- + * matically-generated name for the bitmap. */ + + /* + * Information used by tkCanvas.c only: + */ + + int numIdSearches; + int numSlowSearches; + + /* + * Used by tkColor.c only: + */ + + int colorInit; /* 0 means color module needs initializing. */ + TkStressedCmap *stressPtr; /* First in list of colormaps that have + * filled up, so we have to pick an + * approximate color. */ + Tcl_HashTable colorNameTable; + /* Maps from color name to TkColor structure + * for that color. */ + Tcl_HashTable colorValueTable; + /* Maps from integer RGB values to TkColor + * structures. */ + + /* + * Used by tkCursor.c only: + */ + + int cursorInit; /* 0 means cursor module need initializing. */ + Tcl_HashTable cursorNameTable; + /* Maps from a string name to a cursor to the + * TkCursor record for the cursor. */ + Tcl_HashTable cursorDataTable; + /* Maps from a collection of in-core data + * about a cursor to a TkCursor structure. */ + Tcl_HashTable cursorIdTable; + /* Maps from a cursor id to the TkCursor + * structure for the cursor. */ + char cursorString[20]; /* Used to store a cursor id string. */ + Font cursorFont; /* Font to use for standard cursors. + * None means font not loaded yet. */ + + /* * Information used by tkError.c only: */ @@ -165,68 +241,65 @@ typedef struct TkDisplay { * gets big, handlers get cleaned up. */ /* - * Information used by tkSend.c only: + * Used by tkEvent.c only: */ - Tk_Window commTkwin; /* Window used for communication - * between interpreters during "send" - * commands. NULL means send info hasn't - * been initialized yet. */ - Atom commProperty; /* X's name for comm property. */ - Atom registryProperty; /* X's name for property containing - * registry of interpreter names. */ - Atom appNameProperty; /* X's name for property used to hold the - * application name on each comm window. */ + struct TkWindowEvent *delayedMotionPtr; + /* Points to a malloc-ed motion event + * whose processing has been delayed in + * the hopes that another motion event + * will come along right away and we can + * merge the two of them together. NULL + * means that there is no delayed motion + * event. */ /* - * Information used by tkSelect.c and tkClipboard.c only: + * Information used by tkFocus.c only: */ - struct TkSelectionInfo *selectionInfoPtr; - /* First in list of selection information - * records. Each entry contains information - * about the current owner of a particular - * selection on this display. */ - Atom multipleAtom; /* Atom for MULTIPLE. None means - * selection stuff isn't initialized. */ - Atom incrAtom; /* Atom for INCR. */ - Atom targetsAtom; /* Atom for TARGETS. */ - Atom timestampAtom; /* Atom for TIMESTAMP. */ - Atom textAtom; /* Atom for TEXT. */ - Atom compoundTextAtom; /* Atom for COMPOUND_TEXT. */ - Atom applicationAtom; /* Atom for TK_APPLICATION. */ - Atom windowAtom; /* Atom for TK_WINDOW. */ - Atom clipboardAtom; /* Atom for CLIPBOARD. */ + int focusDebug; /* 1 means collect focus debugging + * statistics. */ + struct TkWindow *implicitWinPtr; + /* If the focus arrived at a toplevel window + * implicitly via an Enter event (rather + * than via a FocusIn event), this points + * to the toplevel window. Otherwise it is + * NULL. */ + struct TkWindow *focusPtr; /* Points to the window on this display that + * should be receiving keyboard events. When + * multiple applications on the display have + * the focus, this will refer to the + * innermost window in the innermost + * application. This information isn't used + * under Unix or Windows, but it's needed on + * the Macintosh. */ - Tk_Window clipWindow; /* Window used for clipboard ownership and to - * retrieve selections between processes. NULL - * means clipboard info hasn't been - * initialized. */ - int clipboardActive; /* 1 means we currently own the clipboard - * selection, 0 means we don't. */ - struct TkMainInfo *clipboardAppPtr; - /* Last application that owned clipboard. */ - struct TkClipboardTarget *clipTargetPtr; - /* First in list of clipboard type information - * records. Each entry contains information - * about the buffers for a given selection - * target. */ + /* + * Information used by tkGC.c only: + */ + + Tcl_HashTable gcValueTable; /* Maps from a GC's values to a TkGC structure + * describing a GC with those values. */ + Tcl_HashTable gcIdTable; /* Maps from a GC to a TkGC. */ + int gcInit; /* 0 means the tables below need + * initializing. */ /* - * Information used by tkAtom.c only: + * Information used by tkGeometry.c only: */ - int atomInit; /* 0 means stuff below hasn't been - * initialized yet. */ - Tcl_HashTable nameTable; /* Maps from names to Atom's. */ - Tcl_HashTable atomTable; /* Maps from Atom's back to names. */ + Tcl_HashTable maintainHashTable; + /* Hash table that maps from a master's + * Tk_Window token to a list of slaves + * managed by that master. */ + int geomInit; /* - * Information used by tkCursor.c only: + * Information used by tkGet.c only: */ - - Font cursorFont; /* Font to use for standard cursors. - * None means font not loaded yet. */ + + Tcl_HashTable uidTable; /* Stores all Tk_Uids used in a thread. */ + int uidInit; /* 0 means uidTable needs initializing. */ /* * Information used by tkGrab.c only: @@ -264,6 +337,100 @@ typedef struct TkDisplay { * in tkGrab.c. */ /* + * Information used by tkGrid.c only: + */ + + int gridInit; /* 0 means table below needs initializing. */ + Tcl_HashTable gridHashTable;/* Maps from Tk_Window tokens to + * corresponding Grid structures. */ + + /* + * Information used by tkImage.c only: + */ + + int imageId; /* Value used to number image ids. */ + + /* + * Information used by tkMacWinMenu.c only: + */ + + int postCommandGeneration; + + /* + * Information used by tkOption.c only. + */ + + + + /* + * Information used by tkPack.c only. + */ + + int packInit; /* 0 means table below needs initializing. */ + Tcl_HashTable packerHashTable; + /* Maps from Tk_Window tokens to + * corresponding Packer structures. */ + + + /* + * Information used by tkPlace.c only. + */ + + int placeInit; /* 0 means tables below need initializing. */ + Tcl_HashTable masterTable; /* Maps from Tk_Window toke to the Master + * structure for the window, if it exists. */ + Tcl_HashTable slaveTable; /* Maps from Tk_Window toke to the Slave + * structure for the window, if it exists. */ + + /* + * Information used by tkSelect.c and tkClipboard.c only: + */ + + struct TkSelectionInfo *selectionInfoPtr; + /* First in list of selection information + * records. Each entry contains information + * about the current owner of a particular + * selection on this display. */ + Atom multipleAtom; /* Atom for MULTIPLE. None means + * selection stuff isn't initialized. */ + Atom incrAtom; /* Atom for INCR. */ + Atom targetsAtom; /* Atom for TARGETS. */ + Atom timestampAtom; /* Atom for TIMESTAMP. */ + Atom textAtom; /* Atom for TEXT. */ + Atom compoundTextAtom; /* Atom for COMPOUND_TEXT. */ + Atom applicationAtom; /* Atom for TK_APPLICATION. */ + Atom windowAtom; /* Atom for TK_WINDOW. */ + Atom clipboardAtom; /* Atom for CLIPBOARD. */ + + Tk_Window clipWindow; /* Window used for clipboard ownership and to + * retrieve selections between processes. NULL + * means clipboard info hasn't been + * initialized. */ + int clipboardActive; /* 1 means we currently own the clipboard + * selection, 0 means we don't. */ + struct TkMainInfo *clipboardAppPtr; + /* Last application that owned clipboard. */ + struct TkClipboardTarget *clipTargetPtr; + /* First in list of clipboard type information + * records. Each entry contains information + * about the buffers for a given selection + * target. */ + + /* + * Information used by tkSend.c only: + */ + + Tk_Window commTkwin; /* Window used for communication + * between interpreters during "send" + * commands. NULL means send info hasn't + * been initialized yet. */ + Atom commProperty; /* X's name for comm property. */ + Atom registryProperty; /* X's name for property containing + * registry of interpreter names. */ + Atom appNameProperty; /* X's name for property used to hold the + * application name on each comm window. */ + + /* * Information used by tkXId.c only: */ @@ -282,6 +449,19 @@ typedef struct TkDisplay { * hasn't. */ /* + * Information used by tkUnixWm.c and tkWinWm.c only: + */ + + int wmTracing; /* Used to enable or disable tracing in + * this module. If tracing is enabled, + * then information is printed on + * standard output about interesting + * interactions with the window manager. */ + struct TkWmInfo *firstWmPtr; /* Points to first top-level window. */ + struct TkWmInfo *foregroundWmPtr; + /* Points to the foreground window. */ + + /* * Information maintained by tkWindow.c for use later on by tkXId.c: */ @@ -302,46 +482,6 @@ typedef struct TkDisplay { * allocated for this display. */ /* - * Information used by tkFocus.c only: - */ - - struct TkWindow *implicitWinPtr; - /* If the focus arrived at a toplevel window - * implicitly via an Enter event (rather - * than via a FocusIn event), this points - * to the toplevel window. Otherwise it is - * NULL. */ - struct TkWindow *focusPtr; /* Points to the window on this display that - * should be receiving keyboard events. When - * multiple applications on the display have - * the focus, this will refer to the - * innermost window in the innermost - * application. This information isn't used - * under Unix or Windows, but it's needed on - * the Macintosh. */ - - /* - * Used by tkColor.c only: - */ - - TkStressedCmap *stressPtr; /* First in list of colormaps that have - * filled up, so we have to pick an - * approximate color. */ - - /* - * Used by tkEvent.c only: - */ - - struct TkWindowEvent *delayedMotionPtr; - /* Points to a malloc-ed motion event - * whose processing has been delayed in - * the hopes that another motion event - * will come along right away and we can - * merge the two of them together. NULL - * means that there is no delayed motion - * event. */ - - /* * Miscellaneous information: */ @@ -392,6 +532,9 @@ typedef struct TkErrorHandler { * list. */ } TkErrorHandler; + + + /* * One of the following structures exists for each event handler * created by calling Tk_CreateEventHandler. This information @@ -802,6 +945,7 @@ EXTERN void TkDrawInsetFocusHighlight _ANSI_ARGS_(( EXTERN void TkEventCleanupProc _ANSI_ARGS_(( ClientData clientData, Tcl_Interp *interp)); EXTERN void TkEventDeadWindow _ANSI_ARGS_((TkWindow *winPtr)); +EXTERN void TkEventInit _ANSI_ARGS_((void)); EXTERN void TkFillPolygon _ANSI_ARGS_((Tk_Canvas canvas, double *coordPtr, int numPoints, Display *display, Drawable drawable, GC gc, GC outlineGC)); @@ -825,6 +969,7 @@ EXTERN void TkFreeWindowId _ANSI_ARGS_((TkDisplay *dispPtr, Window w)); EXTERN void TkGenerateActivateEvents _ANSI_ARGS_(( TkWindow *winPtr, int active)); +EXTERN Tcl_HashTable * TkGetBitmapPredefTabel _ANSI_ARGS_((void)); EXTERN char * TkGetBitmapData _ANSI_ARGS_((Tcl_Interp *interp, char *string, char *fileName, int *widthPtr, int *heightPtr, int *hotXPtr, int *hotYPtr)); @@ -836,12 +981,14 @@ EXTERN TkCursor * TkGetCursorByName _ANSI_ARGS_((Tcl_Interp *interp, EXTERN char * TkGetDefaultScreenName _ANSI_ARGS_((Tcl_Interp *interp, char *screenName)); EXTERN TkDisplay * TkGetDisplay _ANSI_ARGS_((Display *display)); +EXTERN TkDisplay * TkGetDisplayList _ANSI_ARGS_((void)); EXTERN int TkGetDisplayOf _ANSI_ARGS_((Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], Tk_Window *tkwinPtr)); EXTERN TkWindow * TkGetFocusWin _ANSI_ARGS_((TkWindow *winPtr)); EXTERN int TkGetInterpNames _ANSI_ARGS_((Tcl_Interp *interp, Tk_Window tkwin)); +EXTERN TkMainInfo * TkGetMainInfoList _ANSI_ARGS_((void)); EXTERN int TkGetMiterPoints _ANSI_ARGS_((double p1[], double p2[], double p3[], double width, double m1[], double m2[])); diff --git a/generic/tkMacWinMenu.c b/generic/tkMacWinMenu.c index 1f88c7d..dd8e2ac 100644 --- a/generic/tkMacWinMenu.c +++ b/generic/tkMacWinMenu.c @@ -9,12 +9,16 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacWinMenu.c,v 1.1.4.2 1998/09/30 02:17:07 stanton Exp $ + * RCS: @(#) $Id: tkMacWinMenu.c,v 1.1.4.3 1998/12/13 08:16:08 lfb Exp $ */ #include "tkMenu.h" -static int postCommandGeneration; +typedef struct ThreadSpecificData { + int postCommandGeneration; +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + static int PreprocessMenu _ANSI_ARGS_((TkMenu *menuPtr)); @@ -43,6 +47,8 @@ PreprocessMenu(menuPtr) { int index, result, finished; TkMenu *cascadeMenuPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); Tcl_Preserve((ClientData) menuPtr); @@ -74,9 +80,9 @@ PreprocessMenu(menuPtr) cascadeMenuPtr = menuPtr->entries[index]->childMenuRefPtr->menuPtr; if (cascadeMenuPtr->postCommandGeneration != - postCommandGeneration) { + tsdPtr->postCommandGeneration) { cascadeMenuPtr->postCommandGeneration = - postCommandGeneration; + tsdPtr->postCommandGeneration; result = PreprocessMenu(cascadeMenuPtr); if (result != TCL_OK) { goto done; @@ -128,7 +134,10 @@ int TkPreprocessMenu(menuPtr) TkMenu *menuPtr; { - postCommandGeneration++; - menuPtr->postCommandGeneration = postCommandGeneration; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + tsdPtr->postCommandGeneration++; + menuPtr->postCommandGeneration = tsdPtr->postCommandGeneration; return PreprocessMenu(menuPtr); } diff --git a/generic/tkMain.c b/generic/tkMain.c index c03cf7a..0d46bad 100644 --- a/generic/tkMain.c +++ b/generic/tkMain.c @@ -13,7 +13,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMain.c,v 1.1.4.3 1998/12/11 23:32:22 stanton Exp $ + * RCS: @(#) $Id: tkMain.c,v 1.1.4.4 1998/12/13 08:16:09 lfb Exp $ */ #include <ctype.h> @@ -27,6 +27,18 @@ # include <stdlib.h> #endif +typedef struct ThreadSpecificData { + Tcl_Interp *interp; /* Interpreter for this thread. */ + Tcl_DString command; /* Used to assemble lines of terminal input + * into Tcl commands. */ + Tcl_DString line; /* Used to read the next line from the + * terminal input. */ + int tty; /* Non-zero means standard input is a + * terminal-like device. Zero means it's + * a file. */ +} ThreadSpecificData; +Tcl_ThreadDataKey dataKey; + /* * Declarations for various library procedures and variables (don't want * to include tkInt.h or tkPort.h here, because people might copy this @@ -44,19 +56,6 @@ extern void TkpDisplayWarning _ANSI_ARGS_((char *msg, char *title)); /* - * Global variables used by the main program: - */ - -static Tcl_Interp *interp; /* Interpreter for this application. */ -static Tcl_DString command; /* Used to assemble lines of terminal input - * into Tcl commands. */ -static Tcl_DString line; /* Used to read the next line from the - * terminal input. */ -static int tty; /* Non-zero means standard input is a - * terminal-like device. Zero means it's - * a file. */ - -/* * Forward declarations for procedures defined later in this file. */ @@ -98,9 +97,12 @@ Tk_Main(argc, argv, appInitProc) size_t length; Tcl_Channel inChannel, outChannel; Tcl_DString argString; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tcl_Interp *interp; Tcl_FindExecutable(argv[0]); - interp = Tcl_CreateInterp(); + interp = tsdPtr->interp = Tcl_CreateInterp(); #ifdef TCL_MEM_DEBUG Tcl_InitMemory(interp); #endif @@ -158,12 +160,12 @@ Tk_Main(argc, argv, appInitProc) */ #ifdef __WIN32__ - tty = 1; + tsdPtr->tty = 1; #else - tty = isatty(0); + tsdPtr->tty = isatty(0); #endif Tcl_SetVar(interp, "tcl_interactive", - ((fileName == NULL) && tty) ? "1" : "0", TCL_GLOBAL_ONLY); + ((fileName == NULL) && tsdPtr->tty) ? "1" : "0", TCL_GLOBAL_ONLY); /* * Invoke application-specific initialization. @@ -192,7 +194,7 @@ Tk_Main(argc, argv, appInitProc) Tcl_DeleteInterp(interp); Tcl_Exit(1); } - tty = 0; + tsdPtr->tty = 0; } else { /* @@ -210,7 +212,7 @@ Tk_Main(argc, argv, appInitProc) Tcl_CreateChannelHandler(inChannel, TCL_READABLE, StdinProc, (ClientData) inChannel); } - if (tty) { + if (tsdPtr->tty) { Prompt(interp, 0); } } @@ -220,8 +222,8 @@ Tk_Main(argc, argv, appInitProc) if (outChannel) { Tcl_Flush(outChannel); } - Tcl_DStringInit(&command); - Tcl_DStringInit(&line); + Tcl_DStringInit(&tsdPtr->command); + Tcl_DStringInit(&tsdPtr->line); Tcl_ResetResult(interp); /* @@ -264,12 +266,15 @@ StdinProc(clientData, mask) char *cmd; int code, count; Tcl_Channel chan = (Tcl_Channel) clientData; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + Tcl_Interp *interp = tsdPtr->interp; - count = Tcl_Gets(chan, &line); + count = Tcl_Gets(chan, &tsdPtr->line); if (count < 0) { if (!gotPartial) { - if (tty) { + if (tsdPtr->tty) { Tcl_Exit(0); } else { Tcl_DeleteChannelHandler(chan, StdinProc, (ClientData) chan); @@ -278,9 +283,10 @@ StdinProc(clientData, mask) } } - (void) Tcl_DStringAppend(&command, Tcl_DStringValue(&line), -1); - cmd = Tcl_DStringAppend(&command, "\n", -1); - Tcl_DStringFree(&line); + (void) Tcl_DStringAppend(&tsdPtr->command, Tcl_DStringValue( + &tsdPtr->line), -1); + cmd = Tcl_DStringAppend(&tsdPtr->command, "\n", -1); + Tcl_DStringFree(&tsdPtr->line); if (!Tcl_CommandComplete(cmd)) { gotPartial = 1; goto prompt; @@ -303,9 +309,9 @@ StdinProc(clientData, mask) Tcl_CreateChannelHandler(chan, TCL_READABLE, StdinProc, (ClientData) chan); } - Tcl_DStringFree(&command); + Tcl_DStringFree(&tsdPtr->command); if (Tcl_GetStringResult(interp)[0] != '\0') { - if ((code != TCL_OK) || (tty)) { + if ((code != TCL_OK) || (tsdPtr->tty)) { chan = Tcl_GetStdChannel(TCL_STDOUT); if (chan) { Tcl_WriteObj(chan, Tcl_GetObjResult(interp)); @@ -319,7 +325,7 @@ StdinProc(clientData, mask) */ prompt: - if (tty) { + if (tsdPtr->tty) { Prompt(interp, gotPartial); } Tcl_ResetResult(interp); diff --git a/generic/tkMenubutton.c b/generic/tkMenubutton.c index 8249816..2ee8b35 100644 --- a/generic/tkMenubutton.c +++ b/generic/tkMenubutton.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMenubutton.c,v 1.1.4.2 1998/09/30 02:17:10 stanton Exp $ + * RCS: @(#) $Id: tkMenubutton.c,v 1.1.4.3 1998/12/13 08:16:09 lfb Exp $ */ #include "tkMenubutton.h" @@ -26,6 +26,7 @@ static Tk_Uid belowUid = NULL; static Tk_Uid leftUid = NULL; static Tk_Uid rightUid = NULL; static Tk_Uid flushUid = NULL; +TCL_DECLARE_MUTEX(menuButMutex) /* * Information used for parsing configuration specs: @@ -250,12 +251,16 @@ Tk_MenubuttonCmd(clientData, interp, argc, argv) mbPtr->cursor = None; mbPtr->takeFocus = NULL; mbPtr->flags = 0; - if (aboveUid == NULL) { - aboveUid = Tk_GetUid("above"); - belowUid = Tk_GetUid("below"); - leftUid = Tk_GetUid("left"); - rightUid = Tk_GetUid("right"); - flushUid = Tk_GetUid("flush"); + if (flushUid == NULL) { + Tcl_MutexLock(&menuButMutex); + if (flushUid == NULL) { + aboveUid = Tk_GetUid("above"); + belowUid = Tk_GetUid("below"); + leftUid = Tk_GetUid("left"); + rightUid = Tk_GetUid("right"); + flushUid = Tk_GetUid("flush"); + } + Tcl_MutexLock(&menuButMutex); } mbPtr->direction = flushUid; diff --git a/generic/tkOption.c b/generic/tkOption.c index a3fbbe2..6b3fd49 100644 --- a/generic/tkOption.c +++ b/generic/tkOption.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkOption.c,v 1.1.4.2 1998/09/30 02:17:13 stanton Exp $ + * RCS: @(#) $Id: tkOption.c,v 1.1.4.3 1998/12/13 08:16:09 lfb Exp $ */ #include "tkPort.h" @@ -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; @@ -474,6 +479,8 @@ Tk_OptionCmd(clientData, interp, argc, argv) Tk_Window tkwin = (Tk_Window) clientData; size_t length; char c; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (argc < 2) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], @@ -513,7 +520,7 @@ Tk_OptionCmd(clientData, interp, argc, argv) ClearOptionTree(mainPtr->optionRootPtr); mainPtr->optionRootPtr = NULL; } - cachedWindow = NULL; + tsdPtr->cachedWindow = NULL; return TCL_OK; } else if ((c == 'g') && (strncmp(argv[1], "get", length) == 0)) { Tk_Window window; @@ -581,6 +588,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 +598,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 +642,8 @@ TkOptionClassChanged(winPtr) { int i, j, *basePtr; ElArray *arrayPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr->optionLevel == -1) { return; @@ -642,22 +654,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; } @@ -1069,6 +1081,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 @@ -1093,7 +1107,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; } @@ -1107,19 +1121,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 @@ -1127,11 +1141,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; } @@ -1145,33 +1159,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; /* @@ -1191,7 +1213,7 @@ SetupStacks(winPtr, leaf) } else { id = winPtr->nameUid; } - elPtr = stacks[i]->els; + elPtr = tsdPtr->stacks[i]->els; count = levelPtr->bases[i]; /* @@ -1210,7 +1232,7 @@ SetupStacks(winPtr, leaf) ExtendStacks(elPtr->child.arrayPtr, leaf); } } - cachedWindow = winPtr; + tsdPtr->cachedWindow = winPtr; } /* @@ -1239,13 +1261,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); } } @@ -1273,24 +1298,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; } /* diff --git a/generic/tkPack.c b/generic/tkPack.c index 257a09a..93e8e25 100644 --- a/generic/tkPack.c +++ b/generic/tkPack.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkPack.c,v 1.1.4.2 1998/09/30 02:17:13 stanton Exp $ + * RCS: @(#) $Id: tkPack.c,v 1.1.4.3 1998/12/13 08:16:10 lfb Exp $ */ #include "tkPort.h" @@ -96,19 +96,6 @@ typedef struct Packer { #define DONT_PROPAGATE 32 /* - * Hash table used to map from Tk_Window tokens to corresponding - * Packer structures: - */ - -static Tcl_HashTable packerHashTable; - -/* - * Have statics in this module been initialized? - */ - -static int initialized = 0; - -/* * The following structure is the official type record for the * packer: */ @@ -957,10 +944,11 @@ GetPacker(tkwin) register Packer *packPtr; Tcl_HashEntry *hPtr; int new; + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; - if (!initialized) { - initialized = 1; - Tcl_InitHashTable(&packerHashTable, TCL_ONE_WORD_KEYS); + if (!dispPtr->packInit) { + dispPtr->packInit = 1; + Tcl_InitHashTable(&dispPtr->packerHashTable, TCL_ONE_WORD_KEYS); } /* @@ -968,7 +956,8 @@ GetPacker(tkwin) * then create a new one. */ - hPtr = Tcl_CreateHashEntry(&packerHashTable, (char *) tkwin, &new); + hPtr = Tcl_CreateHashEntry(&dispPtr->packerHashTable, (char *) tkwin, + &new); if (!new) { return (Packer *) Tcl_GetHashValue(hPtr); } @@ -1324,6 +1313,8 @@ PackStructureProc(clientData, eventPtr) XEvent *eventPtr; /* Describes what just happened. */ { register Packer *packPtr = (Packer *) clientData; + TkDisplay *dispPtr; + if (eventPtr->type == ConfigureNotify) { if ((packPtr->slavePtr != NULL) && !(packPtr->flags & REQUESTED_REPACK)) { @@ -1353,8 +1344,11 @@ PackStructureProc(clientData, eventPtr) nextPtr = slavePtr->nextPtr; slavePtr->nextPtr = NULL; } - Tcl_DeleteHashEntry(Tcl_FindHashEntry(&packerHashTable, - (char *) packPtr->tkwin)); + if (packPtr->tkwin != NULL) { + dispPtr = ((TkWindow *) packPtr->tkwin)->dispPtr; + Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->packerHashTable, + (char *) packPtr->tkwin)); + } if (packPtr->flags & REQUESTED_REPACK) { Tcl_CancelIdleCall(ArrangePacking, (ClientData) packPtr); } diff --git a/generic/tkPlace.c b/generic/tkPlace.c index 1771b90..89308bd 100644 --- a/generic/tkPlace.c +++ b/generic/tkPlace.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkPlace.c,v 1.1.4.2 1998/09/30 02:17:14 stanton Exp $ + * RCS: @(#) $Id: tkPlace.c,v 1.1.4.3 1998/12/13 08:16:10 lfb Exp $ */ #include "tkPort.h" @@ -99,15 +99,6 @@ typedef struct Master { #define PARENT_RECONFIG_PENDING 1 /* - * The hash tables below both use Tk_Window tokens as keys. They map - * from Tk_Windows to Slave and Master structures for windows, if they - * exist. - */ - -static int initialized = 0; -static Tcl_HashTable masterTable; -static Tcl_HashTable slaveTable; -/* * The following structure is the official type record for the * placer: */ @@ -168,15 +159,18 @@ Tk_PlaceCmd(clientData, interp, argc, argv) Tcl_HashEntry *hPtr; size_t length; int c; + TkDisplay *dispPtr; + + dispPtr = ((TkWindow *) clientData)->dispPtr; /* * Initialize, if that hasn't been done yet. */ - if (!initialized) { - Tcl_InitHashTable(&masterTable, TCL_ONE_WORD_KEYS); - Tcl_InitHashTable(&slaveTable, TCL_ONE_WORD_KEYS); - initialized = 1; + if (!dispPtr->placeInit) { + Tcl_InitHashTable(&dispPtr->masterTable, TCL_ONE_WORD_KEYS); + Tcl_InitHashTable(&dispPtr->slaveTable, TCL_ONE_WORD_KEYS); + dispPtr->placeInit = 1; } if (argc < 3) { @@ -225,7 +219,7 @@ Tk_PlaceCmd(clientData, interp, argc, argv) argv[0], " forget pathName\"", (char *) NULL); return TCL_ERROR; } - hPtr = Tcl_FindHashEntry(&slaveTable, (char *) tkwin); + hPtr = Tcl_FindHashEntry(&dispPtr->slaveTable, (char *) tkwin); if (hPtr == NULL) { return TCL_OK; } @@ -250,7 +244,7 @@ Tk_PlaceCmd(clientData, interp, argc, argv) argv[0], " info pathName\"", (char *) NULL); return TCL_ERROR; } - hPtr = Tcl_FindHashEntry(&slaveTable, (char *) tkwin); + hPtr = Tcl_FindHashEntry(&dispPtr->slaveTable, (char *) tkwin); if (hPtr == NULL) { return TCL_OK; } @@ -306,7 +300,7 @@ Tk_PlaceCmd(clientData, interp, argc, argv) argv[0], " slaves pathName\"", (char *) NULL); return TCL_ERROR; } - hPtr = Tcl_FindHashEntry(&masterTable, (char *) tkwin); + hPtr = Tcl_FindHashEntry(&dispPtr->masterTable, (char *) tkwin); if (hPtr != NULL) { Master *masterPtr; masterPtr = (Master *) Tcl_GetHashValue(hPtr); @@ -348,8 +342,9 @@ FindSlave(tkwin) Tcl_HashEntry *hPtr; register Slave *slavePtr; int new; + TkDisplay * dispPtr = ((TkWindow *) tkwin)->dispPtr; - hPtr = Tcl_CreateHashEntry(&slaveTable, (char *) tkwin, &new); + hPtr = Tcl_CreateHashEntry(&dispPtr->slaveTable, (char *) tkwin, &new); if (new) { slavePtr = (Slave *) ckalloc(sizeof(Slave)); slavePtr->tkwin = tkwin; @@ -441,8 +436,9 @@ FindMaster(tkwin) Tcl_HashEntry *hPtr; register Master *masterPtr; int new; + TkDisplay * dispPtr = ((TkWindow *) tkwin)->dispPtr; - hPtr = Tcl_CreateHashEntry(&masterTable, (char *) tkwin, &new); + hPtr = Tcl_CreateHashEntry(&dispPtr->masterTable, (char *) tkwin, &new); if (new) { masterPtr = (Master *) ckalloc(sizeof(Master)); masterPtr->tkwin = tkwin; @@ -902,6 +898,7 @@ MasterStructureProc(clientData, eventPtr) { register Master *masterPtr = (Master *) clientData; register Slave *slavePtr, *nextPtr; + TkDisplay *dispPtr = ((TkWindow *) masterPtr->tkwin)->dispPtr; if (eventPtr->type == ConfigureNotify) { if ((masterPtr->slavePtr != NULL) @@ -916,7 +913,7 @@ MasterStructureProc(clientData, eventPtr) nextPtr = slavePtr->nextPtr; slavePtr->nextPtr = NULL; } - Tcl_DeleteHashEntry(Tcl_FindHashEntry(&masterTable, + Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->masterTable, (char *) masterPtr->tkwin)); if (masterPtr->flags & PARENT_RECONFIG_PENDING) { Tcl_CancelIdleCall(RecomputePlacement, (ClientData) masterPtr); @@ -971,10 +968,11 @@ SlaveStructureProc(clientData, eventPtr) XEvent *eventPtr; /* Describes what just happened. */ { register Slave *slavePtr = (Slave *) clientData; + TkDisplay * dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr; if (eventPtr->type == DestroyNotify) { UnlinkSlave(slavePtr); - Tcl_DeleteHashEntry(Tcl_FindHashEntry(&slaveTable, + Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable, (char *) slavePtr->tkwin)); ckfree((char *) slavePtr); } @@ -1047,13 +1045,15 @@ PlaceLostSlaveProc(clientData, tkwin) Tk_Window tkwin; /* Tk's handle for the slave window. */ { register Slave *slavePtr = (Slave *) clientData; + TkDisplay * dispPtr = ((TkWindow *) slavePtr->tkwin)->dispPtr; if (slavePtr->masterPtr->tkwin != Tk_Parent(slavePtr->tkwin)) { Tk_UnmaintainGeometry(slavePtr->tkwin, slavePtr->masterPtr->tkwin); } Tk_UnmapWindow(tkwin); UnlinkSlave(slavePtr); - Tcl_DeleteHashEntry(Tcl_FindHashEntry(&slaveTable, (char *) tkwin)); + Tcl_DeleteHashEntry(Tcl_FindHashEntry(&dispPtr->slaveTable, + (char *) tkwin)); Tk_DeleteEventHandler(tkwin, StructureNotifyMask, SlaveStructureProc, (ClientData) slavePtr); ckfree((char *) slavePtr); diff --git a/generic/tkPointer.c b/generic/tkPointer.c index af42d6a..6361421 100644 --- a/generic/tkPointer.c +++ b/generic/tkPointer.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkPointer.c,v 1.1.4.1 1998/09/30 02:17:15 stanton Exp $ + * RCS: @(#) $Id: tkPointer.c,v 1.1.4.2 1998/12/13 08:16:10 lfb Exp $ */ #include "tkInt.h" @@ -32,19 +32,18 @@ static unsigned int buttonMasks[] = { }; #define ButtonMask(b) (buttonMasks[(b)-Button1]) -/* - * Declarations of static variables used in the pointer module. - */ - -static TkWindow *cursorWinPtr = NULL; /* Window that is currently - * controlling the global cursor. */ -static TkWindow *grabWinPtr = NULL; /* Window that defines the top of the +typedef struct ThreadSpecificData { + TkWindow *grabWinPtr; /* Window that defines the top of the * grab tree in a global grab. */ -static XPoint lastPos = { 0, 0}; /* Last reported mouse position. */ -static int lastState = 0; /* Last known state flags. */ -static TkWindow *lastWinPtr = NULL; /* Last reported mouse window. */ -static TkWindow *restrictWinPtr = NULL; /* Window to which all mouse events + int lastState; /* Last known state flags. */ + XPoint lastPos; /* Last reported mouse position. */ + TkWindow *lastWinPtr; /* Last reported mouse window. */ + TkWindow *restrictWinPtr; /* Window to which all mouse events * will be reported. */ + TkWindow *cursorWinPtr; /* Window that is currently + * controlling the global cursor. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * Forward declarations of procedures used in this file. @@ -137,8 +136,12 @@ GenerateEnterLeave(winPtr, x, y, state) int state; /* State flags. */ { int crossed = 0; /* 1 if mouse crossed a window boundary */ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + TkWindow *restrictWinPtr = tsdPtr->restrictWinPtr; + TkWindow *lastWinPtr = tsdPtr->lastWinPtr; - if (winPtr != lastWinPtr) { + if (winPtr != tsdPtr->lastWinPtr) { if (restrictWinPtr) { int newPos, oldPos; @@ -196,7 +199,7 @@ GenerateEnterLeave(winPtr, x, y, state) crossed = 1; } } - lastWinPtr = winPtr; + tsdPtr->lastWinPtr = winPtr; } return crossed; @@ -226,11 +229,13 @@ Tk_UpdatePointer(tkwin, x, y, state) int x, y; /* Pointer location in root coords. */ int state; /* Modifier state mask. */ { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); TkWindow *winPtr = (TkWindow *)tkwin; TkWindow *targetWinPtr; XPoint pos; XEvent event; - int changes = (state ^ lastState) & ALL_BUTTONS; + int changes = (state ^ tsdPtr->lastState) & ALL_BUTTONS; int type, b, mask; pos.x = x; @@ -241,7 +246,8 @@ Tk_UpdatePointer(tkwin, x, y, state) * state since we haven't generated the button events yet. */ - lastState = (state & ~ALL_BUTTONS) | (lastState & ALL_BUTTONS); + tsdPtr->lastState = (state & ~ALL_BUTTONS) | (tsdPtr->lastState + & ALL_BUTTONS); /* * Generate Enter/Leave events. If the pointer has crossed window @@ -249,8 +255,8 @@ Tk_UpdatePointer(tkwin, x, y, state) * redundant motion events. */ - if (GenerateEnterLeave(winPtr, x, y, lastState)) { - lastPos = pos; + if (GenerateEnterLeave(winPtr, x, y, tsdPtr->lastState)) { + tsdPtr->lastPos = pos; } /* @@ -269,30 +275,30 @@ Tk_UpdatePointer(tkwin, x, y, state) * if this is the first button down. */ - if (!restrictWinPtr) { - if (!grabWinPtr) { + if (!tsdPtr->restrictWinPtr) { + if (!tsdPtr->grabWinPtr) { /* * Mouse is not grabbed, so set a button grab. */ - restrictWinPtr = winPtr; - TkpSetCapture(restrictWinPtr); + tsdPtr->restrictWinPtr = winPtr; + TkpSetCapture(tsdPtr->restrictWinPtr); - } else if ((lastState & ALL_BUTTONS) == 0) { + } else if ((tsdPtr->lastState & ALL_BUTTONS) == 0) { /* * Mouse is in a non-button grab, so ensure * the button grab is inside the grab tree. */ - if (TkPositionInTree(winPtr, grabWinPtr) + if (TkPositionInTree(winPtr, tsdPtr->grabWinPtr) == TK_GRAB_IN_TREE) { - restrictWinPtr = winPtr; + tsdPtr->restrictWinPtr = winPtr; } else { - restrictWinPtr = grabWinPtr; + tsdPtr->restrictWinPtr = tsdPtr->grabWinPtr; } - TkpSetCapture(restrictWinPtr); + TkpSetCapture(tsdPtr->restrictWinPtr); } } @@ -305,8 +311,8 @@ Tk_UpdatePointer(tkwin, x, y, state) * aren't in a global grab. */ - if ((lastState & ALL_BUTTONS) == mask) { - if (!grabWinPtr) { + if ((tsdPtr->lastState & ALL_BUTTONS) == mask) { + if (!tsdPtr->grabWinPtr) { TkpSetCapture(NULL); } } @@ -317,16 +323,16 @@ Tk_UpdatePointer(tkwin, x, y, state) * the restrict window to the current mouse position. */ - if (restrictWinPtr) { - InitializeEvent(&event, restrictWinPtr, type, x, y, - lastState, b); + if (tsdPtr->restrictWinPtr) { + InitializeEvent(&event, tsdPtr->restrictWinPtr, type, x, y, + tsdPtr->lastState, b); Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); - lastState &= ~mask; - lastWinPtr = restrictWinPtr; - restrictWinPtr = NULL; + tsdPtr->lastState &= ~mask; + tsdPtr->lastWinPtr = tsdPtr->restrictWinPtr; + tsdPtr->restrictWinPtr = NULL; - GenerateEnterLeave(winPtr, x, y, lastState); - lastPos = pos; + GenerateEnterLeave(winPtr, x, y, tsdPtr->lastState); + tsdPtr->lastPos = pos; continue; } } @@ -338,10 +344,10 @@ Tk_UpdatePointer(tkwin, x, y, state) * managed by Tk should be reported to the grab window. */ - if (restrictWinPtr) { - targetWinPtr = restrictWinPtr; - } else if (grabWinPtr && !winPtr) { - targetWinPtr = grabWinPtr; + if (tsdPtr->restrictWinPtr) { + targetWinPtr = tsdPtr->restrictWinPtr; + } else if (tsdPtr->grabWinPtr && !winPtr) { + targetWinPtr = tsdPtr->grabWinPtr; } else { targetWinPtr = winPtr; } @@ -352,7 +358,7 @@ Tk_UpdatePointer(tkwin, x, y, state) if (winPtr != NULL) { InitializeEvent(&event, targetWinPtr, type, x, y, - lastState, b); + tsdPtr->lastState, b); Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); } @@ -360,9 +366,9 @@ Tk_UpdatePointer(tkwin, x, y, state) * Update the state for the next iteration. */ - lastState = (type == ButtonPress) - ? (lastState | mask) : (lastState & ~mask); - lastPos = pos; + tsdPtr->lastState = (type == ButtonPress) + ? (tsdPtr->lastState | mask) : (tsdPtr->lastState & ~mask); + tsdPtr->lastPos = pos; } } @@ -370,11 +376,11 @@ Tk_UpdatePointer(tkwin, x, y, state) * Make sure the cursor window is up to date. */ - if (restrictWinPtr) { - targetWinPtr = restrictWinPtr; - } else if (grabWinPtr) { - targetWinPtr = (TkPositionInTree(winPtr, grabWinPtr) - == TK_GRAB_IN_TREE) ? winPtr : grabWinPtr; + if (tsdPtr->restrictWinPtr) { + targetWinPtr = tsdPtr->restrictWinPtr; + } else if (tsdPtr->grabWinPtr) { + targetWinPtr = (TkPositionInTree(winPtr, tsdPtr->grabWinPtr) + == TK_GRAB_IN_TREE) ? winPtr : tsdPtr->grabWinPtr; } else { targetWinPtr = winPtr; } @@ -385,19 +391,19 @@ Tk_UpdatePointer(tkwin, x, y, state) * generate a motion event. */ - if (lastPos.x != pos.x || lastPos.y != pos.y) { - if (restrictWinPtr) { - targetWinPtr = restrictWinPtr; - } else if (grabWinPtr && !winPtr) { - targetWinPtr = grabWinPtr; + if (tsdPtr->lastPos.x != pos.x || tsdPtr->lastPos.y != pos.y) { + if (tsdPtr->restrictWinPtr) { + targetWinPtr = tsdPtr->restrictWinPtr; + } else if (tsdPtr->grabWinPtr && !winPtr) { + targetWinPtr = tsdPtr->grabWinPtr; } if (targetWinPtr != NULL) { InitializeEvent(&event, targetWinPtr, MotionNotify, x, y, - lastState, NotifyNormal); + tsdPtr->lastState, NotifyNormal); Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); } - lastPos = pos; + tsdPtr->lastPos = pos; } } @@ -433,12 +439,16 @@ XGrabPointer(display, grab_window, owner_events, event_mask, pointer_mode, Cursor cursor; Time time; { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + display->request++; - grabWinPtr = (TkWindow *) Tk_IdToWindow(display, grab_window); - restrictWinPtr = NULL; - TkpSetCapture(grabWinPtr); - if (TkPositionInTree(lastWinPtr, grabWinPtr) != TK_GRAB_IN_TREE) { - UpdateCursor(grabWinPtr); + tsdPtr->grabWinPtr = (TkWindow *) Tk_IdToWindow(display, grab_window); + tsdPtr->restrictWinPtr = NULL; + TkpSetCapture(tsdPtr->grabWinPtr); + if (TkPositionInTree(tsdPtr->lastWinPtr, tsdPtr->grabWinPtr) + != TK_GRAB_IN_TREE) { + UpdateCursor(tsdPtr->grabWinPtr); } return GrabSuccess; } @@ -464,11 +474,14 @@ XUngrabPointer(display, time) Display* display; Time time; { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + display->request++; - grabWinPtr = NULL; - restrictWinPtr = NULL; + tsdPtr->grabWinPtr = NULL; + tsdPtr->restrictWinPtr = NULL; TkpSetCapture(NULL); - UpdateCursor(lastWinPtr); + UpdateCursor(tsdPtr->lastWinPtr); } /* @@ -491,16 +504,19 @@ void TkPointerDeadWindow(winPtr) TkWindow *winPtr; { - if (winPtr == lastWinPtr) { - lastWinPtr = NULL; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (winPtr == tsdPtr->lastWinPtr) { + tsdPtr->lastWinPtr = NULL; } - if (winPtr == grabWinPtr) { - grabWinPtr = NULL; + if (winPtr == tsdPtr->grabWinPtr) { + tsdPtr->grabWinPtr = NULL; } - if (winPtr == restrictWinPtr) { - restrictWinPtr = NULL; + if (winPtr == tsdPtr->restrictWinPtr) { + tsdPtr->restrictWinPtr = NULL; } - if (!(restrictWinPtr || grabWinPtr)) { + if (!(tsdPtr->restrictWinPtr || tsdPtr->grabWinPtr)) { TkpSetCapture(NULL); } } @@ -527,6 +543,8 @@ UpdateCursor(winPtr) TkWindow *winPtr; { Cursor cursor = None; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * A window inherits its cursor from its parent if it doesn't @@ -534,7 +552,7 @@ UpdateCursor(winPtr) * cursor. */ - cursorWinPtr = winPtr; + tsdPtr->cursorWinPtr = winPtr; while (winPtr != NULL) { if (winPtr->atts.cursor != None) { cursor = winPtr->atts.cursor; @@ -573,8 +591,10 @@ XDefineCursor(display, w, cursor) Cursor cursor; { TkWindow *winPtr = (TkWindow *)Tk_IdToWindow(display, w); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - if (cursorWinPtr == winPtr) { + if (tsdPtr->cursorWinPtr == winPtr) { UpdateCursor(winPtr); } display->request++; diff --git a/generic/tkSelect.c b/generic/tkSelect.c index 90f8844..dd26875 100644 --- a/generic/tkSelect.c +++ b/generic/tkSelect.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkSelect.c,v 1.1.4.2 1998/09/30 02:17:18 stanton Exp $ + * RCS: @(#) $Id: tkSelect.c,v 1.1.4.3 1998/12/13 08:16:11 lfb Exp $ */ #include "tkInt.h" @@ -45,12 +45,16 @@ typedef struct LostCommand { } LostCommand; /* - * Shared variables: + * The structure below is used to keep each thread's pending list + * separate. */ -TkSelInProgress *pendingPtr = NULL; +typedef struct ThreadSpecificData { + TkSelInProgress *pendingPtr; /* Topmost search in progress, or * NULL if none. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * Forward declarations for procedures defined in this file: @@ -199,6 +203,8 @@ Tk_DeleteSelHandler(tkwin, selection, target) TkWindow *winPtr = (TkWindow *) tkwin; register TkSelHandler *selPtr, *prevPtr; register TkSelInProgress *ipPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Find the selection handler to be deleted, or return if it doesn't @@ -220,7 +226,8 @@ Tk_DeleteSelHandler(tkwin, selection, target) * handler is dead. */ - for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { + for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; + ipPtr = ipPtr->nextPtr) { if (ipPtr->selPtr == selPtr) { ipPtr->selPtr = NULL; } @@ -480,6 +487,8 @@ Tk_GetSelection(interp, tkwin, selection, target, proc, clientData) TkWindow *winPtr = (TkWindow *) tkwin; TkDisplay *dispPtr = winPtr->dispPtr; TkSelectionInfo *infoPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (dispPtr->multipleAtom == None) { TkSelInit(tkwin); @@ -528,13 +537,13 @@ Tk_GetSelection(interp, tkwin, selection, target, proc, clientData) offset = 0; result = TCL_OK; ip.selPtr = selPtr; - ip.nextPtr = pendingPtr; - pendingPtr = &ip; + ip.nextPtr = tsdPtr->pendingPtr; + tsdPtr->pendingPtr = &ip; while (1) { count = (selPtr->proc)(selPtr->clientData, offset, buffer, TK_SEL_BYTES_AT_ONCE); if ((count < 0) || (ip.selPtr == NULL)) { - pendingPtr = ip.nextPtr; + tsdPtr->pendingPtr = ip.nextPtr; goto cantget; } if (count > TK_SEL_BYTES_AT_ONCE) { @@ -548,7 +557,7 @@ Tk_GetSelection(interp, tkwin, selection, target, proc, clientData) } offset += count; } - pendingPtr = ip.nextPtr; + tsdPtr->pendingPtr = ip.nextPtr; } return result; } @@ -886,6 +895,60 @@ Tk_SelectionCmd(clientData, interp, argc, argv) /* *---------------------------------------------------------------------- * + * TkSelGetInProgress -- + * + * This procedure returns a pointer to the thread-local + * list of pending searches. + * + * Results: + * The return value is a pointer to the first search in progress, + * or NULL if there are none. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkSelInProgress * +TkSelGetInProgress(void) +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + return tsdPtr->pendingPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkSelSetInProgress -- + * + * This procedure is used to set the thread-local list of pending + * searches. It is required because the pending list is kept + * in thread local storage. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +void +TkSelSetInProgress(pendingPtr) + TkSelInProgress *pendingPtr; +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + tsdPtr->pendingPtr = pendingPtr; +} + +/* + *---------------------------------------------------------------------- + * * TkSelDeadWindow -- * * This procedure is invoked just before a TkWindow is deleted. @@ -907,6 +970,8 @@ TkSelDeadWindow(winPtr) register TkSelHandler *selPtr; register TkSelInProgress *ipPtr; TkSelectionInfo *infoPtr, *prevPtr, *nextPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * While deleting all the handlers, be careful to check whether @@ -917,7 +982,8 @@ TkSelDeadWindow(winPtr) while (winPtr->selHandlerList != NULL) { selPtr = winPtr->selHandlerList; winPtr->selHandlerList = selPtr->nextPtr; - for (ipPtr = pendingPtr; ipPtr != NULL; ipPtr = ipPtr->nextPtr) { + for (ipPtr = tsdPtr->pendingPtr; ipPtr != NULL; + ipPtr = ipPtr->nextPtr) { if (ipPtr->selPtr == selPtr) { ipPtr->selPtr = NULL; } diff --git a/generic/tkSelect.h b/generic/tkSelect.h index 6880497..89ad902 100644 --- a/generic/tkSelect.h +++ b/generic/tkSelect.h @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkSelect.h,v 1.1.4.1 1998/09/30 02:17:19 stanton Exp $ + * RCS: @(#) $Id: tkSelect.h,v 1.1.4.2 1998/12/13 08:16:11 lfb Exp $ */ #ifndef _TKSELECT @@ -146,14 +146,6 @@ typedef struct TkSelInProgress { } TkSelInProgress; /* - * Declarations for variables shared among the selection-related files: - */ - -extern TkSelInProgress *pendingPtr; - /* Topmost search in progress, or - * NULL if none. */ - -/* * Chunk size for retrieving selection. It's defined both in * words and in bytes; the word size is used to allocate * buffer space that's guaranteed to be word-aligned and that @@ -168,6 +160,11 @@ extern TkSelInProgress *pendingPtr; * but shouldn't be used anywhere else in Tk (or by Tk clients): */ +extern TkSelInProgress * + TkSelGetInProgress _ANSI_ARGS_((void)); +extern void TkSelSetInProgress _ANSI_ARGS_(( + TkSelInProgress *pendingPtr)); + extern void TkSelClearSelection _ANSI_ARGS_((Tk_Window tkwin, XEvent *eventPtr)); extern int TkSelDefaultSelection _ANSI_ARGS_(( diff --git a/generic/tkWindow.c b/generic/tkWindow.c index 4d83df9..cc174db 100644 --- a/generic/tkWindow.c +++ b/generic/tkWindow.c @@ -12,35 +12,25 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWindow.c,v 1.1.4.2 1998/09/30 02:17:28 stanton Exp $ + * RCS: @(#) $Id: tkWindow.c,v 1.1.4.3 1998/12/13 08:16:12 lfb Exp $ */ #include "tkPort.h" #include "tkInt.h" -/* - * Count of number of main windows currently open in this process. - */ - -static int numMainWindows; - -/* - * First in list of all main windows managed by this process. - */ - -TkMainInfo *tkMainWindowList = NULL; - -/* - * List of all displays currently in use. - */ - -TkDisplay *tkDisplayList = NULL; - -/* - * Have statics in this module been initialized? - */ - -static int initialized = 0; +typedef struct ThreadSpecificData { + int numMainWindows; /* Count of numver of main windows currently + * open in this thread. */ + TkMainInfo *mainWindowList; + /* First in list of all main windows managed + * by this thread. */ + TkDisplay *displayList; + /* List of all displays currently in use by + * the current thread. */ + int initialized; /* 0 means the structures above need + * initializing. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * The variables below hold several uid's that are used in many places @@ -51,6 +41,12 @@ Tk_Uid tkDisabledUid = NULL; Tk_Uid tkActiveUid = NULL; Tk_Uid tkNormalUid = NULL; +/* + * The Mutex below is used to lock access to the Tk_Uids above. + */ + +TCL_DECLARE_MUTEX(windowMutex); + /* * Default values for "changes" and "atts" fields of TkWindows. Note * that Tk always requests all events for all windows, except StructureNotify @@ -258,12 +254,20 @@ CreateTopLevelWindow(interp, parent, name, screenName) register TkWindow *winPtr; register TkDisplay *dispPtr; int screenId; - - if (!initialized) { - initialized = 1; - tkActiveUid = Tk_GetUid("active"); - tkDisabledUid = Tk_GetUid("disabled"); - tkNormalUid = Tk_GetUid("normal"); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (!tsdPtr->initialized) { + tsdPtr->initialized = 1; + if (tkNormalUid == NULL) { + Tcl_MutexLock(&windowMutex); + if (tkNormalUid == NULL) { + tkActiveUid = Tk_GetUid("active"); + tkDisabledUid = Tk_GetUid("disabled"); + tkNormalUid = Tk_GetUid("normal"); + } + Tcl_MutexUnlock(&windowMutex); + } /* * Create built-in image types. @@ -363,6 +367,8 @@ GetScreen(interp, screenName, screenPtr) char *p; int screenId; size_t length; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Separate the screen number from the rest of the display @@ -394,7 +400,7 @@ GetScreen(interp, screenName, screenPtr) * then open a new connection. */ - for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) { + for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) { if (dispPtr == NULL) { dispPtr = TkpOpenDisplay(screenName); if (dispPtr == NULL) { @@ -402,29 +408,35 @@ GetScreen(interp, screenName, screenPtr) screenName, "\"", (char *) NULL); return (TkDisplay *) NULL; } - dispPtr->nextPtr = tkDisplayList; + dispPtr->nextPtr = TkGetDisplayList(); dispPtr->name = (char *) ckalloc((unsigned) (length+1)); dispPtr->lastEventTime = CurrentTime; - strncpy(dispPtr->name, screenName, length); - dispPtr->name[length] = '\0'; + dispPtr->borderInit = 0; + dispPtr->atomInit = 0; dispPtr->bindInfoStale = 1; dispPtr->modeModMask = 0; dispPtr->metaModMask = 0; dispPtr->altModMask = 0; dispPtr->numModKeyCodes = 0; dispPtr->modKeyCodes = NULL; - OpenIM(dispPtr); + dispPtr->bitmapInit = 0; + dispPtr->bitmapAutoNumber = 0; + dispPtr->numIdSearches = 0; + dispPtr->numSlowSearches = 0; + dispPtr->colorInit = 0; + dispPtr->stressPtr = NULL; + dispPtr->cursorInit = 0; + dispPtr->cursorString[0] = '\0'; + dispPtr->cursorFont = None; dispPtr->errorPtr = NULL; dispPtr->deleteCount = 0; - dispPtr->commTkwin = NULL; - dispPtr->selectionInfoPtr = NULL; - dispPtr->multipleAtom = None; - dispPtr->clipWindow = NULL; - dispPtr->clipboardActive = 0; - dispPtr->clipboardAppPtr = NULL; - dispPtr->clipTargetPtr = NULL; - dispPtr->atomInit = 0; - dispPtr->cursorFont = None; + dispPtr->delayedMotionPtr = NULL; + dispPtr->focusDebug = 0; + dispPtr->implicitWinPtr = NULL; + dispPtr->focusPtr = NULL; + dispPtr->gcInit = 0; + dispPtr->geomInit = 0; + dispPtr->uidInit = 0; dispPtr->grabWinPtr = NULL; dispPtr->eventualGrabWinPtr = NULL; dispPtr->buttonWinPtr = NULL; @@ -432,18 +444,32 @@ GetScreen(interp, screenName, screenPtr) dispPtr->firstGrabEventPtr = NULL; dispPtr->lastGrabEventPtr = NULL; dispPtr->grabFlags = 0; - TkInitXId(dispPtr); + dispPtr->gridInit = 0; + dispPtr->imageId = 0; + dispPtr->packInit = 0; + dispPtr->placeInit = 0; + dispPtr->selectionInfoPtr = NULL; + dispPtr->multipleAtom = None; + dispPtr->clipWindow = NULL; + dispPtr->clipboardActive = 0; + dispPtr->clipboardAppPtr = NULL; + dispPtr->clipTargetPtr = NULL; + dispPtr->commTkwin = NULL; + dispPtr->wmTracing = 0; + dispPtr->firstWmPtr = NULL; + dispPtr->foregroundWmPtr = NULL; dispPtr->destroyCount = 0; dispPtr->lastDestroyRequest = 0; dispPtr->cmapPtr = NULL; - dispPtr->implicitWinPtr = NULL; - dispPtr->focusPtr = NULL; - dispPtr->stressPtr = NULL; - dispPtr->delayedMotionPtr = NULL; Tcl_InitHashTable(&dispPtr->winTable, TCL_ONE_WORD_KEYS); + dispPtr->refCount = 0; - - tkDisplayList = dispPtr; + strncpy(dispPtr->name, screenName, length); + dispPtr->name[length] = '\0'; + OpenIM(dispPtr); + TkInitXId(dispPtr); + + tsdPtr->displayList = dispPtr; break; } if ((strncmp(dispPtr->name, screenName, length) == 0) @@ -485,8 +511,10 @@ TkGetDisplay(display) Display *display; /* X's display pointer */ { TkDisplay *dispPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - for (dispPtr = tkDisplayList; dispPtr != NULL; + for (dispPtr = tsdPtr->displayList; dispPtr != NULL; dispPtr = dispPtr->nextPtr) { if (dispPtr->display == display) { break; @@ -498,6 +526,58 @@ TkGetDisplay(display) /* *-------------------------------------------------------------- * + * TkGetDisplayList -- + * + * This procedure returns a pointer to the thread-local + * list of TkDisplays corresponding to the open displays. + * + * Results: + * The return value is a pointer to the first TkDisplay + * structure in thread-local-storage. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +TkDisplay * +TkGetDisplayList() +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + return tsdPtr->displayList; +} + +/* + *-------------------------------------------------------------- + * + * TkGetMainInfoList -- + * + * This procedure returns a pointer to the list of structures + * containing information about all main windows for the + * current thread. + * + * Results: + * The return value is a pointer to the first TkMainInfo + * structure in thread local storage. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +TkMainInfo * +TkGetMainInfoList() +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + return tsdPtr->mainWindowList; +} +/* + *-------------------------------------------------------------- + * * TkAllocWindow -- * * This procedure creates and initializes a TkWindow structure. @@ -717,6 +797,8 @@ TkCreateMainWindow(interp, screenName, baseName) register TkWindow *winPtr; register TkCmd *cmdPtr; ClientData clientData; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Panic if someone updated the TkWindow structure without @@ -748,6 +830,7 @@ TkCreateMainWindow(interp, screenName, baseName) mainPtr->refCount = 1; mainPtr->interp = interp; Tcl_InitHashTable(&mainPtr->nameTable, TCL_STRING_KEYS); + TkEventInit(); TkBindInit(mainPtr); TkFontPkgInit(mainPtr); mainPtr->tlFocusPtr = NULL; @@ -759,8 +842,8 @@ TkCreateMainWindow(interp, screenName, baseName) TCL_LINK_BOOLEAN) != TCL_OK) { Tcl_ResetResult(interp); } - mainPtr->nextPtr = tkMainWindowList; - tkMainWindowList = mainPtr; + mainPtr->nextPtr = tsdPtr->mainWindowList; + tsdPtr->mainWindowList = mainPtr; winPtr->mainPtr = mainPtr; hPtr = Tcl_CreateHashEntry(&mainPtr->nameTable, ".", &dummy); Tcl_SetHashValue(hPtr, winPtr); @@ -816,7 +899,7 @@ TkCreateMainWindow(interp, screenName, baseName) Tcl_SetVar(interp, "tk_patchLevel", TK_PATCH_LEVEL, TCL_GLOBAL_ONLY); Tcl_SetVar(interp, "tk_version", TK_VERSION, TCL_GLOBAL_ONLY); - numMainWindows++; + tsdPtr->numMainWindows++; return tkwin; } @@ -1032,6 +1115,8 @@ Tk_DestroyWindow(tkwin) TkWindow *winPtr = (TkWindow *) tkwin; TkDisplay *dispPtr = winPtr->dispPtr; XEvent event; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr->flags & TK_ALREADY_DEAD) { /* @@ -1075,19 +1160,19 @@ Tk_DestroyWindow(tkwin) if (winPtr->mainPtr->winPtr == winPtr) { dispPtr->refCount--; - if (tkMainWindowList == winPtr->mainPtr) { - tkMainWindowList = winPtr->mainPtr->nextPtr; + if (tsdPtr->mainWindowList == winPtr->mainPtr) { + tsdPtr->mainWindowList = winPtr->mainPtr->nextPtr; } else { TkMainInfo *prevPtr; - for (prevPtr = tkMainWindowList; + for (prevPtr = tsdPtr->mainWindowList; prevPtr->nextPtr != winPtr->mainPtr; prevPtr = prevPtr->nextPtr) { /* Empty loop body. */ } prevPtr->nextPtr = winPtr->mainPtr->nextPtr; } - numMainWindows--; + tsdPtr->numMainWindows--; } /* @@ -1278,7 +1363,7 @@ Tk_DestroyWindow(tkwin) * Splice this display out of the list of displays. */ - for (theDispPtr = tkDisplayList, backDispPtr = NULL; + for (theDispPtr = displayList, backDispPtr = NULL; (theDispPtr != winPtr->dispPtr) && (theDispPtr != NULL); theDispPtr = theDispPtr->nextPtr) { @@ -1288,7 +1373,7 @@ Tk_DestroyWindow(tkwin) panic("could not find display to close!"); } if (backDispPtr == NULL) { - tkDisplayList = theDispPtr->nextPtr; + displayList = theDispPtr->nextPtr; } else { backDispPtr->nextPtr = theDispPtr->nextPtr; } @@ -2069,7 +2154,7 @@ Tk_IdToWindow(display, window) TkDisplay *dispPtr; Tcl_HashEntry *hPtr; - for (dispPtr = tkDisplayList; ; dispPtr = dispPtr->nextPtr) { + for (dispPtr = TkGetDisplayList(); ; dispPtr = dispPtr->nextPtr) { if (dispPtr == NULL) { return NULL; } @@ -2310,8 +2395,10 @@ Tk_MainWindow(interp) * reporting also. */ { TkMainInfo *mainPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - for (mainPtr = tkMainWindowList; mainPtr != NULL; + for (mainPtr = tsdPtr->mainWindowList; mainPtr != NULL; mainPtr = mainPtr->nextPtr) { if (mainPtr->interp == interp) { return (Tk_Window) mainPtr->winPtr; @@ -2428,7 +2515,10 @@ OpenIM(dispPtr) int Tk_GetNumMainWindows() { - return numMainWindows; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + return tsdPtr->numMainWindows; } /* @@ -2454,8 +2544,10 @@ DeleteWindowsExitProc(clientData) { TkDisplay *displayPtr, *nextPtr; Tcl_Interp *interp; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - while (tkMainWindowList != NULL) { + while (tsdPtr->mainWindowList != NULL) { /* * We must protect the interpreter while deleting the window, * because of <Destroy> bindings which could destroy the interpreter @@ -2463,14 +2555,14 @@ DeleteWindowsExitProc(clientData) * the call stack pointing at deleted memory, causing core dumps. */ - interp = tkMainWindowList->winPtr->mainPtr->interp; + interp = tsdPtr->mainWindowList->winPtr->mainPtr->interp; Tcl_Preserve((ClientData) interp); - Tk_DestroyWindow((Tk_Window) tkMainWindowList->winPtr); + Tk_DestroyWindow((Tk_Window) tsdPtr->mainWindowList->winPtr); Tcl_Release((ClientData) interp); } - displayPtr = tkDisplayList; - tkDisplayList = NULL; + displayPtr = tsdPtr->displayList; + tsdPtr->displayList = NULL; /* * Iterate destroying the displays until no more displays remain. @@ -2479,9 +2571,9 @@ DeleteWindowsExitProc(clientData) * as well as the old ones. */ - for (displayPtr = tkDisplayList; + for (displayPtr = tsdPtr->displayList; displayPtr != NULL; - displayPtr = tkDisplayList) { + displayPtr = tsdPtr->displayList) { /* * Now iterate over the current list of open displays, and first @@ -2492,7 +2584,8 @@ DeleteWindowsExitProc(clientData) * if it needs to dispatch a message. */ - for (tkDisplayList = NULL; displayPtr != NULL; displayPtr = nextPtr) { + for (tsdPtr->displayList = NULL; displayPtr != NULL; + displayPtr = nextPtr) { nextPtr = displayPtr->nextPtr; if (displayPtr->name != (char *) NULL) { ckfree(displayPtr->name); @@ -2502,12 +2595,14 @@ DeleteWindowsExitProc(clientData) } } - numMainWindows = 0; - tkMainWindowList = NULL; - initialized = 0; + tsdPtr->numMainWindows = 0; + tsdPtr->mainWindowList = NULL; + tsdPtr->initialized = 0; + Tcl_MutexLock(&windowMutex); tkDisabledUid = NULL; tkActiveUid = NULL; tkNormalUid = NULL; + Tcl_MutexUnlock(&windowMutex); } /* @@ -2627,6 +2722,8 @@ Initialize(interp) int argc, code; char **argv, *args[20]; Tcl_DString class; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Start by initializing all the static variables to default acceptable @@ -2634,6 +2731,7 @@ Initialize(interp) * code. */ + Tcl_MutexLock(&windowMutex); synchronize = 0; name = NULL; display = NULL; @@ -2788,7 +2886,7 @@ Initialize(interp) * that it will be available to subprocesses created by us. */ - if (numMainWindows == 0) { + if (tsdPtr->numMainWindows == 0) { Tcl_SetVar2(interp, "env", "DISPLAY", display, TCL_GLOBAL_ONLY); } } @@ -2835,6 +2933,8 @@ Initialize(interp) } geometry = NULL; } + Tcl_MutexUnlock(&windowMutex); + if (Tcl_PkgRequire(interp, "Tcl", TCL_VERSION, 1) == NULL) { code = TCL_ERROR; goto done; diff --git a/mac/tkMacBitmap.c b/mac/tkMacBitmap.c index 26c55ef..a4e0488 100644 --- a/mac/tkMacBitmap.c +++ b/mac/tkMacBitmap.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacBitmap.c,v 1.1.4.2 1998/09/30 02:18:02 stanton Exp $ + * RCS: @(#) $Id: tkMacBitmap.c,v 1.1.4.3 1998/12/13 08:16:12 lfb Exp $ */ #include "tkPort.h" @@ -100,10 +100,14 @@ TkpDefineNativeBitmaps() char * name; BuiltInIcon *builtInPtr; NativeIcon *nativeIconPtr; + Tcl_HashTable *tablePtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (builtInPtr = builtInIcons; builtInPtr->name != NULL; builtInPtr++) { name = Tk_GetUid(builtInPtr->name); - predefHashPtr = Tcl_CreateHashEntry(&tkPredefBitmapTable, name, &new); + tablePtr = TkGetBitmapPredefTable(); + predefHashPtr = Tcl_CreateHashEntry(tablePtr, name, &new); if (!new) { continue; } diff --git a/mac/tkMacClipboard.c b/mac/tkMacClipboard.c index e681125..ff31717 100644 --- a/mac/tkMacClipboard.c +++ b/mac/tkMacClipboard.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacClipboard.c,v 1.1.4.2 1998/09/30 02:18:03 stanton Exp $ + * RCS: @(#) $Id: tkMacClipboard.c,v 1.1.4.3 1998/12/13 08:16:12 lfb Exp $ */ #include "tkInt.h" @@ -241,7 +241,7 @@ TkSuspendClipboard() char *buffer, *p, *endPtr, *buffPtr; long length; - dispPtr = tkDisplayList; + dispPtr = TkGetDisplayList(); if ((dispPtr == NULL) || !dispPtr->clipboardActive) { return; } diff --git a/mac/tkMacMenus.c b/mac/tkMacMenus.c index ce885b8..b2cc5ab 100644 --- a/mac/tkMacMenus.c +++ b/mac/tkMacMenus.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacMenus.c,v 1.1.4.1 1998/09/30 02:18:13 stanton Exp $ + * RCS: @(#) $Id: tkMacMenus.c,v 1.1.4.2 1998/12/13 08:16:13 lfb Exp $ */ #include "tcl.h" @@ -80,6 +80,7 @@ TkMacHandleMenuSelect( Str255 name; Tk_Window tkwin; Window window; + TkDisplay *dispPtr; if (mResult == 0) { TkMacHandleTearoffMenu(); @@ -120,7 +121,8 @@ TkMacHandleMenuSelect( case kCloseItem: /* Send close event */ window = TkMacGetXWindow(FrontWindow()); - tkwin = Tk_IdToWindow(tkDisplayList->display, window); + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); TkGenWMDestroyEvent(tkwin); break; case kQuitItem: @@ -251,9 +253,11 @@ GenerateEditEvent( Point where; Tk_Window tkwin; Window window; + TkDisplay *dispPtr; window = TkMacGetXWindow(FrontWindow()); - tkwin = Tk_IdToWindow(tkDisplayList->display, window); + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); tkwin = (Tk_Window) ((TkWindow *) tkwin)->dispPtr->focusPtr; if (tkwin == NULL) { return; diff --git a/mac/tkMacWindowMgr.c b/mac/tkMacWindowMgr.c index bc6d497..8c1d771 100644 --- a/mac/tkMacWindowMgr.c +++ b/mac/tkMacWindowMgr.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacWindowMgr.c,v 1.1.4.2 1998/09/30 02:18:18 stanton Exp $ + * RCS: @(#) $Id: tkMacWindowMgr.c,v 1.1.4.3 1998/12/13 08:16:14 lfb Exp $ */ #include <Events.h> @@ -104,6 +104,7 @@ WindowManagerMouse( Point where, where2; int xOffset, yOffset; short windowPart; + TkDisplay *dispPtr; frontWindow = FrontWindow(); @@ -122,7 +123,8 @@ WindowManagerMouse( } windowPart = FindWindow(eventPtr->where, &whichWindow); - tkwin = Tk_IdToWindow(tkDisplayList->display, window); + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); switch (windowPart) { case inSysWindow: SystemClick(eventPtr, (GrafPort *) whichWindow); @@ -293,8 +295,10 @@ GenerateUpdateEvent( { WindowRef macWindow; register TkWindow *winPtr; + TkDisplay *dispPtr; - winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window); + dispPtr = TkGetDisplayList(); + winPtr = (TkWindow *) Tk_IdToWindow(dispPtr->display, window); if (winPtr == NULL) { return false; @@ -464,6 +468,7 @@ TkGenerateButtonEvent( Point where; Tk_Window tkwin; int dummy; + TkDisplay *dispPtr; /* * ButtonDown events will always occur in the front @@ -480,7 +485,8 @@ TkGenerateButtonEvent( return false; } - tkwin = Tk_IdToWindow(tkDisplayList->display, window); + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); GlobalToLocal(&where); if (tkwin != NULL) { @@ -517,8 +523,10 @@ GenerateActivateEvents( Window window) /* Root X window for event. */ { TkWindow *winPtr; + TkDisplay *dispPtr; - winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window); + dispPtr = TkGetDisplayList(); + winPtr = (TkWindow *) Tk_IdToWindow(dispPtr->display, window); if (winPtr == NULL || winPtr->window == None) { return false; } @@ -629,8 +637,10 @@ GenerateFocusEvent( { XEvent event; Tk_Window tkwin; + TkDisplay *dispPtr; - tkwin = Tk_IdToWindow(tkDisplayList->display, window); + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); if (tkwin == NULL) { return false; } @@ -646,9 +656,9 @@ GenerateFocusEvent( event.xany.type = FocusOut; } - event.xany.serial = tkDisplayList->display->request; + event.xany.serial = dispPtr->display->request; event.xany.send_event = False; - event.xfocus.display = tkDisplayList->display; + event.xfocus.display = dispPtr->display; event.xfocus.window = window; event.xfocus.mode = NotifyNormal; event.xfocus.detail = NotifyDetailNone; @@ -690,6 +700,7 @@ GenerateKeyEvent( XEvent event; unsigned char byte; char buf[16]; + TkDisplay *dispPtr; /* * The focus must be in the FrontWindow on the Macintosh. @@ -697,7 +708,8 @@ GenerateKeyEvent( * that owns the focus. */ - tkwin = Tk_IdToWindow(tkDisplayList->display, window); + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); tkwin = (Tk_Window) ((TkWindow *) tkwin)->dispPtr->focusPtr; if (tkwin == NULL) { return false; @@ -790,7 +802,8 @@ GeneratePollingEvents() short part; int local_x, local_y; int generatedEvents = false; - + TkDisplay *dispPtr; + /* * First we get the current mouse position and determine * what Tk window the mouse is over (if any). @@ -812,7 +825,8 @@ GeneratePollingEvents() tkwin = NULL; } else { window = TkMacGetXWindow(whichwindow); - rootwin = Tk_IdToWindow(tkDisplayList->display, window); + dispPtr = TkGetDisplayList(); + rootwin = Tk_IdToWindow(dispPtr->display, window); if (rootwin == NULL) { tkwin = NULL; } else { @@ -879,6 +893,7 @@ GeneratePollingEvents2( int local_x, local_y; int generatedEvents = false; Rect bounds; + TkDisplay *dispPtr; /* * First we get the current mouse position and determine @@ -901,7 +916,8 @@ GeneratePollingEvents2( if (whichwindow != frontWin) { tkwin = NULL; } else { - rootwin = Tk_IdToWindow(tkDisplayList->display, window); + dispPtr = TkGetDisplayList(); + rootwin = Tk_IdToWindow(dispPtr->display, window); TkMacWinBounds((TkWindow *) rootwin, &bounds); if (!PtInRect(whereLocal, &bounds)) { tkwin = NULL; diff --git a/mac/tkMacWm.c b/mac/tkMacWm.c index 810688d..c574bfe 100644 --- a/mac/tkMacWm.c +++ b/mac/tkMacWm.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacWm.c,v 1.1.4.3 1998/11/25 21:16:37 stanton Exp $ + * RCS: @(#) $Id: tkMacWm.c,v 1.1.4.4 1998/12/13 08:16:14 lfb Exp $ */ #include <Gestalt.h> @@ -2428,6 +2428,7 @@ Tk_CoordsToWindow( * far that contains point. */ int x, y; /* Coordinates in winPtr. */ int tmpx, tmpy, bd; + TkDisplay *dispPtr; /* * Step 1: find the top-level window that contains the desired point. @@ -2440,7 +2441,8 @@ Tk_CoordsToWindow( return NULL; } rootChild = TkMacGetXWindow(whichWin); - winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, rootChild); + dispPtr = TkGetDisplayList(); + winPtr = (TkWindow *) Tk_IdToWindow(dispPtr->display, rootChild); if (winPtr == NULL) { return NULL; } @@ -3284,6 +3286,7 @@ TkMacGrowToplevel( Point start) { Point where = start; + TkDisplay *dispPtr; GlobalToLocal(&where); if (where.h > (whichWindow->portRect.right - 16) && @@ -3296,7 +3299,8 @@ TkMacGrowToplevel( long growResult; window = TkMacGetXWindow(whichWindow); - winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window); + dispPtr = TkGetDisplayList(); + winPtr = (TkWindow *) Tk_IdToWindow(dispPtr->display, window); wmPtr = winPtr->wmInfoPtr; /* TODO: handle grid size options. */ @@ -3628,7 +3632,8 @@ TkMacZoomToplevel( * has changed. */ window = TkMacGetXWindow(whichWindow); - tkwin = Tk_IdToWindow(tkDisplayList->display, window); + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); if (tkwin == NULL) { return false; } diff --git a/win/tkWinButton.c b/win/tkWinButton.c index 78e998f..e9b05f8 100644 --- a/win/tkWinButton.c +++ b/win/tkWinButton.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinButton.c,v 1.1.4.2 1998/09/30 02:19:28 stanton Exp $ + * RCS: @(#) $Id: tkWinButton.c,v 1.1.4.3 1998/12/13 08:16:15 lfb Exp $ */ #define OEMRESOURCE @@ -65,21 +65,20 @@ enum { }; /* - * Variables for the cached information about the boxes bitmap. + * Cached information about the boxes bitmap, and the default border + * width for a button in string form for use in Tk_OptionSpecs for + * the various button widget classes. */ -static BITMAPINFOHEADER *boxesPtr = NULL; /* Information about the bitmap. */ -static DWORD *boxesPalette = NULL; /* Pointer to color palette. */ -static LPSTR boxesBits = NULL; /* Pointer to bitmap data. */ -static DWORD boxHeight = 0, boxWidth = 0; /* Size of each sub-image. */ - -/* - * The following variable holds the default border width for a button - * in string form for use in Tk_OptionSpecs for the various button - * widget classes. - */ - -static char defWidth[TCL_INTEGER_SPACE]; +typedef struct ThreadSpecificData { + BITMAPINFOHEADER *boxesPtr; /* Information about the bitmap. */ + DWORD *boxesPalette; /* Pointer to color palette. */ + LPSTR boxesBits; /* Pointer to bitmap data. */ + DWORD boxHeight; /* Height of each sub-image. */ + DWORD boxWidth ; /* Width of each sub-image. */ + char defWidth[TCL_INTEGER_SPACE]; +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * Declarations for functions defined in this file. @@ -140,31 +139,34 @@ InitBoxes() HGLOBAL hblk; LPBITMAPINFOHEADER newBitmap; DWORD size; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); hrsrc = FindResource(module, "buttons", RT_BITMAP); if (hrsrc) { hblk = LoadResource(module, hrsrc); - boxesPtr = (LPBITMAPINFOHEADER)LockResource(hblk); + tsdPtr->boxesPtr = (LPBITMAPINFOHEADER)LockResource(hblk); } /* * Copy the DIBitmap into writable memory. */ - if (boxesPtr != NULL && !(boxesPtr->biWidth % 4) - && !(boxesPtr->biHeight % 2)) { - size = boxesPtr->biSize + (1 << boxesPtr->biBitCount) * sizeof(RGBQUAD) - + boxesPtr->biSizeImage; + if (tsdPtr->boxesPtr != NULL && !(tsdPtr->boxesPtr->biWidth % 4) + && !(tsdPtr->boxesPtr->biHeight % 2)) { + size = tsdPtr->boxesPtr->biSize + (1 << tsdPtr->boxesPtr->biBitCount) + * sizeof(RGBQUAD) + tsdPtr->boxesPtr->biSizeImage; newBitmap = (LPBITMAPINFOHEADER) ckalloc(size); - memcpy(newBitmap, boxesPtr, size); - boxesPtr = newBitmap; - boxWidth = boxesPtr->biWidth / 4; - boxHeight = boxesPtr->biHeight / 2; - boxesPalette = (DWORD*) (((LPSTR)boxesPtr) + boxesPtr->biSize); - boxesBits = ((LPSTR)boxesPalette) - + ((1 << boxesPtr->biBitCount) * sizeof(RGBQUAD)); + memcpy(newBitmap, tsdPtr->boxesPtr, size); + tsdPtr->boxesPtr = newBitmap; + tsdPtr->boxWidth = tsdPtr->boxesPtr->biWidth / 4; + tsdPtr->boxHeight = tsdPtr->boxesPtr->biHeight / 2; + tsdPtr->boxesPalette = (DWORD*) (((LPSTR) tsdPtr->boxesPtr) + + tsdPtr->boxesPtr->biSize); + tsdPtr->boxesBits = ((LPSTR) tsdPtr->boxesPalette) + + ((1 << tsdPtr->boxesPtr->biBitCount) * sizeof(RGBQUAD)); } else { - boxesPtr = NULL; + tsdPtr->boxesPtr = NULL; } } @@ -193,17 +195,19 @@ TkpButtonSetDefaults(specPtr) * TK_OPTION_END. */ { int width; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - if (defWidth[0] == 0) { + if (tsdPtr->defWidth[0] == 0) { width = GetSystemMetrics(SM_CXEDGE); if (width == 0) { width = 1; } - sprintf(defWidth, "%d", width); + sprintf(tsdPtr->defWidth, "%d", width); } for ( ; specPtr->type != TK_OPTION_END; specPtr++) { if (specPtr->internalOffset == Tk_Offset(TkButton, borderWidth)) { - specPtr->defValue = defWidth; + specPtr->defValue = tsdPtr->defWidth; } } } @@ -348,7 +352,12 @@ TkpDisplayButton(clientData) * it is a flavor of button, so we offset * the text to make the button appear to * move up and down as the relief changes. */ + DWORD *boxesPalette; + + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + boxesPalette= tsdPtr->boxesPalette; butPtr->flags &= ~REDRAW_PENDING; if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { return; @@ -494,17 +503,17 @@ TkpDisplayButton(clientData) */ if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn - && boxesPtr) { + && tsdPtr->boxesPtr) { int xSrc, ySrc; x -= butPtr->indicatorSpace; y -= butPtr->indicatorDiameter / 2; - xSrc = (butPtr->flags & SELECTED) ? boxWidth : 0; + xSrc = (butPtr->flags & SELECTED) ? tsdPtr->boxWidth : 0; if (butPtr->state == STATE_ACTIVE) { - xSrc += boxWidth*2; + xSrc += tsdPtr->boxWidth*2; } - ySrc = (butPtr->type == TYPE_RADIO_BUTTON) ? 0 : boxHeight; + ySrc = (butPtr->type == TYPE_RADIO_BUTTON) ? 0 : tsdPtr->boxHeight; /* * Update the palette in the boxes bitmap to reflect the current @@ -537,9 +546,10 @@ TkpDisplayButton(clientData) border, TK_3D_FLAT_GC)); dc = TkWinGetDrawableDC(butPtr->display, pixmap, &state); - StretchDIBits(dc, x, y, boxWidth, boxHeight, xSrc, ySrc, - boxWidth, boxHeight, boxesBits, (LPBITMAPINFO)boxesPtr, - DIB_RGB_COLORS, SRCCOPY); + StretchDIBits(dc, x, y, tsdPtr->boxWidth, tsdPtr->boxHeight, + xSrc, ySrc, tsdPtr->boxWidth, tsdPtr->boxHeight, + tsdPtr->boxesBits, (LPBITMAPINFO) tsdPtr->boxesPtr, + DIB_RGB_COLORS, SRCCOPY); TkWinReleaseDrawableDC(pixmap, dc, &state); } @@ -630,6 +640,8 @@ TkpComputeButtonGeometry(butPtr) { int width, height, avgWidth; Tk_FontMetrics fm; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (butPtr->highlightWidth < 0) { butPtr->highlightWidth = 0; @@ -637,7 +649,7 @@ TkpComputeButtonGeometry(butPtr) butPtr->inset = butPtr->highlightWidth + butPtr->borderWidth; butPtr->indicatorSpace = 0; - if (!boxesPtr) { + if (!tsdPtr->boxesPtr) { InitBoxes(); } @@ -651,8 +663,8 @@ TkpComputeButtonGeometry(butPtr) height = butPtr->height; } if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { - butPtr->indicatorSpace = boxWidth * 2; - butPtr->indicatorDiameter = boxHeight; + butPtr->indicatorSpace = tsdPtr->boxWidth * 2; + butPtr->indicatorDiameter = tsdPtr->boxHeight; } } else if (butPtr->bitmap != None) { Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); @@ -676,7 +688,7 @@ TkpComputeButtonGeometry(butPtr) } if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { - butPtr->indicatorDiameter = boxHeight; + butPtr->indicatorDiameter = tsdPtr->boxHeight; butPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth; } diff --git a/win/tkWinClipboard.c b/win/tkWinClipboard.c index c7e7cf5..35af94b 100644 --- a/win/tkWinClipboard.c +++ b/win/tkWinClipboard.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinClipboard.c,v 1.1.4.3 1998/12/08 23:28:52 stanton Exp $ + * RCS: @(#) $Id: tkWinClipboard.c,v 1.1.4.4 1998/12/13 08:16:16 lfb Exp $ */ #include "tkWinInt.h" @@ -122,7 +122,7 @@ XSetSelectionOwner(display, selection, owner, time) * It expects a Tk_Window, even though it only needs a Tk_Display. */ - tkwin = (Tk_Window)tkMainWindowList->winPtr; + tkwin = (Tk_Window) TkGetMainInfoList()->winPtr; if (selection == Tk_InternAtom(tkwin, "CLIPBOARD")) { diff --git a/win/tkWinColor.c b/win/tkWinColor.c index 096d585..b2e7391 100644 --- a/win/tkWinColor.c +++ b/win/tkWinColor.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinColor.c,v 1.1.4.2 1998/09/30 02:19:29 stanton Exp $ + * RCS: @(#) $Id: tkWinColor.c,v 1.1.4.3 1998/12/13 08:16:16 lfb Exp $ */ #include "tkWinInt.h" @@ -27,12 +27,6 @@ typedef struct WinColor { } WinColor; /* - * colorTable is a hash table used to look up X colors by name. - */ - -static Tcl_HashTable colorTable; - -/* * The sysColors array contains the names and index values for the * Windows indirect system color names. In use, all of the names * will have the string "System" prepended, but we omit it in the table @@ -75,7 +69,10 @@ static SystemColorEntry sysColors[] = { NULL, 0 }; -static int ncolors = 0; +typedef struct ThreadSpecificData { + int ncolors; +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * Forward declarations for functions defined later in this file. @@ -111,13 +108,15 @@ FindSystemColor(name, colorPtr, indexPtr) int *indexPtr; /* Out parameter to store color index. */ { int l, u, r, i; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Count the number of elements in the color array if we haven't * done so yet. */ - if (ncolors == 0) { + if (tsdPtr->ncolors == 0) { SystemColorEntry *ePtr; int version; @@ -130,7 +129,7 @@ FindSystemColor(name, colorPtr, indexPtr) ePtr->index = COLOR_BTNHIGHLIGHT; } } - ncolors++; + tsdPtr->ncolors++; } } @@ -139,7 +138,7 @@ FindSystemColor(name, colorPtr, indexPtr) */ l = 0; - u = ncolors - 1; + u = tsdPtr->ncolors - 1; while (l <= u) { i = (l + u) / 2; r = strcasecmp(name, sysColors[i].name); diff --git a/win/tkWinDialog.c b/win/tkWinDialog.c index 8e7573a..ce79a5f 100644 --- a/win/tkWinDialog.c +++ b/win/tkWinDialog.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinDialog.c,v 1.1.4.2 1998/09/30 02:19:31 stanton Exp $ + * RCS: @(#) $Id: tkWinDialog.c,v 1.1.4.3 1998/12/13 08:16:17 lfb Exp $ * */ @@ -19,20 +19,16 @@ #include <dlgs.h> /* includes common dialog template defines */ #include <cderr.h> /* includes the common dialog error codes */ -/* - * The following variable flags whether we should output debugging - * infomation while displaying a builtin dialog. - */ - -static int debugFlag = 0; -static Tcl_Interp *debugInterp = NULL; - -/* - * The following variable holds a registered windows event used for - * communicating between the DirectoryChooser dialog and its hook proc. - */ - -static UINT WM_LBSELCHANGED = 0; +typedef struct ThreadSpecificData { + int debugFlag; /* Flags whether we should output debugging + * information while displaying a builtin + * dialog. */ + Tcl_Interp *debugInterp; /* Interpreter to used for debugging. */ + UINT WM_LBSELCHANGED; /* Holds a registered windows event used for + * communicating between the Directory + * Chooser dialog and its hook proc. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * The following structures are used by Tk_MessageBox() to parse @@ -146,7 +142,10 @@ void TkWinDialogDebug( int debug) { - debugFlag = debug; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + tsdPtr->debugFlag = debug; } /* @@ -321,6 +320,9 @@ ColorDlgHookProc(hDlg, uMsg, wParam, lParam) WPARAM wParam; /* First message parameter. */ LPARAM lParam; /* Second message parameter. */ { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + switch (uMsg) { case WM_INITDIALOG: { const char *title; @@ -338,8 +340,8 @@ ColorDlgHookProc(hDlg, uMsg, wParam, lParam) SetWindowText(hDlg, (TCHAR *) Tcl_DStringValue(&ds)); Tcl_DStringFree(&ds); } - if (debugFlag) { - debugInterp = (Tcl_Interp *) ccPtr->lpTemplateName; + if (tsdPtr->debugFlag) { + tsdPtr->debugInterp = (Tcl_Interp *) ccPtr->lpTemplateName; Tcl_DoWhenIdle(SetTkDialog, (ClientData) hDlg); } return TRUE; @@ -435,6 +437,8 @@ GetFileName(clientData, interp, objc, objv, open) Tk_Window tkwin; Tcl_DString utfFilterString, utfDirString; Tcl_DString extString, filterString, dirString, titleString; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); static char *optionStrings[] = { "-defaultextension", "-filetypes", "-initialdir", "-initialfile", "-parent", "-title", NULL @@ -574,7 +578,7 @@ GetFileName(clientData, interp, objc, objv, open) ofn.Flags |= OFN_OVERWRITEPROMPT; } - if (debugFlag != 0) { + if (tsdPtr->debugFlag != 0) { ofn.Flags |= OFN_ENABLEHOOK; } @@ -683,6 +687,8 @@ OFNHookProc( WPARAM wParam, // message parameter LPARAM lParam) // message parameter { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); OPENFILENAME *ofnPtr; if (uMsg == WM_INITDIALOG) { @@ -701,7 +707,7 @@ OFNHookProc( if (ofnPtr->Flags & OFN_EXPLORER) { hdlg = GetParent(hdlg); } - debugInterp = (Tcl_Interp *) ofnPtr->lCustData; + tsdPtr->debugInterp = (Tcl_Interp *) ofnPtr->lCustData; Tcl_DoWhenIdle(SetTkDialog, (ClientData) hdlg); SetWindowLong(hdlg, GWL_USERDATA, (LPARAM) NULL); } @@ -873,6 +879,8 @@ Tk_ChooseDirectoryObjCmd(clientData, interp, objc, objv) char *utfTitle; Tcl_DString utfDirString; Tcl_DString titleString, dirString; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); static char *optionStrings[] = { "-initialdir", "-mustexist", "-parent", "-title", NULL @@ -881,8 +889,8 @@ Tk_ChooseDirectoryObjCmd(clientData, interp, objc, objv) DIR_INITIAL, DIR_EXIST, DIR_PARENT, FILE_TITLE }; - if (WM_LBSELCHANGED == 0) { - WM_LBSELCHANGED = RegisterWindowMessage(LBSELCHSTRING); + if (tsdPtr->WM_LBSELCHANGED == 0) { + tsdPtr->WM_LBSELCHANGED = RegisterWindowMessage(LBSELCHSTRING); } result = TCL_ERROR; @@ -1059,6 +1067,8 @@ ChooseDirectoryHookProc( WPARAM wParam, LPARAM lParam) { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); OPENFILENAME *ofnPtr; /* @@ -1084,8 +1094,8 @@ ChooseDirectoryHookProc( } SetDlgItemText(hwnd, edt10, cdPtr->path); SendDlgItemMessage(hwnd, edt10, EM_SETSEL, 0, -1); - if (debugFlag) { - debugInterp = cdPtr->interp; + if (tsdPtr->debugFlag) { + tsdPtr->debugInterp = cdPtr->interp; Tcl_DoWhenIdle(SetTkDialog, (ClientData) hwnd); } return 0; @@ -1094,7 +1104,7 @@ ChooseDirectoryHookProc( return 0; } - if (message == WM_LBSELCHANGED) { + if (message == tsdPtr->WM_LBSELCHANGED) { /* * Called when double-clicking on directory. * If directory wasn't already open, browse that directory. @@ -1408,11 +1418,13 @@ Tk_MessageBoxObjCmd(clientData, interp, objc, objv) static void SetTkDialog(ClientData clientData) { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); char buf[32]; HWND hwnd; hwnd = (HWND) clientData; sprintf(buf, "0x%08x", hwnd); - Tcl_SetVar(debugInterp, "tk_dialog", buf, TCL_GLOBAL_ONLY); + Tcl_SetVar(tsdPtr->debugInterp, "tk_dialog", buf, TCL_GLOBAL_ONLY); } diff --git a/win/tkWinDraw.c b/win/tkWinDraw.c index 72f258e..04b8475 100644 --- a/win/tkWinDraw.c +++ b/win/tkWinDraw.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinDraw.c,v 1.1.4.1 1998/09/30 02:19:31 stanton Exp $ + * RCS: @(#) $Id: tkWinDraw.c,v 1.1.4.2 1998/12/13 08:16:17 lfb Exp $ */ #include "tkWinInt.h" @@ -106,6 +106,12 @@ static int bltModes[] = { typedef BOOL (CALLBACK *WinDrawFunc) _ANSI_ARGS_((HDC dc, CONST POINT* points, int npoints)); +typedef struct ThreadSpecificData { + POINT *winPoints; /* Array of points that is reused. */ + int nWinPoints; /* Current size of point array. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + /* * Forward declarations for procedures defined in this file: */ @@ -212,7 +218,8 @@ TkWinReleaseDrawableDC(d, dc, state) * Returns the converted array of POINTs. * * Side effects: - * Allocates a block of memory that should not be freed. + * Allocates a block of memory in thread local storage that + * should not be freed. * *---------------------------------------------------------------------- */ @@ -224,8 +231,8 @@ ConvertPoints(points, npoints, mode, bbox) int mode; /* CoordModeOrigin or CoordModePrevious. */ RECT *bbox; /* Bounding box of points. */ { - static POINT *winPoints = NULL; /* Array of points that is reused. */ - static int nWinPoints = -1; /* Current size of point array. */ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); int i; /* @@ -233,16 +240,16 @@ ConvertPoints(points, npoints, mode, bbox) * we reuse the last array if it is large enough. */ - if (npoints > nWinPoints) { - if (winPoints != NULL) { - ckfree((char *) winPoints); + if (npoints > tsdPtr->nWinPoints) { + if (tsdPtr->winPoints != NULL) { + ckfree((char *) tsdPtr->winPoints); } - winPoints = (POINT *) ckalloc(sizeof(POINT) * npoints); - if (winPoints == NULL) { - nWinPoints = -1; + tsdPtr->winPoints = (POINT *) ckalloc(sizeof(POINT) * npoints); + if (tsdPtr->winPoints == NULL) { + tsdPtr->nWinPoints = -1; return NULL; } - nWinPoints = npoints; + tsdPtr->nWinPoints = npoints; } bbox->left = bbox->right = points[0].x; @@ -250,26 +257,26 @@ ConvertPoints(points, npoints, mode, bbox) if (mode == CoordModeOrigin) { for (i = 0; i < npoints; i++) { - winPoints[i].x = points[i].x; - winPoints[i].y = points[i].y; - bbox->left = MIN(bbox->left, winPoints[i].x); - bbox->right = MAX(bbox->right, winPoints[i].x); - bbox->top = MIN(bbox->top, winPoints[i].y); - bbox->bottom = MAX(bbox->bottom, winPoints[i].y); + tsdPtr->winPoints[i].x = points[i].x; + tsdPtr->winPoints[i].y = points[i].y; + bbox->left = MIN(bbox->left, tsdPtr->winPoints[i].x); + bbox->right = MAX(bbox->right, tsdPtr->winPoints[i].x); + bbox->top = MIN(bbox->top, tsdPtr->winPoints[i].y); + bbox->bottom = MAX(bbox->bottom, tsdPtr->winPoints[i].y); } } else { - winPoints[0].x = points[0].x; - winPoints[0].y = points[0].y; + tsdPtr->winPoints[0].x = points[0].x; + tsdPtr->winPoints[0].y = points[0].y; for (i = 1; i < npoints; i++) { - winPoints[i].x = winPoints[i-1].x + points[i].x; - winPoints[i].y = winPoints[i-1].y + points[i].y; - bbox->left = MIN(bbox->left, winPoints[i].x); - bbox->right = MAX(bbox->right, winPoints[i].x); - bbox->top = MIN(bbox->top, winPoints[i].y); - bbox->bottom = MAX(bbox->bottom, winPoints[i].y); + tsdPtr->winPoints[i].x = tsdPtr->winPoints[i-1].x + points[i].x; + tsdPtr->winPoints[i].y = tsdPtr->winPoints[i-1].y + points[i].y; + bbox->left = MIN(bbox->left, tsdPtr->winPoints[i].x); + bbox->right = MAX(bbox->right, tsdPtr->winPoints[i].x); + bbox->top = MIN(bbox->top, tsdPtr->winPoints[i].y); + bbox->bottom = MAX(bbox->bottom, tsdPtr->winPoints[i].y); } } - return winPoints; + return tsdPtr->winPoints; } /* diff --git a/win/tkWinEmbed.c b/win/tkWinEmbed.c index 9594768..93b2202 100644 --- a/win/tkWinEmbed.c +++ b/win/tkWinEmbed.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinEmbed.c,v 1.1.4.2 1998/09/30 02:19:32 stanton Exp $ + * RCS: @(#) $Id: tkWinEmbed.c,v 1.1.4.3 1998/12/13 08:16:18 lfb Exp $ */ #include "tkWinInt.h" @@ -38,9 +38,11 @@ typedef struct Container { * this process. */ } Container; -static Container *firstContainerPtr = NULL; - /* First in list of all containers +typedef struct ThreadSpecificData { + Container *firstContainerPtr; /* First in list of all containers * managed by this process. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; static void CleanupContainerList _ANSI_ARGS_(( ClientData clientData)); @@ -74,14 +76,16 @@ CleanupContainerList(clientData) ClientData clientData; { Container *nextPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); for (; - firstContainerPtr != (Container *) NULL; - firstContainerPtr = nextPtr) { - nextPtr = firstContainerPtr->nextPtr; - ckfree((char *) firstContainerPtr); + tsdPtr->firstContainerPtr != (Container *) NULL; + tsdPtr->firstContainerPtr = nextPtr) { + nextPtr = tsdPtr->firstContainerPtr->nextPtr; + ckfree((char *) tsdPtr->firstContainerPtr); } - firstContainerPtr = (Container *) NULL; + tsdPtr->firstContainerPtr = (Container *) NULL; } /* @@ -147,6 +151,8 @@ TkpUseWindow(interp, tkwin, string) int id; HWND hwnd; Container *containerPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr->window != None) { panic("TkpUseWindow: Already assigned a window"); @@ -191,7 +197,7 @@ TkpUseWindow(interp, tkwin, string) * things will get cleaned up at finalization. */ - if (firstContainerPtr == (Container *) NULL) { + if (tsdPtr->firstContainerPtr == (Container *) NULL) { Tcl_CreateExitHandler(CleanupContainerList, (ClientData) NULL); } @@ -202,8 +208,8 @@ TkpUseWindow(interp, tkwin, string) * app. are in the same process. */ - for (containerPtr = firstContainerPtr; containerPtr != NULL; - containerPtr = containerPtr->nextPtr) { + for (containerPtr = tsdPtr->firstContainerPtr; + containerPtr != NULL; containerPtr = containerPtr->nextPtr) { if (containerPtr->parentHWnd == hwnd) { winPtr->flags |= TK_BOTH_HALVES; containerPtr->parentPtr->flags |= TK_BOTH_HALVES; @@ -214,8 +220,8 @@ TkpUseWindow(interp, tkwin, string) containerPtr = (Container *) ckalloc(sizeof(Container)); containerPtr->parentPtr = NULL; containerPtr->parentHWnd = hwnd; - containerPtr->nextPtr = firstContainerPtr; - firstContainerPtr = containerPtr; + containerPtr->nextPtr = tsdPtr->firstContainerPtr; + tsdPtr->firstContainerPtr = containerPtr; } /* @@ -259,13 +265,15 @@ TkpMakeContainer(tkwin) { TkWindow *winPtr = (TkWindow *) tkwin; Container *containerPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * If this is the first container, register an exit handler so that * things will get cleaned up at finalization. */ - if (firstContainerPtr == (Container *) NULL) { + if (tsdPtr->firstContainerPtr == (Container *) NULL) { Tcl_CreateExitHandler(CleanupContainerList, (ClientData) NULL); } @@ -280,8 +288,8 @@ TkpMakeContainer(tkwin) containerPtr->parentHWnd = Tk_GetHWND(Tk_WindowId(tkwin)); containerPtr->embeddedHWnd = NULL; containerPtr->embeddedPtr = NULL; - containerPtr->nextPtr = firstContainerPtr; - firstContainerPtr = containerPtr; + containerPtr->nextPtr = tsdPtr->firstContainerPtr; + tsdPtr->firstContainerPtr = containerPtr; winPtr->flags |= TK_CONTAINER; /* @@ -359,12 +367,14 @@ TkWinEmbeddedEventProc(hwnd, message, wParam, lParam) LPARAM lParam; { Container *containerPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Find the Container structure associated with the parent window. */ - for (containerPtr = firstContainerPtr; + for (containerPtr = tsdPtr->firstContainerPtr; containerPtr->parentHWnd != hwnd; containerPtr = containerPtr->nextPtr) { if (containerPtr == NULL) { @@ -509,8 +519,10 @@ TkpGetOtherWindow(winPtr) * embedded window. */ { Container *containerPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - for (containerPtr = firstContainerPtr; containerPtr != NULL; + for (containerPtr = tsdPtr->firstContainerPtr; containerPtr != NULL; containerPtr = containerPtr->nextPtr) { if (containerPtr->embeddedPtr == winPtr) { return containerPtr->parentPtr; @@ -609,6 +621,8 @@ EmbedWindowDeleted(winPtr) * was deleted. */ { Container *containerPtr, *prevPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); /* * Find the Container structure for this window work. Delete the @@ -617,7 +631,7 @@ EmbedWindowDeleted(winPtr) */ prevPtr = NULL; - containerPtr = firstContainerPtr; + containerPtr = tsdPtr->firstContainerPtr; while (1) { if (containerPtr->embeddedPtr == winPtr) { containerPtr->embeddedHWnd = NULL; @@ -637,7 +651,7 @@ EmbedWindowDeleted(winPtr) if ((containerPtr->embeddedPtr == NULL) && (containerPtr->parentPtr == NULL)) { if (prevPtr == NULL) { - firstContainerPtr = containerPtr->nextPtr; + tsdPtr->firstContainerPtr = containerPtr->nextPtr; } else { prevPtr->nextPtr = containerPtr->nextPtr; } diff --git a/win/tkWinFont.c b/win/tkWinFont.c index f53351e..4e9db07 100644 --- a/win/tkWinFont.c +++ b/win/tkWinFont.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinFont.c,v 1.1.4.2 1998/09/30 02:19:33 stanton Exp $ + * RCS: @(#) $Id: tkWinFont.c,v 1.1.4.3 1998/12/13 08:16:18 lfb Exp $ */ #include "tkWinInt.h" @@ -151,14 +151,6 @@ typedef struct CanUse { } CanUse; /* - * The list of font families that are currently loaded. As screen fonts - * are loaded, this list grows to hold information about what characters - * exist in each font family. - */ - -static FontFamily *fontFamilyList = NULL; - -/* * The following structure is used to map between the Tcl strings that * represent the system fonts and the numbers used by Windows. */ @@ -173,6 +165,16 @@ static TkStateMap systemMap[] = { {-1, NULL} }; +typedef struct ThreadSpecificData { + FontFamily *fontFamilyList; /* The list of font families that are + * currently loaded. As screen fonts + * are loaded, this list grows to hold + * information about what characters + * exist in each font family. */ + Tcl_HashTable uidTable; +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + /* * Information cached about the system at startup time. */ @@ -1221,6 +1223,8 @@ AllocFontFamily( Tcl_DString faceString; Tcl_Encoding encoding; char buf[LF_FACESIZE * sizeof(WCHAR)]; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); hFont = SelectObject(hdc, hFont); if (platformId == VER_PLATFORM_WIN32_NT) { @@ -1233,7 +1237,7 @@ AllocFontFamily( Tcl_DStringFree(&faceString); hFont = SelectObject(hdc, hFont); - familyPtr = fontFamilyList; + familyPtr = tsdPtr->fontFamilyList; for ( ; familyPtr != NULL; familyPtr = familyPtr->nextPtr) { if (familyPtr->faceName == faceName) { familyPtr->refCount++; @@ -1243,8 +1247,8 @@ AllocFontFamily( familyPtr = (FontFamily *) ckalloc(sizeof(FontFamily)); memset(familyPtr, 0, sizeof(FontFamily)); - familyPtr->nextPtr = fontFamilyList; - fontFamilyList = familyPtr; + familyPtr->nextPtr = tsdPtr->fontFamilyList; + tsdPtr->fontFamilyList = familyPtr; /* * Set key for this FontFamily. @@ -1327,6 +1331,8 @@ FreeFontFamily( { int i; FontFamily **familyPtrPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (familyPtr == NULL) { return; @@ -1354,7 +1360,7 @@ FreeFontFamily( * Delete from list. */ - for (familyPtrPtr = &fontFamilyList; ; ) { + for (familyPtrPtr = &tsdPtr->fontFamilyList; ; ) { if (*familyPtrPtr == familyPtr) { *familyPtrPtr = familyPtr->nextPtr; break; diff --git a/win/tkWinMenu.c b/win/tkWinMenu.c index cf81655..4dc2c0e 100644 --- a/win/tkWinMenu.c +++ b/win/tkWinMenu.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinMenu.c,v 1.1.4.6 1998/11/25 21:16:42 stanton Exp $ + * RCS: @(#) $Id: tkWinMenu.c,v 1.1.4.7 1998/12/13 08:16:18 lfb Exp $ */ #define OEMRESOURCE @@ -51,12 +51,14 @@ static int indicatorDimensions[2]; /* The dimensions of the indicator space * in a menu entry. Calculated at init * time to save time. */ + static Tcl_HashTable commandTable; /* A map of command ids to menu entries */ static int inPostMenu; /* We cannot be re-entrant like X Windows. */ static WORD lastCommandID; /* The last command ID we allocated. */ static HWND menuHWND; /* A window to service popup-menu messages * in. */ + static int oldServiceMode; /* Used while processing a menu; we need * to set the event mode specially when we * enter the menu processing modal loop @@ -66,11 +68,14 @@ static TkMenu *modalMenuPtr; /* The menu we are processing inside the modal * active items when menus go away since * Windows does not see fit to give this * to us when it sends its WM_MENUSELECT. */ -static OSVERSIONINFO versionInfo; - /* So we don't have to keep doing this */ static Tcl_HashTable winMenuTable; /* Need this to map HMENUs back to menuPtrs */ +static OSVERSIONINFO versionInfo; + /* So we don't have to keep doing this */ + +TCL_DECLARE_MUTEX(winmenuMutex) + /* * The following are default menu value strings. */ @@ -2756,6 +2761,12 @@ TkpMenuInit() { WNDCLASS wndClass; + Tcl_MutexLock(&winMenuMutex); + + + Tcl_MutexUnlock(&winMenuMutex); + + Tcl_InitHashTable(&winMenuTable, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&commandTable, TCL_ONE_WORD_KEYS); wndClass.style = CS_OWNDC; diff --git a/win/tkWinScrlbr.c b/win/tkWinScrlbr.c index 28314c9..9449696 100644 --- a/win/tkWinScrlbr.c +++ b/win/tkWinScrlbr.c @@ -9,7 +9,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinScrlbr.c,v 1.1.4.2 1998/09/30 02:19:37 stanton Exp $ + * RCS: @(#) $Id: tkWinScrlbr.c,v 1.1.4.3 1998/12/13 08:16:19 lfb Exp $ */ #include "tkWinInt.h" @@ -57,6 +57,8 @@ static int initialized = 0; static int hArrowWidth, hThumb; /* Horizontal control metrics. */ static int vArrowWidth, vArrowHeight, vThumb; /* Vertical control metrics. */ +TCL_DECLARE_MUTEX(winScrlbrMutex) + /* * This variable holds the default width for a scrollbar in string * form for use in a Tk_ConfigSpec. @@ -116,8 +118,10 @@ TkpCreateScrollbar(tkwin) TkWindow *winPtr = (TkWindow *)tkwin; if (!initialized) { + Tcl_MutexLock(&winScrlbrMutex); UpdateScrollbarMetrics(); initialized = 1; + Tcl_MutexUnlock(&winScrlbrMutex); } scrollPtr = (WinScrollbar *) ckalloc(sizeof(WinScrollbar)); diff --git a/win/tkWinSend.c b/win/tkWinSend.c index 1f82b93..f32dcdb 100644 --- a/win/tkWinSend.c +++ b/win/tkWinSend.c @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinSend.c,v 1.1.4.2 1998/09/30 02:19:38 stanton Exp $ + * RCS: @(#) $Id: tkWinSend.c,v 1.1.4.3 1998/12/13 08:16:19 lfb Exp $ */ #include "tkWinInt.h" @@ -41,19 +41,17 @@ typedef struct Conversation { Tcl_Obj *returnPackagePtr; /* The result package for this conversation. */ } Conversation; -/* - * Static variables used by the registration process. Most of these - * are allocated in RegOpen and freed in RegClose. - */ - -static Conversation *currentConversations; - /* A list of conversations currently - * being processed. */ -static DWORD ddeInstance = 0; /* The application instance handle given +typedef struct ThreadSpecificData { + DWORD ddeInstance; /* The application instance handle given * to us by DdeInitialize. */ -static RegisteredInterp *interpListPtr; - /* The list of interps that this particular - * application knows about. */ + Conversation *currentConversations; + /* A list of conversations currently + * being processed. */ + RegisteredInterp *interpListPtr; + /* List of all interpreters registered + * in the current process. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * Forward declarations for procedures defined later in this file. @@ -116,25 +114,28 @@ Tk_SetAppName(tkwin, name) Tcl_DString dString; Tcl_Obj *resultObjPtr, *interpNamePtr; char *interpName; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + TkDisplay *dispPtr = ((TkWindow *) tkwin)->dispPtr; /* * Make sure that the DDE server is there. This is done only once, * add an exit handler tear it down. */ - if (ddeInstance == 0) { + if (tsdPtr->ddeInstance == 0) { HSZ ddeService; - if (DdeInitialize(&ddeInstance, TkDdeServerProc, + if (DdeInitialize(&tsdPtr->ddeInstance, TkDdeServerProc, CBF_SKIP_REGISTRATIONS|CBF_SKIP_UNREGISTRATIONS |CBF_FAIL_POKES, 0) != DMLERR_NO_ERROR) { - DdeUninitialize(ddeInstance); + DdeUninitialize(tsdPtr->ddeInstance); return NULL; } Tcl_CreateExitHandler(RemoveDdeServerExitProc, NULL); - ddeService = DdeCreateStringHandle(ddeInstance, "Tk", 0); - DdeNameService(ddeInstance, ddeService, 0L, DNS_REGISTER); + ddeService = DdeCreateStringHandle(tsdPtr->ddeInstance, "Tk", 0); + DdeNameService(tsdPtr->ddeInstance, ddeService, 0L, DNS_REGISTER); } /* @@ -143,11 +144,11 @@ Tk_SetAppName(tkwin, name) * will take care of disposing of this entry. */ - for (riPtr = interpListPtr, prevPtr = NULL; riPtr != NULL; + for (riPtr = tsdPtr->interpListPtr, prevPtr = NULL; riPtr != NULL; prevPtr = riPtr, riPtr = riPtr->nextPtr) { if (riPtr->interp == interp) { if (prevPtr == NULL) { - interpListPtr = interpListPtr->nextPtr; + tsdPtr->interpListPtr = tsdPtr->interpListPtr->nextPtr; } else { prevPtr->nextPtr = riPtr->nextPtr; } @@ -202,8 +203,8 @@ Tk_SetAppName(tkwin, name) riPtr = (RegisteredInterp *) ckalloc(sizeof(RegisteredInterp)); riPtr->interp = interp; riPtr->name = ckalloc(strlen(actualName) + 1); - riPtr->nextPtr = interpListPtr; - interpListPtr = riPtr; + riPtr->nextPtr = tsdPtr->interpListPtr; + tsdPtr->interpListPtr = riPtr; strcpy(riPtr->name, actualName); Tcl_CreateObjCommand(interp, "send", Tk_SendObjCmd, @@ -243,6 +244,8 @@ Tk_SendObjCmd( int objc, /* Number of arguments */ Tcl_Obj *CONST objv[]) /* The arguments */ { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); char *string, *sendName; int async, i, result, length; RegisteredInterp *riPtr; @@ -310,7 +313,8 @@ Tk_SendObjCmd( * deallocated objects. */ - for (riPtr = interpListPtr; riPtr != NULL; riPtr = riPtr->nextPtr) { + for (riPtr = tsdPtr->interpListPtr; riPtr != NULL; riPtr + = riPtr->nextPtr) { if (stricmp(sendName, riPtr->name) == 0) { break; } @@ -380,23 +384,23 @@ Tk_SendObjCmd( objPtr = Tcl_ConcatObj(objc, objv); string = Tcl_GetStringFromObj(objPtr, &length); - ddeItem = DdeCreateDataHandle(ddeInstance, string, length, 0, 0, + ddeItem = DdeCreateDataHandle(tsdPtr->ddeInstance, string, length, 0, 0, CF_TEXT, 0); if (async) { ddeData = DdeClientTransaction((LPBYTE) ddeItem, 0xFFFFFFFF, hConv, 0, CF_TEXT, XTYP_EXECUTE, TIMEOUT_ASYNC, &ddeResult); - DdeAbandonTransaction(ddeInstance, hConv, ddeResult); + DdeAbandonTransaction(tsdPtr->ddeInstance, hConv, ddeResult); } else { ddeData = DdeClientTransaction((LPBYTE) ddeItem, 0xFFFFFFFF, hConv, 0, CF_TEXT, XTYP_EXECUTE, 7200000, NULL); if (ddeData != 0) { HSZ ddeCookie; - ddeCookie = DdeCreateStringHandle(ddeInstance, + ddeCookie = DdeCreateStringHandle(tsdPtr->ddeInstance, "$TK$EXECUTE$RESULT", CP_WINANSI); ddeData = DdeClientTransaction(NULL, 0, hConv, ddeCookie, CF_TEXT, XTYP_REQUEST, 7200000, NULL); - DdeFreeStringHandle(ddeInstance, ddeCookie); + DdeFreeStringHandle(tsdPtr->ddeInstance, ddeCookie); } } @@ -499,10 +503,12 @@ TkGetInterpNames(interp, tkwin) Tcl_DString dString; char *topicName; int len; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); convInfo.cb = sizeof(CONVINFO); - ddeService = DdeCreateStringHandle(ddeInstance, "Tk", CP_WINANSI); - hConvList = DdeConnectList(ddeInstance, ddeService, NULL, + ddeService = DdeCreateStringHandle(tsdPtr->ddeInstance, "Tk", CP_WINANSI); + hConvList = DdeConnectList(tsdPtr->ddeInstance, ddeService, NULL, 0, NULL); hConv = 0; @@ -510,11 +516,11 @@ TkGetInterpNames(interp, tkwin) listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); while (hConv = DdeQueryNextServer(hConvList, hConv), hConv != 0) { DdeQueryConvInfo(hConv, QID_SYNC, &convInfo); - len = DdeQueryString(ddeInstance, convInfo.hszTopic, + len = DdeQueryString(tsdPtr->ddeInstance, convInfo.hszTopic, NULL, 0, CP_WINANSI); Tcl_DStringSetLength(&dString, len); topicName = Tcl_DStringValue(&dString); - DdeQueryString(ddeInstance, convInfo.hszTopic, topicName, + DdeQueryString(tsdPtr->ddeInstance, convInfo.hszTopic, topicName, len + 1, CP_WINANSI); Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewStringObj(topicName, len)); @@ -550,8 +556,10 @@ DeleteProc(clientData) { RegisteredInterp *riPtr = (RegisteredInterp *) clientData; RegisteredInterp *searchPtr, *prevPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - for (searchPtr = interpListPtr, prevPtr = NULL; + for (searchPtr = tsdPtr->interpListPtr, prevPtr = NULL; (searchPtr != NULL) && (searchPtr != riPtr); prevPtr = searchPtr, searchPtr = searchPtr->nextPtr) { /* @@ -563,7 +571,7 @@ DeleteProc(clientData) if (searchPtr != NULL) { if (prevPtr == NULL) { - interpListPtr = interpListPtr->nextPtr; + tsdPtr->interpListPtr = tsdPtr->interpListPtr->nextPtr; } else { prevPtr->nextPtr = searchPtr->nextPtr; } @@ -666,6 +674,8 @@ TkDdeServerProc ( HDDEDATA ddeReturn = NULL; RegisteredInterp *riPtr; Conversation *convPtr, *prevConvPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); switch(uType) { case XTYP_CONNECT: @@ -675,14 +685,14 @@ TkDdeServerProc ( * and make sure we have a valid topic. */ - len = DdeQueryString(ddeInstance, ddeTopic, NULL, 0, 0); + len = DdeQueryString(tsdPtr->ddeInstance, ddeTopic, NULL, 0, 0); Tcl_DStringInit(&dString); Tcl_DStringSetLength(&dString, len); utilString = Tcl_DStringValue(&dString); - DdeQueryString(ddeInstance, ddeTopic, utilString, len + 1, + DdeQueryString(tsdPtr->ddeInstance, ddeTopic, utilString, len + 1, CP_WINANSI); - for (riPtr = interpListPtr; riPtr != NULL; + for (riPtr = tsdPtr->interpListPtr; riPtr != NULL; riPtr = riPtr->nextPtr) { if (stricmp(utilString, riPtr->name) == 0) { Tcl_DStringFree(&dString); @@ -702,21 +712,21 @@ TkDdeServerProc ( * XTYP_REQUEST. */ - len = DdeQueryString(ddeInstance, ddeTopic, NULL, 0, 0); + len = DdeQueryString(tsdPtr->ddeInstance, ddeTopic, NULL, 0, 0); Tcl_DStringInit(&dString); Tcl_DStringSetLength(&dString, len); utilString = Tcl_DStringValue(&dString); - DdeQueryString(ddeInstance, ddeTopic, utilString, len + 1, + DdeQueryString(tsdPtr->ddeInstance, ddeTopic, utilString, len + 1, CP_WINANSI); - for (riPtr = interpListPtr; riPtr != NULL; + for (riPtr = tsdPtr->interpListPtr; riPtr != NULL; riPtr = riPtr->nextPtr) { if (stricmp(riPtr->name, utilString) == 0) { convPtr = (Conversation *) ckalloc(sizeof(Conversation)); - convPtr->nextPtr = currentConversations; + convPtr->nextPtr = tsdPtr->currentConversations; convPtr->returnPackagePtr = NULL; convPtr->hConv = hConv; convPtr->riPtr = riPtr; - currentConversations = convPtr; + tsdPtr->currentConversations = convPtr; break; } } @@ -730,12 +740,12 @@ TkDdeServerProc ( * conversation. */ - for (convPtr = currentConversations, prevConvPtr = NULL; + for (convPtr = tsdPtr->currentConversations, prevConvPtr = NULL; convPtr != NULL; prevConvPtr = convPtr, convPtr = convPtr->nextPtr) { if (hConv == convPtr->hConv) { if (prevConvPtr == NULL) { - currentConversations = convPtr->nextPtr; + tsdPtr->currentConversations = convPtr->nextPtr; } else { prevConvPtr->nextPtr = convPtr->nextPtr; } @@ -761,7 +771,7 @@ TkDdeServerProc ( } ddeReturn = (HDDEDATA) FALSE; - for (convPtr = currentConversations; (convPtr != NULL) + for (convPtr = tsdPtr->currentConversations; (convPtr != NULL) && (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) { /* * Empty loop body. @@ -771,17 +781,17 @@ TkDdeServerProc ( if (convPtr != NULL) { char *returnString; - len = DdeQueryString(ddeInstance, ddeItem, NULL, 0, + len = DdeQueryString(tsdPtr->ddeInstance, ddeItem, NULL, 0, CP_WINANSI); Tcl_DStringInit(&dString); Tcl_DStringSetLength(&dString, len); utilString = Tcl_DStringValue(&dString); - DdeQueryString(ddeInstance, ddeItem, utilString, len + 1, - CP_WINANSI); + DdeQueryString(tsdPtr->ddeInstance, ddeItem, utilString, + len + 1, CP_WINANSI); if (stricmp(utilString, "$TK$EXECUTE$RESULT") == 0) { returnString = Tcl_GetStringFromObj(convPtr->returnPackagePtr, &len); - ddeReturn = DdeCreateDataHandle(ddeInstance, + ddeReturn = DdeCreateDataHandle(tsdPtr->ddeInstance, returnString, len, 0, ddeItem, CF_TEXT, 0); } else { @@ -791,7 +801,7 @@ TkDdeServerProc ( if (variableObjPtr != NULL) { returnString = Tcl_GetStringFromObj(variableObjPtr, &len); - ddeReturn = DdeCreateDataHandle(ddeInstance, + ddeReturn = DdeCreateDataHandle(tsdPtr->ddeInstance, returnString, len, 0, ddeItem, CF_TEXT, 0); } else { ddeReturn = NULL; @@ -811,7 +821,7 @@ TkDdeServerProc ( Tcl_Obj *returnPackagePtr; - for (convPtr = currentConversations; (convPtr != NULL) + for (convPtr = tsdPtr->currentConversations; (convPtr != NULL) && (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) { /* * Empty loop body. @@ -833,7 +843,7 @@ TkDdeServerProc ( convPtr->returnPackagePtr = NULL; returnPackagePtr = ExecuteRemoteObject(convPtr->riPtr, ddeObjectPtr); - for (convPtr = currentConversations; (convPtr != NULL) + for (convPtr = tsdPtr->currentConversations; (convPtr != NULL) && (convPtr->hConv != hConv); convPtr = convPtr->nextPtr) { /* * Empty loop body. @@ -862,7 +872,7 @@ TkDdeServerProc ( int i; int numItems; - for (i = 0, riPtr = interpListPtr; riPtr != NULL; + for (i = 0, riPtr = tsdPtr->interpListPtr; riPtr != NULL; i++, riPtr = riPtr->nextPtr) { /* * Empty loop body. @@ -871,15 +881,15 @@ TkDdeServerProc ( } numItems = i; - ddeReturn = DdeCreateDataHandle(ddeInstance, NULL, + ddeReturn = DdeCreateDataHandle(tsdPtr->ddeInstance, NULL, (numItems + 1) * sizeof(HSZPAIR), 0, 0, 0, 0); returnPtr = (HSZPAIR *) DdeAccessData(ddeReturn, &len); - for (i = 0, riPtr = interpListPtr; i < numItems; + for (i = 0, riPtr = tsdPtr->interpListPtr; i < numItems; i++, riPtr = riPtr->nextPtr) { - returnPtr[i].hszSvc = DdeCreateStringHandle(ddeInstance, - "Tk", CP_WINANSI); - returnPtr[i].hszTopic = DdeCreateStringHandle(ddeInstance, - riPtr->name, CP_WINANSI); + returnPtr[i].hszSvc = DdeCreateStringHandle( + tsdPtr->ddeInstance, "Tk", CP_WINANSI); + returnPtr[i].hszTopic = DdeCreateStringHandle( + tsdPtr->ddeInstance, riPtr->name, CP_WINANSI); } returnPtr[i].hszSvc = NULL; returnPtr[i].hszTopic = NULL; @@ -912,9 +922,12 @@ static void RemoveDdeServerExitProc( ClientData clientData) /* Not used in this handler. */ { - DdeNameService(ddeInstance, NULL, 0, DNS_UNREGISTER); - DdeUninitialize(ddeInstance); - ddeInstance = 0; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + DdeNameService(tsdPtr->ddeInstance, NULL, 0, DNS_UNREGISTER); + DdeUninitialize(tsdPtr->ddeInstance); + tsdPtr->ddeInstance = 0; } /* @@ -943,13 +956,15 @@ MakeDdeConnection( { HSZ ddeTopic, ddeService; HCONV ddeConv; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - ddeService = DdeCreateStringHandle(ddeInstance, "Tk", 0); - ddeTopic = DdeCreateStringHandle(ddeInstance, name, 0); + ddeService = DdeCreateStringHandle(tsdPtr->ddeInstance, "Tk", 0); + ddeTopic = DdeCreateStringHandle(tsdPtr->ddeInstance, name, 0); - ddeConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL); - DdeFreeStringHandle(ddeInstance, ddeService); - DdeFreeStringHandle(ddeInstance, ddeTopic); + ddeConv = DdeConnect(tsdPtr->ddeInstance, ddeService, ddeTopic, NULL); + DdeFreeStringHandle(tsdPtr->ddeInstance, ddeService); + DdeFreeStringHandle(tsdPtr->ddeInstance, ddeTopic); if (ddeConv == (HCONV) NULL) { if (interp != NULL) { @@ -987,8 +1002,10 @@ SetDdeError( { Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); int err; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - err = DdeGetLastError(ddeInstance); + err = DdeGetLastError(tsdPtr->ddeInstance); switch (err) { case DMLERR_DATAACKTIMEOUT: case DMLERR_EXECACKTIMEOUT: @@ -1056,6 +1073,8 @@ Tk_DdeObjCmd( int firstArg, length, dataLength; DWORD ddeResult; HDDEDATA ddeReturn; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, @@ -1116,14 +1135,15 @@ Tk_DdeObjCmd( if (length == 0) { serviceName = NULL; } else { - ddeService = DdeCreateStringHandle(ddeInstance, serviceName, + ddeService = DdeCreateStringHandle(tsdPtr->ddeInstance, serviceName, CP_WINANSI); } topicName = Tcl_GetStringFromObj(objv[firstArg + 1], &length); if (length == 0) { topicName = NULL; } else { - ddeTopic = DdeCreateStringHandle(ddeInstance, topicName, CP_WINANSI); + ddeTopic = DdeCreateStringHandle(tsdPtr->ddeInstance, + topicName, CP_WINANSI); } switch (index) { @@ -1135,7 +1155,8 @@ Tk_DdeObjCmd( result = TCL_ERROR; break; } - hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL); + hConv = DdeConnect(tsdPtr->ddeInstance, ddeService, ddeTopic, + NULL); if (hConv == NULL) { SetDdeError(interp); @@ -1143,13 +1164,14 @@ Tk_DdeObjCmd( break; } - ddeData = DdeCreateDataHandle(ddeInstance, dataString, + ddeData = DdeCreateDataHandle(tsdPtr->ddeInstance, dataString, dataLength, 0, 0, CF_TEXT, 0); if (ddeData != NULL) { if (async) { DdeClientTransaction((LPBYTE) ddeData, 0xFFFFFFFF, hConv, 0, CF_TEXT, XTYP_EXECUTE, TIMEOUT_ASYNC, &ddeResult); - DdeAbandonTransaction(ddeInstance, hConv, ddeResult); + DdeAbandonTransaction(tsdPtr->ddeInstance, hConv, + ddeResult); } else { ddeReturn = DdeClientTransaction((LPBYTE) ddeData, 0xFFFFFFFF, hConv, 0, CF_TEXT, XTYP_EXECUTE, 7200000, NULL); @@ -1173,15 +1195,16 @@ Tk_DdeObjCmd( "cannot request value of null data", -1); return TCL_ERROR; } - hConv = DdeConnect(ddeInstance, ddeService, ddeTopic, NULL); + hConv = DdeConnect(tsdPtr->ddeInstance, ddeService, ddeTopic, + NULL); if (hConv == NULL) { SetDdeError(interp); result = TCL_ERROR; } else { Tcl_Obj *returnObjPtr; - ddeItem = DdeCreateStringHandle(ddeInstance, itemString, - CP_WINANSI); + ddeItem = DdeCreateStringHandle(tsdPtr->ddeInstance, + itemString, CP_WINANSI); if (ddeItem != NULL) { ddeData = DdeClientTransaction(NULL, 0, hConv, ddeItem, CF_TEXT, XTYP_REQUEST, 5000, NULL); @@ -1212,8 +1235,8 @@ Tk_DdeObjCmd( char *name; convInfo.cb = sizeof(CONVINFO); - hConvList = DdeConnectList(ddeInstance, ddeService, ddeTopic, - 0, NULL); + hConvList = DdeConnectList(tsdPtr->ddeInstance, ddeService, + ddeTopic, 0, NULL); hConv = 0; convListObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); Tcl_DStringInit(&dString); @@ -1221,19 +1244,19 @@ Tk_DdeObjCmd( while (hConv = DdeQueryNextServer(hConvList, hConv), hConv != 0) { elementObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); DdeQueryConvInfo(hConv, QID_SYNC, &convInfo); - length = DdeQueryString(ddeInstance, convInfo.hszSvcPartner, - NULL, 0, CP_WINANSI); + length = DdeQueryString(tsdPtr->ddeInstance, + convInfo.hszSvcPartner, NULL, 0, CP_WINANSI); Tcl_DStringSetLength(&dString, length); name = Tcl_DStringValue(&dString); - DdeQueryString(ddeInstance, convInfo.hszSvcPartner, name, - length + 1, CP_WINANSI); + DdeQueryString(tsdPtr->ddeInstance, convInfo.hszSvcPartner, + name, length + 1, CP_WINANSI); Tcl_ListObjAppendElement(interp, elementObjPtr, Tcl_NewStringObj(name, length)); - length = DdeQueryString(ddeInstance, convInfo.hszTopic, + length = DdeQueryString(tsdPtr->ddeInstance, convInfo.hszTopic, NULL, 0, CP_WINANSI); Tcl_DStringSetLength(&dString, length); name = Tcl_DStringValue(&dString); - DdeQueryString(ddeInstance, convInfo.hszTopic, name, + DdeQueryString(tsdPtr->ddeInstance, convInfo.hszTopic, name, length + 1, CP_WINANSI); Tcl_ListObjAppendElement(interp, elementObjPtr, Tcl_NewStringObj(name, length)); @@ -1246,10 +1269,10 @@ Tk_DdeObjCmd( } } if (ddeService != NULL) { - DdeFreeStringHandle(ddeInstance, ddeService); + DdeFreeStringHandle(tsdPtr->ddeInstance, ddeService); } if (ddeTopic != NULL) { - DdeFreeStringHandle(ddeInstance, ddeTopic); + DdeFreeStringHandle(tsdPtr->ddeInstance, ddeTopic); } return result; diff --git a/win/tkWinWindow.c b/win/tkWinWindow.c index 3ddc67b..47d6916 100644 --- a/win/tkWinWindow.c +++ b/win/tkWinWindow.c @@ -9,22 +9,17 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinWindow.c,v 1.1.4.2 1998/09/30 02:19:39 stanton Exp $ + * RCS: @(#) $Id: tkWinWindow.c,v 1.1.4.3 1998/12/13 08:16:20 lfb Exp $ */ #include "tkWinInt.h" -/* - * The windowTable maps from HWND to Tk_Window handles. - */ - -static Tcl_HashTable windowTable; - -/* - * Have statics in this module been initialized? - */ - -static int initialized = 0; +typedef struct ThreadSpecificData { + int initialized; /* 0 means table below needs initializing. */ + Tcl_HashTable windowTable; /* The windowTable maps from HWND to + * Tk_Window handles. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * Forward declarations for procedures defined in this file: @@ -61,10 +56,12 @@ Tk_AttachHWND(tkwin, hwnd) int new; Tcl_HashEntry *entryPtr; TkWinDrawable *twdPtr = (TkWinDrawable *) Tk_WindowId(tkwin); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - if (!initialized) { - Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS); - initialized = 1; + if (!tsdPtr->initialized) { + Tcl_InitHashTable(&tsdPtr->windowTable, TCL_ONE_WORD_KEYS); + tsdPtr->initialized = 1; } /* @@ -77,7 +74,7 @@ Tk_AttachHWND(tkwin, hwnd) twdPtr->type = TWD_WINDOW; twdPtr->window.winPtr = (TkWindow *) tkwin; } else if (twdPtr->window.handle != NULL) { - entryPtr = Tcl_FindHashEntry(&windowTable, + entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, (char *)twdPtr->window.handle); Tcl_DeleteHashEntry(entryPtr); } @@ -87,7 +84,7 @@ Tk_AttachHWND(tkwin, hwnd) */ twdPtr->window.handle = hwnd; - entryPtr = Tcl_CreateHashEntry(&windowTable, (char *)hwnd, &new); + entryPtr = Tcl_CreateHashEntry(&tsdPtr->windowTable, (char *)hwnd, &new); Tcl_SetHashValue(entryPtr, (ClientData)tkwin); return (Window)twdPtr; @@ -115,11 +112,14 @@ Tk_HWNDToWindow(hwnd) HWND hwnd; { Tcl_HashEntry *entryPtr; - if (!initialized) { - Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS); - initialized = 1; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (!tsdPtr->initialized) { + Tcl_InitHashTable(&tsdPtr->windowTable, TCL_ONE_WORD_KEYS); + tsdPtr->initialized = 1; } - entryPtr = Tcl_FindHashEntry(&windowTable, (char*)hwnd); + entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, (char*)hwnd); if (entryPtr != NULL) { return (Tk_Window) Tcl_GetHashValue(entryPtr); } @@ -295,6 +295,8 @@ XDestroyWindow(display, w) TkWinDrawable *twdPtr = (TkWinDrawable *)w; TkWindow *winPtr = TkWinGetWinPtr(w); HWND hwnd = Tk_GetHWND(w); + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); display->request++; @@ -305,7 +307,7 @@ XDestroyWindow(display, w) TkPointerDeadWindow(winPtr); - entryPtr = Tcl_FindHashEntry(&windowTable, (char*)hwnd); + entryPtr = Tcl_FindHashEntry(&tsdPtr->windowTable, (char*)hwnd); if (entryPtr != NULL) { Tcl_DeleteHashEntry(entryPtr); } diff --git a/win/tkWinWm.c b/win/tkWinWm.c index 97d3c07..d9d7a19 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinWm.c,v 1.1.4.5 1998/11/25 21:16:43 stanton Exp $ + * RCS: @(#) $Id: tkWinWm.c,v 1.1.4.6 1998/12/13 08:16:20 lfb Exp $ */ #include "tkWinInt.h" @@ -227,22 +227,6 @@ typedef struct TkWmInfo { (WS_EX_TOOLWINDOW|WS_EX_DLGMODALFRAME) /* - * This module keeps a list of all top-level windows. - */ - -static WmInfo *firstWmPtr = NULL; /* Points to first top-level window. */ -static WmInfo *foregroundWmPtr = NULL; /* Points to the foreground window. */ - -/* - * The variable below is used to enable or disable tracing in this - * module. If tracing is enabled, then information is printed on - * standard output about interesting interactions with the window - * manager. - */ - -static int wmTracing = 0; - -/* * The following structure is the official type record for geometry * management of top-level windows. */ @@ -255,41 +239,25 @@ static Tk_GeomMgr wmMgrType = { (Tk_GeomLostSlaveProc *) NULL, /* lostSlaveProc */ }; -/* - * Global system palette. This value always refers to the currently - * installed foreground logical palette. - */ - -static HPALETTE systemPalette = NULL; - -/* - * Window that is being constructed. This value is set immediately - * before a call to CreateWindowEx, and is used by SetLimits. - * This is a gross hack needed to work around Windows brain damage - * where it sends the WM_GETMINMAXINFO message before the WM_CREATE - * window. - */ - -static TkWindow *createWindow = NULL; - -/* - * Flag indicating whether this module has been initialized yet. - */ - -static int initialized = 0; - -/* - * Class for toplevel windows. - */ - -static WNDCLASS toplevelClass; - -/* - * This flag is cleared when the first window is mapped in a non-iconic - * state. - */ - -static int firstWindow = 1; +typedef struct ThreadSpecificData { + HPALETTE systemPalette; /* System palette; refers to the + * currently installed foreground logical + * palette. */ + TkWindow *createWindow; /* Window that is being constructed. This + * value is set immediately before a + * call to CreateWindowEx, and is used + * by SetLimits. This is a gross hack + * needed to work around Windows brain + * damage where it sends the + * WM_GETMINMAXINFO message before the + * WM_CREATE window. */ + WNDCLASS toplevelClass; /* Class for toplevel windows. */ + int initialized; /* Flag indicating whether module has + * been initialized yet. */ + int firstWindow; /* Flag, cleared when the first window + * is mapped in a non-iconic state. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * Forward declarations for procedures defined in this file: @@ -314,7 +282,8 @@ static void InvalidateSubTree _ANSI_ARGS_((TkWindow *winPtr, Colormap colormap)); static int ParseGeometry _ANSI_ARGS_((Tcl_Interp *interp, char *string, TkWindow *winPtr)); -static void RefreshColormap _ANSI_ARGS_((Colormap colormap)); +static void RefreshColormap _ANSI_ARGS_((Colormap colormap, + TkDisplay *dispPtr)); static void SetLimits _ANSI_ARGS_((HWND hwnd, MINMAXINFO *info)); static LRESULT CALLBACK TopLevelProc _ANSI_ARGS_((HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)); @@ -347,23 +316,28 @@ static LRESULT CALLBACK WmProc _ANSI_ARGS_((HWND hwnd, UINT message, static void InitWm(void) { - if (initialized) { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + WNDCLASS * classPtr; + + if (tsdPtr->initialized) { return; } - initialized = 1; - - toplevelClass.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC; - toplevelClass.cbClsExtra = 0; - toplevelClass.cbWndExtra = 0; - toplevelClass.hInstance = Tk_GetHINSTANCE(); - toplevelClass.hbrBackground = NULL; - toplevelClass.lpszMenuName = NULL; - toplevelClass.lpszClassName = TK_WIN_TOPLEVEL_CLASS_NAME; - toplevelClass.lpfnWndProc = WmProc; - toplevelClass.hIcon = LoadIcon(Tk_GetHINSTANCE(), "tk"); - toplevelClass.hCursor = LoadCursor(NULL, IDC_ARROW); - - if (!RegisterClass(&toplevelClass)) { + tsdPtr->initialized = 1; + classPtr = &tsdPtr->toplevelClass; + + classPtr->style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC; + classPtr->cbClsExtra = 0; + classPtr->cbWndExtra = 0; + classPtr->hInstance = Tk_GetHINSTANCE(); + classPtr->hbrBackground = NULL; + classPtr->lpszMenuName = NULL; + classPtr->lpszClassName = TK_WIN_TOPLEVEL_CLASS_NAME; + classPtr->lpfnWndProc = WmProc; + classPtr->hIcon = LoadIcon(Tk_GetHINSTANCE(), "tk"); + classPtr->hCursor = LoadCursor(NULL, IDC_ARROW); + + if (!RegisterClass(classPtr)) { panic("Unable to register TkTopLevel class"); } } @@ -389,14 +363,17 @@ static TkWindow * GetTopLevel(hwnd) HWND hwnd; { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + /* * If this function is called before the CreateWindowEx call * has completed, then the user data slot will not have been * set yet, so we use the global createWindow variable. */ - if (createWindow) { - return createWindow; + if (tsdPtr->createWindow) { + return tsdPtr->createWindow; } return (TkWindow *) GetWindowLong(hwnd, GWL_USERDATA); } @@ -510,10 +487,13 @@ void TkWinWmCleanup(hInstance) HINSTANCE hInstance; { - if (!initialized) { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (!tsdPtr->initialized) { return; } - initialized = 0; + tsdPtr->initialized = 0; UnregisterClass(TK_WIN_TOPLEVEL_CLASS_NAME, hInstance); } @@ -596,8 +576,8 @@ TkWmNewWindow(winPtr) wmPtr->cmdArgv = NULL; wmPtr->clientMachine = NULL; wmPtr->flags = WM_NEVER_MAPPED; - wmPtr->nextPtr = firstWmPtr; - firstWmPtr = wmPtr; + wmPtr->nextPtr = winPtr->dispPtr->firstWmPtr; + winPtr->dispPtr->firstWmPtr = wmPtr; /* * Tk must monitor structure events for top-level windows, in order @@ -645,6 +625,8 @@ UpdateWrapper(winPtr) int x, y, width, height, state; WINDOWPLACEMENT place; Tcl_DString titleString; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); parentHWND = NULL; child = TkWinGetHWND(winPtr->window); @@ -716,7 +698,7 @@ UpdateWrapper(winPtr) * to the TkWindow. */ - createWindow = winPtr; + tsdPtr->createWindow = winPtr; Tcl_UtfToExternalDString(NULL, wmPtr->titleUid, -1, &titleString); wmPtr->wrapper = CreateWindowEx(wmPtr->exStyle, TK_WIN_TOPLEVEL_CLASS_NAME, @@ -724,7 +706,7 @@ UpdateWrapper(winPtr) height, parentHWND, NULL, Tk_GetHINSTANCE(), NULL); Tcl_DStringFree(&titleString); SetWindowLong(wmPtr->wrapper, GWL_USERDATA, (LONG) winPtr); - createWindow = NULL; + tsdPtr->createWindow = NULL; place.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(wmPtr->wrapper, &place); @@ -798,8 +780,8 @@ UpdateWrapper(winPtr) * we should activate the initial window. */ - if (firstWindow) { - firstWindow = 0; + if (tsdPtr->firstWindow) { + tsdPtr->firstWindow = 0; SetActiveWindow(wmPtr->wrapper); } } @@ -833,8 +815,10 @@ TkWmMapWindow(winPtr) * be mapped. */ { register WmInfo *wmPtr = winPtr->wmInfoPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - if (!initialized) { + if (!tsdPtr->initialized) { InitWm(); } @@ -967,11 +951,12 @@ TkWmDeadWindow(winPtr) * Clean up event related window info. */ - if (firstWmPtr == wmPtr) { - firstWmPtr = wmPtr->nextPtr; + if (winPtr->dispPtr->firstWmPtr == wmPtr) { + winPtr->dispPtr->firstWmPtr = wmPtr->nextPtr; } else { register WmInfo *prevPtr; - for (prevPtr = firstWmPtr; ; prevPtr = prevPtr->nextPtr) { + for (prevPtr = winPtr->dispPtr->firstWmPtr; ; prevPtr + = prevPtr->nextPtr) { if (prevPtr == NULL) { panic("couldn't unlink window in TkWmDeadWindow"); } @@ -986,7 +971,8 @@ TkWmDeadWindow(winPtr) * Reset all transient windows whose master is the dead window. */ - for (wmPtr2 = firstWmPtr; wmPtr2 != NULL; wmPtr2 = wmPtr2->nextPtr) { + for (wmPtr2 = winPtr->dispPtr->firstWmPtr; wmPtr2 != NULL; wmPtr2 + = wmPtr2->nextPtr) { if (wmPtr2->masterPtr == winPtr) { wmPtr2->masterPtr = NULL; if ((wmPtr2->wrapper != None) @@ -1121,10 +1107,10 @@ Tk_WmCmd(clientData, interp, argc, argv) return TCL_ERROR; } if (argc == 2) { - Tcl_SetResult(interp, ((wmTracing) ? "on" : "off"), TCL_STATIC); + Tcl_SetResult(interp, ((winPtr->dispPtr->wmTracing) ? "on" : "off"), TCL_STATIC); return TCL_OK; } - return Tcl_GetBoolean(interp, argv[2], &wmTracing); + return Tcl_GetBoolean(interp, argv[2], &winPtr->dispPtr->wmTracing); } if (argc < 3) { @@ -1288,7 +1274,7 @@ Tk_WmCmd(clientData, interp, argc, argv) * Now we need to force the updated colormaps to be installed. */ - if (wmPtr == foregroundWmPtr) { + if (wmPtr == winPtr->dispPtr->foregroundWmPtr) { InstallColormaps(wmPtr->wrapper, WM_QUERYNEWPALETTE, 1); } else { InstallColormaps(wmPtr->wrapper, WM_PALETTECHANGED, 0); @@ -3165,7 +3151,7 @@ TkWmAddToColormapWindows(winPtr) * Now we need to force the updated colormaps to be installed. */ - if (topPtr->wmInfoPtr == foregroundWmPtr) { + if (topPtr->wmInfoPtr == winPtr->dispPtr->foregroundWmPtr) { InstallColormaps(topPtr->wmInfoPtr->wrapper, WM_QUERYNEWPALETTE, 1); } else { InstallColormaps(topPtr->wmInfoPtr->wrapper, WM_PALETTECHANGED, 0); @@ -3563,6 +3549,8 @@ InstallColormaps(hwnd, message, isForemost) HPALETTE oldPalette; TkWindow *winPtr = GetTopLevel(hwnd); WmInfo *wmPtr; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (winPtr == NULL) { return 0; @@ -3579,17 +3567,17 @@ InstallColormaps(hwnd, message, isForemost) * secondary palettes are installed properly. */ - foregroundWmPtr = wmPtr; + winPtr->dispPtr->foregroundWmPtr = wmPtr; if (wmPtr->cmapCount > 0) { winPtr = wmPtr->cmapList[0]; } - systemPalette = TkWinGetPalette(winPtr->atts.colormap); + tsdPtr->systemPalette = TkWinGetPalette(winPtr->atts.colormap); dc = GetDC(hwnd); - oldPalette = SelectPalette(dc, systemPalette, FALSE); + oldPalette = SelectPalette(dc, tsdPtr->systemPalette, FALSE); if (RealizePalette(dc)) { - RefreshColormap(winPtr->atts.colormap); + RefreshColormap(winPtr->atts.colormap, winPtr->dispPtr); } else if (wmPtr->cmapCount > 1) { SelectPalette(dc, oldPalette, TRUE); RealizePalette(dc); @@ -3625,13 +3613,13 @@ InstallColormaps(hwnd, message, isForemost) oldPalette = SelectPalette(dc, TkWinGetPalette(winPtr->atts.colormap), TRUE); if (RealizePalette(dc)) { - RefreshColormap(winPtr->atts.colormap); + RefreshColormap(winPtr->atts.colormap, winPtr->dispPtr); } for (; i < wmPtr->cmapCount; i++) { winPtr = wmPtr->cmapList[i]; SelectPalette(dc, TkWinGetPalette(winPtr->atts.colormap), TRUE); if (RealizePalette(dc)) { - RefreshColormap(winPtr->atts.colormap); + RefreshColormap(winPtr->atts.colormap, winPtr->dispPtr); } } } @@ -3663,13 +3651,14 @@ InstallColormaps(hwnd, message, isForemost) */ static void -RefreshColormap(colormap) +RefreshColormap(colormap, dispPtr) Colormap colormap; + TkDisplay *dispPtr; { WmInfo *wmPtr; int i; - for (wmPtr = firstWmPtr; wmPtr != NULL; wmPtr = wmPtr->nextPtr) { + for (wmPtr = dispPtr->firstWmPtr; wmPtr != NULL; wmPtr = wmPtr->nextPtr) { if (wmPtr->cmapCount > 0) { for (i = 0; i < wmPtr->cmapCount; i++) { if ((wmPtr->cmapList[i]->atts.colormap == colormap) @@ -3751,7 +3740,10 @@ InvalidateSubTree(winPtr, colormap) HPALETTE TkWinGetSystemPalette() { - return systemPalette; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + return tsdPtr->systemPalette; } /* diff --git a/win/tkWinX.c b/win/tkWinX.c index b4ffa17..67aede0 100644 --- a/win/tkWinX.c +++ b/win/tkWinX.c @@ -10,11 +10,19 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinX.c,v 1.1.4.5 1998/11/25 21:16:44 stanton Exp $ + * RCS: @(#) $Id: tkWinX.c,v 1.1.4.6 1998/12/13 08:16:21 lfb Exp $ */ #include "tkWinInt.h" +typedef struct ThreadSpecificData { + TkDisplay *winDisplay; /* Display that represents Windows screen. */ + HINSTANCE tkInstance; /* Application instance handle. */ + int childClassInitialized; /* Registered child class? */ + WNDCLASS childClass; /* Window class for child windows. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; + /* * The zmouse.h file includes the definition for WM_MOUSEWHEEL. */ @@ -31,13 +39,11 @@ int tkpIsWin32s = -1; * Declarations of static variables used in this file. */ -static HINSTANCE tkInstance = (HINSTANCE) NULL; - /* Global application instance handle. */ -static TkDisplay *winDisplay; /* Display that represents Windows screen. */ + /* Registered child class? */ static char winScreenName[] = ":0"; /* Default name of windows display. */ -static WNDCLASS childClass; /* Window class for child windows. */ -static childClassInitialized = 0; /* Registered child class? */ + +TCL_DECLARE_MUTEX(winXMutex) /* * Forward declarations of procedures used in this file. @@ -105,7 +111,10 @@ TkGetServerInfo(interp, tkwin) HINSTANCE Tk_GetHINSTANCE() { - return tkInstance; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + return tsdPtr->tkInstance; } /* @@ -129,35 +138,37 @@ TkWinXInit(hInstance) HINSTANCE hInstance; { OSVERSIONINFO info; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&info); tkpIsWin32s = (info.dwPlatformId == VER_PLATFORM_WIN32s); - if (childClassInitialized != 0) { + if (tsdPtr->childClassInitialized != 0) { return; } - childClassInitialized = 1; + tsdPtr->childClassInitialized = 1; - tkInstance = hInstance; + tsdPtr->tkInstance = hInstance; - childClass.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC; - childClass.cbClsExtra = 0; - childClass.cbWndExtra = 0; - childClass.hInstance = hInstance; - childClass.hbrBackground = NULL; - childClass.lpszMenuName = NULL; + tsdPtr->childClass.style = CS_HREDRAW | CS_VREDRAW | CS_CLASSDC; + tsdPtr->childClass.cbClsExtra = 0; + tsdPtr->childClass.cbWndExtra = 0; + tsdPtr->childClass.hInstance = hInstance; + tsdPtr->childClass.hbrBackground = NULL; + tsdPtr->childClass.lpszMenuName = NULL; /* * Register the Child window class. */ - childClass.lpszClassName = TK_WIN_CHILD_CLASS_NAME; - childClass.lpfnWndProc = TkWinChildProc; - childClass.hIcon = NULL; - childClass.hCursor = NULL; + tsdPtr->childClass.lpszClassName = TK_WIN_CHILD_CLASS_NAME; + tsdPtr->childClass.lpfnWndProc = TkWinChildProc; + tsdPtr->childClass.hIcon = NULL; + tsdPtr->childClass.hCursor = NULL; - if (!RegisterClass(&childClass)) { + if (!RegisterClass(&tsdPtr->childClass)) { panic("Unable to register TkChild class"); } } @@ -182,12 +193,15 @@ void TkWinXCleanup(hInstance) HINSTANCE hInstance; { + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + /* * Clean up our own class. */ - if (childClassInitialized) { - childClassInitialized = 0; + if (tsdPtr->childClassInitialized) { + tsdPtr->childClassInitialized = 0; UnregisterClass(TK_WIN_CHILD_CLASS_NAME, hInstance); } @@ -235,10 +249,10 @@ TkGetDefaultScreenName(interp, screenName) * specific information. * * Results: - * Returns a Display structure on success or NULL on failure. + * Returns a TkDisplay structure on success or NULL on failure. * * Side effects: - * Allocates a new Display structure. + * Allocates a new TkDisplay structure. * *---------------------------------------------------------------------- */ @@ -251,10 +265,13 @@ TkpOpenDisplay(display_name) HDC dc; TkWinDrawable *twdPtr; Display *display; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - if (winDisplay != NULL) { - if (strcmp(winDisplay->display->display_name, display_name) == 0) { - return winDisplay; + if (tsdPtr->winDisplay != NULL) { + if (strcmp(tsdPtr->winDisplay->display->display_name, display_name) + == 0) { + return tsdPtr->winDisplay; } else { return NULL; } @@ -356,9 +373,9 @@ TkpOpenDisplay(display_name) display->default_screen = 0; screen->cmap = XCreateColormap(display, None, screen->root_visual, AllocNone); - winDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay)); - winDisplay->display = display; - return winDisplay; + tsdPtr->winDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay)); + tsdPtr->winDisplay->display = display; + return tsdPtr->winDisplay; } /* @@ -384,8 +401,10 @@ TkpCloseDisplay(dispPtr) { Display *display = dispPtr->display; HWND hwnd; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); - if (dispPtr != winDisplay) { + if (dispPtr != tsdPtr->winDisplay) { panic("TkpCloseDisplay: tried to call TkpCloseDisplay on another display"); return; } @@ -404,7 +423,7 @@ TkpCloseDisplay(dispPtr) } } - winDisplay = NULL; + tsdPtr->winDisplay = NULL; if (display->display_name != (char *) NULL) { ckfree(display->display_name); |