diff options
Diffstat (limited to 'Modules/_tkinter.c')
-rw-r--r-- | Modules/_tkinter.c | 164 |
1 files changed, 80 insertions, 84 deletions
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 6d777d3..d5396f6 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -9,8 +9,8 @@ Copyright (C) 1994 Steen Lumholt. /* TCL/TK VERSION INFO: - Only Tcl/Tk 8.3.1 and later are supported. Older versions are not - supported. Use Python 2.6 or older if you cannot upgrade your + Only Tcl/Tk 8.4 and later are supported. Older versions are not + supported. Use Python 3.4 or older if you cannot upgrade your Tcl/Tk libraries. */ @@ -36,13 +36,6 @@ Copyright (C) 1994 Steen Lumholt. #define CHECK_SIZE(size, elemsize) \ ((size_t)(size) <= Py_MAX((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize))) -/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately, - making _tkinter correct for this API means to break earlier - versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and - earlier versions. Once Tcl releases before 8.4 don't need to be supported - anymore, this should go. */ -#define USE_COMPAT_CONST - /* If Tcl is compiled for threads, we must also define TCL_THREAD. We define it always; if Tcl is not threaded, the thread functions in Tcl are empty. */ @@ -58,15 +51,8 @@ Copyright (C) 1994 Steen Lumholt. #include "tkinter.h" -/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */ -#ifndef CONST84_RETURN -#define CONST84_RETURN -#undef CONST -#define CONST -#endif - -#if TK_VERSION_HEX < 0x08030102 -#error "Tk older than 8.3.1 not supported" +#if TK_VERSION_HEX < 0x08040002 +#error "Tk older than 8.4 not supported" #endif #if !(defined(MS_WINDOWS) || defined(__CYGWIN__)) @@ -242,13 +228,13 @@ typedef struct { int dispatching; /* We cannot include tclInt.h, as this is internal. So we cache interesting types here. */ - Tcl_ObjType *BooleanType; - Tcl_ObjType *ByteArrayType; - Tcl_ObjType *DoubleType; - Tcl_ObjType *IntType; - Tcl_ObjType *ListType; - Tcl_ObjType *ProcBodyType; - Tcl_ObjType *StringType; + const Tcl_ObjType *BooleanType; + const Tcl_ObjType *ByteArrayType; + const Tcl_ObjType *DoubleType; + const Tcl_ObjType *IntType; + const Tcl_ObjType *ListType; + const Tcl_ObjType *ProcBodyType; + const Tcl_ObjType *StringType; } TkappObject; #define Tkapp_Interp(v) (((TkappObject *) (v))->interp) @@ -376,10 +362,10 @@ unicodeFromTclObj(Tcl_Obj *value) static PyObject * -Split(char *list) +Split(const char *list) { int argc; - char **argv; + const char **argv; PyObject *v; if (list == NULL) { @@ -459,9 +445,29 @@ SplitObj(PyObject *arg) return result; /* Fall through, returning arg. */ } + else if (PyList_Check(arg)) { + int i, size; + PyObject *elem, *newelem, *result; + + size = PyList_GET_SIZE(arg); + result = PyTuple_New(size); + if (!result) + return NULL; + /* Recursively invoke SplitObj for all list items. */ + for(i = 0; i < size; i++) { + elem = PyList_GET_ITEM(arg, i); + newelem = SplitObj(elem); + if (!newelem) { + Py_XDECREF(result); + return NULL; + } + PyTuple_SetItem(result, i, newelem); + } + return result; + } else if (PyUnicode_Check(arg)) { int argc; - char **argv; + const char **argv; char *list = PyUnicode_AsUTF8(arg); if (list == NULL || @@ -476,7 +482,7 @@ SplitObj(PyObject *arg) } else if (PyBytes_Check(arg)) { int argc; - char **argv; + const char **argv; char *list = PyBytes_AsString(arg); if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) { @@ -543,8 +549,9 @@ static void EnableEventHook(void); /* Forward */ static void DisableEventHook(void); /* Forward */ static TkappObject * -Tkapp_New(char *screenName, char *className, - int interactive, int wantobjects, int wantTk, int sync, char *use) +Tkapp_New(const char *screenName, const char *className, + int interactive, int wantobjects, int wantTk, int sync, + const char *use) { TkappObject *v; char *argv0; @@ -598,7 +605,7 @@ Tkapp_New(char *screenName, char *className, Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY); /* This is used to get the application class for Tk 4.1 and up */ - argv0 = (char*)attemptckalloc(strlen(className) + 1); + argv0 = (char*)PyMem_Malloc(strlen(className) + 1); if (!argv0) { PyErr_NoMemory(); Py_DECREF(v); @@ -609,7 +616,7 @@ Tkapp_New(char *screenName, char *className, if (Py_ISUPPER(Py_CHARMASK(argv0[0]))) argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0])); Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY); - ckfree(argv0); + PyMem_Free(argv0); if (! wantTk) { Tcl_SetVar(v->interp, @@ -632,7 +639,7 @@ Tkapp_New(char *screenName, char *className, if (use) len += strlen(use) + sizeof "-use "; - args = (char*)attemptckalloc(len); + args = (char*)PyMem_Malloc(len); if (!args) { PyErr_NoMemory(); Py_DECREF(v); @@ -650,7 +657,7 @@ Tkapp_New(char *screenName, char *className, } Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY); - ckfree(args); + PyMem_Free(args); } if (Tcl_AppInit(v->interp) != TCL_OK) { @@ -894,24 +901,28 @@ AsObj(PyObject *value) } else if (PyFloat_Check(value)) return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value)); - else if (PyTuple_Check(value)) { + else if (PyTuple_Check(value) || PyList_Check(value)) { Tcl_Obj **argv; Py_ssize_t size, i; - size = PyTuple_Size(value); + size = PySequence_Fast_GET_SIZE(value); if (size == 0) return Tcl_NewListObj(0, NULL); if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) { - PyErr_SetString(PyExc_OverflowError, "tuple is too long"); + PyErr_SetString(PyExc_OverflowError, + PyTuple_Check(value) ? "tuple is too long" : + "list is too long"); return NULL; } - argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *)); - if(!argv) - return 0; + argv = (Tcl_Obj **) PyMem_Malloc(((size_t)size) * sizeof(Tcl_Obj *)); + if (!argv) { + PyErr_NoMemory(); + return NULL; + } for (i = 0; i < size; i++) - argv[i] = AsObj(PyTuple_GetItem(value,i)); - result = Tcl_NewListObj(PyTuple_Size(value), argv); - ckfree(FREECAST argv); + argv[i] = AsObj(PySequence_Fast_GET_ITEM(value,i)); + result = Tcl_NewListObj(size, argv); + PyMem_Free(argv); return result; } else if (PyUnicode_Check(value)) { @@ -937,7 +948,7 @@ AsObj(PyObject *value) if (kind == sizeof(Tcl_UniChar)) return Tcl_NewUnicodeObj(inbuf, size); allocsize = ((size_t)size) * sizeof(Tcl_UniChar); - outbuf = (Tcl_UniChar*)attemptckalloc(allocsize); + outbuf = (Tcl_UniChar*)PyMem_Malloc(allocsize); /* Else overflow occurred, and we take the next exit */ if (!outbuf) { PyErr_NoMemory(); @@ -954,14 +965,14 @@ AsObj(PyObject *value) "character U+%x is above the range " "(U+0000-U+FFFF) allowed by Tcl", ch); - ckfree(FREECAST outbuf); + PyMem_Free(outbuf); return NULL; } #endif outbuf[i] = ch; } result = Tcl_NewUnicodeObj(outbuf, size); - ckfree(FREECAST outbuf); + PyMem_Free(outbuf); return result; } else if(PyTclObject_Check(value)) { @@ -1073,7 +1084,7 @@ Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc) for (i = 0; i < objc; i++) Tcl_DecrRefCount(objv[i]); if (objv != objStore) - ckfree(FREECAST objv); + PyMem_Free(objv); } /* Convert Python objects to Tcl objects. This must happen in the @@ -1087,7 +1098,7 @@ Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc) if (args == NULL) /* do nothing */; - else if (!PyTuple_Check(args)) { + else if (!(PyTuple_Check(args) || PyList_Check(args))) { objv[0] = AsObj(args); if (objv[0] == 0) goto finally; @@ -1095,14 +1106,16 @@ Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc) Tcl_IncrRefCount(objv[0]); } else { - objc = PyTuple_Size(args); + objc = PySequence_Fast_GET_SIZE(args); if (objc > ARGSZ) { if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) { - PyErr_SetString(PyExc_OverflowError, "tuple is too long"); + PyErr_SetString(PyExc_OverflowError, + PyTuple_Check(args) ? "tuple is too long" : + "list is too long"); return NULL; } - objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *)); + objv = (Tcl_Obj **)PyMem_Malloc(((size_t)objc) * sizeof(Tcl_Obj *)); if (objv == NULL) { PyErr_NoMemory(); objc = 0; @@ -1111,7 +1124,7 @@ Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc) } for (i = 0; i < objc; i++) { - PyObject *v = PyTuple_GetItem(args, i); + PyObject *v = PySequence_Fast_GET_ITEM(args, i); if (v == Py_None) { objc = i; break; @@ -1411,8 +1424,8 @@ varname_converter(PyObject *in, void *_out) return 0; } s = PyBytes_AsString(in); - if (strlen(s) != PyBytes_Size(in)) { - PyErr_SetString(PyExc_ValueError, "null byte in bytes object"); + if (strlen(s) != (size_t)PyBytes_Size(in)) { + PyErr_SetString(PyExc_ValueError, "embedded null byte"); return 0; } *out = s; @@ -1428,8 +1441,8 @@ varname_converter(PyObject *in, void *_out) PyErr_SetString(PyExc_OverflowError, "string is too long"); return 0; } - if (strlen(s) != size) { - PyErr_SetString(PyExc_ValueError, "null character in string"); + if (strlen(s) != (size_t)size) { + PyErr_SetString(PyExc_ValueError, "embedded null character"); return 0; } *out = s; @@ -1844,7 +1857,7 @@ Tkapp_SplitList(PyObject *self, PyObject *args) { char *list; int argc; - char **argv; + const char **argv; PyObject *arg, *v; int i; @@ -1873,6 +1886,9 @@ Tkapp_SplitList(PyObject *self, PyObject *args) Py_INCREF(arg); return arg; } + if (PyList_Check(arg)) { + return PySequence_Tuple(arg); + } if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list)) return NULL; @@ -1934,7 +1950,7 @@ Tkapp_Split(PyObject *self, PyObject *args) } return v; } - if (PyTuple_Check(arg)) + if (PyTuple_Check(arg) || PyList_Check(arg)) return SplitObj(arg); if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list)) @@ -1968,7 +1984,7 @@ PythonCmd_Error(Tcl_Interp *interp) * function or method. */ static int -PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[]) +PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, const char *argv[]) { PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData; PyObject *func, *arg, *res; @@ -2736,35 +2752,15 @@ _flatten1(FlattenContext* context, PyObject* item, int depth) PyErr_SetString(PyExc_ValueError, "nesting too deep in _flatten"); return 0; - } else if (PyList_Check(item)) { - size = PyList_GET_SIZE(item); + } else if (PyTuple_Check(item) || PyList_Check(item)) { + size = PySequence_Fast_GET_SIZE(item); /* preallocate (assume no nesting) */ if (context->size + size > context->maxsize && !_bump(context, size)) return 0; /* copy items to output tuple */ for (i = 0; i < size; i++) { - PyObject *o = PyList_GET_ITEM(item, i); - if (PyList_Check(o) || PyTuple_Check(o)) { - if (!_flatten1(context, o, depth + 1)) - return 0; - } else if (o != Py_None) { - if (context->size + 1 > context->maxsize && - !_bump(context, 1)) - return 0; - Py_INCREF(o); - PyTuple_SET_ITEM(context->tuple, - context->size++, o); - } - } - } else if (PyTuple_Check(item)) { - /* same, for tuples */ - size = PyTuple_GET_SIZE(item); - if (context->size + size > context->maxsize && - !_bump(context, size)) - return 0; - for (i = 0; i < size; i++) { - PyObject *o = PyTuple_GET_ITEM(item, i); + PyObject *o = PySequence_Fast_GET_ITEM(item, i); if (PyList_Check(o) || PyTuple_Check(o)) { if (!_flatten1(context, o, depth + 1)) return 0; @@ -2822,7 +2818,7 @@ Tkinter_Create(PyObject *self, PyObject *args) try getting rid of it. */ char *className = NULL; int interactive = 0; - int wantobjects = 0; + int wantobjects = 1; int wantTk = 1; /* If false, then Tk_Init() doesn't get called */ int sync = 0; /* pass -sync to wish */ char *use = NULL; /* pass -use to wish */ |