summaryrefslogtreecommitdiffstats
path: root/Modules/_tkinter.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_tkinter.c')
-rw-r--r--Modules/_tkinter.c164
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 */