Tk Source Code

Check-in [ab7e1a03]
Login

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

Overview
Comment:Fixed bug [793909] - Problem with nonexistent namespaces
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | core-8-5-branch
Files: files | file ages | folders
SHA1: ab7e1a03d36241df604c19ffea8ed15fe087efbc
User & Date: fvogel 2015-12-19 22:54:54.748
Context
2015-12-23
17:08
Made test textDisp-16.18 pass again on Win7 after [a4bf73e4b8]: map the text widget earlier check-in: dc97dedc user: fvogel tags: core-8-5-branch
11:29
Fixed bug [2f78c7c5ea] - text segfault with tablelist in TkBTreeLinesTo check-in: 311ef109 user: fvogel tags: bug-2f78c7c5ea
2015-12-22
20:59
merge 8.5 check-in: a2b4ba23 user: dgp tags: core-8-5-19-rc
2015-12-21
12:12
Merged core-8-5-branch check-in: a888e911 user: fvogel tags: tip-438
2015-12-19
23:14
Fixed bug [793909] - Problem with nonexistent namespaces check-in: 834abec2 user: fvogel tags: trunk
22:54
Fixed bug [793909] - Problem with nonexistent namespaces check-in: ab7e1a03 user: fvogel tags: core-8-5-branch
21:58
Fixed bug [1700065] - error in trace proc on textvariable doesn't trigger bgerror check-in: a73ee92b user: fvogel tags: core-8-5-branch
2015-12-12
16:01
Fixed bug [793909] - Problem with nonexistent namespaces Closed-Leaf check-in: b117db54 user: fvogel tags: bug-793909fff
Changes
Unified Diff Ignore Whitespace Patch
Changes to generic/tkEntry.c.
1098
1099
1100
1101
1102
1103
1104

