Tk Source Code

Check-in [834b7e14]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Reverting change of return type of function Tk_CreateBinding: 'unsigned long' -> 'Mask'. X11 headers are not using type 'Mask', so I will not use either.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | bug6e8afe516d
Files: files | file ages | folders
SHA3-256:834b7e14fcc43ebed262f19155382fa747b8acbe53b2adfeb7217e62f577b49c
User & Date: gcramer 2019-01-13 12:09:49
Context
2019-01-13
15:48
Superfluous comment removed. check-in: 408bdfa7 user: gcramer tags: bug6e8afe516d
12:09
Reverting change of return type of function Tk_CreateBinding: 'unsigned long' -> 'Mask'. X11 headers are not using type 'Mask', so I will not use either. check-in: 834b7e14 user: gcramer tags: bug6e8afe516d
10:13
(1) Return type of Tk_CreateBinding changed to 'Mask'. (2) Fix of issue with homogeneous equal sequences. New test cases bind-32.12 and bind-32.13. check-in: ec38f729 user: gcramer tags: bug6e8afe516d
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to doc/BindTable.3.

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
\fB#include <tk.h>\fR
.sp
Tk_BindingTable
\fBTk_CreateBindingTable(\fIinterp\fB)\fR
.sp
\fBTk_DeleteBindingTable(\fIbindingTable\fB)\fR
.sp
Mask
\fBTk_CreateBinding(\fIinterp, bindingTable, object, eventString, script, append\fB)\fR
.sp
int
\fBTk_DeleteBinding(\fIinterp, bindingTable, object, eventString\fB)\fR
.sp
const char *
\fBTk_GetBinding(\fIinterp, bindingTable, object, eventString\fB)\fR







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
\fB#include <tk.h>\fR
.sp
Tk_BindingTable
\fBTk_CreateBindingTable(\fIinterp\fB)\fR
.sp
\fBTk_DeleteBindingTable(\fIbindingTable\fB)\fR
.sp
unsigned long
\fBTk_CreateBinding(\fIinterp, bindingTable, object, eventString, script, append\fB)\fR
.sp
int
\fBTk_DeleteBinding(\fIinterp, bindingTable, object, eventString\fB)\fR
.sp
const char *
\fBTk_GetBinding(\fIinterp, bindingTable, object, eventString\fB)\fR

Changes to generic/tk.decls.

159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
	    Tk_Justify justify, int flags, int *widthPtr,
	    int *heightPtr)
}
declare 32 {
    Tk_Window Tk_CoordsToWindow(int rootX, int rootY, Tk_Window tkwin)
}
declare 33 {
    Mask Tk_CreateBinding(Tcl_Interp *interp,
	    Tk_BindingTable bindingTable, ClientData object,
	    const char *eventStr, const char *script, int append)
}
declare 34 {
    Tk_BindingTable Tk_CreateBindingTable(Tcl_Interp *interp)
}
declare 35 {







|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
	    Tk_Justify justify, int flags, int *widthPtr,
	    int *heightPtr)
}
declare 32 {
    Tk_Window Tk_CoordsToWindow(int rootX, int rootY, Tk_Window tkwin)
}
declare 33 {
    unsigned long Tk_CreateBinding(Tcl_Interp *interp,
	    Tk_BindingTable bindingTable, ClientData object,
	    const char *eventStr, const char *script, int append)
}
declare 34 {
    Tk_BindingTable Tk_CreateBindingTable(Tcl_Interp *interp)
}
declare 35 {

Changes to generic/tkBind.c.

144
145
146
147
148
149
150



151
152
153
154
155
156
157
158
159
160
161
...
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
...
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
...
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
...
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
....
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
....
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
....
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
....
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
....
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
....
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
....
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
....
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
    			 * this count considers the detail (keySym or button). */
} Event;

/*
 * We need a structure providing a list of pattern sequences.
 */




struct PatSeq; /* forward declaration */

/* We need this array for bookkeeping the last matching modifier mask per pattern. */
TK_ARRAY_DEFINE(PSModMaskArr, Mask);

typedef struct PSEntry {
    TK_DLIST_LINKS(PSEntry);	/* Makes this struct a double linked list; must be first entry. */
    Window window;		/* Window of last match. */
    struct PatSeq* psPtr;	/* Pointer to pattern sequence. */
    PSModMaskArr *lastModMaskArr;
    				/* Last matching modifier mask per pattern (except last pattern).
................................................................................
TK_ARRAY_DEFINE(PromArr, PSList);

typedef struct Tk_BindingTable_ {
    Event eventInfo[TK_LASTEVENT];
    				/* Containing the most recent event for every event type. */
    PromArr *promArr;		/* Contains the promoted pattern sequences. */
    Event *curEvent;		/* Pointing to most recent event. */
    Mask curModMask;		/* Containing the current modifier mask. */
    LookupTables lookupTables;	/* Containing hash tables for fast lookup. */
    Tcl_HashTable objectTable;	/* Used to map from an object to a list of patterns associated with
    				 * that object. Keys are ClientData, values are (PatSeq *). */
    Tcl_Interp *interp;		/* Interpreter in which commands are executed. */
} BindingTable;

