only use -fno-strict-aliasing when needed by compiler
[python/dscho.git] / Modules / _tkinter.c
blob8552575f408c5ce50e7e85cf513d1ab9d19628cb
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.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
14 Tcl/Tk 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 #include "tkinter.h"
72 /* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
73 #ifndef CONST84_RETURN
74 #define CONST84_RETURN
75 #undef CONST
76 #define CONST
77 #endif
79 #if TK_VERSION_HEX < 0x08030102
80 #error "Tk older than 8.3.1 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;
283 #ifdef TKINTER_PROTECT_LOADTK
284 static int tk_load_failed = 0;
285 #endif
288 static PyObject *
289 Tkinter_Error(PyObject *v)
291 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
292 return NULL;
297 /**** Utils ****/
299 static int Tkinter_busywaitinterval = 20;
301 #ifdef WITH_THREAD
302 #ifndef MS_WINDOWS
304 /* Millisecond sleep() for Unix platforms. */
306 static void
307 Sleep(int milli)
309 /* XXX Too bad if you don't have select(). */
310 struct timeval t;
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. */
319 static int
320 WaitForMainloop(TkappObject* self)
322 int i;
323 for (i = 0; i < 10; i++) {
324 if (self->dispatching)
325 return 1;
326 Py_BEGIN_ALLOW_THREADS
327 Sleep(100);
328 Py_END_ALLOW_THREADS
330 if (self->dispatching)
331 return 1;
332 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
333 return 0;
335 #endif /* WITH_THREAD */
338 static char *
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);
345 if (v == NULL)
346 return NULL;
347 if (PyList_Append(tmp, v) != 0) {
348 Py_DECREF(v);
349 return NULL;
351 Py_DECREF(v);
352 return PyBytes_AsString(v);
354 else {
355 PyObject *v = PyObject_Str(value);
356 if (v == NULL)
357 return NULL;
358 if (PyList_Append(tmp, v) != 0) {
359 Py_DECREF(v);
360 return NULL;
362 Py_DECREF(v);
363 return PyBytes_AsString(v);
369 #define ARGSZ 64
371 static char *
372 Merge(PyObject *args)
374 PyObject *tmp = NULL;
375 char *argvStore[ARGSZ];
376 char **argv = NULL;
377 int fvStore[ARGSZ];
378 int *fv = NULL;
379 int argc = 0, fvc = 0, i;
380 char *res = NULL;
382 if (!(tmp = PyList_New(0)))
383 return NULL;
385 argv = argvStore;
386 fv = fvStore;
388 if (args == NULL)
389 argc = 0;
391 else if (!PyTuple_Check(args)) {
392 argc = 1;
393 fv[0] = 0;
394 if (!(argv[0] = AsString(args, tmp)))
395 goto finally;
397 else {
398 argc = PyTuple_Size(args);
400 if (argc > ARGSZ) {
401 argv = (char **)ckalloc(argc * sizeof(char *));
402 fv = (int *)ckalloc(argc * sizeof(int));
403 if (argv == NULL || fv == NULL) {
404 PyErr_NoMemory();
405 goto finally;
409 for (i = 0; i < argc; i++) {
410 PyObject *v = PyTuple_GetItem(args, i);
411 if (PyTuple_Check(v)) {
412 fv[i] = 1;
413 if (!(argv[i] = Merge(v)))
414 goto finally;
415 fvc++;
417 else if (v == Py_None) {
418 argc = i;
419 break;
421 else {
422 fv[i] = 0;
423 if (!(argv[i] = AsString(v, tmp)))
424 goto finally;
425 fvc++;
429 res = Tcl_Merge(argc, argv);
430 if (res == NULL)
431 PyErr_SetString(Tkinter_TclError, "merge failed");
433 finally:
434 for (i = 0; i < fvc; i++)
435 if (fv[i]) {
436 ckfree(argv[i]);
438 if (argv != argvStore)
439 ckfree(FREECAST argv);
440 if (fv != fvStore)
441 ckfree(FREECAST fv);
443 Py_DECREF(tmp);
444 return res;
449 static PyObject *
450 Split(char *list)
452 int argc;
453 char **argv;
454 PyObject *v;
456 if (list == NULL) {
457 Py_INCREF(Py_None);
458 return Py_None;
461 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
462 /* Not a list.
463 * Could be a quoted string containing funnies, e.g. {"}.
464 * Return the string itself.
466 return PyUnicode_FromString(list);
469 if (argc == 0)
470 v = PyUnicode_FromString("");
471 else if (argc == 1)
472 v = PyUnicode_FromString(argv[0]);
473 else if ((v = PyTuple_New(argc)) != NULL) {
474 int i;
475 PyObject *w;
477 for (i = 0; i < argc; i++) {
478 if ((w = Split(argv[i])) == NULL) {
479 Py_DECREF(v);
480 v = NULL;
481 break;
483 PyTuple_SetItem(v, i, w);
486 Tcl_Free(FREECAST argv);
487 return v;
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
492 need to be split. */
494 static PyObject *
495 SplitObj(PyObject *arg)
497 if (PyTuple_Check(arg)) {
498 int i, size;
499 PyObject *elem, *newelem, *result;
501 size = PyTuple_Size(arg);
502 result = NULL;
503 /* Recursively invoke SplitObj for all tuple items.
504 If this does not return a new object, no action is
505 needed. */
506 for(i = 0; i < size; i++) {
507 elem = PyTuple_GetItem(arg, i);
508 newelem = SplitObj(elem);
509 if (!newelem) {
510 Py_XDECREF(result);
511 return NULL;
513 if (!result) {
514 int k;
515 if (newelem == elem) {
516 Py_DECREF(newelem);
517 continue;
519 result = PyTuple_New(size);
520 if (!result)
521 return NULL;
522 for(k = 0; k < i; k++) {
523 elem = PyTuple_GetItem(arg, k);
524 Py_INCREF(elem);
525 PyTuple_SetItem(result, k, elem);
528 PyTuple_SetItem(result, i, newelem);
530 if (result)
531 return result;
532 /* Fall through, returning arg. */
534 else if (PyBytes_Check(arg)) {
535 int argc;
536 char **argv;
537 char *list = PyBytes_AsString(arg);
539 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
540 Py_INCREF(arg);
541 return arg;
543 Tcl_Free(FREECAST argv);
544 if (argc > 1)
545 return Split(PyBytes_AsString(arg));
546 /* Fall through, returning arg. */
548 Py_INCREF(arg);
549 return arg;
553 /**** Tkapp Object ****/
555 #ifndef WITH_APPINIT
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));
563 return TCL_ERROR;
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) {
570 return TCL_OK;
573 #ifdef TKINTER_PROTECT_LOADTK
574 if (tk_load_failed) {
575 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
576 return TCL_ERROR;
578 #endif
580 if (Tk_Init(interp) == TCL_ERROR) {
581 #ifdef TKINTER_PROTECT_LOADTK
582 tk_load_failed = 1;
583 #endif
584 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
585 return TCL_ERROR;
588 return TCL_OK;
590 #endif /* !WITH_APPINIT */
595 /* Initialize the Tk application; see the `main' function in
596 * `tkMain.c'.
599 static void EnableEventHook(void); /* Forward */
600 static void DisableEventHook(void); /* Forward */
602 static TkappObject *
603 Tkapp_New(char *screenName, char *className,
604 int interactive, int wantobjects, int wantTk, int sync, char *use)
606 TkappObject *v;
607 char *argv0;
609 v = PyObject_New(TkappObject, &Tkapp_Type);
610 if (v == NULL)
611 return NULL;
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();
618 v->dispatching = 0;
620 #ifndef TCL_THREADS
621 if (v->threaded) {
622 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
623 Py_DECREF(v);
624 return 0;
626 #endif
627 #ifdef WITH_THREAD
628 if (v->threaded && tcl_lock) {
629 /* If Tcl is threaded, we don't need the lock. */
630 PyThread_free_lock(tcl_lock);
631 tcl_lock = NULL;
633 #endif
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);
650 if (interactive)
651 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
652 else
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);
657 if (!argv0) {
658 PyErr_NoMemory();
659 Py_DECREF(v);
660 return NULL;
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);
667 ckfree(argv0);
669 if (! wantTk) {
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);
678 #endif
680 /* some initial arguments need to be in argv */
681 if (sync || use) {
682 char *args;
683 int len = 0;
685 if (sync)
686 len += sizeof "-sync";
687 if (use)
688 len += strlen(use) + sizeof "-use ";
690 args = (char*)ckalloc(len);
691 if (!args) {
692 PyErr_NoMemory();
693 Py_DECREF(v);
694 return NULL;
697 args[0] = '\0';
698 if (sync)
699 strcat(args, "-sync");
700 if (use) {
701 if (sync)
702 strcat(args, " ");
703 strcat(args, "-use ");
704 strcat(args, use);
707 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
708 ckfree(args);
711 if (Tcl_AppInit(v->interp) != TCL_OK) {
712 PyObject *result = Tkinter_Error((PyObject *)v);
713 #ifdef TKINTER_PROTECT_LOADTK
714 if (wantTk) {
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) {
721 tk_load_failed = 1;
724 #endif
725 Py_DECREF((PyObject *)v);
726 return (TkappObject *)result;
729 EnableEventHook();
731 return v;
735 #ifdef WITH_THREAD
736 static void
737 Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
738 Tcl_Condition *cond, Tcl_Mutex *mutex)
740 Py_BEGIN_ALLOW_THREADS;
741 Tcl_MutexLock(mutex);
742 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
743 Tcl_ThreadAlert(self->thread_id);
744 Tcl_ConditionWait(cond, mutex, NULL);
745 Tcl_MutexUnlock(mutex);
746 Py_END_ALLOW_THREADS
748 #endif
751 /** Tcl Eval **/
753 typedef struct {
754 PyObject_HEAD
755 Tcl_Obj *value;
756 PyObject *string; /* This cannot cause cycles. */
757 } PyTclObject;
759 static PyTypeObject PyTclObject_Type;
760 #define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
762 static PyObject *
763 newPyTclObject(Tcl_Obj *arg)
765 PyTclObject *self;
766 self = PyObject_New(PyTclObject, &PyTclObject_Type);
767 if (self == NULL)
768 return NULL;
769 Tcl_IncrRefCount(arg);
770 self->value = arg;
771 self->string = NULL;
772 return (PyObject*)self;
775 static void
776 PyTclObject_dealloc(PyTclObject *self)
778 Tcl_DecrRefCount(self->value);
779 Py_XDECREF(self->string);
780 PyObject_Del(self);
783 static char*
784 PyTclObject_TclString(PyObject *self)
786 return Tcl_GetString(((PyTclObject*)self)->value);
789 /* Like _str, but create Unicode if necessary. */
790 PyDoc_STRVAR(PyTclObject_string__doc__,
791 "the string representation of this object, either as str or bytes");
793 static PyObject *
794 PyTclObject_string(PyTclObject *self, void *ignored)
796 char *s;
797 int len;
798 if (!self->string) {
799 s = Tcl_GetStringFromObj(self->value, &len);
800 self->string = PyUnicode_FromStringAndSize(s, len);
801 if (!self->string)
802 return NULL;
804 Py_INCREF(self->string);
805 return self->string;
808 static PyObject *
809 PyTclObject_str(PyTclObject *self, void *ignored)
811 char *s;
812 int len;
813 if (self->string && PyUnicode_Check(self->string)) {
814 Py_INCREF(self->string);
815 return self->string;
817 /* XXX Could chache result if it is non-ASCII. */
818 s = Tcl_GetStringFromObj(self->value, &len);
819 return PyUnicode_DecodeUTF8(s, len, "strict");
822 static PyObject *
823 PyTclObject_repr(PyTclObject *self)
825 return PyUnicode_FromFormat("<%s object at %p>",
826 self->value->typePtr->name, self->value);
829 #define TEST_COND(cond) ((cond) ? Py_True : Py_False)
831 static PyObject *
832 PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
834 int result;
835 PyObject *v;
837 /* neither argument should be NULL, unless something's gone wrong */
838 if (self == NULL || other == NULL) {
839 PyErr_BadInternalCall();
840 return NULL;
843 /* both arguments should be instances of PyTclObject */
844 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
845 v = Py_NotImplemented;
846 goto finished;
849 if (self == other)
850 /* fast path when self and other are identical */
851 result = 0;
852 else
853 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
854 Tcl_GetString(((PyTclObject *)other)->value));
855 /* Convert return value to a Boolean */
856 switch (op) {
857 case Py_EQ:
858 v = TEST_COND(result == 0);
859 break;
860 case Py_NE:
861 v = TEST_COND(result != 0);
862 break;
863 case Py_LE:
864 v = TEST_COND(result <= 0);
865 break;
866 case Py_GE:
867 v = TEST_COND(result >= 0);
868 break;
869 case Py_LT:
870 v = TEST_COND(result < 0);
871 break;
872 case Py_GT:
873 v = TEST_COND(result > 0);
874 break;
875 default:
876 PyErr_BadArgument();
877 return NULL;
879 finished:
880 Py_INCREF(v);
881 return v;
884 PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
886 static PyObject*
887 get_typename(PyTclObject* obj, void* ignored)
889 return PyUnicode_FromString(obj->value->typePtr->name);
893 static PyGetSetDef PyTclObject_getsetlist[] = {
894 {"typename", (getter)get_typename, NULL, get_typename__doc__},
895 {"string", (getter)PyTclObject_string, NULL,
896 PyTclObject_string__doc__},
897 {0},
900 static PyTypeObject PyTclObject_Type = {
901 PyVarObject_HEAD_INIT(NULL, 0)
902 "_tkinter.Tcl_Obj", /*tp_name*/
903 sizeof(PyTclObject), /*tp_basicsize*/
904 0, /*tp_itemsize*/
905 /* methods */
906 (destructor)PyTclObject_dealloc,/*tp_dealloc*/
907 0, /*tp_print*/
908 0, /*tp_getattr*/
909 0, /*tp_setattr*/
910 0, /*tp_reserved*/
911 (reprfunc)PyTclObject_repr, /*tp_repr*/
912 0, /*tp_as_number*/
913 0, /*tp_as_sequence*/
914 0, /*tp_as_mapping*/
915 0, /*tp_hash*/
916 0, /*tp_call*/
917 (reprfunc)PyTclObject_str, /*tp_str*/
918 PyObject_GenericGetAttr, /*tp_getattro*/
919 0, /*tp_setattro*/
920 0, /*tp_as_buffer*/
921 Py_TPFLAGS_DEFAULT, /*tp_flags*/
922 0, /*tp_doc*/
923 0, /*tp_traverse*/
924 0, /*tp_clear*/
925 PyTclObject_richcompare, /*tp_richcompare*/
926 0, /*tp_weaklistoffset*/
927 0, /*tp_iter*/
928 0, /*tp_iternext*/
929 0, /*tp_methods*/
930 0, /*tp_members*/
931 PyTclObject_getsetlist, /*tp_getset*/
932 0, /*tp_base*/
933 0, /*tp_dict*/
934 0, /*tp_descr_get*/
935 0, /*tp_descr_set*/
936 0, /*tp_dictoffset*/
937 0, /*tp_init*/
938 0, /*tp_alloc*/
939 0, /*tp_new*/
940 0, /*tp_free*/
941 0, /*tp_is_gc*/
944 static Tcl_Obj*
945 AsObj(PyObject *value)
947 Tcl_Obj *result;
948 long longVal;
949 int overflow;
951 if (PyBytes_Check(value))
952 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
953 PyBytes_GET_SIZE(value));
954 else if (PyBool_Check(value))
955 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
956 else if (PyLong_CheckExact(value) &&
957 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
958 !overflow)) {
959 /* If there is an overflow in the long conversion,
960 fall through to default object handling. */
961 return Tcl_NewLongObj(longVal);
963 else if (PyFloat_Check(value))
964 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
965 else if (PyTuple_Check(value)) {
966 Tcl_Obj **argv = (Tcl_Obj**)
967 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
968 int i;
969 if(!argv)
970 return 0;
971 for(i=0;i<PyTuple_Size(value);i++)
972 argv[i] = AsObj(PyTuple_GetItem(value,i));
973 result = Tcl_NewListObj(PyTuple_Size(value), argv);
974 ckfree(FREECAST argv);
975 return result;
977 else if (PyUnicode_Check(value)) {
978 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
979 Py_ssize_t size = PyUnicode_GET_SIZE(value);
980 /* This #ifdef assumes that Tcl uses UCS-2.
981 See TCL_UTF_MAX test above. */
982 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
983 Tcl_UniChar *outbuf = NULL;
984 Py_ssize_t i;
985 size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
986 if (allocsize >= size)
987 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
988 /* Else overflow occurred, and we take the next exit */
989 if (!outbuf) {
990 PyErr_NoMemory();
991 return NULL;
993 for (i = 0; i < size; i++) {
994 if (inbuf[i] >= 0x10000) {
995 /* Tcl doesn't do UTF-16, yet. */
996 PyErr_SetString(PyExc_ValueError,
997 "unsupported character");
998 ckfree(FREECAST outbuf);
999 return NULL;
1001 outbuf[i] = inbuf[i];
1003 result = Tcl_NewUnicodeObj(outbuf, size);
1004 ckfree(FREECAST outbuf);
1005 return result;
1006 #else
1007 return Tcl_NewUnicodeObj(inbuf, size);
1008 #endif
1011 else if(PyTclObject_Check(value)) {
1012 Tcl_Obj *v = ((PyTclObject*)value)->value;
1013 Tcl_IncrRefCount(v);
1014 return v;
1016 else {
1017 PyObject *v = PyObject_Str(value);
1018 if (!v)
1019 return 0;
1020 result = AsObj(v);
1021 Py_DECREF(v);
1022 return result;
1026 static PyObject*
1027 FromObj(PyObject* tkapp, Tcl_Obj *value)
1029 PyObject *result = NULL;
1030 TkappObject *app = (TkappObject*)tkapp;
1032 if (value->typePtr == NULL) {
1033 return PyUnicode_FromStringAndSize(value->bytes,
1034 value->length);
1037 if (value->typePtr == app->BooleanType) {
1038 result = value->internalRep.longValue ? Py_True : Py_False;
1039 Py_INCREF(result);
1040 return result;
1043 if (value->typePtr == app->ByteArrayType) {
1044 int size;
1045 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1046 return PyBytes_FromStringAndSize(data, size);
1049 if (value->typePtr == app->DoubleType) {
1050 return PyFloat_FromDouble(value->internalRep.doubleValue);
1053 if (value->typePtr == app->IntType) {
1054 return PyLong_FromLong(value->internalRep.longValue);
1057 if (value->typePtr == app->ListType) {
1058 int size;
1059 int i, status;
1060 PyObject *elem;
1061 Tcl_Obj *tcl_elem;
1063 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1064 if (status == TCL_ERROR)
1065 return Tkinter_Error(tkapp);
1066 result = PyTuple_New(size);
1067 if (!result)
1068 return NULL;
1069 for (i = 0; i < size; i++) {
1070 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1071 value, i, &tcl_elem);
1072 if (status == TCL_ERROR) {
1073 Py_DECREF(result);
1074 return Tkinter_Error(tkapp);
1076 elem = FromObj(tkapp, tcl_elem);
1077 if (!elem) {
1078 Py_DECREF(result);
1079 return NULL;
1081 PyTuple_SetItem(result, i, elem);
1083 return result;
1086 if (value->typePtr == app->ProcBodyType) {
1087 /* fall through: return tcl object. */
1090 if (value->typePtr == app->StringType) {
1091 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1092 PyObject *result;
1093 int size;
1094 Tcl_UniChar *input;
1095 Py_UNICODE *output;
1097 size = Tcl_GetCharLength(value);
1098 result = PyUnicode_FromUnicode(NULL, size);
1099 if (!result)
1100 return NULL;
1101 input = Tcl_GetUnicode(value);
1102 output = PyUnicode_AS_UNICODE(result);
1103 while (size--)
1104 *output++ = *input++;
1105 return result;
1106 #else
1107 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1108 Tcl_GetCharLength(value));
1109 #endif
1112 return newPyTclObject(value);
1115 #ifdef WITH_THREAD
1116 /* This mutex synchronizes inter-thread command calls. */
1117 TCL_DECLARE_MUTEX(call_mutex)
1119 typedef struct Tkapp_CallEvent {
1120 Tcl_Event ev; /* Must be first */
1121 TkappObject *self;
1122 PyObject *args;
1123 int flags;
1124 PyObject **res;
1125 PyObject **exc_type, **exc_value, **exc_tb;
1126 Tcl_Condition *done;
1127 } Tkapp_CallEvent;
1128 #endif
1130 void
1131 Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
1133 int i;
1134 for (i = 0; i < objc; i++)
1135 Tcl_DecrRefCount(objv[i]);
1136 if (objv != objStore)
1137 ckfree(FREECAST objv);
1140 /* Convert Python objects to Tcl objects. This must happen in the
1141 interpreter thread, which may or may not be the calling thread. */
1143 static Tcl_Obj**
1144 Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1146 Tcl_Obj **objv = objStore;
1147 int objc = 0, i;
1148 if (args == NULL)
1149 /* do nothing */;
1151 else if (!PyTuple_Check(args)) {
1152 objv[0] = AsObj(args);
1153 if (objv[0] == 0)
1154 goto finally;
1155 objc = 1;
1156 Tcl_IncrRefCount(objv[0]);
1158 else {
1159 objc = PyTuple_Size(args);
1161 if (objc > ARGSZ) {
1162 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1163 if (objv == NULL) {
1164 PyErr_NoMemory();
1165 objc = 0;
1166 goto finally;
1170 for (i = 0; i < objc; i++) {
1171 PyObject *v = PyTuple_GetItem(args, i);
1172 if (v == Py_None) {
1173 objc = i;
1174 break;
1176 objv[i] = AsObj(v);
1177 if (!objv[i]) {
1178 /* Reset objc, so it attempts to clear
1179 objects only up to i. */
1180 objc = i;
1181 goto finally;
1183 Tcl_IncrRefCount(objv[i]);
1186 *pobjc = objc;
1187 return objv;
1188 finally:
1189 Tkapp_CallDeallocArgs(objv, objStore, objc);
1190 return NULL;
1193 /* Convert the results of a command call into a Python objects. */
1195 static PyObject*
1196 Tkapp_CallResult(TkappObject *self)
1198 PyObject *res = NULL;
1199 if(self->wantobjects) {
1200 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1201 /* Not sure whether the IncrRef is necessary, but something
1202 may overwrite the interpreter result while we are
1203 converting it. */
1204 Tcl_IncrRefCount(value);
1205 res = FromObj((PyObject*)self, value);
1206 Tcl_DecrRefCount(value);
1207 } else {
1208 const char *s = Tcl_GetStringResult(self->interp);
1209 const char *p = s;
1211 res = PyUnicode_FromStringAndSize(s, (int)(p-s));
1213 return res;
1216 #ifdef WITH_THREAD
1218 /* Tkapp_CallProc is the event procedure that is executed in the context of
1219 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1220 hold the Python lock. */
1222 static int
1223 Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1225 Tcl_Obj *objStore[ARGSZ];
1226 Tcl_Obj **objv;
1227 int objc;
1228 int i;
1229 ENTER_PYTHON
1230 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1231 if (!objv) {
1232 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1233 *(e->res) = NULL;
1235 LEAVE_PYTHON
1236 if (!objv)
1237 goto done;
1238 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1239 ENTER_PYTHON
1240 if (i == TCL_ERROR) {
1241 *(e->res) = NULL;
1242 *(e->exc_type) = NULL;
1243 *(e->exc_tb) = NULL;
1244 *(e->exc_value) = PyObject_CallFunction(
1245 Tkinter_TclError, "s",
1246 Tcl_GetStringResult(e->self->interp));
1248 else {
1249 *(e->res) = Tkapp_CallResult(e->self);
1251 LEAVE_PYTHON
1253 Tkapp_CallDeallocArgs(objv, objStore, objc);
1254 done:
1255 /* Wake up calling thread. */
1256 Tcl_MutexLock(&call_mutex);
1257 Tcl_ConditionNotify(e->done);
1258 Tcl_MutexUnlock(&call_mutex);
1259 return 1;
1262 #endif
1264 /* This is the main entry point for calling a Tcl command.
1265 It supports three cases, with regard to threading:
1266 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1267 the context of the calling thread.
1268 2. Tcl is threaded, caller of the command is in the interpreter thread:
1269 Execute the command in the calling thread. Since the Tcl lock will
1270 not be used, we can merge that with case 1.
1271 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1272 the interpreter thread. Allocation of Tcl objects needs to occur in the
1273 interpreter thread, so we ship the PyObject* args to the target thread,
1274 and perform processing there. */
1276 static PyObject *
1277 Tkapp_Call(PyObject *selfptr, PyObject *args)
1279 Tcl_Obj *objStore[ARGSZ];
1280 Tcl_Obj **objv = NULL;
1281 int objc, i;
1282 PyObject *res = NULL;
1283 TkappObject *self = (TkappObject*)selfptr;
1284 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
1286 /* If args is a single tuple, replace with contents of tuple */
1287 if (1 == PyTuple_Size(args)){
1288 PyObject* item = PyTuple_GetItem(args, 0);
1289 if (PyTuple_Check(item))
1290 args = item;
1292 #ifdef WITH_THREAD
1293 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1294 /* We cannot call the command directly. Instead, we must
1295 marshal the parameters to the interpreter thread. */
1296 Tkapp_CallEvent *ev;
1297 Tcl_Condition cond = NULL;
1298 PyObject *exc_type, *exc_value, *exc_tb;
1299 if (!WaitForMainloop(self))
1300 return NULL;
1301 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1302 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1303 ev->self = self;
1304 ev->args = args;
1305 ev->res = &res;
1306 ev->exc_type = &exc_type;
1307 ev->exc_value = &exc_value;
1308 ev->exc_tb = &exc_tb;
1309 ev->done = &cond;
1311 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
1313 if (res == NULL) {
1314 if (exc_type)
1315 PyErr_Restore(exc_type, exc_value, exc_tb);
1316 else
1317 PyErr_SetObject(Tkinter_TclError, exc_value);
1319 Tcl_ConditionFinalize(&cond);
1321 else
1322 #endif
1325 objv = Tkapp_CallArgs(args, objStore, &objc);
1326 if (!objv)
1327 return NULL;
1329 ENTER_TCL
1331 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1333 ENTER_OVERLAP
1335 if (i == TCL_ERROR)
1336 Tkinter_Error(selfptr);
1337 else
1338 res = Tkapp_CallResult(self);
1340 LEAVE_OVERLAP_TCL
1342 Tkapp_CallDeallocArgs(objv, objStore, objc);
1344 return res;
1348 static PyObject *
1349 Tkapp_GlobalCall(PyObject *self, PyObject *args)
1351 /* Could do the same here as for Tkapp_Call(), but this is not used
1352 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1353 way for the user to do what all its Global* variants do (save and
1354 reset the scope pointer, call the local version, restore the saved
1355 scope pointer). */
1357 char *cmd;
1358 PyObject *res = NULL;
1360 CHECK_TCL_APPARTMENT;
1362 cmd = Merge(args);
1363 if (cmd) {
1364 int err;
1365 ENTER_TCL
1366 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1367 ENTER_OVERLAP
1368 if (err == TCL_ERROR)
1369 res = Tkinter_Error(self);
1370 else
1371 res = PyUnicode_FromString(Tkapp_Result(self));
1372 LEAVE_OVERLAP_TCL
1373 ckfree(cmd);
1376 return res;
1379 static PyObject *
1380 Tkapp_Eval(PyObject *self, PyObject *args)
1382 char *script;
1383 PyObject *res = NULL;
1384 int err;
1386 if (!PyArg_ParseTuple(args, "s:eval", &script))
1387 return NULL;
1389 CHECK_TCL_APPARTMENT;
1391 ENTER_TCL
1392 err = Tcl_Eval(Tkapp_Interp(self), script);
1393 ENTER_OVERLAP
1394 if (err == TCL_ERROR)
1395 res = Tkinter_Error(self);
1396 else
1397 res = PyUnicode_FromString(Tkapp_Result(self));
1398 LEAVE_OVERLAP_TCL
1399 return res;
1402 static PyObject *
1403 Tkapp_GlobalEval(PyObject *self, PyObject *args)
1405 char *script;
1406 PyObject *res = NULL;
1407 int err;
1409 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1410 return NULL;
1412 CHECK_TCL_APPARTMENT;
1414 ENTER_TCL
1415 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1416 ENTER_OVERLAP
1417 if (err == TCL_ERROR)
1418 res = Tkinter_Error(self);
1419 else
1420 res = PyUnicode_FromString(Tkapp_Result(self));
1421 LEAVE_OVERLAP_TCL
1422 return res;
1425 static PyObject *
1426 Tkapp_EvalFile(PyObject *self, PyObject *args)
1428 char *fileName;
1429 PyObject *res = NULL;
1430 int err;
1432 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1433 return NULL;
1435 CHECK_TCL_APPARTMENT;
1437 ENTER_TCL
1438 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1439 ENTER_OVERLAP
1440 if (err == TCL_ERROR)
1441 res = Tkinter_Error(self);
1443 else
1444 res = PyUnicode_FromString(Tkapp_Result(self));
1445 LEAVE_OVERLAP_TCL
1446 return res;
1449 static PyObject *
1450 Tkapp_Record(PyObject *self, PyObject *args)
1452 char *script;
1453 PyObject *res = NULL;
1454 int err;
1456 if (!PyArg_ParseTuple(args, "s", &script))
1457 return NULL;
1459 CHECK_TCL_APPARTMENT;
1461 ENTER_TCL
1462 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1463 ENTER_OVERLAP
1464 if (err == TCL_ERROR)
1465 res = Tkinter_Error(self);
1466 else
1467 res = PyUnicode_FromString(Tkapp_Result(self));
1468 LEAVE_OVERLAP_TCL
1469 return res;
1472 static PyObject *
1473 Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
1475 char *msg;
1477 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1478 return NULL;
1479 CHECK_TCL_APPARTMENT;
1481 ENTER_TCL
1482 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1483 LEAVE_TCL
1485 Py_INCREF(Py_None);
1486 return Py_None;
1491 /** Tcl Variable **/
1493 typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1495 #ifdef WITH_THREAD
1496 TCL_DECLARE_MUTEX(var_mutex)
1498 typedef struct VarEvent {
1499 Tcl_Event ev; /* must be first */
1500 PyObject *self;
1501 PyObject *args;
1502 int flags;
1503 EventFunc func;
1504 PyObject **res;
1505 PyObject **exc_type;
1506 PyObject **exc_val;
1507 Tcl_Condition *cond;
1508 } VarEvent;
1509 #endif
1511 static int
1512 varname_converter(PyObject *in, void *_out)
1514 char **out = (char**)_out;
1515 if (PyBytes_Check(in)) {
1516 *out = PyBytes_AsString(in);
1517 return 1;
1519 if (PyUnicode_Check(in)) {
1520 *out = _PyUnicode_AsString(in);
1521 return 1;
1523 if (PyTclObject_Check(in)) {
1524 *out = PyTclObject_TclString(in);
1525 return 1;
1527 /* XXX: Should give diagnostics. */
1528 return 0;
1531 #ifdef WITH_THREAD
1533 static void
1534 var_perform(VarEvent *ev)
1536 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1537 if (!*(ev->res)) {
1538 PyObject *exc, *val, *tb;
1539 PyErr_Fetch(&exc, &val, &tb);
1540 PyErr_NormalizeException(&exc, &val, &tb);
1541 *(ev->exc_type) = exc;
1542 *(ev->exc_val) = val;
1543 Py_DECREF(tb);
1548 static int
1549 var_proc(VarEvent* ev, int flags)
1551 ENTER_PYTHON
1552 var_perform(ev);
1553 Tcl_MutexLock(&var_mutex);
1554 Tcl_ConditionNotify(ev->cond);
1555 Tcl_MutexUnlock(&var_mutex);
1556 LEAVE_PYTHON
1557 return 1;
1560 #endif
1562 static PyObject*
1563 var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
1565 #ifdef WITH_THREAD
1566 TkappObject *self = (TkappObject*)selfptr;
1567 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1568 TkappObject *self = (TkappObject*)selfptr;
1569 VarEvent *ev;
1570 PyObject *res, *exc_type, *exc_val;
1571 Tcl_Condition cond = NULL;
1573 /* The current thread is not the interpreter thread. Marshal
1574 the call to the interpreter thread, then wait for
1575 completion. */
1576 if (!WaitForMainloop(self))
1577 return NULL;
1579 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1581 ev->self = selfptr;
1582 ev->args = args;
1583 ev->flags = flags;
1584 ev->func = func;
1585 ev->res = &res;
1586 ev->exc_type = &exc_type;
1587 ev->exc_val = &exc_val;
1588 ev->cond = &cond;
1589 ev->ev.proc = (Tcl_EventProc*)var_proc;
1590 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1591 Tcl_ConditionFinalize(&cond);
1592 if (!res) {
1593 PyErr_SetObject(exc_type, exc_val);
1594 Py_DECREF(exc_type);
1595 Py_DECREF(exc_val);
1596 return NULL;
1598 return res;
1600 #endif
1601 /* Tcl is not threaded, or this is the interpreter thread. */
1602 return func(selfptr, args, flags);
1605 static PyObject *
1606 SetVar(PyObject *self, PyObject *args, int flags)
1608 char *name1, *name2;
1609 PyObject *newValue;
1610 PyObject *res = NULL;
1611 Tcl_Obj *newval, *ok;
1613 if (PyArg_ParseTuple(args, "O&O:setvar",
1614 varname_converter, &name1, &newValue)) {
1615 /* XXX Acquire tcl lock??? */
1616 newval = AsObj(newValue);
1617 if (newval == NULL)
1618 return NULL;
1619 ENTER_TCL
1620 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1621 newval, flags);
1622 ENTER_OVERLAP
1623 if (!ok)
1624 Tkinter_Error(self);
1625 else {
1626 res = Py_None;
1627 Py_INCREF(res);
1629 LEAVE_OVERLAP_TCL
1631 else {
1632 PyErr_Clear();
1633 if (PyArg_ParseTuple(args, "ssO:setvar",
1634 &name1, &name2, &newValue)) {
1635 /* XXX must hold tcl lock already??? */
1636 newval = AsObj(newValue);
1637 ENTER_TCL
1638 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1639 ENTER_OVERLAP
1640 if (!ok)
1641 Tkinter_Error(self);
1642 else {
1643 res = Py_None;
1644 Py_INCREF(res);
1646 LEAVE_OVERLAP_TCL
1648 else {
1649 return NULL;
1652 return res;
1655 static PyObject *
1656 Tkapp_SetVar(PyObject *self, PyObject *args)
1658 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1661 static PyObject *
1662 Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
1664 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1669 static PyObject *
1670 GetVar(PyObject *self, PyObject *args, int flags)
1672 char *name1, *name2=NULL;
1673 PyObject *res = NULL;
1674 Tcl_Obj *tres;
1676 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1677 varname_converter, &name1, &name2))
1678 return NULL;
1680 ENTER_TCL
1681 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1682 ENTER_OVERLAP
1683 if (tres == NULL) {
1684 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1685 } else {
1686 if (((TkappObject*)self)->wantobjects) {
1687 res = FromObj(self, tres);
1689 else {
1690 res = PyUnicode_FromString(Tcl_GetString(tres));
1693 LEAVE_OVERLAP_TCL
1694 return res;
1697 static PyObject *
1698 Tkapp_GetVar(PyObject *self, PyObject *args)
1700 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1703 static PyObject *
1704 Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1706 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1711 static PyObject *
1712 UnsetVar(PyObject *self, PyObject *args, int flags)
1714 char *name1, *name2=NULL;
1715 int code;
1716 PyObject *res = NULL;
1718 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1719 return NULL;
1721 ENTER_TCL
1722 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1723 ENTER_OVERLAP
1724 if (code == TCL_ERROR)
1725 res = Tkinter_Error(self);
1726 else {
1727 Py_INCREF(Py_None);
1728 res = Py_None;
1730 LEAVE_OVERLAP_TCL
1731 return res;
1734 static PyObject *
1735 Tkapp_UnsetVar(PyObject *self, PyObject *args)
1737 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1740 static PyObject *
1741 Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1743 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1748 /** Tcl to Python **/
1750 static PyObject *
1751 Tkapp_GetInt(PyObject *self, PyObject *args)
1753 char *s;
1754 int v;
1756 if (PyTuple_Size(args) == 1) {
1757 PyObject* o = PyTuple_GetItem(args, 0);
1758 if (PyLong_Check(o)) {
1759 Py_INCREF(o);
1760 return o;
1763 if (!PyArg_ParseTuple(args, "s:getint", &s))
1764 return NULL;
1765 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1766 return Tkinter_Error(self);
1767 return Py_BuildValue("i", v);
1770 static PyObject *
1771 Tkapp_GetDouble(PyObject *self, PyObject *args)
1773 char *s;
1774 double v;
1776 if (PyTuple_Size(args) == 1) {
1777 PyObject *o = PyTuple_GetItem(args, 0);
1778 if (PyFloat_Check(o)) {
1779 Py_INCREF(o);
1780 return o;
1783 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1784 return NULL;
1785 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1786 return Tkinter_Error(self);
1787 return Py_BuildValue("d", v);
1790 static PyObject *
1791 Tkapp_GetBoolean(PyObject *self, PyObject *args)
1793 char *s;
1794 int v;
1796 if (PyTuple_Size(args) == 1) {
1797 PyObject *o = PyTuple_GetItem(args, 0);
1798 if (PyLong_Check(o)) {
1799 Py_INCREF(o);
1800 return o;
1803 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1804 return NULL;
1805 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1806 return Tkinter_Error(self);
1807 return PyBool_FromLong(v);
1810 static PyObject *
1811 Tkapp_ExprString(PyObject *self, PyObject *args)
1813 char *s;
1814 PyObject *res = NULL;
1815 int retval;
1817 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1818 return NULL;
1820 CHECK_TCL_APPARTMENT;
1822 ENTER_TCL
1823 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1824 ENTER_OVERLAP
1825 if (retval == TCL_ERROR)
1826 res = Tkinter_Error(self);
1827 else
1828 res = Py_BuildValue("s", Tkapp_Result(self));
1829 LEAVE_OVERLAP_TCL
1830 return res;
1833 static PyObject *
1834 Tkapp_ExprLong(PyObject *self, PyObject *args)
1836 char *s;
1837 PyObject *res = NULL;
1838 int retval;
1839 long v;
1841 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1842 return NULL;
1844 CHECK_TCL_APPARTMENT;
1846 ENTER_TCL
1847 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1848 ENTER_OVERLAP
1849 if (retval == TCL_ERROR)
1850 res = Tkinter_Error(self);
1851 else
1852 res = Py_BuildValue("l", v);
1853 LEAVE_OVERLAP_TCL
1854 return res;
1857 static PyObject *
1858 Tkapp_ExprDouble(PyObject *self, PyObject *args)
1860 char *s;
1861 PyObject *res = NULL;
1862 double v;
1863 int retval;
1865 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1866 return NULL;
1867 CHECK_TCL_APPARTMENT;
1868 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1869 ENTER_TCL
1870 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1871 ENTER_OVERLAP
1872 PyFPE_END_PROTECT(retval)
1873 if (retval == TCL_ERROR)
1874 res = Tkinter_Error(self);
1875 else
1876 res = Py_BuildValue("d", v);
1877 LEAVE_OVERLAP_TCL
1878 return res;
1881 static PyObject *
1882 Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1884 char *s;
1885 PyObject *res = NULL;
1886 int retval;
1887 int v;
1889 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1890 return NULL;
1891 CHECK_TCL_APPARTMENT;
1892 ENTER_TCL
1893 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1894 ENTER_OVERLAP
1895 if (retval == TCL_ERROR)
1896 res = Tkinter_Error(self);
1897 else
1898 res = Py_BuildValue("i", v);
1899 LEAVE_OVERLAP_TCL
1900 return res;
1905 static PyObject *
1906 Tkapp_SplitList(PyObject *self, PyObject *args)
1908 char *list;
1909 int argc;
1910 char **argv;
1911 PyObject *v;
1912 int i;
1914 if (PyTuple_Size(args) == 1) {
1915 v = PyTuple_GetItem(args, 0);
1916 if (PyTuple_Check(v)) {
1917 Py_INCREF(v);
1918 return v;
1921 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1922 return NULL;
1924 if (Tcl_SplitList(Tkapp_Interp(self), list,
1925 &argc, &argv) == TCL_ERROR) {
1926 PyMem_Free(list);
1927 return Tkinter_Error(self);
1930 if (!(v = PyTuple_New(argc)))
1931 goto finally;
1933 for (i = 0; i < argc; i++) {
1934 PyObject *s = PyUnicode_FromString(argv[i]);
1935 if (!s || PyTuple_SetItem(v, i, s)) {
1936 Py_DECREF(v);
1937 v = NULL;
1938 goto finally;
1942 finally:
1943 ckfree(FREECAST argv);
1944 PyMem_Free(list);
1945 return v;
1948 static PyObject *
1949 Tkapp_Split(PyObject *self, PyObject *args)
1951 PyObject *v;
1952 char *list;
1954 if (PyTuple_Size(args) == 1) {
1955 PyObject* o = PyTuple_GetItem(args, 0);
1956 if (PyTuple_Check(o)) {
1957 o = SplitObj(o);
1958 return o;
1961 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1962 return NULL;
1963 v = Split(list);
1964 PyMem_Free(list);
1965 return v;
1968 static PyObject *
1969 Tkapp_Merge(PyObject *self, PyObject *args)
1971 char *s = Merge(args);
1972 PyObject *res = NULL;
1974 if (s) {
1975 res = PyUnicode_FromString(s);
1976 ckfree(s);
1979 return res;
1984 /** Tcl Command **/
1986 /* Client data struct */
1987 typedef struct {
1988 PyObject *self;
1989 PyObject *func;
1990 } PythonCmd_ClientData;
1992 static int
1993 PythonCmd_Error(Tcl_Interp *interp)
1995 errorInCmd = 1;
1996 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1997 LEAVE_PYTHON
1998 return TCL_ERROR;
2001 /* This is the Tcl command that acts as a wrapper for Python
2002 * function or method.
2004 static int
2005 PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
2007 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2008 PyObject *self, *func, *arg, *res;
2009 int i, rv;
2010 Tcl_Obj *obj_res;
2012 ENTER_PYTHON
2014 /* TBD: no error checking here since we know, via the
2015 * Tkapp_CreateCommand() that the client data is a two-tuple
2017 self = data->self;
2018 func = data->func;
2020 /* Create argument list (argv1, ..., argvN) */
2021 if (!(arg = PyTuple_New(argc - 1)))
2022 return PythonCmd_Error(interp);
2024 for (i = 0; i < (argc - 1); i++) {
2025 PyObject *s = PyUnicode_FromString(argv[i + 1]);
2026 if (!s || PyTuple_SetItem(arg, i, s)) {
2027 Py_DECREF(arg);
2028 return PythonCmd_Error(interp);
2031 res = PyEval_CallObject(func, arg);
2032 Py_DECREF(arg);
2034 if (res == NULL)
2035 return PythonCmd_Error(interp);
2037 obj_res = AsObj(res);
2038 if (obj_res == NULL) {
2039 Py_DECREF(res);
2040 return PythonCmd_Error(interp);
2042 else {
2043 Tcl_SetObjResult(interp, obj_res);
2044 rv = TCL_OK;
2047 Py_DECREF(res);
2049 LEAVE_PYTHON
2051 return rv;
2054 static void
2055 PythonCmdDelete(ClientData clientData)
2057 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2059 ENTER_PYTHON
2060 Py_XDECREF(data->self);
2061 Py_XDECREF(data->func);
2062 PyMem_DEL(data);
2063 LEAVE_PYTHON
2069 #ifdef WITH_THREAD
2070 TCL_DECLARE_MUTEX(command_mutex)
2072 typedef struct CommandEvent{
2073 Tcl_Event ev;
2074 Tcl_Interp* interp;
2075 char *name;
2076 int create;
2077 int *status;
2078 ClientData *data;
2079 Tcl_Condition *done;
2080 } CommandEvent;
2082 static int
2083 Tkapp_CommandProc(CommandEvent *ev, int flags)
2085 if (ev->create)
2086 *ev->status = Tcl_CreateCommand(
2087 ev->interp, ev->name, PythonCmd,
2088 ev->data, PythonCmdDelete) == NULL;
2089 else
2090 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2091 Tcl_MutexLock(&command_mutex);
2092 Tcl_ConditionNotify(ev->done);
2093 Tcl_MutexUnlock(&command_mutex);
2094 return 1;
2096 #endif
2098 static PyObject *
2099 Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2101 TkappObject *self = (TkappObject*)selfptr;
2102 PythonCmd_ClientData *data;
2103 char *cmdName;
2104 PyObject *func;
2105 int err;
2107 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2108 return NULL;
2109 if (!PyCallable_Check(func)) {
2110 PyErr_SetString(PyExc_TypeError, "command not callable");
2111 return NULL;
2114 #ifdef WITH_THREAD
2115 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2116 !WaitForMainloop(self))
2117 return NULL;
2118 #endif
2120 data = PyMem_NEW(PythonCmd_ClientData, 1);
2121 if (!data)
2122 return PyErr_NoMemory();
2123 Py_INCREF(self);
2124 Py_INCREF(func);
2125 data->self = selfptr;
2126 data->func = func;
2127 #ifdef WITH_THREAD
2128 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2129 Tcl_Condition cond = NULL;
2130 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2131 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2132 ev->interp = self->interp;
2133 ev->create = 1;
2134 ev->name = cmdName;
2135 ev->data = (ClientData)data;
2136 ev->status = &err;
2137 ev->done = &cond;
2138 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2139 Tcl_ConditionFinalize(&cond);
2141 else
2142 #endif
2144 ENTER_TCL
2145 err = Tcl_CreateCommand(
2146 Tkapp_Interp(self), cmdName, PythonCmd,
2147 (ClientData)data, PythonCmdDelete) == NULL;
2148 LEAVE_TCL
2150 if (err) {
2151 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2152 PyMem_DEL(data);
2153 return NULL;
2156 Py_INCREF(Py_None);
2157 return Py_None;
2162 static PyObject *
2163 Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2165 TkappObject *self = (TkappObject*)selfptr;
2166 char *cmdName;
2167 int err;
2169 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2170 return NULL;
2172 #ifdef WITH_THREAD
2173 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2174 Tcl_Condition cond = NULL;
2175 CommandEvent *ev;
2176 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2177 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2178 ev->interp = self->interp;
2179 ev->create = 0;
2180 ev->name = cmdName;
2181 ev->status = &err;
2182 ev->done = &cond;
2183 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2184 &command_mutex);
2185 Tcl_ConditionFinalize(&cond);
2187 else
2188 #endif
2190 ENTER_TCL
2191 err = Tcl_DeleteCommand(self->interp, cmdName);
2192 LEAVE_TCL
2194 if (err == -1) {
2195 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2196 return NULL;
2198 Py_INCREF(Py_None);
2199 return Py_None;
2204 #ifdef HAVE_CREATEFILEHANDLER
2205 /** File Handler **/
2207 typedef struct _fhcdata {
2208 PyObject *func;
2209 PyObject *file;
2210 int id;
2211 struct _fhcdata *next;
2212 } FileHandler_ClientData;
2214 static FileHandler_ClientData *HeadFHCD;
2216 static FileHandler_ClientData *
2217 NewFHCD(PyObject *func, PyObject *file, int id)
2219 FileHandler_ClientData *p;
2220 p = PyMem_NEW(FileHandler_ClientData, 1);
2221 if (p != NULL) {
2222 Py_XINCREF(func);
2223 Py_XINCREF(file);
2224 p->func = func;
2225 p->file = file;
2226 p->id = id;
2227 p->next = HeadFHCD;
2228 HeadFHCD = p;
2230 return p;
2233 static void
2234 DeleteFHCD(int id)
2236 FileHandler_ClientData *p, **pp;
2238 pp = &HeadFHCD;
2239 while ((p = *pp) != NULL) {
2240 if (p->id == id) {
2241 *pp = p->next;
2242 Py_XDECREF(p->func);
2243 Py_XDECREF(p->file);
2244 PyMem_DEL(p);
2246 else
2247 pp = &p->next;
2251 static void
2252 FileHandler(ClientData clientData, int mask)
2254 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2255 PyObject *func, *file, *arg, *res;
2257 ENTER_PYTHON
2258 func = data->func;
2259 file = data->file;
2261 arg = Py_BuildValue("(Oi)", file, (long) mask);
2262 res = PyEval_CallObject(func, arg);
2263 Py_DECREF(arg);
2265 if (res == NULL) {
2266 errorInCmd = 1;
2267 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2269 Py_XDECREF(res);
2270 LEAVE_PYTHON
2273 static PyObject *
2274 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2275 /* args is (file, mask, func) */
2277 FileHandler_ClientData *data;
2278 PyObject *file, *func;
2279 int mask, tfile;
2281 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2282 &file, &mask, &func))
2283 return NULL;
2285 CHECK_TCL_APPARTMENT;
2287 tfile = PyObject_AsFileDescriptor(file);
2288 if (tfile < 0)
2289 return NULL;
2290 if (!PyCallable_Check(func)) {
2291 PyErr_SetString(PyExc_TypeError, "bad argument list");
2292 return NULL;
2295 data = NewFHCD(func, file, tfile);
2296 if (data == NULL)
2297 return NULL;
2299 /* Ought to check for null Tcl_File object... */
2300 ENTER_TCL
2301 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2302 LEAVE_TCL
2303 Py_INCREF(Py_None);
2304 return Py_None;
2307 static PyObject *
2308 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2310 PyObject *file;
2311 int tfile;
2313 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2314 return NULL;
2316 CHECK_TCL_APPARTMENT;
2318 tfile = PyObject_AsFileDescriptor(file);
2319 if (tfile < 0)
2320 return NULL;
2322 DeleteFHCD(tfile);
2324 /* Ought to check for null Tcl_File object... */
2325 ENTER_TCL
2326 Tcl_DeleteFileHandler(tfile);
2327 LEAVE_TCL
2328 Py_INCREF(Py_None);
2329 return Py_None;
2331 #endif /* HAVE_CREATEFILEHANDLER */
2334 /**** Tktt Object (timer token) ****/
2336 static PyTypeObject Tktt_Type;
2338 typedef struct {
2339 PyObject_HEAD
2340 Tcl_TimerToken token;
2341 PyObject *func;
2342 } TkttObject;
2344 static PyObject *
2345 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2347 TkttObject *v = (TkttObject *)self;
2348 PyObject *func = v->func;
2350 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2351 return NULL;
2352 if (v->token != NULL) {
2353 Tcl_DeleteTimerHandler(v->token);
2354 v->token = NULL;
2356 if (func != NULL) {
2357 v->func = NULL;
2358 Py_DECREF(func);
2359 Py_DECREF(v); /* See Tktt_New() */
2361 Py_INCREF(Py_None);
2362 return Py_None;
2365 static PyMethodDef Tktt_methods[] =
2367 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2368 {NULL, NULL}
2371 static TkttObject *
2372 Tktt_New(PyObject *func)
2374 TkttObject *v;
2376 v = PyObject_New(TkttObject, &Tktt_Type);
2377 if (v == NULL)
2378 return NULL;
2380 Py_INCREF(func);
2381 v->token = NULL;
2382 v->func = func;
2384 /* Extra reference, deleted when called or when handler is deleted */
2385 Py_INCREF(v);
2386 return v;
2389 static void
2390 Tktt_Dealloc(PyObject *self)
2392 TkttObject *v = (TkttObject *)self;
2393 PyObject *func = v->func;
2395 Py_XDECREF(func);
2397 PyObject_Del(self);
2400 static PyObject *
2401 Tktt_Repr(PyObject *self)
2403 TkttObject *v = (TkttObject *)self;
2404 char buf[100];
2406 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2407 v->func == NULL ? ", handler deleted" : "");
2408 return PyUnicode_FromString(buf);
2411 static PyTypeObject Tktt_Type =
2413 PyVarObject_HEAD_INIT(NULL, 0)
2414 "tktimertoken", /*tp_name */
2415 sizeof(TkttObject), /*tp_basicsize */
2416 0, /*tp_itemsize */
2417 Tktt_Dealloc, /*tp_dealloc */
2418 0, /*tp_print */
2419 0, /*tp_getattr */
2420 0, /*tp_setattr */
2421 0, /*tp_reserved */
2422 Tktt_Repr, /*tp_repr */
2423 0, /*tp_as_number */
2424 0, /*tp_as_sequence */
2425 0, /*tp_as_mapping */
2426 0, /*tp_hash */
2427 0, /*tp_call*/
2428 0, /*tp_str*/
2429 0, /*tp_getattro*/
2430 0, /*tp_setattro*/
2431 0, /*tp_as_buffer*/
2432 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2433 0, /*tp_doc*/
2434 0, /*tp_traverse*/
2435 0, /*tp_clear*/
2436 0, /*tp_richcompare*/
2437 0, /*tp_weaklistoffset*/
2438 0, /*tp_iter*/
2439 0, /*tp_iternext*/
2440 Tktt_methods, /*tp_methods*/
2445 /** Timer Handler **/
2447 static void
2448 TimerHandler(ClientData clientData)
2450 TkttObject *v = (TkttObject *)clientData;
2451 PyObject *func = v->func;
2452 PyObject *res;
2454 if (func == NULL)
2455 return;
2457 v->func = NULL;
2459 ENTER_PYTHON
2461 res = PyEval_CallObject(func, NULL);
2462 Py_DECREF(func);
2463 Py_DECREF(v); /* See Tktt_New() */
2465 if (res == NULL) {
2466 errorInCmd = 1;
2467 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2469 else
2470 Py_DECREF(res);
2472 LEAVE_PYTHON
2475 static PyObject *
2476 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2478 int milliseconds;
2479 PyObject *func;
2480 TkttObject *v;
2482 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2483 &milliseconds, &func))
2484 return NULL;
2485 if (!PyCallable_Check(func)) {
2486 PyErr_SetString(PyExc_TypeError, "bad argument list");
2487 return NULL;
2490 CHECK_TCL_APPARTMENT;
2492 v = Tktt_New(func);
2493 if (v) {
2494 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2495 (ClientData)v);
2498 return (PyObject *) v;
2502 /** Event Loop **/
2504 static PyObject *
2505 Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
2507 int threshold = 0;
2508 TkappObject *self = (TkappObject*)selfptr;
2509 #ifdef WITH_THREAD
2510 PyThreadState *tstate = PyThreadState_Get();
2511 #endif
2513 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2514 return NULL;
2516 CHECK_TCL_APPARTMENT;
2517 self->dispatching = 1;
2519 quitMainLoop = 0;
2520 while (Tk_GetNumMainWindows() > threshold &&
2521 !quitMainLoop &&
2522 !errorInCmd)
2524 int result;
2526 #ifdef WITH_THREAD
2527 if (self->threaded) {
2528 /* Allow other Python threads to run. */
2529 ENTER_TCL
2530 result = Tcl_DoOneEvent(0);
2531 LEAVE_TCL
2533 else {
2534 Py_BEGIN_ALLOW_THREADS
2535 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2536 tcl_tstate = tstate;
2537 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2538 tcl_tstate = NULL;
2539 if(tcl_lock)PyThread_release_lock(tcl_lock);
2540 if (result == 0)
2541 Sleep(Tkinter_busywaitinterval);
2542 Py_END_ALLOW_THREADS
2544 #else
2545 result = Tcl_DoOneEvent(0);
2546 #endif
2548 if (PyErr_CheckSignals() != 0) {
2549 self->dispatching = 0;
2550 return NULL;
2552 if (result < 0)
2553 break;
2555 self->dispatching = 0;
2556 quitMainLoop = 0;
2558 if (errorInCmd) {
2559 errorInCmd = 0;
2560 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2561 excInCmd = valInCmd = trbInCmd = NULL;
2562 return NULL;
2564 Py_INCREF(Py_None);
2565 return Py_None;
2568 static PyObject *
2569 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
2571 int flags = 0;
2572 int rv;
2574 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2575 return NULL;
2577 ENTER_TCL
2578 rv = Tcl_DoOneEvent(flags);
2579 LEAVE_TCL
2580 return Py_BuildValue("i", rv);
2583 static PyObject *
2584 Tkapp_Quit(PyObject *self, PyObject *args)
2587 if (!PyArg_ParseTuple(args, ":quit"))
2588 return NULL;
2590 quitMainLoop = 1;
2591 Py_INCREF(Py_None);
2592 return Py_None;
2595 static PyObject *
2596 Tkapp_InterpAddr(PyObject *self, PyObject *args)
2599 if (!PyArg_ParseTuple(args, ":interpaddr"))
2600 return NULL;
2602 return PyLong_FromLong((long)Tkapp_Interp(self));
2605 static PyObject *
2606 Tkapp_TkInit(PyObject *self, PyObject *args)
2608 Tcl_Interp *interp = Tkapp_Interp(self);
2609 const char * _tk_exists = NULL;
2610 int err;
2612 #ifdef TKINTER_PROTECT_LOADTK
2613 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2614 * first call failed.
2615 * To avoid the deadlock, we just refuse the second call through
2616 * a static variable.
2618 if (tk_load_failed) {
2619 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2620 return NULL;
2622 #endif
2624 /* We want to guard against calling Tk_Init() multiple times */
2625 CHECK_TCL_APPARTMENT;
2626 ENTER_TCL
2627 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2628 ENTER_OVERLAP
2629 if (err == TCL_ERROR) {
2630 /* This sets an exception, but we cannot return right
2631 away because we need to exit the overlap first. */
2632 Tkinter_Error(self);
2633 } else {
2634 _tk_exists = Tkapp_Result(self);
2636 LEAVE_OVERLAP_TCL
2637 if (err == TCL_ERROR) {
2638 return NULL;
2640 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2641 if (Tk_Init(interp) == TCL_ERROR) {
2642 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2643 #ifdef TKINTER_PROTECT_LOADTK
2644 tk_load_failed = 1;
2645 #endif
2646 return NULL;
2649 Py_INCREF(Py_None);
2650 return Py_None;
2653 static PyObject *
2654 Tkapp_WantObjects(PyObject *self, PyObject *args)
2657 int wantobjects = -1;
2658 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2659 return NULL;
2660 if (wantobjects == -1)
2661 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2662 ((TkappObject*)self)->wantobjects = wantobjects;
2664 Py_INCREF(Py_None);
2665 return Py_None;
2668 static PyObject *
2669 Tkapp_WillDispatch(PyObject *self, PyObject *args)
2672 ((TkappObject*)self)->dispatching = 1;
2674 Py_INCREF(Py_None);
2675 return Py_None;
2679 /**** Tkapp Method List ****/
2681 static PyMethodDef Tkapp_methods[] =
2683 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2684 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2685 {"call", Tkapp_Call, METH_VARARGS},
2686 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2687 {"eval", Tkapp_Eval, METH_VARARGS},
2688 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2689 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2690 {"record", Tkapp_Record, METH_VARARGS},
2691 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2692 {"setvar", Tkapp_SetVar, METH_VARARGS},
2693 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2694 {"getvar", Tkapp_GetVar, METH_VARARGS},
2695 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2696 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2697 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2698 {"getint", Tkapp_GetInt, METH_VARARGS},
2699 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2700 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2701 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2702 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2703 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2704 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2705 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2706 {"split", Tkapp_Split, METH_VARARGS},
2707 {"merge", Tkapp_Merge, METH_VARARGS},
2708 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2709 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2710 #ifdef HAVE_CREATEFILEHANDLER
2711 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2712 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2713 #endif
2714 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2715 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2716 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2717 {"quit", Tkapp_Quit, METH_VARARGS},
2718 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2719 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2720 {NULL, NULL}
2725 /**** Tkapp Type Methods ****/
2727 static void
2728 Tkapp_Dealloc(PyObject *self)
2730 /*CHECK_TCL_APPARTMENT;*/
2731 ENTER_TCL
2732 Tcl_DeleteInterp(Tkapp_Interp(self));
2733 LEAVE_TCL
2734 PyObject_Del(self);
2735 DisableEventHook();
2738 static PyTypeObject Tkapp_Type =
2740 PyVarObject_HEAD_INIT(NULL, 0)
2741 "tkapp", /*tp_name */
2742 sizeof(TkappObject), /*tp_basicsize */
2743 0, /*tp_itemsize */
2744 Tkapp_Dealloc, /*tp_dealloc */
2745 0, /*tp_print */
2746 0, /*tp_getattr */
2747 0, /*tp_setattr */
2748 0, /*tp_reserved */
2749 0, /*tp_repr */
2750 0, /*tp_as_number */
2751 0, /*tp_as_sequence */
2752 0, /*tp_as_mapping */
2753 0, /*tp_hash */
2754 0, /*tp_call*/
2755 0, /*tp_str*/
2756 0, /*tp_getattro*/
2757 0, /*tp_setattro*/
2758 0, /*tp_as_buffer*/
2759 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2760 0, /*tp_doc*/
2761 0, /*tp_traverse*/
2762 0, /*tp_clear*/
2763 0, /*tp_richcompare*/
2764 0, /*tp_weaklistoffset*/
2765 0, /*tp_iter*/
2766 0, /*tp_iternext*/
2767 Tkapp_methods, /*tp_methods*/
2772 /**** Tkinter Module ****/
2774 typedef struct {
2775 PyObject* tuple;
2776 int size; /* current size */
2777 int maxsize; /* allocated size */
2778 } FlattenContext;
2780 static int
2781 _bump(FlattenContext* context, int size)
2783 /* expand tuple to hold (at least) size new items.
2784 return true if successful, false if an exception was raised */
2786 int maxsize = context->maxsize * 2;
2788 if (maxsize < context->size + size)
2789 maxsize = context->size + size;
2791 context->maxsize = maxsize;
2793 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2796 static int
2797 _flatten1(FlattenContext* context, PyObject* item, int depth)
2799 /* add tuple or list to argument tuple (recursively) */
2801 int i, size;
2803 if (depth > 1000) {
2804 PyErr_SetString(PyExc_ValueError,
2805 "nesting too deep in _flatten");
2806 return 0;
2807 } else if (PyList_Check(item)) {
2808 size = PyList_GET_SIZE(item);
2809 /* preallocate (assume no nesting) */
2810 if (context->size + size > context->maxsize &&
2811 !_bump(context, size))
2812 return 0;
2813 /* copy items to output tuple */
2814 for (i = 0; i < size; i++) {
2815 PyObject *o = PyList_GET_ITEM(item, i);
2816 if (PyList_Check(o) || PyTuple_Check(o)) {
2817 if (!_flatten1(context, o, depth + 1))
2818 return 0;
2819 } else if (o != Py_None) {
2820 if (context->size + 1 > context->maxsize &&
2821 !_bump(context, 1))
2822 return 0;
2823 Py_INCREF(o);
2824 PyTuple_SET_ITEM(context->tuple,
2825 context->size++, o);
2828 } else if (PyTuple_Check(item)) {
2829 /* same, for tuples */
2830 size = PyTuple_GET_SIZE(item);
2831 if (context->size + size > context->maxsize &&
2832 !_bump(context, size))
2833 return 0;
2834 for (i = 0; i < size; i++) {
2835 PyObject *o = PyTuple_GET_ITEM(item, i);
2836 if (PyList_Check(o) || PyTuple_Check(o)) {
2837 if (!_flatten1(context, o, depth + 1))
2838 return 0;
2839 } else if (o != Py_None) {
2840 if (context->size + 1 > context->maxsize &&
2841 !_bump(context, 1))
2842 return 0;
2843 Py_INCREF(o);
2844 PyTuple_SET_ITEM(context->tuple,
2845 context->size++, o);
2848 } else {
2849 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2850 return 0;
2852 return 1;
2855 static PyObject *
2856 Tkinter_Flatten(PyObject* self, PyObject* args)
2858 FlattenContext context;
2859 PyObject* item;
2861 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2862 return NULL;
2864 context.maxsize = PySequence_Size(item);
2865 if (context.maxsize < 0)
2866 return NULL;
2867 if (context.maxsize == 0)
2868 return PyTuple_New(0);
2870 context.tuple = PyTuple_New(context.maxsize);
2871 if (!context.tuple)
2872 return NULL;
2874 context.size = 0;
2876 if (!_flatten1(&context, item,0))
2877 return NULL;
2879 if (_PyTuple_Resize(&context.tuple, context.size))
2880 return NULL;
2882 return context.tuple;
2885 static PyObject *
2886 Tkinter_Create(PyObject *self, PyObject *args)
2888 char *screenName = NULL;
2889 char *baseName = NULL; /* XXX this is not used anymore;
2890 try getting rid of it. */
2891 char *className = NULL;
2892 int interactive = 0;
2893 int wantobjects = 0;
2894 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2895 int sync = 0; /* pass -sync to wish */
2896 char *use = NULL; /* pass -use to wish */
2898 className = "Tk";
2900 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2901 &screenName, &baseName, &className,
2902 &interactive, &wantobjects, &wantTk,
2903 &sync, &use))
2904 return NULL;
2906 return (PyObject *) Tkapp_New(screenName, className,
2907 interactive, wantobjects, wantTk,
2908 sync, use);
2911 static PyObject *
2912 Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2914 int new_val;
2915 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2916 return NULL;
2917 if (new_val < 0) {
2918 PyErr_SetString(PyExc_ValueError,
2919 "busywaitinterval must be >= 0");
2920 return NULL;
2922 Tkinter_busywaitinterval = new_val;
2923 Py_INCREF(Py_None);
2924 return Py_None;
2927 static char setbusywaitinterval_doc[] =
2928 "setbusywaitinterval(n) -> None\n\
2930 Set the busy-wait interval in milliseconds between successive\n\
2931 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2932 It should be set to a divisor of the maximum time between\n\
2933 frames in an animation.";
2935 static PyObject *
2936 Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2938 return PyLong_FromLong(Tkinter_busywaitinterval);
2941 static char getbusywaitinterval_doc[] =
2942 "getbusywaitinterval() -> int\n\
2944 Return the current busy-wait interval between successive\n\
2945 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2947 static PyMethodDef moduleMethods[] =
2949 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2950 {"create", Tkinter_Create, METH_VARARGS},
2951 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2952 setbusywaitinterval_doc},
2953 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2954 METH_NOARGS, getbusywaitinterval_doc},
2955 {NULL, NULL}
2958 #ifdef WAIT_FOR_STDIN
2960 static int stdin_ready = 0;
2962 #ifndef MS_WINDOWS
2963 static void
2964 MyFileProc(void *clientData, int mask)
2966 stdin_ready = 1;
2968 #endif
2970 #ifdef WITH_THREAD
2971 static PyThreadState *event_tstate = NULL;
2972 #endif
2974 static int
2975 EventHook(void)
2977 #ifndef MS_WINDOWS
2978 int tfile;
2979 #endif
2980 #ifdef WITH_THREAD
2981 PyEval_RestoreThread(event_tstate);
2982 #endif
2983 stdin_ready = 0;
2984 errorInCmd = 0;
2985 #ifndef MS_WINDOWS
2986 tfile = fileno(stdin);
2987 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
2988 #endif
2989 while (!errorInCmd && !stdin_ready) {
2990 int result;
2991 #ifdef MS_WINDOWS
2992 if (_kbhit()) {
2993 stdin_ready = 1;
2994 break;
2996 #endif
2997 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
2998 Py_BEGIN_ALLOW_THREADS
2999 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3000 tcl_tstate = event_tstate;
3002 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3004 tcl_tstate = NULL;
3005 if(tcl_lock)PyThread_release_lock(tcl_lock);
3006 if (result == 0)
3007 Sleep(Tkinter_busywaitinterval);
3008 Py_END_ALLOW_THREADS
3009 #else
3010 result = Tcl_DoOneEvent(0);
3011 #endif
3013 if (result < 0)
3014 break;
3016 #ifndef MS_WINDOWS
3017 Tcl_DeleteFileHandler(tfile);
3018 #endif
3019 if (errorInCmd) {
3020 errorInCmd = 0;
3021 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3022 excInCmd = valInCmd = trbInCmd = NULL;
3023 PyErr_Print();
3025 #ifdef WITH_THREAD
3026 PyEval_SaveThread();
3027 #endif
3028 return 0;
3031 #endif
3033 static void
3034 EnableEventHook(void)
3036 #ifdef WAIT_FOR_STDIN
3037 if (PyOS_InputHook == NULL) {
3038 #ifdef WITH_THREAD
3039 event_tstate = PyThreadState_Get();
3040 #endif
3041 PyOS_InputHook = EventHook;
3043 #endif
3046 static void
3047 DisableEventHook(void)
3049 #ifdef WAIT_FOR_STDIN
3050 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3051 PyOS_InputHook = NULL;
3053 #endif
3057 /* all errors will be checked in one fell swoop in init_tkinter() */
3058 static void
3059 ins_long(PyObject *d, char *name, long val)
3061 PyObject *v = PyLong_FromLong(val);
3062 if (v) {
3063 PyDict_SetItemString(d, name, v);
3064 Py_DECREF(v);
3067 static void
3068 ins_string(PyObject *d, char *name, char *val)
3070 PyObject *v = PyUnicode_FromString(val);
3071 if (v) {
3072 PyDict_SetItemString(d, name, v);
3073 Py_DECREF(v);
3078 static struct PyModuleDef _tkintermodule = {
3079 PyModuleDef_HEAD_INIT,
3080 "_tkinter",
3081 NULL,
3083 moduleMethods,
3084 NULL,
3085 NULL,
3086 NULL,
3087 NULL
3090 PyMODINIT_FUNC
3091 PyInit__tkinter(void)
3093 PyObject *m, *d, *uexe, *cexe;
3095 if (PyType_Ready(&Tkapp_Type) < 0)
3096 return NULL;
3098 #ifdef WITH_THREAD
3099 tcl_lock = PyThread_allocate_lock();
3100 #endif
3102 m = PyModule_Create(&_tkintermodule);
3103 if (m == NULL)
3104 return NULL;
3106 d = PyModule_GetDict(m);
3107 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3108 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3110 ins_long(d, "READABLE", TCL_READABLE);
3111 ins_long(d, "WRITABLE", TCL_WRITABLE);
3112 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3113 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3114 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3115 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3116 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3117 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3118 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3119 ins_string(d, "TK_VERSION", TK_VERSION);
3120 ins_string(d, "TCL_VERSION", TCL_VERSION);
3122 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3124 if (PyType_Ready(&Tktt_Type) < 0)
3125 return NULL;
3126 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3128 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3129 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3131 #ifdef TK_AQUA
3132 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3133 * start waking up. Note that Tcl_FindExecutable will do this, this
3134 * code must be above it! The original warning from
3135 * tkMacOSXAppInit.c is copied below.
3137 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3138 * Tcl interpreter for now. It probably should work to do this
3139 * in the other order, but for now it doesn't seem to.
3142 Tk_MacOSXSetupTkNotifier();
3143 #endif
3146 /* This helps the dynamic loader; in Unicode aware Tcl versions
3147 it also helps Tcl find its encodings. */
3148 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3149 if (uexe) {
3150 cexe = PyUnicode_AsEncodedString(uexe,
3151 Py_FileSystemDefaultEncoding,
3152 NULL);
3153 if (cexe)
3154 Tcl_FindExecutable(PyBytes_AsString(cexe));
3155 Py_XDECREF(cexe);
3156 Py_DECREF(uexe);
3159 if (PyErr_Occurred()) {
3160 Py_DECREF(m);
3161 return NULL;
3164 #if 0
3165 /* This was not a good idea; through <Destroy> bindings,
3166 Tcl_Finalize() may invoke Python code but at that point the
3167 interpreter and thread state have already been destroyed! */
3168 Py_AtExit(Tcl_Finalize);
3169 #endif
3170 return m;