Added information on function name added to LogRecord, and the 'extra' keyword parameter.
[python.git] / Modules / _tkinter.c
blob70cd670b126f9266d5dba20e157e41187f102b9c
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(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 return (TkappObject *)Tkinter_Error((PyObject *)v);
692 EnableEventHook();
694 return v;
698 static void
699 Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
700 Tcl_Condition *cond, Tcl_Mutex *mutex)
702 Py_BEGIN_ALLOW_THREADS;
703 Tcl_MutexLock(mutex);
704 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
705 Tcl_ThreadAlert(self->thread_id);
706 Tcl_ConditionWait(cond, mutex, NULL);
707 Tcl_MutexUnlock(mutex);
708 Py_END_ALLOW_THREADS
712 /** Tcl Eval **/
714 typedef struct {
715 PyObject_HEAD
716 Tcl_Obj *value;
717 PyObject *string; /* This cannot cause cycles. */
718 } PyTclObject;
720 staticforward PyTypeObject PyTclObject_Type;
721 #define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
723 static PyObject *
724 newPyTclObject(Tcl_Obj *arg)
726 PyTclObject *self;
727 self = PyObject_New(PyTclObject, &PyTclObject_Type);
728 if (self == NULL)
729 return NULL;
730 Tcl_IncrRefCount(arg);
731 self->value = arg;
732 self->string = NULL;
733 return (PyObject*)self;
736 static void
737 PyTclObject_dealloc(PyTclObject *self)
739 Tcl_DecrRefCount(self->value);
740 Py_XDECREF(self->string);
741 PyObject_Del(self);
744 static PyObject *
745 PyTclObject_str(PyTclObject *self)
747 if (self->string && PyString_Check(self->string)) {
748 Py_INCREF(self->string);
749 return self->string;
751 /* XXX Could cache value if it is an ASCII string. */
752 return PyString_FromString(Tcl_GetString(self->value));
755 static char*
756 PyTclObject_TclString(PyObject *self)
758 return Tcl_GetString(((PyTclObject*)self)->value);
761 /* Like _str, but create Unicode if necessary. */
762 PyDoc_STRVAR(PyTclObject_string__doc__,
763 "the string representation of this object, either as string or Unicode");
765 static PyObject *
766 PyTclObject_string(PyTclObject *self, void *ignored)
768 char *s;
769 int i, len;
770 if (!self->string) {
771 s = Tcl_GetStringFromObj(self->value, &len);
772 for (i = 0; i < len; i++)
773 if (s[i] & 0x80)
774 break;
775 #ifdef Py_USING_UNICODE
776 if (i == len)
777 /* It is an ASCII string. */
778 self->string = PyString_FromStringAndSize(s, len);
779 else {
780 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
781 if (!self->string) {
782 PyErr_Clear();
783 self->string = PyString_FromStringAndSize(s, len);
786 #else
787 self->string = PyString_FromStringAndSize(s, len);
788 #endif
789 if (!self->string)
790 return NULL;
792 Py_INCREF(self->string);
793 return self->string;
796 #ifdef Py_USING_UNICODE
797 PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
799 static PyObject *
800 PyTclObject_unicode(PyTclObject *self, void *ignored)
802 char *s;
803 int len;
804 if (self->string && PyUnicode_Check(self->string)) {
805 Py_INCREF(self->string);
806 return self->string;
808 /* XXX Could chache result if it is non-ASCII. */
809 s = Tcl_GetStringFromObj(self->value, &len);
810 return PyUnicode_DecodeUTF8(s, len, "strict");
812 #endif
814 static PyObject *
815 PyTclObject_repr(PyTclObject *self)
817 char buf[50];
818 PyOS_snprintf(buf, 50, "<%s object at %p>",
819 self->value->typePtr->name, self->value);
820 return PyString_FromString(buf);
823 static int
824 PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
826 int res;
827 res = strcmp(Tcl_GetString(self->value),
828 Tcl_GetString(other->value));
829 if (res < 0) return -1;
830 if (res > 0) return 1;
831 return 0;
834 PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
836 static PyObject*
837 get_typename(PyTclObject* obj, void* ignored)
839 return PyString_FromString(obj->value->typePtr->name);
843 static PyGetSetDef PyTclObject_getsetlist[] = {
844 {"typename", (getter)get_typename, NULL, get_typename__doc__},
845 {"string", (getter)PyTclObject_string, NULL,
846 PyTclObject_string__doc__},
847 {0},
850 static PyMethodDef PyTclObject_methods[] = {
851 #ifdef Py_USING_UNICODE
852 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
853 PyTclObject_unicode__doc__},
854 #endif
858 statichere PyTypeObject PyTclObject_Type = {
859 PyObject_HEAD_INIT(NULL)
860 0, /*ob_size*/
861 "_tkinter.Tcl_Obj", /*tp_name*/
862 sizeof(PyTclObject), /*tp_basicsize*/
863 0, /*tp_itemsize*/
864 /* methods */
865 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
866 0, /*tp_print*/
867 0, /*tp_getattr*/
868 0, /*tp_setattr*/
869 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
870 (reprfunc)PyTclObject_repr, /*tp_repr*/
871 0, /*tp_as_number*/
872 0, /*tp_as_sequence*/
873 0, /*tp_as_mapping*/
874 0, /*tp_hash*/
875 0, /*tp_call*/
876 (reprfunc)PyTclObject_str, /*tp_str*/
877 PyObject_GenericGetAttr,/*tp_getattro*/
878 0, /*tp_setattro*/
879 0, /*tp_as_buffer*/
880 Py_TPFLAGS_DEFAULT, /*tp_flags*/
881 0, /*tp_doc*/
882 0, /*tp_traverse*/
883 0, /*tp_clear*/
884 0, /*tp_richcompare*/
885 0, /*tp_weaklistoffset*/
886 0, /*tp_iter*/
887 0, /*tp_iternext*/
888 PyTclObject_methods, /*tp_methods*/
889 0, /*tp_members*/
890 PyTclObject_getsetlist, /*tp_getset*/
891 0, /*tp_base*/
892 0, /*tp_dict*/
893 0, /*tp_descr_get*/
894 0, /*tp_descr_set*/
895 0, /*tp_dictoffset*/
896 0, /*tp_init*/
897 0, /*tp_alloc*/
898 0, /*tp_new*/
899 0, /*tp_free*/
900 0, /*tp_is_gc*/
903 static Tcl_Obj*
904 AsObj(PyObject *value)
906 Tcl_Obj *result;
908 if (PyString_Check(value))
909 return Tcl_NewStringObj(PyString_AS_STRING(value),
910 PyString_GET_SIZE(value));
911 else if (PyBool_Check(value))
912 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
913 else if (PyInt_Check(value))
914 return Tcl_NewLongObj(PyInt_AS_LONG(value));
915 else if (PyFloat_Check(value))
916 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
917 else if (PyTuple_Check(value)) {
918 Tcl_Obj **argv = (Tcl_Obj**)
919 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
920 int i;
921 if(!argv)
922 return 0;
923 for(i=0;i<PyTuple_Size(value);i++)
924 argv[i] = AsObj(PyTuple_GetItem(value,i));
925 result = Tcl_NewListObj(PyTuple_Size(value), argv);
926 ckfree(FREECAST argv);
927 return result;
929 #ifdef Py_USING_UNICODE
930 else if (PyUnicode_Check(value)) {
931 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
932 int size = PyUnicode_GET_SIZE(value);
933 /* This #ifdef assumes that Tcl uses UCS-2.
934 See TCL_UTF_MAX test above. */
935 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
936 Tcl_UniChar *outbuf;
937 int i;
938 outbuf = (Tcl_UniChar*)ckalloc(size * sizeof(Tcl_UniChar));
939 if (!outbuf) {
940 PyErr_NoMemory();
941 return NULL;
943 for (i = 0; i < size; i++) {
944 if (inbuf[i] >= 0x10000) {
945 /* Tcl doesn't do UTF-16, yet. */
946 PyErr_SetString(PyExc_ValueError,
947 "unsupported character");
948 ckfree(FREECAST outbuf);
949 return NULL;
951 outbuf[i] = inbuf[i];
953 result = Tcl_NewUnicodeObj(outbuf, size);
954 ckfree(FREECAST outbuf);
955 return result;
956 #else
957 return Tcl_NewUnicodeObj(inbuf, size);
958 #endif
961 #endif
962 else if(PyTclObject_Check(value)) {
963 Tcl_Obj *v = ((PyTclObject*)value)->value;
964 Tcl_IncrRefCount(v);
965 return v;
967 else {
968 PyObject *v = PyObject_Str(value);
969 if (!v)
970 return 0;
971 result = AsObj(v);
972 Py_DECREF(v);
973 return result;
977 static PyObject*
978 FromObj(PyObject* tkapp, Tcl_Obj *value)
980 PyObject *result = NULL;
981 TkappObject *app = (TkappObject*)tkapp;
983 if (value->typePtr == NULL) {
984 /* If the result contains any bytes with the top bit set,
985 it's UTF-8 and we should decode it to Unicode */
986 #ifdef Py_USING_UNICODE
987 int i;
988 char *s = value->bytes;
989 int len = value->length;
990 for (i = 0; i < len; i++) {
991 if (value->bytes[i] & 0x80)
992 break;
995 if (i == value->length)
996 result = PyString_FromStringAndSize(s, len);
997 else {
998 /* Convert UTF-8 to Unicode string */
999 result = PyUnicode_DecodeUTF8(s, len, "strict");
1000 if (result == NULL) {
1001 PyErr_Clear();
1002 result = PyString_FromStringAndSize(s, len);
1005 #else
1006 result = PyString_FromStringAndSize(value->bytes, value->length);
1007 #endif
1008 return result;
1011 if (value->typePtr == app->BooleanType) {
1012 result = value->internalRep.longValue ? Py_True : Py_False;
1013 Py_INCREF(result);
1014 return result;
1017 if (value->typePtr == app->ByteArrayType) {
1018 int size;
1019 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1020 return PyString_FromStringAndSize(data, size);
1023 if (value->typePtr == app->DoubleType) {
1024 return PyFloat_FromDouble(value->internalRep.doubleValue);
1027 if (value->typePtr == app->IntType) {
1028 return PyInt_FromLong(value->internalRep.longValue);
1031 if (value->typePtr == app->ListType) {
1032 int size;
1033 int i, status;
1034 PyObject *elem;
1035 Tcl_Obj *tcl_elem;
1037 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1038 if (status == TCL_ERROR)
1039 return Tkinter_Error(tkapp);
1040 result = PyTuple_New(size);
1041 if (!result)
1042 return NULL;
1043 for (i = 0; i < size; i++) {
1044 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1045 value, i, &tcl_elem);
1046 if (status == TCL_ERROR) {
1047 Py_DECREF(result);
1048 return Tkinter_Error(tkapp);
1050 elem = FromObj(tkapp, tcl_elem);
1051 if (!elem) {
1052 Py_DECREF(result);
1053 return NULL;
1055 PyTuple_SetItem(result, i, elem);
1057 return result;
1060 if (value->typePtr == app->ProcBodyType) {
1061 /* fall through: return tcl object. */
1064 if (value->typePtr == app->StringType) {
1065 #ifdef Py_USING_UNICODE
1066 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1067 PyObject *result;
1068 int size;
1069 Tcl_UniChar *input;
1070 Py_UNICODE *output;
1072 size = Tcl_GetCharLength(value);
1073 result = PyUnicode_FromUnicode(NULL, size);
1074 if (!result)
1075 return NULL;
1076 input = Tcl_GetUnicode(value);
1077 output = PyUnicode_AS_UNICODE(result);
1078 while (size--)
1079 *output++ = *input++;
1080 return result;
1081 #else
1082 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1083 Tcl_GetCharLength(value));
1084 #endif
1085 #else
1086 int size;
1087 char *c;
1088 c = Tcl_GetStringFromObj(value, &size);
1089 return PyString_FromStringAndSize(c, size);
1090 #endif
1093 return newPyTclObject(value);
1096 /* This mutex synchronizes inter-thread command calls. */
1098 TCL_DECLARE_MUTEX(call_mutex)
1100 typedef struct Tkapp_CallEvent {
1101 Tcl_Event ev; /* Must be first */
1102 TkappObject *self;
1103 PyObject *args;
1104 int flags;
1105 PyObject **res;
1106 PyObject **exc_type, **exc_value, **exc_tb;
1107 Tcl_Condition done;
1108 } Tkapp_CallEvent;
1110 void
1111 Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
1113 int i;
1114 for (i = 0; i < objc; i++)
1115 Tcl_DecrRefCount(objv[i]);
1116 if (objv != objStore)
1117 ckfree(FREECAST objv);
1120 /* Convert Python objects to Tcl objects. This must happen in the
1121 interpreter thread, which may or may not be the calling thread. */
1123 static Tcl_Obj**
1124 Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1126 Tcl_Obj **objv = objStore;
1127 int objc = 0, i;
1128 if (args == NULL)
1129 /* do nothing */;
1131 else if (!PyTuple_Check(args)) {
1132 objv[0] = AsObj(args);
1133 if (objv[0] == 0)
1134 goto finally;
1135 objc = 1;
1136 Tcl_IncrRefCount(objv[0]);
1138 else {
1139 objc = PyTuple_Size(args);
1141 if (objc > ARGSZ) {
1142 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1143 if (objv == NULL) {
1144 PyErr_NoMemory();
1145 objc = 0;
1146 goto finally;
1150 for (i = 0; i < objc; i++) {
1151 PyObject *v = PyTuple_GetItem(args, i);
1152 if (v == Py_None) {
1153 objc = i;
1154 break;
1156 objv[i] = AsObj(v);
1157 if (!objv[i]) {
1158 /* Reset objc, so it attempts to clear
1159 objects only up to i. */
1160 objc = i;
1161 goto finally;
1163 Tcl_IncrRefCount(objv[i]);
1166 *pobjc = objc;
1167 return objv;
1168 finally:
1169 Tkapp_CallDeallocArgs(objv, objStore, objc);
1170 return NULL;
1173 /* Convert the results of a command call into a Python objects. */
1175 static PyObject*
1176 Tkapp_CallResult(TkappObject *self)
1178 PyObject *res = NULL;
1179 if(self->wantobjects) {
1180 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1181 /* Not sure whether the IncrRef is necessary, but something
1182 may overwrite the interpreter result while we are
1183 converting it. */
1184 Tcl_IncrRefCount(value);
1185 res = FromObj((PyObject*)self, value);
1186 Tcl_DecrRefCount(value);
1187 } else {
1188 const char *s = Tcl_GetStringResult(self->interp);
1189 const char *p = s;
1191 /* If the result contains any bytes with the top bit set,
1192 it's UTF-8 and we should decode it to Unicode */
1193 #ifdef Py_USING_UNICODE
1194 while (*p != '\0') {
1195 if (*p & 0x80)
1196 break;
1197 p++;
1200 if (*p == '\0')
1201 res = PyString_FromStringAndSize(s, (int)(p-s));
1202 else {
1203 /* Convert UTF-8 to Unicode string */
1204 p = strchr(p, '\0');
1205 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1206 if (res == NULL) {
1207 PyErr_Clear();
1208 res = PyString_FromStringAndSize(s, (int)(p-s));
1211 #else
1212 p = strchr(p, '\0');
1213 res = PyString_FromStringAndSize(s, (int)(p-s));
1214 #endif
1216 return res;
1219 /* Tkapp_CallProc is the event procedure that is executed in the context of
1220 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1221 hold the Python lock. */
1223 static int
1224 Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1226 Tcl_Obj *objStore[ARGSZ];
1227 Tcl_Obj **objv;
1228 int objc;
1229 int i;
1230 ENTER_PYTHON
1231 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1232 if (!objv) {
1233 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1234 *(e->res) = NULL;
1236 LEAVE_PYTHON
1237 if (!objv)
1238 goto done;
1239 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1240 ENTER_PYTHON
1241 if (i == TCL_ERROR) {
1242 *(e->res) = NULL;
1243 *(e->exc_type) = NULL;
1244 *(e->exc_tb) = NULL;
1245 *(e->exc_value) = PyObject_CallFunction(
1246 Tkinter_TclError, "s",
1247 Tcl_GetStringResult(e->self->interp));
1249 else {
1250 *(e->res) = Tkapp_CallResult(e->self);
1252 LEAVE_PYTHON
1253 done:
1254 /* Wake up calling thread. */
1255 Tcl_MutexLock(&call_mutex);
1256 Tcl_ConditionNotify(&e->done);
1257 Tcl_MutexUnlock(&call_mutex);
1258 return 1;
1261 /* This is the main entry point for calling a Tcl command.
1262 It supports three cases, with regard to threading:
1263 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1264 the context of the calling thread.
1265 2. Tcl is threaded, caller of the command is in the interpreter thread:
1266 Execute the command in the calling thread. Since the Tcl lock will
1267 not be used, we can merge that with case 1.
1268 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1269 the interpreter thread. Allocation of Tcl objects needs to occur in the
1270 interpreter thread, so we ship the PyObject* args to the target thread,
1271 and perform processing there. */
1273 static PyObject *
1274 Tkapp_Call(PyObject *_self, PyObject *args)
1276 Tcl_Obj *objStore[ARGSZ];
1277 Tcl_Obj **objv = NULL;
1278 int objc, i;
1279 PyObject *res = NULL;
1280 TkappObject *self = (TkappObject*)_self;
1281 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1282 int flags = TCL_EVAL_DIRECT;
1284 #ifdef WITH_THREAD
1285 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1286 /* We cannot call the command directly. Instead, we must
1287 marshal the parameters to the interpreter thread. */
1288 Tkapp_CallEvent *ev;
1289 PyObject *exc_type, *exc_value, *exc_tb;
1290 if (!WaitForMainloop(self))
1291 return NULL;
1292 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1293 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1294 ev->self = self;
1295 ev->args = args;
1296 ev->res = &res;
1297 ev->exc_type = &exc_type;
1298 ev->exc_value = &exc_value;
1299 ev->exc_tb = &exc_tb;
1300 ev->done = (Tcl_Condition)0;
1302 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1304 if (res == NULL) {
1305 if (exc_type)
1306 PyErr_Restore(exc_type, exc_value, exc_tb);
1307 else
1308 PyErr_SetObject(Tkinter_TclError, exc_value);
1311 else
1312 #endif
1315 objv = Tkapp_CallArgs(args, objStore, &objc);
1316 if (!objv)
1317 return NULL;
1319 ENTER_TCL
1321 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1323 ENTER_OVERLAP
1325 if (i == TCL_ERROR)
1326 Tkinter_Error(_self);
1327 else
1328 res = Tkapp_CallResult(self);
1330 LEAVE_OVERLAP_TCL
1332 Tkapp_CallDeallocArgs(objv, objStore, objc);
1334 return res;
1338 static PyObject *
1339 Tkapp_GlobalCall(PyObject *self, PyObject *args)
1341 /* Could do the same here as for Tkapp_Call(), but this is not used
1342 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1343 way for the user to do what all its Global* variants do (save and
1344 reset the scope pointer, call the local version, restore the saved
1345 scope pointer). */
1347 char *cmd;
1348 PyObject *res = NULL;
1350 CHECK_TCL_APPARTMENT;
1352 cmd = Merge(args);
1353 if (cmd) {
1354 int err;
1355 ENTER_TCL
1356 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1357 ENTER_OVERLAP
1358 if (err == TCL_ERROR)
1359 res = Tkinter_Error(self);
1360 else
1361 res = PyString_FromString(Tkapp_Result(self));
1362 LEAVE_OVERLAP_TCL
1363 ckfree(cmd);
1366 return res;
1369 static PyObject *
1370 Tkapp_Eval(PyObject *self, PyObject *args)
1372 char *script;
1373 PyObject *res = NULL;
1374 int err;
1376 if (!PyArg_ParseTuple(args, "s:eval", &script))
1377 return NULL;
1379 CHECK_TCL_APPARTMENT;
1381 ENTER_TCL
1382 err = Tcl_Eval(Tkapp_Interp(self), script);
1383 ENTER_OVERLAP
1384 if (err == TCL_ERROR)
1385 res = Tkinter_Error(self);
1386 else
1387 res = PyString_FromString(Tkapp_Result(self));
1388 LEAVE_OVERLAP_TCL
1389 return res;
1392 static PyObject *
1393 Tkapp_GlobalEval(PyObject *self, PyObject *args)
1395 char *script;
1396 PyObject *res = NULL;
1397 int err;
1399 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1400 return NULL;
1402 CHECK_TCL_APPARTMENT;
1404 ENTER_TCL
1405 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1406 ENTER_OVERLAP
1407 if (err == TCL_ERROR)
1408 res = Tkinter_Error(self);
1409 else
1410 res = PyString_FromString(Tkapp_Result(self));
1411 LEAVE_OVERLAP_TCL
1412 return res;
1415 static PyObject *
1416 Tkapp_EvalFile(PyObject *self, PyObject *args)
1418 char *fileName;
1419 PyObject *res = NULL;
1420 int err;
1422 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1423 return NULL;
1425 CHECK_TCL_APPARTMENT;
1427 ENTER_TCL
1428 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1429 ENTER_OVERLAP
1430 if (err == TCL_ERROR)
1431 res = Tkinter_Error(self);
1433 else
1434 res = PyString_FromString(Tkapp_Result(self));
1435 LEAVE_OVERLAP_TCL
1436 return res;
1439 static PyObject *
1440 Tkapp_Record(PyObject *self, PyObject *args)
1442 char *script;
1443 PyObject *res = NULL;
1444 int err;
1446 if (!PyArg_ParseTuple(args, "s", &script))
1447 return NULL;
1449 CHECK_TCL_APPARTMENT;
1451 ENTER_TCL
1452 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1453 ENTER_OVERLAP
1454 if (err == TCL_ERROR)
1455 res = Tkinter_Error(self);
1456 else
1457 res = PyString_FromString(Tkapp_Result(self));
1458 LEAVE_OVERLAP_TCL
1459 return res;
1462 static PyObject *
1463 Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
1465 char *msg;
1467 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1468 return NULL;
1469 CHECK_TCL_APPARTMENT;
1471 ENTER_TCL
1472 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1473 LEAVE_TCL
1475 Py_INCREF(Py_None);
1476 return Py_None;
1481 /** Tcl Variable **/
1483 TCL_DECLARE_MUTEX(var_mutex)
1485 typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1486 typedef struct VarEvent {
1487 Tcl_Event ev; /* must be first */
1488 PyObject *self;
1489 PyObject *args;
1490 int flags;
1491 EventFunc func;
1492 PyObject **res;
1493 PyObject **exc_type;
1494 PyObject **exc_val;
1495 Tcl_Condition cond;
1496 } VarEvent;
1498 static int
1499 varname_converter(PyObject *in, void *_out)
1501 char **out = (char**)_out;
1502 if (PyString_Check(in)) {
1503 *out = PyString_AsString(in);
1504 return 1;
1506 if (PyTclObject_Check(in)) {
1507 *out = PyTclObject_TclString(in);
1508 return 1;
1510 /* XXX: Should give diagnostics. */
1511 return 0;
1514 void
1515 var_perform(VarEvent *ev)
1517 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1518 if (!*(ev->res)) {
1519 PyObject *exc, *val, *tb;
1520 PyErr_Fetch(&exc, &val, &tb);
1521 PyErr_NormalizeException(&exc, &val, &tb);
1522 *(ev->exc_type) = exc;
1523 *(ev->exc_val) = val;
1524 Py_DECREF(tb);
1529 static int
1530 var_proc(VarEvent* ev, int flags)
1532 ENTER_PYTHON
1533 var_perform(ev);
1534 Tcl_MutexLock(&var_mutex);
1535 Tcl_ConditionNotify(&ev->cond);
1536 Tcl_MutexUnlock(&var_mutex);
1537 LEAVE_PYTHON
1538 return 1;
1541 static PyObject*
1542 var_invoke(EventFunc func, PyObject *_self, PyObject *args, int flags)
1544 TkappObject *self = (TkappObject*)_self;
1545 #ifdef WITH_THREAD
1546 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1547 TkappObject *self = (TkappObject*)_self;
1548 VarEvent *ev;
1549 PyObject *res, *exc_type, *exc_val;
1551 /* The current thread is not the interpreter thread. Marshal
1552 the call to the interpreter thread, then wait for
1553 completion. */
1554 if (!WaitForMainloop(self))
1555 return NULL;
1557 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1559 ev->self = _self;
1560 ev->args = args;
1561 ev->flags = flags;
1562 ev->func = func;
1563 ev->res = &res;
1564 ev->exc_type = &exc_type;
1565 ev->exc_val = &exc_val;
1566 ev->cond = NULL;
1567 ev->ev.proc = (Tcl_EventProc*)var_proc;
1568 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1569 if (!res) {
1570 PyErr_SetObject(exc_type, exc_val);
1571 Py_DECREF(exc_type);
1572 Py_DECREF(exc_val);
1573 return NULL;
1575 return res;
1577 #endif
1578 /* Tcl is not threaded, or this is the interpreter thread. */
1579 return func(_self, args, flags);
1582 static PyObject *
1583 SetVar(PyObject *self, PyObject *args, int flags)
1585 char *name1, *name2;
1586 PyObject *newValue;
1587 PyObject *res = NULL;
1588 Tcl_Obj *newval, *ok;
1590 if (PyArg_ParseTuple(args, "O&O:setvar",
1591 varname_converter, &name1, &newValue)) {
1592 /* XXX Acquire tcl lock??? */
1593 newval = AsObj(newValue);
1594 if (newval == NULL)
1595 return NULL;
1596 ENTER_TCL
1597 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1598 newval, flags);
1599 ENTER_OVERLAP
1600 if (!ok)
1601 Tkinter_Error(self);
1602 else {
1603 res = Py_None;
1604 Py_INCREF(res);
1606 LEAVE_OVERLAP_TCL
1608 else {
1609 PyErr_Clear();
1610 if (PyArg_ParseTuple(args, "ssO:setvar",
1611 &name1, &name2, &newValue)) {
1612 /* XXX must hold tcl lock already??? */
1613 newval = AsObj(newValue);
1614 ENTER_TCL
1615 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1616 ENTER_OVERLAP
1617 if (!ok)
1618 Tkinter_Error(self);
1619 else {
1620 res = Py_None;
1621 Py_INCREF(res);
1623 LEAVE_OVERLAP_TCL
1625 else {
1626 return NULL;
1629 return res;
1632 static PyObject *
1633 Tkapp_SetVar(PyObject *self, PyObject *args)
1635 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1638 static PyObject *
1639 Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
1641 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1646 static PyObject *
1647 GetVar(PyObject *self, PyObject *args, int flags)
1649 char *name1, *name2=NULL;
1650 PyObject *res = NULL;
1651 Tcl_Obj *tres;
1653 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1654 varname_converter, &name1, &name2))
1655 return NULL;
1657 ENTER_TCL
1658 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1659 ENTER_OVERLAP
1660 if (tres == NULL) {
1661 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1662 } else {
1663 if (((TkappObject*)self)->wantobjects) {
1664 res = FromObj(self, tres);
1666 else {
1667 res = PyString_FromString(Tcl_GetString(tres));
1670 LEAVE_OVERLAP_TCL
1671 return res;
1674 static PyObject *
1675 Tkapp_GetVar(PyObject *self, PyObject *args)
1677 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1680 static PyObject *
1681 Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1683 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1688 static PyObject *
1689 UnsetVar(PyObject *self, PyObject *args, int flags)
1691 char *name1, *name2=NULL;
1692 int code;
1693 PyObject *res = NULL;
1695 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1696 return NULL;
1698 ENTER_TCL
1699 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1700 ENTER_OVERLAP
1701 if (code == TCL_ERROR)
1702 res = Tkinter_Error(self);
1703 else {
1704 Py_INCREF(Py_None);
1705 res = Py_None;
1707 LEAVE_OVERLAP_TCL
1708 return res;
1711 static PyObject *
1712 Tkapp_UnsetVar(PyObject *self, PyObject *args)
1714 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1717 static PyObject *
1718 Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1720 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1725 /** Tcl to Python **/
1727 static PyObject *
1728 Tkapp_GetInt(PyObject *self, PyObject *args)
1730 char *s;
1731 int v;
1733 if (PyTuple_Size(args) == 1) {
1734 PyObject* o = PyTuple_GetItem(args, 0);
1735 if (PyInt_Check(o)) {
1736 Py_INCREF(o);
1737 return o;
1740 if (!PyArg_ParseTuple(args, "s:getint", &s))
1741 return NULL;
1742 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1743 return Tkinter_Error(self);
1744 return Py_BuildValue("i", v);
1747 static PyObject *
1748 Tkapp_GetDouble(PyObject *self, PyObject *args)
1750 char *s;
1751 double v;
1753 if (PyTuple_Size(args) == 1) {
1754 PyObject *o = PyTuple_GetItem(args, 0);
1755 if (PyFloat_Check(o)) {
1756 Py_INCREF(o);
1757 return o;
1760 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1761 return NULL;
1762 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1763 return Tkinter_Error(self);
1764 return Py_BuildValue("d", v);
1767 static PyObject *
1768 Tkapp_GetBoolean(PyObject *self, PyObject *args)
1770 char *s;
1771 int v;
1773 if (PyTuple_Size(args) == 1) {
1774 PyObject *o = PyTuple_GetItem(args, 0);
1775 if (PyInt_Check(o)) {
1776 Py_INCREF(o);
1777 return o;
1780 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1781 return NULL;
1782 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1783 return Tkinter_Error(self);
1784 return PyBool_FromLong(v);
1787 static PyObject *
1788 Tkapp_ExprString(PyObject *self, PyObject *args)
1790 char *s;
1791 PyObject *res = NULL;
1792 int retval;
1794 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1795 return NULL;
1797 CHECK_TCL_APPARTMENT;
1799 ENTER_TCL
1800 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1801 ENTER_OVERLAP
1802 if (retval == TCL_ERROR)
1803 res = Tkinter_Error(self);
1804 else
1805 res = Py_BuildValue("s", Tkapp_Result(self));
1806 LEAVE_OVERLAP_TCL
1807 return res;
1810 static PyObject *
1811 Tkapp_ExprLong(PyObject *self, PyObject *args)
1813 char *s;
1814 PyObject *res = NULL;
1815 int retval;
1816 long v;
1818 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1819 return NULL;
1821 CHECK_TCL_APPARTMENT;
1823 ENTER_TCL
1824 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1825 ENTER_OVERLAP
1826 if (retval == TCL_ERROR)
1827 res = Tkinter_Error(self);
1828 else
1829 res = Py_BuildValue("l", v);
1830 LEAVE_OVERLAP_TCL
1831 return res;
1834 static PyObject *
1835 Tkapp_ExprDouble(PyObject *self, PyObject *args)
1837 char *s;
1838 PyObject *res = NULL;
1839 double v;
1840 int retval;
1842 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1843 return NULL;
1844 CHECK_TCL_APPARTMENT;
1845 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1846 ENTER_TCL
1847 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1848 ENTER_OVERLAP
1849 PyFPE_END_PROTECT(retval)
1850 if (retval == TCL_ERROR)
1851 res = Tkinter_Error(self);
1852 else
1853 res = Py_BuildValue("d", v);
1854 LEAVE_OVERLAP_TCL
1855 return res;
1858 static PyObject *
1859 Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1861 char *s;
1862 PyObject *res = NULL;
1863 int retval;
1864 int v;
1866 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1867 return NULL;
1868 CHECK_TCL_APPARTMENT;
1869 ENTER_TCL
1870 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1871 ENTER_OVERLAP
1872 if (retval == TCL_ERROR)
1873 res = Tkinter_Error(self);
1874 else
1875 res = Py_BuildValue("i", v);
1876 LEAVE_OVERLAP_TCL
1877 return res;
1882 static PyObject *
1883 Tkapp_SplitList(PyObject *self, PyObject *args)
1885 char *list;
1886 int argc;
1887 char **argv;
1888 PyObject *v;
1889 int i;
1891 if (PyTuple_Size(args) == 1) {
1892 v = PyTuple_GetItem(args, 0);
1893 if (PyTuple_Check(v)) {
1894 Py_INCREF(v);
1895 return v;
1898 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1899 return NULL;
1901 if (Tcl_SplitList(Tkapp_Interp(self), list,
1902 &argc, &argv) == TCL_ERROR) {
1903 PyMem_Free(list);
1904 return Tkinter_Error(self);
1907 if (!(v = PyTuple_New(argc)))
1908 goto finally;
1910 for (i = 0; i < argc; i++) {
1911 PyObject *s = PyString_FromString(argv[i]);
1912 if (!s || PyTuple_SetItem(v, i, s)) {
1913 Py_DECREF(v);
1914 v = NULL;
1915 goto finally;
1919 finally:
1920 ckfree(FREECAST argv);
1921 PyMem_Free(list);
1922 return v;
1925 static PyObject *
1926 Tkapp_Split(PyObject *self, PyObject *args)
1928 PyObject *v;
1929 char *list;
1931 if (PyTuple_Size(args) == 1) {
1932 PyObject* o = PyTuple_GetItem(args, 0);
1933 if (PyTuple_Check(o)) {
1934 o = SplitObj(o);
1935 return o;
1938 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1939 return NULL;
1940 v = Split(list);
1941 PyMem_Free(list);
1942 return v;
1945 static PyObject *
1946 Tkapp_Merge(PyObject *self, PyObject *args)
1948 char *s = Merge(args);
1949 PyObject *res = NULL;
1951 if (s) {
1952 res = PyString_FromString(s);
1953 ckfree(s);
1956 return res;
1961 /** Tcl Command **/
1963 /* Client data struct */
1964 typedef struct {
1965 PyObject *self;
1966 PyObject *func;
1967 } PythonCmd_ClientData;
1969 static int
1970 PythonCmd_Error(Tcl_Interp *interp)
1972 errorInCmd = 1;
1973 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1974 LEAVE_PYTHON
1975 return TCL_ERROR;
1978 /* This is the Tcl command that acts as a wrapper for Python
1979 * function or method.
1981 static int
1982 PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1984 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1985 PyObject *self, *func, *arg, *res, *tmp;
1986 int i, rv;
1987 char *s;
1989 ENTER_PYTHON
1991 /* TBD: no error checking here since we know, via the
1992 * Tkapp_CreateCommand() that the client data is a two-tuple
1994 self = data->self;
1995 func = data->func;
1997 /* Create argument list (argv1, ..., argvN) */
1998 if (!(arg = PyTuple_New(argc - 1)))
1999 return PythonCmd_Error(interp);
2001 for (i = 0; i < (argc - 1); i++) {
2002 PyObject *s = PyString_FromString(argv[i + 1]);
2003 if (!s || PyTuple_SetItem(arg, i, s)) {
2004 Py_DECREF(arg);
2005 return PythonCmd_Error(interp);
2008 res = PyEval_CallObject(func, arg);
2009 Py_DECREF(arg);
2011 if (res == NULL)
2012 return PythonCmd_Error(interp);
2014 if (!(tmp = PyList_New(0))) {
2015 Py_DECREF(res);
2016 return PythonCmd_Error(interp);
2019 s = AsString(res, tmp);
2020 if (s == NULL) {
2021 rv = PythonCmd_Error(interp);
2023 else {
2024 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
2025 rv = TCL_OK;
2028 Py_DECREF(res);
2029 Py_DECREF(tmp);
2031 LEAVE_PYTHON
2033 return rv;
2036 static void
2037 PythonCmdDelete(ClientData clientData)
2039 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2041 ENTER_PYTHON
2042 Py_XDECREF(data->self);
2043 Py_XDECREF(data->func);
2044 PyMem_DEL(data);
2045 LEAVE_PYTHON
2051 TCL_DECLARE_MUTEX(command_mutex)
2053 typedef struct CommandEvent{
2054 Tcl_Event ev;
2055 Tcl_Interp* interp;
2056 char *name;
2057 int create;
2058 int *status;
2059 ClientData *data;
2060 Tcl_Condition done;
2061 } CommandEvent;
2063 static int
2064 Tkapp_CommandProc(CommandEvent *ev, int flags)
2066 if (ev->create)
2067 *ev->status = Tcl_CreateCommand(
2068 ev->interp, ev->name, PythonCmd,
2069 ev->data, PythonCmdDelete) == NULL;
2070 else
2071 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2072 Tcl_MutexLock(&command_mutex);
2073 Tcl_ConditionNotify(&ev->done);
2074 Tcl_MutexUnlock(&command_mutex);
2075 return 1;
2078 static PyObject *
2079 Tkapp_CreateCommand(PyObject *_self, PyObject *args)
2081 TkappObject *self = (TkappObject*)_self;
2082 PythonCmd_ClientData *data;
2083 char *cmdName;
2084 PyObject *func;
2085 int err;
2087 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2088 return NULL;
2089 if (!PyCallable_Check(func)) {
2090 PyErr_SetString(PyExc_TypeError, "command not callable");
2091 return NULL;
2094 #ifdef WITH_THREAD
2095 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2096 !WaitForMainloop(self))
2097 return NULL;
2098 #endif
2100 data = PyMem_NEW(PythonCmd_ClientData, 1);
2101 if (!data)
2102 return PyErr_NoMemory();
2103 Py_XINCREF(self);
2104 Py_XINCREF(func);
2105 data->self = _self;
2106 data->func = func;
2108 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2109 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2110 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2111 ev->interp = self->interp;
2112 ev->create = 1;
2113 ev->name = cmdName;
2114 ev->data = (ClientData)data;
2115 ev->status = &err;
2116 ev->done = NULL;
2117 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2119 else {
2120 ENTER_TCL
2121 err = Tcl_CreateCommand(
2122 Tkapp_Interp(self), cmdName, PythonCmd,
2123 (ClientData)data, PythonCmdDelete) == NULL;
2124 LEAVE_TCL
2126 if (err) {
2127 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2128 PyMem_DEL(data);
2129 return NULL;
2132 Py_INCREF(Py_None);
2133 return Py_None;
2138 static PyObject *
2139 Tkapp_DeleteCommand(PyObject *_self, PyObject *args)
2141 TkappObject *self = (TkappObject*)_self;
2142 char *cmdName;
2143 int err;
2145 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2146 return NULL;
2147 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2148 CommandEvent *ev;
2149 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2150 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2151 ev->interp = self->interp;
2152 ev->create = 0;
2153 ev->name = cmdName;
2154 ev->status = &err;
2155 ev->done = NULL;
2156 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2157 &command_mutex);
2159 else {
2160 ENTER_TCL
2161 err = Tcl_DeleteCommand(self->interp, cmdName);
2162 LEAVE_TCL
2164 if (err == -1) {
2165 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2166 return NULL;
2168 Py_INCREF(Py_None);
2169 return Py_None;
2174 #ifdef HAVE_CREATEFILEHANDLER
2175 /** File Handler **/
2177 typedef struct _fhcdata {
2178 PyObject *func;
2179 PyObject *file;
2180 int id;
2181 struct _fhcdata *next;
2182 } FileHandler_ClientData;
2184 static FileHandler_ClientData *HeadFHCD;
2186 static FileHandler_ClientData *
2187 NewFHCD(PyObject *func, PyObject *file, int id)
2189 FileHandler_ClientData *p;
2190 p = PyMem_NEW(FileHandler_ClientData, 1);
2191 if (p != NULL) {
2192 Py_XINCREF(func);
2193 Py_XINCREF(file);
2194 p->func = func;
2195 p->file = file;
2196 p->id = id;
2197 p->next = HeadFHCD;
2198 HeadFHCD = p;
2200 return p;
2203 static void
2204 DeleteFHCD(int id)
2206 FileHandler_ClientData *p, **pp;
2208 pp = &HeadFHCD;
2209 while ((p = *pp) != NULL) {
2210 if (p->id == id) {
2211 *pp = p->next;
2212 Py_XDECREF(p->func);
2213 Py_XDECREF(p->file);
2214 PyMem_DEL(p);
2216 else
2217 pp = &p->next;
2221 static void
2222 FileHandler(ClientData clientData, int mask)
2224 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2225 PyObject *func, *file, *arg, *res;
2227 ENTER_PYTHON
2228 func = data->func;
2229 file = data->file;
2231 arg = Py_BuildValue("(Oi)", file, (long) mask);
2232 res = PyEval_CallObject(func, arg);
2233 Py_DECREF(arg);
2235 if (res == NULL) {
2236 errorInCmd = 1;
2237 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2239 Py_XDECREF(res);
2240 LEAVE_PYTHON
2243 static PyObject *
2244 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2245 /* args is (file, mask, func) */
2247 FileHandler_ClientData *data;
2248 PyObject *file, *func;
2249 int mask, tfile;
2251 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2252 &file, &mask, &func))
2253 return NULL;
2255 #ifdef WITH_THREAD
2256 if (!self && !tcl_lock) {
2257 /* We don't have the Tcl lock since Tcl is threaded. */
2258 PyErr_SetString(PyExc_RuntimeError,
2259 "_tkinter.createfilehandler not supported "
2260 "for threaded Tcl");
2261 return NULL;
2263 #endif
2265 if (self) {
2266 CHECK_TCL_APPARTMENT;
2269 tfile = PyObject_AsFileDescriptor(file);
2270 if (tfile < 0)
2271 return NULL;
2272 if (!PyCallable_Check(func)) {
2273 PyErr_SetString(PyExc_TypeError, "bad argument list");
2274 return NULL;
2277 data = NewFHCD(func, file, tfile);
2278 if (data == NULL)
2279 return NULL;
2281 /* Ought to check for null Tcl_File object... */
2282 ENTER_TCL
2283 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2284 LEAVE_TCL
2285 Py_INCREF(Py_None);
2286 return Py_None;
2289 static PyObject *
2290 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2292 PyObject *file;
2293 int tfile;
2295 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2296 return NULL;
2298 #ifdef WITH_THREAD
2299 if (!self && !tcl_lock) {
2300 /* We don't have the Tcl lock since Tcl is threaded. */
2301 PyErr_SetString(PyExc_RuntimeError,
2302 "_tkinter.deletefilehandler not supported "
2303 "for threaded Tcl");
2304 return NULL;
2306 #endif
2308 if (self) {
2309 CHECK_TCL_APPARTMENT;
2312 tfile = PyObject_AsFileDescriptor(file);
2313 if (tfile < 0)
2314 return NULL;
2316 DeleteFHCD(tfile);
2318 /* Ought to check for null Tcl_File object... */
2319 ENTER_TCL
2320 Tcl_DeleteFileHandler(tfile);
2321 LEAVE_TCL
2322 Py_INCREF(Py_None);
2323 return Py_None;
2325 #endif /* HAVE_CREATEFILEHANDLER */
2328 /**** Tktt Object (timer token) ****/
2330 static PyTypeObject Tktt_Type;
2332 typedef struct {
2333 PyObject_HEAD
2334 Tcl_TimerToken token;
2335 PyObject *func;
2336 } TkttObject;
2338 static PyObject *
2339 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2341 TkttObject *v = (TkttObject *)self;
2342 PyObject *func = v->func;
2344 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2345 return NULL;
2346 if (v->token != NULL) {
2347 Tcl_DeleteTimerHandler(v->token);
2348 v->token = NULL;
2350 if (func != NULL) {
2351 v->func = NULL;
2352 Py_DECREF(func);
2353 Py_DECREF(v); /* See Tktt_New() */
2355 Py_INCREF(Py_None);
2356 return Py_None;
2359 static PyMethodDef Tktt_methods[] =
2361 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2362 {NULL, NULL}
2365 static TkttObject *
2366 Tktt_New(PyObject *func)
2368 TkttObject *v;
2370 v = PyObject_New(TkttObject, &Tktt_Type);
2371 if (v == NULL)
2372 return NULL;
2374 Py_INCREF(func);
2375 v->token = NULL;
2376 v->func = func;
2378 /* Extra reference, deleted when called or when handler is deleted */
2379 Py_INCREF(v);
2380 return v;
2383 static void
2384 Tktt_Dealloc(PyObject *self)
2386 TkttObject *v = (TkttObject *)self;
2387 PyObject *func = v->func;
2389 Py_XDECREF(func);
2391 PyObject_Del(self);
2394 static PyObject *
2395 Tktt_Repr(PyObject *self)
2397 TkttObject *v = (TkttObject *)self;
2398 char buf[100];
2400 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2401 v->func == NULL ? ", handler deleted" : "");
2402 return PyString_FromString(buf);
2405 static PyObject *
2406 Tktt_GetAttr(PyObject *self, const char *name)
2408 return Py_FindMethod(Tktt_methods, self, name);
2411 static PyTypeObject Tktt_Type =
2413 PyObject_HEAD_INIT(NULL)
2414 0, /*ob_size */
2415 "tktimertoken", /*tp_name */
2416 sizeof(TkttObject), /*tp_basicsize */
2417 0, /*tp_itemsize */
2418 Tktt_Dealloc, /*tp_dealloc */
2419 0, /*tp_print */
2420 Tktt_GetAttr, /*tp_getattr */
2421 0, /*tp_setattr */
2422 0, /*tp_compare */
2423 Tktt_Repr, /*tp_repr */
2424 0, /*tp_as_number */
2425 0, /*tp_as_sequence */
2426 0, /*tp_as_mapping */
2427 0, /*tp_hash */
2432 /** Timer Handler **/
2434 static void
2435 TimerHandler(ClientData clientData)
2437 TkttObject *v = (TkttObject *)clientData;
2438 PyObject *func = v->func;
2439 PyObject *res;
2441 if (func == NULL)
2442 return;
2444 v->func = NULL;
2446 ENTER_PYTHON
2448 res = PyEval_CallObject(func, NULL);
2449 Py_DECREF(func);
2450 Py_DECREF(v); /* See Tktt_New() */
2452 if (res == NULL) {
2453 errorInCmd = 1;
2454 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2456 else
2457 Py_DECREF(res);
2459 LEAVE_PYTHON
2462 static PyObject *
2463 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2465 int milliseconds;
2466 PyObject *func;
2467 TkttObject *v;
2469 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2470 &milliseconds, &func))
2471 return NULL;
2472 if (!PyCallable_Check(func)) {
2473 PyErr_SetString(PyExc_TypeError, "bad argument list");
2474 return NULL;
2477 #ifdef WITH_THREAD
2478 if (!self && !tcl_lock) {
2479 /* We don't have the Tcl lock since Tcl is threaded. */
2480 PyErr_SetString(PyExc_RuntimeError,
2481 "_tkinter.createtimerhandler not supported "
2482 "for threaded Tcl");
2483 return NULL;
2485 #endif
2487 if (self) {
2488 CHECK_TCL_APPARTMENT;
2491 v = Tktt_New(func);
2492 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2493 (ClientData)v);
2495 return (PyObject *) v;
2499 /** Event Loop **/
2501 static PyObject *
2502 Tkapp_MainLoop(PyObject *_self, PyObject *args)
2504 int threshold = 0;
2505 TkappObject *self = (TkappObject*)_self;
2506 #ifdef WITH_THREAD
2507 PyThreadState *tstate = PyThreadState_Get();
2508 #endif
2510 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2511 return NULL;
2513 #ifdef WITH_THREAD
2514 if (!self && !tcl_lock) {
2515 /* We don't have the Tcl lock since Tcl is threaded. */
2516 PyErr_SetString(PyExc_RuntimeError,
2517 "_tkinter.mainloop not supported "
2518 "for threaded Tcl");
2519 return NULL;
2521 #endif
2523 if (self) {
2524 CHECK_TCL_APPARTMENT;
2525 self->dispatching = 1;
2528 quitMainLoop = 0;
2529 while (Tk_GetNumMainWindows() > threshold &&
2530 !quitMainLoop &&
2531 !errorInCmd)
2533 int result;
2535 #ifdef WITH_THREAD
2536 if (self && self->threaded) {
2537 /* Allow other Python threads to run. */
2538 ENTER_TCL
2539 result = Tcl_DoOneEvent(0);
2540 LEAVE_TCL
2542 else {
2543 Py_BEGIN_ALLOW_THREADS
2544 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2545 tcl_tstate = tstate;
2546 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2547 tcl_tstate = NULL;
2548 if(tcl_lock)PyThread_release_lock(tcl_lock);
2549 if (result == 0)
2550 Sleep(Tkinter_busywaitinterval);
2551 Py_END_ALLOW_THREADS
2553 #else
2554 result = Tcl_DoOneEvent(0);
2555 #endif
2557 if (PyErr_CheckSignals() != 0) {
2558 if (self)
2559 self->dispatching = 0;
2560 return NULL;
2562 if (result < 0)
2563 break;
2565 if (self)
2566 self->dispatching = 0;
2567 quitMainLoop = 0;
2569 if (errorInCmd) {
2570 errorInCmd = 0;
2571 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2572 excInCmd = valInCmd = trbInCmd = NULL;
2573 return NULL;
2575 Py_INCREF(Py_None);
2576 return Py_None;
2579 static PyObject *
2580 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
2582 int flags = 0;
2583 int rv;
2585 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2586 return NULL;
2588 ENTER_TCL
2589 rv = Tcl_DoOneEvent(flags);
2590 LEAVE_TCL
2591 return Py_BuildValue("i", rv);
2594 static PyObject *
2595 Tkapp_Quit(PyObject *self, PyObject *args)
2598 if (!PyArg_ParseTuple(args, ":quit"))
2599 return NULL;
2601 quitMainLoop = 1;
2602 Py_INCREF(Py_None);
2603 return Py_None;
2606 static PyObject *
2607 Tkapp_InterpAddr(PyObject *self, PyObject *args)
2610 if (!PyArg_ParseTuple(args, ":interpaddr"))
2611 return NULL;
2613 return PyInt_FromLong((long)Tkapp_Interp(self));
2616 static PyObject *
2617 Tkapp_TkInit(PyObject *self, PyObject *args)
2619 Tcl_Interp *interp = Tkapp_Interp(self);
2620 Tk_Window main_window;
2621 const char * _tk_exists = NULL;
2622 PyObject *res = NULL;
2623 int err;
2624 main_window = Tk_MainWindow(interp);
2626 /* We want to guard against calling Tk_Init() multiple times */
2627 CHECK_TCL_APPARTMENT;
2628 ENTER_TCL
2629 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2630 ENTER_OVERLAP
2631 if (err == TCL_ERROR) {
2632 /* XXX: shouldn't we do something with res? */
2633 res = Tkinter_Error(self);
2634 } else {
2635 _tk_exists = Tkapp_Result(self);
2637 LEAVE_OVERLAP_TCL
2638 if (err == TCL_ERROR) {
2639 return NULL;
2641 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2642 if (Tk_Init(interp) == TCL_ERROR) {
2643 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2644 return NULL;
2647 Py_INCREF(Py_None);
2648 return Py_None;
2651 static PyObject *
2652 Tkapp_WantObjects(PyObject *self, PyObject *args)
2655 int wantobjects = -1;
2656 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2657 return NULL;
2658 if (wantobjects == -1)
2659 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2660 ((TkappObject*)self)->wantobjects = wantobjects;
2662 Py_INCREF(Py_None);
2663 return Py_None;
2666 static PyObject *
2667 Tkapp_WillDispatch(PyObject *self, PyObject *args)
2670 ((TkappObject*)self)->dispatching = 1;
2672 Py_INCREF(Py_None);
2673 return Py_None;
2677 /**** Tkapp Method List ****/
2679 static PyMethodDef Tkapp_methods[] =
2681 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2682 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2683 {"call", Tkapp_Call, METH_OLDARGS},
2684 {"globalcall", Tkapp_GlobalCall, METH_OLDARGS},
2685 {"eval", Tkapp_Eval, METH_VARARGS},
2686 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2687 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2688 {"record", Tkapp_Record, METH_VARARGS},
2689 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2690 {"setvar", Tkapp_SetVar, METH_VARARGS},
2691 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2692 {"getvar", Tkapp_GetVar, METH_VARARGS},
2693 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2694 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2695 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2696 {"getint", Tkapp_GetInt, METH_VARARGS},
2697 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2698 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2699 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2700 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2701 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2702 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2703 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2704 {"split", Tkapp_Split, METH_VARARGS},
2705 {"merge", Tkapp_Merge, METH_OLDARGS},
2706 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2707 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2708 #ifdef HAVE_CREATEFILEHANDLER
2709 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2710 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2711 #endif
2712 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2713 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2714 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2715 {"quit", Tkapp_Quit, METH_VARARGS},
2716 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2717 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2718 {NULL, NULL}
2723 /**** Tkapp Type Methods ****/
2725 static void
2726 Tkapp_Dealloc(PyObject *self)
2728 /*CHECK_TCL_APPARTMENT;*/
2729 ENTER_TCL
2730 Tcl_DeleteInterp(Tkapp_Interp(self));
2731 LEAVE_TCL
2732 PyObject_Del(self);
2733 DisableEventHook();
2736 static PyObject *
2737 Tkapp_GetAttr(PyObject *self, const char *name)
2739 return Py_FindMethod(Tkapp_methods, self, name);
2742 static PyTypeObject Tkapp_Type =
2744 PyObject_HEAD_INIT(NULL)
2745 0, /*ob_size */
2746 "tkapp", /*tp_name */
2747 sizeof(TkappObject), /*tp_basicsize */
2748 0, /*tp_itemsize */
2749 Tkapp_Dealloc, /*tp_dealloc */
2750 0, /*tp_print */
2751 Tkapp_GetAttr, /*tp_getattr */
2752 0, /*tp_setattr */
2753 0, /*tp_compare */
2754 0, /*tp_repr */
2755 0, /*tp_as_number */
2756 0, /*tp_as_sequence */
2757 0, /*tp_as_mapping */
2758 0, /*tp_hash */
2763 /**** Tkinter Module ****/
2765 typedef struct {
2766 PyObject* tuple;
2767 int size; /* current size */
2768 int maxsize; /* allocated size */
2769 } FlattenContext;
2771 static int
2772 _bump(FlattenContext* context, int size)
2774 /* expand tuple to hold (at least) size new items.
2775 return true if successful, false if an exception was raised */
2777 int maxsize = context->maxsize * 2;
2779 if (maxsize < context->size + size)
2780 maxsize = context->size + size;
2782 context->maxsize = maxsize;
2784 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2787 static int
2788 _flatten1(FlattenContext* context, PyObject* item, int depth)
2790 /* add tuple or list to argument tuple (recursively) */
2792 int i, size;
2794 if (depth > 1000) {
2795 PyErr_SetString(PyExc_ValueError,
2796 "nesting too deep in _flatten");
2797 return 0;
2798 } else if (PyList_Check(item)) {
2799 size = PyList_GET_SIZE(item);
2800 /* preallocate (assume no nesting) */
2801 if (context->size + size > context->maxsize &&
2802 !_bump(context, size))
2803 return 0;
2804 /* copy items to output tuple */
2805 for (i = 0; i < size; i++) {
2806 PyObject *o = PyList_GET_ITEM(item, i);
2807 if (PyList_Check(o) || PyTuple_Check(o)) {
2808 if (!_flatten1(context, o, depth + 1))
2809 return 0;
2810 } else if (o != Py_None) {
2811 if (context->size + 1 > context->maxsize &&
2812 !_bump(context, 1))
2813 return 0;
2814 Py_INCREF(o);
2815 PyTuple_SET_ITEM(context->tuple,
2816 context->size++, o);
2819 } else if (PyTuple_Check(item)) {
2820 /* same, for tuples */
2821 size = PyTuple_GET_SIZE(item);
2822 if (context->size + size > context->maxsize &&
2823 !_bump(context, size))
2824 return 0;
2825 for (i = 0; i < size; i++) {
2826 PyObject *o = PyTuple_GET_ITEM(item, i);
2827 if (PyList_Check(o) || PyTuple_Check(o)) {
2828 if (!_flatten1(context, o, depth + 1))
2829 return 0;
2830 } else if (o != Py_None) {
2831 if (context->size + 1 > context->maxsize &&
2832 !_bump(context, 1))
2833 return 0;
2834 Py_INCREF(o);
2835 PyTuple_SET_ITEM(context->tuple,
2836 context->size++, o);
2839 } else {
2840 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2841 return 0;
2843 return 1;
2846 static PyObject *
2847 Tkinter_Flatten(PyObject* self, PyObject* args)
2849 FlattenContext context;
2850 PyObject* item;
2852 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2853 return NULL;
2855 context.maxsize = PySequence_Size(item);
2856 if (context.maxsize <= 0)
2857 return PyTuple_New(0);
2859 context.tuple = PyTuple_New(context.maxsize);
2860 if (!context.tuple)
2861 return NULL;
2863 context.size = 0;
2865 if (!_flatten1(&context, item,0))
2866 return NULL;
2868 if (_PyTuple_Resize(&context.tuple, context.size))
2869 return NULL;
2871 return context.tuple;
2874 static PyObject *
2875 Tkinter_Create(PyObject *self, PyObject *args)
2877 char *screenName = NULL;
2878 char *baseName = NULL;
2879 char *className = NULL;
2880 int interactive = 0;
2881 int wantobjects = 0;
2882 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2883 int sync = 0; /* pass -sync to wish */
2884 char *use = NULL; /* pass -use to wish */
2886 baseName = strrchr(Py_GetProgramName(), '/');
2887 if (baseName != NULL)
2888 baseName++;
2889 else
2890 baseName = Py_GetProgramName();
2891 className = "Tk";
2893 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2894 &screenName, &baseName, &className,
2895 &interactive, &wantobjects, &wantTk,
2896 &sync, &use))
2897 return NULL;
2899 return (PyObject *) Tkapp_New(screenName, baseName, className,
2900 interactive, wantobjects, wantTk,
2901 sync, use);
2904 static PyObject *
2905 Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2907 int new_val;
2908 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2909 return NULL;
2910 if (new_val < 0) {
2911 PyErr_SetString(PyExc_ValueError,
2912 "busywaitinterval must be >= 0");
2913 return NULL;
2915 Tkinter_busywaitinterval = new_val;
2916 Py_INCREF(Py_None);
2917 return Py_None;
2920 static char setbusywaitinterval_doc[] =
2921 "setbusywaitinterval(n) -> None\n\
2923 Set the busy-wait interval in milliseconds between successive\n\
2924 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2925 It should be set to a divisor of the maximum time between\n\
2926 frames in an animation.";
2928 static PyObject *
2929 Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2931 return PyInt_FromLong(Tkinter_busywaitinterval);
2934 static char getbusywaitinterval_doc[] =
2935 "getbusywaitinterval() -> int\n\
2937 Return the current busy-wait interval between successive\n\
2938 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2940 static PyMethodDef moduleMethods[] =
2942 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2943 {"create", Tkinter_Create, METH_VARARGS},
2944 #ifdef HAVE_CREATEFILEHANDLER
2945 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2946 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2947 #endif
2948 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2949 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2950 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2951 {"quit", Tkapp_Quit, METH_VARARGS},
2952 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2953 setbusywaitinterval_doc},
2954 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2955 METH_NOARGS, getbusywaitinterval_doc},
2956 {NULL, NULL}
2959 #ifdef WAIT_FOR_STDIN
2961 static int stdin_ready = 0;
2963 #ifndef MS_WINDOWS
2964 static void
2965 MyFileProc(void *clientData, int mask)
2967 stdin_ready = 1;
2969 #endif
2971 #ifdef WITH_THREAD
2972 static PyThreadState *event_tstate = NULL;
2973 #endif
2975 static int
2976 EventHook(void)
2978 #ifndef MS_WINDOWS
2979 int tfile;
2980 #endif
2981 #ifdef WITH_THREAD
2982 PyEval_RestoreThread(event_tstate);
2983 #endif
2984 stdin_ready = 0;
2985 errorInCmd = 0;
2986 #ifndef MS_WINDOWS
2987 tfile = fileno(stdin);
2988 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
2989 #endif
2990 while (!errorInCmd && !stdin_ready) {
2991 int result;
2992 #ifdef MS_WINDOWS
2993 if (_kbhit()) {
2994 stdin_ready = 1;
2995 break;
2997 #endif
2998 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
2999 Py_BEGIN_ALLOW_THREADS
3000 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3001 tcl_tstate = event_tstate;
3003 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3005 tcl_tstate = NULL;
3006 if(tcl_lock)PyThread_release_lock(tcl_lock);
3007 if (result == 0)
3008 Sleep(Tkinter_busywaitinterval);
3009 Py_END_ALLOW_THREADS
3010 #else
3011 result = Tcl_DoOneEvent(0);
3012 #endif
3014 if (result < 0)
3015 break;
3017 #ifndef MS_WINDOWS
3018 Tcl_DeleteFileHandler(tfile);
3019 #endif
3020 if (errorInCmd) {
3021 errorInCmd = 0;
3022 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3023 excInCmd = valInCmd = trbInCmd = NULL;
3024 PyErr_Print();
3026 #ifdef WITH_THREAD
3027 PyEval_SaveThread();
3028 #endif
3029 return 0;
3032 #endif
3034 static void
3035 EnableEventHook(void)
3037 #ifdef WAIT_FOR_STDIN
3038 if (PyOS_InputHook == NULL) {
3039 #ifdef WITH_THREAD
3040 event_tstate = PyThreadState_Get();
3041 #endif
3042 PyOS_InputHook = EventHook;
3044 #endif
3047 static void
3048 DisableEventHook(void)
3050 #ifdef WAIT_FOR_STDIN
3051 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3052 PyOS_InputHook = NULL;
3054 #endif
3058 /* all errors will be checked in one fell swoop in init_tkinter() */
3059 static void
3060 ins_long(PyObject *d, char *name, long val)
3062 PyObject *v = PyInt_FromLong(val);
3063 if (v) {
3064 PyDict_SetItemString(d, name, v);
3065 Py_DECREF(v);
3068 static void
3069 ins_string(PyObject *d, char *name, char *val)
3071 PyObject *v = PyString_FromString(val);
3072 if (v) {
3073 PyDict_SetItemString(d, name, v);
3074 Py_DECREF(v);
3079 PyMODINIT_FUNC
3080 init_tkinter(void)
3082 PyObject *m, *d;
3084 Tkapp_Type.ob_type = &PyType_Type;
3086 #ifdef WITH_THREAD
3087 tcl_lock = PyThread_allocate_lock();
3088 #endif
3090 m = Py_InitModule("_tkinter", moduleMethods);
3091 if (m == NULL)
3092 return;
3094 d = PyModule_GetDict(m);
3095 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3096 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3098 ins_long(d, "READABLE", TCL_READABLE);
3099 ins_long(d, "WRITABLE", TCL_WRITABLE);
3100 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3101 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3102 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3103 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3104 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3105 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3106 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3107 ins_string(d, "TK_VERSION", TK_VERSION);
3108 ins_string(d, "TCL_VERSION", TCL_VERSION);
3110 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3112 Tktt_Type.ob_type = &PyType_Type;
3113 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3115 PyTclObject_Type.ob_type = &PyType_Type;
3116 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3118 #ifdef TK_AQUA
3119 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3120 * start waking up. Note that Tcl_FindExecutable will do this, this
3121 * code must be above it! The original warning from
3122 * tkMacOSXAppInit.c is copied below.
3124 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3125 * Tcl interpreter for now. It probably should work to do this
3126 * in the other order, but for now it doesn't seem to.
3129 Tk_MacOSXSetupTkNotifier();
3130 #endif
3133 /* This helps the dynamic loader; in Unicode aware Tcl versions
3134 it also helps Tcl find its encodings. */
3135 Tcl_FindExecutable(Py_GetProgramName());
3137 if (PyErr_Occurred())
3138 return;
3140 #if 0
3141 /* This was not a good idea; through <Destroy> bindings,
3142 Tcl_Finalize() may invoke Python code but at that point the
3143 interpreter and thread state have already been destroyed! */
3144 Py_AtExit(Tcl_Finalize);
3145 #endif