Remove tuple parameter unpacking in aifc to silence warnings under -3.
[python.git] / Modules / _tkinter.c
blobf101450de3627aec5811a26901bf8a5a5fdd5ef4
1 /***********************************************************
2 Copyright (C) 1994 Steen Lumholt.
4 All Rights Reserved
6 ******************************************************************/
8 /* _tkinter.c -- Interface to libtk.a and libtcl.a. */
10 /* TCL/TK VERSION INFO:
12 Only Tcl/Tk 8.2 and later are supported. Older versions are not
13 supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk
14 libraries.)
17 /* XXX Further speed-up ideas, involving Tcl 8.0 features:
19 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
25 #include "Python.h"
26 #include <ctype.h>
28 #ifdef WITH_THREAD
29 #include "pythread.h"
30 #endif
32 #ifdef MS_WINDOWS
33 #include <windows.h>
34 #endif
36 /* Allow using this code in Python 2.[12] */
37 #ifndef PyDoc_STRVAR
38 #define PyDoc_STRVAR(name,str) static char name[] = str
39 #endif
41 #ifndef PyMODINIT_FUNC
42 #define PyMODINIT_FUNC void
43 #endif
45 #ifndef PyBool_Check
46 #define PyBool_Check(o) 0
47 #define PyBool_FromLong PyInt_FromLong
48 #endif
50 /* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55 #define USE_COMPAT_CONST
57 /* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
59 Tcl are empty. */
60 #define TCL_THREADS
62 #ifdef TK_FRAMEWORK
63 #include <Tcl/tcl.h>
64 #include <Tk/tk.h>
65 #else
66 #include <tcl.h>
67 #include <tk.h>
68 #endif
70 /* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
71 #ifndef CONST84_RETURN
72 #define CONST84_RETURN
73 #undef CONST
74 #define CONST
75 #endif
77 #define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
79 #if TKMAJORMINOR < 8002
80 #error "Tk older than 8.2 not supported"
81 #endif
83 /* Unicode conversion assumes that Tcl_UniChar is two bytes.
84 We cannot test this directly, so we test UTF-8 size instead,
85 expecting that TCL_UTF_MAX is changed if Tcl ever supports
86 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
88 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
89 as well.
91 #if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
92 #error "unsupported Tcl configuration"
93 #endif
95 #if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
96 #define HAVE_CREATEFILEHANDLER
97 #endif
99 #ifdef HAVE_CREATEFILEHANDLER
101 /* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
102 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
103 #ifndef TCL_UNIX_FD
104 # ifdef TCL_WIN_SOCKET
105 # define TCL_UNIX_FD (! TCL_WIN_SOCKET)
106 # else
107 # define TCL_UNIX_FD 1
108 # endif
109 #endif
111 /* Tcl_CreateFileHandler() changed several times; these macros deal with the
112 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
113 Unix, only because Jack added it back); when available on Windows, it only
114 applies to sockets. */
116 #ifdef MS_WINDOWS
117 #define FHANDLETYPE TCL_WIN_SOCKET
118 #else
119 #define FHANDLETYPE TCL_UNIX_FD
120 #endif
122 /* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
123 which uses this to handle Tcl events while the user is typing commands. */
125 #if FHANDLETYPE == TCL_UNIX_FD
126 #define WAIT_FOR_STDIN
127 #endif
129 #endif /* HAVE_CREATEFILEHANDLER */
131 #ifdef MS_WINDOWS
132 #include <conio.h>
133 #define WAIT_FOR_STDIN
134 #endif
136 #ifdef WITH_THREAD
138 /* The threading situation is complicated. Tcl is not thread-safe, except
139 when configured with --enable-threads.
140 So we need to use a lock around all uses of Tcl. Previously, the Python
141 interpreter lock was used for this. However, this causes problems when
142 other Python threads need to run while Tcl is blocked waiting for events.
144 To solve this problem, a separate lock for Tcl is introduced. Holding it
145 is incompatible with holding Python's interpreter lock. The following four
146 macros manipulate both locks together.
148 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
149 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
150 that could call an event handler, or otherwise affect the state of a Tcl
151 interpreter. These assume that the surrounding code has the Python
152 interpreter lock; inside the brackets, the Python interpreter lock has been
153 released and the lock for Tcl has been acquired.
155 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
156 (For example, when transferring data from the Tcl interpreter result to a
157 Python string object.) This can be done by using different macros to close
158 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
159 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
160 releases the Tcl lock.
162 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
163 handlers when the handler needs to use Python. Such event handlers are
164 entered while the lock for Tcl is held; the event handler presumably needs
165 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
166 the Python interpreter lock, restoring the appropriate thread state, and
167 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
168 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
169 the code between ENTER_PYTHON and LEAVE_PYTHON.
171 These locks expand to several statements and brackets; they should not be
172 used in branches of if statements and the like.
174 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
175 only valid in the thread that created it, and all Tk activity must happen in this
176 thread, also. That means that the mainloop must be invoked in the thread that
177 created the interpreter. Invoking commands from other threads is possible;
178 _tkinter will queue an event for the interpreter thread, which will then
179 execute the command and pass back the result. If the main thread is not in the
180 mainloop, and invoking commands causes an exception; if the main loop is running
181 but not processing events, the command invocation will block.
183 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
184 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
185 threads. So we use the Tcl TLS API.
189 static PyThread_type_lock tcl_lock = 0;
191 #ifdef TCL_THREADS
192 static Tcl_ThreadDataKey state_key;
193 typedef PyThreadState *ThreadSpecificData;
194 #define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
195 #else
196 static PyThreadState *tcl_tstate = NULL;
197 #endif
199 #define ENTER_TCL \
200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
203 #define LEAVE_TCL \
204 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
206 #define ENTER_OVERLAP \
207 Py_END_ALLOW_THREADS
209 #define LEAVE_OVERLAP_TCL \
210 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
212 #define ENTER_PYTHON \
213 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
214 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
216 #define LEAVE_PYTHON \
217 { PyThreadState *tstate = PyEval_SaveThread(); \
218 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
220 #define CHECK_TCL_APPARTMENT \
221 if (((TkappObject *)self)->threaded && \
222 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
223 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
224 return 0; \
227 #else
229 #define ENTER_TCL
230 #define LEAVE_TCL
231 #define ENTER_OVERLAP
232 #define LEAVE_OVERLAP_TCL
233 #define ENTER_PYTHON
234 #define LEAVE_PYTHON
235 #define CHECK_TCL_APPARTMENT
237 #endif
239 #ifndef FREECAST
240 #define FREECAST (char *)
241 #endif
243 /**** Tkapp Object Declaration ****/
245 static PyTypeObject Tkapp_Type;
247 typedef struct {
248 PyObject_HEAD
249 Tcl_Interp *interp;
250 int wantobjects;
251 int threaded; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id;
253 int dispatching;
254 /* We cannot include tclInt.h, as this is internal.
255 So we cache interesting types here. */
256 Tcl_ObjType *BooleanType;
257 Tcl_ObjType *ByteArrayType;
258 Tcl_ObjType *DoubleType;
259 Tcl_ObjType *IntType;
260 Tcl_ObjType *ListType;
261 Tcl_ObjType *ProcBodyType;
262 Tcl_ObjType *StringType;
263 } TkappObject;
265 #define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
266 #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
267 #define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
269 #define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
270 (void *) v, Py_REFCNT(v)))
274 /**** Error Handling ****/
276 static PyObject *Tkinter_TclError;
277 static int quitMainLoop = 0;
278 static int errorInCmd = 0;
279 static PyObject *excInCmd;
280 static PyObject *valInCmd;
281 static PyObject *trbInCmd;
285 static PyObject *
286 Tkinter_Error(PyObject *v)
288 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
289 return NULL;
294 /**** Utils ****/
296 static int Tkinter_busywaitinterval = 20;
298 #ifdef WITH_THREAD
299 #ifndef MS_WINDOWS
301 /* Millisecond sleep() for Unix platforms. */
303 static void
304 Sleep(int milli)
306 /* XXX Too bad if you don't have select(). */
307 struct timeval t;
308 t.tv_sec = milli/1000;
309 t.tv_usec = (milli%1000) * 1000;
310 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
312 #endif /* MS_WINDOWS */
314 /* Wait up to 1s for the mainloop to come up. */
316 static int
317 WaitForMainloop(TkappObject* self)
319 int i;
320 for (i = 0; i < 10; i++) {
321 if (self->dispatching)
322 return 1;
323 Py_BEGIN_ALLOW_THREADS
324 Sleep(100);
325 Py_END_ALLOW_THREADS
327 if (self->dispatching)
328 return 1;
329 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
330 return 0;
332 #endif /* WITH_THREAD */
335 static char *
336 AsString(PyObject *value, PyObject *tmp)
338 if (PyString_Check(value))
339 return PyString_AsString(value);
340 #ifdef Py_USING_UNICODE
341 else if (PyUnicode_Check(value)) {
342 PyObject *v = PyUnicode_AsUTF8String(value);
343 if (v == NULL)
344 return NULL;
345 if (PyList_Append(tmp, v) != 0) {
346 Py_DECREF(v);
347 return NULL;
349 Py_DECREF(v);
350 return PyString_AsString(v);
352 #endif
353 else {
354 PyObject *v = PyObject_Str(value);
355 if (v == NULL)
356 return NULL;
357 if (PyList_Append(tmp, v) != 0) {
358 Py_DECREF(v);
359 return NULL;
361 Py_DECREF(v);
362 return PyString_AsString(v);
368 #define ARGSZ 64
370 static char *
371 Merge(PyObject *args)
373 PyObject *tmp = NULL;
374 char *argvStore[ARGSZ];
375 char **argv = NULL;
376 int fvStore[ARGSZ];
377 int *fv = NULL;
378 int argc = 0, fvc = 0, i;
379 char *res = NULL;
381 if (!(tmp = PyList_New(0)))
382 return NULL;
384 argv = argvStore;
385 fv = fvStore;
387 if (args == NULL)
388 argc = 0;
390 else if (!PyTuple_Check(args)) {
391 argc = 1;
392 fv[0] = 0;
393 if (!(argv[0] = AsString(args, tmp)))
394 goto finally;
396 else {
397 argc = PyTuple_Size(args);
399 if (argc > ARGSZ) {
400 argv = (char **)ckalloc(argc * sizeof(char *));
401 fv = (int *)ckalloc(argc * sizeof(int));
402 if (argv == NULL || fv == NULL) {
403 PyErr_NoMemory();
404 goto finally;
408 for (i = 0; i < argc; i++) {
409 PyObject *v = PyTuple_GetItem(args, i);
410 if (PyTuple_Check(v)) {
411 fv[i] = 1;
412 if (!(argv[i] = Merge(v)))
413 goto finally;
414 fvc++;
416 else if (v == Py_None) {
417 argc = i;
418 break;
420 else {
421 fv[i] = 0;
422 if (!(argv[i] = AsString(v, tmp)))
423 goto finally;
424 fvc++;
428 res = Tcl_Merge(argc, argv);
429 if (res == NULL)
430 PyErr_SetString(Tkinter_TclError, "merge failed");
432 finally:
433 for (i = 0; i < fvc; i++)
434 if (fv[i]) {
435 ckfree(argv[i]);
437 if (argv != argvStore)
438 ckfree(FREECAST argv);
439 if (fv != fvStore)
440 ckfree(FREECAST fv);
442 Py_DECREF(tmp);
443 return res;
448 static PyObject *
449 Split(char *list)
451 int argc;
452 char **argv;
453 PyObject *v;
455 if (list == NULL) {
456 Py_INCREF(Py_None);
457 return Py_None;
460 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
461 /* Not a list.
462 * Could be a quoted string containing funnies, e.g. {"}.
463 * Return the string itself.
465 return PyString_FromString(list);
468 if (argc == 0)
469 v = PyString_FromString("");
470 else if (argc == 1)
471 v = PyString_FromString(argv[0]);
472 else if ((v = PyTuple_New(argc)) != NULL) {
473 int i;
474 PyObject *w;
476 for (i = 0; i < argc; i++) {
477 if ((w = Split(argv[i])) == NULL) {
478 Py_DECREF(v);
479 v = NULL;
480 break;
482 PyTuple_SetItem(v, i, w);
485 Tcl_Free(FREECAST argv);
486 return v;
489 /* In some cases, Tcl will still return strings that are supposed to be
490 lists. SplitObj walks through a nested tuple, finding string objects that
491 need to be split. */
493 static 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 = NULL;
940 Py_ssize_t i;
941 size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
942 if (allocsize >= size)
943 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
944 /* Else overflow occurred, and we take the next exit */
945 if (!outbuf) {
946 PyErr_NoMemory();
947 return NULL;
949 for (i = 0; i < size; i++) {
950 if (inbuf[i] >= 0x10000) {
951 /* Tcl doesn't do UTF-16, yet. */
952 PyErr_SetString(PyExc_ValueError,
953 "unsupported character");
954 ckfree(FREECAST outbuf);
955 return NULL;
957 outbuf[i] = inbuf[i];
959 result = Tcl_NewUnicodeObj(outbuf, size);
960 ckfree(FREECAST outbuf);
961 return result;
962 #else
963 return Tcl_NewUnicodeObj(inbuf, size);
964 #endif
967 #endif
968 else if(PyTclObject_Check(value)) {
969 Tcl_Obj *v = ((PyTclObject*)value)->value;
970 Tcl_IncrRefCount(v);
971 return v;
973 else {
974 PyObject *v = PyObject_Str(value);
975 if (!v)
976 return 0;
977 result = AsObj(v);
978 Py_DECREF(v);
979 return result;
983 static PyObject*
984 FromObj(PyObject* tkapp, Tcl_Obj *value)
986 PyObject *result = NULL;
987 TkappObject *app = (TkappObject*)tkapp;
989 if (value->typePtr == NULL) {
990 /* If the result contains any bytes with the top bit set,
991 it's UTF-8 and we should decode it to Unicode */
992 #ifdef Py_USING_UNICODE
993 int i;
994 char *s = value->bytes;
995 int len = value->length;
996 for (i = 0; i < len; i++) {
997 if (value->bytes[i] & 0x80)
998 break;
1001 if (i == value->length)
1002 result = PyString_FromStringAndSize(s, len);
1003 else {
1004 /* Convert UTF-8 to Unicode string */
1005 result = PyUnicode_DecodeUTF8(s, len, "strict");
1006 if (result == NULL) {
1007 PyErr_Clear();
1008 result = PyString_FromStringAndSize(s, len);
1011 #else
1012 result = PyString_FromStringAndSize(value->bytes, value->length);
1013 #endif
1014 return result;
1017 if (value->typePtr == app->BooleanType) {
1018 result = value->internalRep.longValue ? Py_True : Py_False;
1019 Py_INCREF(result);
1020 return result;
1023 if (value->typePtr == app->ByteArrayType) {
1024 int size;
1025 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1026 return PyString_FromStringAndSize(data, size);
1029 if (value->typePtr == app->DoubleType) {
1030 return PyFloat_FromDouble(value->internalRep.doubleValue);
1033 if (value->typePtr == app->IntType) {
1034 return PyInt_FromLong(value->internalRep.longValue);
1037 if (value->typePtr == app->ListType) {
1038 int size;
1039 int i, status;
1040 PyObject *elem;
1041 Tcl_Obj *tcl_elem;
1043 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1044 if (status == TCL_ERROR)
1045 return Tkinter_Error(tkapp);
1046 result = PyTuple_New(size);
1047 if (!result)
1048 return NULL;
1049 for (i = 0; i < size; i++) {
1050 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1051 value, i, &tcl_elem);
1052 if (status == TCL_ERROR) {
1053 Py_DECREF(result);
1054 return Tkinter_Error(tkapp);
1056 elem = FromObj(tkapp, tcl_elem);
1057 if (!elem) {
1058 Py_DECREF(result);
1059 return NULL;
1061 PyTuple_SetItem(result, i, elem);
1063 return result;
1066 if (value->typePtr == app->ProcBodyType) {
1067 /* fall through: return tcl object. */
1070 if (value->typePtr == app->StringType) {
1071 #ifdef Py_USING_UNICODE
1072 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1073 PyObject *result;
1074 int size;
1075 Tcl_UniChar *input;
1076 Py_UNICODE *output;
1078 size = Tcl_GetCharLength(value);
1079 result = PyUnicode_FromUnicode(NULL, size);
1080 if (!result)
1081 return NULL;
1082 input = Tcl_GetUnicode(value);
1083 output = PyUnicode_AS_UNICODE(result);
1084 while (size--)
1085 *output++ = *input++;
1086 return result;
1087 #else
1088 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1089 Tcl_GetCharLength(value));
1090 #endif
1091 #else
1092 int size;
1093 char *c;
1094 c = Tcl_GetStringFromObj(value, &size);
1095 return PyString_FromStringAndSize(c, size);
1096 #endif
1099 return newPyTclObject(value);
1102 /* This mutex synchronizes inter-thread command calls. */
1104 TCL_DECLARE_MUTEX(call_mutex)
1106 typedef struct Tkapp_CallEvent {
1107 Tcl_Event ev; /* Must be first */
1108 TkappObject *self;
1109 PyObject *args;
1110 int flags;
1111 PyObject **res;
1112 PyObject **exc_type, **exc_value, **exc_tb;
1113 Tcl_Condition done;
1114 } Tkapp_CallEvent;
1116 void
1117 Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
1119 int i;
1120 for (i = 0; i < objc; i++)
1121 Tcl_DecrRefCount(objv[i]);
1122 if (objv != objStore)
1123 ckfree(FREECAST objv);
1126 /* Convert Python objects to Tcl objects. This must happen in the
1127 interpreter thread, which may or may not be the calling thread. */
1129 static Tcl_Obj**
1130 Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1132 Tcl_Obj **objv = objStore;
1133 int objc = 0, i;
1134 if (args == NULL)
1135 /* do nothing */;
1137 else if (!PyTuple_Check(args)) {
1138 objv[0] = AsObj(args);
1139 if (objv[0] == 0)
1140 goto finally;
1141 objc = 1;
1142 Tcl_IncrRefCount(objv[0]);
1144 else {
1145 objc = PyTuple_Size(args);
1147 if (objc > ARGSZ) {
1148 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1149 if (objv == NULL) {
1150 PyErr_NoMemory();
1151 objc = 0;
1152 goto finally;
1156 for (i = 0; i < objc; i++) {
1157 PyObject *v = PyTuple_GetItem(args, i);
1158 if (v == Py_None) {
1159 objc = i;
1160 break;
1162 objv[i] = AsObj(v);
1163 if (!objv[i]) {
1164 /* Reset objc, so it attempts to clear
1165 objects only up to i. */
1166 objc = i;
1167 goto finally;
1169 Tcl_IncrRefCount(objv[i]);
1172 *pobjc = objc;
1173 return objv;
1174 finally:
1175 Tkapp_CallDeallocArgs(objv, objStore, objc);
1176 return NULL;
1179 /* Convert the results of a command call into a Python objects. */
1181 static PyObject*
1182 Tkapp_CallResult(TkappObject *self)
1184 PyObject *res = NULL;
1185 if(self->wantobjects) {
1186 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1187 /* Not sure whether the IncrRef is necessary, but something
1188 may overwrite the interpreter result while we are
1189 converting it. */
1190 Tcl_IncrRefCount(value);
1191 res = FromObj((PyObject*)self, value);
1192 Tcl_DecrRefCount(value);
1193 } else {
1194 const char *s = Tcl_GetStringResult(self->interp);
1195 const char *p = s;
1197 /* If the result contains any bytes with the top bit set,
1198 it's UTF-8 and we should decode it to Unicode */
1199 #ifdef Py_USING_UNICODE
1200 while (*p != '\0') {
1201 if (*p & 0x80)
1202 break;
1203 p++;
1206 if (*p == '\0')
1207 res = PyString_FromStringAndSize(s, (int)(p-s));
1208 else {
1209 /* Convert UTF-8 to Unicode string */
1210 p = strchr(p, '\0');
1211 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1212 if (res == NULL) {
1213 PyErr_Clear();
1214 res = PyString_FromStringAndSize(s, (int)(p-s));
1217 #else
1218 p = strchr(p, '\0');
1219 res = PyString_FromStringAndSize(s, (int)(p-s));
1220 #endif
1222 return res;
1225 /* Tkapp_CallProc is the event procedure that is executed in the context of
1226 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1227 hold the Python lock. */
1229 static int
1230 Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1232 Tcl_Obj *objStore[ARGSZ];
1233 Tcl_Obj **objv;
1234 int objc;
1235 int i;
1236 ENTER_PYTHON
1237 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1238 if (!objv) {
1239 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1240 *(e->res) = NULL;
1242 LEAVE_PYTHON
1243 if (!objv)
1244 goto done;
1245 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1246 ENTER_PYTHON
1247 if (i == TCL_ERROR) {
1248 *(e->res) = NULL;
1249 *(e->exc_type) = NULL;
1250 *(e->exc_tb) = NULL;
1251 *(e->exc_value) = PyObject_CallFunction(
1252 Tkinter_TclError, "s",
1253 Tcl_GetStringResult(e->self->interp));
1255 else {
1256 *(e->res) = Tkapp_CallResult(e->self);
1258 LEAVE_PYTHON
1259 done:
1260 /* Wake up calling thread. */
1261 Tcl_MutexLock(&call_mutex);
1262 Tcl_ConditionNotify(&e->done);
1263 Tcl_MutexUnlock(&call_mutex);
1264 return 1;
1267 /* This is the main entry point for calling a Tcl command.
1268 It supports three cases, with regard to threading:
1269 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1270 the context of the calling thread.
1271 2. Tcl is threaded, caller of the command is in the interpreter thread:
1272 Execute the command in the calling thread. Since the Tcl lock will
1273 not be used, we can merge that with case 1.
1274 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1275 the interpreter thread. Allocation of Tcl objects needs to occur in the
1276 interpreter thread, so we ship the PyObject* args to the target thread,
1277 and perform processing there. */
1279 static PyObject *
1280 Tkapp_Call(PyObject *selfptr, PyObject *args)
1282 Tcl_Obj *objStore[ARGSZ];
1283 Tcl_Obj **objv = NULL;
1284 int objc, i;
1285 PyObject *res = NULL;
1286 TkappObject *self = (TkappObject*)selfptr;
1287 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1288 int flags = TCL_EVAL_DIRECT;
1290 /* If args is a single tuple, replace with contents of tuple */
1291 if (1 == PyTuple_Size(args)){
1292 PyObject* item = PyTuple_GetItem(args, 0);
1293 if (PyTuple_Check(item))
1294 args = item;
1296 #ifdef WITH_THREAD
1297 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1298 /* We cannot call the command directly. Instead, we must
1299 marshal the parameters to the interpreter thread. */
1300 Tkapp_CallEvent *ev;
1301 PyObject *exc_type, *exc_value, *exc_tb;
1302 if (!WaitForMainloop(self))
1303 return NULL;
1304 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1305 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1306 ev->self = self;
1307 ev->args = args;
1308 ev->res = &res;
1309 ev->exc_type = &exc_type;
1310 ev->exc_value = &exc_value;
1311 ev->exc_tb = &exc_tb;
1312 ev->done = (Tcl_Condition)0;
1314 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1316 if (res == NULL) {
1317 if (exc_type)
1318 PyErr_Restore(exc_type, exc_value, exc_tb);
1319 else
1320 PyErr_SetObject(Tkinter_TclError, exc_value);
1323 else
1324 #endif
1327 objv = Tkapp_CallArgs(args, objStore, &objc);
1328 if (!objv)
1329 return NULL;
1331 ENTER_TCL
1333 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1335 ENTER_OVERLAP
1337 if (i == TCL_ERROR)
1338 Tkinter_Error(selfptr);
1339 else
1340 res = Tkapp_CallResult(self);
1342 LEAVE_OVERLAP_TCL
1344 Tkapp_CallDeallocArgs(objv, objStore, objc);
1346 return res;
1350 static PyObject *
1351 Tkapp_GlobalCall(PyObject *self, PyObject *args)
1353 /* Could do the same here as for Tkapp_Call(), but this is not used
1354 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1355 way for the user to do what all its Global* variants do (save and
1356 reset the scope pointer, call the local version, restore the saved
1357 scope pointer). */
1359 char *cmd;
1360 PyObject *res = NULL;
1362 CHECK_TCL_APPARTMENT;
1364 cmd = Merge(args);
1365 if (cmd) {
1366 int err;
1367 ENTER_TCL
1368 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1369 ENTER_OVERLAP
1370 if (err == TCL_ERROR)
1371 res = Tkinter_Error(self);
1372 else
1373 res = PyString_FromString(Tkapp_Result(self));
1374 LEAVE_OVERLAP_TCL
1375 ckfree(cmd);
1378 return res;
1381 static PyObject *
1382 Tkapp_Eval(PyObject *self, PyObject *args)
1384 char *script;
1385 PyObject *res = NULL;
1386 int err;
1388 if (!PyArg_ParseTuple(args, "s:eval", &script))
1389 return NULL;
1391 CHECK_TCL_APPARTMENT;
1393 ENTER_TCL
1394 err = Tcl_Eval(Tkapp_Interp(self), script);
1395 ENTER_OVERLAP
1396 if (err == TCL_ERROR)
1397 res = Tkinter_Error(self);
1398 else
1399 res = PyString_FromString(Tkapp_Result(self));
1400 LEAVE_OVERLAP_TCL
1401 return res;
1404 static PyObject *
1405 Tkapp_GlobalEval(PyObject *self, PyObject *args)
1407 char *script;
1408 PyObject *res = NULL;
1409 int err;
1411 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1412 return NULL;
1414 CHECK_TCL_APPARTMENT;
1416 ENTER_TCL
1417 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1418 ENTER_OVERLAP
1419 if (err == TCL_ERROR)
1420 res = Tkinter_Error(self);
1421 else
1422 res = PyString_FromString(Tkapp_Result(self));
1423 LEAVE_OVERLAP_TCL
1424 return res;
1427 static PyObject *
1428 Tkapp_EvalFile(PyObject *self, PyObject *args)
1430 char *fileName;
1431 PyObject *res = NULL;
1432 int err;
1434 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1435 return NULL;
1437 CHECK_TCL_APPARTMENT;
1439 ENTER_TCL
1440 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1441 ENTER_OVERLAP
1442 if (err == TCL_ERROR)
1443 res = Tkinter_Error(self);
1445 else
1446 res = PyString_FromString(Tkapp_Result(self));
1447 LEAVE_OVERLAP_TCL
1448 return res;
1451 static PyObject *
1452 Tkapp_Record(PyObject *self, PyObject *args)
1454 char *script;
1455 PyObject *res = NULL;
1456 int err;
1458 if (!PyArg_ParseTuple(args, "s", &script))
1459 return NULL;
1461 CHECK_TCL_APPARTMENT;
1463 ENTER_TCL
1464 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1465 ENTER_OVERLAP
1466 if (err == TCL_ERROR)
1467 res = Tkinter_Error(self);
1468 else
1469 res = PyString_FromString(Tkapp_Result(self));
1470 LEAVE_OVERLAP_TCL
1471 return res;
1474 static PyObject *
1475 Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
1477 char *msg;
1479 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1480 return NULL;
1481 CHECK_TCL_APPARTMENT;
1483 ENTER_TCL
1484 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1485 LEAVE_TCL
1487 Py_INCREF(Py_None);
1488 return Py_None;
1493 /** Tcl Variable **/
1495 TCL_DECLARE_MUTEX(var_mutex)
1497 typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1498 typedef struct VarEvent {
1499 Tcl_Event ev; /* must be first */
1500 PyObject *self;
1501 PyObject *args;
1502 int flags;
1503 EventFunc func;
1504 PyObject **res;
1505 PyObject **exc_type;
1506 PyObject **exc_val;
1507 Tcl_Condition cond;
1508 } VarEvent;
1510 static int
1511 varname_converter(PyObject *in, void *_out)
1513 char **out = (char**)_out;
1514 if (PyString_Check(in)) {
1515 *out = PyString_AsString(in);
1516 return 1;
1518 if (PyTclObject_Check(in)) {
1519 *out = PyTclObject_TclString(in);
1520 return 1;
1522 /* XXX: Should give diagnostics. */
1523 return 0;
1526 static void
1527 var_perform(VarEvent *ev)
1529 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1530 if (!*(ev->res)) {
1531 PyObject *exc, *val, *tb;
1532 PyErr_Fetch(&exc, &val, &tb);
1533 PyErr_NormalizeException(&exc, &val, &tb);
1534 *(ev->exc_type) = exc;
1535 *(ev->exc_val) = val;
1536 Py_DECREF(tb);
1541 static int
1542 var_proc(VarEvent* ev, int flags)
1544 ENTER_PYTHON
1545 var_perform(ev);
1546 Tcl_MutexLock(&var_mutex);
1547 Tcl_ConditionNotify(&ev->cond);
1548 Tcl_MutexUnlock(&var_mutex);
1549 LEAVE_PYTHON
1550 return 1;
1553 static PyObject*
1554 var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
1556 TkappObject *self = (TkappObject*)selfptr;
1557 #ifdef WITH_THREAD
1558 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1559 TkappObject *self = (TkappObject*)selfptr;
1560 VarEvent *ev;
1561 PyObject *res, *exc_type, *exc_val;
1563 /* The current thread is not the interpreter thread. Marshal
1564 the call to the interpreter thread, then wait for
1565 completion. */
1566 if (!WaitForMainloop(self))
1567 return NULL;
1569 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1571 ev->self = selfptr;
1572 ev->args = args;
1573 ev->flags = flags;
1574 ev->func = func;
1575 ev->res = &res;
1576 ev->exc_type = &exc_type;
1577 ev->exc_val = &exc_val;
1578 ev->cond = NULL;
1579 ev->ev.proc = (Tcl_EventProc*)var_proc;
1580 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1581 if (!res) {
1582 PyErr_SetObject(exc_type, exc_val);
1583 Py_DECREF(exc_type);
1584 Py_DECREF(exc_val);
1585 return NULL;
1587 return res;
1589 #endif
1590 /* Tcl is not threaded, or this is the interpreter thread. */
1591 return func(selfptr, args, flags);
1594 static PyObject *
1595 SetVar(PyObject *self, PyObject *args, int flags)
1597 char *name1, *name2;
1598 PyObject *newValue;
1599 PyObject *res = NULL;
1600 Tcl_Obj *newval, *ok;
1602 if (PyArg_ParseTuple(args, "O&O:setvar",
1603 varname_converter, &name1, &newValue)) {
1604 /* XXX Acquire tcl lock??? */
1605 newval = AsObj(newValue);
1606 if (newval == NULL)
1607 return NULL;
1608 ENTER_TCL
1609 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1610 newval, flags);
1611 ENTER_OVERLAP
1612 if (!ok)
1613 Tkinter_Error(self);
1614 else {
1615 res = Py_None;
1616 Py_INCREF(res);
1618 LEAVE_OVERLAP_TCL
1620 else {
1621 PyErr_Clear();
1622 if (PyArg_ParseTuple(args, "ssO:setvar",
1623 &name1, &name2, &newValue)) {
1624 /* XXX must hold tcl lock already??? */
1625 newval = AsObj(newValue);
1626 ENTER_TCL
1627 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1628 ENTER_OVERLAP
1629 if (!ok)
1630 Tkinter_Error(self);
1631 else {
1632 res = Py_None;
1633 Py_INCREF(res);
1635 LEAVE_OVERLAP_TCL
1637 else {
1638 return NULL;
1641 return res;
1644 static PyObject *
1645 Tkapp_SetVar(PyObject *self, PyObject *args)
1647 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1650 static PyObject *
1651 Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
1653 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1658 static PyObject *
1659 GetVar(PyObject *self, PyObject *args, int flags)
1661 char *name1, *name2=NULL;
1662 PyObject *res = NULL;
1663 Tcl_Obj *tres;
1665 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1666 varname_converter, &name1, &name2))
1667 return NULL;
1669 ENTER_TCL
1670 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1671 ENTER_OVERLAP
1672 if (tres == NULL) {
1673 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1674 } else {
1675 if (((TkappObject*)self)->wantobjects) {
1676 res = FromObj(self, tres);
1678 else {
1679 res = PyString_FromString(Tcl_GetString(tres));
1682 LEAVE_OVERLAP_TCL
1683 return res;
1686 static PyObject *
1687 Tkapp_GetVar(PyObject *self, PyObject *args)
1689 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1692 static PyObject *
1693 Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1695 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1700 static PyObject *
1701 UnsetVar(PyObject *self, PyObject *args, int flags)
1703 char *name1, *name2=NULL;
1704 int code;
1705 PyObject *res = NULL;
1707 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1708 return NULL;
1710 ENTER_TCL
1711 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1712 ENTER_OVERLAP
1713 if (code == TCL_ERROR)
1714 res = Tkinter_Error(self);
1715 else {
1716 Py_INCREF(Py_None);
1717 res = Py_None;
1719 LEAVE_OVERLAP_TCL
1720 return res;
1723 static PyObject *
1724 Tkapp_UnsetVar(PyObject *self, PyObject *args)
1726 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1729 static PyObject *
1730 Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1732 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1737 /** Tcl to Python **/
1739 static PyObject *
1740 Tkapp_GetInt(PyObject *self, PyObject *args)
1742 char *s;
1743 int v;
1745 if (PyTuple_Size(args) == 1) {
1746 PyObject* o = PyTuple_GetItem(args, 0);
1747 if (PyInt_Check(o)) {
1748 Py_INCREF(o);
1749 return o;
1752 if (!PyArg_ParseTuple(args, "s:getint", &s))
1753 return NULL;
1754 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1755 return Tkinter_Error(self);
1756 return Py_BuildValue("i", v);
1759 static PyObject *
1760 Tkapp_GetDouble(PyObject *self, PyObject *args)
1762 char *s;
1763 double v;
1765 if (PyTuple_Size(args) == 1) {
1766 PyObject *o = PyTuple_GetItem(args, 0);
1767 if (PyFloat_Check(o)) {
1768 Py_INCREF(o);
1769 return o;
1772 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1773 return NULL;
1774 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1775 return Tkinter_Error(self);
1776 return Py_BuildValue("d", v);
1779 static PyObject *
1780 Tkapp_GetBoolean(PyObject *self, PyObject *args)
1782 char *s;
1783 int v;
1785 if (PyTuple_Size(args) == 1) {
1786 PyObject *o = PyTuple_GetItem(args, 0);
1787 if (PyInt_Check(o)) {
1788 Py_INCREF(o);
1789 return o;
1792 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1793 return NULL;
1794 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1795 return Tkinter_Error(self);
1796 return PyBool_FromLong(v);
1799 static PyObject *
1800 Tkapp_ExprString(PyObject *self, PyObject *args)
1802 char *s;
1803 PyObject *res = NULL;
1804 int retval;
1806 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1807 return NULL;
1809 CHECK_TCL_APPARTMENT;
1811 ENTER_TCL
1812 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1813 ENTER_OVERLAP
1814 if (retval == TCL_ERROR)
1815 res = Tkinter_Error(self);
1816 else
1817 res = Py_BuildValue("s", Tkapp_Result(self));
1818 LEAVE_OVERLAP_TCL
1819 return res;
1822 static PyObject *
1823 Tkapp_ExprLong(PyObject *self, PyObject *args)
1825 char *s;
1826 PyObject *res = NULL;
1827 int retval;
1828 long v;
1830 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1831 return NULL;
1833 CHECK_TCL_APPARTMENT;
1835 ENTER_TCL
1836 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1837 ENTER_OVERLAP
1838 if (retval == TCL_ERROR)
1839 res = Tkinter_Error(self);
1840 else
1841 res = Py_BuildValue("l", v);
1842 LEAVE_OVERLAP_TCL
1843 return res;
1846 static PyObject *
1847 Tkapp_ExprDouble(PyObject *self, PyObject *args)
1849 char *s;
1850 PyObject *res = NULL;
1851 double v;
1852 int retval;
1854 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1855 return NULL;
1856 CHECK_TCL_APPARTMENT;
1857 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1858 ENTER_TCL
1859 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1860 ENTER_OVERLAP
1861 PyFPE_END_PROTECT(retval)
1862 if (retval == TCL_ERROR)
1863 res = Tkinter_Error(self);
1864 else
1865 res = Py_BuildValue("d", v);
1866 LEAVE_OVERLAP_TCL
1867 return res;
1870 static PyObject *
1871 Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1873 char *s;
1874 PyObject *res = NULL;
1875 int retval;
1876 int v;
1878 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1879 return NULL;
1880 CHECK_TCL_APPARTMENT;
1881 ENTER_TCL
1882 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1883 ENTER_OVERLAP
1884 if (retval == TCL_ERROR)
1885 res = Tkinter_Error(self);
1886 else
1887 res = Py_BuildValue("i", v);
1888 LEAVE_OVERLAP_TCL
1889 return res;
1894 static PyObject *
1895 Tkapp_SplitList(PyObject *self, PyObject *args)
1897 char *list;
1898 int argc;
1899 char **argv;
1900 PyObject *v;
1901 int i;
1903 if (PyTuple_Size(args) == 1) {
1904 v = PyTuple_GetItem(args, 0);
1905 if (PyTuple_Check(v)) {
1906 Py_INCREF(v);
1907 return v;
1910 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1911 return NULL;
1913 if (Tcl_SplitList(Tkapp_Interp(self), list,
1914 &argc, &argv) == TCL_ERROR) {
1915 PyMem_Free(list);
1916 return Tkinter_Error(self);
1919 if (!(v = PyTuple_New(argc)))
1920 goto finally;
1922 for (i = 0; i < argc; i++) {
1923 PyObject *s = PyString_FromString(argv[i]);
1924 if (!s || PyTuple_SetItem(v, i, s)) {
1925 Py_DECREF(v);
1926 v = NULL;
1927 goto finally;
1931 finally:
1932 ckfree(FREECAST argv);
1933 PyMem_Free(list);
1934 return v;
1937 static PyObject *
1938 Tkapp_Split(PyObject *self, PyObject *args)
1940 PyObject *v;
1941 char *list;
1943 if (PyTuple_Size(args) == 1) {
1944 PyObject* o = PyTuple_GetItem(args, 0);
1945 if (PyTuple_Check(o)) {
1946 o = SplitObj(o);
1947 return o;
1950 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1951 return NULL;
1952 v = Split(list);
1953 PyMem_Free(list);
1954 return v;
1957 static PyObject *
1958 Tkapp_Merge(PyObject *self, PyObject *args)
1960 char *s = Merge(args);
1961 PyObject *res = NULL;
1963 if (s) {
1964 res = PyString_FromString(s);
1965 ckfree(s);
1968 return res;
1973 /** Tcl Command **/
1975 /* Client data struct */
1976 typedef struct {
1977 PyObject *self;
1978 PyObject *func;
1979 } PythonCmd_ClientData;
1981 static int
1982 PythonCmd_Error(Tcl_Interp *interp)
1984 errorInCmd = 1;
1985 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1986 LEAVE_PYTHON
1987 return TCL_ERROR;
1990 /* This is the Tcl command that acts as a wrapper for Python
1991 * function or method.
1993 static int
1994 PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1996 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1997 PyObject *self, *func, *arg, *res;
1998 int i, rv;
1999 Tcl_Obj *obj_res;
2001 ENTER_PYTHON
2003 /* TBD: no error checking here since we know, via the
2004 * Tkapp_CreateCommand() that the client data is a two-tuple
2006 self = data->self;
2007 func = data->func;
2009 /* Create argument list (argv1, ..., argvN) */
2010 if (!(arg = PyTuple_New(argc - 1)))
2011 return PythonCmd_Error(interp);
2013 for (i = 0; i < (argc - 1); i++) {
2014 PyObject *s = PyString_FromString(argv[i + 1]);
2015 if (!s || PyTuple_SetItem(arg, i, s)) {
2016 Py_DECREF(arg);
2017 return PythonCmd_Error(interp);
2020 res = PyEval_CallObject(func, arg);
2021 Py_DECREF(arg);
2023 if (res == NULL)
2024 return PythonCmd_Error(interp);
2026 obj_res = AsObj(res);
2027 if (obj_res == NULL) {
2028 Py_DECREF(res);
2029 return PythonCmd_Error(interp);
2031 else {
2032 Tcl_SetObjResult(Tkapp_Interp(self), obj_res);
2033 rv = TCL_OK;
2036 Py_DECREF(res);
2038 LEAVE_PYTHON
2040 return rv;
2043 static void
2044 PythonCmdDelete(ClientData clientData)
2046 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2048 ENTER_PYTHON
2049 Py_XDECREF(data->self);
2050 Py_XDECREF(data->func);
2051 PyMem_DEL(data);
2052 LEAVE_PYTHON
2058 TCL_DECLARE_MUTEX(command_mutex)
2060 typedef struct CommandEvent{
2061 Tcl_Event ev;
2062 Tcl_Interp* interp;
2063 char *name;
2064 int create;
2065 int *status;
2066 ClientData *data;
2067 Tcl_Condition done;
2068 } CommandEvent;
2070 static int
2071 Tkapp_CommandProc(CommandEvent *ev, int flags)
2073 if (ev->create)
2074 *ev->status = Tcl_CreateCommand(
2075 ev->interp, ev->name, PythonCmd,
2076 ev->data, PythonCmdDelete) == NULL;
2077 else
2078 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2079 Tcl_MutexLock(&command_mutex);
2080 Tcl_ConditionNotify(&ev->done);
2081 Tcl_MutexUnlock(&command_mutex);
2082 return 1;
2085 static PyObject *
2086 Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2088 TkappObject *self = (TkappObject*)selfptr;
2089 PythonCmd_ClientData *data;
2090 char *cmdName;
2091 PyObject *func;
2092 int err;
2094 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2095 return NULL;
2096 if (!PyCallable_Check(func)) {
2097 PyErr_SetString(PyExc_TypeError, "command not callable");
2098 return NULL;
2101 #ifdef WITH_THREAD
2102 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2103 !WaitForMainloop(self))
2104 return NULL;
2105 #endif
2107 data = PyMem_NEW(PythonCmd_ClientData, 1);
2108 if (!data)
2109 return PyErr_NoMemory();
2110 Py_INCREF(self);
2111 Py_INCREF(func);
2112 data->self = selfptr;
2113 data->func = func;
2115 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2116 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2117 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2118 ev->interp = self->interp;
2119 ev->create = 1;
2120 ev->name = cmdName;
2121 ev->data = (ClientData)data;
2122 ev->status = &err;
2123 ev->done = NULL;
2124 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2126 else {
2127 ENTER_TCL
2128 err = Tcl_CreateCommand(
2129 Tkapp_Interp(self), cmdName, PythonCmd,
2130 (ClientData)data, PythonCmdDelete) == NULL;
2131 LEAVE_TCL
2133 if (err) {
2134 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2135 PyMem_DEL(data);
2136 return NULL;
2139 Py_INCREF(Py_None);
2140 return Py_None;
2145 static PyObject *
2146 Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2148 TkappObject *self = (TkappObject*)selfptr;
2149 char *cmdName;
2150 int err;
2152 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2153 return NULL;
2154 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2155 CommandEvent *ev;
2156 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2157 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2158 ev->interp = self->interp;
2159 ev->create = 0;
2160 ev->name = cmdName;
2161 ev->status = &err;
2162 ev->done = NULL;
2163 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2164 &command_mutex);
2166 else {
2167 ENTER_TCL
2168 err = Tcl_DeleteCommand(self->interp, cmdName);
2169 LEAVE_TCL
2171 if (err == -1) {
2172 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2173 return NULL;
2175 Py_INCREF(Py_None);
2176 return Py_None;
2181 #ifdef HAVE_CREATEFILEHANDLER
2182 /** File Handler **/
2184 typedef struct _fhcdata {
2185 PyObject *func;
2186 PyObject *file;
2187 int id;
2188 struct _fhcdata *next;
2189 } FileHandler_ClientData;
2191 static FileHandler_ClientData *HeadFHCD;
2193 static FileHandler_ClientData *
2194 NewFHCD(PyObject *func, PyObject *file, int id)
2196 FileHandler_ClientData *p;
2197 p = PyMem_NEW(FileHandler_ClientData, 1);
2198 if (p != NULL) {
2199 Py_XINCREF(func);
2200 Py_XINCREF(file);
2201 p->func = func;
2202 p->file = file;
2203 p->id = id;
2204 p->next = HeadFHCD;
2205 HeadFHCD = p;
2207 return p;
2210 static void
2211 DeleteFHCD(int id)
2213 FileHandler_ClientData *p, **pp;
2215 pp = &HeadFHCD;
2216 while ((p = *pp) != NULL) {
2217 if (p->id == id) {
2218 *pp = p->next;
2219 Py_XDECREF(p->func);
2220 Py_XDECREF(p->file);
2221 PyMem_DEL(p);
2223 else
2224 pp = &p->next;
2228 static void
2229 FileHandler(ClientData clientData, int mask)
2231 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2232 PyObject *func, *file, *arg, *res;
2234 ENTER_PYTHON
2235 func = data->func;
2236 file = data->file;
2238 arg = Py_BuildValue("(Oi)", file, (long) mask);
2239 res = PyEval_CallObject(func, arg);
2240 Py_DECREF(arg);
2242 if (res == NULL) {
2243 errorInCmd = 1;
2244 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2246 Py_XDECREF(res);
2247 LEAVE_PYTHON
2250 static PyObject *
2251 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2252 /* args is (file, mask, func) */
2254 FileHandler_ClientData *data;
2255 PyObject *file, *func;
2256 int mask, tfile;
2258 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2259 &file, &mask, &func))
2260 return NULL;
2262 #ifdef WITH_THREAD
2263 if (!self && !tcl_lock) {
2264 /* We don't have the Tcl lock since Tcl is threaded. */
2265 PyErr_SetString(PyExc_RuntimeError,
2266 "_tkinter.createfilehandler not supported "
2267 "for threaded Tcl");
2268 return NULL;
2270 #endif
2272 if (self) {
2273 CHECK_TCL_APPARTMENT;
2276 tfile = PyObject_AsFileDescriptor(file);
2277 if (tfile < 0)
2278 return NULL;
2279 if (!PyCallable_Check(func)) {
2280 PyErr_SetString(PyExc_TypeError, "bad argument list");
2281 return NULL;
2284 data = NewFHCD(func, file, tfile);
2285 if (data == NULL)
2286 return NULL;
2288 /* Ought to check for null Tcl_File object... */
2289 ENTER_TCL
2290 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2291 LEAVE_TCL
2292 Py_INCREF(Py_None);
2293 return Py_None;
2296 static PyObject *
2297 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2299 PyObject *file;
2300 int tfile;
2302 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2303 return NULL;
2305 #ifdef WITH_THREAD
2306 if (!self && !tcl_lock) {
2307 /* We don't have the Tcl lock since Tcl is threaded. */
2308 PyErr_SetString(PyExc_RuntimeError,
2309 "_tkinter.deletefilehandler not supported "
2310 "for threaded Tcl");
2311 return NULL;
2313 #endif
2315 if (self) {
2316 CHECK_TCL_APPARTMENT;
2319 tfile = PyObject_AsFileDescriptor(file);
2320 if (tfile < 0)
2321 return NULL;
2323 DeleteFHCD(tfile);
2325 /* Ought to check for null Tcl_File object... */
2326 ENTER_TCL
2327 Tcl_DeleteFileHandler(tfile);
2328 LEAVE_TCL
2329 Py_INCREF(Py_None);
2330 return Py_None;
2332 #endif /* HAVE_CREATEFILEHANDLER */
2335 /**** Tktt Object (timer token) ****/
2337 static PyTypeObject Tktt_Type;
2339 typedef struct {
2340 PyObject_HEAD
2341 Tcl_TimerToken token;
2342 PyObject *func;
2343 } TkttObject;
2345 static PyObject *
2346 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2348 TkttObject *v = (TkttObject *)self;
2349 PyObject *func = v->func;
2351 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2352 return NULL;
2353 if (v->token != NULL) {
2354 Tcl_DeleteTimerHandler(v->token);
2355 v->token = NULL;
2357 if (func != NULL) {
2358 v->func = NULL;
2359 Py_DECREF(func);
2360 Py_DECREF(v); /* See Tktt_New() */
2362 Py_INCREF(Py_None);
2363 return Py_None;
2366 static PyMethodDef Tktt_methods[] =
2368 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2369 {NULL, NULL}
2372 static TkttObject *
2373 Tktt_New(PyObject *func)
2375 TkttObject *v;
2377 v = PyObject_New(TkttObject, &Tktt_Type);
2378 if (v == NULL)
2379 return NULL;
2381 Py_INCREF(func);
2382 v->token = NULL;
2383 v->func = func;
2385 /* Extra reference, deleted when called or when handler is deleted */
2386 Py_INCREF(v);
2387 return v;
2390 static void
2391 Tktt_Dealloc(PyObject *self)
2393 TkttObject *v = (TkttObject *)self;
2394 PyObject *func = v->func;
2396 Py_XDECREF(func);
2398 PyObject_Del(self);
2401 static PyObject *
2402 Tktt_Repr(PyObject *self)
2404 TkttObject *v = (TkttObject *)self;
2405 char buf[100];
2407 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2408 v->func == NULL ? ", handler deleted" : "");
2409 return PyString_FromString(buf);
2412 static PyObject *
2413 Tktt_GetAttr(PyObject *self, char *name)
2415 return Py_FindMethod(Tktt_methods, self, name);
2418 static PyTypeObject Tktt_Type =
2420 PyVarObject_HEAD_INIT(NULL, 0)
2421 "tktimertoken", /*tp_name */
2422 sizeof(TkttObject), /*tp_basicsize */
2423 0, /*tp_itemsize */
2424 Tktt_Dealloc, /*tp_dealloc */
2425 0, /*tp_print */
2426 Tktt_GetAttr, /*tp_getattr */
2427 0, /*tp_setattr */
2428 0, /*tp_compare */
2429 Tktt_Repr, /*tp_repr */
2430 0, /*tp_as_number */
2431 0, /*tp_as_sequence */
2432 0, /*tp_as_mapping */
2433 0, /*tp_hash */
2438 /** Timer Handler **/
2440 static void
2441 TimerHandler(ClientData clientData)
2443 TkttObject *v = (TkttObject *)clientData;
2444 PyObject *func = v->func;
2445 PyObject *res;
2447 if (func == NULL)
2448 return;
2450 v->func = NULL;
2452 ENTER_PYTHON
2454 res = PyEval_CallObject(func, NULL);
2455 Py_DECREF(func);
2456 Py_DECREF(v); /* See Tktt_New() */
2458 if (res == NULL) {
2459 errorInCmd = 1;
2460 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2462 else
2463 Py_DECREF(res);
2465 LEAVE_PYTHON
2468 static PyObject *
2469 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2471 int milliseconds;
2472 PyObject *func;
2473 TkttObject *v;
2475 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2476 &milliseconds, &func))
2477 return NULL;
2478 if (!PyCallable_Check(func)) {
2479 PyErr_SetString(PyExc_TypeError, "bad argument list");
2480 return NULL;
2483 #ifdef WITH_THREAD
2484 if (!self && !tcl_lock) {
2485 /* We don't have the Tcl lock since Tcl is threaded. */
2486 PyErr_SetString(PyExc_RuntimeError,
2487 "_tkinter.createtimerhandler not supported "
2488 "for threaded Tcl");
2489 return NULL;
2491 #endif
2493 if (self) {
2494 CHECK_TCL_APPARTMENT;
2497 v = Tktt_New(func);
2498 if (v) {
2499 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2500 (ClientData)v);
2503 return (PyObject *) v;
2507 /** Event Loop **/
2509 static PyObject *
2510 Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
2512 int threshold = 0;
2513 TkappObject *self = (TkappObject*)selfptr;
2514 #ifdef WITH_THREAD
2515 PyThreadState *tstate = PyThreadState_Get();
2516 #endif
2518 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2519 return NULL;
2521 #ifdef WITH_THREAD
2522 if (!self && !tcl_lock) {
2523 /* We don't have the Tcl lock since Tcl is threaded. */
2524 PyErr_SetString(PyExc_RuntimeError,
2525 "_tkinter.mainloop not supported "
2526 "for threaded Tcl");
2527 return NULL;
2529 #endif
2531 if (self) {
2532 CHECK_TCL_APPARTMENT;
2533 self->dispatching = 1;
2536 quitMainLoop = 0;
2537 while (Tk_GetNumMainWindows() > threshold &&
2538 !quitMainLoop &&
2539 !errorInCmd)
2541 int result;
2543 #ifdef WITH_THREAD
2544 if (self && self->threaded) {
2545 /* Allow other Python threads to run. */
2546 ENTER_TCL
2547 result = Tcl_DoOneEvent(0);
2548 LEAVE_TCL
2550 else {
2551 Py_BEGIN_ALLOW_THREADS
2552 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2553 tcl_tstate = tstate;
2554 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2555 tcl_tstate = NULL;
2556 if(tcl_lock)PyThread_release_lock(tcl_lock);
2557 if (result == 0)
2558 Sleep(Tkinter_busywaitinterval);
2559 Py_END_ALLOW_THREADS
2561 #else
2562 result = Tcl_DoOneEvent(0);
2563 #endif
2565 if (PyErr_CheckSignals() != 0) {
2566 if (self)
2567 self->dispatching = 0;
2568 return NULL;
2570 if (result < 0)
2571 break;
2573 if (self)
2574 self->dispatching = 0;
2575 quitMainLoop = 0;
2577 if (errorInCmd) {
2578 errorInCmd = 0;
2579 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2580 excInCmd = valInCmd = trbInCmd = NULL;
2581 return NULL;
2583 Py_INCREF(Py_None);
2584 return Py_None;
2587 static PyObject *
2588 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
2590 int flags = 0;
2591 int rv;
2593 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2594 return NULL;
2596 ENTER_TCL
2597 rv = Tcl_DoOneEvent(flags);
2598 LEAVE_TCL
2599 return Py_BuildValue("i", rv);
2602 static PyObject *
2603 Tkapp_Quit(PyObject *self, PyObject *args)
2606 if (!PyArg_ParseTuple(args, ":quit"))
2607 return NULL;
2609 quitMainLoop = 1;
2610 Py_INCREF(Py_None);
2611 return Py_None;
2614 static PyObject *
2615 Tkapp_InterpAddr(PyObject *self, PyObject *args)
2618 if (!PyArg_ParseTuple(args, ":interpaddr"))
2619 return NULL;
2621 return PyInt_FromLong((long)Tkapp_Interp(self));
2624 static PyObject *
2625 Tkapp_TkInit(PyObject *self, PyObject *args)
2627 static int has_failed;
2628 Tcl_Interp *interp = Tkapp_Interp(self);
2629 Tk_Window main_window;
2630 const char * _tk_exists = NULL;
2631 int err;
2632 main_window = Tk_MainWindow(interp);
2634 /* In all current versions of Tk (including 8.4.13), Tk_Init
2635 deadlocks on the second call when the first call failed.
2636 To avoid the deadlock, we just refuse the second call through
2637 a static variable. */
2638 if (has_failed) {
2639 PyErr_SetString(Tkinter_TclError,
2640 "Calling Tk_Init again after a previous call failed might deadlock");
2641 return NULL;
2644 /* We want to guard against calling Tk_Init() multiple times */
2645 CHECK_TCL_APPARTMENT;
2646 ENTER_TCL
2647 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2648 ENTER_OVERLAP
2649 if (err == TCL_ERROR) {
2650 /* This sets an exception, but we cannot return right
2651 away because we need to exit the overlap first. */
2652 Tkinter_Error(self);
2653 } else {
2654 _tk_exists = Tkapp_Result(self);
2656 LEAVE_OVERLAP_TCL
2657 if (err == TCL_ERROR) {
2658 return NULL;
2660 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2661 if (Tk_Init(interp) == TCL_ERROR) {
2662 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2663 has_failed = 1;
2664 return NULL;
2667 Py_INCREF(Py_None);
2668 return Py_None;
2671 static PyObject *
2672 Tkapp_WantObjects(PyObject *self, PyObject *args)
2675 int wantobjects = -1;
2676 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2677 return NULL;
2678 if (wantobjects == -1)
2679 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2680 ((TkappObject*)self)->wantobjects = wantobjects;
2682 Py_INCREF(Py_None);
2683 return Py_None;
2686 static PyObject *
2687 Tkapp_WillDispatch(PyObject *self, PyObject *args)
2690 ((TkappObject*)self)->dispatching = 1;
2692 Py_INCREF(Py_None);
2693 return Py_None;
2697 /**** Tkapp Method List ****/
2699 static PyMethodDef Tkapp_methods[] =
2701 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2702 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2703 {"call", Tkapp_Call, METH_VARARGS},
2704 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2705 {"eval", Tkapp_Eval, METH_VARARGS},
2706 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2707 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2708 {"record", Tkapp_Record, METH_VARARGS},
2709 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2710 {"setvar", Tkapp_SetVar, METH_VARARGS},
2711 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2712 {"getvar", Tkapp_GetVar, METH_VARARGS},
2713 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2714 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2715 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2716 {"getint", Tkapp_GetInt, METH_VARARGS},
2717 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2718 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2719 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2720 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2721 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2722 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2723 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2724 {"split", Tkapp_Split, METH_VARARGS},
2725 {"merge", Tkapp_Merge, METH_VARARGS},
2726 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2727 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2728 #ifdef HAVE_CREATEFILEHANDLER
2729 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2730 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2731 #endif
2732 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2733 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2734 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2735 {"quit", Tkapp_Quit, METH_VARARGS},
2736 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2737 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2738 {NULL, NULL}
2743 /**** Tkapp Type Methods ****/
2745 static void
2746 Tkapp_Dealloc(PyObject *self)
2748 /*CHECK_TCL_APPARTMENT;*/
2749 ENTER_TCL
2750 Tcl_DeleteInterp(Tkapp_Interp(self));
2751 LEAVE_TCL
2752 PyObject_Del(self);
2753 DisableEventHook();
2756 static PyObject *
2757 Tkapp_GetAttr(PyObject *self, char *name)
2759 return Py_FindMethod(Tkapp_methods, self, name);
2762 static PyTypeObject Tkapp_Type =
2764 PyVarObject_HEAD_INIT(NULL, 0)
2765 "tkapp", /*tp_name */
2766 sizeof(TkappObject), /*tp_basicsize */
2767 0, /*tp_itemsize */
2768 Tkapp_Dealloc, /*tp_dealloc */
2769 0, /*tp_print */
2770 Tkapp_GetAttr, /*tp_getattr */
2771 0, /*tp_setattr */
2772 0, /*tp_compare */
2773 0, /*tp_repr */
2774 0, /*tp_as_number */
2775 0, /*tp_as_sequence */
2776 0, /*tp_as_mapping */
2777 0, /*tp_hash */
2782 /**** Tkinter Module ****/
2784 typedef struct {
2785 PyObject* tuple;
2786 int size; /* current size */
2787 int maxsize; /* allocated size */
2788 } FlattenContext;
2790 static int
2791 _bump(FlattenContext* context, int size)
2793 /* expand tuple to hold (at least) size new items.
2794 return true if successful, false if an exception was raised */
2796 int maxsize = context->maxsize * 2;
2798 if (maxsize < context->size + size)
2799 maxsize = context->size + size;
2801 context->maxsize = maxsize;
2803 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2806 static int
2807 _flatten1(FlattenContext* context, PyObject* item, int depth)
2809 /* add tuple or list to argument tuple (recursively) */
2811 int i, size;
2813 if (depth > 1000) {
2814 PyErr_SetString(PyExc_ValueError,
2815 "nesting too deep in _flatten");
2816 return 0;
2817 } else if (PyList_Check(item)) {
2818 size = PyList_GET_SIZE(item);
2819 /* preallocate (assume no nesting) */
2820 if (context->size + size > context->maxsize &&
2821 !_bump(context, size))
2822 return 0;
2823 /* copy items to output tuple */
2824 for (i = 0; i < size; i++) {
2825 PyObject *o = PyList_GET_ITEM(item, i);
2826 if (PyList_Check(o) || PyTuple_Check(o)) {
2827 if (!_flatten1(context, o, depth + 1))
2828 return 0;
2829 } else if (o != Py_None) {
2830 if (context->size + 1 > context->maxsize &&
2831 !_bump(context, 1))
2832 return 0;
2833 Py_INCREF(o);
2834 PyTuple_SET_ITEM(context->tuple,
2835 context->size++, o);
2838 } else if (PyTuple_Check(item)) {
2839 /* same, for tuples */
2840 size = PyTuple_GET_SIZE(item);
2841 if (context->size + size > context->maxsize &&
2842 !_bump(context, size))
2843 return 0;
2844 for (i = 0; i < size; i++) {
2845 PyObject *o = PyTuple_GET_ITEM(item, i);
2846 if (PyList_Check(o) || PyTuple_Check(o)) {
2847 if (!_flatten1(context, o, depth + 1))
2848 return 0;
2849 } else if (o != Py_None) {
2850 if (context->size + 1 > context->maxsize &&
2851 !_bump(context, 1))
2852 return 0;
2853 Py_INCREF(o);
2854 PyTuple_SET_ITEM(context->tuple,
2855 context->size++, o);
2858 } else {
2859 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2860 return 0;
2862 return 1;
2865 static PyObject *
2866 Tkinter_Flatten(PyObject* self, PyObject* args)
2868 FlattenContext context;
2869 PyObject* item;
2871 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2872 return NULL;
2874 context.maxsize = PySequence_Size(item);
2875 if (context.maxsize <= 0)
2876 return PyTuple_New(0);
2878 context.tuple = PyTuple_New(context.maxsize);
2879 if (!context.tuple)
2880 return NULL;
2882 context.size = 0;
2884 if (!_flatten1(&context, item,0))
2885 return NULL;
2887 if (_PyTuple_Resize(&context.tuple, context.size))
2888 return NULL;
2890 return context.tuple;
2893 static PyObject *
2894 Tkinter_Create(PyObject *self, PyObject *args)
2896 char *screenName = NULL;
2897 char *baseName = NULL;
2898 char *className = NULL;
2899 int interactive = 0;
2900 int wantobjects = 0;
2901 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2902 int sync = 0; /* pass -sync to wish */
2903 char *use = NULL; /* pass -use to wish */
2905 baseName = strrchr(Py_GetProgramName(), '/');
2906 if (baseName != NULL)
2907 baseName++;
2908 else
2909 baseName = Py_GetProgramName();
2910 className = "Tk";
2912 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2913 &screenName, &baseName, &className,
2914 &interactive, &wantobjects, &wantTk,
2915 &sync, &use))
2916 return NULL;
2918 return (PyObject *) Tkapp_New(screenName, baseName, className,
2919 interactive, wantobjects, wantTk,
2920 sync, use);
2923 static PyObject *
2924 Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2926 int new_val;
2927 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2928 return NULL;
2929 if (new_val < 0) {
2930 PyErr_SetString(PyExc_ValueError,
2931 "busywaitinterval must be >= 0");
2932 return NULL;
2934 Tkinter_busywaitinterval = new_val;
2935 Py_INCREF(Py_None);
2936 return Py_None;
2939 static char setbusywaitinterval_doc[] =
2940 "setbusywaitinterval(n) -> None\n\
2942 Set the busy-wait interval in milliseconds between successive\n\
2943 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2944 It should be set to a divisor of the maximum time between\n\
2945 frames in an animation.";
2947 static PyObject *
2948 Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2950 return PyInt_FromLong(Tkinter_busywaitinterval);
2953 static char getbusywaitinterval_doc[] =
2954 "getbusywaitinterval() -> int\n\
2956 Return the current busy-wait interval between successive\n\
2957 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2959 static PyMethodDef moduleMethods[] =
2961 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2962 {"create", Tkinter_Create, METH_VARARGS},
2963 #ifdef HAVE_CREATEFILEHANDLER
2964 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2965 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2966 #endif
2967 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2968 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2969 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2970 {"quit", Tkapp_Quit, METH_VARARGS},
2971 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
2972 setbusywaitinterval_doc},
2973 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
2974 METH_NOARGS, getbusywaitinterval_doc},
2975 {NULL, NULL}
2978 #ifdef WAIT_FOR_STDIN
2980 static int stdin_ready = 0;
2982 #ifndef MS_WINDOWS
2983 static void
2984 MyFileProc(void *clientData, int mask)
2986 stdin_ready = 1;
2988 #endif
2990 #ifdef WITH_THREAD
2991 static PyThreadState *event_tstate = NULL;
2992 #endif
2994 static int
2995 EventHook(void)
2997 #ifndef MS_WINDOWS
2998 int tfile;
2999 #endif
3000 #ifdef WITH_THREAD
3001 PyEval_RestoreThread(event_tstate);
3002 #endif
3003 stdin_ready = 0;
3004 errorInCmd = 0;
3005 #ifndef MS_WINDOWS
3006 tfile = fileno(stdin);
3007 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
3008 #endif
3009 while (!errorInCmd && !stdin_ready) {
3010 int result;
3011 #ifdef MS_WINDOWS
3012 if (_kbhit()) {
3013 stdin_ready = 1;
3014 break;
3016 #endif
3017 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3018 Py_BEGIN_ALLOW_THREADS
3019 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3020 tcl_tstate = event_tstate;
3022 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3024 tcl_tstate = NULL;
3025 if(tcl_lock)PyThread_release_lock(tcl_lock);
3026 if (result == 0)
3027 Sleep(Tkinter_busywaitinterval);
3028 Py_END_ALLOW_THREADS
3029 #else
3030 result = Tcl_DoOneEvent(0);
3031 #endif
3033 if (result < 0)
3034 break;
3036 #ifndef MS_WINDOWS
3037 Tcl_DeleteFileHandler(tfile);
3038 #endif
3039 if (errorInCmd) {
3040 errorInCmd = 0;
3041 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3042 excInCmd = valInCmd = trbInCmd = NULL;
3043 PyErr_Print();
3045 #ifdef WITH_THREAD
3046 PyEval_SaveThread();
3047 #endif
3048 return 0;
3051 #endif
3053 static void
3054 EnableEventHook(void)
3056 #ifdef WAIT_FOR_STDIN
3057 if (PyOS_InputHook == NULL) {
3058 #ifdef WITH_THREAD
3059 event_tstate = PyThreadState_Get();
3060 #endif
3061 PyOS_InputHook = EventHook;
3063 #endif
3066 static void
3067 DisableEventHook(void)
3069 #ifdef WAIT_FOR_STDIN
3070 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3071 PyOS_InputHook = NULL;
3073 #endif
3077 /* all errors will be checked in one fell swoop in init_tkinter() */
3078 static void
3079 ins_long(PyObject *d, char *name, long val)
3081 PyObject *v = PyInt_FromLong(val);
3082 if (v) {
3083 PyDict_SetItemString(d, name, v);
3084 Py_DECREF(v);
3087 static void
3088 ins_string(PyObject *d, char *name, char *val)
3090 PyObject *v = PyString_FromString(val);
3091 if (v) {
3092 PyDict_SetItemString(d, name, v);
3093 Py_DECREF(v);
3098 PyMODINIT_FUNC
3099 init_tkinter(void)
3101 PyObject *m, *d;
3103 Py_TYPE(&Tkapp_Type) = &PyType_Type;
3105 #ifdef WITH_THREAD
3106 tcl_lock = PyThread_allocate_lock();
3107 #endif
3109 m = Py_InitModule("_tkinter", moduleMethods);
3110 if (m == NULL)
3111 return;
3113 d = PyModule_GetDict(m);
3114 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3115 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3117 ins_long(d, "READABLE", TCL_READABLE);
3118 ins_long(d, "WRITABLE", TCL_WRITABLE);
3119 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3120 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3121 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3122 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3123 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3124 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3125 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3126 ins_string(d, "TK_VERSION", TK_VERSION);
3127 ins_string(d, "TCL_VERSION", TCL_VERSION);
3129 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3131 Py_TYPE(&Tktt_Type) = &PyType_Type;
3132 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3134 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3135 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3137 #ifdef TK_AQUA
3138 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3139 * start waking up. Note that Tcl_FindExecutable will do this, this
3140 * code must be above it! The original warning from
3141 * tkMacOSXAppInit.c is copied below.
3143 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3144 * Tcl interpreter for now. It probably should work to do this
3145 * in the other order, but for now it doesn't seem to.
3148 Tk_MacOSXSetupTkNotifier();
3149 #endif
3152 /* This helps the dynamic loader; in Unicode aware Tcl versions
3153 it also helps Tcl find its encodings. */
3154 Tcl_FindExecutable(Py_GetProgramName());
3156 if (PyErr_Occurred())
3157 return;
3159 #if 0
3160 /* This was not a good idea; through <Destroy> bindings,
3161 Tcl_Finalize() may invoke Python code but at that point the
3162 interpreter and thread state have already been destroyed! */
3163 Py_AtExit(Tcl_Finalize);
3164 #endif