diff options
Diffstat (limited to 'generic/tkBind.c')
-rw-r--r-- | generic/tkBind.c | 831 |
1 files changed, 208 insertions, 623 deletions
diff --git a/generic/tkBind.c b/generic/tkBind.c index 11b2122..6841f1e 100644 --- a/generic/tkBind.c +++ b/generic/tkBind.c @@ -29,13 +29,10 @@ * * Init/Free this package. * - * Tcl "bind" command (actually located in tkCmds.c). - * "bind" command implementation. - * "bind" implementation helpers. + * Tcl "bind" command (actually located in tkCmds.c) core implementation, plus + * helpers. * - * Tcl "event" command. - * "event" command implementation. - * "event" implementation helpers. + * Tcl "event" command implementation, plus helpers. * * Package-specific common helpers. * @@ -79,7 +76,7 @@ typedef union { */ #define EVENT_BUFFER_SIZE 30 -typedef struct BindingTable { +typedef struct Tk_BindingTable_ { XEvent eventRing[EVENT_BUFFER_SIZE]; /* Circular queue of recent events (higher * indices are for more recent events). */ @@ -108,12 +105,12 @@ typedef struct BindingTable { * * A virtual event is usually never part of the event stream, but instead is * synthesized inline by matching low-level events. However, a virtual event - * may be generated by platform-specific code or by Tcl scripts. In that case, + * may be generated by platform-specific code or by Tcl commands. In that case, * no lookup of the virtual event will need to be done using this table, * because the virtual event is actually in the event stream. */ -typedef struct VirtualEventTable { +typedef struct { Tcl_HashTable patternTable; /* Used to map from a physical event to a list * of patterns that may match that event. Keys * are PatternTableKey structs, values are @@ -140,7 +137,7 @@ typedef struct VirtualEventTable { * tables and virtual event tables. */ -typedef struct PatternTableKey { +typedef struct { ClientData object; /* For binding table, identifies the binding * tag of the object (or class of objects) * relative to which the event occurred. For @@ -156,7 +153,7 @@ typedef struct PatternTableKey { * events as part of the process of converting X events into Tcl commands. */ -typedef struct Pattern { +typedef struct { int eventType; /* Type of X event, e.g. ButtonPress. */ int needMods; /* Mask of modifiers that must be present (0 * means no modifiers are required). */ @@ -193,21 +190,10 @@ typedef struct Pattern { typedef struct PatSeq { int numPats; /* Number of patterns in sequence (usually * 1). */ - TkBindEvalProc *eventProc; /* The function that will be invoked on the - * clientData when this pattern sequence - * matches. */ - TkBindFreeProc *freeProc; /* The function that will be invoked to - * release the clientData when this pattern - * sequence is freed. */ - ClientData clientData; /* Arbitray data passed to eventProc and - * freeProc when sequence matches. */ + char *script; /* Binding script to evaluate when sequence + * matches (ckalloc()ed) */ int flags; /* Miscellaneous flag values; see below for * definitions. */ - int refCount; /* Number of times that this binding is in the - * midst of executing. If greater than 1, then - * a recursive invocation is happening. Only - * when this is zero can the binding actually - * be freed. */ struct PatSeq *nextSeqPtr; /* Next in list of all pattern sequences that * have the same initial pattern. NULL means * end of list. */ @@ -238,16 +224,9 @@ typedef struct PatSeq { * must occur with nearby X and Y mouse coordinates and * close in time. This is typically used to restrict * multiple button presses. - * MARKED_DELETED 1 means that this binding has been marked as deleted - * and removed from the binding table, but its memory - * could not be released because it was already queued - * for execution. When the binding is actually about to - * be executed, this flag will be checked and the binding - * skipped if set. */ #define PAT_NEARBY 0x1 -#define MARKED_DELETED 0x2 /* * Constants that define how close together two events must be in milliseconds @@ -275,7 +254,7 @@ typedef struct VirtualOwners { * to associate a virtual event with all the physical events that can trigger * it. */ -typedef struct PhysicalsOwned { +typedef struct { int numOwned; /* Number of physical events owned. */ PatSeq *patSeqs[1]; /* Array of pointers to physical event * patterns. Enough space will actually be @@ -285,7 +264,7 @@ typedef struct PhysicalsOwned { /* * One of the following structures exists for each interpreter. This structure * keeps track of the current display and screen in the interpreter, so that a - * script can be invoked whenever the display/screen changes (the script does + * command can be invoked whenever the display/screen changes (the command does * things like point tk::Priv at a display-specific structure). */ @@ -298,44 +277,17 @@ typedef struct { } ScreenInfo; /* - * The following structure is used to keep track of all the C bindings that - * are awaiting invocation and whether the window they refer to has been - * destroyed. If the window is destroyed, then all pending callbacks for that - * window will be cancelled. The Tcl bindings will still all be invoked, - * however. - */ - -typedef struct PendingBinding { - struct PendingBinding *nextPtr; - /* Next in chain of pending bindings, in case - * a recursive binding evaluation is in - * progress. */ - Tk_Window tkwin; /* The window that the following bindings - * depend upon. */ - int deleted; /* Set to non-zero by window cleanup code if - * tkwin is deleted. */ - PatSeq *matchArray[5]; /* Array of pending C bindings. The actual - * size of this depends on how many C bindings - * matched the event passed to Tk_BindEvent. - * THIS FIELD MUST BE THE LAST IN THE - * STRUCTURE. */ -} PendingBinding; - -/* * The following structure keeps track of all the information local to the * binding package on a per interpreter basis. */ -typedef struct BindInfo { +typedef struct TkBindInfo_ { VirtualEventTable virtualEventTable; /* The virtual events that exist in this * interpreter. */ ScreenInfo screenInfo; /* Keeps track of the current display and * screen, so it can be restored after a * binding has executed. */ - PendingBinding *pendingList;/* The list of pending C bindings, kept in - * case a C or Tcl binding causes the target - * window to be deleted. */ int deleted; /* 1 the application has been deleted but the * structure has been preserved. */ } BindInfo; @@ -352,10 +304,10 @@ typedef struct BindInfo { #ifdef REDO_KEYSYM_LOOKUP typedef struct { - char *name; /* Name of keysym. */ + const char *name; /* Name of keysym. */ KeySym value; /* Numeric identifier for keysym. */ } KeySymInfo; -static KeySymInfo keyArray[] = { +static const KeySymInfo keyArray[] = { #ifndef lint #include "ks_names.h" #endif @@ -381,7 +333,7 @@ TCL_DECLARE_MUTEX(bindMutex) */ typedef struct { - char *name; /* Name of modifier. */ + const char *name; /* Name of modifier. */ int mask; /* Button/modifier mask value, such as * Button1Mask. */ int flags; /* Various flags; see below for @@ -405,7 +357,7 @@ typedef struct { #define QUADRUPLE 4 #define MULT_CLICKS 7 -static ModInfo modArray[] = { +static const ModInfo modArray[] = { {"Control", ControlMask, 0}, {"Shift", ShiftMask, 0}, {"Lock", LockMask, 0}, @@ -450,7 +402,7 @@ static Tcl_HashTable modTable; */ typedef struct { - char *name; /* Name of event. */ + const char *name; /* Name of event. */ int type; /* Event type for X, such as ButtonPress. */ int eventMask; /* Mask bits (for XSelectInput) for this event * type. */ @@ -463,7 +415,7 @@ typedef struct { * unless you've asked about button events. */ -static EventInfo eventArray[] = { +static const EventInfo eventArray[] = { {"Key", KeyPress, KeyPressMask}, {"KeyPress", KeyPress, KeyPressMask}, {"KeyRelease", KeyRelease, KeyPressMask|KeyReleaseMask}, @@ -535,7 +487,7 @@ static Tcl_HashTable eventTable; #define KEY_BUTTON_MOTION_VIRTUAL (KEY|BUTTON|MOTION|VIRTUAL) #define KEY_BUTTON_MOTION_CROSSING (KEY|BUTTON|MOTION|VIRTUAL|CROSSING) -static int flagArray[TK_LASTEVENT] = { +static const int flagArray[TK_LASTEVENT] = { /* Not used */ 0, /* Not used */ 0, /* KeyPress */ KEY, @@ -654,14 +606,13 @@ static void ChangeScreen(Tcl_Interp *interp, char *dispName, int screenIndex); static int CreateVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr, char *virtString, - char *eventString); + const char *eventString); static int DeleteVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr, char *virtString, - char *eventString); + const char *eventString); static void DeleteVirtualEventTable(VirtualEventTable *vetPtr); static void ExpandPercents(TkWindow *winPtr, const char *before, XEvent *eventPtr,KeySym keySym,Tcl_DString *dsPtr); -static void FreeTclBinding(ClientData clientData); static PatSeq * FindSequence(Tcl_Interp *interp, Tcl_HashTable *patternTablePtr, ClientData object, const char *eventString, int create, @@ -671,7 +622,7 @@ static void GetAllVirtualEvents(Tcl_Interp *interp, static char * GetField(char *p, char *copy, int size); static void GetPatternString(PatSeq *psPtr, Tcl_DString *dsPtr); static int GetVirtualEvent(Tcl_Interp *interp, - VirtualEventTable *vetPtr, char *virtString); + VirtualEventTable *vetPtr, Tcl_Obj *virtName); static Tk_Uid GetVirtualEventUid(Tcl_Interp *interp, char *virtString); static int HandleEventGenerate(Tcl_Interp *interp, Tk_Window main, @@ -687,15 +638,6 @@ static int ParseEventDescription(Tcl_Interp *interp, const char **eventStringPtr, Pattern *patPtr, unsigned long *eventMaskPtr); static void DoWarp(ClientData clientData); - -/* - * The following define is used as a short circuit for the callback function - * to evaluate a TclBinding. The actual evaluation of the binding is handled - * inline, because special things have to be done with a Tcl binding before - * evaluation time. - */ - -#define EvalTclBinding ((TkBindEvalProc *) 1) /* *--------------------------------------------------------------------------- @@ -734,11 +676,11 @@ TkBindInit( Tcl_MutexLock(&bindMutex); if (!initialized) { Tcl_HashEntry *hPtr; - ModInfo *modPtr; - EventInfo *eiPtr; + const ModInfo *modPtr; + const EventInfo *eiPtr; int newEntry; #ifdef REDO_KEYSYM_LOOKUP - KeySymInfo *kPtr; + const KeySymInfo *kPtr; Tcl_InitHashTable(&keySymTable, TCL_STRING_KEYS); Tcl_InitHashTable(&nameTable, TCL_ONE_WORD_KEYS); @@ -771,14 +713,13 @@ TkBindInit( mainPtr->bindingTable = Tk_CreateBindingTable(mainPtr->interp); - bindInfoPtr = (BindInfo *) ckalloc(sizeof(BindInfo)); + bindInfoPtr = ckalloc(sizeof(BindInfo)); InitVirtualEventTable(&bindInfoPtr->virtualEventTable); bindInfoPtr->screenInfo.curDispPtr = NULL; bindInfoPtr->screenInfo.curScreenIndex = -1; bindInfoPtr->screenInfo.bindingDepth = 0; - bindInfoPtr->pendingList = NULL; bindInfoPtr->deleted = 0; - mainPtr->bindInfo = (TkBindInfo) bindInfoPtr; + mainPtr->bindInfo = bindInfoPtr; TkpInitializeMenuBindings(mainPtr->interp, mainPtr->bindingTable); } @@ -809,10 +750,10 @@ TkBindFree( Tk_DeleteBindingTable(mainPtr->bindingTable); mainPtr->bindingTable = NULL; - bindInfoPtr = (BindInfo *) mainPtr->bindInfo; + bindInfoPtr = mainPtr->bindInfo; DeleteVirtualEventTable(&bindInfoPtr->virtualEventTable); bindInfoPtr->deleted = 1; - Tcl_EventuallyFree((ClientData) bindInfoPtr, TCL_DYNAMIC); + Tcl_EventuallyFree(bindInfoPtr, TCL_DYNAMIC); mainPtr->bindInfo = NULL; } @@ -839,14 +780,13 @@ Tk_CreateBindingTable( * table: commands are executed in this * interpreter. */ { - BindingTable *bindPtr; + BindingTable *bindPtr = ckalloc(sizeof(BindingTable)); int i; /* * Create and initialize a new binding table. */ - bindPtr = (BindingTable *) ckalloc(sizeof(BindingTable)); for (i = 0; i < EVENT_BUFFER_SIZE; i++) { bindPtr->eventRing[i].type = -1; } @@ -855,7 +795,7 @@ Tk_CreateBindingTable( sizeof(PatternTableKey)/sizeof(int)); Tcl_InitHashTable(&bindPtr->objectTable, TCL_ONE_WORD_KEYS); bindPtr->interp = interp; - return (Tk_BindingTable) bindPtr; + return bindPtr; } /* @@ -877,10 +817,8 @@ Tk_CreateBindingTable( void Tk_DeleteBindingTable( - Tk_BindingTable bindingTable) - /* Token for the binding table to destroy. */ + Tk_BindingTable bindPtr) /* Token for the binding table to destroy. */ { - BindingTable *bindPtr = (BindingTable *) bindingTable; PatSeq *psPtr, *nextPtr; Tcl_HashEntry *hPtr; Tcl_HashSearch search; @@ -891,16 +829,10 @@ Tk_DeleteBindingTable( for (hPtr = Tcl_FirstHashEntry(&bindPtr->patternTable, &search); hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - for (psPtr = (PatSeq *) Tcl_GetHashValue(hPtr); - psPtr != NULL; psPtr = nextPtr) { + for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL; psPtr = nextPtr) { nextPtr = psPtr->nextSeqPtr; - psPtr->flags |= MARKED_DELETED; - if (psPtr->refCount == 0) { - if (psPtr->freeProc != NULL) { - (*psPtr->freeProc)(psPtr->clientData); - } - ckfree((char *) psPtr); - } + ckfree(psPtr->script); + ckfree(psPtr); } } @@ -910,7 +842,7 @@ Tk_DeleteBindingTable( Tcl_DeleteHashTable(&bindPtr->patternTable); Tcl_DeleteHashTable(&bindPtr->objectTable); - ckfree((char *) bindPtr); + ckfree(bindPtr); } /* @@ -940,13 +872,12 @@ Tk_DeleteBindingTable( unsigned long Tk_CreateBinding( Tcl_Interp *interp, /* Used for error reporting. */ - Tk_BindingTable bindingTable, - /* Table in which to create binding. */ + Tk_BindingTable bindPtr, /* Table in which to create binding. */ ClientData object, /* Token for object with which binding is * associated. */ const char *eventString, /* String describing event sequence that * triggers binding. */ - const char *command, /* Contains Tcl command to execute when + const char *script, /* Contains Tcl script to execute when * binding triggers. */ int append) /* 0 means replace any existing binding for * eventString; 1 means append to that @@ -955,12 +886,11 @@ Tk_CreateBinding( * string, the existing binding will always be * replaced. */ { - BindingTable *bindPtr = (BindingTable *) bindingTable; PatSeq *psPtr; unsigned long eventMask; char *newStr, *oldStr; - if (!*command) { + if (!*script) { /* Silently ignore empty scripts -- see SF#3006842 */ return 1; } @@ -969,7 +899,7 @@ Tk_CreateBinding( if (psPtr == NULL) { return 0; } - if (psPtr->eventProc == NULL) { + if (psPtr->script == NULL) { int isNew; Tcl_HashEntry *hPtr; @@ -984,120 +914,29 @@ Tk_CreateBinding( if (isNew) { psPtr->nextObjPtr = NULL; } else { - psPtr->nextObjPtr = (PatSeq *) Tcl_GetHashValue(hPtr); + psPtr->nextObjPtr = Tcl_GetHashValue(hPtr); } Tcl_SetHashValue(hPtr, psPtr); - } else if (psPtr->eventProc != EvalTclBinding) { - /* - * Free existing procedural binding. - */ - - if (psPtr->freeProc != NULL) { - (*psPtr->freeProc)(psPtr->clientData); - } - psPtr->clientData = NULL; - append = 0; } - oldStr = (char *) psPtr->clientData; + oldStr = psPtr->script; if ((append != 0) && (oldStr != NULL)) { - size_t length; + size_t length1 = strlen(oldStr), length2 = strlen(script); - length = strlen(oldStr) + strlen(command) + 2; - newStr = (char *) ckalloc((unsigned) length); - sprintf(newStr, "%s\n%s", oldStr, command); + newStr = ckalloc(length1 + length2 + 2); + memcpy(newStr, oldStr, length1); + newStr[length1] = '\n'; + memcpy(newStr+length1+1, script, length2+1); } else { - newStr = (char *) ckalloc((unsigned) strlen(command) + 1); - strcpy(newStr, command); + size_t length = strlen(script); + + newStr = ckalloc(length + 1); + memcpy(newStr, script, length+1); } if (oldStr != NULL) { ckfree(oldStr); } - psPtr->eventProc = EvalTclBinding; - psPtr->freeProc = FreeTclBinding; - psPtr->clientData = (ClientData) newStr; - return eventMask; -} - -/* - *--------------------------------------------------------------------------- - * - * TkCreateBindingProcedure -- - * - * Add a C binding to a binding table, so that future calls to - * Tk_BindEvent may callback the function in the binding. - * - * Results: - - * The return value is 0 if an error occurred while setting up the - * binding. In this case, an error message will be left in the interp's - * result. If all went well then the return value is a mask of the event - * types that must be made available to Tk_BindEvent in order to properly - * detect when this binding triggers. This value can be used to determine - * what events to select for in a window, for example. - * - * Side effects: - * Any existing binding on the same event sequence will be replaced. - * - *--------------------------------------------------------------------------- - */ - -unsigned long -TkCreateBindingProcedure( - Tcl_Interp *interp, /* Used for error reporting. */ - Tk_BindingTable bindingTable, - /* Table in which to create binding. */ - ClientData object, /* Token for object with which binding is - * associated. */ - const char *eventString, /* String describing event sequence that - * triggers binding. */ - TkBindEvalProc *eventProc, /* Function to invoke when binding triggers. - * Must not be NULL. */ - TkBindFreeProc *freeProc, /* Function to invoke when binding is freed. - * May be NULL for no function. */ - ClientData clientData) /* Arbitrary ClientData to pass to eventProc - * and freeProc. */ -{ - BindingTable *bindPtr = (BindingTable *) bindingTable; - PatSeq *psPtr; - unsigned long eventMask; - - psPtr = FindSequence(interp, &bindPtr->patternTable, object, eventString, - 1, 1, &eventMask); - if (psPtr == NULL) { - return 0; - } - if (psPtr->eventProc == NULL) { - int isNew; - Tcl_HashEntry *hPtr; - - /* - * This pattern sequence was just created. Link the pattern into the - * list associated with the object, so that if the object goes away, - * these bindings will all automatically be deleted. - */ - - hPtr = Tcl_CreateHashEntry(&bindPtr->objectTable, (char *) object, - &isNew); - if (isNew) { - psPtr->nextObjPtr = NULL; - } else { - psPtr->nextObjPtr = (PatSeq *) Tcl_GetHashValue(hPtr); - } - Tcl_SetHashValue(hPtr, psPtr); - } else { - /* - * Free existing callback. - */ - - if (psPtr->freeProc != NULL) { - (*psPtr->freeProc)(psPtr->clientData); - } - } - - psPtr->eventProc = eventProc; - psPtr->freeProc = freeProc; - psPtr->clientData = clientData; + psPtr->script = newStr; return eventMask; } @@ -1122,14 +961,12 @@ TkCreateBindingProcedure( int Tk_DeleteBinding( Tcl_Interp *interp, /* Used for error reporting. */ - Tk_BindingTable bindingTable, - /* Table in which to delete binding. */ + Tk_BindingTable bindPtr, /* Table in which to delete binding. */ ClientData object, /* Token for object with which binding is * associated. */ const char *eventString) /* String describing event sequence that * triggers binding. */ { - BindingTable *bindPtr = (BindingTable *) bindingTable; PatSeq *psPtr, *prevPtr; unsigned long eventMask; Tcl_HashEntry *hPtr; @@ -1150,7 +987,7 @@ Tk_DeleteBinding( if (hPtr == NULL) { Tcl_Panic("Tk_DeleteBinding couldn't find object table entry"); } - prevPtr = (PatSeq *) Tcl_GetHashValue(hPtr); + prevPtr = Tcl_GetHashValue(hPtr); if (prevPtr == psPtr) { Tcl_SetHashValue(hPtr, psPtr->nextObjPtr); } else { @@ -1164,7 +1001,7 @@ Tk_DeleteBinding( } } } - prevPtr = (PatSeq *) Tcl_GetHashValue(psPtr->hPtr); + prevPtr = Tcl_GetHashValue(psPtr->hPtr); if (prevPtr == psPtr) { if (psPtr->nextSeqPtr == NULL) { Tcl_DeleteHashEntry(psPtr->hPtr); @@ -1183,13 +1020,8 @@ Tk_DeleteBinding( } } - psPtr->flags |= MARKED_DELETED; - if (psPtr->refCount == 0) { - if (psPtr->freeProc != NULL) { - (*psPtr->freeProc)(psPtr->clientData); - } - ckfree((char *) psPtr); - } + ckfree(psPtr->script); + ckfree(psPtr); return TCL_OK; } @@ -1198,10 +1030,10 @@ Tk_DeleteBinding( * * Tk_GetBinding -- * - * Return the command associated with a given event string. + * Return the script associated with a given event string. * * Results: - * The return value is a pointer to the command string associated with + * The return value is a pointer to the script associated with * eventString for object in the domain given by bindingTable. If there * is no binding for eventString, or if eventString is improperly formed, * then NULL is returned and an error message is left in the interp's @@ -1217,14 +1049,12 @@ Tk_DeleteBinding( const char * Tk_GetBinding( Tcl_Interp *interp, /* Interpreter for error reporting. */ - Tk_BindingTable bindingTable, - /* Table in which to look for binding. */ + Tk_BindingTable bindPtr, /* Table in which to look for binding. */ ClientData object, /* Token for object with which binding is * associated. */ const char *eventString) /* String describing event sequence that * triggers binding. */ { - BindingTable *bindPtr = (BindingTable *) bindingTable; PatSeq *psPtr; unsigned long eventMask; @@ -1233,10 +1063,7 @@ Tk_GetBinding( if (psPtr == NULL) { return NULL; } - if (psPtr->eventProc == EvalTclBinding) { - return (const char *) psPtr->clientData; - } - return ""; + return psPtr->script; } /* @@ -1262,11 +1089,9 @@ Tk_GetBinding( void Tk_GetAllBindings( Tcl_Interp *interp, /* Interpreter returning result or error. */ - Tk_BindingTable bindingTable, - /* Table in which to look for bindings. */ + Tk_BindingTable bindPtr, /* Table in which to look for bindings. */ ClientData object) /* Token for object. */ { - BindingTable *bindPtr = (BindingTable *) bindingTable; PatSeq *psPtr; Tcl_HashEntry *hPtr; Tcl_DString ds; @@ -1276,7 +1101,7 @@ Tk_GetAllBindings( return; } Tcl_DStringInit(&ds); - for (psPtr = (PatSeq *) Tcl_GetHashValue(hPtr); psPtr != NULL; + for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL; psPtr = psPtr->nextObjPtr) { /* * For each binding, output information about each of the patterns in @@ -1309,11 +1134,9 @@ Tk_GetAllBindings( void Tk_DeleteAllBindings( - Tk_BindingTable bindingTable, - /* Table in which to delete bindings. */ + Tk_BindingTable bindPtr, /* Table in which to delete bindings. */ ClientData object) /* Token for object. */ { - BindingTable *bindPtr = (BindingTable *) bindingTable; PatSeq *psPtr, *prevPtr; PatSeq *nextPtr; Tcl_HashEntry *hPtr; @@ -1322,7 +1145,7 @@ Tk_DeleteAllBindings( if (hPtr == NULL) { return; } - for (psPtr = (PatSeq *) Tcl_GetHashValue(hPtr); psPtr != NULL; + for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL; psPtr = nextPtr) { nextPtr = psPtr->nextObjPtr; @@ -1332,7 +1155,7 @@ Tk_DeleteAllBindings( * hash entry too. */ - prevPtr = (PatSeq *) Tcl_GetHashValue(psPtr->hPtr); + prevPtr = Tcl_GetHashValue(psPtr->hPtr); if (prevPtr == psPtr) { if (psPtr->nextSeqPtr == NULL) { Tcl_DeleteHashEntry(psPtr->hPtr); @@ -1350,14 +1173,8 @@ Tk_DeleteAllBindings( } } } - psPtr->flags |= MARKED_DELETED; - - if (psPtr->refCount == 0) { - if (psPtr->freeProc != NULL) { - (*psPtr->freeProc)(psPtr->clientData); - } - ckfree((char *) psPtr); - } + ckfree(psPtr->script); + ckfree(psPtr); } Tcl_DeleteHashEntry(hPtr); } @@ -1377,27 +1194,19 @@ Tk_DeleteAllBindings( * None. * * Side effects: - * Depends on the command associated with the matching binding. + * Depends on the script associated with the matching binding. * - * All Tcl bindings scripts for each object are accumulated before the + * All Tcl binding scripts for each object are accumulated before the * first binding is evaluated. If the action of a Tcl binding is to * change or delete a binding, or delete the window associated with the * binding, all the original Tcl binding scripts will still fire. - * Contrast this with C binding functions. If a pending C binding (one - * that hasn't fired yet, but is queued to be fired for this window) is - * deleted, it will not be called, and if it is changed, then the new - * binding function will be called. If the window itself is deleted, no - * further C binding functions will be called for this window. When both - * Tcl binding scripts and C binding functions are interleaved, the above - * rules still apply. * *--------------------------------------------------------------------------- */ void Tk_BindEvent( - Tk_BindingTable bindingTable, - /* Table in which to look for bindings. */ + Tk_BindingTable bindPtr, /* Table in which to look for bindings. */ XEvent *eventPtr, /* What actually happened. */ Tk_Window tkwin, /* Window on display where event occurred * (needed in order to locate display @@ -1406,23 +1215,19 @@ Tk_BindEvent( ClientData *objectPtr) /* Array of one or more objects to check for a * matching binding. */ { - BindingTable *bindPtr; TkDisplay *dispPtr; ScreenInfo *screenPtr; BindInfo *bindInfoPtr; TkDisplay *oldDispPtr; XEvent *ringPtr; PatSeq *vMatchDetailList, *vMatchNoDetailList; - int flags, oldScreen, i, deferModal; - unsigned int matchCount, matchSpace; + int flags, oldScreen; Tcl_Interp *interp; Tcl_DString scripts, savedResult; Detail detail; char *p, *end; - PendingBinding staticPending, *pendingPtr; TkWindow *winPtr = (TkWindow *) tkwin; PatternTableKey key; - Tk_ClassModalProc *modalProc; /* * Ignore events on windows that don't have names: these are windows like @@ -1453,9 +1258,8 @@ Tk_BindEvent( } } - bindPtr = (BindingTable *) bindingTable; dispPtr = ((TkWindow *) tkwin)->dispPtr; - bindInfoPtr = (BindInfo *) winPtr->mainPtr->bindInfo; + bindInfoPtr = winPtr->mainPtr->bindInfo; /* * Add the new event to the ring of saved events for the binding table. @@ -1515,7 +1319,7 @@ Tk_BindEvent( } } ringPtr = &bindPtr->eventRing[bindPtr->curEvent]; - memcpy((void *) ringPtr, (void *) eventPtr, sizeof(XEvent)); + memcpy(ringPtr, eventPtr, sizeof(XEvent)); detail.clientData = 0; flags = flagArray[ringPtr->type]; if (flags & KEY) { @@ -1549,14 +1353,14 @@ Tk_BindEvent( hPtr = Tcl_FindHashEntry(veptPtr, (char *) &key); if (hPtr != NULL) { - vMatchDetailList = (PatSeq *) Tcl_GetHashValue(hPtr); + vMatchDetailList = Tcl_GetHashValue(hPtr); } if (key.detail.clientData != 0) { key.detail.clientData = 0; hPtr = Tcl_FindHashEntry(veptPtr, (char *) &key); if (hPtr != NULL) { - vMatchNoDetailList = (PatSeq *) Tcl_GetHashValue(hPtr); + vMatchNoDetailList = Tcl_GetHashValue(hPtr); } } } @@ -1565,13 +1369,9 @@ Tk_BindEvent( * Loop over all the binding tags, finding the binding script or callback * for each one. Append all of the binding scripts, with %-sequences * expanded, to "scripts", with null characters separating the scripts for - * each object. Append all the callbacks to the array of pending - * callbacks. + * each object. */ - pendingPtr = &staticPending; - matchCount = 0; - matchSpace = sizeof(staticPending.matchArray) / sizeof(PatSeq *); Tcl_DStringInit(&scripts); for ( ; numObjects > 0; numObjects--, objectPtr++) { @@ -1591,9 +1391,8 @@ Tk_BindEvent( key.detail = detail; hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key); if (hPtr != NULL) { - matchPtr = MatchPatterns(dispPtr, bindPtr, - (PatSeq *) Tcl_GetHashValue(hPtr), matchPtr, NULL, - &sourcePtr); + matchPtr = MatchPatterns(dispPtr, bindPtr, Tcl_GetHashValue(hPtr), + matchPtr, NULL, &sourcePtr); } if (vMatchDetailList != NULL) { @@ -1611,47 +1410,18 @@ Tk_BindEvent( hPtr = Tcl_FindHashEntry(&bindPtr->patternTable, (char *) &key); if (hPtr != NULL) { matchPtr = MatchPatterns(dispPtr, bindPtr, - (PatSeq *) Tcl_GetHashValue(hPtr), matchPtr, NULL, - &sourcePtr); + Tcl_GetHashValue(hPtr), matchPtr, NULL, &sourcePtr); } if (vMatchNoDetailList != NULL) { matchPtr = MatchPatterns(dispPtr, bindPtr, vMatchNoDetailList, matchPtr, objectPtr, &sourcePtr); } - } if (matchPtr != NULL) { - if (sourcePtr->eventProc == NULL) { - Tcl_Panic("Tk_BindEvent: missing command"); - } - if (sourcePtr->eventProc == EvalTclBinding) { - ExpandPercents(winPtr, (char *) sourcePtr->clientData, - eventPtr, detail.keySym, &scripts); - } else { - if (matchCount >= matchSpace) { - PendingBinding *newPtr; - unsigned int oldSize, newSize; - - oldSize = sizeof(staticPending) - - sizeof(staticPending.matchArray) - + matchSpace * sizeof(PatSeq*); - matchSpace *= 2; - newSize = sizeof(staticPending) - - sizeof(staticPending.matchArray) - + matchSpace * sizeof(PatSeq*); - newPtr = (PendingBinding *) ckalloc(newSize); - memcpy((void *) newPtr, (void *) pendingPtr, oldSize); - if (pendingPtr != &staticPending) { - ckfree((char *) pendingPtr); - } - pendingPtr = newPtr; - } - sourcePtr->refCount++; - pendingPtr->matchArray[matchCount] = sourcePtr; - matchCount++; - } + ExpandPercents(winPtr, sourcePtr->script, eventPtr, + detail.keySym, &scripts); /* * A "" is added to the scripts string to separate the various @@ -1701,31 +1471,8 @@ Tk_BindEvent( ChangeScreen(interp, dispPtr->name, screenPtr->curScreenIndex); } - if (matchCount > 0) { - /* - * Remember the list of pending C binding callbacks, so we can mark - * them as deleted and not call them if the act of evaluating a C or - * Tcl binding deletes a C binding callback or even the whole window. - */ - - pendingPtr->nextPtr = bindInfoPtr->pendingList; - pendingPtr->tkwin = tkwin; - pendingPtr->deleted = 0; - bindInfoPtr->pendingList = pendingPtr; - } - - /* - * Save the current value of the TK_DEFER_MODAL flag so we can restore it - * at the end of the loop. Clear the flag so we can detect any recursive - * requests for a modal loop. - */ - - flags = winPtr->flags; - winPtr->flags &= ~TK_DEFER_MODAL; - p = Tcl_DStringValue(&scripts); end = p + Tcl_DStringLength(&scripts); - i = 0; /* * Be carefule when dereferencing screenPtr or bindInfoPtr. If we evaluate @@ -1733,8 +1480,9 @@ Tk_BindEvent( * can tell that by first checking to see if winPtr->mainPtr == NULL. */ - Tcl_Preserve((ClientData) bindInfoPtr); + Tcl_Preserve(bindInfoPtr); while (p < end) { + int len = (int) strlen(p); int code; if (!bindInfoPtr->deleted) { @@ -1742,31 +1490,8 @@ Tk_BindEvent( } Tcl_AllowExceptions(interp); - if (*p == '\0') { - PatSeq *psPtr; - - psPtr = pendingPtr->matchArray[i]; - i++; - code = TCL_OK; - if ((pendingPtr->deleted == 0) - && ((psPtr->flags & MARKED_DELETED) == 0)) { - code = (*psPtr->eventProc)(psPtr->clientData, interp, eventPtr, - tkwin, detail.keySym); - } - psPtr->refCount--; - if ((psPtr->refCount == 0) && (psPtr->flags & MARKED_DELETED)) { - if (psPtr->freeProc != NULL) { - (*psPtr->freeProc)(psPtr->clientData); - } - ckfree((char *) psPtr); - } - } else { - int len = (int) strlen(p); - - code = Tcl_EvalEx(interp, p, len, TCL_EVAL_GLOBAL); - p += len; - } - p++; + code = Tcl_EvalEx(interp, p, len, TCL_EVAL_GLOBAL); + p += len + 1; if (!bindInfoPtr->deleted) { screenPtr->bindingDepth--; @@ -1780,29 +1505,12 @@ Tk_BindEvent( break; } else { Tcl_AddErrorInfo(interp, "\n (command bound to event)"); - Tcl_BackgroundError(interp); + Tcl_BackgroundException(interp, code); break; } } } - if (matchCount > 0 && !pendingPtr->deleted) { - /* - * Restore the original modal flag value and invoke the modal loop if - * needed. - */ - - deferModal = winPtr->flags & TK_DEFER_MODAL; - winPtr->flags = (winPtr->flags & (unsigned int) ~TK_DEFER_MODAL) - | (flags & TK_DEFER_MODAL); - if (deferModal) { - modalProc = Tk_GetClassProc(winPtr->classProcsPtr, modalProc); - if (modalProc != NULL) { - (*modalProc)(tkwin, eventPtr); - } - } - } - if (!bindInfoPtr->deleted && (screenPtr->bindingDepth != 0) && ((oldDispPtr != screenPtr->curDispPtr) || (oldScreen != screenPtr->curScreenIndex))) { @@ -1818,71 +1526,7 @@ Tk_BindEvent( Tcl_DStringResult(interp, &savedResult); Tcl_DStringFree(&scripts); - if (matchCount > 0) { - if (!bindInfoPtr->deleted) { - /* - * Delete the pending list from the list of pending scripts for - * this window. - */ - - PendingBinding **curPtrPtr; - - for (curPtrPtr = &bindInfoPtr->pendingList; ; ) { - if (*curPtrPtr == pendingPtr) { - *curPtrPtr = pendingPtr->nextPtr; - break; - } - curPtrPtr = &(*curPtrPtr)->nextPtr; - } - } - if (pendingPtr != &staticPending) { - ckfree((char *) pendingPtr); - } - } - Tcl_Release((ClientData) bindInfoPtr); -} - -/* - *--------------------------------------------------------------------------- - * - * TkBindDeadWindow -- - * - * This function is invoked when it is determined that a window is dead. - * It cleans up bind-related information about the window - * - * Results: - * None. - * - * Side effects: - * Any pending C bindings for this window are cancelled. - * - *--------------------------------------------------------------------------- - */ - -void -TkBindDeadWindow( - TkWindow *winPtr) /* The window that is being deleted. */ -{ - BindInfo *bindInfoPtr; - PendingBinding *curPtr; - - /* - * Certain special windows like those used for send and clipboard have no - * mainPtr. - */ - - if (winPtr->mainPtr == NULL) { - return; - } - - bindInfoPtr = (BindInfo *) winPtr->mainPtr->bindInfo; - curPtr = bindInfoPtr->pendingList; - while (curPtr != NULL) { - if (curPtr->tkwin == (Tk_Window) winPtr) { - curPtr->deleted = 1; - } - curPtr = curPtr->nextPtr; - } + Tcl_Release(bindInfoPtr); } /* @@ -1921,6 +1565,7 @@ TkBindDeadWindow( * *---------------------------------------------------------------------- */ + static PatSeq * MatchPatterns( TkDisplay *dispPtr, /* Display from which the event came. */ @@ -2144,7 +1789,7 @@ MatchPatterns( * virtual event's definition. */ - PatSeq *virtMatchPtr = (PatSeq *) Tcl_GetHashValue(hPtr); + PatSeq *virtMatchPtr = Tcl_GetHashValue(hPtr); if ((virtMatchPtr->numPats != 1) || (virtMatchPtr->nextSeqPtr != NULL)) { @@ -2533,7 +2178,7 @@ ExpandPercents( goto doNumber; case 'K': if (flags & KEY) { - char *name = TkKeysymToString(keySym); + const char *name = TkKeysymToString(keySym); if (name != NULL) { string = name; @@ -2662,23 +2307,18 @@ ChangeScreen( char *dispName, /* Name of new display. */ int screenIndex) /* Index of new screen. */ { - Tcl_DString cmd; + Tcl_Obj *cmdObj = Tcl_ObjPrintf("::tk::ScreenChanged %s.%d", + dispName, screenIndex); int code; - char screen[TCL_INTEGER_SPACE]; - - Tcl_DStringInit(&cmd); - Tcl_DStringAppend(&cmd, "tk::ScreenChanged ", 18); - Tcl_DStringAppend(&cmd, dispName, -1); - sprintf(screen, ".%d", screenIndex); - Tcl_DStringAppend(&cmd, screen, -1); - code = Tcl_EvalEx(interp, Tcl_DStringValue(&cmd), Tcl_DStringLength(&cmd), - TCL_EVAL_GLOBAL); - Tcl_DStringFree(&cmd); + + Tcl_IncrRefCount(cmdObj); + code = Tcl_GlobalEvalObj(interp, cmdObj); if (code != TCL_OK) { Tcl_AddErrorInfo(interp, "\n (changing screen in event binding)"); - Tcl_BackgroundError(interp); + Tcl_BackgroundException(interp, code); } + Tcl_DecrRefCount(cmdObj); } /* @@ -2705,11 +2345,13 @@ Tk_EventObjCmd( int objc, /* Number of arguments. */ Tcl_Obj *const objv[]) /* Argument objects. */ { - int index; - Tk_Window tkwin; - VirtualEventTable *vetPtr; - TkBindInfo bindInfo; - static const char *optionStrings[] = { + int index, i; + char *name; + const char *event; + Tk_Window tkwin = clientData; + TkBindInfo bindInfo = ((TkWindow *) tkwin)->mainPtr->bindInfo; + VirtualEventTable *vetPtr = &bindInfo->virtualEventTable; + static const char *const optionStrings[] = { "add", "delete", "generate", "info", NULL }; @@ -2717,9 +2359,6 @@ Tk_EventObjCmd( EVENT_ADD, EVENT_DELETE, EVENT_GENERATE, EVENT_INFO }; - tkwin = (Tk_Window) clientData; - bindInfo = ((TkWindow *) tkwin)->mainPtr->bindInfo; - vetPtr = &((BindInfo *) bindInfo)->virtualEventTable; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg?"); @@ -2731,10 +2370,7 @@ Tk_EventObjCmd( } switch ((enum options) index) { - case EVENT_ADD: { - int i; - char *name, *event; - + case EVENT_ADD: if (objc < 4) { Tcl_WrongNumArgs(interp, 2, objv, "virtual sequence ?sequence ...?"); @@ -2748,14 +2384,9 @@ Tk_EventObjCmd( } } break; - } - case EVENT_DELETE: { - int i; - char *name, *event; - + case EVENT_DELETE: if (objc < 3) { - Tcl_WrongNumArgs(interp, 2, objv, - "virtual ?sequence sequence ...?"); + Tcl_WrongNumArgs(interp, 2, objv, "virtual ?sequence ...?"); return TCL_ERROR; } name = Tcl_GetString(objv[2]); @@ -2769,10 +2400,10 @@ Tk_EventObjCmd( } } break; - } case EVENT_GENERATE: if (objc < 4) { - Tcl_WrongNumArgs(interp, 2, objv, "window event ?options?"); + Tcl_WrongNumArgs(interp, 2, objv, + "window event ?-option value ...?"); return TCL_ERROR; } return HandleEventGenerate(interp, tkwin, objc - 2, objv + 2); @@ -2781,7 +2412,7 @@ Tk_EventObjCmd( GetAllVirtualEvents(interp, vetPtr); return TCL_OK; } else if (objc == 3) { - return GetVirtualEvent(interp, vetPtr, Tcl_GetString(objv[2])); + return GetVirtualEvent(interp, vetPtr, objv[2]); } else { Tcl_WrongNumArgs(interp, 2, objv, "?virtual?"); return TCL_ERROR; @@ -2844,18 +2475,18 @@ DeleteVirtualEventTable( hPtr = Tcl_FirstHashEntry(&vetPtr->patternTable, &search); for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - psPtr = (PatSeq *) Tcl_GetHashValue(hPtr); + psPtr = Tcl_GetHashValue(hPtr); for ( ; psPtr != NULL; psPtr = nextPtr) { nextPtr = psPtr->nextSeqPtr; - ckfree((char *) psPtr->voPtr); - ckfree((char *) psPtr); + ckfree(psPtr->voPtr); + ckfree(psPtr); } } Tcl_DeleteHashTable(&vetPtr->patternTable); hPtr = Tcl_FirstHashEntry(&vetPtr->nameTable, &search); for ( ; hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) { - ckfree((char *) Tcl_GetHashValue(hPtr)); + ckfree(Tcl_GetHashValue(hPtr)); } Tcl_DeleteHashTable(&vetPtr->nameTable); } @@ -2885,7 +2516,7 @@ CreateVirtualEvent( Tcl_Interp *interp, /* Used for error reporting. */ VirtualEventTable *vetPtr, /* Table in which to augment virtual event. */ char *virtString, /* Name of new virtual event. */ - char *eventString) /* String describing physical event that + const char *eventString) /* String describing physical event that * triggers virtual event. */ { PatSeq *psPtr; @@ -2921,9 +2552,9 @@ CreateVirtualEvent( * Make virtual event own the physical event. */ - poPtr = (PhysicalsOwned *) Tcl_GetHashValue(vhPtr); + poPtr = Tcl_GetHashValue(vhPtr); if (poPtr == NULL) { - poPtr = (PhysicalsOwned *) ckalloc(sizeof(PhysicalsOwned)); + poPtr = ckalloc(sizeof(PhysicalsOwned)); poPtr->numOwned = 0; } else { /* @@ -2938,10 +2569,10 @@ CreateVirtualEvent( return TCL_OK; } } - poPtr = (PhysicalsOwned *) ckrealloc((char *) poPtr, - sizeof(PhysicalsOwned) + poPtr->numOwned * sizeof(PatSeq *)); + poPtr = ckrealloc(poPtr, sizeof(PhysicalsOwned) + + poPtr->numOwned * sizeof(PatSeq *)); } - Tcl_SetHashValue(vhPtr, (ClientData) poPtr); + Tcl_SetHashValue(vhPtr, poPtr); poPtr->patSeqs[poPtr->numOwned] = psPtr; poPtr->numOwned++; @@ -2951,11 +2582,10 @@ CreateVirtualEvent( voPtr = psPtr->voPtr; if (voPtr == NULL) { - voPtr = (VirtualOwners *) ckalloc(sizeof(VirtualOwners)); + voPtr = ckalloc(sizeof(VirtualOwners)); voPtr->numOwners = 0; } else { - voPtr = (VirtualOwners *) ckrealloc((char *) voPtr, - sizeof(VirtualOwners) + voPtr = ckrealloc(voPtr, sizeof(VirtualOwners) + voPtr->numOwners * sizeof(Tcl_HashEntry *)); } psPtr->voPtr = voPtr; @@ -2994,7 +2624,7 @@ DeleteVirtualEvent( VirtualEventTable *vetPtr, /* Table in which to delete event. */ char *virtString, /* String describing event sequence that * triggers binding. */ - char *eventString) /* The event sequence that should be deleted, + const char *eventString) /* The event sequence that should be deleted, * or NULL to delete all event sequences for * the entire virtual event. */ { @@ -3013,7 +2643,7 @@ DeleteVirtualEvent( if (vhPtr == NULL) { return TCL_OK; } - poPtr = (PhysicalsOwned *) Tcl_GetHashValue(vhPtr); + poPtr = Tcl_GetHashValue(vhPtr); eventPSPtr = NULL; if (eventString != NULL) { @@ -3062,7 +2692,7 @@ DeleteVirtualEvent( * from physical->virtual map. */ - PatSeq *prevPtr = (PatSeq *) Tcl_GetHashValue(psPtr->hPtr); + PatSeq *prevPtr = Tcl_GetHashValue(psPtr->hPtr); if (prevPtr == psPtr) { if (psPtr->nextSeqPtr == NULL) { @@ -3082,8 +2712,8 @@ DeleteVirtualEvent( } } } - ckfree((char *) psPtr->voPtr); - ckfree((char *) psPtr); + ckfree(psPtr->voPtr); + ckfree(psPtr); } else { /* * This physical event still triggers some other virtual @@ -3120,7 +2750,7 @@ DeleteVirtualEvent( * itself should be deleted. */ - ckfree((char *) poPtr); + ckfree(poPtr); Tcl_DeleteHashEntry(vhPtr); } return TCL_OK; @@ -3152,7 +2782,7 @@ static int GetVirtualEvent( Tcl_Interp *interp, /* Interpreter for reporting. */ VirtualEventTable *vetPtr, /* Table in which to look for event. */ - char *virtString) /* String describing virtual event. */ + Tcl_Obj *virtName) /* String describing virtual event. */ { Tcl_HashEntry *vhPtr; Tcl_DString ds; @@ -3160,7 +2790,7 @@ GetVirtualEvent( PhysicalsOwned *poPtr; Tk_Uid virtUid; - virtUid = GetVirtualEventUid(interp, virtString); + virtUid = GetVirtualEventUid(interp, Tcl_GetString(virtName)); if (virtUid == NULL) { return TCL_ERROR; } @@ -3172,7 +2802,7 @@ GetVirtualEvent( Tcl_DStringInit(&ds); - poPtr = (PhysicalsOwned *) Tcl_GetHashValue(vhPtr); + poPtr = Tcl_GetHashValue(vhPtr); for (iPhys = 0; iPhys < poPtr->numOwned; iPhys++) { Tcl_DStringSetLength(&ds, 0); GetPatternString(poPtr->patSeqs[iPhys], &ds); @@ -3268,7 +2898,7 @@ HandleEventGenerate( { union {XEvent general; XVirtualEvent virtual;} event; const char *p; - char *name, *windowName; + const char *name, *windowName; int count, flags, synch, i, number, warp; Tcl_QueuePosition pos; Pattern pat; @@ -3276,7 +2906,8 @@ HandleEventGenerate( TkWindow *mainPtr; unsigned long eventMask; Tcl_Obj *userDataObj; - static const char *fieldStrings[] = { + + static const char *const fieldStrings[] = { "-when", "-above", "-borderwidth", "-button", "-count", "-data", "-delta", "-detail", "-focus", "-height", @@ -3332,7 +2963,7 @@ HandleEventGenerate( return TCL_ERROR; } - memset((void *) &event, 0, sizeof(event)); + memset(&event, 0, sizeof(event)); event.general.xany.type = pat.eventType; event.general.xany.serial = NextRequest(Tk_Display(tkwin)); event.general.xany.send_event = False; @@ -3372,6 +3003,11 @@ HandleEventGenerate( event.general.xkey.y_root = -1; } + if (event.general.xany.type == FocusIn + || event.general.xany.type == FocusOut) { + event.general.xany.send_event = GENERATED_FOCUS_EVENT_MAGIC; + } + /* * Process the remaining arguments to fill in additional fields of the * event. @@ -3536,7 +3172,7 @@ HandleEventGenerate( break; case EVENT_KEYSYM: { KeySym keysym; - char *value; + const char *value; value = Tcl_GetString(valuePtr); keysym = TkStringToKeysym(value); @@ -3724,7 +3360,7 @@ HandleEventGenerate( if (Tk_GetPixelsFromObj(interp,tkwin,valuePtr,&number) != TCL_OK) { return TCL_ERROR; } - if (flags & (KEY_BUTTON_MOTION_VIRTUAL|CROSSING)) { + if (flags & KEY_BUTTON_MOTION_CROSSING) { event.general.xkey.x = number; /* @@ -3782,8 +3418,16 @@ HandleEventGenerate( Tcl_GetString(optionPtr), "\" option", NULL); return TCL_ERROR; } + + /* + * Don't generate events for windows that don't exist yet. + */ + + if (!event.general.xany.window) { + goto done; + } + if (userDataObj != NULL) { - XVirtualEvent *vePtr = (XVirtualEvent *) &event; /* * Must be virtual event to set that variable to non-NULL. Now we want @@ -3792,7 +3436,7 @@ HandleEventGenerate( * refcount will be decremented once the event has been processed. */ - vePtr->user_data = userDataObj; + event.virtual.user_data = userDataObj; Tcl_IncrRefCount(userDataObj); } @@ -3815,13 +3459,17 @@ HandleEventGenerate( TkDisplay *dispPtr = TkGetDisplay(event.general.xmotion.display); if (!(dispPtr->flags & TK_DISPLAY_IN_WARP)) { - Tcl_DoWhenIdle(DoWarp, (ClientData) dispPtr); + Tcl_DoWhenIdle(DoWarp, dispPtr); dispPtr->flags |= TK_DISPLAY_IN_WARP; } - dispPtr->warpWindow = event.general.xany.window; - dispPtr->warpX = event.general.xkey.x; - dispPtr->warpY = event.general.xkey.y; + dispPtr->warpWindow = Tk_IdToWindow(Tk_Display(mainWin), + event.general.xmotion.window); + dispPtr->warpMainwin = mainWin; + dispPtr->warpX = event.general.xmotion.x; + dispPtr->warpY = event.general.xmotion.y; } + + done: Tcl_ResetResult(interp); return TCL_OK; } @@ -3833,32 +3481,36 @@ NameToWindow( Tcl_Obj *objPtr, /* Contains name or id string of window. */ Tk_Window *tkwinPtr) /* Filled with token for window. */ { - char *name; + const char *name = Tcl_GetString(objPtr); Tk_Window tkwin; - Window id; - name = Tcl_GetString(objPtr); if (name[0] == '.') { tkwin = Tk_NameToWindow(interp, name, mainWin); if (tkwin == NULL) { return TCL_ERROR; } - *tkwinPtr = tkwin; } else { + Window id; + /* * Check for the winPtr being valid, even if it looks ok to * TkpScanWindowId. [Bug #411307] */ - if ((TkpScanWindowId(NULL, name, &id) != TCL_OK) || - ((*tkwinPtr = Tk_IdToWindow(Tk_Display(mainWin), id)) - == NULL)) { - Tcl_AppendResult(interp, "bad window name/identifier \"", - name, "\"", NULL); - return TCL_ERROR; + if (TkpScanWindowId(NULL, name, &id) != TCL_OK) { + goto badWindow; + } + tkwin = Tk_IdToWindow(Tk_Display(mainWin), id); + if (tkwin == NULL) { + goto badWindow; } } + *tkwinPtr = tkwin; return TCL_OK; + + badWindow: + Tcl_AppendResult(interp, "bad window name/identifier \"",name,"\"", NULL); + return TCL_ERROR; } /* @@ -3876,14 +3528,14 @@ NameToWindow( * *------------------------------------------------------------------------- */ + static void DoWarp( ClientData clientData) { - TkDisplay *dispPtr = (TkDisplay *) clientData; + TkDisplay *dispPtr = clientData; - XWarpPointer(dispPtr->display, (Window) None, (Window) dispPtr->warpWindow, - 0, 0, 0, 0, (int) dispPtr->warpX, (int) dispPtr->warpY); + TkpWarpPointer(dispPtr); XForceScreenSaver(dispPtr->display, ScreenSaverReset); dispPtr->flags &= ~TK_DISPLAY_IN_WARP; } @@ -4058,12 +3710,11 @@ FindSequence( hPtr = Tcl_CreateHashEntry(patternTablePtr, (char *) &key, &isNew); sequenceSize = numPats*sizeof(Pattern); if (!isNew) { - for (psPtr = (PatSeq *) Tcl_GetHashValue(hPtr); psPtr != NULL; + for (psPtr = Tcl_GetHashValue(hPtr); psPtr != NULL; psPtr = psPtr->nextSeqPtr) { if ((numPats == psPtr->numPats) && ((flags & PAT_NEARBY) == (psPtr->flags & PAT_NEARBY)) - && (memcmp((char *) patPtr, (char *) psPtr->pats, - sequenceSize) == 0)) { + && (memcmp(patPtr, psPtr->pats, sequenceSize) == 0)) { goto done; } } @@ -4083,21 +3734,17 @@ FindSequence( return NULL; } - psPtr = (PatSeq *) ckalloc((unsigned) (sizeof(PatSeq) - + (numPats-1)*sizeof(Pattern))); + psPtr = ckalloc(sizeof(PatSeq) + (numPats-1)*sizeof(Pattern)); psPtr->numPats = numPats; - psPtr->eventProc = NULL; - psPtr->freeProc = NULL; - psPtr->clientData = NULL; + psPtr->script = NULL; psPtr->flags = flags; - psPtr->refCount = 0; - psPtr->nextSeqPtr = (PatSeq *) Tcl_GetHashValue(hPtr); + psPtr->nextSeqPtr = Tcl_GetHashValue(hPtr); psPtr->hPtr = hPtr; psPtr->voPtr = NULL; psPtr->nextObjPtr = NULL; Tcl_SetHashValue(hPtr, psPtr); - memcpy((void *) psPtr->pats, (void *) patPtr, sequenceSize); + memcpy(psPtr->pats, patPtr, sequenceSize); done: *maskPtr = eventMask; @@ -4169,10 +3816,8 @@ ParseEventDescription( if (isprint(UCHAR(*p))) { patPtr->detail.keySym = *p; } else { - char buf[64]; - - sprintf(buf, "bad ASCII character 0x%x", (unsigned char) *p); - Tcl_SetResult(interp, buf, TCL_VOLATILE); + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "bad ASCII character 0x%x", UCHAR(*p))); count = 0; goto done; } @@ -4251,7 +3896,7 @@ ParseEventDescription( if (hPtr == NULL) { break; } - modPtr = (ModInfo *) Tcl_GetHashValue(hPtr); + modPtr = Tcl_GetHashValue(hPtr); patPtr->needMods |= modPtr->mask; if (modPtr->flags & MULT_CLICKS) { int i = modPtr->flags & MULT_CLICKS; @@ -4269,7 +3914,7 @@ ParseEventDescription( eventFlags = 0; hPtr = Tcl_FindHashEntry(&eventTable, field); if (hPtr != NULL) { - EventInfo *eiPtr = (EventInfo *) Tcl_GetHashValue(hPtr); + const EventInfo *eiPtr = Tcl_GetHashValue(hPtr); patPtr->eventType = eiPtr->type; eventFlags = flagArray[eiPtr->type]; @@ -4412,8 +4057,8 @@ GetPatternString( Pattern *patPtr; char c, buffer[TCL_INTEGER_SPACE]; int patsLeft, needMods; - ModInfo *modPtr; - EventInfo *eiPtr; + const ModInfo *modPtr; + const EventInfo *eiPtr; /* * The order of the patterns in the sequence is backwards from the order @@ -4458,22 +4103,21 @@ GetPatternString( Tcl_DStringAppend(dsPtr, "<", 1); if ((psPtr->flags & PAT_NEARBY) && (patsLeft > 1) - && (memcmp((char *) patPtr, (char *) (patPtr-1), - sizeof(Pattern)) == 0)) { + && (memcmp(patPtr, patPtr-1, sizeof(Pattern)) == 0)) { patsLeft--; patPtr--; - if ((patsLeft > 1) && (memcmp((char *) patPtr, - (char *) (patPtr-1), sizeof(Pattern)) == 0)) { + if ((patsLeft > 1) && + (memcmp(patPtr, patPtr-1, sizeof(Pattern)) == 0)) { patsLeft--; patPtr--; - if ((patsLeft > 1) && (memcmp((char *) patPtr, - (char *) (patPtr-1), sizeof(Pattern)) == 0)) { - patsLeft--; - patPtr--; - Tcl_DStringAppend(dsPtr, "Quadruple-", 10); - } else { - Tcl_DStringAppend(dsPtr, "Triple-", 7); - } + if ((patsLeft > 1) && + (memcmp(patPtr, patPtr-1, sizeof(Pattern)) == 0)) { + patsLeft--; + patPtr--; + Tcl_DStringAppend(dsPtr, "Quadruple-", 10); + } else { + Tcl_DStringAppend(dsPtr, "Triple-", 7); + } } else { Tcl_DStringAppend(dsPtr, "Double-", 7); } @@ -4501,7 +4145,8 @@ GetPatternString( if (patPtr->detail.clientData != 0) { if ((patPtr->eventType == KeyPress) || (patPtr->eventType == KeyRelease)) { - char *string = TkKeysymToString(patPtr->detail.keySym); + const char *string = TkKeysymToString(patPtr->detail.keySym); + if (string != NULL) { Tcl_DStringAppend(dsPtr, string, -1); } @@ -4516,31 +4161,6 @@ GetPatternString( } /* - *--------------------------------------------------------------------------- - * - * EvalTclBinding -- - * - * The function that is invoked by Tk_BindEvent when a Tcl binding is - * fired. - * - * Results: - * A standard Tcl result code, the result of globally evaluating the - * percent-substitued binding string. - * - * Side effects: - * Normal side effects due to eval. - * - *--------------------------------------------------------------------------- - */ - -static void -FreeTclBinding( - ClientData clientData) -{ - ckfree((char *) clientData); -} - -/* *---------------------------------------------------------------------- * * TkStringToKeysym -- @@ -4559,7 +4179,7 @@ FreeTclBinding( KeySym TkStringToKeysym( - char *name) /* Name of a keysym. */ + const char *name) /* Name of a keysym. */ { #ifdef REDO_KEYSYM_LOOKUP Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&keySymTable, name); @@ -4595,7 +4215,7 @@ TkStringToKeysym( *---------------------------------------------------------------------- */ -char * +const char * TkKeysymToString( KeySym keysym) { @@ -4603,7 +4223,7 @@ TkKeysymToString( Tcl_HashEntry *hPtr = Tcl_FindHashEntry(&nameTable, (char *)keysym); if (hPtr != NULL) { - return (char *) Tcl_GetHashValue(hPtr); + return Tcl_GetHashValue(hPtr); } #endif /* REDO_KEYSYM_LOOKUP */ @@ -4613,41 +4233,6 @@ TkKeysymToString( /* *---------------------------------------------------------------------- * - * TkCopyAndGlobalEval -- - * - * This function makes a copy of a script then calls Tcl_GlobalEval to - * evaluate it. It's used in situations where the execution of a command - * may cause the original command string to be reallocated. - * - * Results: - * Returns the result of evaluating script, including both a standard Tcl - * completion code and a string in the interp's result. - * - * Side effects: - * Any; depends on script. - * - *---------------------------------------------------------------------- - */ - -int -TkCopyAndGlobalEval( - Tcl_Interp *interp, /* Interpreter in which to evaluate script. */ - char *script) /* Script to evaluate. */ -{ - Tcl_DString buffer; - int code; - - Tcl_DStringInit(&buffer); - Tcl_DStringAppend(&buffer, script, -1); - code = Tcl_EvalEx(interp, Tcl_DStringValue(&buffer), - Tcl_DStringLength(&buffer), TCL_EVAL_GLOBAL); - Tcl_DStringFree(&buffer); - return code; -} - -/* - *---------------------------------------------------------------------- - * * TkpGetBindingXEvent -- * * This function returns the XEvent associated with the currently @@ -4669,7 +4254,7 @@ TkpGetBindingXEvent( Tcl_Interp *interp) /* Interpreter. */ { TkWindow *winPtr = (TkWindow *) Tk_MainWindow(interp); - BindingTable *bindPtr = (BindingTable *) winPtr->mainPtr->bindingTable; + BindingTable *bindPtr = winPtr->mainPtr->bindingTable; return &(bindPtr->eventRing[bindPtr->curEvent]); } |