/*
................................................................................
 * For technical reasons we do not use 'union Detail', although this would
 * be possible, instead 'info' and 'name' are both included.
 */

typedef struct {
    unsigned eventType;		/* Type of X event, e.g. ButtonPress. */
    unsigned count;		/* Multi-event count, e.g. double-clicks, triple-clicks, etc. */
    Mask modMask;		/* Mask of modifiers that must be present (zero means no modifiers
    				 * are required). */
    Info info;			/* Additional information that must match event. Normally this is zero,
    				 * meaning no additional information must match. For KeyPress and
				 * KeyRelease events, it may be specified to select a particular
				 * keystroke (zero means any keystrokes). For button events, specifies
				 * a particular button (zero means any buttons are OK). */
    Tk_Uid name;		/* Specifies the Tk_Uid of the virtual event name. NULL if not a
................................................................................
static int		DeleteVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr,
			    char *virtString, const char *eventString);
static void		DeleteVirtualEventTable(VirtualEventTable *vetPtr);
static void		ExpandPercents(TkWindow *winPtr, const char *before, Event *eventPtr,
			    unsigned scriptCount, Tcl_DString *dsPtr);
static PatSeq *		FindSequence(Tcl_Interp *interp, LookupTables *lookupTables,
			    ClientData object, const char *eventString, bool create,
			    bool allowVirtual, Mask *maskPtr);
static void		GetAllVirtualEvents(Tcl_Interp *interp, VirtualEventTable *vetPtr);
static const char *	GetField(const char *p, char *copy, unsigned size);
static Tcl_Obj *	GetPatternObj(const PatSeq *psPtr);
static int		GetVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr,
			    Tcl_Obj *virtName);
static Tk_Uid		GetVirtualEventUid(Tcl_Interp *interp, char *virtString);
static int		HandleEventGenerate(Tcl_Interp *interp, Tk_Window main,
................................................................................
static void		InitVirtualEventTable(VirtualEventTable *vetPtr);
static PatSeq *		MatchPatterns(TkDisplay *dispPtr, Tk_BindingTable bindPtr, PSList *psList,
			    PSList *psSuccList, unsigned patIndex, const Event *eventPtr,
			    ClientData object, PatSeq **physPtrPtr);
static bool		NameToWindow(Tcl_Interp *interp, Tk_Window main,
			    Tcl_Obj *objPtr, Tk_Window *tkwinPtr);
static unsigned		ParseEventDescription(Tcl_Interp *interp, const char **eventStringPtr,
			    TkPattern *patPtr, Mask *eventMaskPtr);
static void		DoWarp(ClientData clientData);
static PSList *		GetLookupForEvent(LookupTables* lookupPtr, const Event *eventPtr,
			    Tcl_Obj *object, bool onlyConsiderDetailedEvents);
static void		ClearLookupTable(LookupTables *lookupTables, ClientData object);
static void		ClearPromotionLists(Tk_BindingTable bindPtr, ClientData object);
static PSEntry *	MakeListEntry(PSList *pool, PatSeq *psPtr, bool needModMasks);
static void		RemovePatSeqFromLookup(LookupTables *lookupTables, PatSeq *psPtr);
................................................................................
static bool IsOdd(int n) { return n & 1; }

static bool TestNearbyTime(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_MS; }
static bool TestNearbyCoords(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_PIXELS; }

static bool
IsSubsetOf(
    Mask lhsMask,	/* this is a subset */
    Mask rhsMask)	/* of this bit field? */
{
    return (lhsMask & rhsMask) == lhsMask;
}

static const char*
SkipSpaces(
    const char* s)
................................................................................
 *	An existing binding on the same event sequence may be replaced. The
 *	new binding may cause future calls to Tk_BindEvent to behave
 *	differently than they did previously.
 *
 *--------------------------------------------------------------
 */

Mask
Tk_CreateBinding(
    Tcl_Interp *interp,		/* Used for error reporting. */
    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 *script,		/* Contains Tcl script to execute when binding triggers. */
    bool append)		/* False means replace any existing binding for eventString;
    				 * True means append to that binding. If the existing binding is
				 * for a callback function and not a Tcl command string, the
				 * existing binding will always be replaced. */
{
    PatSeq *psPtr;
    Mask eventMask;
    char *oldStr;
    char *newStr;

    assert(bindPtr);
    assert(object);
    assert(eventString);
    assert(script);
................................................................................
}

