Tk Source Code

Check-in [18c2efa9]
Login

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

Overview
Comment:64 bit problem finally solved, I hope.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | bug6e8afe516d
Files: files | file ages | folders
SHA3-256:18c2efa903d19b800fed3700f03c7f90c17fbfb15fc7fd7932f9d00cba80febd
User & Date: gcramer 2018-12-07 20:15:43
References
2018-12-07
21:54 Ticket [6e8afe51] Severe bugs in binding (tkBind.c) status still Open with 3 other changes artifact: b8fcb1b2 user: fvogel
Context
2018-12-09
10:51
Try to fix failing test case bind-15.23 (Windoze only). check-in: 50ebf7d5 user: gcramer tags: bug6e8afe516d
2018-12-07
20:15
64 bit problem finally solved, I hope. check-in: 18c2efa9 user: gcramer tags: bug6e8afe516d
2018-12-04
20:37
Merge 8.6 check-in: 93e35597 user: jan.nijtmans tags: bug6e8afe516d
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tkBind.c.

253
254
255
256
257
258
259

260
261
262
263
264
265
266
267
268
269
...
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804














805
806
807
808
809
810
811
...
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
....
1007
1008
1009
1010
1011
1012
1013

1014
1015
1016
1017
1018
1019
1020
....
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
....
1248
1249
1250
1251
1252
1253
1254

1255
1256
1257
1258
1259
1260
1261
....
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
....
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
....
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
....
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
....
4578
4579
4580
4581
4582
4583
4584

4585
4586
4587
4588
4589
4590
4591
....
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615

4616
4617
4618
4619
4620
4621
4622
 *
 * 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 long modStateMask;	/* Mask of modifiers that must be present (zero means no modifiers
    				 * are required). */
    unsigned count;		/* Multi-event count, e.g. double-clicks, triple-clicks, etc. */
    unsigned long 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
    				 * virtual event. */
................................................................................
    assert(index < psPtr->numPats);

    return psPtr->pats[index].count;
}

static bool
MatchEventNearby(
    const XEvent *lhs,
    const XEvent *rhs)
{
    assert(lhs);
    assert(rhs);
    assert(lhs->type == ButtonPress || lhs->type == ButtonRelease || lhs->type == MotionNotify);
    assert(lhs->type == rhs->type);

    /* assert: lhs->xbutton.time <= rhs->xbutton.time */

    return rhs->xbutton.time - lhs->xbutton.time <= NEARBY_MS
	    && Abs(rhs->xbutton.x_root - lhs->xbutton.x_root) <= NEARBY_PIXELS
	    && Abs(rhs->xbutton.y_root - lhs->xbutton.y_root) <= NEARBY_PIXELS;
}















static void
FreePatSeq(
    PatSeq *psPtr)
{
    assert(psPtr);
    assert(!psPtr->owned);
................................................................................
    assert(psPtr);

    /* otherwise on some systems the key contains uninitialized bytes */
    memset(key, 0, sizeof(PatternTableKey));

    patPtr = psPtr->pats;
    assert(!patPtr->info || !patPtr->name);
    assert(!patPtr->name || !patPtr->info);

    key->object = psPtr->object;
    key->type = patPtr->eventType;
    if (patPtr->info) {
	key->detail.info = patPtr->info;
    } else {
	key->detail.name = patPtr->name;
................................................................................
	case ButtonRelease: key.detail.info = eventPtr->xev.xbutton.button; break;
	case MotionNotify:  key.detail.info = ButtonNumberFromState(eventPtr->xev.xmotion.state); break;
	case KeyPress:      /* fallthru */
	case KeyRelease:    key.detail.info = eventPtr->detail.info; break;
	case VirtualEvent:  key.detail.name = eventPtr->detail.name; break;
	}
	if (!key.detail.name) {

	    return NULL;
	}
    }

    key.object = object;
    key.type = eventPtr->xev.type;
    hPtr = Tcl_FindHashEntry(&lookupTables->listTable, (char *) &key);
................................................................................

    assert(bindPtr);

    for (i = 0; i < PromArr_Size(bindPtr->promArr); ++i) {
	PSList *psList = PromArr_Get(bindPtr->promArr, i);
	ClearList(psList, &bindPtr->lookupTables.entryPool, object);
	if (!PSList_IsEmpty(psList)) {
	    newArraySize = Max(newArraySize, i + 1);
	}
    }

    PromArr_SetSize(bindPtr->promArr, newArraySize);
}
 
