summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlfb <lfb>1998-12-13 08:16:00 (GMT)
committerlfb <lfb>1998-12-13 08:16:00 (GMT)
commit6a11e0ffdf0b7a302f94f3b38b1f9e751dc8ab8b (patch)
tree55c9929c38a99b28203b5e5dfb758a9dd1bf303e
parent2d3a35af140d791de362fc99fe6254312f6f53ed (diff)
downloadtk-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.
-rw-r--r--generic/tk3d.c36
-rw-r--r--generic/tkBind.c56
-rw-r--r--generic/tkBitmap.c268
-rw-r--r--generic/tkCanvArc.c17
-rw-r--r--generic/tkCanvLine.c8
-rw-r--r--generic/tkCanvas.c22
-rw-r--r--generic/tkCmds.c4
-rw-r--r--generic/tkColor.c87
-rw-r--r--generic/tkConsole.c21
-rw-r--r--generic/tkCursor.c114
-rw-r--r--generic/tkEvent.c145
-rw-r--r--generic/tkFocus.c18
-rw-r--r--generic/tkGC.c57
-rw-r--r--generic/tkGeometry.c34
-rw-r--r--generic/tkGet.c35
-rw-r--r--generic/tkGrab.c4
-rw-r--r--generic/tkGrid.c22
-rw-r--r--generic/tkImage.c32
-rw-r--r--generic/tkImgGIF.c47
-rw-r--r--generic/tkImgPhoto.c32
-rw-r--r--generic/tkInt.h327
-rw-r--r--generic/tkMacWinMenu.c21
-rw-r--r--generic/tkMain.c66
-rw-r--r--generic/tkMenubutton.c19
-rw-r--r--generic/tkOption.c241
-rw-r--r--generic/tkPack.c34
-rw-r--r--generic/tkPlace.c44
-rw-r--r--generic/tkPointer.c168
-rw-r--r--generic/tkSelect.c84
-rw-r--r--generic/tkSelect.h15
-rw-r--r--generic/tkWindow.c252
-rw-r--r--mac/tkMacBitmap.c8
-rw-r--r--mac/tkMacClipboard.c4
-rw-r--r--mac/tkMacMenus.c10
-rw-r--r--mac/tkMacWindowMgr.c40
-rw-r--r--mac/tkMacWm.c13
-rw-r--r--win/tkWinButton.c94
-rw-r--r--win/tkWinClipboard.c4
-rw-r--r--win/tkWinColor.c21
-rw-r--r--win/tkWinDialog.c64
-rw-r--r--win/tkWinDraw.c59
-rw-r--r--win/tkWinEmbed.c54
-rw-r--r--win/tkWinFont.c32
-rw-r--r--win/tkWinMenu.c17
-rw-r--r--win/tkWinScrlbr.c6
-rw-r--r--win/tkWinSend.c193
-rw-r--r--win/tkWinWindow.c46
-rw-r--r--win/tkWinWm.c184
-rw-r--r--win/tkWinX.c85
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);