Index: Modules/_tkinter.c =================================================================== --- Modules/_tkinter.c (revision 74322) +++ Modules/_tkinter.c (working copy) @@ -1025,12 +1025,12 @@ TkappObject *app = (TkappObject*)tkapp; if (value->typePtr == NULL) { + int len; + const char *s = Tcl_GetStringFromObj(value, &len); +#ifdef Py_USING_UNICODE + int i; /* If the result contains any bytes with the top bit set, it's UTF-8 and we should decode it to Unicode */ -#ifdef Py_USING_UNICODE - int i; - char *s = value->bytes; - int len = value->length; for (i = 0; i < len; i++) { if (value->bytes[i] & 0x80) break; @@ -1039,15 +1039,50 @@ if (i == value->length) result = PyString_FromStringAndSize(s, len); else { + /* Before converting from UTF-8 we must check if Tcl + * didn't let some 0xC0 0x80 slip out. If we happen + * to find any embedded nulls then we replace them + * by a 0. */ + int clen; + char *bstr, *cstr, *nullstr, *end; + + bstr = PyMem_Malloc(len); + if (!bstr) { + PyErr_NoMemory(); + goto finally; + } + Py_MEMCPY(bstr, s, len); + + clen = len - i; + end = bstr + len; + cstr = bstr + i; + + while ((nullstr = memchr(cstr, '\xC0', clen))) { + if (nullstr + 1 < end && + *(nullstr + 1) == '\x80') { + /* Found the bytes 0xC0 0x80, replace + * them by a 0 */ + nullstr[0] = '\0'; + memmove(nullstr + 1, nullstr + 2, + end - (nullstr + 2)); + len--; + end--; + } + clen -= (nullstr + 1) - cstr; + cstr = nullstr + 1; + } + /* Convert UTF-8 to Unicode string */ - result = PyUnicode_DecodeUTF8(s, len, "strict"); + result = PyUnicode_DecodeUTF8(bstr, len, "strict"); if (result == NULL) { PyErr_Clear(); - result = PyString_FromStringAndSize(s, len); + result = PyString_FromStringAndSize(bstr, len); } +finally: + PyMem_Free(bstr); } #else - result = PyString_FromStringAndSize(value->bytes, value->length); + result = PyString_FromStringAndSize(s, len); #endif return result; } @@ -2046,9 +2081,10 @@ * function or method. */ static int -PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) +PythonCmd(ClientData clientData, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[]) { - PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData; + PythonCmd_ClientData *data = clientData; PyObject *self, *func, *arg, *res; int i, rv; Tcl_Obj *obj_res; @@ -2061,13 +2097,16 @@ self = data->self; func = data->func; - /* Create argument list (argv1, ..., argvN) */ - if (!(arg = PyTuple_New(argc - 1))) + /* Create a tuple for holding all the objects, the first arg in obvj + * is not considered since it is the command name and is not used here. + */ + objc--; + if (!(arg = PyTuple_New(objc))) return PythonCmd_Error(interp); - for (i = 0; i < (argc - 1); i++) { - PyObject *s = PyString_FromString(argv[i + 1]); - if (!s || PyTuple_SetItem(arg, i, s)) { + for (i = 0; i < objc; i++) { + PyObject *ob = FromObj(self, objv[i + 1]); + if (!ob || PyTuple_SetItem(arg, i, ob)) { Py_DECREF(arg); return PythonCmd_Error(interp); } @@ -2127,7 +2166,7 @@ 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 @@ -2187,7 +2226,7 @@ #endif { ENTER_TCL - err = Tcl_CreateCommand( + err = Tcl_CreateObjCommand( Tkapp_Interp(self), cmdName, PythonCmd, (ClientData)data, PythonCmdDelete) == NULL; LEAVE_TCL