diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2019-10-04 10:09:52 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-04 10:09:52 (GMT) |
commit | 06cb94bc8419b9a24df6b0d724fcd8e40c6971d6 (patch) | |
tree | 61dff1fe122eac251b43b7994f7deb40f1b9efcc /Modules | |
parent | 2290b23dfc9cce71ffc49bfcb6a5a16c570cefae (diff) | |
download | cpython-06cb94bc8419b9a24df6b0d724fcd8e40c6971d6.zip cpython-06cb94bc8419b9a24df6b0d724fcd8e40c6971d6.tar.gz cpython-06cb94bc8419b9a24df6b0d724fcd8e40c6971d6.tar.bz2 |
bpo-13153: Use OS native encoding for converting between Python and Tcl. (GH-16545)
On Windows use UTF-16 (or UTF-32 for 32-bit Tcl_UniChar) with the
"surrogatepass" error handler for converting to/from Tcl Unicode objects.
On Linux use UTF-8 with the "surrogateescape" error handler for converting
to/from Tcl String objects.
Converting strings from Tcl to Python and back now never fails
(except MemoryError).
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_tkinter.c | 375 |
1 files changed, 202 insertions, 173 deletions
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 94d5b64..c431d61 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -96,6 +96,24 @@ Copyright (C) 1994 Steen Lumholt. #endif /* HAVE_CREATEFILEHANDLER */ +/* Use OS native encoding for converting between Python strings and + Tcl objects. + On Windows use UTF-16 (or UTF-32 for 32-bit Tcl_UniChar) with the + "surrogatepass" error handler for converting to/from Tcl Unicode objects. + On Linux use UTF-8 with the "surrogateescape" error handler for converting + to/from Tcl String objects. */ +#ifdef MS_WINDOWS +#define USE_TCL_UNICODE 1 +#else +#define USE_TCL_UNICODE 0 +#endif + +#if PY_LITTLE_ENDIAN +#define NATIVE_BYTEORDER -1 +#else +#define NATIVE_BYTEORDER 1 +#endif + #ifdef MS_WINDOWS #include <conio.h> #define WAIT_FOR_STDIN @@ -290,7 +308,6 @@ typedef struct { } TkappObject; #define Tkapp_Interp(v) (((TkappObject *) (v))->interp) -#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v)) #define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \ (void *) v, Py_REFCNT(v))) @@ -311,10 +328,16 @@ static int tk_load_failed = 0; #endif +static PyObject *Tkapp_UnicodeResult(TkappObject *); + static PyObject * -Tkinter_Error(PyObject *v) +Tkinter_Error(TkappObject *self) { - PyErr_SetString(Tkinter_TclError, Tkapp_Result(v)); + PyObject *res = Tkapp_UnicodeResult(self); + if (res != NULL) { + PyErr_SetObject(Tkinter_TclError, res); + Py_DECREF(res); + } return NULL; } @@ -368,30 +391,35 @@ static PyObject * unicodeFromTclStringAndSize(const char *s, Py_ssize_t size) { PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL); - if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { - /* Tcl encodes null character as \xc0\x80 */ - if (memchr(s, '\xc0', size)) { - char *buf, *q; - const char *e = s + size; - PyErr_Clear(); - q = buf = (char *)PyMem_Malloc(size); - if (buf == NULL) { - PyErr_NoMemory(); - return NULL; - } - while (s != e) { - if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') { - *q++ = '\0'; - s += 2; - } - else - *q++ = *s++; + if (r != NULL || !PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) { + return r; + } + + char *buf = NULL; + PyErr_Clear(); + /* Tcl encodes null character as \xc0\x80 */ + if (memchr(s, '\xc0', size)) { + char *q; + const char *e = s + size; + q = buf = (char *)PyMem_Malloc(size); + if (buf == NULL) { + PyErr_NoMemory(); + return NULL; + } + while (s != e) { + if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') { + *q++ = '\0'; + s += 2; } - s = buf; - size = q - s; - r = PyUnicode_DecodeUTF8(s, size, NULL); - PyMem_Free(buf); + else + *q++ = *s++; } + s = buf; + size = q - s; + } + r = PyUnicode_DecodeUTF8(s, size, "surrogateescape"); + if (buf != NULL) { + PyMem_Free(buf); } return r; } @@ -406,8 +434,21 @@ static PyObject * unicodeFromTclObj(Tcl_Obj *value) { int len; - char *s = Tcl_GetStringFromObj(value, &len); +#if USE_TCL_UNICODE + int byteorder = NATIVE_BYTEORDER; + const Tcl_UniChar *u = Tcl_GetUnicodeFromObj(value, &len); + if (sizeof(Tcl_UniChar) == 2) + return PyUnicode_DecodeUTF16((const char *)u, len * 2, + "surrogatepass", &byteorder); + else if (sizeof(Tcl_UniChar) == 4) + return PyUnicode_DecodeUTF32((const char *)u, len * 4, + "surrogatepass", &byteorder); + else + Py_UNREACHABLE(); +#else + const char *s = Tcl_GetStringFromObj(value, &len); return unicodeFromTclStringAndSize(s, len); +#endif } @@ -746,7 +787,7 @@ Tkapp_New(const char *screenName, const char *className, #endif if (Tcl_AppInit(v->interp) != TCL_OK) { - PyObject *result = Tkinter_Error((PyObject *)v); + PyObject *result = Tkinter_Error(v); #ifdef TKINTER_PROTECT_LOADTK if (wantTk) { const char *_tkinter_tk_failed; @@ -817,12 +858,6 @@ PyTclObject_dealloc(PyTclObject *self) Py_DECREF(tp); } -static const char * -PyTclObject_TclString(PyObject *self) -{ - return Tcl_GetString(((PyTclObject*)self)->value); -} - /* Like _str, but create Unicode if necessary. */ PyDoc_STRVAR(PyTclObject_string__doc__, "the string representation of this object, either as str or bytes"); @@ -1048,53 +1083,51 @@ AsObj(PyObject *value) } if (PyUnicode_Check(value)) { - void *inbuf; - Py_ssize_t size; - int kind; - Tcl_UniChar *outbuf = NULL; - Py_ssize_t i; - size_t allocsize; - if (PyUnicode_READY(value) == -1) return NULL; - inbuf = PyUnicode_DATA(value); - size = PyUnicode_GET_LENGTH(value); - if (size == 0) - return Tcl_NewUnicodeObj((const void *)"", 0); + Py_ssize_t size = PyUnicode_GET_LENGTH(value); + if (size == 0) { + return Tcl_NewStringObj("", 0); + } if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) { PyErr_SetString(PyExc_OverflowError, "string is too long"); return NULL; } - kind = PyUnicode_KIND(value); - if (kind == sizeof(Tcl_UniChar)) - return Tcl_NewUnicodeObj(inbuf, (int)size); - allocsize = ((size_t)size) * sizeof(Tcl_UniChar); - outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize); - /* Else overflow occurred, and we take the next exit */ - if (!outbuf) { - PyErr_NoMemory(); - return NULL; + if (PyUnicode_IS_ASCII(value)) { + return Tcl_NewStringObj((const char *)PyUnicode_DATA(value), + (int)size); } - for (i = 0; i < size; i++) { - Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i); - /* We cannot test for sizeof(Tcl_UniChar) directly, - so we test for UTF-8 size instead. */ -#if TCL_UTF_MAX == 3 - if (ch >= 0x10000) { - /* Tcl doesn't do UTF-16, yet. */ - PyErr_Format(Tkinter_TclError, - "character U+%x is above the range " - "(U+0000-U+FFFF) allowed by Tcl", - ch); - PyMem_Free(outbuf); - return NULL; - } + + PyObject *encoded; +#if USE_TCL_UNICODE + if (sizeof(Tcl_UniChar) == 2) + encoded = _PyUnicode_EncodeUTF16(value, + "surrogatepass", NATIVE_BYTEORDER); + else if (sizeof(Tcl_UniChar) == 4) + encoded = _PyUnicode_EncodeUTF32(value, + "surrogatepass", NATIVE_BYTEORDER); + else + Py_UNREACHABLE(); +#else + encoded = _PyUnicode_AsUTF8String(value, "surrogateescape"); #endif - outbuf[i] = ch; + if (!encoded) { + return NULL; } - result = Tcl_NewUnicodeObj(outbuf, (int)size); - PyMem_Free(outbuf); + size = PyBytes_GET_SIZE(encoded); + if (size > INT_MAX) { + Py_DECREF(encoded); + PyErr_SetString(PyExc_OverflowError, "string is too long"); + return NULL; + } +#if USE_TCL_UNICODE + result = Tcl_NewUnicodeObj((const Tcl_UniChar *)PyBytes_AS_STRING(encoded), + (int)(size / sizeof(Tcl_UniChar))); +#else + result = Tcl_NewStringObj(PyBytes_AS_STRING(encoded), (int)size); +#endif + Py_DECREF(encoded); return result; } @@ -1113,7 +1146,7 @@ AsObj(PyObject *value) } static PyObject * -fromBoolean(PyObject* tkapp, Tcl_Obj *value) +fromBoolean(TkappObject *tkapp, Tcl_Obj *value) { int boolValue; if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR) @@ -1122,7 +1155,7 @@ fromBoolean(PyObject* tkapp, Tcl_Obj *value) } static PyObject* -fromWideIntObj(PyObject* tkapp, Tcl_Obj *value) +fromWideIntObj(TkappObject *tkapp, Tcl_Obj *value) { Tcl_WideInt wideValue; if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) { @@ -1138,7 +1171,7 @@ fromWideIntObj(PyObject* tkapp, Tcl_Obj *value) #ifdef HAVE_LIBTOMMAMTH static PyObject* -fromBignumObj(PyObject* tkapp, Tcl_Obj *value) +fromBignumObj(TkappObject *tkapp, Tcl_Obj *value) { mp_int bigValue; unsigned long numBytes; @@ -1174,32 +1207,31 @@ fromBignumObj(PyObject* tkapp, Tcl_Obj *value) #endif static PyObject* -FromObj(PyObject* tkapp, Tcl_Obj *value) +FromObj(TkappObject *tkapp, Tcl_Obj *value) { PyObject *result = NULL; - TkappObject *app = (TkappObject*)tkapp; Tcl_Interp *interp = Tkapp_Interp(tkapp); if (value->typePtr == NULL) { - return unicodeFromTclStringAndSize(value->bytes, value->length); + return unicodeFromTclObj(value); } - if (value->typePtr == app->BooleanType || - value->typePtr == app->OldBooleanType) { + if (value->typePtr == tkapp->BooleanType || + value->typePtr == tkapp->OldBooleanType) { return fromBoolean(tkapp, value); } - if (value->typePtr == app->ByteArrayType) { + if (value->typePtr == tkapp->ByteArrayType) { int size; char *data = (char*)Tcl_GetByteArrayFromObj(value, &size); return PyBytes_FromStringAndSize(data, size); } - if (value->typePtr == app->DoubleType) { + if (value->typePtr == tkapp->DoubleType) { return PyFloat_FromDouble(value->internalRep.doubleValue); } - if (value->typePtr == app->IntType) { + if (value->typePtr == tkapp->IntType) { long longValue; if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK) return PyLong_FromLong(longValue); @@ -1207,8 +1239,8 @@ FromObj(PyObject* tkapp, Tcl_Obj *value) fall through to wideInt handling. */ } - if (value->typePtr == app->IntType || - value->typePtr == app->WideIntType) { + if (value->typePtr == tkapp->IntType || + value->typePtr == tkapp->WideIntType) { result = fromWideIntObj(tkapp, value); if (result != NULL || PyErr_Occurred()) return result; @@ -1218,14 +1250,14 @@ FromObj(PyObject* tkapp, Tcl_Obj *value) } #ifdef HAVE_LIBTOMMAMTH - if (value->typePtr == app->IntType || - value->typePtr == app->WideIntType || - value->typePtr == app->BignumType) { + if (value->typePtr == tkapp->IntType || + value->typePtr == tkapp->WideIntType || + value->typePtr == tkapp->BignumType) { return fromBignumObj(tkapp, value); } #endif - if (value->typePtr == app->ListType) { + if (value->typePtr == tkapp->ListType) { int size; int i, status; PyObject *elem; @@ -1253,30 +1285,28 @@ FromObj(PyObject* tkapp, Tcl_Obj *value) return result; } - if (value->typePtr == app->ProcBodyType) { + if (value->typePtr == tkapp->ProcBodyType) { /* fall through: return tcl object. */ } - if (value->typePtr == app->StringType) { - return PyUnicode_FromKindAndData( - sizeof(Tcl_UniChar), Tcl_GetUnicode(value), - Tcl_GetCharLength(value)); + if (value->typePtr == tkapp->StringType) { + return unicodeFromTclObj(value); } #if TK_HEX_VERSION >= 0x08050000 - if (app->BooleanType == NULL && + if (tkapp->BooleanType == NULL && strcmp(value->typePtr->name, "booleanString") == 0) { /* booleanString type is not registered in Tcl */ - app->BooleanType = value->typePtr; + tkapp->BooleanType = value->typePtr; return fromBoolean(tkapp, value); } #endif #ifdef HAVE_LIBTOMMAMTH - if (app->BignumType == NULL && + if (tkapp->BignumType == NULL && strcmp(value->typePtr->name, "bignum") == 0) { /* bignum type is not registered in Tcl */ - app->BignumType = value->typePtr; + tkapp->BignumType = value->typePtr; return fromBignumObj(tkapp, value); } #endif @@ -1366,19 +1396,28 @@ finally: return NULL; } +/* Convert the results of a command call into a Python string. */ + +static PyObject * +Tkapp_UnicodeResult(TkappObject *self) +{ + return unicodeFromTclObj(Tcl_GetObjResult(self->interp)); +} + + /* Convert the results of a command call into a Python objects. */ -static PyObject* -Tkapp_CallResult(TkappObject *self) +static PyObject * +Tkapp_ObjectResult(TkappObject *self) { PyObject *res = NULL; Tcl_Obj *value = Tcl_GetObjResult(self->interp); - if(self->wantobjects) { + if (self->wantobjects) { /* Not sure whether the IncrRef is necessary, but something may overwrite the interpreter result while we are converting it. */ Tcl_IncrRefCount(value); - res = FromObj((PyObject*)self, value); + res = FromObj(self, value); Tcl_DecrRefCount(value); } else { res = unicodeFromTclObj(value); @@ -1410,15 +1449,13 @@ Tkapp_CallProc(Tkapp_CallEvent *e, int flags) i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags); ENTER_PYTHON if (i == TCL_ERROR) { - *(e->res) = NULL; - *(e->exc_type) = NULL; - *(e->exc_tb) = NULL; - *(e->exc_value) = PyObject_CallFunction( - Tkinter_TclError, "s", - Tcl_GetStringResult(e->self->interp)); + *(e->res) = Tkinter_Error(e->self); } else { - *(e->res) = Tkapp_CallResult(e->self); + *(e->res) = Tkapp_ObjectResult(e->self); + } + if (*(e->res) == NULL) { + PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb); } LEAVE_PYTHON @@ -1506,9 +1543,9 @@ Tkapp_Call(PyObject *selfptr, PyObject *args) ENTER_OVERLAP if (i == TCL_ERROR) - Tkinter_Error(selfptr); + Tkinter_Error(self); else - res = Tkapp_CallResult(self); + res = Tkapp_ObjectResult(self); LEAVE_OVERLAP_TCL @@ -1540,9 +1577,9 @@ _tkinter_tkapp_eval_impl(TkappObject *self, const char *script) err = Tcl_Eval(Tkapp_Interp(self), script); ENTER_OVERLAP if (err == TCL_ERROR) - res = Tkinter_Error((PyObject *)self); + res = Tkinter_Error(self); else - res = unicodeFromTclString(Tkapp_Result(self)); + res = Tkapp_UnicodeResult(self); LEAVE_OVERLAP_TCL return res; } @@ -1569,9 +1606,9 @@ _tkinter_tkapp_evalfile_impl(TkappObject *self, const char *fileName) err = Tcl_EvalFile(Tkapp_Interp(self), fileName); ENTER_OVERLAP if (err == TCL_ERROR) - res = Tkinter_Error((PyObject *)self); + res = Tkinter_Error(self); else - res = unicodeFromTclString(Tkapp_Result(self)); + res = Tkapp_UnicodeResult(self); LEAVE_OVERLAP_TCL return res; } @@ -1598,9 +1635,9 @@ _tkinter_tkapp_record_impl(TkappObject *self, const char *script) err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL); ENTER_OVERLAP if (err == TCL_ERROR) - res = Tkinter_Error((PyObject *)self); + res = Tkinter_Error(self); else - res = unicodeFromTclString(Tkapp_Result(self)); + res = Tkapp_UnicodeResult(self); LEAVE_OVERLAP_TCL return res; } @@ -1631,13 +1668,13 @@ _tkinter_tkapp_adderrorinfo_impl(TkappObject *self, const char *msg) /** Tcl Variable **/ -typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags); +typedef PyObject* (*EventFunc)(TkappObject *, PyObject *, int); TCL_DECLARE_MUTEX(var_mutex) typedef struct VarEvent { Tcl_Event ev; /* must be first */ - PyObject *self; + TkappObject *self; PyObject *args; int flags; EventFunc func; @@ -1692,7 +1729,7 @@ varname_converter(PyObject *in, void *_out) return 1; } if (PyTclObject_Check(in)) { - *out = PyTclObject_TclString(in); + *out = Tcl_GetString(((PyTclObject *)in)->value); return 1; } PyErr_Format(PyExc_TypeError, @@ -1750,7 +1787,7 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags) PyErr_NoMemory(); return NULL; } - ev->self = selfptr; + ev->self = self; ev->args = args; ev->flags = flags; ev->func = func; @@ -1770,11 +1807,11 @@ var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags) return res; } /* Tcl is not threaded, or this is the interpreter thread. */ - return func(selfptr, args, flags); + return func(self, args, flags); } static PyObject * -SetVar(PyObject *self, PyObject *args, int flags) +SetVar(TkappObject *self, PyObject *args, int flags) { const char *name1, *name2; PyObject *newValue; @@ -1843,7 +1880,7 @@ Tkapp_GlobalSetVar(PyObject *self, PyObject *args) static PyObject * -GetVar(PyObject *self, PyObject *args, int flags) +GetVar(TkappObject *self, PyObject *args, int flags) { const char *name1, *name2=NULL; PyObject *res = NULL; @@ -1858,10 +1895,9 @@ GetVar(PyObject *self, PyObject *args, int flags) tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags); ENTER_OVERLAP if (tres == NULL) { - PyErr_SetString(Tkinter_TclError, - Tcl_GetStringResult(Tkapp_Interp(self))); + Tkinter_Error(self); } else { - if (((TkappObject*)self)->wantobjects) { + if (self->wantobjects) { res = FromObj(self, tres); } else { @@ -1887,7 +1923,7 @@ Tkapp_GlobalGetVar(PyObject *self, PyObject *args) static PyObject * -UnsetVar(PyObject *self, PyObject *args, int flags) +UnsetVar(TkappObject *self, PyObject *args, int flags) { char *name1, *name2=NULL; int code; @@ -1959,7 +1995,7 @@ _tkinter_tkapp_getint(TkappObject *self, PyObject *arg) CHECK_STRING_LENGTH(s); value = Tcl_NewStringObj(s, -1); if (value == NULL) - return Tkinter_Error((PyObject *)self); + return Tkinter_Error(self); } /* Don't use Tcl_GetInt() because it returns ambiguous result for value in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform). @@ -1968,14 +2004,14 @@ _tkinter_tkapp_getint(TkappObject *self, PyObject *arg) value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform). */ #ifdef HAVE_LIBTOMMAMTH - result = fromBignumObj((PyObject *)self, value); + result = fromBignumObj(self, value); #else - result = fromWideIntObj((PyObject *)self, value); + result = fromWideIntObj(self, value); #endif Tcl_DecrRefCount(value); if (result != NULL || PyErr_Occurred()) return result; - return Tkinter_Error((PyObject *)self); + return Tkinter_Error(self); } /*[clinic input] @@ -2006,7 +2042,7 @@ _tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg) if (Tcl_GetDoubleFromObj(Tkapp_Interp(self), ((PyTclObject*)arg)->value, &v) == TCL_ERROR) - return Tkinter_Error((PyObject *)self); + return Tkinter_Error(self); return PyFloat_FromDouble(v); } @@ -2014,7 +2050,7 @@ _tkinter_tkapp_getdouble(TkappObject *self, PyObject *arg) return NULL; CHECK_STRING_LENGTH(s); if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR) - return Tkinter_Error((PyObject *)self); + return Tkinter_Error(self); return PyFloat_FromDouble(v); } @@ -2041,7 +2077,7 @@ _tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg) if (Tcl_GetBooleanFromObj(Tkapp_Interp(self), ((PyTclObject*)arg)->value, &v) == TCL_ERROR) - return Tkinter_Error((PyObject *)self); + return Tkinter_Error(self); return PyBool_FromLong(v); } @@ -2049,7 +2085,7 @@ _tkinter_tkapp_getboolean(TkappObject *self, PyObject *arg) return NULL; CHECK_STRING_LENGTH(s); if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR) - return Tkinter_Error((PyObject *)self); + return Tkinter_Error(self); return PyBool_FromLong(v); } @@ -2075,9 +2111,9 @@ _tkinter_tkapp_exprstring_impl(TkappObject *self, const char *s) retval = Tcl_ExprString(Tkapp_Interp(self), s); ENTER_OVERLAP if (retval == TCL_ERROR) - res = Tkinter_Error((PyObject *)self); + res = Tkinter_Error(self); else - res = unicodeFromTclString(Tkapp_Result(self)); + res = Tkapp_UnicodeResult(self); LEAVE_OVERLAP_TCL return res; } @@ -2105,7 +2141,7 @@ _tkinter_tkapp_exprlong_impl(TkappObject *self, const char *s) retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v); ENTER_OVERLAP if (retval == TCL_ERROR) - res = Tkinter_Error((PyObject *)self); + res = Tkinter_Error(self); else res = PyLong_FromLong(v); LEAVE_OVERLAP_TCL @@ -2136,7 +2172,7 @@ _tkinter_tkapp_exprdouble_impl(TkappObject *self, const char *s) ENTER_OVERLAP PyFPE_END_PROTECT(retval) if (retval == TCL_ERROR) - res = Tkinter_Error((PyObject *)self); + res = Tkinter_Error(self); else res = PyFloat_FromDouble(v); LEAVE_OVERLAP_TCL @@ -2165,7 +2201,7 @@ _tkinter_tkapp_exprboolean_impl(TkappObject *self, const char *s) retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v); ENTER_OVERLAP if (retval == TCL_ERROR) - res = Tkinter_Error((PyObject *)self); + res = Tkinter_Error(self); else res = PyLong_FromLong(v); LEAVE_OVERLAP_TCL @@ -2198,12 +2234,12 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg) if (Tcl_ListObjGetElements(Tkapp_Interp(self), ((PyTclObject*)arg)->value, &objc, &objv) == TCL_ERROR) { - return Tkinter_Error((PyObject *)self); + return Tkinter_Error(self); } if (!(v = PyTuple_New(objc))) return NULL; for (i = 0; i < objc; i++) { - PyObject *s = FromObj((PyObject*)self, objv[i]); + PyObject *s = FromObj(self, objv[i]); if (!s) { Py_DECREF(v); return NULL; @@ -2231,7 +2267,7 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg) if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR) { PyMem_Free(list); - return Tkinter_Error((PyObject *)self); + return Tkinter_Error(self); } if (!(v = PyTuple_New(argc))) @@ -2275,16 +2311,16 @@ _tkinter_tkapp_split(TkappObject *self, PyObject *arg) int i; if (Tcl_ListObjGetElements(Tkapp_Interp(self), value, &objc, &objv) == TCL_ERROR) { - return FromObj((PyObject*)self, value); + return FromObj(self, value); } if (objc == 0) return PyUnicode_FromString(""); if (objc == 1) - return FromObj((PyObject*)self, objv[0]); + return FromObj(self, objv[0]); if (!(v = PyTuple_New(objc))) return NULL; for (i = 0; i < objc; i++) { - PyObject *s = FromObj((PyObject*)self, objv[i]); + PyObject *s = FromObj(self, objv[i]); if (!s) { Py_DECREF(v); return NULL; @@ -2331,34 +2367,31 @@ PythonCmd_Error(Tcl_Interp *interp) * function or method. */ static int -PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[]) +PythonCmd(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *const objv[]) { PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData; - PyObject *func, *arg, *res; - int i, rv; + PyObject *args, *res; + int i; Tcl_Obj *obj_res; ENTER_PYTHON - /* TBD: no error checking here since we know, via the - * Tkapp_CreateCommand() that the client data is a two-tuple - */ - func = data->func; - - /* Create argument list (argv1, ..., argvN) */ - if (!(arg = PyTuple_New(argc - 1))) + /* Create argument tuple (objv1, ..., objvN) */ + if (!(args = PyTuple_New(objc - 1))) return PythonCmd_Error(interp); - for (i = 0; i < (argc - 1); i++) { - PyObject *s = unicodeFromTclString(argv[i + 1]); + for (i = 0; i < (objc - 1); i++) { + PyObject *s = unicodeFromTclObj(objv[i + 1]); if (!s) { - Py_DECREF(arg); + Py_DECREF(args); return PythonCmd_Error(interp); } - PyTuple_SET_ITEM(arg, i, s); + PyTuple_SET_ITEM(args, i, s); } - res = PyObject_Call(func, arg, NULL); - Py_DECREF(arg); + + res = PyObject_Call(data->func, args, NULL); + Py_DECREF(args); if (res == NULL) return PythonCmd_Error(interp); @@ -2368,18 +2401,15 @@ PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[ Py_DECREF(res); return PythonCmd_Error(interp); } - else { - Tcl_SetObjResult(interp, obj_res); - rv = TCL_OK; - } - + Tcl_SetObjResult(interp, obj_res); Py_DECREF(res); LEAVE_PYTHON - return rv; + return TCL_OK; } + static void PythonCmdDelete(ClientData clientData) { @@ -2411,7 +2441,7 @@ static int Tkapp_CommandProc(CommandEvent *ev, int flags) { if (ev->create) - *ev->status = Tcl_CreateCommand( + *ev->status = Tcl_CreateObjCommand( ev->interp, ev->name, PythonCmd, ev->data, PythonCmdDelete) == NULL; else @@ -2477,7 +2507,7 @@ _tkinter_tkapp_createcommand_impl(TkappObject *self, const char *name, else { ENTER_TCL - err = Tcl_CreateCommand( + err = Tcl_CreateObjCommand( Tkapp_Interp(self), name, PythonCmd, (ClientData)data, PythonCmdDelete) == NULL; LEAVE_TCL @@ -2953,9 +2983,9 @@ _tkinter_tkapp_loadtk_impl(TkappObject *self) if (err == TCL_ERROR) { /* This sets an exception, but we cannot return right away because we need to exit the overlap first. */ - Tkinter_Error((PyObject *)self); + Tkinter_Error(self); } else { - _tk_exists = Tkapp_Result(self); + _tk_exists = Tcl_GetStringResult(Tkapp_Interp(self)); } LEAVE_OVERLAP_TCL if (err == TCL_ERROR) { @@ -2963,8 +2993,7 @@ _tkinter_tkapp_loadtk_impl(TkappObject *self) } if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) { if (Tk_Init(interp) == TCL_ERROR) { - PyErr_SetString(Tkinter_TclError, - Tcl_GetStringResult(Tkapp_Interp(self))); + Tkinter_Error(self); #ifdef TKINTER_PROTECT_LOADTK tk_load_failed = 1; #endif |