summaryrefslogtreecommitdiffstats
path: root/generic/tkEntry.c
diff options
context:
space:
mode:
authorhobbs <hobbs>2000-03-02 21:52:40 (GMT)
committerhobbs <hobbs>2000-03-02 21:52:40 (GMT)
commit2c8a777381c7c653bf9304fd50a526a8a81ce293 (patch)
tree5a53a857601925e08c884ef63ce5190f753f93cc /generic/tkEntry.c
parent9521a71f90589b90b5506505a8c81b7cb198b96d (diff)
downloadtk-2c8a777381c7c653bf9304fd50a526a8a81ce293.zip
tk-2c8a777381c7c653bf9304fd50a526a8a81ce293.tar.gz
tk-2c8a777381c7c653bf9304fd50a526a8a81ce293.tar.bz2
* generic/tkListbox.c (DestroyListbox): fixed crash in
DestroyListbox due to null tkwin. [Bug: 4207] * tests/entry.test: added test suite for entry validation * doc/entry.n: improved docs discussing caveats and gotchas when mixing textvar with widget validation * generic/tkEntry.c (EntryValidateChange): improved handling of validation with relation to -textvariable. Previously, it would turn off whenever the textvar was set. Now it will it will turn off only when the textvar is set and validation returns 0. Added %V (type of validation occuring) to %-subs to help work with trickier validation.
Diffstat (limited to 'generic/tkEntry.c')
-rw-r--r--generic/tkEntry.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/generic/tkEntry.c b/generic/tkEntry.c
index 9f3b560..d860289 100644
--- a/generic/tkEntry.c
+++ b/generic/tkEntry.c
@@ -11,7 +11,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkEntry.c,v 1.9 2000/01/12 11:45:02 hobbs Exp $
+ * RCS: @(#) $Id: tkEntry.c,v 1.10 2000/03/02 21:52:40 hobbs Exp $
*/
#include "tkInt.h"
@@ -181,6 +181,7 @@ typedef struct {
* UPDATE_SCROLLBAR: Non-zero means scrollbar should be updated
* during next redisplay operation.
* GOT_SELECTION: Non-zero means we've claimed the selection.
+ * ENTRY_DELETED: This entry has been effectively destroyed.
* VALIDATING: Non-zero means we are in a validateCmd
* VALIDATE_VAR: Non-zero means we are attempting to validate
* the entry's textvariable with validateCmd
@@ -2818,13 +2819,13 @@ EntryValidateChange(entryPtr, change, new, index, type)
int type; /* forced, delete, insert,
* focusin or focusout */
{
- int code;
+ int code, varValidate = (entryPtr->flags & VALIDATE_VAR);
char *p;
Tcl_DString script;
if (entryPtr->validateCmd == NULL ||
entryPtr->validate == VALIDATE_NONE) {
- return (entryPtr->flags & VALIDATE_VAR) ? TCL_ERROR : TCL_OK;
+ return (varValidate ? TCL_ERROR : TCL_OK);
}
/*
@@ -2834,7 +2835,7 @@ EntryValidateChange(entryPtr, change, new, index, type)
*/
if (entryPtr->flags & VALIDATING) {
entryPtr->validate = VALIDATE_NONE;
- return (entryPtr->flags & VALIDATE_VAR) ? TCL_ERROR : TCL_OK;
+ return (varValidate ? TCL_ERROR : TCL_OK);
}
entryPtr->flags |= VALIDATING;
@@ -2853,12 +2854,13 @@ EntryValidateChange(entryPtr, change, new, index, type)
Tcl_DStringFree(&script);
/*
- * If e->validate has become VALIDATE_NONE during the validation,
+ * If e->validate has become VALIDATE_NONE during the validation, or
+ * we now have VALIDATE_VAR set (from EntrySetValue) and didn't before,
* it means that a loop condition almost occured. Do not allow
* this validation result to finish.
*/
- if (entryPtr->validate == VALIDATE_NONE ||
- (entryPtr->flags & VALIDATE_VAR)) {
+ if (entryPtr->validate == VALIDATE_NONE
+ || (!varValidate && (entryPtr->flags & VALIDATE_VAR))) {
code = TCL_ERROR;
}
/*
@@ -2869,7 +2871,17 @@ EntryValidateChange(entryPtr, change, new, index, type)
if (code == TCL_ERROR) {
entryPtr->validate = VALIDATE_NONE;
} else if (code == TCL_BREAK) {
- if (entryPtr->invalidCmd != NULL) {
+ /*
+ * If we were doing forced validation (like via a variable
+ * trace) and the command returned 0, the we turn off validation
+ * because we assume that textvariables have precedence in
+ * managing the value. We also don't call the invcmd, as it
+ * may want to do entry manipulation which the setting of the
+ * var will later wipe anyway.
+ */
+ if (varValidate) {
+ entryPtr->validate = VALIDATE_NONE;
+ } else if (entryPtr->invalidCmd != NULL) {
Tcl_DStringInit(&script);
ExpandPercents(entryPtr, entryPtr->invalidCmd,
change, new, index, type, &script);
@@ -2989,9 +3001,23 @@ ExpandPercents(entryPtr, before, change, new, index, type, dsPtr)
case 'S': /* string to be inserted/deleted, if any */
string = change;
break;
- case 'v': /* type of validation */
+ case 'v': /* type of validation currently set */
string = validateStrings[entryPtr->validate];
break;
+ case 'V': /* type of validation in effect */
+ switch (type) {
+ case VALIDATE_INSERT:
+ case VALIDATE_DELETE:
+ string = validateStrings[VALIDATE_KEY];
+ break;
+ case VALIDATE_FORCED:
+ string = "forced";
+ break;
+ default:
+ string = validateStrings[type];
+ break;
+ }
+ break;
case 'W': /* widget name */
string = Tk_PathName(entryPtr->tkwin);
break;