1
/***********************************************************
2
Copyright (C) 1994 Steen Lumholt.
6
******************************************************************/
8
/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
10
/* TCL/TK VERSION INFO:
12
Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
13
supported. Use Python 2.6 or older if you cannot upgrade your
17
/* XXX Further speed-up ideas, involving Tcl 8.0 features:
19
- Register a new Tcl type, "Python callable", which can be called more
20
efficiently and passed to Tcl_EvalObj() directly (if this is possible).
38
/* Allow using this code in Python 2.[12] */
40
#define PyDoc_STRVAR(name,str) static char name[] = str
43
#ifndef PyMODINIT_FUNC
44
#define PyMODINIT_FUNC void
48
#define PyBool_Check(o) 0
49
#define PyBool_FromLong PyLong_FromLong
52
/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
53
making _tkinter correct for this API means to break earlier
54
versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
55
earlier versions. Once Tcl releases before 8.4 don't need to be supported
56
anymore, this should go. */
57
#define USE_COMPAT_CONST
59
/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
60
it always; if Tcl is not threaded, the thread functions in
72
/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
73
#ifndef CONST84_RETURN
74
#define CONST84_RETURN
79
#if TK_VERSION_HEX < 0x08030102
80
#error "Tk older than 8.3.1 not supported"
83
/* Unicode conversion assumes that Tcl_UniChar is two bytes.
84
We cannot test this directly, so we test UTF-8 size instead,
85
expecting that TCL_UTF_MAX is changed if Tcl ever supports
86
either UTF-16 or UCS-4.
87
Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
88
Tcl_Unichar. This is also ok as long as Python uses UCS-4,
91
#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
92
#error "unsupported Tcl configuration"
95
#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
96
#define HAVE_CREATEFILEHANDLER
99
#ifdef HAVE_CREATEFILEHANDLER
101
/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
102
with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
104
# ifdef TCL_WIN_SOCKET
105
# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
107
# define TCL_UNIX_FD 1
111
/* Tcl_CreateFileHandler() changed several times; these macros deal with the
112
messiness. In Tcl 8.0 and later, it is not available on Windows (and on
113
Unix, only because Jack added it back); when available on Windows, it only
114
applies to sockets. */
117
#define FHANDLETYPE TCL_WIN_SOCKET
119
#define FHANDLETYPE TCL_UNIX_FD
122
/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
123
which uses this to handle Tcl events while the user is typing commands. */
125
#if FHANDLETYPE == TCL_UNIX_FD
126
#define WAIT_FOR_STDIN
129
#endif /* HAVE_CREATEFILEHANDLER */
133
#define WAIT_FOR_STDIN
138
/* The threading situation is complicated. Tcl is not thread-safe, except
139
when configured with --enable-threads.
140
So we need to use a lock around all uses of Tcl. Previously, the Python
141
interpreter lock was used for this. However, this causes problems when
142
other Python threads need to run while Tcl is blocked waiting for events.
144
To solve this problem, a separate lock for Tcl is introduced. Holding it
145
is incompatible with holding Python's interpreter lock. The following four
146
macros manipulate both locks together.
148
ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
149
Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
150
that could call an event handler, or otherwise affect the state of a Tcl
151
interpreter. These assume that the surrounding code has the Python
152
interpreter lock; inside the brackets, the Python interpreter lock has been
153
released and the lock for Tcl has been acquired.
155
Sometimes, it is necessary to have both the Python lock and the Tcl lock.
156
(For example, when transferring data from the Tcl interpreter result to a
157
Python string object.) This can be done by using different macros to close
158
the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
159
the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
160
releases the Tcl lock.
162
By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
163
handlers when the handler needs to use Python. Such event handlers are
164
entered while the lock for Tcl is held; the event handler presumably needs
165
to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
166
the Python interpreter lock, restoring the appropriate thread state, and
167
LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
168
for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
169
the code between ENTER_PYTHON and LEAVE_PYTHON.
171
These locks expand to several statements and brackets; they should not be
172
used in branches of if statements and the like.
174
If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
175
only valid in the thread that created it, and all Tk activity must happen in this
176
thread, also. That means that the mainloop must be invoked in the thread that
177
created the interpreter. Invoking commands from other threads is possible;
178
_tkinter will queue an event for the interpreter thread, which will then
179
execute the command and pass back the result. If the main thread is not in the
180
mainloop, and invoking commands causes an exception; if the main loop is running
181
but not processing events, the command invocation will block.
183
In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
184
anymore, since multiple Tcl interpreters may simultaneously dispatch in different
185
threads. So we use the Tcl TLS API.
189
static PyThread_type_lock tcl_lock = 0;
192
static Tcl_ThreadDataKey state_key;
193
typedef PyThreadState *ThreadSpecificData;
194
#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
196
static PyThreadState *tcl_tstate = NULL;
200
{ PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
201
if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
204
tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
206
#define ENTER_OVERLAP \
209
#define LEAVE_OVERLAP_TCL \
210
tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
212
#define ENTER_PYTHON \
213
{ PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
214
if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
216
#define LEAVE_PYTHON \
217
{ PyThreadState *tstate = PyEval_SaveThread(); \
218
if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
220
#define CHECK_TCL_APPARTMENT \
221
if (((TkappObject *)self)->threaded && \
222
((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
223
PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
231
#define ENTER_OVERLAP
232
#define LEAVE_OVERLAP_TCL
235
#define CHECK_TCL_APPARTMENT
240
#define FREECAST (char *)
243
/**** Tkapp Object Declaration ****/
245
static PyTypeObject Tkapp_Type;
251
int threaded; /* True if tcl_platform[threaded] */
252
Tcl_ThreadId thread_id;
254
/* We cannot include tclInt.h, as this is internal.
255
So we cache interesting types here. */
256
Tcl_ObjType *BooleanType;
257
Tcl_ObjType *ByteArrayType;
258
Tcl_ObjType *DoubleType;
259
Tcl_ObjType *IntType;
260
Tcl_ObjType *ListType;
261
Tcl_ObjType *ProcBodyType;
262
Tcl_ObjType *StringType;
265
#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
266
#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
267
#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
269
#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
270
(void *) v, Py_REFCNT(v)))
274
/**** Error Handling ****/
276
static PyObject *Tkinter_TclError;
277
static int quitMainLoop = 0;
278
static int errorInCmd = 0;
279
static PyObject *excInCmd;
280
static PyObject *valInCmd;
281
static PyObject *trbInCmd;
283
#ifdef TKINTER_PROTECT_LOADTK
284
static int tk_load_failed;
289
Tkinter_Error(PyObject *v)
291
PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
299
static int Tkinter_busywaitinterval = 20;
304
/* Millisecond sleep() for Unix platforms. */
309
/* XXX Too bad if you don't have select(). */
311
t.tv_sec = milli/1000;
312
t.tv_usec = (milli%1000) * 1000;
313
select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
315
#endif /* MS_WINDOWS */
317
/* Wait up to 1s for the mainloop to come up. */
320
WaitForMainloop(TkappObject* self)
323
for (i = 0; i < 10; i++) {
324
if (self->dispatching)
326
Py_BEGIN_ALLOW_THREADS
330
if (self->dispatching)
332
PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
335
#endif /* WITH_THREAD */
339
AsString(PyObject *value, PyObject *tmp)
341
if (PyBytes_Check(value))
342
return PyBytes_AsString(value);
343
else if (PyUnicode_Check(value)) {
344
PyObject *v = PyUnicode_AsUTF8String(value);
347
if (PyList_Append(tmp, v) != 0) {
352
return PyBytes_AsString(v);
355
PyObject *v = PyObject_Str(value);
358
if (PyList_Append(tmp, v) != 0) {
363
return PyBytes_AsString(v);
372
Merge(PyObject *args)
374
PyObject *tmp = NULL;
375
char *argvStore[ARGSZ];
379
int argc = 0, fvc = 0, i;
382
if (!(tmp = PyList_New(0)))
391
else if (!PyTuple_Check(args)) {
394
if (!(argv[0] = AsString(args, tmp)))
398
argc = PyTuple_Size(args);
401
argv = (char **)ckalloc(argc * sizeof(char *));
402
fv = (int *)ckalloc(argc * sizeof(int));
403
if (argv == NULL || fv == NULL) {
409
for (i = 0; i < argc; i++) {
410
PyObject *v = PyTuple_GetItem(args, i);
411
if (PyTuple_Check(v)) {
413
if (!(argv[i] = Merge(v)))
417
else if (v == Py_None) {
423
if (!(argv[i] = AsString(v, tmp)))
429
res = Tcl_Merge(argc, argv);
431
PyErr_SetString(Tkinter_TclError, "merge failed");
434
for (i = 0; i < fvc; i++)
438
if (argv != argvStore)
439
ckfree(FREECAST argv);
461
if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
463
* Could be a quoted string containing funnies, e.g. {"}.
464
* Return the string itself.
466
return PyUnicode_FromString(list);
470
v = PyUnicode_FromString("");
472
v = PyUnicode_FromString(argv[0]);
473
else if ((v = PyTuple_New(argc)) != NULL) {
477
for (i = 0; i < argc; i++) {
478
if ((w = Split(argv[i])) == NULL) {
483
PyTuple_SetItem(v, i, w);
486
Tcl_Free(FREECAST argv);
490
/* In some cases, Tcl will still return strings that are supposed to be
491
lists. SplitObj walks through a nested tuple, finding string objects that
495
SplitObj(PyObject *arg)
497
if (PyTuple_Check(arg)) {
499
PyObject *elem, *newelem, *result;
501
size = PyTuple_Size(arg);
503
/* Recursively invoke SplitObj for all tuple items.
504
If this does not return a new object, no action is
506
for(i = 0; i < size; i++) {
507
elem = PyTuple_GetItem(arg, i);
508
newelem = SplitObj(elem);
515
if (newelem == elem) {
519
result = PyTuple_New(size);
522
for(k = 0; k < i; k++) {
523
elem = PyTuple_GetItem(arg, k);
525
PyTuple_SetItem(result, k, elem);
528
PyTuple_SetItem(result, i, newelem);
532
/* Fall through, returning arg. */
534
else if (PyBytes_Check(arg)) {
537
char *list = PyBytes_AsString(arg);
539
if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
543
Tcl_Free(FREECAST argv);
545
return Split(PyBytes_AsString(arg));
546
/* Fall through, returning arg. */
553
/**** Tkapp Object ****/
557
Tcl_AppInit(Tcl_Interp *interp)
559
const char * _tkinter_skip_tk_init;
561
if (Tcl_Init(interp) == TCL_ERROR) {
562
PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
566
_tkinter_skip_tk_init = Tcl_GetVar(interp,
567
"_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
568
if (_tkinter_skip_tk_init != NULL &&
569
strcmp(_tkinter_skip_tk_init, "1") == 0) {
573
#ifdef TKINTER_PROTECT_LOADTK
574
if (tk_load_failed) {
575
PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
580
if (Tk_Init(interp) == TCL_ERROR) {
581
#ifdef TKINTER_PROTECT_LOADTK
584
PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
590
#endif /* !WITH_APPINIT */
595
/* Initialize the Tk application; see the `main' function in
599
static void EnableEventHook(void); /* Forward */
600
static void DisableEventHook(void); /* Forward */
603
Tkapp_New(char *screenName, char *className,
604
int interactive, int wantobjects, int wantTk, int sync, char *use)
609
v = PyObject_New(TkappObject, &Tkapp_Type);
613
v->interp = Tcl_CreateInterp();
614
v->wantobjects = wantobjects;
615
v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
616
TCL_GLOBAL_ONLY) != NULL;
617
v->thread_id = Tcl_GetCurrentThread();
622
PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
628
if (v->threaded && tcl_lock) {
629
/* If Tcl is threaded, we don't need the lock. */
630
PyThread_free_lock(tcl_lock);
635
v->BooleanType = Tcl_GetObjType("boolean");
636
v->ByteArrayType = Tcl_GetObjType("bytearray");
637
v->DoubleType = Tcl_GetObjType("double");
638
v->IntType = Tcl_GetObjType("int");
639
v->ListType = Tcl_GetObjType("list");
640
v->ProcBodyType = Tcl_GetObjType("procbody");
641
v->StringType = Tcl_GetObjType("string");
643
/* Delete the 'exit' command, which can screw things up */
644
Tcl_DeleteCommand(v->interp, "exit");
646
if (screenName != NULL)
647
Tcl_SetVar2(v->interp, "env", "DISPLAY",
648
screenName, TCL_GLOBAL_ONLY);
651
Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
653
Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
655
/* This is used to get the application class for Tk 4.1 and up */
656
argv0 = (char*)ckalloc(strlen(className) + 1);
663
strcpy(argv0, className);
664
if (isupper(Py_CHARMASK(argv0[0])))
665
argv0[0] = tolower(Py_CHARMASK(argv0[0]));
666
Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
670
Tcl_SetVar(v->interp,
671
"_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
673
#ifdef TKINTER_PROTECT_LOADTK
674
else if (tk_load_failed) {
675
Tcl_SetVar(v->interp,
676
"_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
680
/* some initial arguments need to be in argv */
686
len += sizeof "-sync";
688
len += strlen(use) + sizeof "-use ";
690
args = (char*)ckalloc(len);
699
strcat(args, "-sync");
703
strcat(args, "-use ");
707
Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
711
if (Tcl_AppInit(v->interp) != TCL_OK) {
712
PyObject *result = Tkinter_Error((PyObject *)v);
713
#ifdef TKINTER_PROTECT_LOADTK
715
const char *_tkinter_tk_failed;
716
_tkinter_tk_failed = Tcl_GetVar(v->interp,
717
"_tkinter_tk_failed", TCL_GLOBAL_ONLY);
719
if ( _tkinter_tk_failed != NULL &&
720
strcmp(_tkinter_tk_failed, "1") == 0) {
725
Py_DECREF((PyObject *)v);
726
return (TkappObject *)result;
736
Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
737
Tcl_Condition *cond, Tcl_Mutex *mutex)
739
Py_BEGIN_ALLOW_THREADS;
740
Tcl_MutexLock(mutex);
741
Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
742
Tcl_ThreadAlert(self->thread_id);
743
Tcl_ConditionWait(cond, mutex, NULL);
744
Tcl_MutexUnlock(mutex);
754
PyObject *string; /* This cannot cause cycles. */
757
static PyTypeObject PyTclObject_Type;
758
#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
761
newPyTclObject(Tcl_Obj *arg)
764
self = PyObject_New(PyTclObject, &PyTclObject_Type);
767
Tcl_IncrRefCount(arg);
770
return (PyObject*)self;
774
PyTclObject_dealloc(PyTclObject *self)
776
Tcl_DecrRefCount(self->value);
777
Py_XDECREF(self->string);
782
PyTclObject_TclString(PyObject *self)
784
return Tcl_GetString(((PyTclObject*)self)->value);
787
/* Like _str, but create Unicode if necessary. */
788
PyDoc_STRVAR(PyTclObject_string__doc__,
789
"the string representation of this object, either as str or bytes");
792
PyTclObject_string(PyTclObject *self, void *ignored)
797
s = Tcl_GetStringFromObj(self->value, &len);
798
self->string = PyUnicode_FromStringAndSize(s, len);
802
Py_INCREF(self->string);
807
PyTclObject_str(PyTclObject *self, void *ignored)
811
if (self->string && PyUnicode_Check(self->string)) {
812
Py_INCREF(self->string);
815
/* XXX Could chache result if it is non-ASCII. */
816
s = Tcl_GetStringFromObj(self->value, &len);
817
return PyUnicode_DecodeUTF8(s, len, "strict");
821
PyTclObject_repr(PyTclObject *self)
823
return PyUnicode_FromFormat("<%s object at %p>",
824
self->value->typePtr->name, self->value);
827
#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
830
PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
835
/* neither argument should be NULL, unless something's gone wrong */
836
if (self == NULL || other == NULL) {
837
PyErr_BadInternalCall();
841
/* both arguments should be instances of PyTclObject */
842
if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
843
v = Py_NotImplemented;
848
/* fast path when self and other are identical */
851
result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
852
Tcl_GetString(((PyTclObject *)other)->value));
853
/* Convert return value to a Boolean */
856
v = TEST_COND(result == 0);
859
v = TEST_COND(result != 0);
862
v = TEST_COND(result <= 0);
865
v = TEST_COND(result >= 0);
868
v = TEST_COND(result < 0);
871
v = TEST_COND(result > 0);
882
PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
885
get_typename(PyTclObject* obj, void* ignored)
887
return PyUnicode_FromString(obj->value->typePtr->name);
891
static PyGetSetDef PyTclObject_getsetlist[] = {
892
{"typename", (getter)get_typename, NULL, get_typename__doc__},
893
{"string", (getter)PyTclObject_string, NULL,
894
PyTclObject_string__doc__},
898
static PyTypeObject PyTclObject_Type = {
899
PyVarObject_HEAD_INIT(NULL, 0)
900
"_tkinter.Tcl_Obj", /*tp_name*/
901
sizeof(PyTclObject), /*tp_basicsize*/
904
(destructor)PyTclObject_dealloc,/*tp_dealloc*/
909
(reprfunc)PyTclObject_repr, /*tp_repr*/
911
0, /*tp_as_sequence*/
915
(reprfunc)PyTclObject_str, /*tp_str*/
916
PyObject_GenericGetAttr, /*tp_getattro*/
919
Py_TPFLAGS_DEFAULT, /*tp_flags*/
923
PyTclObject_richcompare, /*tp_richcompare*/
924
0, /*tp_weaklistoffset*/
929
PyTclObject_getsetlist, /*tp_getset*/
943
AsObj(PyObject *value)
949
if (PyBytes_Check(value))
950
return Tcl_NewStringObj(PyBytes_AS_STRING(value),
951
PyBytes_GET_SIZE(value));
952
else if (PyBool_Check(value))
953
return Tcl_NewBooleanObj(PyObject_IsTrue(value));
954
else if (PyLong_CheckExact(value) &&
955
((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
957
/* If there is an overflow in the long conversion,
958
fall through to default object handling. */
959
return Tcl_NewLongObj(longVal);
961
else if (PyFloat_Check(value))
962
return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
963
else if (PyTuple_Check(value)) {
964
Tcl_Obj **argv = (Tcl_Obj**)
965
ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
969
for(i=0;i<PyTuple_Size(value);i++)
970
argv[i] = AsObj(PyTuple_GetItem(value,i));
971
result = Tcl_NewListObj(PyTuple_Size(value), argv);
972
ckfree(FREECAST argv);
975
else if (PyUnicode_Check(value)) {
976
Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
977
Py_ssize_t size = PyUnicode_GET_SIZE(value);
978
/* This #ifdef assumes that Tcl uses UCS-2.
979
See TCL_UTF_MAX test above. */
980
#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
981
Tcl_UniChar *outbuf = NULL;
983
size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
984
if (allocsize >= size)
985
outbuf = (Tcl_UniChar*)ckalloc(allocsize);
986
/* Else overflow occurred, and we take the next exit */
991
for (i = 0; i < size; i++) {
992
if (inbuf[i] >= 0x10000) {
993
/* Tcl doesn't do UTF-16, yet. */
994
PyErr_SetString(PyExc_ValueError,
995
"unsupported character");
996
ckfree(FREECAST outbuf);
999
outbuf[i] = inbuf[i];
1001
result = Tcl_NewUnicodeObj(outbuf, size);
1002
ckfree(FREECAST outbuf);
1005
return Tcl_NewUnicodeObj(inbuf, size);
1009
else if(PyTclObject_Check(value)) {
1010
Tcl_Obj *v = ((PyTclObject*)value)->value;
1011
Tcl_IncrRefCount(v);
1015
PyObject *v = PyObject_Str(value);
1025
FromObj(PyObject* tkapp, Tcl_Obj *value)
1027
PyObject *result = NULL;
1028
TkappObject *app = (TkappObject*)tkapp;
1030
if (value->typePtr == NULL) {
1031
return PyUnicode_FromStringAndSize(value->bytes,
1035
if (value->typePtr == app->BooleanType) {
1036
result = value->internalRep.longValue ? Py_True : Py_False;
1041
if (value->typePtr == app->ByteArrayType) {
1043
char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1044
return PyBytes_FromStringAndSize(data, size);
1047
if (value->typePtr == app->DoubleType) {
1048
return PyFloat_FromDouble(value->internalRep.doubleValue);
1051
if (value->typePtr == app->IntType) {
1052
return PyLong_FromLong(value->internalRep.longValue);
1055
if (value->typePtr == app->ListType) {
1061
status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1062
if (status == TCL_ERROR)
1063
return Tkinter_Error(tkapp);
1064
result = PyTuple_New(size);
1067
for (i = 0; i < size; i++) {
1068
status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1069
value, i, &tcl_elem);
1070
if (status == TCL_ERROR) {
1072
return Tkinter_Error(tkapp);
1074
elem = FromObj(tkapp, tcl_elem);
1079
PyTuple_SetItem(result, i, elem);
1084
if (value->typePtr == app->ProcBodyType) {
1085
/* fall through: return tcl object. */
1088
if (value->typePtr == app->StringType) {
1089
#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1095
size = Tcl_GetCharLength(value);
1096
result = PyUnicode_FromUnicode(NULL, size);
1099
input = Tcl_GetUnicode(value);
1100
output = PyUnicode_AS_UNICODE(result);
1102
*output++ = *input++;
1105
return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1106
Tcl_GetCharLength(value));
1110
return newPyTclObject(value);
1113
/* This mutex synchronizes inter-thread command calls. */
1115
TCL_DECLARE_MUTEX(call_mutex)
1117
typedef struct Tkapp_CallEvent {
1118
Tcl_Event ev; /* Must be first */
1123
PyObject **exc_type, **exc_value, **exc_tb;
1124
Tcl_Condition *done;
1128
Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
1131
for (i = 0; i < objc; i++)
1132
Tcl_DecrRefCount(objv[i]);
1133
if (objv != objStore)
1134
ckfree(FREECAST objv);
1137
/* Convert Python objects to Tcl objects. This must happen in the
1138
interpreter thread, which may or may not be the calling thread. */
1141
Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1143
Tcl_Obj **objv = objStore;
1148
else if (!PyTuple_Check(args)) {
1149
objv[0] = AsObj(args);
1153
Tcl_IncrRefCount(objv[0]);
1156
objc = PyTuple_Size(args);
1159
objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1167
for (i = 0; i < objc; i++) {
1168
PyObject *v = PyTuple_GetItem(args, i);
1175
/* Reset objc, so it attempts to clear
1176
objects only up to i. */
1180
Tcl_IncrRefCount(objv[i]);
1186
Tkapp_CallDeallocArgs(objv, objStore, objc);
1190
/* Convert the results of a command call into a Python objects. */
1193
Tkapp_CallResult(TkappObject *self)
1195
PyObject *res = NULL;
1196
if(self->wantobjects) {
1197
Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1198
/* Not sure whether the IncrRef is necessary, but something
1199
may overwrite the interpreter result while we are
1201
Tcl_IncrRefCount(value);
1202
res = FromObj((PyObject*)self, value);
1203
Tcl_DecrRefCount(value);
1205
const char *s = Tcl_GetStringResult(self->interp);
1208
res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1213
/* Tkapp_CallProc is the event procedure that is executed in the context of
1214
the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1215
hold the Python lock. */
1218
Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1220
Tcl_Obj *objStore[ARGSZ];
1225
objv = Tkapp_CallArgs(e->args, objStore, &objc);
1227
PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1233
i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1235
if (i == TCL_ERROR) {
1237
*(e->exc_type) = NULL;
1238
*(e->exc_tb) = NULL;
1239
*(e->exc_value) = PyObject_CallFunction(
1240
Tkinter_TclError, "s",
1241
Tcl_GetStringResult(e->self->interp));
1244
*(e->res) = Tkapp_CallResult(e->self);
1248
Tkapp_CallDeallocArgs(objv, objStore, objc);
1250
/* Wake up calling thread. */
1251
Tcl_MutexLock(&call_mutex);
1252
Tcl_ConditionNotify(e->done);
1253
Tcl_MutexUnlock(&call_mutex);
1257
/* This is the main entry point for calling a Tcl command.
1258
It supports three cases, with regard to threading:
1259
1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1260
the context of the calling thread.
1261
2. Tcl is threaded, caller of the command is in the interpreter thread:
1262
Execute the command in the calling thread. Since the Tcl lock will
1263
not be used, we can merge that with case 1.
1264
3. Tcl is threaded, caller is in a different thread: Must queue an event to
1265
the interpreter thread. Allocation of Tcl objects needs to occur in the
1266
interpreter thread, so we ship the PyObject* args to the target thread,
1267
and perform processing there. */
1270
Tkapp_Call(PyObject *selfptr, PyObject *args)
1272
Tcl_Obj *objStore[ARGSZ];
1273
Tcl_Obj **objv = NULL;
1275
PyObject *res = NULL;
1276
TkappObject *self = (TkappObject*)selfptr;
1277
int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
1279
/* If args is a single tuple, replace with contents of tuple */
1280
if (1 == PyTuple_Size(args)){
1281
PyObject* item = PyTuple_GetItem(args, 0);
1282
if (PyTuple_Check(item))
1286
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1287
/* We cannot call the command directly. Instead, we must
1288
marshal the parameters to the interpreter thread. */
1289
Tkapp_CallEvent *ev;
1290
Tcl_Condition cond = NULL;
1291
PyObject *exc_type, *exc_value, *exc_tb;
1292
if (!WaitForMainloop(self))
1294
ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1295
ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1299
ev->exc_type = &exc_type;
1300
ev->exc_value = &exc_value;
1301
ev->exc_tb = &exc_tb;
1304
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
1308
PyErr_Restore(exc_type, exc_value, exc_tb);
1310
PyErr_SetObject(Tkinter_TclError, exc_value);
1312
Tcl_ConditionFinalize(&cond);
1318
objv = Tkapp_CallArgs(args, objStore, &objc);
1324
i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1329
Tkinter_Error(selfptr);
1331
res = Tkapp_CallResult(self);
1335
Tkapp_CallDeallocArgs(objv, objStore, objc);
1342
Tkapp_GlobalCall(PyObject *self, PyObject *args)
1344
/* Could do the same here as for Tkapp_Call(), but this is not used
1345
much, so I can't be bothered. Unfortunately Tcl doesn't export a
1346
way for the user to do what all its Global* variants do (save and
1347
reset the scope pointer, call the local version, restore the saved
1351
PyObject *res = NULL;
1353
CHECK_TCL_APPARTMENT;
1359
err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1361
if (err == TCL_ERROR)
1362
res = Tkinter_Error(self);
1364
res = PyUnicode_FromString(Tkapp_Result(self));
1373
Tkapp_Eval(PyObject *self, PyObject *args)
1376
PyObject *res = NULL;
1379
if (!PyArg_ParseTuple(args, "s:eval", &script))
1382
CHECK_TCL_APPARTMENT;
1385
err = Tcl_Eval(Tkapp_Interp(self), script);
1387
if (err == TCL_ERROR)
1388
res = Tkinter_Error(self);
1390
res = PyUnicode_FromString(Tkapp_Result(self));
1396
Tkapp_GlobalEval(PyObject *self, PyObject *args)
1399
PyObject *res = NULL;
1402
if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1405
CHECK_TCL_APPARTMENT;
1408
err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1410
if (err == TCL_ERROR)
1411
res = Tkinter_Error(self);
1413
res = PyUnicode_FromString(Tkapp_Result(self));
1419
Tkapp_EvalFile(PyObject *self, PyObject *args)
1422
PyObject *res = NULL;
1425
if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1428
CHECK_TCL_APPARTMENT;
1431
err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1433
if (err == TCL_ERROR)
1434
res = Tkinter_Error(self);
1437
res = PyUnicode_FromString(Tkapp_Result(self));
1443
Tkapp_Record(PyObject *self, PyObject *args)
1446
PyObject *res = NULL;
1449
if (!PyArg_ParseTuple(args, "s", &script))
1452
CHECK_TCL_APPARTMENT;
1455
err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1457
if (err == TCL_ERROR)
1458
res = Tkinter_Error(self);
1460
res = PyUnicode_FromString(Tkapp_Result(self));
1466
Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
1470
if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1472
CHECK_TCL_APPARTMENT;
1475
Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1484
/** Tcl Variable **/
1486
TCL_DECLARE_MUTEX(var_mutex)
1488
typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1489
typedef struct VarEvent {
1490
Tcl_Event ev; /* must be first */
1496
PyObject **exc_type;
1498
Tcl_Condition *cond;
1502
varname_converter(PyObject *in, void *_out)
1504
char **out = (char**)_out;
1505
if (PyBytes_Check(in)) {
1506
*out = PyBytes_AsString(in);
1509
if (PyUnicode_Check(in)) {
1510
*out = _PyUnicode_AsString(in);
1513
if (PyTclObject_Check(in)) {
1514
*out = PyTclObject_TclString(in);
1517
/* XXX: Should give diagnostics. */
1522
var_perform(VarEvent *ev)
1524
*(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1526
PyObject *exc, *val, *tb;
1527
PyErr_Fetch(&exc, &val, &tb);
1528
PyErr_NormalizeException(&exc, &val, &tb);
1529
*(ev->exc_type) = exc;
1530
*(ev->exc_val) = val;
1537
var_proc(VarEvent* ev, int flags)
1541
Tcl_MutexLock(&var_mutex);
1542
Tcl_ConditionNotify(ev->cond);
1543
Tcl_MutexUnlock(&var_mutex);
1549
var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
1551
TkappObject *self = (TkappObject*)selfptr;
1553
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1554
TkappObject *self = (TkappObject*)selfptr;
1556
PyObject *res, *exc_type, *exc_val;
1557
Tcl_Condition cond = NULL;
1559
/* The current thread is not the interpreter thread. Marshal
1560
the call to the interpreter thread, then wait for
1562
if (!WaitForMainloop(self))
1565
ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1572
ev->exc_type = &exc_type;
1573
ev->exc_val = &exc_val;
1575
ev->ev.proc = (Tcl_EventProc*)var_proc;
1576
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1577
Tcl_ConditionFinalize(&cond);
1579
PyErr_SetObject(exc_type, exc_val);
1580
Py_DECREF(exc_type);
1587
/* Tcl is not threaded, or this is the interpreter thread. */
1588
return func(selfptr, args, flags);
1592
SetVar(PyObject *self, PyObject *args, int flags)
1594
char *name1, *name2;
1596
PyObject *res = NULL;
1597
Tcl_Obj *newval, *ok;
1599
if (PyArg_ParseTuple(args, "O&O:setvar",
1600
varname_converter, &name1, &newValue)) {
1601
/* XXX Acquire tcl lock??? */
1602
newval = AsObj(newValue);
1606
ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1610
Tkinter_Error(self);
1619
if (PyArg_ParseTuple(args, "ssO:setvar",
1620
&name1, &name2, &newValue)) {
1621
/* XXX must hold tcl lock already??? */
1622
newval = AsObj(newValue);
1624
ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1627
Tkinter_Error(self);
1642
Tkapp_SetVar(PyObject *self, PyObject *args)
1644
return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1648
Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
1650
return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1656
GetVar(PyObject *self, PyObject *args, int flags)
1658
char *name1, *name2=NULL;
1659
PyObject *res = NULL;
1662
if (!PyArg_ParseTuple(args, "O&|s:getvar",
1663
varname_converter, &name1, &name2))
1667
tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1670
PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1672
if (((TkappObject*)self)->wantobjects) {
1673
res = FromObj(self, tres);
1676
res = PyUnicode_FromString(Tcl_GetString(tres));
1684
Tkapp_GetVar(PyObject *self, PyObject *args)
1686
return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1690
Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1692
return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1698
UnsetVar(PyObject *self, PyObject *args, int flags)
1700
char *name1, *name2=NULL;
1702
PyObject *res = NULL;
1704
if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1708
code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1710
if (code == TCL_ERROR)
1711
res = Tkinter_Error(self);
1721
Tkapp_UnsetVar(PyObject *self, PyObject *args)
1723
return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1727
Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1729
return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1734
/** Tcl to Python **/
1737
Tkapp_GetInt(PyObject *self, PyObject *args)
1742
if (PyTuple_Size(args) == 1) {
1743
PyObject* o = PyTuple_GetItem(args, 0);
1744
if (PyLong_Check(o)) {
1749
if (!PyArg_ParseTuple(args, "s:getint", &s))
1751
if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1752
return Tkinter_Error(self);
1753
return Py_BuildValue("i", v);
1757
Tkapp_GetDouble(PyObject *self, PyObject *args)
1762
if (PyTuple_Size(args) == 1) {
1763
PyObject *o = PyTuple_GetItem(args, 0);
1764
if (PyFloat_Check(o)) {
1769
if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1771
if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1772
return Tkinter_Error(self);
1773
return Py_BuildValue("d", v);
1777
Tkapp_GetBoolean(PyObject *self, PyObject *args)
1782
if (PyTuple_Size(args) == 1) {
1783
PyObject *o = PyTuple_GetItem(args, 0);
1784
if (PyLong_Check(o)) {
1789
if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1791
if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1792
return Tkinter_Error(self);
1793
return PyBool_FromLong(v);
1797
Tkapp_ExprString(PyObject *self, PyObject *args)
1800
PyObject *res = NULL;
1803
if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1806
CHECK_TCL_APPARTMENT;
1809
retval = Tcl_ExprString(Tkapp_Interp(self), s);
1811
if (retval == TCL_ERROR)
1812
res = Tkinter_Error(self);
1814
res = Py_BuildValue("s", Tkapp_Result(self));
1820
Tkapp_ExprLong(PyObject *self, PyObject *args)
1823
PyObject *res = NULL;
1827
if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1830
CHECK_TCL_APPARTMENT;
1833
retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1835
if (retval == TCL_ERROR)
1836
res = Tkinter_Error(self);
1838
res = Py_BuildValue("l", v);
1844
Tkapp_ExprDouble(PyObject *self, PyObject *args)
1847
PyObject *res = NULL;
1851
if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1853
CHECK_TCL_APPARTMENT;
1854
PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1856
retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1858
PyFPE_END_PROTECT(retval)
1859
if (retval == TCL_ERROR)
1860
res = Tkinter_Error(self);
1862
res = Py_BuildValue("d", v);
1868
Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1871
PyObject *res = NULL;
1875
if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1877
CHECK_TCL_APPARTMENT;
1879
retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1881
if (retval == TCL_ERROR)
1882
res = Tkinter_Error(self);
1884
res = Py_BuildValue("i", v);
1892
Tkapp_SplitList(PyObject *self, PyObject *args)
1900
if (PyTuple_Size(args) == 1) {
1901
v = PyTuple_GetItem(args, 0);
1902
if (PyTuple_Check(v)) {
1907
if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1910
if (Tcl_SplitList(Tkapp_Interp(self), list,
1911
&argc, &argv) == TCL_ERROR) {
1913
return Tkinter_Error(self);
1916
if (!(v = PyTuple_New(argc)))
1919
for (i = 0; i < argc; i++) {
1920
PyObject *s = PyUnicode_FromString(argv[i]);
1921
if (!s || PyTuple_SetItem(v, i, s)) {
1929
ckfree(FREECAST argv);
1935
Tkapp_Split(PyObject *self, PyObject *args)
1940
if (PyTuple_Size(args) == 1) {
1941
PyObject* o = PyTuple_GetItem(args, 0);
1942
if (PyTuple_Check(o)) {
1947
if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1955
Tkapp_Merge(PyObject *self, PyObject *args)
1957
char *s = Merge(args);
1958
PyObject *res = NULL;
1961
res = PyUnicode_FromString(s);
1972
/* Client data struct */
1976
} PythonCmd_ClientData;
1979
PythonCmd_Error(Tcl_Interp *interp)
1982
PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1987
/* This is the Tcl command that acts as a wrapper for Python
1988
* function or method.
1991
PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1993
PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1994
PyObject *self, *func, *arg, *res;
2000
/* TBD: no error checking here since we know, via the
2001
* Tkapp_CreateCommand() that the client data is a two-tuple
2006
/* Create argument list (argv1, ..., argvN) */
2007
if (!(arg = PyTuple_New(argc - 1)))
2008
return PythonCmd_Error(interp);
2010
for (i = 0; i < (argc - 1); i++) {
2011
PyObject *s = PyUnicode_FromString(argv[i + 1]);
2012
if (!s || PyTuple_SetItem(arg, i, s)) {
2014
return PythonCmd_Error(interp);
2017
res = PyEval_CallObject(func, arg);
2021
return PythonCmd_Error(interp);
2023
obj_res = AsObj(res);
2024
if (obj_res == NULL) {
2026
return PythonCmd_Error(interp);
2029
Tcl_SetObjResult(interp, obj_res);
2041
PythonCmdDelete(ClientData clientData)
2043
PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2046
Py_XDECREF(data->self);
2047
Py_XDECREF(data->func);
2055
TCL_DECLARE_MUTEX(command_mutex)
2057
typedef struct CommandEvent{
2064
Tcl_Condition *done;
2068
Tkapp_CommandProc(CommandEvent *ev, int flags)
2071
*ev->status = Tcl_CreateCommand(
2072
ev->interp, ev->name, PythonCmd,
2073
ev->data, PythonCmdDelete) == NULL;
2075
*ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2076
Tcl_MutexLock(&command_mutex);
2077
Tcl_ConditionNotify(ev->done);
2078
Tcl_MutexUnlock(&command_mutex);
2083
Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2085
TkappObject *self = (TkappObject*)selfptr;
2086
PythonCmd_ClientData *data;
2091
if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2093
if (!PyCallable_Check(func)) {
2094
PyErr_SetString(PyExc_TypeError, "command not callable");
2099
if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2100
!WaitForMainloop(self))
2104
data = PyMem_NEW(PythonCmd_ClientData, 1);
2106
return PyErr_NoMemory();
2109
data->self = selfptr;
2112
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2113
Tcl_Condition cond = NULL;
2114
CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2115
ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2116
ev->interp = self->interp;
2119
ev->data = (ClientData)data;
2122
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2123
Tcl_ConditionFinalize(&cond);
2127
err = Tcl_CreateCommand(
2128
Tkapp_Interp(self), cmdName, PythonCmd,
2129
(ClientData)data, PythonCmdDelete) == NULL;
2133
PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2145
Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2147
TkappObject *self = (TkappObject*)selfptr;
2151
if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2153
if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2154
Tcl_Condition cond = NULL;
2156
ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2157
ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2158
ev->interp = self->interp;
2163
Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2165
Tcl_ConditionFinalize(&cond);
2169
err = Tcl_DeleteCommand(self->interp, cmdName);
2173
PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2182
#ifdef HAVE_CREATEFILEHANDLER
2183
/** File Handler **/
2185
typedef struct _fhcdata {
2189
struct _fhcdata *next;
2190
} FileHandler_ClientData;
2192
static FileHandler_ClientData *HeadFHCD;
2194
static FileHandler_ClientData *
2195
NewFHCD(PyObject *func, PyObject *file, int id)
2197
FileHandler_ClientData *p;
2198
p = PyMem_NEW(FileHandler_ClientData, 1);
2214
FileHandler_ClientData *p, **pp;
2217
while ((p = *pp) != NULL) {
2220
Py_XDECREF(p->func);
2221
Py_XDECREF(p->file);
2230
FileHandler(ClientData clientData, int mask)
2232
FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2233
PyObject *func, *file, *arg, *res;
2239
arg = Py_BuildValue("(Oi)", file, (long) mask);
2240
res = PyEval_CallObject(func, arg);
2245
PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2252
Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2253
/* args is (file, mask, func) */
2255
FileHandler_ClientData *data;
2256
PyObject *file, *func;
2259
if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2260
&file, &mask, &func))
2263
CHECK_TCL_APPARTMENT;
2265
tfile = PyObject_AsFileDescriptor(file);
2268
if (!PyCallable_Check(func)) {
2269
PyErr_SetString(PyExc_TypeError, "bad argument list");
2273
data = NewFHCD(func, file, tfile);
2277
/* Ought to check for null Tcl_File object... */
2279
Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2286
Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2291
if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2294
CHECK_TCL_APPARTMENT;
2296
tfile = PyObject_AsFileDescriptor(file);
2302
/* Ought to check for null Tcl_File object... */
2304
Tcl_DeleteFileHandler(tfile);
2309
#endif /* HAVE_CREATEFILEHANDLER */
2312
/**** Tktt Object (timer token) ****/
2314
static PyTypeObject Tktt_Type;
2318
Tcl_TimerToken token;
2323
Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2325
TkttObject *v = (TkttObject *)self;
2326
PyObject *func = v->func;
2328
if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2330
if (v->token != NULL) {
2331
Tcl_DeleteTimerHandler(v->token);
2337
Py_DECREF(v); /* See Tktt_New() */
2343
static PyMethodDef Tktt_methods[] =
2345
{"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2350
Tktt_New(PyObject *func)
2354
v = PyObject_New(TkttObject, &Tktt_Type);
2362
/* Extra reference, deleted when called or when handler is deleted */
2368
Tktt_Dealloc(PyObject *self)
2370
TkttObject *v = (TkttObject *)self;
2371
PyObject *func = v->func;
2379
Tktt_Repr(PyObject *self)
2381
TkttObject *v = (TkttObject *)self;
2384
PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2385
v->func == NULL ? ", handler deleted" : "");
2386
return PyUnicode_FromString(buf);
2389
static PyTypeObject Tktt_Type =
2391
PyVarObject_HEAD_INIT(NULL, 0)
2392
"tktimertoken", /*tp_name */
2393
sizeof(TkttObject), /*tp_basicsize */
2395
Tktt_Dealloc, /*tp_dealloc */
2400
Tktt_Repr, /*tp_repr */
2401
0, /*tp_as_number */
2402
0, /*tp_as_sequence */
2403
0, /*tp_as_mapping */
2410
Py_TPFLAGS_DEFAULT, /*tp_flags*/
2414
0, /*tp_richcompare*/
2415
0, /*tp_weaklistoffset*/
2418
Tktt_methods, /*tp_methods*/
2423
/** Timer Handler **/
2426
TimerHandler(ClientData clientData)
2428
TkttObject *v = (TkttObject *)clientData;
2429
PyObject *func = v->func;
2439
res = PyEval_CallObject(func, NULL);
2441
Py_DECREF(v); /* See Tktt_New() */
2445
PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2454
Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2460
if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2461
&milliseconds, &func))
2463
if (!PyCallable_Check(func)) {
2464
PyErr_SetString(PyExc_TypeError, "bad argument list");
2468
CHECK_TCL_APPARTMENT;
2472
v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2476
return (PyObject *) v;
2483
Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
2486
TkappObject *self = (TkappObject*)selfptr;
2488
PyThreadState *tstate = PyThreadState_Get();
2491
if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2494
CHECK_TCL_APPARTMENT;
2495
self->dispatching = 1;
2498
while (Tk_GetNumMainWindows() > threshold &&
2505
if (self->threaded) {
2506
/* Allow other Python threads to run. */
2508
result = Tcl_DoOneEvent(0);
2512
Py_BEGIN_ALLOW_THREADS
2513
if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2514
tcl_tstate = tstate;
2515
result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2517
if(tcl_lock)PyThread_release_lock(tcl_lock);
2519
Sleep(Tkinter_busywaitinterval);
2520
Py_END_ALLOW_THREADS
2523
result = Tcl_DoOneEvent(0);
2526
if (PyErr_CheckSignals() != 0) {
2527
self->dispatching = 0;
2533
self->dispatching = 0;
2538
PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2539
excInCmd = valInCmd = trbInCmd = NULL;
2547
Tkapp_DoOneEvent(PyObject *self, PyObject *args)
2552
if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2556
rv = Tcl_DoOneEvent(flags);
2558
return Py_BuildValue("i", rv);
2562
Tkapp_Quit(PyObject *self, PyObject *args)
2565
if (!PyArg_ParseTuple(args, ":quit"))
2574
Tkapp_InterpAddr(PyObject *self, PyObject *args)
2577
if (!PyArg_ParseTuple(args, ":interpaddr"))
2580
return PyLong_FromLong((long)Tkapp_Interp(self));
2584
Tkapp_TkInit(PyObject *self, PyObject *args)
2586
Tcl_Interp *interp = Tkapp_Interp(self);
2587
const char * _tk_exists = NULL;
2590
#ifdef TKINTER_PROTECT_LOADTK
2591
/* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2592
* first call failed.
2593
* To avoid the deadlock, we just refuse the second call through
2594
* a static variable.
2596
if (tk_load_failed) {
2597
PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2602
/* We want to guard against calling Tk_Init() multiple times */
2603
CHECK_TCL_APPARTMENT;
2605
err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2607
if (err == TCL_ERROR) {
2608
/* This sets an exception, but we cannot return right
2609
away because we need to exit the overlap first. */
2610
Tkinter_Error(self);
2612
_tk_exists = Tkapp_Result(self);
2615
if (err == TCL_ERROR) {
2618
if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2619
if (Tk_Init(interp) == TCL_ERROR) {
2620
PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2621
#ifdef TKINTER_PROTECT_LOADTK
2632
Tkapp_WantObjects(PyObject *self, PyObject *args)
2635
int wantobjects = -1;
2636
if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2638
if (wantobjects == -1)
2639
return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2640
((TkappObject*)self)->wantobjects = wantobjects;
2647
Tkapp_WillDispatch(PyObject *self, PyObject *args)
2650
((TkappObject*)self)->dispatching = 1;
2657
/**** Tkapp Method List ****/
2659
static PyMethodDef Tkapp_methods[] =
2661
{"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2662
{"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2663
{"call", Tkapp_Call, METH_VARARGS},
2664
{"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2665
{"eval", Tkapp_Eval, METH_VARARGS},
2666
{"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2667
{"evalfile", Tkapp_EvalFile, METH_VARARGS},
2668
{"record", Tkapp_Record, METH_VARARGS},
2669
{"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2670
{"setvar", Tkapp_SetVar, METH_VARARGS},
2671
{"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2672
{"getvar", Tkapp_GetVar, METH_VARARGS},
2673
{"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2674
{"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2675
{"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2676
{"getint", Tkapp_GetInt, METH_VARARGS},
2677
{"getdouble", Tkapp_GetDouble, METH_VARARGS},
2678
{"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2679
{"exprstring", Tkapp_ExprString, METH_VARARGS},
2680
{"exprlong", Tkapp_ExprLong, METH_VARARGS},
2681
{"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2682
{"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2683
{"splitlist", Tkapp_SplitList, METH_VARARGS},
2684
{"split", Tkapp_Split, METH_VARARGS},
2685
{"merge", Tkapp_Merge, METH_VARARGS},
2686
{"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2687
{"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2688
#ifdef HAVE_CREATEFILEHANDLER
2689
{"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2690
{"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2692
{"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2693
{"mainloop", Tkapp_MainLoop, METH_VARARGS},
2694
{"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2695
{"quit", Tkapp_Quit, METH_VARARGS},
2696
{"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2697
{"loadtk", Tkapp_TkInit, METH_NOARGS},
2703
/**** Tkapp Type Methods ****/
2706
Tkapp_Dealloc(PyObject *self)
2708
/*CHECK_TCL_APPARTMENT;*/
2710
Tcl_DeleteInterp(Tkapp_Interp(self));
2716
static PyTypeObject Tkapp_Type =
2718
PyVarObject_HEAD_INIT(NULL, 0)
2719
"tkapp", /*tp_name */
2720
sizeof(TkappObject), /*tp_basicsize */
2722
Tkapp_Dealloc, /*tp_dealloc */
2728
0, /*tp_as_number */
2729
0, /*tp_as_sequence */
2730
0, /*tp_as_mapping */
2737
Py_TPFLAGS_DEFAULT, /*tp_flags*/
2741
0, /*tp_richcompare*/
2742
0, /*tp_weaklistoffset*/
2745
Tkapp_methods, /*tp_methods*/
2750
/**** Tkinter Module ****/
2754
int size; /* current size */
2755
int maxsize; /* allocated size */
2759
_bump(FlattenContext* context, int size)
2761
/* expand tuple to hold (at least) size new items.
2762
return true if successful, false if an exception was raised */
2764
int maxsize = context->maxsize * 2;
2766
if (maxsize < context->size + size)
2767
maxsize = context->size + size;
2769
context->maxsize = maxsize;
2771
return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2775
_flatten1(FlattenContext* context, PyObject* item, int depth)
2777
/* add tuple or list to argument tuple (recursively) */
2782
PyErr_SetString(PyExc_ValueError,
2783
"nesting too deep in _flatten");
2785
} else if (PyList_Check(item)) {
2786
size = PyList_GET_SIZE(item);
2787
/* preallocate (assume no nesting) */
2788
if (context->size + size > context->maxsize &&
2789
!_bump(context, size))
2791
/* copy items to output tuple */
2792
for (i = 0; i < size; i++) {
2793
PyObject *o = PyList_GET_ITEM(item, i);
2794
if (PyList_Check(o) || PyTuple_Check(o)) {
2795
if (!_flatten1(context, o, depth + 1))
2797
} else if (o != Py_None) {
2798
if (context->size + 1 > context->maxsize &&
2802
PyTuple_SET_ITEM(context->tuple,
2803
context->size++, o);
2806
} else if (PyTuple_Check(item)) {
2807
/* same, for tuples */
2808
size = PyTuple_GET_SIZE(item);
2809
if (context->size + size > context->maxsize &&
2810
!_bump(context, size))
2812
for (i = 0; i < size; i++) {
2813
PyObject *o = PyTuple_GET_ITEM(item, i);
2814
if (PyList_Check(o) || PyTuple_Check(o)) {
2815
if (!_flatten1(context, o, depth + 1))
2817
} else if (o != Py_None) {
2818
if (context->size + 1 > context->maxsize &&
2822
PyTuple_SET_ITEM(context->tuple,
2823
context->size++, o);
2827
PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2834
Tkinter_Flatten(PyObject* self, PyObject* args)
2836
FlattenContext context;
2839
if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2842
context.maxsize = PySequence_Size(item);
2843
if (context.maxsize < 0)
2845
if (context.maxsize == 0)
2846
return PyTuple_New(0);
2848
context.tuple = PyTuple_New(context.maxsize);
2854
if (!_flatten1(&context, item,0))
2857
if (_PyTuple_Resize(&context.tuple, context.size))
2860
return context.tuple;
2864
Tkinter_Create(PyObject *self, PyObject *args)
2866
char *screenName = NULL;
2867
char *baseName = NULL; /* XXX this is not used anymore;
2868
try getting rid of it. */
2869
char *className = NULL;
2870
int interactive = 0;
2871
int wantobjects = 0;
2872
int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2873
int sync = 0; /* pass -sync to wish */
2874
char *use = NULL; /* pass -use to wish */
2878
if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2879
&screenName, &baseName, &className,
2880
&interactive, &wantobjects, &wantTk,
2884
return (PyObject *) Tkapp_New(screenName, className,
2885
interactive, wantobjects, wantTk,
2890
Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2893
if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2896
PyErr_SetString(PyExc_ValueError,
2897
"busywaitinterval must be >= 0");
2900
Tkinter_busywaitinterval = new_val;
2905
static char setbusywaitinterval_doc[] =
2906
"setbusywaitinterval(n) -> None\n\
2908
Set the busy-wait interval in milliseconds between successive\n\
2909
calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2910
It should be set to a divisor of the maximum time between\n\
2911
frames in an animation.";
2914
Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2916
return PyLong_FromLong(Tkinter_busywaitinterval);
2919
static char getbusywaitinterval_doc[] =
2920
"getbusywaitinterval() -> int\n\
2922
Return the current busy-wait interval between successive\n\
2923
calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2925
static PyMethodDef moduleMethods[] =
2927
{"_flatten", Tkinter_Flatten, METH_VARARGS},
2928
{"create", Tkinter_Create, METH_VARARGS},
2929
{"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2930
setbusywaitinterval_doc},
2931
{"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2932
METH_NOARGS, getbusywaitinterval_doc},
2936
#ifdef WAIT_FOR_STDIN
2938
static int stdin_ready = 0;
2942
MyFileProc(void *clientData, int mask)
2949
static PyThreadState *event_tstate = NULL;
2959
PyEval_RestoreThread(event_tstate);
2964
tfile = fileno(stdin);
2965
Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
2967
while (!errorInCmd && !stdin_ready) {
2975
#if defined(WITH_THREAD) || defined(MS_WINDOWS)
2976
Py_BEGIN_ALLOW_THREADS
2977
if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2978
tcl_tstate = event_tstate;
2980
result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2983
if(tcl_lock)PyThread_release_lock(tcl_lock);
2985
Sleep(Tkinter_busywaitinterval);
2986
Py_END_ALLOW_THREADS
2988
result = Tcl_DoOneEvent(0);
2995
Tcl_DeleteFileHandler(tfile);
2999
PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3000
excInCmd = valInCmd = trbInCmd = NULL;
3004
PyEval_SaveThread();
3012
EnableEventHook(void)
3014
#ifdef WAIT_FOR_STDIN
3015
if (PyOS_InputHook == NULL) {
3017
event_tstate = PyThreadState_Get();
3019
PyOS_InputHook = EventHook;
3025
DisableEventHook(void)
3027
#ifdef WAIT_FOR_STDIN
3028
if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3029
PyOS_InputHook = NULL;
3035
/* all errors will be checked in one fell swoop in init_tkinter() */
3037
ins_long(PyObject *d, char *name, long val)
3039
PyObject *v = PyLong_FromLong(val);
3041
PyDict_SetItemString(d, name, v);
3046
ins_string(PyObject *d, char *name, char *val)
3048
PyObject *v = PyUnicode_FromString(val);
3050
PyDict_SetItemString(d, name, v);
3056
static struct PyModuleDef _tkintermodule = {
3057
PyModuleDef_HEAD_INIT,
3069
PyInit__tkinter(void)
3071
PyObject *m, *d, *uexe, *cexe;
3073
if (PyType_Ready(&Tkapp_Type) < 0)
3077
tcl_lock = PyThread_allocate_lock();
3080
m = PyModule_Create(&_tkintermodule);
3084
d = PyModule_GetDict(m);
3085
Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3086
PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3088
ins_long(d, "READABLE", TCL_READABLE);
3089
ins_long(d, "WRITABLE", TCL_WRITABLE);
3090
ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3091
ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3092
ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3093
ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3094
ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3095
ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3096
ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3097
ins_string(d, "TK_VERSION", TK_VERSION);
3098
ins_string(d, "TCL_VERSION", TCL_VERSION);
3100
PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3102
if (PyType_Ready(&Tktt_Type) < 0)
3104
PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3106
Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3107
PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3110
/* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3111
* start waking up. Note that Tcl_FindExecutable will do this, this
3112
* code must be above it! The original warning from
3113
* tkMacOSXAppInit.c is copied below.
3115
* NB - You have to swap in the Tk Notifier BEFORE you start up the
3116
* Tcl interpreter for now. It probably should work to do this
3117
* in the other order, but for now it doesn't seem to.
3120
Tk_MacOSXSetupTkNotifier();
3124
/* This helps the dynamic loader; in Unicode aware Tcl versions
3125
it also helps Tcl find its encodings. */
3126
uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3128
cexe = PyUnicode_AsEncodedString(uexe,
3129
Py_FileSystemDefaultEncoding,
3132
Tcl_FindExecutable(PyBytes_AsString(cexe));
3137
if (PyErr_Occurred()) {
3143
/* This was not a good idea; through <Destroy> bindings,
3144
Tcl_Finalize() may invoke Python code but at that point the
3145
interpreter and thread state have already been destroyed! */
3146
Py_AtExit(Tcl_Finalize);