1105
1106
1107
1108
1109
1110
1111
    char *oldValues = NULL;	/* lint initialization */
    char *oldFormat = NULL;	/* lint initialization */
    int error;
    int oldExport = 0;		/* lint initialization */
    int valuesChanged = 0;	/* lint initialization */
    double oldFrom = 0.0;	/* lint initialization */
    double oldTo = 0.0;		/* lint initialization */


    /*
     * Eliminate any existing trace on a variable monitored by the entry.
     */

    if ((entryPtr->textVarName != NULL)
	    && (entryPtr->flags & ENTRY_VAR_TRACED)) {







>







1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
    char *oldValues = NULL;	/* lint initialization */
    char *oldFormat = NULL;	/* lint initialization */
    int error;
    int oldExport = 0;		/* lint initialization */
    int valuesChanged = 0;	/* lint initialization */
    double oldFrom = 0.0;	/* lint initialization */
    double oldTo = 0.0;		/* lint initialization */
    int code;

    /*
     * Eliminate any existing trace on a variable monitored by the entry.
     */

    if ((entryPtr->textVarName != NULL)
	    && (entryPtr->flags & ENTRY_VAR_TRACED)) {
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309











1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327






1328
1329
1330
1331
1332
1333
1334
1335
    if (!error) {
	Tk_FreeSavedOptions(&savedOptions);
    }

    /*
     * If the entry is tied to the value of a variable, create the variable if
     * it doesn't exist, and set the entry's value from the variable's value.
     * No checking of the return value of EntryValueChanged is needed since it
     * can only return TCL_ERROR if there is a trace on the textvariable and
     * since any existing trace on it was eliminated above.
     */

    if (entryPtr->textVarName != NULL) {
	const char *value;

	value = Tcl_GetVar(interp, entryPtr->textVarName, TCL_GLOBAL_ONLY);
	if (value == NULL) {











	    EntryValueChanged(entryPtr, NULL);
	} else {
	    EntrySetValue(entryPtr, value);
	}
    }

    if (entryPtr->type == TK_SPINBOX) {
	ComputeFormat(sbPtr);

	if (valuesChanged > 0) {
	    Tcl_Obj *objPtr;

	    /*
	     * No check for error return, because there shouldn't be one given
	     * the check for valid list above.
	     */

	    Tcl_ListObjIndex(interp, sbPtr->listObj, 0, &objPtr);






	    EntryValueChanged(entryPtr, Tcl_GetString(objPtr));
	} else if ((sbPtr->valueStr == NULL)
		&& !DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue)
		&& (!DOUBLES_EQ(sbPtr->fromValue, oldFrom)
			|| !DOUBLES_EQ(sbPtr->toValue, oldTo))) {
	    /*
	     * If the valueStr is empty and -from && -to are specified, check
	     * to see if the current string is within the range. If not, it







<
<
<







>
>
>
>
>
>
>
>
>
>
>


















>
>
>
>
>
>
|







1294
1295
1296
1297
1298
1299
1300



1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
    if (!error) {
	Tk_FreeSavedOptions(&savedOptions);
    }

    /*
     * If the entry is tied to the value of a variable, create the variable if
     * it doesn't exist, and set the entry's value from the variable's value.



     */

    if (entryPtr->textVarName != NULL) {
	const char *value;

	value = Tcl_GetVar(interp, entryPtr->textVarName, TCL_GLOBAL_ONLY);
	if (value == NULL) {

            /*
             * Since any trace on the textvariable was eliminated above,
             * the only possible reason for EntryValueChanged to return
             * an error is that the textvariable lives in a namespace
             * that does not (yet) exist. Indeed, namespaces are not
             * automatically created as needed. Don't trap this error
             * here, better do it below when attempting to trace the
             * variable.
             */

	    EntryValueChanged(entryPtr, NULL);
	} else {
	    EntrySetValue(entryPtr, value);
	}
    }

    if (entryPtr->type == TK_SPINBOX) {
	ComputeFormat(sbPtr);

	if (valuesChanged > 0) {
	    Tcl_Obj *objPtr;

	    /*
	     * No check for error return, because there shouldn't be one given
	     * the check for valid list above.
	     */

	    Tcl_ListObjIndex(interp, sbPtr->listObj, 0, &objPtr);

            /*
	     * No check for error return here as well, because any possible
	     * error will be trapped below when attempting tracing.
	     */

            EntryValueChanged(entryPtr, Tcl_GetString(objPtr));
	} else if ((sbPtr->valueStr == NULL)
		&& !DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue)
		&& (!DOUBLES_EQ(sbPtr->fromValue, oldFrom)
			|| !DOUBLES_EQ(sbPtr->toValue, oldTo))) {
	    /*
	     * If the valueStr is empty and -from && -to are specified, check
	     * to see if the current string is within the range. If not, it
1346
1347
1348
1349
1350
1351
1352






1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366



1367
1368
1369
1370
1371
1372
1373
1374
		if (dvalue > sbPtr->toValue) {
		    dvalue = sbPtr->toValue;
		} else if (dvalue < sbPtr->fromValue) {
		    dvalue = sbPtr->fromValue;
		}
	    }
	    sprintf(sbPtr->formatBuf, sbPtr->valueFormat, dvalue);






	    EntryValueChanged(entryPtr, sbPtr->formatBuf);
	}
    }

    /*
     * Set up a trace on the variable's value after we've possibly constrained
     * the value according to new -from/-to values.
     */

    if ((entryPtr->textVarName != NULL)
	    && !(entryPtr->flags & ENTRY_VAR_TRACED)) {
	Tcl_TraceVar(interp, entryPtr->textVarName,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		EntryTextVarProc, (ClientData) entryPtr);



	entryPtr->flags |= ENTRY_VAR_TRACED;
    }

    EntryWorldChanged((ClientData) entryPtr);
    if (error) {
	Tcl_SetObjResult(interp, errorResult);
	Tcl_DecrRefCount(errorResult);
	return TCL_ERROR;







>
>
>
>
>
>











|


>
>
>
|







1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
		if (dvalue > sbPtr->toValue) {
		    dvalue = sbPtr->toValue;
		} else if (dvalue < sbPtr->fromValue) {
		    dvalue = sbPtr->fromValue;
		}
	    }
	    sprintf(sbPtr->formatBuf, sbPtr->valueFormat, dvalue);

            /*
	     * No check for error return here as well, because any possible
	     * error will be trapped below when attempting tracing.
	     */

	    EntryValueChanged(entryPtr, sbPtr->formatBuf);
	}
    }

    /*
     * Set up a trace on the variable's value after we've possibly constrained
     * the value according to new -from/-to values.
     */

    if ((entryPtr->textVarName != NULL)
	    && !(entryPtr->flags & ENTRY_VAR_TRACED)) {
	code = Tcl_TraceVar(interp, entryPtr->textVarName,
		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
		EntryTextVarProc, (ClientData) entryPtr);
        if (code != TCL_OK) {
            return TCL_ERROR;
        }
        entryPtr->flags |= ENTRY_VAR_TRACED;
    }

    EntryWorldChanged((ClientData) entryPtr);
    if (error) {
	Tcl_SetObjResult(interp, errorResult);
	Tcl_DecrRefCount(errorResult);
	return TCL_ERROR;
2263
2264
2265
2266
2267
2268
2269


2270
2271
2272
2273
2274
2275
2276
	EntryComputeGeometry(entryPtr);
	EventuallyRedraw(entryPtr);
    }

    /*
     * An error may have happened when setting the textvariable in case there
     * is a trace on that variable and the trace proc triggered an error.


     * Signal this error.
     */

    if ((entryPtr->textVarName != NULL) && (newValue == NULL)) {
        return TCL_ERROR;
    }
    return TCL_OK;







>
>







2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
	EntryComputeGeometry(entryPtr);
	EventuallyRedraw(entryPtr);
    }

    /*
     * An error may have happened when setting the textvariable in case there
     * is a trace on that variable and the trace proc triggered an error.
     * Another possibility is that the textvariable is in a namespace that
     * does not (yet) exist.
     * Signal this error.
     */

    if ((entryPtr->textVarName != NULL) && (newValue == NULL)) {
        return TCL_ERROR;
    }
    return TCL_OK;
Changes to tests/entry.test.
1637
1638
1639
1640
1641
1642
1643






1644
1645
1646
1647
1648
1649
1650
    entry .e -textvariable myvar
    catch {.e insert end mystring} result1
    catch {.e delete 0} result2
    list $result1 $result2
} [list {can't set "myvar": Intentional error here!} \
    {can't set "myvar": Intentional error here!}]