/*
................................................................................

	    for (i = 0; i < SIZE_OF_ARRAY(eventArrayIndex); ++i) {
		eventArrayIndex[i] = -1;
	    }
	    for (i = 0; i < SIZE_OF_ARRAY(eventArray); ++i) {
		unsigned type = eventArray[i].type;
		assert(type < TK_LASTEVENT);

		if (type > 0 && eventArrayIndex[type] == -1) {
		    eventArrayIndex[type] = i;
		}
	    }

	    Tcl_InitHashTable(&modTable, TCL_STRING_KEYS);
	    for (modPtr = modArray; modPtr->name; ++modPtr) {
................................................................................
     */

    /* NOTE: if curEvent is not yet set, then the following cannot match: */
    if (curEvent->xev.xany.window == eventPtr->xany.window) {
	switch (eventPtr->type) {
	case KeyPress:
	case KeyRelease:
	    if (eventPtr->xkey.time - curEvent->xev.xkey.time <= NEARBY_MS) {
		if (curEvent->xev.xkey.keycode == eventPtr->xkey.keycode) {
		    ++curEvent->countDetailed;
		} else {
		    curEvent->countDetailed = 1;
		}
		++curEvent->countAny;
	    } else {
................................................................................
		} else {
		    curEvent->countDetailed = 1;
		}
		++curEvent->countAny;
	    } else {
		curEvent->countAny = curEvent->countDetailed = 1;
	    }
	    break;
	case MotionNotify:
	    if (MatchEventNearby(&curEvent->xev, eventPtr)) {
		++curEvent->countAny;
	    } else {
		curEvent->countAny = 1;
	    }
	    break;
	case EnterNotify:
	case LeaveNotify:
	    if (eventPtr->xcrossing.time - curEvent->xev.xcrossing.time <= NEARBY_MS) {
		++curEvent->countAny;
	    } else {
		curEvent->countAny = 1;
	    }
	    break;
	case PropertyNotify:
	    if (eventPtr->xproperty.time - curEvent->xev.xproperty.time <= NEARBY_MS) {
		++curEvent->countAny;
	    } else {
		curEvent->countAny = 1;
	    }
	    break;
	default:
	    ++curEvent->countAny;
................................................................................
    unsigned long eventMask = 0;
    PatternTableKey key;

    assert(lookupTables);
    assert(eventString);

    psPtr = ckalloc(sizeof(PatSeq) + (patsBufSize - 1)*sizeof(TkPattern));
    memset(psPtr->pats, 0, patsBufSize*sizeof(TkPattern)); /* otherwise memcmp doesn't work */

    /*
     *------------------------------------------------------------------
     * Step 1: parse the pattern string to produce an array of Patterns.
     *------------------------------------------------------------------
     */

    for (patPtr = psPtr->pats, numPats = 0; *(p = SkipSpaces(p)); ++patPtr, ++numPats) {
	if (numPats >= patsBufSize) {
	    unsigned pos = patPtr - psPtr->pats;
	    patsBufSize += patsBufSize;
	    psPtr = ckrealloc(psPtr, sizeof(PatSeq) + (patsBufSize - 1)*sizeof(TkPattern));
	    patPtr = psPtr->pats + pos;
	    memset(patPtr, 0, (patsBufSize - pos)*sizeof(TkPattern)); /* otherwise memcmp doesn't work */
	}

	if ((count = ParseEventDescription(interp, &p, patPtr, &eventMask)) == 0) {
	    /* error encountered */
	    ckfree(psPtr);
	    return NULL;
	}
................................................................................
    }
    if (patsBufSize > numPats) {
	psPtr = ckrealloc(psPtr, sizeof(PatSeq) + (numPats - 1)*sizeof(TkPattern));
    }

    patPtr = psPtr->pats;
    psPtr->object = object;
    memset(&key, 0, sizeof(key));
    SetupPatternKey(&key, psPtr);
    hPtr = Tcl_CreateHashEntry(&lookupTables->patternTable, (char *) &key, &isNew);
    if (!isNew) {
	unsigned sequenceSize = numPats*sizeof(TkPattern);
	PatSeq *psPtr2;

	for (psPtr2 = Tcl_GetHashValue(hPtr); psPtr2; psPtr2 = psPtr2->nextSeqPtr) {
................................................................................
    Tcl_Interp *interp,
    TkPattern *patPtr,
    unsigned count,
    Tcl_Obj* errorObj,
    const char* errCode)
{
    assert(patPtr);


    if (errorObj) {
	Tcl_SetObjResult(interp, errorObj);
	Tcl_SetErrorCode(interp, "TK", "EVENT", errCode, NULL);
    }
    patPtr->count = count;
    return count;
................................................................................
    unsigned count = 1;

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

    p = *eventStringPtr;

    patPtr->eventType = -1;
    patPtr->modStateMask = 0;
    patPtr->info = 0;
    patPtr->name = NULL;


    /*
     * Handle simple ASCII characters.
     */

    if (*p != '<') {
	char string[2];







>


<







 







|
|



|




|



>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<







 







>







 







|







 







>







 







|







 







<
<
<
<
<
<
<



|






|







 







<













<







 







<







 







>







 







<
<
<
<
<
>







253
254
255
256
257
258
259
260
261
262

263
264
265
266
267
268
269
...
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
...
923
924
925
926
927
928
929

930
931
932
933
934
935
936
....
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
....
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
....
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
....
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
....
2179
2180
2181
2182
2183
2184
2185







2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
....
4436
4437
4438
4439
4440
4441
4442

4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455

4456
4457
4458
4459
4460
4461
4462
....
4500
4501
4502
4503
4504
4505
4506

4507
4508
4509
4510
4511
4512
4513
....
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
....
4610
4611
4612
4613
4614
4615
4616





4617
4618
4619
4620
4621
4622
4623
4624
 *
 * 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. */
    unsigned long modStateMask;	/* Mask of modifiers that must be present (zero means no modifiers
    				 * are required). */

    unsigned long 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
    				 * virtual event. */
................................................................................
    assert(index < psPtr->numPats);

    return psPtr->pats[index].count;
}

static bool
MatchEventNearby(
    const XEvent *lhs,	/* previous button event */
    const XEvent *rhs)	/* current button event */
{
    assert(lhs);
    assert(rhs);
    assert(lhs->type == ButtonPress || lhs->type == ButtonRelease);
    assert(lhs->type == rhs->type);

    /* assert: lhs->xbutton.time <= rhs->xbutton.time */

    return Abs(rhs->xbutton.time - lhs->xbutton.time) <= NEARBY_MS
	    && Abs(rhs->xbutton.x_root - lhs->xbutton.x_root) <= NEARBY_PIXELS
	    && Abs(rhs->xbutton.y_root - lhs->xbutton.y_root) <= NEARBY_PIXELS;
}

static bool
MatchEventRepeat(
    const XEvent *lhs,	/* previous key event */
    const XEvent *rhs)	/* current key event */
{
    assert(lhs);
    assert(rhs);
    assert(lhs->type == KeyPress || lhs->type == KeyRelease);
    assert(lhs->type == rhs->type);

    /* assert: lhs->xkey.time <= rhs->xkey.time */
    return Abs(rhs->xkey.time - lhs->xkey.time) <= NEARBY_MS;
}

static void
FreePatSeq(
    PatSeq *psPtr)
{
    assert(psPtr);
    assert(!psPtr->owned);
................................................................................
    assert(psPtr);

    /* otherwise on some systems the key contains uninitialized bytes */
    memset(key, 0, sizeof(PatternTableKey));

    patPtr = psPtr->pats;
    assert(!patPtr->info || !patPtr->name);


    key->object = psPtr->object;
    key->type = patPtr->eventType;
    if (patPtr->info) {
	key->detail.info = patPtr->info;
    } else {
	key->detail.name = patPtr->name;
................................................................................
	case ButtonRelease: key.detail.info = eventPtr->xev.xbutton.button; break;
	case MotionNotify:  key.detail.info = ButtonNumberFromState(eventPtr->xev.xmotion.state); break;
	case KeyPress:      /* fallthru */
	case KeyRelease:    key.detail.info = eventPtr->detail.info; break;
	case VirtualEvent:  key.detail.name = eventPtr->detail.name; break;
	}
	if (!key.detail.name) {
	    assert(!key.detail.info);
	    return NULL;
	}
    }

    key.object = object;
    key.type = eventPtr->xev.type;
    hPtr = Tcl_FindHashEntry(&lookupTables->listTable, (char *) &key);
................................................................................

    assert(bindPtr);

    for (i = 0; i < PromArr_Size(bindPtr->promArr); ++i) {
	PSList *psList = PromArr_Get(bindPtr->promArr, i);
	ClearList(psList, &bindPtr->lookupTables.entryPool, object);
	if (!PSList_IsEmpty(psList)) {
	    newArraySize = i + 1;
	}
    }

    PromArr_SetSize(bindPtr->promArr, newArraySize);
}
 
/*
................................................................................

	    for (i = 0; i < SIZE_OF_ARRAY(eventArrayIndex); ++i) {
		eventArrayIndex[i] = -1;
	    }
	    for (i = 0; i < SIZE_OF_ARRAY(eventArray); ++i) {
		unsigned type = eventArray[i].type;
		assert(type < TK_LASTEVENT);
		assert(type > 0 || i == SIZE_OF_ARRAY(eventArray) - 1);
		if (type > 0 && eventArrayIndex[type] == -1) {
		    eventArrayIndex[type] = i;
		}
	    }

	    Tcl_InitHashTable(&modTable, TCL_STRING_KEYS);
	    for (modPtr = modArray; modPtr->name; ++modPtr) {
................................................................................
     */

    /* NOTE: if curEvent is not yet set, then the following cannot match: */
    if (curEvent->xev.xany.window == eventPtr->xany.window) {
	switch (eventPtr->type) {
	case KeyPress:
	case KeyRelease:
	    if (MatchEventRepeat(&curEvent->xev, eventPtr)) {
		if (curEvent->xev.xkey.keycode == eventPtr->xkey.keycode) {
		    ++curEvent->countDetailed;
		} else {
		    curEvent->countDetailed = 1;
		}
		++curEvent->countAny;
	    } else {
................................................................................
		} else {
		    curEvent->countDetailed = 1;
		}
		++curEvent->countAny;
	    } else {
		curEvent->countAny = curEvent->countDetailed = 1;
	    }







	    break;
	case EnterNotify:
	case LeaveNotify:
	    if (Abs(eventPtr->xcrossing.time - curEvent->xev.xcrossing.time) <= NEARBY_MS) {
		++curEvent->countAny;
	    } else {
		curEvent->countAny = 1;
	    }
	    break;
	case PropertyNotify:
	    if (Abs(eventPtr->xproperty.time - curEvent->xev.xproperty.time) <= NEARBY_MS) {
		++curEvent->countAny;
	    } else {
		curEvent->countAny = 1;
	    }
	    break;
	default:
	    ++curEvent->countAny;
................................................................................
    unsigned long eventMask = 0;
    PatternTableKey key;

    assert(lookupTables);
    assert(eventString);

    psPtr = ckalloc(sizeof(PatSeq) + (patsBufSize - 1)*sizeof(TkPattern));


    /*
     *------------------------------------------------------------------
     * Step 1: parse the pattern string to produce an array of Patterns.
     *------------------------------------------------------------------
     */

    for (patPtr = psPtr->pats, numPats = 0; *(p = SkipSpaces(p)); ++patPtr, ++numPats) {
	if (numPats >= patsBufSize) {
	    unsigned pos = patPtr - psPtr->pats;
	    patsBufSize += patsBufSize;
	    psPtr = ckrealloc(psPtr, sizeof(PatSeq) + (patsBufSize - 1)*sizeof(TkPattern));
	    patPtr = psPtr->pats + pos;

	}

	if ((count = ParseEventDescription(interp, &p, patPtr, &eventMask)) == 0) {
	    /* error encountered */
	    ckfree(psPtr);
	    return NULL;
	}
................................................................................
    }
    if (patsBufSize > numPats) {
	psPtr = ckrealloc(psPtr, sizeof(PatSeq) + (numPats - 1)*sizeof(TkPattern));
    }

    patPtr = psPtr->pats;
    psPtr->object = object;

    SetupPatternKey(&key, psPtr);
    hPtr = Tcl_CreateHashEntry(&lookupTables->patternTable, (char *) &key, &isNew);
    if (!isNew) {
	unsigned sequenceSize = numPats*sizeof(TkPattern);
	PatSeq *psPtr2;

	for (psPtr2 = Tcl_GetHashValue(hPtr); psPtr2; psPtr2 = psPtr2->nextSeqPtr) {
................................................................................
    Tcl_Interp *interp,
    TkPattern *patPtr,
    unsigned count,
    Tcl_Obj* errorObj,
    const char* errCode)
{
    assert(patPtr);
    assert(!errorObj == (count > 0));

    if (errorObj) {
	Tcl_SetObjResult(interp, errorObj);
	Tcl_SetErrorCode(interp, "TK", "EVENT", errCode, NULL);
    }
    patPtr->count = count;
    return count;
................................................................................
    unsigned count = 1;

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

    p = *eventStringPtr;





    memset(patPtr, 0, sizeof(TkPattern)); /* otherwise memcmp doesn't work */

    /*
     * Handle simple ASCII characters.
     */

    if (*p != '<') {
	char string[2];