summaryrefslogtreecommitdiffstats
path: root/generic/tkListbox.c
diff options
context:
space:
mode:
authorhobbs <hobbs>2002-02-26 01:07:29 (GMT)
committerhobbs <hobbs>2002-02-26 01:07:29 (GMT)
commit7dfdadc282105c5d6f50ebedb6f623cdb4a56f15 (patch)
tree82b9e7b042c4d57578462a2f1861ee698ad37de7 /generic/tkListbox.c
parent81348b18fcd26678bbdd04d40a2370f13260fbc1 (diff)
downloadtk-7dfdadc282105c5d6f50ebedb6f623cdb4a56f15.zip
tk-7dfdadc282105c5d6f50ebedb6f623cdb4a56f15.tar.gz
tk-7dfdadc282105c5d6f50ebedb6f623cdb4a56f15.tar.bz2
* tests/listbox.test:
* generic/tkListbox.c: corrected error handling when setting to an invalid listvar value. [Bug #503613]
Diffstat (limited to 'generic/tkListbox.c')
-rw-r--r--generic/tkListbox.c180
1 files changed, 100 insertions, 80 deletions
diff --git a/generic/tkListbox.c b/generic/tkListbox.c
index 7bf5e0b..3eaa135 100644
--- a/generic/tkListbox.c
+++ b/generic/tkListbox.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: tkListbox.c,v 1.24 2002/01/18 02:55:06 hobbs Exp $
+ * RCS: @(#) $Id: tkListbox.c,v 1.25 2002/02/26 01:07:29 hobbs Exp $
*/
#include "tkPort.h"
@@ -1529,7 +1529,8 @@ ConfigureListbox(interp, listPtr, objc, objv, flags)
{
Tk_SavedOptions savedOptions;
Tcl_Obj *oldListObj = NULL;
- int oldExport;
+ Tcl_Obj *errorResult = NULL;
+ int oldExport, error;
oldExport = listPtr->exportSelection;
if (listPtr->listVarName != NULL) {
@@ -1537,99 +1538,118 @@ ConfigureListbox(interp, listPtr, objc, objv, flags)
TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
ListboxListVarProc, (ClientData) listPtr);
}
-
- if (Tk_SetOptions(interp, (char *)listPtr,
- listPtr->optionTable, objc, objv, listPtr->tkwin,
- &savedOptions, (int *)NULL) != TCL_OK) {
- Tk_RestoreSavedOptions(&savedOptions);
- return TCL_ERROR;
- }
-
- /*
- * A few options need special processing, such as setting the
- * background from a 3-D border.
- */
- Tk_SetBackgroundFromBorder(listPtr->tkwin, listPtr->normalBorder);
+ for (error = 0; error <= 1; error++) {
+ if (!error) {
+ /*
+ * First pass: set options to new values.
+ */
- if (listPtr->highlightWidth < 0) {
- listPtr->highlightWidth = 0;
- }
- listPtr->inset = listPtr->highlightWidth + listPtr->borderWidth;
+ if (Tk_SetOptions(interp, (char *) listPtr,
+ listPtr->optionTable, objc, objv,
+ listPtr->tkwin, &savedOptions, (int *) NULL) != TCL_OK) {
+ continue;
+ }
+ } else {
+ /*
+ * Second pass: restore options to old values.
+ */
- /*
- * Claim the selection if we've suddenly started exporting it and
- * there is a selection to export.
- */
+ errorResult = Tcl_GetObjResult(interp);
+ Tcl_IncrRefCount(errorResult);
+ Tk_RestoreSavedOptions(&savedOptions);
+ }
- if (listPtr->exportSelection && !oldExport
- && (listPtr->numSelected != 0)) {
- Tk_OwnSelection(listPtr->tkwin, XA_PRIMARY, ListboxLostSelection,
- (ClientData) listPtr);
- }
+ /*
+ * A few options need special processing, such as setting the
+ * background from a 3-D border.
+ */
-
- /* Verify the current status of the list var.
- * PREVIOUS STATE | NEW STATE | ACTION
- * ------------------+---------------+----------------------------------
- * no listvar | listvar | If listvar does not exist, create
- * it and copy the internal list obj's
- * content to the new var. If it does
- * exist, toss the internal list obj.
- *
- * listvar | no listvar | Copy old listvar content to the
- * internal list obj
- *
- * listvar | listvar | no special action
- *
- * no listvar | no listvar | no special action
- */
- oldListObj = listPtr->listObj;
- if (listPtr->listVarName != NULL) {
- Tcl_Obj *listVarObj = Tcl_GetVar2Ex(interp, listPtr->listVarName,
- (char *)NULL, TCL_GLOBAL_ONLY);
- int dummy;
- if (listVarObj == NULL) {
- if (listPtr->listObj != NULL) {
- listVarObj = listPtr->listObj;
- } else {
- listVarObj = Tcl_NewObj();
+ Tk_SetBackgroundFromBorder(listPtr->tkwin, listPtr->normalBorder);
+
+ if (listPtr->highlightWidth < 0) {
+ listPtr->highlightWidth = 0;
+ }
+ listPtr->inset = listPtr->highlightWidth + listPtr->borderWidth;
+
+ /*
+ * Claim the selection if we've suddenly started exporting it and
+ * there is a selection to export.
+ */
+
+ if (listPtr->exportSelection && !oldExport
+ && (listPtr->numSelected != 0)) {
+ Tk_OwnSelection(listPtr->tkwin, XA_PRIMARY, ListboxLostSelection,
+ (ClientData) listPtr);
+ }
+
+ /* Verify the current status of the list var.
+ * PREVIOUS STATE | NEW STATE | ACTION
+ * ---------------+------------+----------------------------------
+ * no listvar | listvar | If listvar does not exist, create
+ * it and copy the internal list obj's
+ * content to the new var. If it does
+ * exist, toss the internal list obj.
+ *
+ * listvar | no listvar | Copy old listvar content to the
+ * internal list obj
+ *
+ * listvar | listvar | no special action
+ *
+ * no listvar | no listvar | no special action
+ */
+ oldListObj = listPtr->listObj;
+ if (listPtr->listVarName != NULL) {
+ Tcl_Obj *listVarObj = Tcl_GetVar2Ex(interp, listPtr->listVarName,
+ (char *) NULL, TCL_GLOBAL_ONLY);
+ int dummy;
+ if (listVarObj == NULL) {
+ listVarObj = (oldListObj ? oldListObj : Tcl_NewObj());
+ if (Tcl_SetVar2Ex(interp, listPtr->listVarName, (char *) NULL,
+ listVarObj, TCL_GLOBAL_ONLY|TCL_LEAVE_ERR_MSG)
+ == NULL) {
+ if (oldListObj == NULL) {
+ Tcl_DecrRefCount(listVarObj);
+ }
+ continue;
+ }
}
- if (Tcl_SetVar2Ex(interp, listPtr->listVarName, (char *)NULL,
- listVarObj, TCL_GLOBAL_ONLY) == NULL) {
- Tcl_DecrRefCount(listVarObj);
- Tk_RestoreSavedOptions(&savedOptions);
- return TCL_ERROR;
+ /* Make sure the object is a good list object */
+ if (Tcl_ListObjLength(listPtr->interp, listVarObj, &dummy)
+ != TCL_OK) {
+ Tcl_AppendResult(listPtr->interp,
+ ": invalid -listvariable value", (char *) NULL);
+ continue;
}
- }
- /* Make sure the object is a good list object */
- if (Tcl_ListObjLength(listPtr->interp, listVarObj, &dummy) != TCL_OK) {
- Tk_RestoreSavedOptions(&savedOptions);
- Tcl_AppendResult(listPtr->interp, ": invalid listvar value",
- (char *)NULL);
- return TCL_ERROR;
- }
-
- listPtr->listObj = listVarObj;
- Tcl_TraceVar(listPtr->interp, listPtr->listVarName,
- TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
- ListboxListVarProc, (ClientData) listPtr);
- } else {
- if (listPtr->listObj == NULL) {
+
+ listPtr->listObj = listVarObj;
+ Tcl_TraceVar(listPtr->interp, listPtr->listVarName,
+ TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+ ListboxListVarProc, (ClientData) listPtr);
+ } else if (listPtr->listObj == NULL) {
listPtr->listObj = Tcl_NewObj();
}
+ Tcl_IncrRefCount(listPtr->listObj);
+ if (oldListObj != NULL) {
+ Tcl_DecrRefCount(oldListObj);
+ }
+ break;
}
- Tcl_IncrRefCount(listPtr->listObj);
- if (oldListObj != NULL) {
- Tcl_DecrRefCount(oldListObj);
+ if (!error) {
+ Tk_FreeSavedOptions(&savedOptions);
}
/* Make sure that the list length is correct */
Tcl_ListObjLength(listPtr->interp, listPtr->listObj, &listPtr->nElements);
- Tk_FreeSavedOptions(&savedOptions);
- ListboxWorldChanged((ClientData) listPtr);
- return TCL_OK;
+ if (error) {
+ Tcl_SetObjResult(interp, errorResult);
+ Tcl_DecrRefCount(errorResult);
+ return TCL_ERROR;
+ } else {
+ ListboxWorldChanged((ClientData) listPtr);
+ return TCL_OK;
+ }
}
/*