destroy .e

# XXX Still need to write tests for EntryBlinkProc, EntryFocusProc,
# and EntryTextVarProc.

option clear








>
>
>
>
>
>







1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
    entry .e -textvariable myvar
    catch {.e insert end mystring} result1
    catch {.e delete 0} result2
    list $result1 $result2
} [list {can't set "myvar": Intentional error here!} \
    {can't set "myvar": Intentional error here!}]

test entry-24.1 {textvariable lives in a non-existing namespace} {
    destroy .e
    catch {entry .e -textvariable thisnsdoesntexist::myvar} result1
    set result1
} {can't trace "thisnsdoesntexist::myvar": parent namespace doesn't exist}

destroy .e

# XXX Still need to write tests for EntryBlinkProc, EntryFocusProc,
# and EntryTextVarProc.

option clear

Changes to tests/spinbox.test.
1595
1596
1597
1598
1599
1600
1601






1602
1603
1604
1605
1606
1607
1608
    catch {.s invoke buttonup} result4
    list $result1 $result2 $result3 $result4
} [list {can't set "myvar": Intentional error here!} \
    {can't set "myvar": Intentional error here!} \
    {can't set "myvar": Intentional error here!} \
    {can't set "myvar": Intentional error here!}]







catch {unset ::e ::vVals}

##
## End validation tests
##

# XXX Still need to write tests for SpinboxBlinkProc, SpinboxFocusProc,







>
>
>
>
>
>







1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
    catch {.s invoke buttonup} result4
    list $result1 $result2 $result3 $result4
} [list {can't set "myvar": Intentional error here!} \
    {can't set "myvar": Intentional error here!} \
    {can't set "myvar": Intentional error here!} \
    {can't set "myvar": Intentional error here!}]

test spinbox-25.1 {textvariable lives in a non-existing namespace} {
    destroy .s
    catch {spinbox .s -textvariable thisnsdoesntexist::myvar} result1
    set result1
} {can't trace "thisnsdoesntexist::myvar": parent namespace doesn't exist}

catch {unset ::e ::vVals}

##
## End validation tests
##

# XXX Still need to write tests for SpinboxBlinkProc, SpinboxFocusProc,