Tagging 3.0a4.
[python/dscho.git] / Modules / _tkinter.c
blob97f85f939c66db72ef10cc0fe626d82326a0102a
1 /***********************************************************
2 Copyright (C) 1994 Steen Lumholt.
4 All Rights Reserved
6 ******************************************************************/
8 /* _tkinter.c -- Interface to libtk.a and libtcl.a. */
10 /* TCL/TK VERSION INFO:
12 Only Tcl/Tk 8.2 and later are supported. Older versions are not
13 supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk
14 libraries.)
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).
25 #include "Python.h"
26 #include <ctype.h>
28 #ifdef WITH_THREAD
29 #include "pythread.h"
30 #endif
32 #ifdef MS_WINDOWS
33 #include <windows.h>
34 #endif
36 /* Allow using this code in Python 2.[12] */
37 #ifndef PyDoc_STRVAR
38 #define PyDoc_STRVAR(name,str) static char name[] = str
39 #endif
41 #ifndef PyMODINIT_FUNC
42 #define PyMODINIT_FUNC void
43 #endif
45 #ifndef PyBool_Check
46 #define PyBool_Check(o) 0
47 #define PyBool_FromLong PyLong_FromLong
48 #endif
50 /* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55 #define USE_COMPAT_CONST
57 /* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
59 Tcl are empty. */
60 #define TCL_THREADS
62 #ifdef TK_FRAMEWORK
63 #include <Tcl/tcl.h>
64 #include <Tk/tk.h>
65 #else
66 #include <tcl.h>
67 #include <tk.h>
68 #endif
70 /* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
71 #ifndef CONST84_RETURN
72 #define CONST84_RETURN
73 #undef CONST
74 #define CONST
75 #endif
77 #define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
79 #if TKMAJORMINOR < 8002
80 #error "Tk older than 8.2 not supported"
81 #endif
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,
89 as well.
91 #if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
92 #error "unsupported Tcl configuration"
93 #endif
95 #if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
96 #define HAVE_CREATEFILEHANDLER
97 #endif
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. */
103 #ifndef TCL_UNIX_FD
104 # ifdef TCL_WIN_SOCKET
105 # define TCL_UNIX_FD (! TCL_WIN_SOCKET)
106 # else
107 # define TCL_UNIX_FD 1
108 # endif
109 #endif
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. */
116 #ifdef MS_WINDOWS
117 #define FHANDLETYPE TCL_WIN_SOCKET
118 #else
119 #define FHANDLETYPE TCL_UNIX_FD
120 #endif
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
127 #endif
129 #endif /* HAVE_CREATEFILEHANDLER */
131 #ifdef MS_WINDOWS
132 #include <conio.h>
133 #define WAIT_FOR_STDIN
134 #endif
136 #ifdef WITH_THREAD
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;
191 #ifdef TCL_THREADS
192 static Tcl_ThreadDataKey state_key;
193 typedef PyThreadState *ThreadSpecificData;
194 #define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
195 #else
196 static PyThreadState *tcl_tstate = NULL;
197 #endif
199 #define ENTER_TCL \
200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
203 #define LEAVE_TCL \
204 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
206 #define ENTER_OVERLAP \
207 Py_END_ALLOW_THREADS
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"); \
224 return 0; \
227 #else
229 #define ENTER_TCL
230 #define LEAVE_TCL
231 #define ENTER_OVERLAP
232 #define LEAVE_OVERLAP_TCL
233 #define ENTER_PYTHON
234 #define LEAVE_PYTHON
235 #define CHECK_TCL_APPARTMENT
237 #endif
239 #ifndef FREECAST
240 #define FREECAST (char *)
241 #endif
243 /**** Tkapp Object Declaration ****/
245 static PyTypeObject Tkapp_Type;
247 typedef struct {
248 PyObject_HEAD
249 Tcl_Interp *interp;
250 int wantobjects;
251 int threaded; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id;
253 int dispatching;
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;
263 } TkappObject;
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;
285 static PyObject *
286 Tkinter_Error(PyObject *v)
288 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
289 return NULL;
294 /**** Utils ****/
296 static int Tkinter_busywaitinterval = 20;
298 #ifdef WITH_THREAD
299 #ifndef MS_WINDOWS
301 /* Millisecond sleep() for Unix platforms. */
303 static void
304 Sleep(int milli)
306 /* XXX Too bad if you don't have select(). */
307 struct timeval t;
308 t.tv_sec = milli/1000;
309 t.tv_usec = (milli%1000) * 1000;
310 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
312 #endif /* MS_WINDOWS */
314 /* Wait up to 1s for the mainloop to come up. */
316 static int
317 WaitForMainloop(TkappObject* self)
319 int i;
320 for (i = 0; i < 10; i++) {
321 if (self->dispatching)
322 return 1;
323 Py_BEGIN_ALLOW_THREADS
324 Sleep(100);
325 Py_END_ALLOW_THREADS
327 if (self->dispatching)
328 return 1;
329 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
330 return 0;
332 #endif /* WITH_THREAD */
335 static char *
336 AsString(PyObject *value, PyObject *tmp)
338 if (PyString_Check(value))
339 return PyString_AsString(value);
340 else if (PyUnicode_Check(value)) {
341 PyObject *v = PyUnicode_AsUTF8String(value);
342 if (v == NULL)
343 return NULL;
344 if (PyList_Append(tmp, v) != 0) {
345 Py_DECREF(v);
346 return NULL;
348 Py_DECREF(v);
349 return PyString_AsString(v);
351 else {
352 PyObject *v = PyObject_Str(value);
353 if (v == NULL)
354 return NULL;
355 if (PyList_Append(tmp, v) != 0) {
356 Py_DECREF(v);
357 return NULL;
359 Py_DECREF(v);
360 return PyString_AsString(v);
366 #define ARGSZ 64
368 static char *
369 Merge(PyObject *args)
371 PyObject *tmp = NULL;
372 char *argvStore[ARGSZ];
373 char **argv = NULL;
374 int fvStore[ARGSZ];
375 int *fv = NULL;
376 int argc = 0, fvc = 0, i;
377 char *res = NULL;
379 if (!(tmp = PyList_New(0)))
380 return NULL;
382 argv = argvStore;
383 fv = fvStore;
385 if (args == NULL)
386 argc = 0;
388 else if (!PyTuple_Check(args)) {
389 argc = 1;
390 fv[0] = 0;
391 if (!(argv[0] = AsString(args, tmp)))
392 goto finally;
394 else {
395 argc = PyTuple_Size(args);
397 if (argc > ARGSZ) {
398 argv = (char **)ckalloc(argc * sizeof(char *));
399 fv = (int *)ckalloc(argc * sizeof(int));
400 if (argv == NULL || fv == NULL) {
401 PyErr_NoMemory();
402 goto finally;
406 for (i = 0; i < argc; i++) {
407 PyObject *v = PyTuple_GetItem(args, i);
408 if (PyTuple_Check(v)) {
409 fv[i] = 1;
410 if (!(argv[i] = Merge(v)))
411 goto finally;
412 fvc++;
414 else if (v == Py_None) {
415 argc = i;
416 break;
418 else {
419 fv[i] = 0;
420 if (!(argv[i] = AsString(v, tmp)))
421 goto finally;
422 fvc++;
426 res = Tcl_Merge(argc, argv);
427 if (res == NULL)
428 PyErr_SetString(Tkinter_TclError, "merge failed");
430 finally:
431 for (i = 0; i < fvc; i++)
432 if (fv[i]) {
433 ckfree(argv[i]);
435 if (argv != argvStore)
436 ckfree(FREECAST argv);
437 if (fv != fvStore)
438 ckfree(FREECAST fv);
440 Py_DECREF(tmp);
441 return res;
446 static PyObject *
447 Split(char *list)
449 int argc;
450 char **argv;
451 PyObject *v;
453 if (list == NULL) {
454 Py_INCREF(Py_None);
455 return Py_None;
458 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
459 /* Not a list.
460 * Could be a quoted string containing funnies, e.g. {"}.
461 * Return the string itself.
463 return PyUnicode_FromString(list);
466 if (argc == 0)
467 v = PyUnicode_FromString("");
468 else if (argc == 1)
469 v = PyUnicode_FromString(argv[0]);
470 else if ((v = PyTuple_New(argc)) != NULL) {
471 int i;
472 PyObject *w;
474 for (i = 0; i < argc; i++) {
475 if ((w = Split(argv[i])) == NULL) {
476 Py_DECREF(v);
477 v = NULL;
478 break;
480 PyTuple_SetItem(v, i, w);
483 Tcl_Free(FREECAST argv);
484 return v;
487 /* In some cases, Tcl will still return strings that are supposed to be
488 lists. SplitObj walks through a nested tuple, finding string objects that
489 need to be split. */
491 PyObject *
492 SplitObj(PyObject *arg)
494 if (PyTuple_Check(arg)) {
495 int i, size;
496 PyObject *elem, *newelem, *result;
498 size = PyTuple_Size(arg);
499 result = NULL;
500 /* Recursively invoke SplitObj for all tuple items.
501 If this does not return a new object, no action is
502 needed. */
503 for(i = 0; i < size; i++) {
504 elem = PyTuple_GetItem(arg, i);
505 newelem = SplitObj(elem);
506 if (!newelem) {
507 Py_XDECREF(result);
508 return NULL;
510 if (!result) {
511 int k;
512 if (newelem == elem) {
513 Py_DECREF(newelem);
514 continue;
516 result = PyTuple_New(size);
517 if (!result)
518 return NULL;
519 for(k = 0; k < i; k++) {
520 elem = PyTuple_GetItem(arg, k);
521 Py_INCREF(elem);
522 PyTuple_SetItem(result, k, elem);
525 PyTuple_SetItem(result, i, newelem);
527 if (result)
528 return result;
529 /* Fall through, returning arg. */
531 else if (PyString_Check(arg)) {
532 int argc;
533 char **argv;
534 char *list = PyString_AsString(arg);
536 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
537 Py_INCREF(arg);
538 return arg;
540 Tcl_Free(FREECAST argv);
541 if (argc > 1)
542 return Split(PyString_AsString(arg));
543 /* Fall through, returning arg. */
545 Py_INCREF(arg);
546 return arg;
550 /**** Tkapp Object ****/
552 #ifndef WITH_APPINIT
554 Tcl_AppInit(Tcl_Interp *interp)
556 Tk_Window main;
557 const char * _tkinter_skip_tk_init;
559 if (Tcl_Init(interp) == TCL_ERROR) {
560 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
561 return TCL_ERROR;
563 _tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
564 if (_tkinter_skip_tk_init == NULL || strcmp(_tkinter_skip_tk_init, "1") != 0) {
565 main = Tk_MainWindow(interp);
566 if (Tk_Init(interp) == TCL_ERROR) {
567 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
568 return TCL_ERROR;
571 return TCL_OK;
573 #endif /* !WITH_APPINIT */
578 /* Initialize the Tk application; see the `main' function in
579 * `tkMain.c'.
582 static void EnableEventHook(void); /* Forward */
583 static void DisableEventHook(void); /* Forward */
585 static TkappObject *
586 Tkapp_New(char *screenName, char *baseName, char *className,
587 int interactive, int wantobjects, int wantTk, int sync, char *use)
589 TkappObject *v;
590 char *argv0;
592 v = PyObject_New(TkappObject, &Tkapp_Type);
593 if (v == NULL)
594 return NULL;
596 v->interp = Tcl_CreateInterp();
597 v->wantobjects = wantobjects;
598 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
599 TCL_GLOBAL_ONLY) != NULL;
600 v->thread_id = Tcl_GetCurrentThread();
601 v->dispatching = 0;
603 #ifndef TCL_THREADS
604 if (v->threaded) {
605 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
606 Py_DECREF(v);
607 return 0;
609 #endif
610 #ifdef WITH_THREAD
611 if (v->threaded && tcl_lock) {
612 /* If Tcl is threaded, we don't need the lock. */
613 PyThread_free_lock(tcl_lock);
614 tcl_lock = NULL;
616 #endif
618 v->BooleanType = Tcl_GetObjType("boolean");
619 v->ByteArrayType = Tcl_GetObjType("bytearray");
620 v->DoubleType = Tcl_GetObjType("double");
621 v->IntType = Tcl_GetObjType("int");
622 v->ListType = Tcl_GetObjType("list");
623 v->ProcBodyType = Tcl_GetObjType("procbody");
624 v->StringType = Tcl_GetObjType("string");
626 /* Delete the 'exit' command, which can screw things up */
627 Tcl_DeleteCommand(v->interp, "exit");
629 if (screenName != NULL)
630 Tcl_SetVar2(v->interp, "env", "DISPLAY",
631 screenName, TCL_GLOBAL_ONLY);
633 if (interactive)
634 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
635 else
636 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
638 /* This is used to get the application class for Tk 4.1 and up */
639 argv0 = (char*)ckalloc(strlen(className) + 1);
640 if (!argv0) {
641 PyErr_NoMemory();
642 Py_DECREF(v);
643 return NULL;
646 strcpy(argv0, className);
647 if (isupper(Py_CHARMASK(argv0[0])))
648 argv0[0] = tolower(Py_CHARMASK(argv0[0]));
649 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
650 ckfree(argv0);
652 if (! wantTk) {
653 Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
656 /* some initial arguments need to be in argv */
657 if (sync || use) {
658 char *args;
659 int len = 0;
661 if (sync)
662 len += sizeof "-sync";
663 if (use)
664 len += strlen(use) + sizeof "-use ";
666 args = (char*)ckalloc(len);
667 if (!args) {
668 PyErr_NoMemory();
669 Py_DECREF(v);
670 return NULL;
673 args[0] = '\0';
674 if (sync)
675 strcat(args, "-sync");
676 if (use) {
677 if (sync)
678 strcat(args, " ");
679 strcat(args, "-use ");
680 strcat(args, use);
683 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
684 ckfree(args);
687 if (Tcl_AppInit(v->interp) != TCL_OK) {
688 PyObject *result = Tkinter_Error((PyObject *)v);
689 Py_DECREF((PyObject *)v);
690 return (TkappObject *)result;
693 EnableEventHook();
695 return v;
699 static void
700 Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
701 Tcl_Condition *cond, Tcl_Mutex *mutex)
703 Py_BEGIN_ALLOW_THREADS;
704 Tcl_MutexLock(mutex);
705 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
706 Tcl_ThreadAlert(self->thread_id);
707 Tcl_ConditionWait(cond, mutex, NULL);
708 Tcl_MutexUnlock(mutex);
709 Py_END_ALLOW_THREADS
713 /** Tcl Eval **/
715 typedef struct {
716 PyObject_HEAD
717 Tcl_Obj *value;
718 PyObject *string; /* This cannot cause cycles. */
719 } PyTclObject;
721 static PyTypeObject PyTclObject_Type;
722 #define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
724 static PyObject *
725 newPyTclObject(Tcl_Obj *arg)
727 PyTclObject *self;
728 self = PyObject_New(PyTclObject, &PyTclObject_Type);
729 if (self == NULL)
730 return NULL;
731 Tcl_IncrRefCount(arg);
732 self->value = arg;
733 self->string = NULL;
734 return (PyObject*)self;
737 static void
738 PyTclObject_dealloc(PyTclObject *self)
740 Tcl_DecrRefCount(self->value);
741 Py_XDECREF(self->string);
742 PyObject_Del(self);
745 static char*
746 PyTclObject_TclString(PyObject *self)
748 return Tcl_GetString(((PyTclObject*)self)->value);
751 /* Like _str, but create Unicode if necessary. */
752 PyDoc_STRVAR(PyTclObject_string__doc__,
753 "the string representation of this object, either as str or bytes");
755 static PyObject *
756 PyTclObject_string(PyTclObject *self, void *ignored)
758 char *s;
759 int len;
760 if (!self->string) {
761 s = Tcl_GetStringFromObj(self->value, &len);
762 self->string = PyUnicode_FromStringAndSize(s, len);
763 if (!self->string)
764 return NULL;
766 Py_INCREF(self->string);
767 return self->string;
770 static PyObject *
771 PyTclObject_str(PyTclObject *self, void *ignored)
773 char *s;
774 int len;
775 if (self->string && PyUnicode_Check(self->string)) {
776 Py_INCREF(self->string);
777 return self->string;
779 /* XXX Could chache result if it is non-ASCII. */
780 s = Tcl_GetStringFromObj(self->value, &len);
781 return PyUnicode_DecodeUTF8(s, len, "strict");
784 static PyObject *
785 PyTclObject_repr(PyTclObject *self)
787 return PyUnicode_FromFormat("<%s object at %p>",
788 self->value->typePtr->name, self->value);
791 static int
792 PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
794 int res;
795 res = strcmp(Tcl_GetString(self->value),
796 Tcl_GetString(other->value));
797 if (res < 0) return -1;
798 if (res > 0) return 1;
799 return 0;
802 PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
804 static PyObject*
805 get_typename(PyTclObject* obj, void* ignored)
807 return PyUnicode_FromString(obj->value->typePtr->name);
811 static PyGetSetDef PyTclObject_getsetlist[] = {
812 {"typename", (getter)get_typename, NULL, get_typename__doc__},
813 {"string", (getter)PyTclObject_string, NULL,
814 PyTclObject_string__doc__},
815 {0},
818 static PyTypeObject PyTclObject_Type = {
819 PyVarObject_HEAD_INIT(NULL, 0)
820 "_tkinter.Tcl_Obj", /*tp_name*/
821 sizeof(PyTclObject), /*tp_basicsize*/
822 0, /*tp_itemsize*/
823 /* methods */
824 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
825 0, /*tp_print*/
826 0, /*tp_getattr*/
827 0, /*tp_setattr*/
828 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
829 (reprfunc)PyTclObject_repr, /*tp_repr*/
830 0, /*tp_as_number*/
831 0, /*tp_as_sequence*/
832 0, /*tp_as_mapping*/
833 0, /*tp_hash*/
834 0, /*tp_call*/
835 (reprfunc)PyTclObject_str, /*tp_str*/
836 PyObject_GenericGetAttr,/*tp_getattro*/
837 0, /*tp_setattro*/
838 0, /*tp_as_buffer*/
839 Py_TPFLAGS_DEFAULT, /*tp_flags*/
840 0, /*tp_doc*/
841 0, /*tp_traverse*/
842 0, /*tp_clear*/
843 0, /*tp_richcompare*/
844 0, /*tp_weaklistoffset*/
845 0, /*tp_iter*/
846 0, /*tp_iternext*/
847 0, /*tp_methods*/
848 0, /*tp_members*/
849 PyTclObject_getsetlist, /*tp_getset*/
850 0, /*tp_base*/
851 0, /*tp_dict*/
852 0, /*tp_descr_get*/
853 0, /*tp_descr_set*/
854 0, /*tp_dictoffset*/
855 0, /*tp_init*/
856 0, /*tp_alloc*/
857 0, /*tp_new*/
858 0, /*tp_free*/
859 0, /*tp_is_gc*/
862 static Tcl_Obj*
863 AsObj(PyObject *value)
865 Tcl_Obj *result;
866 long longVal;
867 int overflow;
869 if (PyString_Check(value))
870 return Tcl_NewStringObj(PyString_AS_STRING(value),
871 PyString_GET_SIZE(value));
872 else if (PyBool_Check(value))
873 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
874 else if (PyLong_CheckExact(value) &&
875 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
876 !overflow)) {
877 /* If there is an overflow in the long conversion,
878 fall through to default object handling. */
879 return Tcl_NewLongObj(longVal);
881 else if (PyFloat_Check(value))
882 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
883 else if (PyTuple_Check(value)) {
884 Tcl_Obj **argv = (Tcl_Obj**)
885 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
886 int i;
887 if(!argv)
888 return 0;
889 for(i=0;i<PyTuple_Size(value);i++)
890 argv[i] = AsObj(PyTuple_GetItem(value,i));
891 result = Tcl_NewListObj(PyTuple_Size(value), argv);
892 ckfree(FREECAST argv);
893 return result;
895 else if (PyUnicode_Check(value)) {
896 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
897 Py_ssize_t size = PyUnicode_GET_SIZE(value);
898 /* This #ifdef assumes that Tcl uses UCS-2.
899 See TCL_UTF_MAX test above. */
900 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
901 Tcl_UniChar *outbuf = NULL;
902 Py_ssize_t i;
903 size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
904 if (allocsize >= size)
905 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
906 /* Else overflow occurred, and we take the next exit */
907 if (!outbuf) {
908 PyErr_NoMemory();
909 return NULL;
911 for (i = 0; i < size; i++) {
912 if (inbuf[i] >= 0x10000) {
913 /* Tcl doesn't do UTF-16, yet. */
914 PyErr_SetString(PyExc_ValueError,
915 "unsupported character");
916 ckfree(FREECAST outbuf);
917 return NULL;
919 outbuf[i] = inbuf[i];
921 result = Tcl_NewUnicodeObj(outbuf, size);
922 ckfree(FREECAST outbuf);
923 return result;
924 #else
925 return Tcl_NewUnicodeObj(inbuf, size);
926 #endif
929 else if(PyTclObject_Check(value)) {
930 Tcl_Obj *v = ((PyTclObject*)value)->value;
931 Tcl_IncrRefCount(v);
932 return v;
934 else {
935 PyObject *v = PyObject_Str(value);
936 if (!v)
937 return 0;
938 result = AsObj(v);
939 Py_DECREF(v);
940 return result;
944 static PyObject*
945 FromObj(PyObject* tkapp, Tcl_Obj *value)
947 PyObject *result = NULL;
948 TkappObject *app = (TkappObject*)tkapp;
950 if (value->typePtr == NULL) {
951 return PyUnicode_FromStringAndSize(value->bytes,
952 value->length);
955 if (value->typePtr == app->BooleanType) {
956 result = value->internalRep.longValue ? Py_True : Py_False;
957 Py_INCREF(result);
958 return result;
961 if (value->typePtr == app->ByteArrayType) {
962 int size;
963 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
964 return PyString_FromStringAndSize(data, size);
967 if (value->typePtr == app->DoubleType) {
968 return PyFloat_FromDouble(value->internalRep.doubleValue);
971 if (value->typePtr == app->IntType) {
972 return PyLong_FromLong(value->internalRep.longValue);
975 if (value->typePtr == app->ListType) {
976 int size;
977 int i, status;
978 PyObject *elem;
979 Tcl_Obj *tcl_elem;
981 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
982 if (status == TCL_ERROR)
983 return Tkinter_Error(tkapp);
984 result = PyTuple_New(size);
985 if (!result)
986 return NULL;
987 for (i = 0; i < size; i++) {
988 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
989 value, i, &tcl_elem);
990 if (status == TCL_ERROR) {
991 Py_DECREF(result);
992 return Tkinter_Error(tkapp);
994 elem = FromObj(tkapp, tcl_elem);
995 if (!elem) {
996 Py_DECREF(result);
997 return NULL;
999 PyTuple_SetItem(result, i, elem);
1001 return result;
1004 if (value->typePtr == app->ProcBodyType) {
1005 /* fall through: return tcl object. */
1008 if (value->typePtr == app->StringType) {
1009 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1010 PyObject *result;
1011 int size;
1012 Tcl_UniChar *input;
1013 Py_UNICODE *output;
1015 size = Tcl_GetCharLength(value);
1016 result = PyUnicode_FromUnicode(NULL, size);
1017 if (!result)
1018 return NULL;
1019 input = Tcl_GetUnicode(value);
1020 output = PyUnicode_AS_UNICODE(result);
1021 while (size--)
1022 *output++ = *input++;
1023 return result;
1024 #else
1025 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1026 Tcl_GetCharLength(value));
1027 #endif
1030 return newPyTclObject(value);
1033 /* This mutex synchronizes inter-thread command calls. */
1035 TCL_DECLARE_MUTEX(call_mutex)
1037 typedef struct Tkapp_CallEvent {
1038 Tcl_Event ev; /* Must be first */
1039 TkappObject *self;
1040 PyObject *args;
1041 int flags;
1042 PyObject **res;
1043 PyObject **exc_type, **exc_value, **exc_tb;
1044 Tcl_Condition done;
1045 } Tkapp_CallEvent;
1047 void
1048 Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
1050 int i;
1051 for (i = 0; i < objc; i++)
1052 Tcl_DecrRefCount(objv[i]);
1053 if (objv != objStore)
1054 ckfree(FREECAST objv);
1057 /* Convert Python objects to Tcl objects. This must happen in the
1058 interpreter thread, which may or may not be the calling thread. */
1060 static Tcl_Obj**
1061 Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1063 Tcl_Obj **objv = objStore;
1064 int objc = 0, i;
1065 if (args == NULL)
1066 /* do nothing */;
1068 else if (!PyTuple_Check(args)) {
1069 objv[0] = AsObj(args);
1070 if (objv[0] == 0)
1071 goto finally;
1072 objc = 1;
1073 Tcl_IncrRefCount(objv[0]);
1075 else {
1076 objc = PyTuple_Size(args);
1078 if (objc > ARGSZ) {
1079 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1080 if (objv == NULL) {
1081 PyErr_NoMemory();
1082 objc = 0;
1083 goto finally;
1087 for (i = 0; i < objc; i++) {
1088 PyObject *v = PyTuple_GetItem(args, i);
1089 if (v == Py_None) {
1090 objc = i;
1091 break;
1093 objv[i] = AsObj(v);
1094 if (!objv[i]) {
1095 /* Reset objc, so it attempts to clear
1096 objects only up to i. */
1097 objc = i;
1098 goto finally;
1100 Tcl_IncrRefCount(objv[i]);
1103 *pobjc = objc;
1104 return objv;
1105 finally:
1106 Tkapp_CallDeallocArgs(objv, objStore, objc);
1107 return NULL;
1110 /* Convert the results of a command call into a Python objects. */
1112 static PyObject*
1113 Tkapp_CallResult(TkappObject *self)
1115 PyObject *res = NULL;
1116 if(self->wantobjects) {
1117 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1118 /* Not sure whether the IncrRef is necessary, but something
1119 may overwrite the interpreter result while we are
1120 converting it. */
1121 Tcl_IncrRefCount(value);
1122 res = FromObj((PyObject*)self, value);
1123 Tcl_DecrRefCount(value);
1124 } else {
1125 const char *s = Tcl_GetStringResult(self->interp);
1126 const char *p = s;
1128 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1130 return res;
1133 /* Tkapp_CallProc is the event procedure that is executed in the context of
1134 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1135 hold the Python lock. */
1137 static int
1138 Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1140 Tcl_Obj *objStore[ARGSZ];
1141 Tcl_Obj **objv;
1142 int objc;
1143 int i;
1144 ENTER_PYTHON
1145 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1146 if (!objv) {
1147 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1148 *(e->res) = NULL;
1150 LEAVE_PYTHON
1151 if (!objv)
1152 goto done;
1153 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1154 ENTER_PYTHON
1155 if (i == TCL_ERROR) {
1156 *(e->res) = NULL;
1157 *(e->exc_type) = NULL;
1158 *(e->exc_tb) = NULL;
1159 *(e->exc_value) = PyObject_CallFunction(
1160 Tkinter_TclError, "s",
1161 Tcl_GetStringResult(e->self->interp));
1163 else {
1164 *(e->res) = Tkapp_CallResult(e->self);
1166 LEAVE_PYTHON
1167 done:
1168 /* Wake up calling thread. */
1169 Tcl_MutexLock(&call_mutex);
1170 Tcl_ConditionNotify(&e->done);
1171 Tcl_MutexUnlock(&call_mutex);
1172 return 1;
1175 /* This is the main entry point for calling a Tcl command.
1176 It supports three cases, with regard to threading:
1177 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1178 the context of the calling thread.
1179 2. Tcl is threaded, caller of the command is in the interpreter thread:
1180 Execute the command in the calling thread. Since the Tcl lock will
1181 not be used, we can merge that with case 1.
1182 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1183 the interpreter thread. Allocation of Tcl objects needs to occur in the
1184 interpreter thread, so we ship the PyObject* args to the target thread,
1185 and perform processing there. */
1187 static PyObject *
1188 Tkapp_Call(PyObject *selfptr, PyObject *args)
1190 Tcl_Obj *objStore[ARGSZ];
1191 Tcl_Obj **objv = NULL;
1192 int objc, i;
1193 PyObject *res = NULL;
1194 TkappObject *self = (TkappObject*)selfptr;
1195 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1196 int flags = TCL_EVAL_DIRECT;
1198 /* If args is a single tuple, replace with contents of tuple */
1199 if (1 == PyTuple_Size(args)){
1200 PyObject* item = PyTuple_GetItem(args, 0);
1201 if (PyTuple_Check(item))
1202 args = item;
1204 #ifdef WITH_THREAD
1205 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1206 /* We cannot call the command directly. Instead, we must
1207 marshal the parameters to the interpreter thread. */
1208 Tkapp_CallEvent *ev;
1209 PyObject *exc_type, *exc_value, *exc_tb;
1210 if (!WaitForMainloop(self))
1211 return NULL;
1212 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1213 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1214 ev->self = self;
1215 ev->args = args;
1216 ev->res = &res;
1217 ev->exc_type = &exc_type;
1218 ev->exc_value = &exc_value;
1219 ev->exc_tb = &exc_tb;
1220 ev->done = (Tcl_Condition)0;
1222 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1224 if (res == NULL) {
1225 if (exc_type)
1226 PyErr_Restore(exc_type, exc_value, exc_tb);
1227 else
1228 PyErr_SetObject(Tkinter_TclError, exc_value);
1231 else
1232 #endif
1235 objv = Tkapp_CallArgs(args, objStore, &objc);
1236 if (!objv)
1237 return NULL;
1239 ENTER_TCL
1241 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1243 ENTER_OVERLAP
1245 if (i == TCL_ERROR)
1246 Tkinter_Error(selfptr);
1247 else
1248 res = Tkapp_CallResult(self);
1250 LEAVE_OVERLAP_TCL
1252 Tkapp_CallDeallocArgs(objv, objStore, objc);
1254 return res;
1258 static PyObject *
1259 Tkapp_GlobalCall(PyObject *self, PyObject *args)
1261 /* Could do the same here as for Tkapp_Call(), but this is not used
1262 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1263 way for the user to do what all its Global* variants do (save and
1264 reset the scope pointer, call the local version, restore the saved
1265 scope pointer). */
1267 char *cmd;
1268 PyObject *res = NULL;
1270 CHECK_TCL_APPARTMENT;
1272 cmd = Merge(args);
1273 if (cmd) {
1274 int err;
1275 ENTER_TCL
1276 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1277 ENTER_OVERLAP
1278 if (err == TCL_ERROR)
1279 res = Tkinter_Error(self);
1280 else
1281 res = PyUnicode_FromString(Tkapp_Result(self));
1282 LEAVE_OVERLAP_TCL
1283 ckfree(cmd);
1286 return res;
1289 static PyObject *
1290 Tkapp_Eval(PyObject *self, PyObject *args)
1292 char *script;
1293 PyObject *res = NULL;
1294 int err;
1296 if (!PyArg_ParseTuple(args, "s:eval", &script))
1297 return NULL;
1299 CHECK_TCL_APPARTMENT;
1301 ENTER_TCL
1302 err = Tcl_Eval(Tkapp_Interp(self), script);
1303 ENTER_OVERLAP
1304 if (err == TCL_ERROR)
1305 res = Tkinter_Error(self);
1306 else
1307 res = PyUnicode_FromString(Tkapp_Result(self));
1308 LEAVE_OVERLAP_TCL
1309 return res;
1312 static PyObject *
1313 Tkapp_GlobalEval(PyObject *self, PyObject *args)
1315 char *script;
1316 PyObject *res = NULL;
1317 int err;
1319 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1320 return NULL;
1322 CHECK_TCL_APPARTMENT;
1324 ENTER_TCL
1325 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1326 ENTER_OVERLAP
1327 if (err == TCL_ERROR)
1328 res = Tkinter_Error(self);
1329 else
1330 res = PyUnicode_FromString(Tkapp_Result(self));
1331 LEAVE_OVERLAP_TCL
1332 return res;
1335 static PyObject *
1336 Tkapp_EvalFile(PyObject *self, PyObject *args)
1338 char *fileName;
1339 PyObject *res = NULL;
1340 int err;
1342 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1343 return NULL;
1345 CHECK_TCL_APPARTMENT;
1347 ENTER_TCL
1348 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1349 ENTER_OVERLAP
1350 if (err == TCL_ERROR)
1351 res = Tkinter_Error(self);
1353 else
1354 res = PyUnicode_FromString(Tkapp_Result(self));
1355 LEAVE_OVERLAP_TCL
1356 return res;
1359 static PyObject *
1360 Tkapp_Record(PyObject *self, PyObject *args)
1362 char *script;
1363 PyObject *res = NULL;
1364 int err;
1366 if (!PyArg_ParseTuple(args, "s", &script))
1367 return NULL;
1369 CHECK_TCL_APPARTMENT;
1371 ENTER_TCL
1372 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1373 ENTER_OVERLAP
1374 if (err == TCL_ERROR)
1375 res = Tkinter_Error(self);
1376 else
1377 res = PyUnicode_FromString(Tkapp_Result(self));
1378 LEAVE_OVERLAP_TCL
1379 return res;
1382 static PyObject *
1383 Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
1385 char *msg;
1387 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1388 return NULL;
1389 CHECK_TCL_APPARTMENT;
1391 ENTER_TCL
1392 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1393 LEAVE_TCL
1395 Py_INCREF(Py_None);
1396 return Py_None;
1401 /** Tcl Variable **/
1403 TCL_DECLARE_MUTEX(var_mutex)
1405 typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1406 typedef struct VarEvent {
1407 Tcl_Event ev; /* must be first */
1408 PyObject *self;
1409 PyObject *args;
1410 int flags;
1411 EventFunc func;
1412 PyObject **res;
1413 PyObject **exc_type;
1414 PyObject **exc_val;
1415 Tcl_Condition cond;
1416 } VarEvent;
1418 static int
1419 varname_converter(PyObject *in, void *_out)
1421 char **out = (char**)_out;
1422 if (PyString_Check(in)) {
1423 *out = PyString_AsString(in);
1424 return 1;
1426 if (PyUnicode_Check(in)) {
1427 *out = PyUnicode_AsString(in);
1428 return 1;
1430 if (PyTclObject_Check(in)) {
1431 *out = PyTclObject_TclString(in);
1432 return 1;
1434 /* XXX: Should give diagnostics. */
1435 return 0;
1438 void
1439 var_perform(VarEvent *ev)
1441 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1442 if (!*(ev->res)) {
1443 PyObject *exc, *val, *tb;
1444 PyErr_Fetch(&exc, &val, &tb);
1445 PyErr_NormalizeException(&exc, &val, &tb);
1446 *(ev->exc_type) = exc;
1447 *(ev->exc_val) = val;
1448 Py_DECREF(tb);
1453 static int
1454 var_proc(VarEvent* ev, int flags)
1456 ENTER_PYTHON
1457 var_perform(ev);
1458 Tcl_MutexLock(&var_mutex);
1459 Tcl_ConditionNotify(&ev->cond);
1460 Tcl_MutexUnlock(&var_mutex);
1461 LEAVE_PYTHON
1462 return 1;
1465 static PyObject*
1466 var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
1468 TkappObject *self = (TkappObject*)selfptr;
1469 #ifdef WITH_THREAD
1470 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1471 TkappObject *self = (TkappObject*)selfptr;
1472 VarEvent *ev;
1473 PyObject *res, *exc_type, *exc_val;
1475 /* The current thread is not the interpreter thread. Marshal
1476 the call to the interpreter thread, then wait for
1477 completion. */
1478 if (!WaitForMainloop(self))
1479 return NULL;
1481 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1483 ev->self = selfptr;
1484 ev->args = args;
1485 ev->flags = flags;
1486 ev->func = func;
1487 ev->res = &res;
1488 ev->exc_type = &exc_type;
1489 ev->exc_val = &exc_val;
1490 ev->cond = NULL;
1491 ev->ev.proc = (Tcl_EventProc*)var_proc;
1492 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1493 if (!res) {
1494 PyErr_SetObject(exc_type, exc_val);
1495 Py_DECREF(exc_type);
1496 Py_DECREF(exc_val);
1497 return NULL;
1499 return res;
1501 #endif
1502 /* Tcl is not threaded, or this is the interpreter thread. */
1503 return func(selfptr, args, flags);
1506 static PyObject *
1507 SetVar(PyObject *self, PyObject *args, int flags)
1509 char *name1, *name2;
1510 PyObject *newValue;
1511 PyObject *res = NULL;
1512 Tcl_Obj *newval, *ok;
1514 if (PyArg_ParseTuple(args, "O&O:setvar",
1515 varname_converter, &name1, &newValue)) {
1516 /* XXX Acquire tcl lock??? */
1517 newval = AsObj(newValue);
1518 if (newval == NULL)
1519 return NULL;
1520 ENTER_TCL
1521 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1522 newval, flags);
1523 ENTER_OVERLAP
1524 if (!ok)
1525 Tkinter_Error(self);
1526 else {
1527 res = Py_None;
1528 Py_INCREF(res);
1530 LEAVE_OVERLAP_TCL
1532 else {
1533 PyErr_Clear();
1534 if (PyArg_ParseTuple(args, "ssO:setvar",
1535 &name1, &name2, &newValue)) {
1536 /* XXX must hold tcl lock already??? */
1537 newval = AsObj(newValue);
1538 ENTER_TCL
1539 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1540 ENTER_OVERLAP
1541 if (!ok)
1542 Tkinter_Error(self);
1543 else {
1544 res = Py_None;
1545 Py_INCREF(res);
1547 LEAVE_OVERLAP_TCL
1549 else {
1550 return NULL;
1553 return res;
1556 static PyObject *
1557 Tkapp_SetVar(PyObject *self, PyObject *args)
1559 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1562 static PyObject *
1563 Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
1565 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1570 static PyObject *
1571 GetVar(PyObject *self, PyObject *args, int flags)
1573 char *name1, *name2=NULL;
1574 PyObject *res = NULL;
1575 Tcl_Obj *tres;
1577 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1578 varname_converter, &name1, &name2))
1579 return NULL;
1581 ENTER_TCL
1582 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1583 ENTER_OVERLAP
1584 if (tres == NULL) {
1585 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1586 } else {
1587 if (((TkappObject*)self)->wantobjects) {
1588 res = FromObj(self, tres);
1590 else {
1591 res = PyUnicode_FromString(Tcl_GetString(tres));
1594 LEAVE_OVERLAP_TCL
1595 return res;
1598 static PyObject *
1599 Tkapp_GetVar(PyObject *self, PyObject *args)
1601 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1604 static PyObject *
1605 Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1607 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1612 static PyObject *
1613 UnsetVar(PyObject *self, PyObject *args, int flags)
1615 char *name1, *name2=NULL;
1616 int code;
1617 PyObject *res = NULL;
1619 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1620 return NULL;
1622 ENTER_TCL
1623 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1624 ENTER_OVERLAP
1625 if (code == TCL_ERROR)
1626 res = Tkinter_Error(self);
1627 else {
1628 Py_INCREF(Py_None);
1629 res = Py_None;
1631 LEAVE_OVERLAP_TCL
1632 return res;
1635 static PyObject *
1636 Tkapp_UnsetVar(PyObject *self, PyObject *args)
1638 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1641 static PyObject *
1642 Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1644 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1649 /** Tcl to Python **/
1651 static PyObject *
1652 Tkapp_GetInt(PyObject *self, PyObject *args)
1654 char *s;
1655 int v;
1657 if (PyTuple_Size(args) == 1) {
1658 PyObject* o = PyTuple_GetItem(args, 0);
1659 if (PyLong_Check(o)) {
1660 Py_INCREF(o);
1661 return o;
1664 if (!PyArg_ParseTuple(args, "s:getint", &s))
1665 return NULL;
1666 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1667 return Tkinter_Error(self);
1668 return Py_BuildValue("i", v);
1671 static PyObject *
1672 Tkapp_GetDouble(PyObject *self, PyObject *args)
1674 char *s;
1675 double v;
1677 if (PyTuple_Size(args) == 1) {
1678 PyObject *o = PyTuple_GetItem(args, 0);
1679 if (PyFloat_Check(o)) {
1680 Py_INCREF(o);
1681 return o;
1684 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1685 return NULL;
1686 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1687 return Tkinter_Error(self);
1688 return Py_BuildValue("d", v);
1691 static PyObject *
1692 Tkapp_GetBoolean(PyObject *self, PyObject *args)
1694 char *s;
1695 int v;
1697 if (PyTuple_Size(args) == 1) {
1698 PyObject *o = PyTuple_GetItem(args, 0);
1699 if (PyLong_Check(o)) {
1700 Py_INCREF(o);
1701 return o;
1704 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1705 return NULL;
1706 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1707 return Tkinter_Error(self);
1708 return PyBool_FromLong(v);
1711 static PyObject *
1712 Tkapp_ExprString(PyObject *self, PyObject *args)
1714 char *s;
1715 PyObject *res = NULL;
1716 int retval;
1718 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1719 return NULL;
1721 CHECK_TCL_APPARTMENT;
1723 ENTER_TCL
1724 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1725 ENTER_OVERLAP
1726 if (retval == TCL_ERROR)
1727 res = Tkinter_Error(self);
1728 else
1729 res = Py_BuildValue("s", Tkapp_Result(self));
1730 LEAVE_OVERLAP_TCL
1731 return res;
1734 static PyObject *
1735 Tkapp_ExprLong(PyObject *self, PyObject *args)
1737 char *s;
1738 PyObject *res = NULL;
1739 int retval;
1740 long v;
1742 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1743 return NULL;
1745 CHECK_TCL_APPARTMENT;
1747 ENTER_TCL
1748 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1749 ENTER_OVERLAP
1750 if (retval == TCL_ERROR)
1751 res = Tkinter_Error(self);
1752 else
1753 res = Py_BuildValue("l", v);
1754 LEAVE_OVERLAP_TCL
1755 return res;
1758 static PyObject *
1759 Tkapp_ExprDouble(PyObject *self, PyObject *args)
1761 char *s;
1762 PyObject *res = NULL;
1763 double v;
1764 int retval;
1766 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1767 return NULL;
1768 CHECK_TCL_APPARTMENT;
1769 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1770 ENTER_TCL
1771 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1772 ENTER_OVERLAP
1773 PyFPE_END_PROTECT(retval)
1774 if (retval == TCL_ERROR)
1775 res = Tkinter_Error(self);
1776 else
1777 res = Py_BuildValue("d", v);
1778 LEAVE_OVERLAP_TCL
1779 return res;
1782 static PyObject *
1783 Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1785 char *s;
1786 PyObject *res = NULL;
1787 int retval;
1788 int v;
1790 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1791 return NULL;
1792 CHECK_TCL_APPARTMENT;
1793 ENTER_TCL
1794 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1795 ENTER_OVERLAP
1796 if (retval == TCL_ERROR)
1797 res = Tkinter_Error(self);
1798 else
1799 res = Py_BuildValue("i", v);
1800 LEAVE_OVERLAP_TCL
1801 return res;
1806 static PyObject *
1807 Tkapp_SplitList(PyObject *self, PyObject *args)
1809 char *list;
1810 int argc;
1811 char **argv;
1812 PyObject *v;
1813 int i;
1815 if (PyTuple_Size(args) == 1) {
1816 v = PyTuple_GetItem(args, 0);
1817 if (PyTuple_Check(v)) {
1818 Py_INCREF(v);
1819 return v;
1822 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1823 return NULL;
1825 if (Tcl_SplitList(Tkapp_Interp(self), list,
1826 &argc, &argv) == TCL_ERROR) {
1827 PyMem_Free(list);
1828 return Tkinter_Error(self);
1831 if (!(v = PyTuple_New(argc)))
1832 goto finally;
1834 for (i = 0; i < argc; i++) {
1835 PyObject *s = PyUnicode_FromString(argv[i]);
1836 if (!s || PyTuple_SetItem(v, i, s)) {
1837 Py_DECREF(v);
1838 v = NULL;
1839 goto finally;
1843 finally:
1844 ckfree(FREECAST argv);
1845 PyMem_Free(list);
1846 return v;
1849 static PyObject *
1850 Tkapp_Split(PyObject *self, PyObject *args)
1852 PyObject *v;
1853 char *list;
1855 if (PyTuple_Size(args) == 1) {
1856 PyObject* o = PyTuple_GetItem(args, 0);
1857 if (PyTuple_Check(o)) {
1858 o = SplitObj(o);
1859 return o;
1862 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1863 return NULL;
1864 v = Split(list);
1865 PyMem_Free(list);
1866 return v;
1869 static PyObject *
1870 Tkapp_Merge(PyObject *self, PyObject *args)
1872 char *s = Merge(args);
1873 PyObject *res = NULL;
1875 if (s) {
1876 res = PyUnicode_FromString(s);
1877 ckfree(s);
1880 return res;
1885 /** Tcl Command **/
1887 /* Client data struct */
1888 typedef struct {
1889 PyObject *self;
1890 PyObject *func;
1891 } PythonCmd_ClientData;
1893 static int
1894 PythonCmd_Error(Tcl_Interp *interp)
1896 errorInCmd = 1;
1897 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1898 LEAVE_PYTHON
1899 return TCL_ERROR;
1902 /* This is the Tcl command that acts as a wrapper for Python
1903 * function or method.
1905 static int
1906 PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1908 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1909 PyObject *self, *func, *arg, *res, *s;
1910 int i, rv;
1911 Tcl_Obj *obj_res;
1913 ENTER_PYTHON
1915 /* TBD: no error checking here since we know, via the
1916 * Tkapp_CreateCommand() that the client data is a two-tuple
1918 self = data->self;
1919 func = data->func;
1921 /* Create argument list (argv1, ..., argvN) */
1922 if (!(arg = PyTuple_New(argc - 1)))
1923 return PythonCmd_Error(interp);
1925 for (i = 0; i < (argc - 1); i++) {
1926 if (11 == (i + 1)) { /* the %A arg is the unicode char */
1927 char *a = argv[i + 1];
1928 s = PyUnicode_FromUnicode((Py_UNICODE *) a, strlen(a));
1930 else {
1931 s = PyUnicode_FromString(argv[i + 1]);
1933 if (!s || PyTuple_SetItem(arg, i, s)) {
1934 Py_DECREF(arg);
1935 return PythonCmd_Error(interp);
1938 res = PyEval_CallObject(func, arg);
1939 Py_DECREF(arg);
1941 if (res == NULL)
1942 return PythonCmd_Error(interp);
1944 obj_res = AsObj(res);
1945 if (obj_res == NULL) {
1946 Py_DECREF(res);
1947 return PythonCmd_Error(interp);
1949 else {
1950 Tcl_SetObjResult(Tkapp_Interp(self), obj_res);
1951 rv = TCL_OK;
1954 Py_DECREF(res);
1956 LEAVE_PYTHON
1958 return rv;
1961 static void
1962 PythonCmdDelete(ClientData clientData)
1964 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1966 ENTER_PYTHON
1967 Py_XDECREF(data->self);
1968 Py_XDECREF(data->func);
1969 PyMem_DEL(data);
1970 LEAVE_PYTHON
1976 TCL_DECLARE_MUTEX(command_mutex)
1978 typedef struct CommandEvent{
1979 Tcl_Event ev;
1980 Tcl_Interp* interp;
1981 char *name;
1982 int create;
1983 int *status;
1984 ClientData *data;
1985 Tcl_Condition done;
1986 } CommandEvent;
1988 static int
1989 Tkapp_CommandProc(CommandEvent *ev, int flags)
1991 if (ev->create)
1992 *ev->status = Tcl_CreateCommand(
1993 ev->interp, ev->name, PythonCmd,
1994 ev->data, PythonCmdDelete) == NULL;
1995 else
1996 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
1997 Tcl_MutexLock(&command_mutex);
1998 Tcl_ConditionNotify(&ev->done);
1999 Tcl_MutexUnlock(&command_mutex);
2000 return 1;
2003 static PyObject *
2004 Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2006 TkappObject *self = (TkappObject*)selfptr;
2007 PythonCmd_ClientData *data;
2008 char *cmdName;
2009 PyObject *func;
2010 int err;
2012 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2013 return NULL;
2014 if (!PyCallable_Check(func)) {
2015 PyErr_SetString(PyExc_TypeError, "command not callable");
2016 return NULL;
2019 #ifdef WITH_THREAD
2020 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2021 !WaitForMainloop(self))
2022 return NULL;
2023 #endif
2025 data = PyMem_NEW(PythonCmd_ClientData, 1);
2026 if (!data)
2027 return PyErr_NoMemory();
2028 Py_INCREF(self);
2029 Py_INCREF(func);
2030 data->self = selfptr;
2031 data->func = func;
2033 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2034 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2035 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2036 ev->interp = self->interp;
2037 ev->create = 1;
2038 ev->name = cmdName;
2039 ev->data = (ClientData)data;
2040 ev->status = &err;
2041 ev->done = NULL;
2042 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2044 else {
2045 ENTER_TCL
2046 err = Tcl_CreateCommand(
2047 Tkapp_Interp(self), cmdName, PythonCmd,
2048 (ClientData)data, PythonCmdDelete) == NULL;
2049 LEAVE_TCL
2051 if (err) {
2052 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2053 PyMem_DEL(data);
2054 return NULL;
2057 Py_INCREF(Py_None);
2058 return Py_None;
2063 static PyObject *
2064 Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2066 TkappObject *self = (TkappObject*)selfptr;
2067 char *cmdName;
2068 int err;
2070 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2071 return NULL;
2072 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2073 CommandEvent *ev;
2074 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2075 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2076 ev->interp = self->interp;
2077 ev->create = 0;
2078 ev->name = cmdName;
2079 ev->status = &err;
2080 ev->done = NULL;
2081 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2082 &command_mutex);
2084 else {
2085 ENTER_TCL
2086 err = Tcl_DeleteCommand(self->interp, cmdName);
2087 LEAVE_TCL
2089 if (err == -1) {
2090 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2091 return NULL;
2093 Py_INCREF(Py_None);
2094 return Py_None;
2099 #ifdef HAVE_CREATEFILEHANDLER
2100 /** File Handler **/
2102 typedef struct _fhcdata {
2103 PyObject *func;
2104 PyObject *file;
2105 int id;
2106 struct _fhcdata *next;
2107 } FileHandler_ClientData;
2109 static FileHandler_ClientData *HeadFHCD;
2111 static FileHandler_ClientData *
2112 NewFHCD(PyObject *func, PyObject *file, int id)
2114 FileHandler_ClientData *p;
2115 p = PyMem_NEW(FileHandler_ClientData, 1);
2116 if (p != NULL) {
2117 Py_XINCREF(func);
2118 Py_XINCREF(file);
2119 p->func = func;
2120 p->file = file;
2121 p->id = id;
2122 p->next = HeadFHCD;
2123 HeadFHCD = p;
2125 return p;
2128 static void
2129 DeleteFHCD(int id)
2131 FileHandler_ClientData *p, **pp;
2133 pp = &HeadFHCD;
2134 while ((p = *pp) != NULL) {
2135 if (p->id == id) {
2136 *pp = p->next;
2137 Py_XDECREF(p->func);
2138 Py_XDECREF(p->file);
2139 PyMem_DEL(p);
2141 else
2142 pp = &p->next;
2146 static void
2147 FileHandler(ClientData clientData, int mask)
2149 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2150 PyObject *func, *file, *arg, *res;
2152 ENTER_PYTHON
2153 func = data->func;
2154 file = data->file;
2156 arg = Py_BuildValue("(Oi)", file, (long) mask);
2157 res = PyEval_CallObject(func, arg);
2158 Py_DECREF(arg);
2160 if (res == NULL) {
2161 errorInCmd = 1;
2162 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2164 Py_XDECREF(res);
2165 LEAVE_PYTHON
2168 static PyObject *
2169 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2170 /* args is (file, mask, func) */
2172 FileHandler_ClientData *data;
2173 PyObject *file, *func;
2174 int mask, tfile;
2176 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2177 &file, &mask, &func))
2178 return NULL;
2180 #ifdef WITH_THREAD
2181 if (!self && !tcl_lock) {
2182 /* We don't have the Tcl lock since Tcl is threaded. */
2183 PyErr_SetString(PyExc_RuntimeError,
2184 "_tkinter.createfilehandler not supported "
2185 "for threaded Tcl");
2186 return NULL;
2188 #endif
2190 if (self) {
2191 CHECK_TCL_APPARTMENT;
2194 tfile = PyObject_AsFileDescriptor(file);
2195 if (tfile < 0)
2196 return NULL;
2197 if (!PyCallable_Check(func)) {
2198 PyErr_SetString(PyExc_TypeError, "bad argument list");
2199 return NULL;
2202 data = NewFHCD(func, file, tfile);
2203 if (data == NULL)
2204 return NULL;
2206 /* Ought to check for null Tcl_File object... */
2207 ENTER_TCL
2208 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2209 LEAVE_TCL
2210 Py_INCREF(Py_None);
2211 return Py_None;
2214 static PyObject *
2215 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2217 PyObject *file;
2218 int tfile;
2220 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2221 return NULL;
2223 #ifdef WITH_THREAD
2224 if (!self && !tcl_lock) {
2225 /* We don't have the Tcl lock since Tcl is threaded. */
2226 PyErr_SetString(PyExc_RuntimeError,
2227 "_tkinter.deletefilehandler not supported "
2228 "for threaded Tcl");
2229 return NULL;
2231 #endif
2233 if (self) {
2234 CHECK_TCL_APPARTMENT;
2237 tfile = PyObject_AsFileDescriptor(file);
2238 if (tfile < 0)
2239 return NULL;
2241 DeleteFHCD(tfile);
2243 /* Ought to check for null Tcl_File object... */
2244 ENTER_TCL
2245 Tcl_DeleteFileHandler(tfile);
2246 LEAVE_TCL
2247 Py_INCREF(Py_None);
2248 return Py_None;
2250 #endif /* HAVE_CREATEFILEHANDLER */
2253 /**** Tktt Object (timer token) ****/
2255 static PyTypeObject Tktt_Type;
2257 typedef struct {
2258 PyObject_HEAD
2259 Tcl_TimerToken token;
2260 PyObject *func;
2261 } TkttObject;
2263 static PyObject *
2264 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2266 TkttObject *v = (TkttObject *)self;
2267 PyObject *func = v->func;
2269 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2270 return NULL;
2271 if (v->token != NULL) {
2272 Tcl_DeleteTimerHandler(v->token);
2273 v->token = NULL;
2275 if (func != NULL) {
2276 v->func = NULL;
2277 Py_DECREF(func);
2278 Py_DECREF(v); /* See Tktt_New() */
2280 Py_INCREF(Py_None);
2281 return Py_None;
2284 static PyMethodDef Tktt_methods[] =
2286 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2287 {NULL, NULL}
2290 static TkttObject *
2291 Tktt_New(PyObject *func)
2293 TkttObject *v;
2295 v = PyObject_New(TkttObject, &Tktt_Type);
2296 if (v == NULL)
2297 return NULL;
2299 Py_INCREF(func);
2300 v->token = NULL;
2301 v->func = func;
2303 /* Extra reference, deleted when called or when handler is deleted */
2304 Py_INCREF(v);
2305 return v;
2308 static void
2309 Tktt_Dealloc(PyObject *self)
2311 TkttObject *v = (TkttObject *)self;
2312 PyObject *func = v->func;
2314 Py_XDECREF(func);
2316 PyObject_Del(self);
2319 static PyObject *
2320 Tktt_Repr(PyObject *self)
2322 TkttObject *v = (TkttObject *)self;
2323 char buf[100];
2325 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2326 v->func == NULL ? ", handler deleted" : "");
2327 return PyUnicode_FromString(buf);
2330 static PyObject *
2331 Tktt_GetAttr(PyObject *self, char *name)
2333 return Py_FindMethod(Tktt_methods, self, name);
2336 static PyTypeObject Tktt_Type =
2338 PyVarObject_HEAD_INIT(NULL, 0)
2339 "tktimertoken", /*tp_name */
2340 sizeof(TkttObject), /*tp_basicsize */
2341 0, /*tp_itemsize */
2342 Tktt_Dealloc, /*tp_dealloc */
2343 0, /*tp_print */
2344 Tktt_GetAttr, /*tp_getattr */
2345 0, /*tp_setattr */
2346 0, /*tp_compare */
2347 Tktt_Repr, /*tp_repr */
2348 0, /*tp_as_number */
2349 0, /*tp_as_sequence */
2350 0, /*tp_as_mapping */
2351 0, /*tp_hash */
2356 /** Timer Handler **/
2358 static void
2359 TimerHandler(ClientData clientData)
2361 TkttObject *v = (TkttObject *)clientData;
2362 PyObject *func = v->func;
2363 PyObject *res;
2365 if (func == NULL)
2366 return;
2368 v->func = NULL;
2370 ENTER_PYTHON
2372 res = PyEval_CallObject(func, NULL);
2373 Py_DECREF(func);
2374 Py_DECREF(v); /* See Tktt_New() */
2376 if (res == NULL) {
2377 errorInCmd = 1;
2378 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2380 else
2381 Py_DECREF(res);
2383 LEAVE_PYTHON
2386 static PyObject *
2387 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2389 int milliseconds;
2390 PyObject *func;
2391 TkttObject *v;
2393 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2394 &milliseconds, &func))
2395 return NULL;
2396 if (!PyCallable_Check(func)) {
2397 PyErr_SetString(PyExc_TypeError, "bad argument list");
2398 return NULL;
2401 #ifdef WITH_THREAD
2402 if (!self && !tcl_lock) {
2403 /* We don't have the Tcl lock since Tcl is threaded. */
2404 PyErr_SetString(PyExc_RuntimeError,
2405 "_tkinter.createtimerhandler not supported "
2406 "for threaded Tcl");
2407 return NULL;
2409 #endif
2411 if (self) {
2412 CHECK_TCL_APPARTMENT;
2415 v = Tktt_New(func);
2416 if (v) {
2417 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2418 (ClientData)v);
2421 return (PyObject *) v;
2425 /** Event Loop **/
2427 static PyObject *
2428 Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
2430 int threshold = 0;
2431 TkappObject *self = (TkappObject*)selfptr;
2432 #ifdef WITH_THREAD
2433 PyThreadState *tstate = PyThreadState_Get();
2434 #endif
2436 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2437 return NULL;
2439 #ifdef WITH_THREAD
2440 if (!self && !tcl_lock) {
2441 /* We don't have the Tcl lock since Tcl is threaded. */
2442 PyErr_SetString(PyExc_RuntimeError,
2443 "_tkinter.mainloop not supported "
2444 "for threaded Tcl");
2445 return NULL;
2447 #endif
2449 if (self) {
2450 CHECK_TCL_APPARTMENT;
2451 self->dispatching = 1;
2454 quitMainLoop = 0;
2455 while (Tk_GetNumMainWindows() > threshold &&
2456 !quitMainLoop &&
2457 !errorInCmd)
2459 int result;
2461 #ifdef WITH_THREAD
2462 if (self && self->threaded) {
2463 /* Allow other Python threads to run. */
2464 ENTER_TCL
2465 result = Tcl_DoOneEvent(0);
2466 LEAVE_TCL
2468 else {
2469 Py_BEGIN_ALLOW_THREADS
2470 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2471 tcl_tstate = tstate;
2472 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2473 tcl_tstate = NULL;
2474 if(tcl_lock)PyThread_release_lock(tcl_lock);
2475 if (result == 0)
2476 Sleep(Tkinter_busywaitinterval);
2477 Py_END_ALLOW_THREADS
2479 #else
2480 result = Tcl_DoOneEvent(0);
2481 #endif
2483 if (PyErr_CheckSignals() != 0) {
2484 if (self)
2485 self->dispatching = 0;
2486 return NULL;
2488 if (result < 0)
2489 break;
2491 if (self)
2492 self->dispatching = 0;
2493 quitMainLoop = 0;
2495 if (errorInCmd) {
2496 errorInCmd = 0;
2497 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2498 excInCmd = valInCmd = trbInCmd = NULL;
2499 return NULL;
2501 Py_INCREF(Py_None);
2502 return Py_None;
2505 static PyObject *
2506 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
2508 int flags = 0;
2509 int rv;
2511 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2512 return NULL;
2514 ENTER_TCL
2515 rv = Tcl_DoOneEvent(flags);
2516 LEAVE_TCL
2517 return Py_BuildValue("i", rv);
2520 static PyObject *
2521 Tkapp_Quit(PyObject *self, PyObject *args)
2524 if (!PyArg_ParseTuple(args, ":quit"))
2525 return NULL;
2527 quitMainLoop = 1;
2528 Py_INCREF(Py_None);
2529 return Py_None;
2532 static PyObject *
2533 Tkapp_InterpAddr(PyObject *self, PyObject *args)
2536 if (!PyArg_ParseTuple(args, ":interpaddr"))
2537 return NULL;
2539 return PyLong_FromLong((long)Tkapp_Interp(self));
2542 static PyObject *
2543 Tkapp_TkInit(PyObject *self, PyObject *args)
2545 static int has_failed;
2546 Tcl_Interp *interp = Tkapp_Interp(self);
2547 Tk_Window main_window;
2548 const char * _tk_exists = NULL;
2549 int err;
2550 main_window = Tk_MainWindow(interp);
2552 /* In all current versions of Tk (including 8.4.13), Tk_Init
2553 deadlocks on the second call when the first call failed.
2554 To avoid the deadlock, we just refuse the second call through
2555 a static variable. */
2556 if (has_failed) {
2557 PyErr_SetString(Tkinter_TclError,
2558 "Calling Tk_Init again after a previous call failed might deadlock");
2559 return NULL;
2562 /* We want to guard against calling Tk_Init() multiple times */
2563 CHECK_TCL_APPARTMENT;
2564 ENTER_TCL
2565 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2566 ENTER_OVERLAP
2567 if (err == TCL_ERROR) {
2568 /* This sets an exception, but we cannot return right
2569 away because we need to exit the overlap first. */
2570 Tkinter_Error(self);
2571 } else {
2572 _tk_exists = Tkapp_Result(self);
2574 LEAVE_OVERLAP_TCL
2575 if (err == TCL_ERROR) {
2576 return NULL;
2578 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2579 if (Tk_Init(interp) == TCL_ERROR) {
2580 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2581 has_failed = 1;
2582 return NULL;
2585 Py_INCREF(Py_None);
2586 return Py_None;
2589 static PyObject *
2590 Tkapp_WantObjects(PyObject *self, PyObject *args)
2593 int wantobjects = -1;
2594 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2595 return NULL;
2596 if (wantobjects == -1)
2597 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2598 ((TkappObject*)self)->wantobjects = wantobjects;
2600 Py_INCREF(Py_None);
2601 return Py_None;
2604 static PyObject *
2605 Tkapp_WillDispatch(PyObject *self, PyObject *args)
2608 ((TkappObject*)self)->dispatching = 1;
2610 Py_INCREF(Py_None);
2611 return Py_None;
2615 /**** Tkapp Method List ****/
2617 static PyMethodDef Tkapp_methods[] =
2619 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2620 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2621 {"call", Tkapp_Call, METH_VARARGS},
2622 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2623 {"eval", Tkapp_Eval, METH_VARARGS},
2624 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2625 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2626 {"record", Tkapp_Record, METH_VARARGS},
2627 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2628 {"setvar", Tkapp_SetVar, METH_VARARGS},
2629 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2630 {"getvar", Tkapp_GetVar, METH_VARARGS},
2631 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2632 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2633 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2634 {"getint", Tkapp_GetInt, METH_VARARGS},
2635 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2636 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2637 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2638 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2639 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2640 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2641 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2642 {"split", Tkapp_Split, METH_VARARGS},
2643 {"merge", Tkapp_Merge, METH_VARARGS},
2644 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2645 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2646 #ifdef HAVE_CREATEFILEHANDLER
2647 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2648 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2649 #endif
2650 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2651 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2652 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2653 {"quit", Tkapp_Quit, METH_VARARGS},
2654 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2655 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2656 {NULL, NULL}
2661 /**** Tkapp Type Methods ****/
2663 static void
2664 Tkapp_Dealloc(PyObject *self)
2666 /*CHECK_TCL_APPARTMENT;*/
2667 ENTER_TCL
2668 Tcl_DeleteInterp(Tkapp_Interp(self));
2669 LEAVE_TCL
2670 PyObject_Del(self);
2671 DisableEventHook();
2674 static PyObject *
2675 Tkapp_GetAttr(PyObject *self, char *name)
2677 return Py_FindMethod(Tkapp_methods, self, name);
2680 static PyTypeObject Tkapp_Type =
2682 PyVarObject_HEAD_INIT(NULL, 0)
2683 "tkapp", /*tp_name */
2684 sizeof(TkappObject), /*tp_basicsize */
2685 0, /*tp_itemsize */
2686 Tkapp_Dealloc, /*tp_dealloc */
2687 0, /*tp_print */
2688 Tkapp_GetAttr, /*tp_getattr */
2689 0, /*tp_setattr */
2690 0, /*tp_compare */
2691 0, /*tp_repr */
2692 0, /*tp_as_number */
2693 0, /*tp_as_sequence */
2694 0, /*tp_as_mapping */
2695 0, /*tp_hash */
2700 /**** Tkinter Module ****/
2702 typedef struct {
2703 PyObject* tuple;
2704 int size; /* current size */
2705 int maxsize; /* allocated size */
2706 } FlattenContext;
2708 static int
2709 _bump(FlattenContext* context, int size)
2711 /* expand tuple to hold (at least) size new items.
2712 return true if successful, false if an exception was raised */
2714 int maxsize = context->maxsize * 2;
2716 if (maxsize < context->size + size)
2717 maxsize = context->size + size;
2719 context->maxsize = maxsize;
2721 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2724 static int
2725 _flatten1(FlattenContext* context, PyObject* item, int depth)
2727 /* add tuple or list to argument tuple (recursively) */
2729 int i, size;
2731 if (depth > 1000) {
2732 PyErr_SetString(PyExc_ValueError,
2733 "nesting too deep in _flatten");
2734 return 0;
2735 } else if (PyList_Check(item)) {
2736 size = PyList_GET_SIZE(item);
2737 /* preallocate (assume no nesting) */
2738 if (context->size + size > context->maxsize &&
2739 !_bump(context, size))
2740 return 0;
2741 /* copy items to output tuple */
2742 for (i = 0; i < size; i++) {
2743 PyObject *o = PyList_GET_ITEM(item, i);
2744 if (PyList_Check(o) || PyTuple_Check(o)) {
2745 if (!_flatten1(context, o, depth + 1))
2746 return 0;
2747 } else if (o != Py_None) {
2748 if (context->size + 1 > context->maxsize &&
2749 !_bump(context, 1))
2750 return 0;
2751 Py_INCREF(o);
2752 PyTuple_SET_ITEM(context->tuple,
2753 context->size++, o);
2756 } else if (PyTuple_Check(item)) {
2757 /* same, for tuples */
2758 size = PyTuple_GET_SIZE(item);
2759 if (context->size + size > context->maxsize &&
2760 !_bump(context, size))
2761 return 0;
2762 for (i = 0; i < size; i++) {
2763 PyObject *o = PyTuple_GET_ITEM(item, i);
2764 if (PyList_Check(o) || PyTuple_Check(o)) {
2765 if (!_flatten1(context, o, depth + 1))
2766 return 0;
2767 } else if (o != Py_None) {
2768 if (context->size + 1 > context->maxsize &&
2769 !_bump(context, 1))
2770 return 0;
2771 Py_INCREF(o);
2772 PyTuple_SET_ITEM(context->tuple,
2773 context->size++, o);
2776 } else {
2777 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2778 return 0;
2780 return 1;
2783 static PyObject *
2784 Tkinter_Flatten(PyObject* self, PyObject* args)
2786 FlattenContext context;
2787 PyObject* item;
2789 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2790 return NULL;
2792 context.maxsize = PySequence_Size(item);
2793 if (context.maxsize <= 0)
2794 return PyTuple_New(0);
2796 context.tuple = PyTuple_New(context.maxsize);
2797 if (!context.tuple)
2798 return NULL;
2800 context.size = 0;
2802 if (!_flatten1(&context, item,0))
2803 return NULL;
2805 if (_PyTuple_Resize(&context.tuple, context.size))
2806 return NULL;
2808 return context.tuple;
2811 static PyObject *
2812 Tkinter_Create(PyObject *self, PyObject *args)
2814 char *screenName = NULL;
2815 char *baseName = NULL;
2816 char *className = NULL;
2817 int interactive = 0;
2818 int wantobjects = 0;
2819 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2820 int sync = 0; /* pass -sync to wish */
2821 char *use = NULL; /* pass -use to wish */
2823 baseName = strrchr(Py_GetProgramName(), '/');
2824 if (baseName != NULL)
2825 baseName++;
2826 else
2827 baseName = Py_GetProgramName();
2828 className = "Tk";
2830 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2831 &screenName, &baseName, &className,
2832 &interactive, &wantobjects, &wantTk,
2833 &sync, &use))
2834 return NULL;
2836 return (PyObject *) Tkapp_New(screenName, baseName, className,
2837 interactive, wantobjects, wantTk,
2838 sync, use);
2841 static PyObject *
2842 Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2844 int new_val;
2845 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2846 return NULL;
2847 if (new_val < 0) {
2848 PyErr_SetString(PyExc_ValueError,
2849 "busywaitinterval must be >= 0");
2850 return NULL;
2852 Tkinter_busywaitinterval = new_val;
2853 Py_INCREF(Py_None);
2854 return Py_None;
2857 static char setbusywaitinterval_doc[] =
2858 "setbusywaitinterval(n) -> None\n\
2860 Set the busy-wait interval in milliseconds between successive\n\
2861 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2862 It should be set to a divisor of the maximum time between\n\
2863 frames in an animation.";
2865 static PyObject *
2866 Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2868 return PyLong_FromLong(Tkinter_busywaitinterval);
2871 static char getbusywaitinterval_doc[] =
2872 "getbusywaitinterval() -> int\n\
2874 Return the current busy-wait interval between successive\n\
2875 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2877 static PyMethodDef moduleMethods[] =
2879 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2880 {"create", Tkinter_Create, METH_VARARGS},
2881 #ifdef HAVE_CREATEFILEHANDLER
2882 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2883 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2884 #endif
2885 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2886 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2887 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2888 {"quit", Tkapp_Quit, METH_VARARGS},
2889 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2890 setbusywaitinterval_doc},
2891 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2892 METH_NOARGS, getbusywaitinterval_doc},
2893 {NULL, NULL}
2896 #ifdef WAIT_FOR_STDIN
2898 static int stdin_ready = 0;
2900 #ifndef MS_WINDOWS
2901 static void
2902 MyFileProc(void *clientData, int mask)
2904 stdin_ready = 1;
2906 #endif
2908 #ifdef WITH_THREAD
2909 static PyThreadState *event_tstate = NULL;
2910 #endif
2912 static int
2913 EventHook(void)
2915 #ifndef MS_WINDOWS
2916 int tfile;
2917 #endif
2918 #ifdef WITH_THREAD
2919 PyEval_RestoreThread(event_tstate);
2920 #endif
2921 stdin_ready = 0;
2922 errorInCmd = 0;
2923 #ifndef MS_WINDOWS
2924 tfile = fileno(stdin);
2925 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
2926 #endif
2927 while (!errorInCmd && !stdin_ready) {
2928 int result;
2929 #ifdef MS_WINDOWS
2930 if (_kbhit()) {
2931 stdin_ready = 1;
2932 break;
2934 #endif
2935 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
2936 Py_BEGIN_ALLOW_THREADS
2937 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2938 tcl_tstate = event_tstate;
2940 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2942 tcl_tstate = NULL;
2943 if(tcl_lock)PyThread_release_lock(tcl_lock);
2944 if (result == 0)
2945 Sleep(Tkinter_busywaitinterval);
2946 Py_END_ALLOW_THREADS
2947 #else
2948 result = Tcl_DoOneEvent(0);
2949 #endif
2951 if (result < 0)
2952 break;
2954 #ifndef MS_WINDOWS
2955 Tcl_DeleteFileHandler(tfile);
2956 #endif
2957 if (errorInCmd) {
2958 errorInCmd = 0;
2959 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2960 excInCmd = valInCmd = trbInCmd = NULL;
2961 PyErr_Print();
2963 #ifdef WITH_THREAD
2964 PyEval_SaveThread();
2965 #endif
2966 return 0;
2969 #endif
2971 static void
2972 EnableEventHook(void)
2974 #ifdef WAIT_FOR_STDIN
2975 if (PyOS_InputHook == NULL) {
2976 #ifdef WITH_THREAD
2977 event_tstate = PyThreadState_Get();
2978 #endif
2979 PyOS_InputHook = EventHook;
2981 #endif
2984 static void
2985 DisableEventHook(void)
2987 #ifdef WAIT_FOR_STDIN
2988 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2989 PyOS_InputHook = NULL;
2991 #endif
2995 /* all errors will be checked in one fell swoop in init_tkinter() */
2996 static void
2997 ins_long(PyObject *d, char *name, long val)
2999 PyObject *v = PyLong_FromLong(val);
3000 if (v) {
3001 PyDict_SetItemString(d, name, v);
3002 Py_DECREF(v);
3005 static void
3006 ins_string(PyObject *d, char *name, char *val)
3008 PyObject *v = PyUnicode_FromString(val);
3009 if (v) {
3010 PyDict_SetItemString(d, name, v);
3011 Py_DECREF(v);
3016 PyMODINIT_FUNC
3017 init_tkinter(void)
3019 PyObject *m, *d;
3021 Py_TYPE(&Tkapp_Type) = &PyType_Type;
3023 #ifdef WITH_THREAD
3024 tcl_lock = PyThread_allocate_lock();
3025 #endif
3027 m = Py_InitModule("_tkinter", moduleMethods);
3028 if (m == NULL)
3029 return;
3031 d = PyModule_GetDict(m);
3032 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3033 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3035 ins_long(d, "READABLE", TCL_READABLE);
3036 ins_long(d, "WRITABLE", TCL_WRITABLE);
3037 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3038 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3039 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3040 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3041 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3042 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3043 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3044 ins_string(d, "TK_VERSION", TK_VERSION);
3045 ins_string(d, "TCL_VERSION", TCL_VERSION);
3047 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3049 Py_TYPE(&Tktt_Type) = &PyType_Type;
3050 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3052 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3053 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3055 #ifdef TK_AQUA
3056 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3057 * start waking up. Note that Tcl_FindExecutable will do this, this
3058 * code must be above it! The original warning from
3059 * tkMacOSXAppInit.c is copied below.
3061 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3062 * Tcl interpreter for now. It probably should work to do this
3063 * in the other order, but for now it doesn't seem to.
3066 Tk_MacOSXSetupTkNotifier();
3067 #endif
3070 /* This helps the dynamic loader; in Unicode aware Tcl versions
3071 it also helps Tcl find its encodings. */
3072 Tcl_FindExecutable(Py_GetProgramName());
3074 if (PyErr_Occurred())
3075 return;
3077 #if 0
3078 /* This was not a good idea; through <Destroy> bindings,
3079 Tcl_Finalize() may invoke Python code but at that point the
3080 interpreter and thread state have already been destroyed! */
3081 Py_AtExit(Tcl_Finalize);
3082 #endif