Use object interface for global vars. Fixes #721171.
Also move complete processing of get/set/delvar calls to target thread.
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 822a0c3..303119f 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -1449,65 +1449,39 @@
 
 TCL_DECLARE_MUTEX(var_mutex)
 
-typedef CONST84_RETURN char* (*EventFunc1)(Tcl_Interp*, CONST char*, int);
-typedef CONST84_RETURN char* (*EventFunc2)(Tcl_Interp*, CONST char*, CONST char*, int);
-typedef CONST84_RETURN char* (*EventFunc3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int);
+typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
 typedef struct VarEvent {
 	Tcl_Event ev; /* must be first */
-	TkappObject *self;
-	char* arg1;
-	char* arg2;
-	char* arg3;
+	PyObject *self;
+	PyObject *args;
 	int flags;
-	EventFunc1 func1;
-	EventFunc2 func2;
-	EventFunc3 func3;
+	EventFunc func;
 	PyObject **res;
-	PyObject **exc;
+	PyObject **exc_type;
+	PyObject **exc_val;
 	Tcl_Condition cond;
-	int coderesult;
 } VarEvent;
 
-static const char*
+void
 var_perform(VarEvent *ev)
 {
-	if (!ev->arg2 && !ev->arg2)
-		return ev->func1(ev->self->interp, ev->arg1, ev->flags);
-	if (!ev->arg3)
-		return ev->func2(ev->self->interp, ev->arg1,
-				 ev->arg2, ev->flags);
-	return ev->func3(ev->self->interp, ev->arg1, ev->arg2,
-			 ev->arg3, ev->flags);
-}
-
-static void
-var_fill_result(VarEvent *ev, const char* res)
-{
-	if (ev->coderesult) {
-		if ((int)res != TCL_ERROR) {
-			Py_INCREF(Py_None);
-			*(ev->res) = Py_None;
-			return;
-		}
+	*(ev->res) = ev->func(ev->self, ev->args, ev->flags);
+	if (!*(ev->res)) {
+		PyObject *exc, *val, *tb;
+		PyErr_Fetch(&exc, &val, &tb);
+		PyErr_NormalizeException(&exc, &val, &tb);
+		*(ev->exc_type) = exc;
+		*(ev->exc_val) = val;
+		Py_DECREF(tb);
 	}
-	else if (res) {
-		*(ev->res) = PyString_FromString(res);
-		return;
-	}
-
-	*(ev->res) = NULL;
-	*(ev->exc) = PyObject_CallFunction(
-		Tkinter_TclError, "s",
-		Tcl_GetStringResult(ev->self->interp));
-
+		
 }
 
 static int
 var_proc(VarEvent* ev, int flags)
 {
-	const char *result = var_perform(ev);
 	ENTER_PYTHON
-	var_fill_result(ev, result);
+        var_perform(ev);
 	Tcl_MutexLock(&var_mutex);
 	Tcl_ConditionNotify(&ev->cond);
 	Tcl_MutexUnlock(&var_mutex);
@@ -1516,125 +1490,105 @@
 }
 
 static PyObject*
-var_invoke(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
-	   EventFunc1 func1, EventFunc2 func2, EventFunc3 func3,
-	   int coderesult)
+var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
 {
-	VarEvent _ev;
 	TkappObject *self = (TkappObject*)_self;
-	VarEvent *ev = self->threaded ? 
-		(VarEvent*)ckalloc(sizeof(VarEvent)) : &_ev;
-	PyObject *res, *exc;
-
-	ev->self = self;
-	ev->arg1 = arg1;
-	ev->arg2 = arg2;
-	ev->arg3 = arg3;
-	ev->flags = flags;
-	ev->func1 = func1;
-	ev->func2 = func2;
-	ev->func3 = func3;
-	ev->coderesult = coderesult;
-	ev->res = &res;
-	ev->exc = &exc;
 #ifdef WITH_THREAD
 	if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
+		TkappObject *self = (TkappObject*)_self;
+		VarEvent *ev;
+		PyObject *res, *exc_type, *exc_val;
+		
 		/* The current thread is not the interpreter thread.  Marshal
 		   the call to the interpreter thread, then wait for
 		   completion. */
-
 		if (!WaitForMainloop(self))
 			return NULL;
+
+		ev = (VarEvent*)ckalloc(sizeof(VarEvent));
+
+		ev->self = _self;
+		ev->args = args;
+		ev->flags = flags;
+		ev->func = func;
+		ev->res = &res;
+		ev->exc_type = &exc_type;
+		ev->exc_val = &exc_val;
 		ev->cond = NULL;
 		ev->ev.proc = (Tcl_EventProc*)var_proc;
 		Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
+		if (!res) {
+			PyErr_SetObject(exc_type, exc_val);
+			Py_DECREF(exc_type);
+			Py_DECREF(exc_val);
+			return NULL;
+		}
+		return res;
 	}
-	else 
 #endif
-	{
-		/* Tcl is not threaded, or this is the interpreter thread.  To
-		   perform the call, we must hold the TCL lock. To receive the
-		   results, we must also hold the Python lock. */
-		const char *result;
-		ENTER_TCL
-		result = var_perform(ev);
-		ENTER_OVERLAP
-		var_fill_result(ev, result);
-		LEAVE_OVERLAP_TCL
-	}
-	if (!res) {
-		PyErr_SetObject(Tkinter_TclError, exc);
-		return NULL;
-	}
-	return res;
-}
-
-static PyObject*
-var_invoke2(PyObject *_self, char* arg1, char* arg2, char* arg3, int flags,
-	   int (*func1)(Tcl_Interp*, CONST char*, int),
-	   int (*func2)(Tcl_Interp*, CONST char*, CONST char*, int),
-	   int (*func3)(Tcl_Interp*, CONST char*, CONST char*, CONST char*, int))
-{
-	return var_invoke(_self, arg1, arg2, arg3, flags,
-			  (EventFunc1)func1, (EventFunc2)func2,
-			  (EventFunc3)func3, 1);
+        /* Tcl is not threaded, or this is the interpreter thread. */
+	return func(_self, args, flags);
 }
 
 static PyObject *
 SetVar(PyObject *self, PyObject *args, int flags)
 {
-	char *name1, *name2, *s;
-	PyObject *res;
+	char *name1, *name2;
 	PyObject *newValue;
-	PyObject *tmp;
+	PyObject *res = NULL;
+	Tcl_Obj *newval, *ok;
 
-	tmp = PyList_New(0);
-	if (!tmp)
-		return NULL;
-	
 	if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
-		/* XXX Merge? */
-		s = AsString(newValue, tmp);
-		if (s == NULL)
+		/* XXX Acquire tcl lock??? */
+		newval = AsObj(newValue);
+		if (newval == NULL)
 			return NULL;
-		res = var_invoke(self, name1, s, NULL, flags,
-				 NULL, Tcl_SetVar, NULL, 0);
+		ENTER_TCL
+		ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL, 
+				   newval, flags);
+		ENTER_OVERLAP
+		if (!ok)
+			Tkinter_Error(self);
+		else {
+			res = Py_None;
+			Py_INCREF(res);
+		}
+		LEAVE_OVERLAP_TCL
 	}
 	else {
 		PyErr_Clear();
 		if (PyArg_ParseTuple(args, "ssO:setvar",
 				     &name1, &name2, &newValue)) {
-			s = AsString(newValue, tmp);
-			if (s == NULL)
-				return NULL;
-			res = var_invoke(self, name1, name2, s, flags,
-					 NULL, NULL, Tcl_SetVar2, 0);
+			/* XXX must hold tcl lock already??? */
+			newval = AsObj(newValue);
+			ENTER_TCL
+			ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
+			ENTER_OVERLAP
+			if (!ok)
+				Tkinter_Error(self);
+			else {
+				res = Py_None;
+				Py_INCREF(res);
+			}
+			LEAVE_OVERLAP_TCL
 		}
 		else {
-			Py_DECREF(tmp);
 			return NULL;
 		}
 	}
