Updated documentation for findCaller() to indicate that a 3-tuple is now returned...
[python.git] / Modules / _tkinter.c
blob0b853b5b48bc9f29132bec5f7c8ccf9444e4623a
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) ((v)->ob_type == &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, ((PyObject *) v)->ob_refcnt))
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 #ifdef WITH_THREAD
1289 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1290 /* We cannot call the command directly. Instead, we must
1291 marshal the parameters to the interpreter thread. */
1292 Tkapp_CallEvent *ev;
1293 PyObject *exc_type, *exc_value, *exc_tb;
1294 if (!WaitForMainloop(self))
1295 return NULL;
1296 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1297 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1298 ev->self = self;
1299 ev->args = args;
1300 ev->res = &res;
1301 ev->exc_type = &exc_type;
1302 ev->exc_value = &exc_value;
1303 ev->exc_tb = &exc_tb;
1304 ev->done = (Tcl_Condition)0;
1306 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1308 if (res == NULL) {
1309 if (exc_type)
1310 PyErr_Restore(exc_type, exc_value, exc_tb);
1311 else
1312 PyErr_SetObject(Tkinter_TclError, exc_value);
1315 else
1316 #endif
1319 objv = Tkapp_CallArgs(args, objStore, &objc);
1320 if (!objv)
1321 return NULL;
1323 ENTER_TCL
1325 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1327 ENTER_OVERLAP
1329 if (i == TCL_ERROR)
1330 Tkinter_Error(selfptr);
1331 else
1332 res = Tkapp_CallResult(self);
1334 LEAVE_OVERLAP_TCL
1336 Tkapp_CallDeallocArgs(objv, objStore, objc);
1338 return res;
1342 static PyObject *
1343 Tkapp_GlobalCall(PyObject *self, PyObject *args)
1345 /* Could do the same here as for Tkapp_Call(), but this is not used
1346 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1347 way for the user to do what all its Global* variants do (save and
1348 reset the scope pointer, call the local version, restore the saved
1349 scope pointer). */
1351 char *cmd;
1352 PyObject *res = NULL;
1354 CHECK_TCL_APPARTMENT;
1356 cmd = Merge(args);
1357 if (cmd) {
1358 int err;
1359 ENTER_TCL
1360 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1361 ENTER_OVERLAP
1362 if (err == TCL_ERROR)
1363 res = Tkinter_Error(self);
1364 else
1365 res = PyString_FromString(Tkapp_Result(self));
1366 LEAVE_OVERLAP_TCL
1367 ckfree(cmd);
1370 return res;
1373 static PyObject *
1374 Tkapp_Eval(PyObject *self, PyObject *args)
1376 char *script;
1377 PyObject *res = NULL;
1378 int err;
1380 if (!PyArg_ParseTuple(args, "s:eval", &script))
1381 return NULL;
1383 CHECK_TCL_APPARTMENT;
1385 ENTER_TCL
1386 err = Tcl_Eval(Tkapp_Interp(self), script);
1387 ENTER_OVERLAP
1388 if (err == TCL_ERROR)
1389 res = Tkinter_Error(self);
1390 else
1391 res = PyString_FromString(Tkapp_Result(self));
1392 LEAVE_OVERLAP_TCL
1393 return res;
1396 static PyObject *
1397 Tkapp_GlobalEval(PyObject *self, PyObject *args)
1399 char *script;
1400 PyObject *res = NULL;
1401 int err;
1403 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1404 return NULL;
1406 CHECK_TCL_APPARTMENT;
1408 ENTER_TCL
1409 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1410 ENTER_OVERLAP
1411 if (err == TCL_ERROR)
1412 res = Tkinter_Error(self);
1413 else
1414 res = PyString_FromString(Tkapp_Result(self));
1415 LEAVE_OVERLAP_TCL
1416 return res;
1419 static PyObject *
1420 Tkapp_EvalFile(PyObject *self, PyObject *args)
1422 char *fileName;
1423 PyObject *res = NULL;
1424 int err;
1426 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1427 return NULL;
1429 CHECK_TCL_APPARTMENT;
1431 ENTER_TCL
1432 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1433 ENTER_OVERLAP
1434 if (err == TCL_ERROR)
1435 res = Tkinter_Error(self);
1437 else
1438 res = PyString_FromString(Tkapp_Result(self));
1439 LEAVE_OVERLAP_TCL
1440 return res;
1443 static PyObject *
1444 Tkapp_Record(PyObject *self, PyObject *args)
1446 char *script;
1447 PyObject *res = NULL;
1448 int err;
1450 if (!PyArg_ParseTuple(args, "s", &script))
1451 return NULL;
1453 CHECK_TCL_APPARTMENT;
1455 ENTER_TCL
1456 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1457 ENTER_OVERLAP
1458 if (err == TCL_ERROR)
1459 res = Tkinter_Error(self);
1460 else
1461 res = PyString_FromString(Tkapp_Result(self));
1462 LEAVE_OVERLAP_TCL
1463 return res;
1466 static PyObject *
1467 Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
1469 char *msg;
1471 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1472 return NULL;
1473 CHECK_TCL_APPARTMENT;
1475 ENTER_TCL
1476 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1477 LEAVE_TCL
1479 Py_INCREF(Py_None);
1480 return Py_None;
1485 /** Tcl Variable **/
1487 TCL_DECLARE_MUTEX(var_mutex)
1489 typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1490 typedef struct VarEvent {
1491 Tcl_Event ev; /* must be first */
1492 PyObject *self;
1493 PyObject *args;
1494 int flags;
1495 EventFunc func;
1496 PyObject **res;
1497 PyObject **exc_type;
1498 PyObject **exc_val;
1499 Tcl_Condition cond;
1500 } VarEvent;
1502 static int
1503 varname_converter(PyObject *in, void *_out)
1505 char **out = (char**)_out;
1506 if (PyString_Check(in)) {
1507 *out = PyString_AsString(in);
1508 return 1;
1510 if (PyTclObject_Check(in)) {
1511 *out = PyTclObject_TclString(in);
1512 return 1;
1514 /* XXX: Should give diagnostics. */
1515 return 0;
1518 void
1519 var_perform(VarEvent *ev)
1521 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1522 if (!*(ev->res)) {
1523 PyObject *exc, *val, *tb;
1524 PyErr_Fetch(&exc, &val, &tb);
1525 PyErr_NormalizeException(&exc, &val, &tb);
1526 *(ev->exc_type) = exc;
1527 *(ev->exc_val) = val;
1528 Py_DECREF(tb);
1533 static int
1534 var_proc(VarEvent* ev, int flags)
1536 ENTER_PYTHON
1537 var_perform(ev);
1538 Tcl_MutexLock(&var_mutex);
1539 Tcl_ConditionNotify(&ev->cond);
1540 Tcl_MutexUnlock(&var_mutex);
1541 LEAVE_PYTHON
1542 return 1;
1545 static PyObject*
1546 var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
1548 TkappObject *self = (TkappObject*)selfptr;
1549 #ifdef WITH_THREAD
1550 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1551 TkappObject *self = (TkappObject*)selfptr;
1552 VarEvent *ev;
1553 PyObject *res, *exc_type, *exc_val;
1555 /* The current thread is not the interpreter thread. Marshal
1556 the call to the interpreter thread, then wait for
1557 completion. */
1558 if (!WaitForMainloop(self))
1559 return NULL;
1561 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1563 ev->self = selfptr;
1564 ev->args = args;
1565 ev->flags = flags;
1566 ev->func = func;
1567 ev->res = &res;
1568 ev->exc_type = &exc_type;
1569 ev->exc_val = &exc_val;
1570 ev->cond = NULL;
1571 ev->ev.proc = (Tcl_EventProc*)var_proc;
1572 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1573 if (!res) {
1574 PyErr_SetObject(exc_type, exc_val);
1575 Py_DECREF(exc_type);
1576 Py_DECREF(exc_val);
1577 return NULL;
1579 return res;
1581 #endif
1582 /* Tcl is not threaded, or this is the interpreter thread. */
1583 return func(selfptr, args, flags);
1586 static PyObject *
1587 SetVar(PyObject *self, PyObject *args, int flags)
1589 char *name1, *name2;
1590 PyObject *newValue;
1591 PyObject *res = NULL;
1592 Tcl_Obj *newval, *ok;
1594 if (PyArg_ParseTuple(args, "O&O:setvar",
1595 varname_converter, &name1, &newValue)) {
1596 /* XXX Acquire tcl lock??? */
1597 newval = AsObj(newValue);
1598 if (newval == NULL)
1599 return NULL;
1600 ENTER_TCL
1601 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1602 newval, flags);
1603 ENTER_OVERLAP
1604 if (!ok)
1605 Tkinter_Error(self);
1606 else {
1607 res = Py_None;
1608 Py_INCREF(res);
1610 LEAVE_OVERLAP_TCL
1612 else {
1613 PyErr_Clear();
1614 if (PyArg_ParseTuple(args, "ssO:setvar",
1615 &name1, &name2, &newValue)) {
1616 /* XXX must hold tcl lock already??? */
1617 newval = AsObj(newValue);
1618 ENTER_TCL
1619 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1620 ENTER_OVERLAP
1621 if (!ok)
1622 Tkinter_Error(self);
1623 else {
1624 res = Py_None;
1625 Py_INCREF(res);
1627 LEAVE_OVERLAP_TCL
1629 else {
1630 return NULL;
1633 return res;
1636 static PyObject *
1637 Tkapp_SetVar(PyObject *self, PyObject *args)
1639 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1642 static PyObject *
1643 Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
1645 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1650 static PyObject *
1651 GetVar(PyObject *self, PyObject *args, int flags)
1653 char *name1, *name2=NULL;
1654 PyObject *res = NULL;
1655 Tcl_Obj *tres;
1657 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1658 varname_converter, &name1, &name2))
1659 return NULL;
1661 ENTER_TCL
1662 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1663 ENTER_OVERLAP
1664 if (tres == NULL) {
1665 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1666 } else {
1667 if (((TkappObject*)self)->wantobjects) {
1668 res = FromObj(self, tres);
1670 else {
1671 res = PyString_FromString(Tcl_GetString(tres));
1674 LEAVE_OVERLAP_TCL
1675 return res;
1678 static PyObject *
1679 Tkapp_GetVar(PyObject *self, PyObject *args)
1681 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1684 static PyObject *
1685 Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1687 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1692 static PyObject *
1693 UnsetVar(PyObject *self, PyObject *args, int flags)
1695 char *name1, *name2=NULL;
1696 int code;
1697 PyObject *res = NULL;
1699 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1700 return NULL;
1702 ENTER_TCL
1703 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1704 ENTER_OVERLAP
1705 if (code == TCL_ERROR)
1706 res = Tkinter_Error(self);
1707 else {
1708 Py_INCREF(Py_None);
1709 res = Py_None;
1711 LEAVE_OVERLAP_TCL
1712 return res;
1715 static PyObject *
1716 Tkapp_UnsetVar(PyObject *self, PyObject *args)
1718 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1721 static PyObject *
1722 Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1724 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1729 /** Tcl to Python **/
1731 static PyObject *
1732 Tkapp_GetInt(PyObject *self, PyObject *args)
1734 char *s;
1735 int v;
1737 if (PyTuple_Size(args) == 1) {
1738 PyObject* o = PyTuple_GetItem(args, 0);
1739 if (PyInt_Check(o)) {
1740 Py_INCREF(o);
1741 return o;
1744 if (!PyArg_ParseTuple(args, "s:getint", &s))
1745 return NULL;
1746 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1747 return Tkinter_Error(self);
1748 return Py_BuildValue("i", v);
1751 static PyObject *
1752 Tkapp_GetDouble(PyObject *self, PyObject *args)
1754 char *s;
1755 double v;
1757 if (PyTuple_Size(args) == 1) {
1758 PyObject *o = PyTuple_GetItem(args, 0);
1759 if (PyFloat_Check(o)) {
1760 Py_INCREF(o);
1761 return o;
1764 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1765 return NULL;
1766 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1767 return Tkinter_Error(self);
1768 return Py_BuildValue("d", v);
1771 static PyObject *
1772 Tkapp_GetBoolean(PyObject *self, PyObject *args)
1774 char *s;
1775 int v;
1777 if (PyTuple_Size(args) == 1) {
1778 PyObject *o = PyTuple_GetItem(args, 0);
1779 if (PyInt_Check(o)) {
1780 Py_INCREF(o);
1781 return o;
1784 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1785 return NULL;
1786 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1787 return Tkinter_Error(self);
1788 return PyBool_FromLong(v);
1791 static PyObject *
1792 Tkapp_ExprString(PyObject *self, PyObject *args)
1794 char *s;
1795 PyObject *res = NULL;
1796 int retval;
1798 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1799 return NULL;
1801 CHECK_TCL_APPARTMENT;
1803 ENTER_TCL
1804 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1805 ENTER_OVERLAP
1806 if (retval == TCL_ERROR)
1807 res = Tkinter_Error(self);
1808 else
1809 res = Py_BuildValue("s", Tkapp_Result(self));
1810 LEAVE_OVERLAP_TCL
1811 return res;
1814 static PyObject *
1815 Tkapp_ExprLong(PyObject *self, PyObject *args)
1817 char *s;
1818 PyObject *res = NULL;
1819 int retval;
1820 long v;
1822 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1823 return NULL;
1825 CHECK_TCL_APPARTMENT;
1827 ENTER_TCL
1828 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1829 ENTER_OVERLAP
1830 if (retval == TCL_ERROR)
1831 res = Tkinter_Error(self);
1832 else
1833 res = Py_BuildValue("l", v);
1834 LEAVE_OVERLAP_TCL
1835 return res;
1838 static PyObject *
1839 Tkapp_ExprDouble(PyObject *self, PyObject *args)
1841 char *s;
1842 PyObject *res = NULL;
1843 double v;
1844 int retval;
1846 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1847 return NULL;
1848 CHECK_TCL_APPARTMENT;
1849 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1850 ENTER_TCL
1851 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1852 ENTER_OVERLAP
1853 PyFPE_END_PROTECT(retval)
1854 if (retval == TCL_ERROR)
1855 res = Tkinter_Error(self);
1856 else
1857 res = Py_BuildValue("d", v);
1858 LEAVE_OVERLAP_TCL
1859 return res;
1862 static PyObject *
1863 Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1865 char *s;
1866 PyObject *res = NULL;
1867 int retval;
1868 int v;
1870 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1871 return NULL;
1872 CHECK_TCL_APPARTMENT;
1873 ENTER_TCL
1874 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1875 ENTER_OVERLAP
1876 if (retval == TCL_ERROR)
1877 res = Tkinter_Error(self);
1878 else
1879 res = Py_BuildValue("i", v);
1880 LEAVE_OVERLAP_TCL
1881 return res;
1886 static PyObject *
1887 Tkapp_SplitList(PyObject *self, PyObject *args)
1889 char *list;
1890 int argc;
1891 char **argv;
1892 PyObject *v;
1893 int i;
1895 if (PyTuple_Size(args) == 1) {
1896 v = PyTuple_GetItem(args, 0);
1897 if (PyTuple_Check(v)) {
1898 Py_INCREF(v);
1899 return v;
1902 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1903 return NULL;
1905 if (Tcl_SplitList(Tkapp_Interp(self), list,
1906 &argc, &argv) == TCL_ERROR) {
1907 PyMem_Free(list);
1908 return Tkinter_Error(self);
1911 if (!(v = PyTuple_New(argc)))
1912 goto finally;
1914 for (i = 0; i < argc; i++) {
1915 PyObject *s = PyString_FromString(argv[i]);
1916 if (!s || PyTuple_SetItem(v, i, s)) {
1917 Py_DECREF(v);
1918 v = NULL;
1919 goto finally;
1923 finally:
1924 ckfree(FREECAST argv);
1925 PyMem_Free(list);
1926 return v;
1929 static PyObject *
1930 Tkapp_Split(PyObject *self, PyObject *args)
1932 PyObject *v;
1933 char *list;
1935 if (PyTuple_Size(args) == 1) {
1936 PyObject* o = PyTuple_GetItem(args, 0);
1937 if (PyTuple_Check(o)) {
1938 o = SplitObj(o);
1939 return o;
1942 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1943 return NULL;
1944 v = Split(list);
1945 PyMem_Free(list);
1946 return v;
1949 static PyObject *
1950 Tkapp_Merge(PyObject *self, PyObject *args)
1952 char *s = Merge(args);
1953 PyObject *res = NULL;
1955 if (s) {
1956 res = PyString_FromString(s);
1957 ckfree(s);
1960 return res;
1965 /** Tcl Command **/
1967 /* Client data struct */
1968 typedef struct {
1969 PyObject *self;
1970 PyObject *func;
1971 } PythonCmd_ClientData;
1973 static int
1974 PythonCmd_Error(Tcl_Interp *interp)
1976 errorInCmd = 1;
1977 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1978 LEAVE_PYTHON
1979 return TCL_ERROR;
1982 /* This is the Tcl command that acts as a wrapper for Python
1983 * function or method.
1985 static int
1986 PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1988 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1989 PyObject *self, *func, *arg, *res, *tmp;
1990 int i, rv;
1991 char *s;
1993 ENTER_PYTHON
1995 /* TBD: no error checking here since we know, via the
1996 * Tkapp_CreateCommand() that the client data is a two-tuple
1998 self = data->self;
1999 func = data->func;
2001 /* Create argument list (argv1, ..., argvN) */
2002 if (!(arg = PyTuple_New(argc - 1)))
2003 return PythonCmd_Error(interp);
2005 for (i = 0; i < (argc - 1); i++) {
2006 PyObject *s = PyString_FromString(argv[i + 1]);
2007 if (!s || PyTuple_SetItem(arg, i, s)) {
2008 Py_DECREF(arg);
2009 return PythonCmd_Error(interp);
2012 res = PyEval_CallObject(func, arg);
2013 Py_DECREF(arg);
2015 if (res == NULL)
2016 return PythonCmd_Error(interp);
2018 if (!(tmp = PyList_New(0))) {
2019 Py_DECREF(res);
2020 return PythonCmd_Error(interp);
2023 s = AsString(res, tmp);
2024 if (s == NULL) {
2025 rv = PythonCmd_Error(interp);
2027 else {
2028 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
2029 rv = TCL_OK;
2032 Py_DECREF(res);
2033 Py_DECREF(tmp);
2035 LEAVE_PYTHON
2037 return rv;
2040 static void
2041 PythonCmdDelete(ClientData clientData)
2043 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2045 ENTER_PYTHON
2046 Py_XDECREF(data->self);
2047 Py_XDECREF(data->func);
2048 PyMem_DEL(data);
2049 LEAVE_PYTHON
2055 TCL_DECLARE_MUTEX(command_mutex)
2057 typedef struct CommandEvent{
2058 Tcl_Event ev;
2059 Tcl_Interp* interp;
2060 char *name;
2061 int create;
2062 int *status;
2063 ClientData *data;
2064 Tcl_Condition done;
2065 } CommandEvent;
2067 static int
2068 Tkapp_CommandProc(CommandEvent *ev, int flags)
2070 if (ev->create)
2071 *ev->status = Tcl_CreateCommand(
2072 ev->interp, ev->name, PythonCmd,
2073 ev->data, PythonCmdDelete) == NULL;
2074 else
2075 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2076 Tcl_MutexLock(&command_mutex);
2077 Tcl_ConditionNotify(&ev->done);
2078 Tcl_MutexUnlock(&command_mutex);
2079 return 1;
2082 static PyObject *
2083 Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2085 TkappObject *self = (TkappObject*)selfptr;
2086 PythonCmd_ClientData *data;
2087 char *cmdName;
2088 PyObject *func;
2089 int err;
2091 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2092 return NULL;
2093 if (!PyCallable_Check(func)) {
2094 PyErr_SetString(PyExc_TypeError, "command not callable");
2095 return NULL;
2098 #ifdef WITH_THREAD
2099 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2100 !WaitForMainloop(self))
2101 return NULL;
2102 #endif
2104 data = PyMem_NEW(PythonCmd_ClientData, 1);
2105 if (!data)
2106 return PyErr_NoMemory();
2107 Py_INCREF(self);
2108 Py_INCREF(func);
2109 data->self = selfptr;
2110 data->func = func;
2112 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2113 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2114 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2115 ev->interp = self->interp;
2116 ev->create = 1;
2117 ev->name = cmdName;
2118 ev->data = (ClientData)data;
2119 ev->status = &err;
2120 ev->done = NULL;
2121 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2123 else {
2124 ENTER_TCL
2125 err = Tcl_CreateCommand(
2126 Tkapp_Interp(self), cmdName, PythonCmd,
2127 (ClientData)data, PythonCmdDelete) == NULL;
2128 LEAVE_TCL
2130 if (err) {
2131 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2132 PyMem_DEL(data);
2133 return NULL;
2136 Py_INCREF(Py_None);
2137 return Py_None;
2142 static PyObject *
2143 Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2145 TkappObject *self = (TkappObject*)selfptr;
2146 char *cmdName;
2147 int err;
2149 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2150 return NULL;
2151 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2152 CommandEvent *ev;
2153 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2154 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2155 ev->interp = self->interp;
2156 ev->create = 0;
2157 ev->name = cmdName;
2158 ev->status = &err;
2159 ev->done = NULL;
2160 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2161 &command_mutex);
2163 else {
2164 ENTER_TCL
2165 err = Tcl_DeleteCommand(self->interp, cmdName);
2166 LEAVE_TCL
2168 if (err == -1) {
2169 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2170 return NULL;
2172 Py_INCREF(Py_None);
2173 return Py_None;
2178 #ifdef HAVE_CREATEFILEHANDLER
2179 /** File Handler **/
2181 typedef struct _fhcdata {
2182 PyObject *func;
2183 PyObject *file;
2184 int id;
2185 struct _fhcdata *next;
2186 } FileHandler_ClientData;
2188 static FileHandler_ClientData *HeadFHCD;
2190 static FileHandler_ClientData *
2191 NewFHCD(PyObject *func, PyObject *file, int id)
2193 FileHandler_ClientData *p;
2194 p = PyMem_NEW(FileHandler_ClientData, 1);
2195 if (p != NULL) {
2196 Py_XINCREF(func);
2197 Py_XINCREF(file);
2198 p->func = func;
2199 p->file = file;
2200 p->id = id;
2201 p->next = HeadFHCD;
2202 HeadFHCD = p;
2204 return p;
2207 static void
2208 DeleteFHCD(int id)
2210 FileHandler_ClientData *p, **pp;
2212 pp = &HeadFHCD;
2213 while ((p = *pp) != NULL) {
2214 if (p->id == id) {
2215 *pp = p->next;
2216 Py_XDECREF(p->func);
2217 Py_XDECREF(p->file);
2218 PyMem_DEL(p);
2220 else
2221 pp = &p->next;
2225 static void
2226 FileHandler(ClientData clientData, int mask)
2228 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2229 PyObject *func, *file, *arg, *res;
2231 ENTER_PYTHON
2232 func = data->func;
2233 file = data->file;
2235 arg = Py_BuildValue("(Oi)", file, (long) mask);
2236 res = PyEval_CallObject(func, arg);
2237 Py_DECREF(arg);
2239 if (res == NULL) {
2240 errorInCmd = 1;
2241 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2243 Py_XDECREF(res);
2244 LEAVE_PYTHON
2247 static PyObject *
2248 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2249 /* args is (file, mask, func) */
2251 FileHandler_ClientData *data;
2252 PyObject *file, *func;
2253 int mask, tfile;
2255 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2256 &file, &mask, &func))
2257 return NULL;
2259 #ifdef WITH_THREAD
2260 if (!self && !tcl_lock) {
2261 /* We don't have the Tcl lock since Tcl is threaded. */
2262 PyErr_SetString(PyExc_RuntimeError,
2263 "_tkinter.createfilehandler not supported "
2264 "for threaded Tcl");
2265 return NULL;
2267 #endif
2269 if (self) {
2270 CHECK_TCL_APPARTMENT;
2273 tfile = PyObject_AsFileDescriptor(file);
2274 if (tfile < 0)
2275 return NULL;
2276 if (!PyCallable_Check(func)) {
2277 PyErr_SetString(PyExc_TypeError, "bad argument list");
2278 return NULL;
2281 data = NewFHCD(func, file, tfile);
2282 if (data == NULL)
2283 return NULL;
2285 /* Ought to check for null Tcl_File object... */
2286 ENTER_TCL
2287 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2288 LEAVE_TCL
2289 Py_INCREF(Py_None);
2290 return Py_None;
2293 static PyObject *
2294 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2296 PyObject *file;
2297 int tfile;
2299 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2300 return NULL;
2302 #ifdef WITH_THREAD
2303 if (!self && !tcl_lock) {
2304 /* We don't have the Tcl lock since Tcl is threaded. */
2305 PyErr_SetString(PyExc_RuntimeError,
2306 "_tkinter.deletefilehandler not supported "
2307 "for threaded Tcl");
2308 return NULL;
2310 #endif
2312 if (self) {
2313 CHECK_TCL_APPARTMENT;
2316 tfile = PyObject_AsFileDescriptor(file);
2317 if (tfile < 0)
2318 return NULL;
2320 DeleteFHCD(tfile);
2322 /* Ought to check for null Tcl_File object... */
2323 ENTER_TCL
2324 Tcl_DeleteFileHandler(tfile);
2325 LEAVE_TCL
2326 Py_INCREF(Py_None);
2327 return Py_None;
2329 #endif /* HAVE_CREATEFILEHANDLER */
2332 /**** Tktt Object (timer token) ****/
2334 static PyTypeObject Tktt_Type;
2336 typedef struct {
2337 PyObject_HEAD
2338 Tcl_TimerToken token;
2339 PyObject *func;
2340 } TkttObject;
2342 static PyObject *
2343 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2345 TkttObject *v = (TkttObject *)self;
2346 PyObject *func = v->func;
2348 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2349 return NULL;
2350 if (v->token != NULL) {
2351 Tcl_DeleteTimerHandler(v->token);
2352 v->token = NULL;
2354 if (func != NULL) {
2355 v->func = NULL;
2356 Py_DECREF(func);
2357 Py_DECREF(v); /* See Tktt_New() */
2359 Py_INCREF(Py_None);
2360 return Py_None;
2363 static PyMethodDef Tktt_methods[] =
2365 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2366 {NULL, NULL}
2369 static TkttObject *
2370 Tktt_New(PyObject *func)
2372 TkttObject *v;
2374 v = PyObject_New(TkttObject, &Tktt_Type);
2375 if (v == NULL)
2376 return NULL;
2378 Py_INCREF(func);
2379 v->token = NULL;
2380 v->func = func;
2382 /* Extra reference, deleted when called or when handler is deleted */
2383 Py_INCREF(v);
2384 return v;
2387 static void
2388 Tktt_Dealloc(PyObject *self)
2390 TkttObject *v = (TkttObject *)self;
2391 PyObject *func = v->func;
2393 Py_XDECREF(func);
2395 PyObject_Del(self);
2398 static PyObject *
2399 Tktt_Repr(PyObject *self)
2401 TkttObject *v = (TkttObject *)self;
2402 char buf[100];
2404 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2405 v->func == NULL ? ", handler deleted" : "");
2406 return PyString_FromString(buf);
2409 static PyObject *
2410 Tktt_GetAttr(PyObject *self, char *name)
2412 return Py_FindMethod(Tktt_methods, self, name);
2415 static PyTypeObject Tktt_Type =
2417 PyObject_HEAD_INIT(NULL)
2418 0, /*ob_size */
2419 "tktimertoken", /*tp_name */
2420 sizeof(TkttObject), /*tp_basicsize */
2421 0, /*tp_itemsize */
2422 Tktt_Dealloc, /*tp_dealloc */
2423 0, /*tp_print */
2424 Tktt_GetAttr, /*tp_getattr */
2425 0, /*tp_setattr */
2426 0, /*tp_compare */
2427 Tktt_Repr, /*tp_repr */
2428 0, /*tp_as_number */
2429 0, /*tp_as_sequence */
2430 0, /*tp_as_mapping */
2431 0, /*tp_hash */
2436 /** Timer Handler **/
2438 static void
2439 TimerHandler(ClientData clientData)
2441 TkttObject *v = (TkttObject *)clientData;
2442 PyObject *func = v->func;
2443 PyObject *res;
2445 if (func == NULL)
2446 return;
2448 v->func = NULL;
2450 ENTER_PYTHON
2452 res = PyEval_CallObject(func, NULL);
2453 Py_DECREF(func);
2454 Py_DECREF(v); /* See Tktt_New() */
2456 if (res == NULL) {
2457 errorInCmd = 1;
2458 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2460 else
2461 Py_DECREF(res);
2463 LEAVE_PYTHON
2466 static PyObject *
2467 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2469 int milliseconds;
2470 PyObject *func;
2471 TkttObject *v;
2473 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2474 &milliseconds, &func))
2475 return NULL;
2476 if (!PyCallable_Check(func)) {
2477 PyErr_SetString(PyExc_TypeError, "bad argument list");
2478 return NULL;
2481 #ifdef WITH_THREAD
2482 if (!self && !tcl_lock) {
2483 /* We don't have the Tcl lock since Tcl is threaded. */
2484 PyErr_SetString(PyExc_RuntimeError,
2485 "_tkinter.createtimerhandler not supported "
2486 "for threaded Tcl");
2487 return NULL;
2489 #endif
2491 if (self) {
2492 CHECK_TCL_APPARTMENT;
2495 v = Tktt_New(func);
2496 if (v) {
2497 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2498 (ClientData)v);
2501 return (PyObject *) v;
2505 /** Event Loop **/
2507 static PyObject *
2508 Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
2510 int threshold = 0;
2511 TkappObject *self = (TkappObject*)selfptr;
2512 #ifdef WITH_THREAD
2513 PyThreadState *tstate = PyThreadState_Get();
2514 #endif
2516 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2517 return NULL;
2519 #ifdef WITH_THREAD
2520 if (!self && !tcl_lock) {
2521 /* We don't have the Tcl lock since Tcl is threaded. */
2522 PyErr_SetString(PyExc_RuntimeError,
2523 "_tkinter.mainloop not supported "
2524 "for threaded Tcl");
2525 return NULL;
2527 #endif
2529 if (self) {
2530 CHECK_TCL_APPARTMENT;
2531 self->dispatching = 1;
2534 quitMainLoop = 0;
2535 while (Tk_GetNumMainWindows() > threshold &&
2536 !quitMainLoop &&
2537 !errorInCmd)
2539 int result;
2541 #ifdef WITH_THREAD
2542 if (self && self->threaded) {
2543 /* Allow other Python threads to run. */
2544 ENTER_TCL
2545 result = Tcl_DoOneEvent(0);
2546 LEAVE_TCL
2548 else {
2549 Py_BEGIN_ALLOW_THREADS
2550 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2551 tcl_tstate = tstate;
2552 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2553 tcl_tstate = NULL;
2554 if(tcl_lock)PyThread_release_lock(tcl_lock);
2555 if (result == 0)
2556 Sleep(Tkinter_busywaitinterval);
2557 Py_END_ALLOW_THREADS
2559 #else
2560 result = Tcl_DoOneEvent(0);
2561 #endif
2563 if (PyErr_CheckSignals() != 0) {
2564 if (self)
2565 self->dispatching = 0;
2566 return NULL;
2568 if (result < 0)
2569 break;
2571 if (self)
2572 self->dispatching = 0;
2573 quitMainLoop = 0;
2575 if (errorInCmd) {
2576 errorInCmd = 0;
2577 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2578 excInCmd = valInCmd = trbInCmd = NULL;
2579 return NULL;
2581 Py_INCREF(Py_None);
2582 return Py_None;
2585 static PyObject *
2586 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
2588 int flags = 0;
2589 int rv;
2591 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2592 return NULL;
2594 ENTER_TCL
2595 rv = Tcl_DoOneEvent(flags);
2596 LEAVE_TCL
2597 return Py_BuildValue("i", rv);
2600 static PyObject *
2601 Tkapp_Quit(PyObject *self, PyObject *args)
2604 if (!PyArg_ParseTuple(args, ":quit"))
2605 return NULL;
2607 quitMainLoop = 1;
2608 Py_INCREF(Py_None);
2609 return Py_None;
2612 static PyObject *
2613 Tkapp_InterpAddr(PyObject *self, PyObject *args)
2616 if (!PyArg_ParseTuple(args, ":interpaddr"))
2617 return NULL;
2619 return PyInt_FromLong((long)Tkapp_Interp(self));
2622 static PyObject *
2623 Tkapp_TkInit(PyObject *self, PyObject *args)
2625 static int has_failed;
2626 Tcl_Interp *interp = Tkapp_Interp(self);
2627 Tk_Window main_window;
2628 const char * _tk_exists = NULL;
2629 int err;
2630 main_window = Tk_MainWindow(interp);
2632 /* In all current versions of Tk (including 8.4.13), Tk_Init
2633 deadlocks on the second call when the first call failed.
2634 To avoid the deadlock, we just refuse the second call through
2635 a static variable. */
2636 if (has_failed) {
2637 PyErr_SetString(Tkinter_TclError,
2638 "Calling Tk_Init again after a previous call failed might deadlock");
2639 return NULL;
2642 /* We want to guard against calling Tk_Init() multiple times */
2643 CHECK_TCL_APPARTMENT;
2644 ENTER_TCL
2645 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2646 ENTER_OVERLAP
2647 if (err == TCL_ERROR) {
2648 /* This sets an exception, but we cannot return right
2649 away because we need to exit the overlap first. */
2650 Tkinter_Error(self);
2651 } else {
2652 _tk_exists = Tkapp_Result(self);
2654 LEAVE_OVERLAP_TCL
2655 if (err == TCL_ERROR) {
2656 return NULL;
2658 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2659 if (Tk_Init(interp) == TCL_ERROR) {
2660 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2661 has_failed = 1;
2662 return NULL;
2665 Py_INCREF(Py_None);
2666 return Py_None;
2669 static PyObject *
2670 Tkapp_WantObjects(PyObject *self, PyObject *args)
2673 int wantobjects = -1;
2674 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2675 return NULL;
2676 if (wantobjects == -1)
2677 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2678 ((TkappObject*)self)->wantobjects = wantobjects;
2680 Py_INCREF(Py_None);
2681 return Py_None;
2684 static PyObject *
2685 Tkapp_WillDispatch(PyObject *self, PyObject *args)
2688 ((TkappObject*)self)->dispatching = 1;
2690 Py_INCREF(Py_None);
2691 return Py_None;
2695 /**** Tkapp Method List ****/
2697 static PyMethodDef Tkapp_methods[] =
2699 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2700 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2701 {"call", Tkapp_Call, METH_OLDARGS},
2702 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2703 {"eval", Tkapp_Eval, METH_VARARGS},
2704 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2705 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2706 {"record", Tkapp_Record, METH_VARARGS},
2707 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2708 {"setvar", Tkapp_SetVar, METH_VARARGS},
2709 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2710 {"getvar", Tkapp_GetVar, METH_VARARGS},
2711 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2712 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2713 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2714 {"getint", Tkapp_GetInt, METH_VARARGS},
2715 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2716 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2717 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2718 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2719 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2720 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2721 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2722 {"split", Tkapp_Split, METH_VARARGS},
2723 {"merge", Tkapp_Merge, METH_OLDARGS},
2724 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2725 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2726 #ifdef HAVE_CREATEFILEHANDLER
2727 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2728 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2729 #endif
2730 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2731 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2732 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2733 {"quit", Tkapp_Quit, METH_VARARGS},
2734 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2735 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2736 {NULL, NULL}
2741 /**** Tkapp Type Methods ****/
2743 static void
2744 Tkapp_Dealloc(PyObject *self)
2746 /*CHECK_TCL_APPARTMENT;*/
2747 ENTER_TCL
2748 Tcl_DeleteInterp(Tkapp_Interp(self));
2749 LEAVE_TCL
2750 PyObject_Del(self);
2751 DisableEventHook();
2754 static PyObject *
2755 Tkapp_GetAttr(PyObject *self, char *name)
2757 return Py_FindMethod(Tkapp_methods, self, name);
2760 static PyTypeObject Tkapp_Type =
2762 PyObject_HEAD_INIT(NULL)
2763 0, /*ob_size */
2764 "tkapp", /*tp_name */
2765 sizeof(TkappObject), /*tp_basicsize */
2766 0, /*tp_itemsize */
2767 Tkapp_Dealloc, /*tp_dealloc */
2768 0, /*tp_print */
2769 Tkapp_GetAttr, /*tp_getattr */
2770 0, /*tp_setattr */
2771 0, /*tp_compare */
2772 0, /*tp_repr */
2773 0, /*tp_as_number */
2774 0, /*tp_as_sequence */
2775 0, /*tp_as_mapping */
2776 0, /*tp_hash */
2781 /**** Tkinter Module ****/
2783 typedef struct {
2784 PyObject* tuple;
2785 int size; /* current size */
2786 int maxsize; /* allocated size */
2787 } FlattenContext;
2789 static int
2790 _bump(FlattenContext* context, int size)
2792 /* expand tuple to hold (at least) size new items.
2793 return true if successful, false if an exception was raised */
2795 int maxsize = context->maxsize * 2;
2797 if (maxsize < context->size + size)
2798 maxsize = context->size + size;
2800 context->maxsize = maxsize;
2802 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2805 static int
2806 _flatten1(FlattenContext* context, PyObject* item, int depth)
2808 /* add tuple or list to argument tuple (recursively) */
2810 int i, size;
2812 if (depth > 1000) {
2813 PyErr_SetString(PyExc_ValueError,
2814 "nesting too deep in _flatten");
2815 return 0;
2816 } else if (PyList_Check(item)) {
2817 size = PyList_GET_SIZE(item);
2818 /* preallocate (assume no nesting) */
2819 if (context->size + size > context->maxsize &&
2820 !_bump(context, size))
2821 return 0;
2822 /* copy items to output tuple */
2823 for (i = 0; i < size; i++) {
2824 PyObject *o = PyList_GET_ITEM(item, i);
2825 if (PyList_Check(o) || PyTuple_Check(o)) {
2826 if (!_flatten1(context, o, depth + 1))
2827 return 0;
2828 } else if (o != Py_None) {
2829 if (context->size + 1 > context->maxsize &&
2830 !_bump(context, 1))
2831 return 0;
2832 Py_INCREF(o);
2833 PyTuple_SET_ITEM(context->tuple,
2834 context->size++, o);
2837 } else if (PyTuple_Check(item)) {
2838 /* same, for tuples */
2839 size = PyTuple_GET_SIZE(item);
2840 if (context->size + size > context->maxsize &&
2841 !_bump(context, size))
2842 return 0;
2843 for (i = 0; i < size; i++) {
2844 PyObject *o = PyTuple_GET_ITEM(item, i);
2845 if (PyList_Check(o) || PyTuple_Check(o)) {
2846 if (!_flatten1(context, o, depth + 1))
2847 return 0;
2848 } else if (o != Py_None) {
2849 if (context->size + 1 > context->maxsize &&
2850 !_bump(context, 1))
2851 return 0;
2852 Py_INCREF(o);
2853 PyTuple_SET_ITEM(context->tuple,
2854 context->size++, o);
2857 } else {
2858 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2859 return 0;
2861 return 1;
2864 static PyObject *
2865 Tkinter_Flatten(PyObject* self, PyObject* args)
2867 FlattenContext context;
2868 PyObject* item;
2870 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2871 return NULL;
2873 context.maxsize = PySequence_Size(item);
2874 if (context.maxsize <= 0)
2875 return PyTuple_New(0);
2877 context.tuple = PyTuple_New(context.maxsize);
2878 if (!context.tuple)
2879 return NULL;
2881 context.size = 0;
2883 if (!_flatten1(&context, item,0))
2884 return NULL;
2886 if (_PyTuple_Resize(&context.tuple, context.size))
2887 return NULL;
2889 return context.tuple;
2892 static PyObject *
2893 Tkinter_Create(PyObject *self, PyObject *args)
2895 char *screenName = NULL;
2896 char *baseName = NULL;
2897 char *className = NULL;
2898 int interactive = 0;
2899 int wantobjects = 0;
2900 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2901 int sync = 0; /* pass -sync to wish */
2902 char *use = NULL; /* pass -use to wish */
2904 baseName = strrchr(Py_GetProgramName(), '/');
2905 if (baseName != NULL)
2906 baseName++;
2907 else
2908 baseName = Py_GetProgramName();
2909 className = "Tk";
2911 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2912 &screenName, &baseName, &className,
2913 &interactive, &wantobjects, &wantTk,
2914 &sync, &use))
2915 return NULL;
2917 return (PyObject *) Tkapp_New(screenName, baseName, className,
2918 interactive, wantobjects, wantTk,
2919 sync, use);
2922 static PyObject *
2923 Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2925 int new_val;
2926 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2927 return NULL;
2928 if (new_val < 0) {
2929 PyErr_SetString(PyExc_ValueError,
2930 "busywaitinterval must be >= 0");
2931 return NULL;
2933 Tkinter_busywaitinterval = new_val;
2934 Py_INCREF(Py_None);
2935 return Py_None;
2938 static char setbusywaitinterval_doc[] =
2939 "setbusywaitinterval(n) -> None\n\
2941 Set the busy-wait interval in milliseconds between successive\n\
2942 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2943 It should be set to a divisor of the maximum time between\n\
2944 frames in an animation.";
2946 static PyObject *
2947 Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2949 return PyInt_FromLong(Tkinter_busywaitinterval);
2952 static char getbusywaitinterval_doc[] =
2953 "getbusywaitinterval() -> int\n\
2955 Return the current busy-wait interval between successive\n\
2956 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2958 static PyMethodDef moduleMethods[] =
2960 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2961 {"create", Tkinter_Create, METH_VARARGS},
2962 #ifdef HAVE_CREATEFILEHANDLER
2963 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2964 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2965 #endif
2966 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2967 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2968 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2969 {"quit", Tkapp_Quit, METH_VARARGS},
2970 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2971 setbusywaitinterval_doc},
2972 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2973 METH_NOARGS, getbusywaitinterval_doc},
2974 {NULL, NULL}
2977 #ifdef WAIT_FOR_STDIN
2979 static int stdin_ready = 0;
2981 #ifndef MS_WINDOWS
2982 static void
2983 MyFileProc(void *clientData, int mask)
2985 stdin_ready = 1;
2987 #endif
2989 #ifdef WITH_THREAD
2990 static PyThreadState *event_tstate = NULL;
2991 #endif
2993 static int
2994 EventHook(void)
2996 #ifndef MS_WINDOWS
2997 int tfile;
2998 #endif
2999 #ifdef WITH_THREAD
3000 PyEval_RestoreThread(event_tstate);
3001 #endif
3002 stdin_ready = 0;
3003 errorInCmd = 0;
3004 #ifndef MS_WINDOWS
3005 tfile = fileno(stdin);
3006 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
3007 #endif
3008 while (!errorInCmd && !stdin_ready) {
3009 int result;
3010 #ifdef MS_WINDOWS
3011 if (_kbhit()) {
3012 stdin_ready = 1;
3013 break;
3015 #endif
3016 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3017 Py_BEGIN_ALLOW_THREADS
3018 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3019 tcl_tstate = event_tstate;
3021 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3023 tcl_tstate = NULL;
3024 if(tcl_lock)PyThread_release_lock(tcl_lock);
3025 if (result == 0)
3026 Sleep(Tkinter_busywaitinterval);
3027 Py_END_ALLOW_THREADS
3028 #else
3029 result = Tcl_DoOneEvent(0);
3030 #endif
3032 if (result < 0)
3033 break;
3035 #ifndef MS_WINDOWS
3036 Tcl_DeleteFileHandler(tfile);
3037 #endif
3038 if (errorInCmd) {
3039 errorInCmd = 0;
3040 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3041 excInCmd = valInCmd = trbInCmd = NULL;
3042 PyErr_Print();
3044 #ifdef WITH_THREAD
3045 PyEval_SaveThread();
3046 #endif
3047 return 0;
3050 #endif
3052 static void
3053 EnableEventHook(void)
3055 #ifdef WAIT_FOR_STDIN
3056 if (PyOS_InputHook == NULL) {
3057 #ifdef WITH_THREAD
3058 event_tstate = PyThreadState_Get();
3059 #endif
3060 PyOS_InputHook = EventHook;
3062 #endif
3065 static void
3066 DisableEventHook(void)
3068 #ifdef WAIT_FOR_STDIN
3069 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3070 PyOS_InputHook = NULL;
3072 #endif
3076 /* all errors will be checked in one fell swoop in init_tkinter() */
3077 static void
3078 ins_long(PyObject *d, char *name, long val)
3080 PyObject *v = PyInt_FromLong(val);
3081 if (v) {
3082 PyDict_SetItemString(d, name, v);
3083 Py_DECREF(v);
3086 static void
3087 ins_string(PyObject *d, char *name, char *val)
3089 PyObject *v = PyString_FromString(val);
3090 if (v) {
3091 PyDict_SetItemString(d, name, v);
3092 Py_DECREF(v);
3097 PyMODINIT_FUNC
3098 init_tkinter(void)
3100 PyObject *m, *d;
3102 Tkapp_Type.ob_type = &PyType_Type;
3104 #ifdef WITH_THREAD
3105 tcl_lock = PyThread_allocate_lock();
3106 #endif
3108 m = Py_InitModule("_tkinter", moduleMethods);
3109 if (m == NULL)
3110 return;
3112 d = PyModule_GetDict(m);
3113 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3114 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3116 ins_long(d, "READABLE", TCL_READABLE);
3117 ins_long(d, "WRITABLE", TCL_WRITABLE);
3118 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3119 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3120 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3121 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3122 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3123 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3124 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3125 ins_string(d, "TK_VERSION", TK_VERSION);
3126 ins_string(d, "TCL_VERSION", TCL_VERSION);
3128 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3130 Tktt_Type.ob_type = &PyType_Type;
3131 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3133 PyTclObject_Type.ob_type = &PyType_Type;
3134 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3136 #ifdef TK_AQUA
3137 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3138 * start waking up. Note that Tcl_FindExecutable will do this, this
3139 * code must be above it! The original warning from
3140 * tkMacOSXAppInit.c is copied below.
3142 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3143 * Tcl interpreter for now. It probably should work to do this
3144 * in the other order, but for now it doesn't seem to.
3147 Tk_MacOSXSetupTkNotifier();
3148 #endif
3151 /* This helps the dynamic loader; in Unicode aware Tcl versions
3152 it also helps Tcl find its encodings. */
3153 Tcl_FindExecutable(Py_GetProgramName());
3155 if (PyErr_Occurred())
3156 return;
3158 #if 0
3159 /* This was not a good idea; through <Destroy> bindings,
3160 Tcl_Finalize() may invoke Python code but at that point the
3161 interpreter and thread state have already been destroyed! */
3162 Py_AtExit(Tcl_Finalize);
3163 #endif