diff options
author | treectrl <treectrl> | 2005-06-08 01:16:51 (GMT) |
---|---|---|
committer | treectrl <treectrl> | 2005-06-08 01:16:51 (GMT) |
commit | 555b64bafcf216a9e936c55106ff5ddb5c1552a6 (patch) | |
tree | 32bb37d80cc95d047ad27162a2688c8f9e758f85 /generic/qebind.c | |
parent | 4a042e5e3e293cbc7aa46dadf968c12248346775 (diff) | |
download | tktreectrl-555b64bafcf216a9e936c55106ff5ddb5c1552a6.zip tktreectrl-555b64bafcf216a9e936c55106ff5ddb5c1552a6.tar.gz tktreectrl-555b64bafcf216a9e936c55106ff5ddb5c1552a6.tar.bz2 |
Binding scripts on a Tk window are automatically deleted if the window is destroyed.
Diffstat (limited to 'generic/qebind.c')
-rw-r--r-- | generic/qebind.c | 139 |
1 files changed, 138 insertions, 1 deletions
diff --git a/generic/qebind.c b/generic/qebind.c index 58871e0..4650938 100644 --- a/generic/qebind.c +++ b/generic/qebind.c @@ -5,7 +5,7 @@ * * Copyright (c) 2002-2005 Tim Baker * - * RCS: @(#) $Id: qebind.c,v 1.11 2005/05/01 01:20:47 treectrl Exp $ + * RCS: @(#) $Id: qebind.c,v 1.12 2005/06/08 01:16:51 treectrl Exp $ */ /* @@ -54,8 +54,16 @@ int debug_bindings = 0; */ #define BIND_ACTIVE 1 +/* + * Allow new events to be added/removed by Tcl commands. + */ #define ALLOW_INSTALL 1 +/* + * Delete scripts bound to a window when that window is destroyed. + */ +#define DELETE_WIN_BINDINGS 1 + typedef struct BindValue { int type; /* Type of event, etc) */ int detail; /* Misc. other information, or 0 for none */ @@ -129,6 +137,9 @@ typedef struct BindingTable { Tcl_HashTable eventTableByName; /* Key: string, Value: EventInfo */ Tcl_HashTable eventTableByType; /* Key: int, Value: EventInfo */ Tcl_HashTable detailTableByType; /* Key: PatternTableKey, Value: Detail */ +#if DELETE_WIN_BINDINGS + Tcl_HashTable winTable; /* Key: Tk_Uid of window name, Value: WinTableValue */ +#endif EventInfo *eventList; /* List of all EventInfos */ int nextEventId; /* Next unique EventInfo.type */ } BindingTable; @@ -464,6 +475,58 @@ static Detail *FindDetail(BindingTable *bindPtr, int eventType, int code) return (Detail *) Tcl_GetHashValue(hPtr); } +#if DELETE_WIN_BINDINGS +typedef struct WinTableValue +{ + BindingTable *bindPtr; + ClientData object; + Tk_Window tkwin; + int count; /* Number of BindValues on object */ +} WinTableValue; +static void TkWinEventProc(ClientData clientData, XEvent *eventPtr) +{ + WinTableValue *cd = (WinTableValue *) clientData; + BindingTable *bindPtr = cd->bindPtr; + ClientData object = cd->object; + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + Tcl_DString dString; + BindValue **valueList; + int i, count = 0; + + if (eventPtr->type != DestroyNotify) + return; + + Tcl_DStringInit(&dString); + + hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); + while (hPtr != NULL) + { + BindValue *valuePtr = (BindValue *) Tcl_GetHashValue(hPtr); + + while (valuePtr != NULL) + { + if (valuePtr->object == object) + { + Tcl_DStringAppend(&dString, (char *) &valuePtr, sizeof(valuePtr)); + count++; + /* The object can only appear once in this chain of + * BindValues */ + break; + } + valuePtr = valuePtr->nextValue; + } + hPtr = Tcl_NextHashEntry(&search); + } + + valueList = (BindValue **) Tcl_DStringValue(&dString); + for (i = 0; i < count; i++) + DeleteBinding(bindPtr, valueList[i]); + + Tcl_DStringFree(&dString); +} +#endif + QE_BindingTable QE_CreateBindingTable(Tcl_Interp *interp) { BindingTable *bindPtr; @@ -478,6 +541,9 @@ QE_BindingTable QE_CreateBindingTable(Tcl_Interp *interp) Tcl_InitHashTable(&bindPtr->eventTableByType, TCL_ONE_WORD_KEYS); Tcl_InitHashTable(&bindPtr->detailTableByType, sizeof(PatternTableKey) / sizeof(int)); +#if DELETE_WIN_BINDINGS + Tcl_InitHashTable(&bindPtr->winTable, TCL_ONE_WORD_KEYS); +#endif bindPtr->nextEventId = 1; bindPtr->eventList = NULL; @@ -543,6 +609,20 @@ void QE_DeleteBindingTable(QE_BindingTable bindingTable) Tcl_DeleteHashTable(&bindPtr->eventTableByType); Tcl_DeleteHashTable(&bindPtr->detailTableByType); +#if DELETE_WIN_BINDINGS + hPtr = Tcl_FirstHashEntry(&bindPtr->winTable, &search); + while (hPtr != NULL) + { + WinTableValue *cd = (WinTableValue *) Tcl_GetHashValue(hPtr); + + Tk_DeleteEventHandler(cd->tkwin, StructureNotifyMask, + TkWinEventProc, (ClientData) cd); + Tcl_Free((char *) cd); + hPtr = Tcl_NextHashEntry(&search); + } + Tcl_DeleteHashTable(&bindPtr->winTable); +#endif + memset((char *) bindPtr, 0xAA, sizeof(BindingTable)); Tcl_Free((char *) bindPtr); } @@ -563,6 +643,40 @@ int QE_CreateBinding(QE_BindingTable bindingTable, ClientData object, { Tcl_HashEntry *hPtr; PatternTableKey key; +#if DELETE_WIN_BINDINGS + char *winName = (char *) object; + + if (winName[0] == '.') + { + Tk_Window tkwin = Tk_MainWindow(bindPtr->interp); + Tk_Window tkwin2; + + tkwin2 = Tk_NameToWindow(bindPtr->interp, winName, tkwin); + if (tkwin2 != NULL) + { + WinTableValue *cd; + + hPtr = Tcl_CreateHashEntry(&bindPtr->winTable, object, &isNew); + if (isNew) + { + cd = (WinTableValue *) Tcl_Alloc(sizeof(WinTableValue)); + cd->bindPtr = bindPtr; + cd->object = object; + cd->tkwin = tkwin2; + cd->count = 0; + Tk_CreateEventHandler(tkwin2, StructureNotifyMask, + TkWinEventProc, (ClientData) cd); + Tcl_SetHashValue(hPtr, (ClientData) cd); + } + else + { + cd = (WinTableValue *) Tcl_GetHashValue(hPtr); + } + /* Number of BindValues for this window */ + cd->count++; + } + } +#endif key.type = valuePtr->type; key.detail = valuePtr->detail; @@ -689,6 +803,29 @@ static int DeleteBinding(BindingTable *bindPtr, BindValue *valuePtr) } } +#if DELETE_WIN_BINDINGS + { + char *winName = (char *) valuePtr->object; + + if (winName[0] == '.') + { + WinTableValue *cd; + + hPtr = Tcl_FindHashEntry(&bindPtr->winTable, winName); + if (hPtr == NULL) return TCL_ERROR; /* fatal error */ + cd = (WinTableValue *) Tcl_GetHashValue(hPtr); + cd->count--; + if (cd->count == 0) + { + Tk_DeleteEventHandler(cd->tkwin, StructureNotifyMask, + TkWinEventProc, (ClientData) cd); + Tcl_Free((char *) cd); + Tcl_DeleteHashEntry(hPtr); + } + } + } +#endif + Tcl_Free((char *) valuePtr->command); memset((char *) valuePtr, 0xAA, sizeof(BindValue)); Tcl_Free((char *) valuePtr); |