-	Py_DECREF(tmp);
-
-	if (!res)
-		return NULL;
-
-	Py_DECREF(res);
-	Py_INCREF(Py_None);
-	return Py_None;
+	return res;
 }
 
 static PyObject *
 Tkapp_SetVar(PyObject *self, PyObject *args)
 {
-	return SetVar(self, args, TCL_LEAVE_ERR_MSG);
+	return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
 }
 
 static PyObject *
 Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
 {
-	return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
+	return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
 }
 
 
@@ -1644,25 +1598,29 @@
 {
 	char *name1, *name2=NULL;
 	PyObject *res = NULL;
+	Tcl_Obj *tres;
 
 	if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
 		return NULL;
 
-	res = var_invoke(self, name1, name2, NULL, flags,
-			 Tcl_GetVar, Tcl_GetVar2, NULL, 0);
+	ENTER_TCL
+	tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
+	ENTER_OVERLAP
+	res = FromObj(self, tres);
+	LEAVE_OVERLAP_TCL
 	return res;
 }
 
 static PyObject *
 Tkapp_GetVar(PyObject *self, PyObject *args)
 {
-	return GetVar(self, args, TCL_LEAVE_ERR_MSG);
+	return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
 }
 
 static PyObject *
 Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
 {
-	return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
+	return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
 }
 
 
@@ -1671,26 +1629,35 @@
 UnsetVar(PyObject *self, PyObject *args, int flags)
 {
 	char *name1, *name2=NULL;
+	int code;
 	PyObject *res = NULL;
 
 	if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
 		return NULL;
 
-	res = var_invoke2(self, name1, name2, NULL, flags,
-			  Tcl_UnsetVar, Tcl_UnsetVar2, NULL);
+	ENTER_TCL
+	code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
+	ENTER_OVERLAP
+	if (code == TCL_ERROR)
+		res = Tkinter_Error(self);
+	else {
+		Py_INCREF(Py_None);
+		res = Py_None;
+	}
+	LEAVE_OVERLAP_TCL
 	return res;
 }
 
 static PyObject *
 Tkapp_UnsetVar(PyObject *self, PyObject *args)
 {
-	return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
+	return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
 }
 
 static PyObject *
 Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
 {
-	return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
+	return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
 }