summaryrefslogtreecommitdiffstats
path: root/generic/tkEntry.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tkEntry.c')
-rw-r--r--generic/tkEntry.c156
1 files changed, 110 insertions, 46 deletions
diff --git a/generic/tkEntry.c b/generic/tkEntry.c
index 6683cdc..9f43f90 100644
--- a/generic/tkEntry.c
+++ b/generic/tkEntry.c
@@ -133,7 +133,7 @@ static const Tk_OptionSpec entryOptSpec[] = {
0, (ClientData) DEF_ENTRY_SELECT_BD_MONO, 0},
{TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr),
- TK_CONFIG_NULL_OK, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0},
+ TK_OPTION_NULL_OK, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0},
{TK_OPTION_STRING, "-show", "show", "Show",
DEF_ENTRY_SHOW, -1, Tk_Offset(Entry, showChar),
TK_OPTION_NULL_OK, 0, 0},
@@ -279,23 +279,23 @@ static const Tk_OptionSpec sbOptSpec[] = {
0, (ClientData) DEF_ENTRY_SELECT_BD_MONO, 0},
{TK_OPTION_COLOR, "-selectforeground", "selectForeground", "Background",
DEF_ENTRY_SELECT_FG_COLOR, -1, Tk_Offset(Entry, selFgColorPtr),
- TK_CONFIG_NULL_OK, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0},
+ TK_OPTION_NULL_OK, (ClientData) DEF_ENTRY_SELECT_FG_MONO, 0},
{TK_OPTION_STRING_TABLE, "-state", "state", "State",
DEF_ENTRY_STATE, -1, Tk_Offset(Entry, state),
0, (ClientData) stateStrings, 0},
{TK_OPTION_STRING, "-takefocus", "takeFocus", "TakeFocus",
DEF_ENTRY_TAKE_FOCUS, -1, Tk_Offset(Entry, takeFocus),
- TK_CONFIG_NULL_OK, 0, 0},
+ TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_STRING, "-textvariable", "textVariable", "Variable",
DEF_ENTRY_TEXT_VARIABLE, -1, Tk_Offset(Entry, textVarName),
- TK_CONFIG_NULL_OK, 0, 0},
+ TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_DOUBLE, "-to", "to", "To",
DEF_SPINBOX_TO, -1, Tk_Offset(Spinbox, toValue), 0, 0, 0},
{TK_OPTION_STRING_TABLE, "-validate", "validate", "Validate",
DEF_ENTRY_VALIDATE, -1, Tk_Offset(Entry, validate),
0, (ClientData) validateStrings, 0},
{TK_OPTION_STRING, "-validatecommand", "validateCommand","ValidateCommand",
- NULL, -1, Tk_Offset(Entry, validateCmd), TK_CONFIG_NULL_OK, 0, 0},
+ NULL, -1, Tk_Offset(Entry, validateCmd), TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_STRING, "-values", "values", "Values",
DEF_SPINBOX_VALUES, -1, Tk_Offset(Spinbox, valueStr),
TK_OPTION_NULL_OK, 0, 0},
@@ -307,7 +307,7 @@ static const Tk_OptionSpec sbOptSpec[] = {
DEF_SPINBOX_WRAP, -1, Tk_Offset(Spinbox, wrap), 0, 0, 0},
{TK_OPTION_STRING, "-xscrollcommand", "xScrollCommand", "ScrollCommand",
DEF_ENTRY_SCROLL_COMMAND, -1, Tk_Offset(Entry, scrollCmd),
- TK_CONFIG_NULL_OK, 0, 0},
+ TK_OPTION_NULL_OK, 0, 0},
{TK_OPTION_END, NULL, NULL, NULL, NULL, 0, -1, 0, 0, 0}
};
@@ -390,8 +390,8 @@ static const char *selElementNames[] = {
*/
static int ConfigureEntry(Tcl_Interp *interp, Entry *entryPtr,
- int objc, Tcl_Obj *const objv[], int flags);
-static void DeleteChars(Entry *entryPtr, int index, int count);
+ int objc, Tcl_Obj *const objv[]);
+static int DeleteChars(Entry *entryPtr, int index, int count);
static void DestroyEntry(char *memPtr);
static void DisplayEntry(ClientData clientData);
static void EntryBlinkProc(ClientData clientData);
@@ -417,7 +417,7 @@ static int EntryValidateChange(Entry *entryPtr, char *change,
static void ExpandPercents(Entry *entryPtr, const char *before,
const char *change, const char *newStr, int index,
int type, Tcl_DString *dsPtr);
-static void EntryValueChanged(Entry *entryPtr,
+static int EntryValueChanged(Entry *entryPtr,
const char *newValue);
static void EntryVisibleRange(Entry *entryPtr,
double *firstPtr, double *lastPtr);
@@ -427,7 +427,7 @@ static int EntryWidgetObjCmd(ClientData clientData,
static void EntryWorldChanged(ClientData instanceData);
static int GetEntryIndex(Tcl_Interp *interp, Entry *entryPtr,
char *string, int *indexPtr);
-static void InsertChars(Entry *entryPtr, int index, char *string);
+static int InsertChars(Entry *entryPtr, int index, char *string);
/*
* These forward declarations are the spinbox specific ones:
@@ -553,7 +553,7 @@ Tk_EntryObjCmd(
if ((Tk_InitOptions(interp, (char *) entryPtr, optionTable, tkwin)
!= TCL_OK) ||
- (ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0) != TCL_OK)) {
+ (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK)) {
Tk_DestroyWindow(entryPtr->tkwin);
return TCL_ERROR;
}
@@ -658,12 +658,12 @@ EntryWidgetObjCmd(
Tcl_SetObjResult(interp, objPtr);
}
} else {
- result = ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0);
+ result = ConfigureEntry(interp, entryPtr, objc-2, objv+2);
}
break;
case COMMAND_DELETE: {
- int first, last;
+ int first, last, code;
if ((objc < 3) || (objc > 4)) {
Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
@@ -680,7 +680,10 @@ EntryWidgetObjCmd(
goto error;
}
if ((last >= first) && (entryPtr->state == STATE_NORMAL)) {
- DeleteChars(entryPtr, first, last - first);
+ code = DeleteChars(entryPtr, first, last - first);
+ if (code != TCL_OK) {
+ goto error;
+ }
}
break;
}
@@ -721,7 +724,7 @@ EntryWidgetObjCmd(
}
case COMMAND_INSERT: {
- int index;
+ int index, code;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "index text");
@@ -732,7 +735,10 @@ EntryWidgetObjCmd(
goto error;
}
if (entryPtr->state == STATE_NORMAL) {
- InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
+ code = InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
+ if (code != TCL_OK) {
+ goto error;
+ }
}
break;
}
@@ -1080,8 +1086,7 @@ ConfigureEntry(
Entry *entryPtr, /* Information about widget; may or may not
* already have values for some fields. */
int objc, /* Number of valid entries in argv. */
- Tcl_Obj *const objv[], /* Argument objects. */
- int flags) /* Flags to pass to Tk_ConfigureWidget. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
Tk_SavedOptions savedOptions;
Tk_3DBorder border;
@@ -1096,6 +1101,7 @@ ConfigureEntry(
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.
@@ -1298,6 +1304,17 @@ ConfigureEntry(
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);
@@ -1316,7 +1333,13 @@ ConfigureEntry(
*/
Tcl_ListObjIndex(interp, sbPtr->listObj, 0, &objPtr);
- EntryValueChanged(entryPtr, Tcl_GetString(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)
@@ -1341,6 +1364,12 @@ ConfigureEntry(
}
}
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);
}
}
@@ -1352,10 +1381,13 @@ ConfigureEntry(
if ((entryPtr->textVarName != NULL)
&& !(entryPtr->flags & ENTRY_VAR_TRACED)) {
- Tcl_TraceVar(interp, entryPtr->textVarName,
+ code = Tcl_TraceVar(interp, entryPtr->textVarName,
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
EntryTextVarProc, (ClientData) entryPtr);
- entryPtr->flags |= ENTRY_VAR_TRACED;
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
+ entryPtr->flags |= ENTRY_VAR_TRACED;
}
EntryWorldChanged((ClientData) entryPtr);
@@ -1675,7 +1707,7 @@ DisplayEntry(
Tk_CharBbox(entryPtr->textLayout, entryPtr->insertPos, &cursorX, NULL,
NULL, NULL);
cursorX += entryPtr->layoutX;
- cursorX -= (entryPtr->insertWidth)/2;
+ cursorX -= (entryPtr->insertWidth == 1) ? 1 : (entryPtr->insertWidth)/2;
Tk_SetCaretPos(entryPtr->tkwin, cursorX, baseY - fm.ascent,
fm.ascent + fm.descent);
if (entryPtr->insertPos >= entryPtr->leftIndex && cursorX < xBound) {
@@ -1990,7 +2022,8 @@ EntryComputeGeometry(
* Add new characters to an entry widget.
*
* Results:
- * None.
+ * A standard Tcl result. If an error occurred then an error message is
+ * left in the interp's result.
*
* Side effects:
* New information gets added to entryPtr; it will be redisplayed soon,
@@ -1999,7 +2032,7 @@ EntryComputeGeometry(
*----------------------------------------------------------------------
*/
-static void
+static int
InsertChars(
Entry *entryPtr, /* Entry that is to get the new elements. */
int index, /* Add the new elements before this character
@@ -2017,7 +2050,7 @@ InsertChars(
byteIndex = Tcl_UtfAtIndex(string, index) - string;
byteCount = strlen(value);
if (byteCount == 0) {
- return;
+ return TCL_OK;
}
newByteCount = entryPtr->numBytes + byteCount + 1;
@@ -2031,7 +2064,7 @@ InsertChars(
EntryValidateChange(entryPtr, value, newStr, index,
VALIDATE_INSERT) != TCL_OK) {
ckfree(newStr);
- return;
+ return TCL_OK;
}
ckfree((char *)string);
@@ -2079,7 +2112,7 @@ InsertChars(
if (entryPtr->insertPos >= index) {
entryPtr->insertPos += charsAdded;
}
- EntryValueChanged(entryPtr, NULL);
+ return EntryValueChanged(entryPtr, NULL);
}
/*
@@ -2090,7 +2123,8 @@ InsertChars(
* Remove one or more characters from an entry widget.
*
* Results:
- * None.
+ * A standard Tcl result. If an error occurred then an error message is
+ * left in the interp's result.
*
* Side effects:
* Memory gets freed, the entry gets modified and (eventually)
@@ -2099,7 +2133,7 @@ InsertChars(
*----------------------------------------------------------------------
*/
-static void
+static int
DeleteChars(
Entry *entryPtr, /* Entry widget to modify. */
int index, /* Index of first character to delete. */
@@ -2113,7 +2147,7 @@ DeleteChars(
count = entryPtr->numChars - index;
}
if (count <= 0) {
- return;
+ return TCL_OK;
}
string = entryPtr->string;
@@ -2135,7 +2169,7 @@ DeleteChars(
VALIDATE_DELETE) != TCL_OK) {
ckfree(newStr);
ckfree(toDelete);
- return;
+ return TCL_OK;
}
ckfree(toDelete);
@@ -2194,7 +2228,7 @@ DeleteChars(
entryPtr->insertPos = index;
}
}
- EntryValueChanged(entryPtr, NULL);
+ return EntryValueChanged(entryPtr, NULL);
}
/*
@@ -2207,7 +2241,8 @@ DeleteChars(
* is one, and does other bookkeeping such as arranging for redisplay.
*
* Results:
- * None.
+ * A standard Tcl result. If an error occurred then an error message is
+ * left in the interp's result.
*
* Side effects:
* None.
@@ -2215,7 +2250,7 @@ DeleteChars(
*----------------------------------------------------------------------
*/
-static void
+static int
EntryValueChanged(
Entry *entryPtr, /* Entry whose value just changed. */
const char *newValue) /* If this value is not NULL, we first force
@@ -2229,7 +2264,7 @@ EntryValueChanged(
newValue = NULL;
} else {
newValue = Tcl_SetVar(entryPtr->interp, entryPtr->textVarName,
- entryPtr->string, TCL_GLOBAL_ONLY);
+ entryPtr->string, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG);
}
if ((newValue != NULL) && (strcmp(newValue, entryPtr->string) != 0)) {
@@ -2251,6 +2286,19 @@ EntryValueChanged(
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;
}
/*
@@ -3588,7 +3636,7 @@ Tk_SpinboxObjCmd(
Tk_DestroyWindow(entryPtr->tkwin);
return TCL_ERROR;
}
- if (ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0) != TCL_OK) {
+ if (ConfigureEntry(interp, entryPtr, objc-2, objv+2) != TCL_OK) {
goto error;
}
@@ -3698,12 +3746,12 @@ SpinboxWidgetObjCmd(
Tcl_SetObjResult(interp, objPtr);
}
} else {
- result = ConfigureEntry(interp, entryPtr, objc-2, objv+2, 0);
+ result = ConfigureEntry(interp, entryPtr, objc-2, objv+2);
}
break;
case SB_CMD_DELETE: {
- int first, last;
+ int first, last, code;
if ((objc < 3) || (objc > 4)) {
Tcl_WrongNumArgs(interp, 2, objv, "firstIndex ?lastIndex?");
@@ -3722,7 +3770,10 @@ SpinboxWidgetObjCmd(
}
}
if ((last >= first) && (entryPtr->state == STATE_NORMAL)) {
- DeleteChars(entryPtr, first, last - first);
+ code = DeleteChars(entryPtr, first, last - first);
+ if (code != TCL_OK) {
+ goto error;
+ }
}
break;
}
@@ -3782,7 +3833,7 @@ SpinboxWidgetObjCmd(
}
case SB_CMD_INSERT: {
- int index;
+ int index, code;
if (objc != 4) {
Tcl_WrongNumArgs(interp, 2, objv, "index text");
@@ -3793,7 +3844,10 @@ SpinboxWidgetObjCmd(
goto error;
}
if (entryPtr->state == STATE_NORMAL) {
- InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
+ code = InsertChars(entryPtr, index, Tcl_GetString(objv[3]));
+ if (code != TCL_OK) {
+ goto error;
+ }
}
break;
}
@@ -4001,16 +4055,22 @@ SpinboxWidgetObjCmd(
break;
}
- case SB_CMD_SET:
+ case SB_CMD_SET: {
+ int code = TCL_OK;
+
if (objc > 3) {
Tcl_WrongNumArgs(interp, 2, objv, "?string?");
goto error;
}
if (objc == 3) {
- EntryValueChanged(entryPtr, Tcl_GetString(objv[2]));
+ code = EntryValueChanged(entryPtr, Tcl_GetString(objv[2]));
+ if (code != TCL_OK) {
+ goto error;
+ }
}
Tcl_SetStringObj(Tcl_GetObjResult(interp), entryPtr->string, -1);
break;
+ }
case SB_CMD_VALIDATE: {
int code;
@@ -4151,7 +4211,7 @@ GetSpinboxElement(
* TCL_OK.
*
* Side effects:
- * An background error condition may arise when invoking the callback.
+ * A background error condition may arise when invoking the callback.
* The widget value may change.
*
*--------------------------------------------------------------
@@ -4182,6 +4242,7 @@ SpinboxInvoke(
return TCL_OK;
}
+ code = TCL_OK;
if (fabs(sbPtr->increment) > MIN_DBL_VAL) {
if (sbPtr->listObj != NULL) {
Tcl_Obj *objPtr;
@@ -4227,7 +4288,7 @@ SpinboxInvoke(
}
}
Tcl_ListObjIndex(interp, sbPtr->listObj, sbPtr->eIndex, &objPtr);
- EntryValueChanged(entryPtr, Tcl_GetString(objPtr));
+ code = EntryValueChanged(entryPtr, Tcl_GetString(objPtr));
} else if (!DOUBLES_EQ(sbPtr->fromValue, sbPtr->toValue)) {
double dvalue;
@@ -4274,9 +4335,12 @@ SpinboxInvoke(
}
}
sprintf(sbPtr->formatBuf, sbPtr->valueFormat, dvalue);
- EntryValueChanged(entryPtr, sbPtr->formatBuf);
+ code = EntryValueChanged(entryPtr, sbPtr->formatBuf);
}
}
+ if (code != TCL_OK) {
+ return TCL_ERROR;
+ }
if (sbPtr->command != NULL) {
Tcl_DStringInit(&script);