/* helper function */
static bool
CompareModMasks(
    const PSModMaskArr *fstModMaskArr,
    const PSModMaskArr *sndModMaskArr,
    Mask fstModMask,
    Mask sndModMask)
{
    int fstCount = 0;
    int sndCount = 0;
    int i;

    if (PSModMaskArr_IsEmpty(fstModMaskArr)) {
	if (!PSModMaskArr_IsEmpty(sndModMaskArr)) {
................................................................................
		++fstCount;
	    }
	}
    } else {
	assert(PSModMaskArr_Size(fstModMaskArr) == PSModMaskArr_Size(sndModMaskArr));

	for (i = PSModMaskArr_Size(fstModMaskArr) - 1; i >= 0; --i) {
	    Mask fstModMask = *PSModMaskArr_Get(fstModMaskArr, i);
	    Mask sndModMask = *PSModMaskArr_Get(sndModMaskArr, i);

	    if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; }
	    if (IsSubsetOf(sndModMask, fstModMask)) { ++fstCount; }
	}
    }

    if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; }
................................................................................
    				 * Output: the associated physical event for the best matching virtual
				 * event; NULL when we match physical events. */
{
    Window window;
    PSEntry *psEntry;
    PatSeq *bestPtr;
    PatSeq *bestPhysPtr;
    Mask bestModMask;
    const PSModMaskArr *bestModMaskArr;

    assert(dispPtr);
    assert(bindPtr);
    assert(curEvent);

    if (!psList) {
................................................................................
			&& (!patPtr->name || patPtr->name == curEvent->detail.name)
			&& (!patPtr->info || patPtr->info == curEvent->detail.info)) {
		    /*
		     * Resolve the modifier mask for Alt and Mod keys. Unfortunately this
		     * cannot be done in ParseEventDescription, otherwise this function would
		     * be the better place.
		     */
		    Mask modMask = ResolveModifiers(dispPtr, patPtr->modMask);
		    Mask curModMask = ResolveModifiers(dispPtr, bindPtr->curModMask);

		    psEntry->expired = true; /* remove it from promotion list */

		    if ((modMask & ~curModMask) == 0) {
			unsigned count = patPtr->info ? curEvent->countDetailed : curEvent->countAny;

			if (patIndex < PSModMaskArr_Size(psEntry->lastModMaskArr)) {
................................................................................
    const char *name;
    const char *windowName;
    Tcl_QueuePosition pos;
    TkPattern pat;
    Tk_Window tkwin;
    Tk_Window tkwin2;
    TkWindow *mainPtr;
    Mask eventMask;
    Tcl_Obj *userDataObj;
    bool synch;
    bool warp;
    unsigned count;
    unsigned flags;
    int number;
    unsigned i;
................................................................................
    				 * associated. For virtual event table, NULL. */
    const char *eventString,	/* String description of pattern to match on. See user
    				 * documentation for details. */
    bool create,		/* False means don't create the entry if it doesn't already exist.
    				 * True means create. */
    bool allowVirtual,		/* False means that virtual events are not allowed in the sequence.
    				 * True otherwise. */
    Mask *maskPtr)		/* *maskPtr is filled in with the event types on which this
    				 * pattern sequence depends. */
{
    unsigned patsBufSize = 1;
    unsigned numPats;
    unsigned totalCount = 0;
    bool virtualFound = false;
    const char *p = eventString;
    TkPattern *patPtr;
    PatSeq *psPtr;
    Tcl_HashEntry *hPtr;
    bool isNew;
    unsigned count;
    unsigned maxCount = 0;
    Mask eventMask = 0;
    Mask modMask = 0;
    PatternTableKey key;

    assert(lookupTables);
    assert(eventString);

    psPtr = ckalloc(PATSEQ_MEMSIZE(patsBufSize));

................................................................................

static unsigned
ParseEventDescription(
    Tcl_Interp *interp,		/* For error messages. */
    const char **eventStringPtr,/* On input, holds a pointer to start of event string. On exit,
    				 * gets pointer to rest of string after parsed event. */
    TkPattern *patPtr,		/* Filled with the pattern parsed from the event string. */
    Mask *eventMaskPtr)		/* Filled with event mask of matched event. */
{
    const char *p;
    Mask eventMask = 0;
    unsigned count = 1;

    assert(eventStringPtr);
    assert(patPtr);
    assert(eventMaskPtr);

    p = *eventStringPtr;







>
>
>



|







 







|







 







|







 







|







 







|







 







|
|







 







|












|







 







|
|







 







|
|







 







|







 







|
|







 







|







 







|













|
|







 







|


|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
...
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
...
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
...
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
....
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
....
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
....
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
....
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
....
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
....
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
....
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
....
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
    			 * this count considers the detail (keySym or button). */
} Event;

/*
 * We need a structure providing a list of pattern sequences.
 */

typedef unsigned EventMask;
typedef unsigned long ModMask;

struct PatSeq; /* forward declaration */

/* We need this array for bookkeeping the last matching modifier mask per pattern. */
TK_ARRAY_DEFINE(PSModMaskArr, ModMask);

typedef struct PSEntry {
    TK_DLIST_LINKS(PSEntry);	/* Makes this struct a double linked list; must be first entry. */
    Window window;		/* Window of last match. */
    struct PatSeq* psPtr;	/* Pointer to pattern sequence. */
    PSModMaskArr *lastModMaskArr;
    				/* Last matching modifier mask per pattern (except last pattern).
................................................................................
TK_ARRAY_DEFINE(PromArr, PSList);

typedef struct Tk_BindingTable_ {
    Event eventInfo[TK_LASTEVENT];
    				/* Containing the most recent event for every event type. */
    PromArr *promArr;		/* Contains the promoted pattern sequences. */
    Event *curEvent;		/* Pointing to most recent event. */
    ModMask curModMask;		/* Containing the current modifier mask. */
    LookupTables lookupTables;	/* Containing hash tables for fast lookup. */
    Tcl_HashTable objectTable;	/* Used to map from an object to a list of patterns associated with
    				 * that object. Keys are ClientData, values are (PatSeq *). */
    Tcl_Interp *interp;		/* Interpreter in which commands are executed. */
} BindingTable;

/*
................................................................................
 * For technical reasons we do not use 'union Detail', although this would
 * be possible, instead 'info' and 'name' are both included.
 */

typedef struct {
    unsigned eventType;		/* Type of X event, e.g. ButtonPress. */
    unsigned count;		/* Multi-event count, e.g. double-clicks, triple-clicks, etc. */
    ModMask modMask;		/* Mask of modifiers that must be present (zero means no modifiers
    				 * are required). */
    Info info;			/* Additional information that must match event. Normally this is zero,
    				 * meaning no additional information must match. For KeyPress and
				 * KeyRelease events, it may be specified to select a particular
				 * keystroke (zero means any keystrokes). For button events, specifies
				 * a particular button (zero means any buttons are OK). */
    Tk_Uid name;		/* Specifies the Tk_Uid of the virtual event name. NULL if not a
................................................................................
static int		DeleteVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr,
			    char *virtString, const char *eventString);
static void		DeleteVirtualEventTable(VirtualEventTable *vetPtr);
static void		ExpandPercents(TkWindow *winPtr, const char *before, Event *eventPtr,
			    unsigned scriptCount, Tcl_DString *dsPtr);
static PatSeq *		FindSequence(Tcl_Interp *interp, LookupTables *lookupTables,
			    ClientData object, const char *eventString, bool create,
			    bool allowVirtual, EventMask *maskPtr);
static void		GetAllVirtualEvents(Tcl_Interp *interp, VirtualEventTable *vetPtr);
static const char *	GetField(const char *p, char *copy, unsigned size);
static Tcl_Obj *	GetPatternObj(const PatSeq *psPtr);
static int		GetVirtualEvent(Tcl_Interp *interp, VirtualEventTable *vetPtr,
			    Tcl_Obj *virtName);
static Tk_Uid		GetVirtualEventUid(Tcl_Interp *interp, char *virtString);
static int		HandleEventGenerate(Tcl_Interp *interp, Tk_Window main,
................................................................................
static void		InitVirtualEventTable(VirtualEventTable *vetPtr);
static PatSeq *		MatchPatterns(TkDisplay *dispPtr, Tk_BindingTable bindPtr, PSList *psList,
			    PSList *psSuccList, unsigned patIndex, const Event *eventPtr,
			    ClientData object, PatSeq **physPtrPtr);
static bool		NameToWindow(Tcl_Interp *interp, Tk_Window main,
			    Tcl_Obj *objPtr, Tk_Window *tkwinPtr);
static unsigned		ParseEventDescription(Tcl_Interp *interp, const char **eventStringPtr,
			    TkPattern *patPtr, EventMask *eventMaskPtr);
static void		DoWarp(ClientData clientData);
static PSList *		GetLookupForEvent(LookupTables* lookupPtr, const Event *eventPtr,
			    Tcl_Obj *object, bool onlyConsiderDetailedEvents);
static void		ClearLookupTable(LookupTables *lookupTables, ClientData object);
static void		ClearPromotionLists(Tk_BindingTable bindPtr, ClientData object);
static PSEntry *	MakeListEntry(PSList *pool, PatSeq *psPtr, bool needModMasks);
static void		RemovePatSeqFromLookup(LookupTables *lookupTables, PatSeq *psPtr);
................................................................................
static bool IsOdd(int n) { return n & 1; }

static bool TestNearbyTime(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_MS; }
static bool TestNearbyCoords(int lhs, int rhs) { return Abs(lhs - rhs) <= NEARBY_PIXELS; }

static bool
IsSubsetOf(
    ModMask lhsMask,	/* this is a subset */
    ModMask rhsMask)	/* of this bit field? */
{
    return (lhsMask & rhsMask) == lhsMask;
}

static const char*
SkipSpaces(
    const char* s)
................................................................................
 *	An existing binding on the same event sequence may be replaced. The
 *	new binding may cause future calls to Tk_BindEvent to behave
 *	differently than they did previously.
 *
 *--------------------------------------------------------------
 */

unsigned long
Tk_CreateBinding(
    Tcl_Interp *interp,		/* Used for error reporting. */
    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 *script,		/* Contains Tcl script to execute when binding triggers. */
    bool append)		/* False means replace any existing binding for eventString;
    				 * True means append to that binding. If the existing binding is
				 * for a callback function and not a Tcl command string, the
				 * existing binding will always be replaced. */
{
    PatSeq *psPtr;
    EventMask eventMask;
    char *oldStr;
    char *newStr;

    assert(bindPtr);
    assert(object);
    assert(eventString);
    assert(script);
................................................................................
}

/* helper function */
static bool
CompareModMasks(
    const PSModMaskArr *fstModMaskArr,
    const PSModMaskArr *sndModMaskArr,
    ModMask fstModMask,
    ModMask sndModMask)
{
    int fstCount = 0;
    int sndCount = 0;
    int i;

    if (PSModMaskArr_IsEmpty(fstModMaskArr)) {
	if (!PSModMaskArr_IsEmpty(sndModMaskArr)) {
................................................................................
		++fstCount;
	    }
	}
    } else {
	assert(PSModMaskArr_Size(fstModMaskArr) == PSModMaskArr_Size(sndModMaskArr));

	for (i = PSModMaskArr_Size(fstModMaskArr) - 1; i >= 0; --i) {
	    ModMask fstModMask = *PSModMaskArr_Get(fstModMaskArr, i);
	    ModMask sndModMask = *PSModMaskArr_Get(sndModMaskArr, i);

	    if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; }
	    if (IsSubsetOf(sndModMask, fstModMask)) { ++fstCount; }
	}
    }

    if (IsSubsetOf(fstModMask, sndModMask)) { ++sndCount; }
................................................................................
    				 * Output: the associated physical event for the best matching virtual
				 * event; NULL when we match physical events. */
{
    Window window;
    PSEntry *psEntry;
    PatSeq *bestPtr;
    PatSeq *bestPhysPtr;
    ModMask bestModMask;
    const PSModMaskArr *bestModMaskArr;

    assert(dispPtr);
    assert(bindPtr);
    assert(curEvent);

    if (!psList) {
................................................................................
			&& (!patPtr->name || patPtr->name == curEvent->detail.name)
			&& (!patPtr->info || patPtr->info == curEvent->detail.info)) {
		    /*
		     * Resolve the modifier mask for Alt and Mod keys. Unfortunately this
		     * cannot be done in ParseEventDescription, otherwise this function would
		     * be the better place.
		     */
		    ModMask modMask = ResolveModifiers(dispPtr, patPtr->modMask);
		    ModMask curModMask = ResolveModifiers(dispPtr, bindPtr->curModMask);

		    psEntry->expired = true; /* remove it from promotion list */

		    if ((modMask & ~curModMask) == 0) {
			unsigned count = patPtr->info ? curEvent->countDetailed : curEvent->countAny;

			if (patIndex < PSModMaskArr_Size(psEntry->lastModMaskArr)) {
................................................................................
    const char *name;
    const char *windowName;
    Tcl_QueuePosition pos;
    TkPattern pat;
    Tk_Window tkwin;
    Tk_Window tkwin2;
    TkWindow *mainPtr;
    EventMask eventMask;
    Tcl_Obj *userDataObj;
    bool synch;
    bool warp;
    unsigned count;
    unsigned flags;
    int number;
    unsigned i;
................................................................................
    				 * associated. For virtual event table, NULL. */
    const char *eventString,	/* String description of pattern to match on. See user
    				 * documentation for details. */
    bool create,		/* False means don't create the entry if it doesn't already exist.
    				 * True means create. */
    bool allowVirtual,		/* False means that virtual events are not allowed in the sequence.
    				 * True otherwise. */
    EventMask *maskPtr)		/* *maskPtr is filled in with the event types on which this
    				 * pattern sequence depends. */
{
    unsigned patsBufSize = 1;
    unsigned numPats;
    unsigned totalCount = 0;
    bool virtualFound = false;
    const char *p = eventString;
    TkPattern *patPtr;
    PatSeq *psPtr;
    Tcl_HashEntry *hPtr;
    bool isNew;
    unsigned count;
    unsigned maxCount = 0;
    EventMask eventMask = 0;
    ModMask modMask = 0;
    PatternTableKey key;

    assert(lookupTables);
    assert(eventString);

    psPtr = ckalloc(PATSEQ_MEMSIZE(patsBufSize));

................................................................................

static unsigned
ParseEventDescription(
    Tcl_Interp *interp,		/* For error messages. */
    const char **eventStringPtr,/* On input, holds a pointer to start of event string. On exit,
    				 * gets pointer to rest of string after parsed event. */
    TkPattern *patPtr,		/* Filled with the pattern parsed from the event string. */
    EventMask *eventMaskPtr)	/* Filled with event mask of matched event. */
{
    const char *p;
    EventMask eventMask = 0;
    unsigned count = 1;

    assert(eventStringPtr);
    assert(patPtr);
    assert(eventMaskPtr);

    p = *eventStringPtr;

Changes to generic/tkCanvas.c.

973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
....
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
....
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757

	if (canvasPtr->bindingTable == NULL) {
	    canvasPtr->bindingTable = Tk_CreateBindingTable(interp);
	}

	if (objc == 5) {
	    int append = 0;
	    Mask mask;
	    const char *argv4 = Tcl_GetString(objv[4]);

	    if (argv4[0] == 0) {
		result = Tk_DeleteBinding(interp, canvasPtr->bindingTable,
			object, Tcl_GetString(objv[3]));
		goto done;
	    }
................................................................................
	    }
	    mask = Tk_CreateBinding(interp, canvasPtr->bindingTable,
		    object, Tcl_GetString(objv[3]), argv4, append);
	    if (mask == 0) {
		result = TCL_ERROR;
		goto done;
	    }
	    if (mask & (Mask) ~(ButtonMotionMask|Button1MotionMask
		    |Button2MotionMask|Button3MotionMask|Button4MotionMask
		    |Button5MotionMask|ButtonPressMask|ButtonReleaseMask
		    |EnterWindowMask|LeaveWindowMask|KeyPressMask
		    |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {
		Tk_DeleteBinding(interp, canvasPtr->bindingTable,
			object, Tcl_GetString(objv[3]));
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
................................................................................

static void
CanvasBindProc(
    ClientData clientData,	/* Pointer to canvas structure. */
    XEvent *eventPtr)		/* Pointer to X event that just happened. */
{
    TkCanvas *canvasPtr = clientData;
    Mask mask;

    Tcl_Preserve(canvasPtr);

    /*
     * This code below keeps track of the current modifier state in
     * canvasPtr>state. This information is used to defer repicks of the
     * current item while buttons are down.







|







 







|







 







|







973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
....
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
....
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757

	if (canvasPtr->bindingTable == NULL) {
	    canvasPtr->bindingTable = Tk_CreateBindingTable(interp);
	}

	if (objc == 5) {
	    int append = 0;
	    unsigned long mask;
	    const char *argv4 = Tcl_GetString(objv[4]);

	    if (argv4[0] == 0) {
		result = Tk_DeleteBinding(interp, canvasPtr->bindingTable,
			object, Tcl_GetString(objv[3]));
		goto done;
	    }
................................................................................
	    }
	    mask = Tk_CreateBinding(interp, canvasPtr->bindingTable,
		    object, Tcl_GetString(objv[3]), argv4, append);
	    if (mask == 0) {
		result = TCL_ERROR;
		goto done;
	    }
	    if (mask & (unsigned long) ~(ButtonMotionMask|Button1MotionMask
		    |Button2MotionMask|Button3MotionMask|Button4MotionMask
		    |Button5MotionMask|ButtonPressMask|ButtonReleaseMask
		    |EnterWindowMask|LeaveWindowMask|KeyPressMask
		    |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {
		Tk_DeleteBinding(interp, canvasPtr->bindingTable,
			object, Tcl_GetString(objv[3]));
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
................................................................................

static void
CanvasBindProc(
    ClientData clientData,	/* Pointer to canvas structure. */
    XEvent *eventPtr)		/* Pointer to X event that just happened. */
{
    TkCanvas *canvasPtr = clientData;
    unsigned long mask;

    Tcl_Preserve(canvasPtr);

    /*
     * This code below keeps track of the current modifier state in
     * canvasPtr>state. This information is used to defer repicks of the
     * current item while buttons are down.

Changes to generic/tkCmds.c.

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
     * there are three arguments, the command is querying a binding. If there
     * are only two arguments, the command is querying all the bindings for
     * the given tag/window.
     */

    if (objc == 4) {
	int append = 0;
	Mask mask;
	const char *sequence = Tcl_GetString(objv[2]);
	const char *script = Tcl_GetString(objv[3]);

	/*
	 * If the script is null, just delete the binding.
	 */








|







196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
     * there are three arguments, the command is querying a binding. If there
     * are only two arguments, the command is querying all the bindings for
     * the given tag/window.
     */

    if (objc == 4) {
	int append = 0;
	unsigned long mask;
	const char *sequence = Tcl_GetString(objv[2]);
	const char *script = Tcl_GetString(objv[3]);

	/*
	 * If the script is null, just delete the binding.
	 */

Changes to generic/tkDecls.h.

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
				int numChars, int wrapLength,
				Tk_Justify justify, int flags, int *widthPtr,
				int *heightPtr);
/* 32 */
EXTERN Tk_Window	Tk_CoordsToWindow(int rootX, int rootY,
				Tk_Window tkwin);
/* 33 */
EXTERN Mask		Tk_CreateBinding(Tcl_Interp *interp,
				Tk_BindingTable bindingTable,
				ClientData object, const char *eventStr,
				const char *script, int append);
/* 34 */
EXTERN Tk_BindingTable	Tk_CreateBindingTable(Tcl_Interp *interp);
/* 35 */
EXTERN Tk_ErrorHandler	Tk_CreateErrorHandler(Display *display, int errNum,
................................................................................
    int (*tk_ClipboardClear) (Tcl_Interp *interp, Tk_Window tkwin); /* 26 */
    int (*tk_ConfigureInfo) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, char *widgRec, const char *argvName, int flags); /* 27 */
    int (*tk_ConfigureValue) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, char *widgRec, const char *argvName, int flags); /* 28 */
    int (*tk_ConfigureWidget) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, int argc, CONST84 char **argv, char *widgRec, int flags); /* 29 */
    void (*tk_ConfigureWindow) (Tk_Window tkwin, unsigned int valueMask, XWindowChanges *valuePtr); /* 30 */
    Tk_TextLayout (*tk_ComputeTextLayout) (Tk_Font font, const char *str, int numChars, int wrapLength, Tk_Justify justify, int flags, int *widthPtr, int *heightPtr); /* 31 */
    Tk_Window (*tk_CoordsToWindow) (int rootX, int rootY, Tk_Window tkwin); /* 32 */
    Mask (*tk_CreateBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr, const char *script, int append); /* 33 */
    Tk_BindingTable (*tk_CreateBindingTable) (Tcl_Interp *interp); /* 34 */
    Tk_ErrorHandler (*tk_CreateErrorHandler) (Display *display, int errNum, int request, int minorCode, Tk_ErrorProc *errorProc, ClientData clientData); /* 35 */
    void (*tk_CreateEventHandler) (Tk_Window token, unsigned long mask, Tk_EventProc *proc, ClientData clientData); /* 36 */
    void (*tk_CreateGenericHandler) (Tk_GenericProc *proc, ClientData clientData); /* 37 */
    void (*tk_CreateImageType) (const Tk_ImageType *typePtr); /* 38 */
    void (*tk_CreateItemType) (Tk_ItemType *typePtr); /* 39 */
    void (*tk_CreatePhotoImageFormat) (const Tk_PhotoImageFormat *formatPtr); /* 40 */







|







 







|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
				int numChars, int wrapLength,
				Tk_Justify justify, int flags, int *widthPtr,
				int *heightPtr);
/* 32 */
EXTERN Tk_Window	Tk_CoordsToWindow(int rootX, int rootY,
				Tk_Window tkwin);
/* 33 */
EXTERN unsigned long	Tk_CreateBinding(Tcl_Interp *interp,
				Tk_BindingTable bindingTable,
				ClientData object, const char *eventStr,
				const char *script, int append);
/* 34 */
EXTERN Tk_BindingTable	Tk_CreateBindingTable(Tcl_Interp *interp);
/* 35 */
EXTERN Tk_ErrorHandler	Tk_CreateErrorHandler(Display *display, int errNum,
................................................................................
    int (*tk_ClipboardClear) (Tcl_Interp *interp, Tk_Window tkwin); /* 26 */
    int (*tk_ConfigureInfo) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, char *widgRec, const char *argvName, int flags); /* 27 */
    int (*tk_ConfigureValue) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, char *widgRec, const char *argvName, int flags); /* 28 */
    int (*tk_ConfigureWidget) (Tcl_Interp *interp, Tk_Window tkwin, const Tk_ConfigSpec *specs, int argc, CONST84 char **argv, char *widgRec, int flags); /* 29 */
    void (*tk_ConfigureWindow) (Tk_Window tkwin, unsigned int valueMask, XWindowChanges *valuePtr); /* 30 */
    Tk_TextLayout (*tk_ComputeTextLayout) (Tk_Font font, const char *str, int numChars, int wrapLength, Tk_Justify justify, int flags, int *widthPtr, int *heightPtr); /* 31 */
    Tk_Window (*tk_CoordsToWindow) (int rootX, int rootY, Tk_Window tkwin); /* 32 */
    unsigned long (*tk_CreateBinding) (Tcl_Interp *interp, Tk_BindingTable bindingTable, ClientData object, const char *eventStr, const char *script, int append); /* 33 */
    Tk_BindingTable (*tk_CreateBindingTable) (Tcl_Interp *interp); /* 34 */
    Tk_ErrorHandler (*tk_CreateErrorHandler) (Display *display, int errNum, int request, int minorCode, Tk_ErrorProc *errorProc, ClientData clientData); /* 35 */
    void (*tk_CreateEventHandler) (Tk_Window token, unsigned long mask, Tk_EventProc *proc, ClientData clientData); /* 36 */
    void (*tk_CreateGenericHandler) (Tk_GenericProc *proc, ClientData clientData); /* 37 */
    void (*tk_CreateImageType) (const Tk_ImageType *typePtr); /* 38 */
    void (*tk_CreateItemType) (Tk_ItemType *typePtr); /* 39 */
    void (*tk_CreatePhotoImageFormat) (const Tk_PhotoImageFormat *formatPtr); /* 40 */

Changes to generic/tkTextTag.c.

269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
....
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
	if (textPtr->sharedTextPtr->bindingTable == NULL) {
	    textPtr->sharedTextPtr->bindingTable =
		    Tk_CreateBindingTable(interp);
	}

	if (objc == 6) {
	    int append = 0;
	    Mask mask;
	    const char *fifth = Tcl_GetString(objv[5]);

	    if (fifth[0] == 0) {
		return Tk_DeleteBinding(interp,
			textPtr->sharedTextPtr->bindingTable,
			(ClientData) tagPtr->name, Tcl_GetString(objv[4]));
	    }
................................................................................
	    mask = Tk_CreateBinding(interp,
		    textPtr->sharedTextPtr->bindingTable,
		    (ClientData) tagPtr->name, Tcl_GetString(objv[4]), fifth,
		    append);
	    if (mask == 0) {
		return TCL_ERROR;
	    }
	    if (mask & (Mask) ~(ButtonMotionMask|Button1MotionMask
		    |Button2MotionMask|Button3MotionMask|Button4MotionMask
		    |Button5MotionMask|ButtonPressMask|ButtonReleaseMask
		    |EnterWindowMask|LeaveWindowMask|KeyPressMask
		    |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {
		Tk_DeleteBinding(interp, textPtr->sharedTextPtr->bindingTable,
			(ClientData) tagPtr->name, Tcl_GetString(objv[4]));
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
................................................................................
     * a button is pressed and refusing to pick a new current character while
     * a button is pressed.
     */

    if (eventPtr->type == ButtonPress) {
	textPtr->flags |= BUTTON_DOWN;
    } else if (eventPtr->type == ButtonRelease) {
	Mask mask;

	switch (eventPtr->xbutton.button) {
	case Button1:
	    mask = Button1Mask;
	    break;
	case Button2:
	    mask = Button2Mask;







|







 







|







 







|







269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
....
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
	if (textPtr->sharedTextPtr->bindingTable == NULL) {
	    textPtr->sharedTextPtr->bindingTable =
		    Tk_CreateBindingTable(interp);
	}

	if (objc == 6) {
	    int append = 0;
	    unsigned long mask;
	    const char *fifth = Tcl_GetString(objv[5]);

	    if (fifth[0] == 0) {
		return Tk_DeleteBinding(interp,
			textPtr->sharedTextPtr->bindingTable,
			(ClientData) tagPtr->name, Tcl_GetString(objv[4]));
	    }
................................................................................
	    mask = Tk_CreateBinding(interp,
		    textPtr->sharedTextPtr->bindingTable,
		    (ClientData) tagPtr->name, Tcl_GetString(objv[4]), fifth,
		    append);
	    if (mask == 0) {
		return TCL_ERROR;
	    }
	    if (mask & (unsigned long) ~(ButtonMotionMask|Button1MotionMask
		    |Button2MotionMask|Button3MotionMask|Button4MotionMask
		    |Button5MotionMask|ButtonPressMask|ButtonReleaseMask
		    |EnterWindowMask|LeaveWindowMask|KeyPressMask
		    |KeyReleaseMask|PointerMotionMask|VirtualEventMask)) {
		Tk_DeleteBinding(interp, textPtr->sharedTextPtr->bindingTable,
			(ClientData) tagPtr->name, Tcl_GetString(objv[4]));
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
................................................................................
     * a button is pressed and refusing to pick a new current character while
     * a button is pressed.
     */

    if (eventPtr->type == ButtonPress) {
	textPtr->flags |= BUTTON_DOWN;
    } else if (eventPtr->type == ButtonRelease) {
	unsigned long mask;

	switch (eventPtr->xbutton.button) {
	case Button1:
	    mask = Button1Mask;
	    break;
	case Button2:
	    mask = Button2Mask;