Change to flush and close logic to fix #1760556.
[python.git] / Modules / _tkinter.c
blobd26728c15f6562123328956b051b715787223927
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 PyInt_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 #ifdef Py_USING_UNICODE
341 else if (PyUnicode_Check(value)) {
342 PyObject *v = PyUnicode_AsUTF8String(value);
343 if (v == NULL)
344 return NULL;
345 if (PyList_Append(tmp, v) != 0) {
346 Py_DECREF(v);
347 return NULL;
349 Py_DECREF(v);
350 return PyString_AsString(v);
352 #endif
353 else {
354 PyObject *v = PyObject_Str(value);
355 if (v == NULL)
356 return NULL;
357 if (PyList_Append(tmp, v) != 0) {
358 Py_DECREF(v);
359 return NULL;
361 Py_DECREF(v);
362 return PyString_AsString(v);
368 #define ARGSZ 64
370 static char *
371 Merge(PyObject *args)
373 PyObject *tmp = NULL;
374 char *argvStore[ARGSZ];
375 char **argv = NULL;
376 int fvStore[ARGSZ];
377 int *fv = NULL;
378 int argc = 0, fvc = 0, i;
379 char *res = NULL;
381 if (!(tmp = PyList_New(0)))
382 return NULL;
384 argv = argvStore;
385 fv = fvStore;
387 if (args == NULL)
388 argc = 0;
390 else if (!PyTuple_Check(args)) {
391 argc = 1;
392 fv[0] = 0;
393 if (!(argv[0] = AsString(args, tmp)))
394 goto finally;
396 else {
397 argc = PyTuple_Size(args);
399 if (argc > ARGSZ) {
400 argv = (char **)ckalloc(argc * sizeof(char *));
401 fv = (int *)ckalloc(argc * sizeof(int));
402 if (argv == NULL || fv == NULL) {
403 PyErr_NoMemory();
404 goto finally;
408 for (i = 0; i < argc; i++) {
409 PyObject *v = PyTuple_GetItem(args, i);
410 if (PyTuple_Check(v)) {
411 fv[i] = 1;
412 if (!(argv[i] = Merge(v)))
413 goto finally;
414 fvc++;
416 else if (v == Py_None) {
417 argc = i;
418 break;
420 else {
421 fv[i] = 0;
422 if (!(argv[i] = AsString(v, tmp)))
423 goto finally;
424 fvc++;
428 res = Tcl_Merge(argc, argv);
429 if (res == NULL)
430 PyErr_SetString(Tkinter_TclError, "merge failed");
432 finally:
433 for (i = 0; i < fvc; i++)
434 if (fv[i]) {
435 ckfree(argv[i]);
437 if (argv != argvStore)
438 ckfree(FREECAST argv);
439 if (fv != fvStore)
440 ckfree(FREECAST fv);
442 Py_DECREF(tmp);
443 return res;
448 static PyObject *
449 Split(char *list)
451 int argc;
452 char **argv;
453 PyObject *v;
455 if (list == NULL) {
456 Py_INCREF(Py_None);
457 return Py_None;
460 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
461 /* Not a list.
462 * Could be a quoted string containing funnies, e.g. {"}.
463 * Return the string itself.
465 return PyString_FromString(list);
468 if (argc == 0)
469 v = PyString_FromString("");
470 else if (argc == 1)
471 v = PyString_FromString(argv[0]);
472 else if ((v = PyTuple_New(argc)) != NULL) {
473 int i;
474 PyObject *w;
476 for (i = 0; i < argc; i++) {
477 if ((w = Split(argv[i])) == NULL) {
478 Py_DECREF(v);
479 v = NULL;
480 break;
482 PyTuple_SetItem(v, i, w);
485 Tcl_Free(FREECAST argv);
486 return v;
489 /* In some cases, Tcl will still return strings that are supposed to be
490 lists. SplitObj walks through a nested tuple, finding string objects that
491 need to be split. */
493 PyObject *
494 SplitObj(PyObject *arg)
496 if (PyTuple_Check(arg)) {
497 int i, size;
498 PyObject *elem, *newelem, *result;
500 size = PyTuple_Size(arg);
501 result = NULL;
502 /* Recursively invoke SplitObj for all tuple items.
503 If this does not return a new object, no action is
504 needed. */
505 for(i = 0; i < size; i++) {
506 elem = PyTuple_GetItem(arg, i);
507 newelem = SplitObj(elem);
508 if (!newelem) {
509 Py_XDECREF(result);
510 return NULL;
512 if (!result) {
513 int k;
514 if (newelem == elem) {
515 Py_DECREF(newelem);
516 continue;
518 result = PyTuple_New(size);
519 if (!result)
520 return NULL;
521 for(k = 0; k < i; k++) {
522 elem = PyTuple_GetItem(arg, k);
523 Py_INCREF(elem);
524 PyTuple_SetItem(result, k, elem);
527 PyTuple_SetItem(result, i, newelem);
529 if (result)
530 return result;
531 /* Fall through, returning arg. */
533 else if (PyString_Check(arg)) {
534 int argc;
535 char **argv;
536 char *list = PyString_AsString(arg);
538 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
539 Py_INCREF(arg);
540 return arg;
542 Tcl_Free(FREECAST argv);
543 if (argc > 1)
544 return Split(PyString_AsString(arg));
545 /* Fall through, returning arg. */
547 Py_INCREF(arg);
548 return arg;
552 /**** Tkapp Object ****/
554 #ifndef WITH_APPINIT
556 Tcl_AppInit(Tcl_Interp *interp)
558 Tk_Window main;
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;
565 _tkinter_skip_tk_init = Tcl_GetVar(interp, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
566 if (_tkinter_skip_tk_init == NULL || strcmp(_tkinter_skip_tk_init, "1") != 0) {
567 main = Tk_MainWindow(interp);
568 if (Tk_Init(interp) == TCL_ERROR) {
569 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
570 return TCL_ERROR;
573 return TCL_OK;
575 #endif /* !WITH_APPINIT */
580 /* Initialize the Tk application; see the `main' function in
581 * `tkMain.c'.
584 static void EnableEventHook(void); /* Forward */
585 static void DisableEventHook(void); /* Forward */
587 static TkappObject *
588 Tkapp_New(char *screenName, char *baseName, char *className,
589 int interactive, int wantobjects, int wantTk, int sync, char *use)
591 TkappObject *v;
592 char *argv0;
594 v = PyObject_New(TkappObject, &Tkapp_Type);
595 if (v == NULL)
596 return NULL;
598 v->interp = Tcl_CreateInterp();
599 v->wantobjects = wantobjects;
600 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
601 TCL_GLOBAL_ONLY) != NULL;
602 v->thread_id = Tcl_GetCurrentThread();
603 v->dispatching = 0;
605 #ifndef TCL_THREADS
606 if (v->threaded) {
607 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
608 Py_DECREF(v);
609 return 0;
611 #endif
612 #ifdef WITH_THREAD
613 if (v->threaded && tcl_lock) {
614 /* If Tcl is threaded, we don't need the lock. */
615 PyThread_free_lock(tcl_lock);
616 tcl_lock = NULL;
618 #endif
620 v->BooleanType = Tcl_GetObjType("boolean");
621 v->ByteArrayType = Tcl_GetObjType("bytearray");
622 v->DoubleType = Tcl_GetObjType("double");
623 v->IntType = Tcl_GetObjType("int");
624 v->ListType = Tcl_GetObjType("list");
625 v->ProcBodyType = Tcl_GetObjType("procbody");
626 v->StringType = Tcl_GetObjType("string");
628 /* Delete the 'exit' command, which can screw things up */
629 Tcl_DeleteCommand(v->interp, "exit");
631 if (screenName != NULL)
632 Tcl_SetVar2(v->interp, "env", "DISPLAY",
633 screenName, TCL_GLOBAL_ONLY);
635 if (interactive)
636 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
637 else
638 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
640 /* This is used to get the application class for Tk 4.1 and up */
641 argv0 = (char*)ckalloc(strlen(className) + 1);
642 if (!argv0) {
643 PyErr_NoMemory();
644 Py_DECREF(v);
645 return NULL;
648 strcpy(argv0, className);
649 if (isupper(Py_CHARMASK(argv0[0])))
650 argv0[0] = tolower(Py_CHARMASK(argv0[0]));
651 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
652 ckfree(argv0);
654 if (! wantTk) {
655 Tcl_SetVar(v->interp, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
658 /* some initial arguments need to be in argv */
659 if (sync || use) {
660 char *args;
661 int len = 0;
663 if (sync)
664 len += sizeof "-sync";
665 if (use)
666 len += strlen(use) + sizeof "-use ";
668 args = (char*)ckalloc(len);
669 if (!args) {
670 PyErr_NoMemory();
671 Py_DECREF(v);
672 return NULL;
675 args[0] = '\0';
676 if (sync)
677 strcat(args, "-sync");
678 if (use) {
679 if (sync)
680 strcat(args, " ");
681 strcat(args, "-use ");
682 strcat(args, use);
685 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
686 ckfree(args);
689 if (Tcl_AppInit(v->interp) != TCL_OK) {
690 PyObject *result = Tkinter_Error((PyObject *)v);
691 Py_DECREF((PyObject *)v);
692 return (TkappObject *)result;
695 EnableEventHook();
697 return v;
701 static void
702 Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
703 Tcl_Condition *cond, Tcl_Mutex *mutex)
705 Py_BEGIN_ALLOW_THREADS;
706 Tcl_MutexLock(mutex);
707 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
708 Tcl_ThreadAlert(self->thread_id);
709 Tcl_ConditionWait(cond, mutex, NULL);
710 Tcl_MutexUnlock(mutex);
711 Py_END_ALLOW_THREADS
715 /** Tcl Eval **/
717 typedef struct {
718 PyObject_HEAD
719 Tcl_Obj *value;
720 PyObject *string; /* This cannot cause cycles. */
721 } PyTclObject;
723 staticforward PyTypeObject PyTclObject_Type;
724 #define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
726 static PyObject *
727 newPyTclObject(Tcl_Obj *arg)
729 PyTclObject *self;
730 self = PyObject_New(PyTclObject, &PyTclObject_Type);
731 if (self == NULL)
732 return NULL;
733 Tcl_IncrRefCount(arg);
734 self->value = arg;
735 self->string = NULL;
736 return (PyObject*)self;
739 static void
740 PyTclObject_dealloc(PyTclObject *self)
742 Tcl_DecrRefCount(self->value);
743 Py_XDECREF(self->string);
744 PyObject_Del(self);
747 static PyObject *
748 PyTclObject_str(PyTclObject *self)
750 if (self->string && PyString_Check(self->string)) {
751 Py_INCREF(self->string);
752 return self->string;
754 /* XXX Could cache value if it is an ASCII string. */
755 return PyString_FromString(Tcl_GetString(self->value));
758 static char*
759 PyTclObject_TclString(PyObject *self)
761 return Tcl_GetString(((PyTclObject*)self)->value);
764 /* Like _str, but create Unicode if necessary. */
765 PyDoc_STRVAR(PyTclObject_string__doc__,
766 "the string representation of this object, either as string or Unicode");
768 static PyObject *
769 PyTclObject_string(PyTclObject *self, void *ignored)
771 char *s;
772 int i, len;
773 if (!self->string) {
774 s = Tcl_GetStringFromObj(self->value, &len);
775 for (i = 0; i < len; i++)
776 if (s[i] & 0x80)
777 break;
778 #ifdef Py_USING_UNICODE
779 if (i == len)
780 /* It is an ASCII string. */
781 self->string = PyString_FromStringAndSize(s, len);
782 else {
783 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
784 if (!self->string) {
785 PyErr_Clear();
786 self->string = PyString_FromStringAndSize(s, len);
789 #else
790 self->string = PyString_FromStringAndSize(s, len);
791 #endif
792 if (!self->string)
793 return NULL;
795 Py_INCREF(self->string);
796 return self->string;
799 #ifdef Py_USING_UNICODE
800 PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
802 static PyObject *
803 PyTclObject_unicode(PyTclObject *self, void *ignored)
805 char *s;
806 int len;
807 if (self->string && PyUnicode_Check(self->string)) {
808 Py_INCREF(self->string);
809 return self->string;
811 /* XXX Could chache result if it is non-ASCII. */
812 s = Tcl_GetStringFromObj(self->value, &len);
813 return PyUnicode_DecodeUTF8(s, len, "strict");
815 #endif
817 static PyObject *
818 PyTclObject_repr(PyTclObject *self)
820 char buf[50];
821 PyOS_snprintf(buf, 50, "<%s object at %p>",
822 self->value->typePtr->name, self->value);
823 return PyString_FromString(buf);
826 static int
827 PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
829 int res;
830 res = strcmp(Tcl_GetString(self->value),
831 Tcl_GetString(other->value));
832 if (res < 0) return -1;
833 if (res > 0) return 1;
834 return 0;
837 PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
839 static PyObject*
840 get_typename(PyTclObject* obj, void* ignored)
842 return PyString_FromString(obj->value->typePtr->name);
846 static PyGetSetDef PyTclObject_getsetlist[] = {
847 {"typename", (getter)get_typename, NULL, get_typename__doc__},
848 {"string", (getter)PyTclObject_string, NULL,
849 PyTclObject_string__doc__},
850 {0},
853 static PyMethodDef PyTclObject_methods[] = {
854 #ifdef Py_USING_UNICODE
855 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
856 PyTclObject_unicode__doc__},
857 #endif
861 statichere PyTypeObject PyTclObject_Type = {
862 PyObject_HEAD_INIT(NULL)
863 0, /*ob_size*/
864 "_tkinter.Tcl_Obj", /*tp_name*/
865 sizeof(PyTclObject), /*tp_basicsize*/
866 0, /*tp_itemsize*/
867 /* methods */
868 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
869 0, /*tp_print*/
870 0, /*tp_getattr*/
871 0, /*tp_setattr*/
872 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
873 (reprfunc)PyTclObject_repr, /*tp_repr*/
874 0, /*tp_as_number*/
875 0, /*tp_as_sequence*/
876 0, /*tp_as_mapping*/
877 0, /*tp_hash*/
878 0, /*tp_call*/
879 (reprfunc)PyTclObject_str, /*tp_str*/
880 PyObject_GenericGetAttr,/*tp_getattro*/
881 0, /*tp_setattro*/
882 0, /*tp_as_buffer*/
883 Py_TPFLAGS_DEFAULT, /*tp_flags*/
884 0, /*tp_doc*/
885 0, /*tp_traverse*/
886 0, /*tp_clear*/
887 0, /*tp_richcompare*/
888 0, /*tp_weaklistoffset*/
889 0, /*tp_iter*/
890 0, /*tp_iternext*/
891 PyTclObject_methods, /*tp_methods*/
892 0, /*tp_members*/
893 PyTclObject_getsetlist, /*tp_getset*/
894 0, /*tp_base*/
895 0, /*tp_dict*/
896 0, /*tp_descr_get*/
897 0, /*tp_descr_set*/
898 0, /*tp_dictoffset*/
899 0, /*tp_init*/
900 0, /*tp_alloc*/
901 0, /*tp_new*/
902 0, /*tp_free*/
903 0, /*tp_is_gc*/
906 static Tcl_Obj*
907 AsObj(PyObject *value)
909 Tcl_Obj *result;
911 if (PyString_Check(value))
912 return Tcl_NewStringObj(PyString_AS_STRING(value),
913 PyString_GET_SIZE(value));
914 else if (PyBool_Check(value))
915 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
916 else if (PyInt_Check(value))
917 return Tcl_NewLongObj(PyInt_AS_LONG(value));
918 else if (PyFloat_Check(value))
919 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
920 else if (PyTuple_Check(value)) {
921 Tcl_Obj **argv = (Tcl_Obj**)
922 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
923 int i;
924 if(!argv)
925 return 0;
926 for(i=0;i<PyTuple_Size(value);i++)
927 argv[i] = AsObj(PyTuple_GetItem(value,i));
928 result = Tcl_NewListObj(PyTuple_Size(value), argv);
929 ckfree(FREECAST argv);
930 return result;
932 #ifdef Py_USING_UNICODE
933 else if (PyUnicode_Check(value)) {
934 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
935 Py_ssize_t size = PyUnicode_GET_SIZE(value);
936 /* This #ifdef assumes that Tcl uses UCS-2.
937 See TCL_UTF_MAX test above. */
938 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
939 Tcl_UniChar *outbuf;
940 Py_ssize_t i;
941 assert(size < size * sizeof(Tcl_UniChar));
942 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
943 if (!outbuf) {
944 PyErr_NoMemory();
945 return NULL;
947 for (i = 0; i < size; i++) {
948 if (inbuf[i] >= 0x10000) {
949 /* Tcl doesn't do UTF-16, yet. */
950 PyErr_SetString(PyExc_ValueError,
951 "unsupported character");
952 ckfree(FREECAST outbuf);
953 return NULL;
955 outbuf[i] = inbuf[i];
957 result = Tcl_NewUnicodeObj(outbuf, size);
958 ckfree(FREECAST outbuf);
959 return result;
960 #else
961 return Tcl_NewUnicodeObj(inbuf, size);
962 #endif
965 #endif
966 else if(PyTclObject_Check(value)) {
967 Tcl_Obj *v = ((PyTclObject*)value)->value;
968 Tcl_IncrRefCount(v);
969 return v;
971 else {
972 PyObject *v = PyObject_Str(value);
973 if (!v)
974 return 0;
975 result = AsObj(v);
976 Py_DECREF(v);
977 return result;
981 static PyObject*
982 FromObj(PyObject* tkapp, Tcl_Obj *value)
984 PyObject *result = NULL;
985 TkappObject *app = (TkappObject*)tkapp;
987 if (value->typePtr == NULL) {
988 /* If the result contains any bytes with the top bit set,
989 it's UTF-8 and we should decode it to Unicode */
990 #ifdef Py_USING_UNICODE
991 int i;
992 char *s = value->bytes;
993 int len = value->length;
994 for (i = 0; i < len; i++) {
995 if (value->bytes[i] & 0x80)
996 break;
999 if (i == value->length)
1000 result = PyString_FromStringAndSize(s, len);
1001 else {
1002 /* Convert UTF-8 to Unicode string */
1003 result = PyUnicode_DecodeUTF8(s, len, "strict");
1004 if (result == NULL) {
1005 PyErr_Clear();
1006 result = PyString_FromStringAndSize(s, len);
1009 #else
1010 result = PyString_FromStringAndSize(value->bytes, value->length);
1011 #endif
1012 return result;
1015 if (value->typePtr == app->BooleanType) {
1016 result = value->internalRep.longValue ? Py_True : Py_False;
1017 Py_INCREF(result);
1018 return result;
1021 if (value->typePtr == app->ByteArrayType) {
1022 int size;
1023 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1024 return PyString_FromStringAndSize(data, size);
1027 if (value->typePtr == app->DoubleType) {
1028 return PyFloat_FromDouble(value->internalRep.doubleValue);
1031 if (value->typePtr == app->IntType) {
1032 return PyInt_FromLong(value->internalRep.longValue);
1035 if (value->typePtr == app->ListType) {
1036 int size;
1037 int i, status;
1038 PyObject *elem;
1039 Tcl_Obj *tcl_elem;
1041 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1042 if (status == TCL_ERROR)
1043 return Tkinter_Error(tkapp);
1044 result = PyTuple_New(size);
1045 if (!result)
1046 return NULL;
1047 for (i = 0; i < size; i++) {
1048 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1049 value, i, &tcl_elem);
1050 if (status == TCL_ERROR) {
1051 Py_DECREF(result);
1052 return Tkinter_Error(tkapp);
1054 elem = FromObj(tkapp, tcl_elem);
1055 if (!elem) {
1056 Py_DECREF(result);
1057 return NULL;
1059 PyTuple_SetItem(result, i, elem);
1061 return result;
1064 if (value->typePtr == app->ProcBodyType) {
1065 /* fall through: return tcl object. */
1068 if (value->typePtr == app->StringType) {
1069 #ifdef Py_USING_UNICODE
1070 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1071 PyObject *result;
1072 int size;
1073 Tcl_UniChar *input;
1074 Py_UNICODE *output;
1076 size = Tcl_GetCharLength(value);
1077 result = PyUnicode_FromUnicode(NULL, size);
1078 if (!result)
1079 return NULL;
1080 input = Tcl_GetUnicode(value);
1081 output = PyUnicode_AS_UNICODE(result);
1082 while (size--)
1083 *output++ = *input++;
1084 return result;
1085 #else
1086 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1087 Tcl_GetCharLength(value));
1088 #endif
1089 #else
1090 int size;
1091 char *c;
1092 c = Tcl_GetStringFromObj(value, &size);
1093 return PyString_FromStringAndSize(c, size);
1094 #endif
1097 return newPyTclObject(value);
1100 /* This mutex synchronizes inter-thread command calls. */
1102 TCL_DECLARE_MUTEX(call_mutex)
1104 typedef struct Tkapp_CallEvent {
1105 Tcl_Event ev; /* Must be first */
1106 TkappObject *self;
1107 PyObject *args;
1108 int flags;
1109 PyObject **res;
1110 PyObject **exc_type, **exc_value, **exc_tb;
1111 Tcl_Condition done;
1112 } Tkapp_CallEvent;
1114 void
1115 Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
1117 int i;
1118 for (i = 0; i < objc; i++)
1119 Tcl_DecrRefCount(objv[i]);
1120 if (objv != objStore)
1121 ckfree(FREECAST objv);
1124 /* Convert Python objects to Tcl objects. This must happen in the
1125 interpreter thread, which may or may not be the calling thread. */
1127 static Tcl_Obj**
1128 Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1130 Tcl_Obj **objv = objStore;
1131 int objc = 0, i;
1132 if (args == NULL)
1133 /* do nothing */;
1135 else if (!PyTuple_Check(args)) {
1136 objv[0] = AsObj(args);
1137 if (objv[0] == 0)
1138 goto finally;
1139 objc = 1;
1140 Tcl_IncrRefCount(objv[0]);
1142 else {
1143 objc = PyTuple_Size(args);
1145 if (objc > ARGSZ) {
1146 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1147 if (objv == NULL) {
1148 PyErr_NoMemory();
1149 objc = 0;
1150 goto finally;
1154 for (i = 0; i < objc; i++) {
1155 PyObject *v = PyTuple_GetItem(args, i);
1156 if (v == Py_None) {
1157 objc = i;
1158 break;
1160 objv[i] = AsObj(v);
1161 if (!objv[i]) {
1162 /* Reset objc, so it attempts to clear
1163 objects only up to i. */
1164 objc = i;
1165 goto finally;
1167 Tcl_IncrRefCount(objv[i]);
1170 *pobjc = objc;
1171 return objv;
1172 finally:
1173 Tkapp_CallDeallocArgs(objv, objStore, objc);
1174 return NULL;
1177 /* Convert the results of a command call into a Python objects. */
1179 static PyObject*
1180 Tkapp_CallResult(TkappObject *self)
1182 PyObject *res = NULL;
1183 if(self->wantobjects) {
1184 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1185 /* Not sure whether the IncrRef is necessary, but something
1186 may overwrite the interpreter result while we are
1187 converting it. */
1188 Tcl_IncrRefCount(value);
1189 res = FromObj((PyObject*)self, value);
1190 Tcl_DecrRefCount(value);
1191 } else {
1192 const char *s = Tcl_GetStringResult(self->interp);
1193 const char *p = s;
1195 /* If the result contains any bytes with the top bit set,
1196 it's UTF-8 and we should decode it to Unicode */
1197 #ifdef Py_USING_UNICODE
1198 while (*p != '\0') {
1199 if (*p & 0x80)
1200 break;
1201 p++;
1204 if (*p == '\0')
1205 res = PyString_FromStringAndSize(s, (int)(p-s));
1206 else {
1207 /* Convert UTF-8 to Unicode string */
1208 p = strchr(p, '\0');
1209 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1210 if (res == NULL) {
1211 PyErr_Clear();
1212 res = PyString_FromStringAndSize(s, (int)(p-s));
1215 #else
1216 p = strchr(p, '\0');
1217 res = PyString_FromStringAndSize(s, (int)(p-s));
1218 #endif
1220 return res;
1223 /* Tkapp_CallProc is the event procedure that is executed in the context of
1224 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1225 hold the Python lock. */
1227 static int
1228 Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1230 Tcl_Obj *objStore[ARGSZ];
1231 Tcl_Obj **objv;
1232 int objc;
1233 int i;
1234 ENTER_PYTHON
1235 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1236 if (!objv) {
1237 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1238 *(e->res) = NULL;
1240 LEAVE_PYTHON
1241 if (!objv)
1242 goto done;
1243 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1244 ENTER_PYTHON
1245 if (i == TCL_ERROR) {
1246 *(e->res) = NULL;
1247 *(e->exc_type) = NULL;
1248 *(e->exc_tb) = NULL;
1249 *(e->exc_value) = PyObject_CallFunction(
1250 Tkinter_TclError, "s",
1251 Tcl_GetStringResult(e->self->interp));
1253 else {
1254 *(e->res) = Tkapp_CallResult(e->self);
1256 LEAVE_PYTHON
1257 done:
1258 /* Wake up calling thread. */
1259 Tcl_MutexLock(&call_mutex);
1260 Tcl_ConditionNotify(&e->done);
1261 Tcl_MutexUnlock(&call_mutex);
1262 return 1;
1265 /* This is the main entry point for calling a Tcl command.
1266 It supports three cases, with regard to threading:
1267 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1268 the context of the calling thread.
1269 2. Tcl is threaded, caller of the command is in the interpreter thread:
1270 Execute the command in the calling thread. Since the Tcl lock will
1271 not be used, we can merge that with case 1.
1272 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1273 the interpreter thread. Allocation of Tcl objects needs to occur in the
1274 interpreter thread, so we ship the PyObject* args to the target thread,
1275 and perform processing there. */
1277 static PyObject *
1278 Tkapp_Call(PyObject *selfptr, PyObject *args)
1280 Tcl_Obj *objStore[ARGSZ];
1281 Tcl_Obj **objv = NULL;
1282 int objc, i;
1283 PyObject *res = NULL;
1284 TkappObject *self = (TkappObject*)selfptr;
1285 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1286 int flags = TCL_EVAL_DIRECT;
1288 /* If args is a single tuple, replace with contents of tuple */
1289 if (1 == PyTuple_Size(args)){
1290 PyObject* item = PyTuple_GetItem(args, 0);
1291 if (PyTuple_Check(item))
1292 args = item;
1294 #ifdef WITH_THREAD
1295 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1296 /* We cannot call the command directly. Instead, we must
1297 marshal the parameters to the interpreter thread. */
1298 Tkapp_CallEvent *ev;
1299 PyObject *exc_type, *exc_value, *exc_tb;
1300 if (!WaitForMainloop(self))
1301 return NULL;
1302 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1303 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1304 ev->self = self;
1305 ev->args = args;
1306 ev->res = &res;
1307 ev->exc_type = &exc_type;
1308 ev->exc_value = &exc_value;
1309 ev->exc_tb = &exc_tb;
1310 ev->done = (Tcl_Condition)0;
1312 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1314 if (res == NULL) {
1315 if (exc_type)
1316 PyErr_Restore(exc_type, exc_value, exc_tb);
1317 else
1318 PyErr_SetObject(Tkinter_TclError, exc_value);
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 = PyString_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 = PyString_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 = PyString_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 = PyString_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 = PyString_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 TCL_DECLARE_MUTEX(var_mutex)
1495 typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1496 typedef struct VarEvent {
1497 Tcl_Event ev; /* must be first */
1498 PyObject *self;
1499 PyObject *args;
1500 int flags;
1501 EventFunc func;
1502 PyObject **res;
1503 PyObject **exc_type;
1504 PyObject **exc_val;
1505 Tcl_Condition cond;
1506 } VarEvent;
1508 static int
1509 varname_converter(PyObject *in, void *_out)
1511 char **out = (char**)_out;
1512 if (PyString_Check(in)) {
1513 *out = PyString_AsString(in);
1514 return 1;
1516 if (PyTclObject_Check(in)) {
1517 *out = PyTclObject_TclString(in);
1518 return 1;
1520 /* XXX: Should give diagnostics. */
1521 return 0;
1524 void
1525 var_perform(VarEvent *ev)
1527 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1528 if (!*(ev->res)) {
1529 PyObject *exc, *val, *tb;
1530 PyErr_Fetch(&exc, &val, &tb);
1531 PyErr_NormalizeException(&exc, &val, &tb);
1532 *(ev->exc_type) = exc;
1533 *(ev->exc_val) = val;
1534 Py_DECREF(tb);
1539 static int
1540 var_proc(VarEvent* ev, int flags)
1542 ENTER_PYTHON
1543 var_perform(ev);
1544 Tcl_MutexLock(&var_mutex);
1545 Tcl_ConditionNotify(&ev->cond);
1546 Tcl_MutexUnlock(&var_mutex);
1547 LEAVE_PYTHON
1548 return 1;
1551 static PyObject*
1552 var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
1554 TkappObject *self = (TkappObject*)selfptr;
1555 #ifdef WITH_THREAD
1556 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1557 TkappObject *self = (TkappObject*)selfptr;
1558 VarEvent *ev;
1559 PyObject *res, *exc_type, *exc_val;
1561 /* The current thread is not the interpreter thread. Marshal
1562 the call to the interpreter thread, then wait for
1563 completion. */
1564 if (!WaitForMainloop(self))
1565 return NULL;
1567 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1569 ev->self = selfptr;
1570 ev->args = args;
1571 ev->flags = flags;
1572 ev->func = func;
1573 ev->res = &res;
1574 ev->exc_type = &exc_type;
1575 ev->exc_val = &exc_val;
1576 ev->cond = NULL;
1577 ev->ev.proc = (Tcl_EventProc*)var_proc;
1578 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1579 if (!res) {
1580 PyErr_SetObject(exc_type, exc_val);
1581 Py_DECREF(exc_type);
1582 Py_DECREF(exc_val);
1583 return NULL;
1585 return res;
1587 #endif
1588 /* Tcl is not threaded, or this is the interpreter thread. */
1589 return func(selfptr, args, flags);
1592 static PyObject *
1593 SetVar(PyObject *self, PyObject *args, int flags)
1595 char *name1, *name2;
1596 PyObject *newValue;
1597 PyObject *res = NULL;
1598 Tcl_Obj *newval, *ok;
1600 if (PyArg_ParseTuple(args, "O&O:setvar",
1601 varname_converter, &name1, &newValue)) {
1602 /* XXX Acquire tcl lock??? */
1603 newval = AsObj(newValue);
1604 if (newval == NULL)
1605 return NULL;
1606 ENTER_TCL
1607 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1608 newval, flags);
1609 ENTER_OVERLAP
1610 if (!ok)
1611 Tkinter_Error(self);
1612 else {
1613 res = Py_None;
1614 Py_INCREF(res);
1616 LEAVE_OVERLAP_TCL
1618 else {
1619 PyErr_Clear();
1620 if (PyArg_ParseTuple(args, "ssO:setvar",
1621 &name1, &name2, &newValue)) {
1622 /* XXX must hold tcl lock already??? */
1623 newval = AsObj(newValue);
1624 ENTER_TCL
1625 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1626 ENTER_OVERLAP
1627 if (!ok)
1628 Tkinter_Error(self);
1629 else {
1630 res = Py_None;
1631 Py_INCREF(res);
1633 LEAVE_OVERLAP_TCL
1635 else {
1636 return NULL;
1639 return res;
1642 static PyObject *
1643 Tkapp_SetVar(PyObject *self, PyObject *args)
1645 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1648 static PyObject *
1649 Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
1651 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1656 static PyObject *
1657 GetVar(PyObject *self, PyObject *args, int flags)
1659 char *name1, *name2=NULL;
1660 PyObject *res = NULL;
1661 Tcl_Obj *tres;
1663 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1664 varname_converter, &name1, &name2))
1665 return NULL;
1667 ENTER_TCL
1668 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1669 ENTER_OVERLAP
1670 if (tres == NULL) {
1671 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1672 } else {
1673 if (((TkappObject*)self)->wantobjects) {
1674 res = FromObj(self, tres);
1676 else {
1677 res = PyString_FromString(Tcl_GetString(tres));
1680 LEAVE_OVERLAP_TCL
1681 return res;
1684 static PyObject *
1685 Tkapp_GetVar(PyObject *self, PyObject *args)
1687 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1690 static PyObject *
1691 Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1693 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1698 static PyObject *
1699 UnsetVar(PyObject *self, PyObject *args, int flags)
1701 char *name1, *name2=NULL;
1702 int code;
1703 PyObject *res = NULL;
1705 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1706 return NULL;
1708 ENTER_TCL
1709 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1710 ENTER_OVERLAP
1711 if (code == TCL_ERROR)
1712 res = Tkinter_Error(self);
1713 else {
1714 Py_INCREF(Py_None);
1715 res = Py_None;
1717 LEAVE_OVERLAP_TCL
1718 return res;
1721 static PyObject *
1722 Tkapp_UnsetVar(PyObject *self, PyObject *args)
1724 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1727 static PyObject *
1728 Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1730 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1735 /** Tcl to Python **/
1737 static PyObject *
1738 Tkapp_GetInt(PyObject *self, PyObject *args)
1740 char *s;
1741 int v;
1743 if (PyTuple_Size(args) == 1) {
1744 PyObject* o = PyTuple_GetItem(args, 0);
1745 if (PyInt_Check(o)) {
1746 Py_INCREF(o);
1747 return o;
1750 if (!PyArg_ParseTuple(args, "s:getint", &s))
1751 return NULL;
1752 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1753 return Tkinter_Error(self);
1754 return Py_BuildValue("i", v);
1757 static PyObject *
1758 Tkapp_GetDouble(PyObject *self, PyObject *args)
1760 char *s;
1761 double v;
1763 if (PyTuple_Size(args) == 1) {
1764 PyObject *o = PyTuple_GetItem(args, 0);
1765 if (PyFloat_Check(o)) {
1766 Py_INCREF(o);
1767 return o;
1770 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1771 return NULL;
1772 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1773 return Tkinter_Error(self);
1774 return Py_BuildValue("d", v);
1777 static PyObject *
1778 Tkapp_GetBoolean(PyObject *self, PyObject *args)
1780 char *s;
1781 int v;
1783 if (PyTuple_Size(args) == 1) {
1784 PyObject *o = PyTuple_GetItem(args, 0);
1785 if (PyInt_Check(o)) {
1786 Py_INCREF(o);
1787 return o;
1790 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1791 return NULL;
1792 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1793 return Tkinter_Error(self);
1794 return PyBool_FromLong(v);
1797 static PyObject *
1798 Tkapp_ExprString(PyObject *self, PyObject *args)
1800 char *s;
1801 PyObject *res = NULL;
1802 int retval;
1804 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1805 return NULL;
1807 CHECK_TCL_APPARTMENT;
1809 ENTER_TCL
1810 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1811 ENTER_OVERLAP
1812 if (retval == TCL_ERROR)
1813 res = Tkinter_Error(self);
1814 else
1815 res = Py_BuildValue("s", Tkapp_Result(self));
1816 LEAVE_OVERLAP_TCL
1817 return res;
1820 static PyObject *
1821 Tkapp_ExprLong(PyObject *self, PyObject *args)
1823 char *s;
1824 PyObject *res = NULL;
1825 int retval;
1826 long v;
1828 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1829 return NULL;
1831 CHECK_TCL_APPARTMENT;
1833 ENTER_TCL
1834 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1835 ENTER_OVERLAP
1836 if (retval == TCL_ERROR)
1837 res = Tkinter_Error(self);
1838 else
1839 res = Py_BuildValue("l", v);
1840 LEAVE_OVERLAP_TCL
1841 return res;
1844 static PyObject *
1845 Tkapp_ExprDouble(PyObject *self, PyObject *args)
1847 char *s;
1848 PyObject *res = NULL;
1849 double v;
1850 int retval;
1852 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1853 return NULL;
1854 CHECK_TCL_APPARTMENT;
1855 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1856 ENTER_TCL
1857 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1858 ENTER_OVERLAP
1859 PyFPE_END_PROTECT(retval)
1860 if (retval == TCL_ERROR)
1861 res = Tkinter_Error(self);
1862 else
1863 res = Py_BuildValue("d", v);
1864 LEAVE_OVERLAP_TCL
1865 return res;
1868 static PyObject *
1869 Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1871 char *s;
1872 PyObject *res = NULL;
1873 int retval;
1874 int v;
1876 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1877 return NULL;
1878 CHECK_TCL_APPARTMENT;
1879 ENTER_TCL
1880 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1881 ENTER_OVERLAP
1882 if (retval == TCL_ERROR)
1883 res = Tkinter_Error(self);
1884 else
1885 res = Py_BuildValue("i", v);
1886 LEAVE_OVERLAP_TCL
1887 return res;
1892 static PyObject *
1893 Tkapp_SplitList(PyObject *self, PyObject *args)
1895 char *list;
1896 int argc;
1897 char **argv;
1898 PyObject *v;
1899 int i;
1901 if (PyTuple_Size(args) == 1) {
1902 v = PyTuple_GetItem(args, 0);
1903 if (PyTuple_Check(v)) {
1904 Py_INCREF(v);
1905 return v;
1908 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1909 return NULL;
1911 if (Tcl_SplitList(Tkapp_Interp(self), list,
1912 &argc, &argv) == TCL_ERROR) {
1913 PyMem_Free(list);
1914 return Tkinter_Error(self);
1917 if (!(v = PyTuple_New(argc)))
1918 goto finally;
1920 for (i = 0; i < argc; i++) {
1921 PyObject *s = PyString_FromString(argv[i]);
1922 if (!s || PyTuple_SetItem(v, i, s)) {
1923 Py_DECREF(v);
1924 v = NULL;
1925 goto finally;
1929 finally:
1930 ckfree(FREECAST argv);
1931 PyMem_Free(list);
1932 return v;
1935 static PyObject *
1936 Tkapp_Split(PyObject *self, PyObject *args)
1938 PyObject *v;
1939 char *list;
1941 if (PyTuple_Size(args) == 1) {
1942 PyObject* o = PyTuple_GetItem(args, 0);
1943 if (PyTuple_Check(o)) {
1944 o = SplitObj(o);
1945 return o;
1948 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1949 return NULL;
1950 v = Split(list);
1951 PyMem_Free(list);
1952 return v;
1955 static PyObject *
1956 Tkapp_Merge(PyObject *self, PyObject *args)
1958 char *s = Merge(args);
1959 PyObject *res = NULL;
1961 if (s) {
1962 res = PyString_FromString(s);
1963 ckfree(s);
1966 return res;
1971 /** Tcl Command **/
1973 /* Client data struct */
1974 typedef struct {
1975 PyObject *self;
1976 PyObject *func;
1977 } PythonCmd_ClientData;
1979 static int
1980 PythonCmd_Error(Tcl_Interp *interp)
1982 errorInCmd = 1;
1983 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1984 LEAVE_PYTHON
1985 return TCL_ERROR;
1988 /* This is the Tcl command that acts as a wrapper for Python
1989 * function or method.
1991 static int
1992 PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1994 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1995 PyObject *self, *func, *arg, *res, *tmp;
1996 int i, rv;
1997 char *s;
1999 ENTER_PYTHON
2001 /* TBD: no error checking here since we know, via the
2002 * Tkapp_CreateCommand() that the client data is a two-tuple
2004 self = data->self;
2005 func = data->func;
2007 /* Create argument list (argv1, ..., argvN) */
2008 if (!(arg = PyTuple_New(argc - 1)))
2009 return PythonCmd_Error(interp);
2011 for (i = 0; i < (argc - 1); i++) {
2012 PyObject *s = PyString_FromString(argv[i + 1]);
2013 if (!s || PyTuple_SetItem(arg, i, s)) {
2014 Py_DECREF(arg);
2015 return PythonCmd_Error(interp);
2018 res = PyEval_CallObject(func, arg);
2019 Py_DECREF(arg);
2021 if (res == NULL)
2022 return PythonCmd_Error(interp);
2024 if (!(tmp = PyList_New(0))) {
2025 Py_DECREF(res);
2026 return PythonCmd_Error(interp);
2029 s = AsString(res, tmp);
2030 if (s == NULL) {
2031 Py_DECREF(res);
2032 Py_DECREF(tmp);
2033 return PythonCmd_Error(interp);
2035 else {
2036 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
2037 rv = TCL_OK;
2040 Py_DECREF(res);
2041 Py_DECREF(tmp);
2043 LEAVE_PYTHON
2045 return rv;
2048 static void
2049 PythonCmdDelete(ClientData clientData)
2051 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2053 ENTER_PYTHON
2054 Py_XDECREF(data->self);
2055 Py_XDECREF(data->func);
2056 PyMem_DEL(data);
2057 LEAVE_PYTHON
2063 TCL_DECLARE_MUTEX(command_mutex)
2065 typedef struct CommandEvent{
2066 Tcl_Event ev;
2067 Tcl_Interp* interp;
2068 char *name;
2069 int create;
2070 int *status;
2071 ClientData *data;
2072 Tcl_Condition done;
2073 } CommandEvent;
2075 static int
2076 Tkapp_CommandProc(CommandEvent *ev, int flags)
2078 if (ev->create)
2079 *ev->status = Tcl_CreateCommand(
2080 ev->interp, ev->name, PythonCmd,
2081 ev->data, PythonCmdDelete) == NULL;
2082 else
2083 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2084 Tcl_MutexLock(&command_mutex);
2085 Tcl_ConditionNotify(&ev->done);
2086 Tcl_MutexUnlock(&command_mutex);
2087 return 1;
2090 static PyObject *
2091 Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2093 TkappObject *self = (TkappObject*)selfptr;
2094 PythonCmd_ClientData *data;
2095 char *cmdName;
2096 PyObject *func;
2097 int err;
2099 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2100 return NULL;
2101 if (!PyCallable_Check(func)) {
2102 PyErr_SetString(PyExc_TypeError, "command not callable");
2103 return NULL;
2106 #ifdef WITH_THREAD
2107 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2108 !WaitForMainloop(self))
2109 return NULL;
2110 #endif
2112 data = PyMem_NEW(PythonCmd_ClientData, 1);
2113 if (!data)
2114 return PyErr_NoMemory();
2115 Py_INCREF(self);
2116 Py_INCREF(func);
2117 data->self = selfptr;
2118 data->func = func;
2120 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2121 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2122 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2123 ev->interp = self->interp;
2124 ev->create = 1;
2125 ev->name = cmdName;
2126 ev->data = (ClientData)data;
2127 ev->status = &err;
2128 ev->done = NULL;
2129 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2131 else {
2132 ENTER_TCL
2133 err = Tcl_CreateCommand(
2134 Tkapp_Interp(self), cmdName, PythonCmd,
2135 (ClientData)data, PythonCmdDelete) == NULL;
2136 LEAVE_TCL
2138 if (err) {
2139 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2140 PyMem_DEL(data);
2141 return NULL;
2144 Py_INCREF(Py_None);
2145 return Py_None;
2150 static PyObject *
2151 Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2153 TkappObject *self = (TkappObject*)selfptr;
2154 char *cmdName;
2155 int err;
2157 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2158 return NULL;
2159 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2160 CommandEvent *ev;
2161 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2162 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2163 ev->interp = self->interp;
2164 ev->create = 0;
2165 ev->name = cmdName;
2166 ev->status = &err;
2167 ev->done = NULL;
2168 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2169 &command_mutex);
2171 else {
2172 ENTER_TCL
2173 err = Tcl_DeleteCommand(self->interp, cmdName);
2174 LEAVE_TCL
2176 if (err == -1) {
2177 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2178 return NULL;
2180 Py_INCREF(Py_None);
2181 return Py_None;
2186 #ifdef HAVE_CREATEFILEHANDLER
2187 /** File Handler **/
2189 typedef struct _fhcdata {
2190 PyObject *func;
2191 PyObject *file;
2192 int id;
2193 struct _fhcdata *next;
2194 } FileHandler_ClientData;
2196 static FileHandler_ClientData *HeadFHCD;
2198 static FileHandler_ClientData *
2199 NewFHCD(PyObject *func, PyObject *file, int id)
2201 FileHandler_ClientData *p;
2202 p = PyMem_NEW(FileHandler_ClientData, 1);
2203 if (p != NULL) {
2204 Py_XINCREF(func);
2205 Py_XINCREF(file);
2206 p->func = func;
2207 p->file = file;
2208 p->id = id;
2209 p->next = HeadFHCD;
2210 HeadFHCD = p;
2212 return p;
2215 static void
2216 DeleteFHCD(int id)
2218 FileHandler_ClientData *p, **pp;
2220 pp = &HeadFHCD;
2221 while ((p = *pp) != NULL) {
2222 if (p->id == id) {
2223 *pp = p->next;
2224 Py_XDECREF(p->func);
2225 Py_XDECREF(p->file);
2226 PyMem_DEL(p);
2228 else
2229 pp = &p->next;
2233 static void
2234 FileHandler(ClientData clientData, int mask)
2236 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2237 PyObject *func, *file, *arg, *res;
2239 ENTER_PYTHON
2240 func = data->func;
2241 file = data->file;
2243 arg = Py_BuildValue("(Oi)", file, (long) mask);
2244 res = PyEval_CallObject(func, arg);
2245 Py_DECREF(arg);
2247 if (res == NULL) {
2248 errorInCmd = 1;
2249 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2251 Py_XDECREF(res);
2252 LEAVE_PYTHON
2255 static PyObject *
2256 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2257 /* args is (file, mask, func) */
2259 FileHandler_ClientData *data;
2260 PyObject *file, *func;
2261 int mask, tfile;
2263 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2264 &file, &mask, &func))
2265 return NULL;
2267 #ifdef WITH_THREAD
2268 if (!self && !tcl_lock) {
2269 /* We don't have the Tcl lock since Tcl is threaded. */
2270 PyErr_SetString(PyExc_RuntimeError,
2271 "_tkinter.createfilehandler not supported "
2272 "for threaded Tcl");
2273 return NULL;
2275 #endif
2277 if (self) {
2278 CHECK_TCL_APPARTMENT;
2281 tfile = PyObject_AsFileDescriptor(file);
2282 if (tfile < 0)
2283 return NULL;
2284 if (!PyCallable_Check(func)) {
2285 PyErr_SetString(PyExc_TypeError, "bad argument list");
2286 return NULL;
2289 data = NewFHCD(func, file, tfile);
2290 if (data == NULL)
2291 return NULL;
2293 /* Ought to check for null Tcl_File object... */
2294 ENTER_TCL
2295 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2296 LEAVE_TCL
2297 Py_INCREF(Py_None);
2298 return Py_None;
2301 static PyObject *
2302 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2304 PyObject *file;
2305 int tfile;
2307 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2308 return NULL;
2310 #ifdef WITH_THREAD
2311 if (!self && !tcl_lock) {
2312 /* We don't have the Tcl lock since Tcl is threaded. */
2313 PyErr_SetString(PyExc_RuntimeError,
2314 "_tkinter.deletefilehandler not supported "
2315 "for threaded Tcl");
2316 return NULL;
2318 #endif
2320 if (self) {
2321 CHECK_TCL_APPARTMENT;
2324 tfile = PyObject_AsFileDescriptor(file);
2325 if (tfile < 0)
2326 return NULL;
2328 DeleteFHCD(tfile);
2330 /* Ought to check for null Tcl_File object... */
2331 ENTER_TCL
2332 Tcl_DeleteFileHandler(tfile);
2333 LEAVE_TCL
2334 Py_INCREF(Py_None);
2335 return Py_None;
2337 #endif /* HAVE_CREATEFILEHANDLER */
2340 /**** Tktt Object (timer token) ****/
2342 static PyTypeObject Tktt_Type;
2344 typedef struct {
2345 PyObject_HEAD
2346 Tcl_TimerToken token;
2347 PyObject *func;
2348 } TkttObject;
2350 static PyObject *
2351 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2353 TkttObject *v = (TkttObject *)self;
2354 PyObject *func = v->func;
2356 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2357 return NULL;
2358 if (v->token != NULL) {
2359 Tcl_DeleteTimerHandler(v->token);
2360 v->token = NULL;
2362 if (func != NULL) {
2363 v->func = NULL;
2364 Py_DECREF(func);
2365 Py_DECREF(v); /* See Tktt_New() */
2367 Py_INCREF(Py_None);
2368 return Py_None;
2371 static PyMethodDef Tktt_methods[] =
2373 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2374 {NULL, NULL}
2377 static TkttObject *
2378 Tktt_New(PyObject *func)
2380 TkttObject *v;
2382 v = PyObject_New(TkttObject, &Tktt_Type);
2383 if (v == NULL)
2384 return NULL;
2386 Py_INCREF(func);
2387 v->token = NULL;
2388 v->func = func;
2390 /* Extra reference, deleted when called or when handler is deleted */
2391 Py_INCREF(v);
2392 return v;
2395 static void
2396 Tktt_Dealloc(PyObject *self)
2398 TkttObject *v = (TkttObject *)self;
2399 PyObject *func = v->func;
2401 Py_XDECREF(func);
2403 PyObject_Del(self);
2406 static PyObject *
2407 Tktt_Repr(PyObject *self)
2409 TkttObject *v = (TkttObject *)self;
2410 char buf[100];
2412 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2413 v->func == NULL ? ", handler deleted" : "");
2414 return PyString_FromString(buf);
2417 static PyObject *
2418 Tktt_GetAttr(PyObject *self, char *name)
2420 return Py_FindMethod(Tktt_methods, self, name);
2423 static PyTypeObject Tktt_Type =
2425 PyVarObject_HEAD_INIT(NULL, 0)
2426 "tktimertoken", /*tp_name */
2427 sizeof(TkttObject), /*tp_basicsize */
2428 0, /*tp_itemsize */
2429 Tktt_Dealloc, /*tp_dealloc */
2430 0, /*tp_print */
2431 Tktt_GetAttr, /*tp_getattr */
2432 0, /*tp_setattr */
2433 0, /*tp_compare */
2434 Tktt_Repr, /*tp_repr */
2435 0, /*tp_as_number */
2436 0, /*tp_as_sequence */
2437 0, /*tp_as_mapping */
2438 0, /*tp_hash */
2443 /** Timer Handler **/
2445 static void
2446 TimerHandler(ClientData clientData)
2448 TkttObject *v = (TkttObject *)clientData;
2449 PyObject *func = v->func;
2450 PyObject *res;
2452 if (func == NULL)
2453 return;
2455 v->func = NULL;
2457 ENTER_PYTHON
2459 res = PyEval_CallObject(func, NULL);
2460 Py_DECREF(func);
2461 Py_DECREF(v); /* See Tktt_New() */
2463 if (res == NULL) {
2464 errorInCmd = 1;
2465 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2467 else
2468 Py_DECREF(res);
2470 LEAVE_PYTHON
2473 static PyObject *
2474 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2476 int milliseconds;
2477 PyObject *func;
2478 TkttObject *v;
2480 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2481 &milliseconds, &func))
2482 return NULL;
2483 if (!PyCallable_Check(func)) {
2484 PyErr_SetString(PyExc_TypeError, "bad argument list");
2485 return NULL;
2488 #ifdef WITH_THREAD
2489 if (!self && !tcl_lock) {
2490 /* We don't have the Tcl lock since Tcl is threaded. */
2491 PyErr_SetString(PyExc_RuntimeError,
2492 "_tkinter.createtimerhandler not supported "
2493 "for threaded Tcl");
2494 return NULL;
2496 #endif
2498 if (self) {
2499 CHECK_TCL_APPARTMENT;
2502 v = Tktt_New(func);
2503 if (v) {
2504 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2505 (ClientData)v);
2508 return (PyObject *) v;
2512 /** Event Loop **/
2514 static PyObject *
2515 Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
2517 int threshold = 0;
2518 TkappObject *self = (TkappObject*)selfptr;
2519 #ifdef WITH_THREAD
2520 PyThreadState *tstate = PyThreadState_Get();
2521 #endif
2523 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2524 return NULL;
2526 #ifdef WITH_THREAD
2527 if (!self && !tcl_lock) {
2528 /* We don't have the Tcl lock since Tcl is threaded. */
2529 PyErr_SetString(PyExc_RuntimeError,
2530 "_tkinter.mainloop not supported "
2531 "for threaded Tcl");
2532 return NULL;
2534 #endif
2536 if (self) {
2537 CHECK_TCL_APPARTMENT;
2538 self->dispatching = 1;
2541 quitMainLoop = 0;
2542 while (Tk_GetNumMainWindows() > threshold &&
2543 !quitMainLoop &&
2544 !errorInCmd)
2546 int result;
2548 #ifdef WITH_THREAD
2549 if (self && self->threaded) {
2550 /* Allow other Python threads to run. */
2551 ENTER_TCL
2552 result = Tcl_DoOneEvent(0);
2553 LEAVE_TCL
2555 else {
2556 Py_BEGIN_ALLOW_THREADS
2557 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2558 tcl_tstate = tstate;
2559 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2560 tcl_tstate = NULL;
2561 if(tcl_lock)PyThread_release_lock(tcl_lock);
2562 if (result == 0)
2563 Sleep(Tkinter_busywaitinterval);
2564 Py_END_ALLOW_THREADS
2566 #else
2567 result = Tcl_DoOneEvent(0);
2568 #endif
2570 if (PyErr_CheckSignals() != 0) {
2571 if (self)
2572 self->dispatching = 0;
2573 return NULL;
2575 if (result < 0)
2576 break;
2578 if (self)
2579 self->dispatching = 0;
2580 quitMainLoop = 0;
2582 if (errorInCmd) {
2583 errorInCmd = 0;
2584 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2585 excInCmd = valInCmd = trbInCmd = NULL;
2586 return NULL;
2588 Py_INCREF(Py_None);
2589 return Py_None;
2592 static PyObject *
2593 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
2595 int flags = 0;
2596 int rv;
2598 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2599 return NULL;
2601 ENTER_TCL
2602 rv = Tcl_DoOneEvent(flags);
2603 LEAVE_TCL
2604 return Py_BuildValue("i", rv);
2607 static PyObject *
2608 Tkapp_Quit(PyObject *self, PyObject *args)
2611 if (!PyArg_ParseTuple(args, ":quit"))
2612 return NULL;
2614 quitMainLoop = 1;
2615 Py_INCREF(Py_None);
2616 return Py_None;
2619 static PyObject *
2620 Tkapp_InterpAddr(PyObject *self, PyObject *args)
2623 if (!PyArg_ParseTuple(args, ":interpaddr"))
2624 return NULL;
2626 return PyInt_FromLong((long)Tkapp_Interp(self));
2629 static PyObject *
2630 Tkapp_TkInit(PyObject *self, PyObject *args)
2632 static int has_failed;
2633 Tcl_Interp *interp = Tkapp_Interp(self);
2634 Tk_Window main_window;
2635 const char * _tk_exists = NULL;
2636 int err;
2637 main_window = Tk_MainWindow(interp);
2639 /* In all current versions of Tk (including 8.4.13), Tk_Init
2640 deadlocks on the second call when the first call failed.
2641 To avoid the deadlock, we just refuse the second call through
2642 a static variable. */
2643 if (has_failed) {
2644 PyErr_SetString(Tkinter_TclError,
2645 "Calling Tk_Init again after a previous call failed might deadlock");
2646 return NULL;
2649 /* We want to guard against calling Tk_Init() multiple times */
2650 CHECK_TCL_APPARTMENT;
2651 ENTER_TCL
2652 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2653 ENTER_OVERLAP
2654 if (err == TCL_ERROR) {
2655 /* This sets an exception, but we cannot return right
2656 away because we need to exit the overlap first. */
2657 Tkinter_Error(self);
2658 } else {
2659 _tk_exists = Tkapp_Result(self);
2661 LEAVE_OVERLAP_TCL
2662 if (err == TCL_ERROR) {
2663 return NULL;
2665 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2666 if (Tk_Init(interp) == TCL_ERROR) {
2667 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2668 has_failed = 1;
2669 return NULL;
2672 Py_INCREF(Py_None);
2673 return Py_None;
2676 static PyObject *
2677 Tkapp_WantObjects(PyObject *self, PyObject *args)
2680 int wantobjects = -1;
2681 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2682 return NULL;
2683 if (wantobjects == -1)
2684 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2685 ((TkappObject*)self)->wantobjects = wantobjects;
2687 Py_INCREF(Py_None);
2688 return Py_None;
2691 static PyObject *
2692 Tkapp_WillDispatch(PyObject *self, PyObject *args)
2695 ((TkappObject*)self)->dispatching = 1;
2697 Py_INCREF(Py_None);
2698 return Py_None;
2702 /**** Tkapp Method List ****/
2704 static PyMethodDef Tkapp_methods[] =
2706 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2707 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2708 {"call", Tkapp_Call, METH_VARARGS},
2709 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2710 {"eval", Tkapp_Eval, METH_VARARGS},
2711 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2712 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2713 {"record", Tkapp_Record, METH_VARARGS},
2714 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2715 {"setvar", Tkapp_SetVar, METH_VARARGS},
2716 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2717 {"getvar", Tkapp_GetVar, METH_VARARGS},
2718 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2719 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2720 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2721 {"getint", Tkapp_GetInt, METH_VARARGS},
2722 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2723 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2724 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2725 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2726 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2727 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2728 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2729 {"split", Tkapp_Split, METH_VARARGS},
2730 {"merge", Tkapp_Merge, METH_VARARGS},
2731 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2732 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2733 #ifdef HAVE_CREATEFILEHANDLER
2734 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2735 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2736 #endif
2737 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2738 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2739 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2740 {"quit", Tkapp_Quit, METH_VARARGS},
2741 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2742 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2743 {NULL, NULL}
2748 /**** Tkapp Type Methods ****/
2750 static void
2751 Tkapp_Dealloc(PyObject *self)
2753 /*CHECK_TCL_APPARTMENT;*/
2754 ENTER_TCL
2755 Tcl_DeleteInterp(Tkapp_Interp(self));
2756 LEAVE_TCL
2757 PyObject_Del(self);
2758 DisableEventHook();
2761 static PyObject *
2762 Tkapp_GetAttr(PyObject *self, char *name)
2764 return Py_FindMethod(Tkapp_methods, self, name);
2767 static PyTypeObject Tkapp_Type =
2769 PyVarObject_HEAD_INIT(NULL, 0)
2770 "tkapp", /*tp_name */
2771 sizeof(TkappObject), /*tp_basicsize */
2772 0, /*tp_itemsize */
2773 Tkapp_Dealloc, /*tp_dealloc */
2774 0, /*tp_print */
2775 Tkapp_GetAttr, /*tp_getattr */
2776 0, /*tp_setattr */
2777 0, /*tp_compare */
2778 0, /*tp_repr */
2779 0, /*tp_as_number */
2780 0, /*tp_as_sequence */
2781 0, /*tp_as_mapping */
2782 0, /*tp_hash */
2787 /**** Tkinter Module ****/
2789 typedef struct {
2790 PyObject* tuple;
2791 int size; /* current size */
2792 int maxsize; /* allocated size */
2793 } FlattenContext;
2795 static int
2796 _bump(FlattenContext* context, int size)
2798 /* expand tuple to hold (at least) size new items.
2799 return true if successful, false if an exception was raised */
2801 int maxsize = context->maxsize * 2;
2803 if (maxsize < context->size + size)
2804 maxsize = context->size + size;
2806 context->maxsize = maxsize;
2808 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2811 static int
2812 _flatten1(FlattenContext* context, PyObject* item, int depth)
2814 /* add tuple or list to argument tuple (recursively) */
2816 int i, size;
2818 if (depth > 1000) {
2819 PyErr_SetString(PyExc_ValueError,
2820 "nesting too deep in _flatten");
2821 return 0;
2822 } else if (PyList_Check(item)) {
2823 size = PyList_GET_SIZE(item);
2824 /* preallocate (assume no nesting) */
2825 if (context->size + size > context->maxsize &&
2826 !_bump(context, size))
2827 return 0;
2828 /* copy items to output tuple */
2829 for (i = 0; i < size; i++) {
2830 PyObject *o = PyList_GET_ITEM(item, i);
2831 if (PyList_Check(o) || PyTuple_Check(o)) {
2832 if (!_flatten1(context, o, depth + 1))
2833 return 0;
2834 } else if (o != Py_None) {
2835 if (context->size + 1 > context->maxsize &&
2836 !_bump(context, 1))
2837 return 0;
2838 Py_INCREF(o);
2839 PyTuple_SET_ITEM(context->tuple,
2840 context->size++, o);
2843 } else if (PyTuple_Check(item)) {
2844 /* same, for tuples */
2845 size = PyTuple_GET_SIZE(item);
2846 if (context->size + size > context->maxsize &&
2847 !_bump(context, size))
2848 return 0;
2849 for (i = 0; i < size; i++) {
2850 PyObject *o = PyTuple_GET_ITEM(item, i);
2851 if (PyList_Check(o) || PyTuple_Check(o)) {
2852 if (!_flatten1(context, o, depth + 1))
2853 return 0;
2854 } else if (o != Py_None) {
2855 if (context->size + 1 > context->maxsize &&
2856 !_bump(context, 1))
2857 return 0;
2858 Py_INCREF(o);
2859 PyTuple_SET_ITEM(context->tuple,
2860 context->size++, o);
2863 } else {
2864 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2865 return 0;
2867 return 1;
2870 static PyObject *
2871 Tkinter_Flatten(PyObject* self, PyObject* args)
2873 FlattenContext context;
2874 PyObject* item;
2876 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2877 return NULL;
2879 context.maxsize = PySequence_Size(item);
2880 if (context.maxsize <= 0)
2881 return PyTuple_New(0);
2883 context.tuple = PyTuple_New(context.maxsize);
2884 if (!context.tuple)
2885 return NULL;
2887 context.size = 0;
2889 if (!_flatten1(&context, item,0))
2890 return NULL;
2892 if (_PyTuple_Resize(&context.tuple, context.size))
2893 return NULL;
2895 return context.tuple;
2898 static PyObject *
2899 Tkinter_Create(PyObject *self, PyObject *args)
2901 char *screenName = NULL;
2902 char *baseName = NULL;
2903 char *className = NULL;
2904 int interactive = 0;
2905 int wantobjects = 0;
2906 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2907 int sync = 0; /* pass -sync to wish */
2908 char *use = NULL; /* pass -use to wish */
2910 baseName = strrchr(Py_GetProgramName(), '/');
2911 if (baseName != NULL)
2912 baseName++;
2913 else
2914 baseName = Py_GetProgramName();
2915 className = "Tk";
2917 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2918 &screenName, &baseName, &className,
2919 &interactive, &wantobjects, &wantTk,
2920 &sync, &use))
2921 return NULL;
2923 return (PyObject *) Tkapp_New(screenName, baseName, className,
2924 interactive, wantobjects, wantTk,
2925 sync, use);
2928 static PyObject *
2929 Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2931 int new_val;
2932 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2933 return NULL;
2934 if (new_val < 0) {
2935 PyErr_SetString(PyExc_ValueError,
2936 "busywaitinterval must be >= 0");
2937 return NULL;
2939 Tkinter_busywaitinterval = new_val;
2940 Py_INCREF(Py_None);
2941 return Py_None;
2944 static char setbusywaitinterval_doc[] =
2945 "setbusywaitinterval(n) -> None\n\
2947 Set the busy-wait interval in milliseconds between successive\n\
2948 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2949 It should be set to a divisor of the maximum time between\n\
2950 frames in an animation.";
2952 static PyObject *
2953 Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2955 return PyInt_FromLong(Tkinter_busywaitinterval);
2958 static char getbusywaitinterval_doc[] =
2959 "getbusywaitinterval() -> int\n\
2961 Return the current busy-wait interval between successive\n\
2962 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2964 static PyMethodDef moduleMethods[] =
2966 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2967 {"create", Tkinter_Create, METH_VARARGS},
2968 #ifdef HAVE_CREATEFILEHANDLER
2969 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2970 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2971 #endif
2972 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2973 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2974 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2975 {"quit", Tkapp_Quit, METH_VARARGS},
2976 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2977 setbusywaitinterval_doc},
2978 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2979 METH_NOARGS, getbusywaitinterval_doc},
2980 {NULL, NULL}
2983 #ifdef WAIT_FOR_STDIN
2985 static int stdin_ready = 0;
2987 #ifndef MS_WINDOWS
2988 static void
2989 MyFileProc(void *clientData, int mask)
2991 stdin_ready = 1;
2993 #endif
2995 #ifdef WITH_THREAD
2996 static PyThreadState *event_tstate = NULL;
2997 #endif
2999 static int
3000 EventHook(void)
3002 #ifndef MS_WINDOWS
3003 int tfile;
3004 #endif
3005 #ifdef WITH_THREAD
3006 PyEval_RestoreThread(event_tstate);
3007 #endif
3008 stdin_ready = 0;
3009 errorInCmd = 0;
3010 #ifndef MS_WINDOWS
3011 tfile = fileno(stdin);
3012 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
3013 #endif
3014 while (!errorInCmd && !stdin_ready) {
3015 int result;
3016 #ifdef MS_WINDOWS
3017 if (_kbhit()) {
3018 stdin_ready = 1;
3019 break;
3021 #endif
3022 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3023 Py_BEGIN_ALLOW_THREADS
3024 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3025 tcl_tstate = event_tstate;
3027 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3029 tcl_tstate = NULL;
3030 if(tcl_lock)PyThread_release_lock(tcl_lock);
3031 if (result == 0)
3032 Sleep(Tkinter_busywaitinterval);
3033 Py_END_ALLOW_THREADS
3034 #else
3035 result = Tcl_DoOneEvent(0);
3036 #endif
3038 if (result < 0)
3039 break;
3041 #ifndef MS_WINDOWS
3042 Tcl_DeleteFileHandler(tfile);
3043 #endif
3044 if (errorInCmd) {
3045 errorInCmd = 0;
3046 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3047 excInCmd = valInCmd = trbInCmd = NULL;
3048 PyErr_Print();
3050 #ifdef WITH_THREAD
3051 PyEval_SaveThread();
3052 #endif
3053 return 0;
3056 #endif
3058 static void
3059 EnableEventHook(void)
3061 #ifdef WAIT_FOR_STDIN
3062 if (PyOS_InputHook == NULL) {
3063 #ifdef WITH_THREAD
3064 event_tstate = PyThreadState_Get();
3065 #endif
3066 PyOS_InputHook = EventHook;
3068 #endif
3071 static void
3072 DisableEventHook(void)
3074 #ifdef WAIT_FOR_STDIN
3075 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3076 PyOS_InputHook = NULL;
3078 #endif
3082 /* all errors will be checked in one fell swoop in init_tkinter() */
3083 static void
3084 ins_long(PyObject *d, char *name, long val)
3086 PyObject *v = PyInt_FromLong(val);
3087 if (v) {
3088 PyDict_SetItemString(d, name, v);
3089 Py_DECREF(v);
3092 static void
3093 ins_string(PyObject *d, char *name, char *val)
3095 PyObject *v = PyString_FromString(val);
3096 if (v) {
3097 PyDict_SetItemString(d, name, v);
3098 Py_DECREF(v);
3103 PyMODINIT_FUNC
3104 init_tkinter(void)
3106 PyObject *m, *d;
3108 Py_Type(&Tkapp_Type) = &PyType_Type;
3110 #ifdef WITH_THREAD
3111 tcl_lock = PyThread_allocate_lock();
3112 #endif
3114 m = Py_InitModule("_tkinter", moduleMethods);
3115 if (m == NULL)
3116 return;
3118 d = PyModule_GetDict(m);
3119 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3120 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3122 ins_long(d, "READABLE", TCL_READABLE);
3123 ins_long(d, "WRITABLE", TCL_WRITABLE);
3124 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3125 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3126 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3127 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3128 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3129 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3130 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3131 ins_string(d, "TK_VERSION", TK_VERSION);
3132 ins_string(d, "TCL_VERSION", TCL_VERSION);
3134 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3136 Py_Type(&Tktt_Type) = &PyType_Type;
3137 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3139 Py_Type(&PyTclObject_Type) = &PyType_Type;
3140 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3142 #ifdef TK_AQUA
3143 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3144 * start waking up. Note that Tcl_FindExecutable will do this, this
3145 * code must be above it! The original warning from
3146 * tkMacOSXAppInit.c is copied below.
3148 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3149 * Tcl interpreter for now. It probably should work to do this
3150 * in the other order, but for now it doesn't seem to.
3153 Tk_MacOSXSetupTkNotifier();
3154 #endif
3157 /* This helps the dynamic loader; in Unicode aware Tcl versions
3158 it also helps Tcl find its encodings. */
3159 Tcl_FindExecutable(Py_GetProgramName());
3161 if (PyErr_Occurred())
3162 return;
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