Make importlib backwards-compatible to Python 2.2 (but this is not promised to
[python.git] / Modules / _tkinter.c
blob8b56bcd0dc38bef072d7120e3383207744ac9f9b
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 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
1289 /* If args is a single tuple, replace with contents of tuple */
1290 if (1 == PyTuple_Size(args)){
1291 PyObject* item = PyTuple_GetItem(args, 0);
1292 if (PyTuple_Check(item))
1293 args = item;
1295 #ifdef WITH_THREAD
1296 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1297 /* We cannot call the command directly. Instead, we must
1298 marshal the parameters to the interpreter thread. */
1299 Tkapp_CallEvent *ev;
1300 PyObject *exc_type, *exc_value, *exc_tb;
1301 if (!WaitForMainloop(self))
1302 return NULL;
1303 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1304 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1305 ev->self = self;
1306 ev->args = args;
1307 ev->res = &res;
1308 ev->exc_type = &exc_type;
1309 ev->exc_value = &exc_value;
1310 ev->exc_tb = &exc_tb;
1311 ev->done = (Tcl_Condition)0;
1313 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &call_mutex);
1315 if (res == NULL) {
1316 if (exc_type)
1317 PyErr_Restore(exc_type, exc_value, exc_tb);
1318 else
1319 PyErr_SetObject(Tkinter_TclError, exc_value);
1322 else
1323 #endif
1326 objv = Tkapp_CallArgs(args, objStore, &objc);
1327 if (!objv)
1328 return NULL;
1330 ENTER_TCL
1332 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1334 ENTER_OVERLAP
1336 if (i == TCL_ERROR)
1337 Tkinter_Error(selfptr);
1338 else
1339 res = Tkapp_CallResult(self);
1341 LEAVE_OVERLAP_TCL
1343 Tkapp_CallDeallocArgs(objv, objStore, objc);
1345 return res;
1349 static PyObject *
1350 Tkapp_GlobalCall(PyObject *self, PyObject *args)
1352 /* Could do the same here as for Tkapp_Call(), but this is not used
1353 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1354 way for the user to do what all its Global* variants do (save and
1355 reset the scope pointer, call the local version, restore the saved
1356 scope pointer). */
1358 char *cmd;
1359 PyObject *res = NULL;
1361 CHECK_TCL_APPARTMENT;
1363 cmd = Merge(args);
1364 if (cmd) {
1365 int err;
1366 ENTER_TCL
1367 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1368 ENTER_OVERLAP
1369 if (err == TCL_ERROR)
1370 res = Tkinter_Error(self);
1371 else
1372 res = PyString_FromString(Tkapp_Result(self));
1373 LEAVE_OVERLAP_TCL
1374 ckfree(cmd);
1377 return res;
1380 static PyObject *
1381 Tkapp_Eval(PyObject *self, PyObject *args)
1383 char *script;
1384 PyObject *res = NULL;
1385 int err;
1387 if (!PyArg_ParseTuple(args, "s:eval", &script))
1388 return NULL;
1390 CHECK_TCL_APPARTMENT;
1392 ENTER_TCL
1393 err = Tcl_Eval(Tkapp_Interp(self), script);
1394 ENTER_OVERLAP
1395 if (err == TCL_ERROR)
1396 res = Tkinter_Error(self);
1397 else
1398 res = PyString_FromString(Tkapp_Result(self));
1399 LEAVE_OVERLAP_TCL
1400 return res;
1403 static PyObject *
1404 Tkapp_GlobalEval(PyObject *self, PyObject *args)
1406 char *script;
1407 PyObject *res = NULL;
1408 int err;
1410 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1411 return NULL;
1413 CHECK_TCL_APPARTMENT;
1415 ENTER_TCL
1416 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1417 ENTER_OVERLAP
1418 if (err == TCL_ERROR)
1419 res = Tkinter_Error(self);
1420 else
1421 res = PyString_FromString(Tkapp_Result(self));
1422 LEAVE_OVERLAP_TCL
1423 return res;
1426 static PyObject *
1427 Tkapp_EvalFile(PyObject *self, PyObject *args)
1429 char *fileName;
1430 PyObject *res = NULL;
1431 int err;
1433 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1434 return NULL;
1436 CHECK_TCL_APPARTMENT;
1438 ENTER_TCL
1439 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1440 ENTER_OVERLAP
1441 if (err == TCL_ERROR)
1442 res = Tkinter_Error(self);
1444 else
1445 res = PyString_FromString(Tkapp_Result(self));
1446 LEAVE_OVERLAP_TCL
1447 return res;
1450 static PyObject *
1451 Tkapp_Record(PyObject *self, PyObject *args)
1453 char *script;
1454 PyObject *res = NULL;
1455 int err;
1457 if (!PyArg_ParseTuple(args, "s", &script))
1458 return NULL;
1460 CHECK_TCL_APPARTMENT;
1462 ENTER_TCL
1463 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1464 ENTER_OVERLAP
1465 if (err == TCL_ERROR)
1466 res = Tkinter_Error(self);
1467 else
1468 res = PyString_FromString(Tkapp_Result(self));
1469 LEAVE_OVERLAP_TCL
1470 return res;
1473 static PyObject *
1474 Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
1476 char *msg;
1478 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1479 return NULL;
1480 CHECK_TCL_APPARTMENT;
1482 ENTER_TCL
1483 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1484 LEAVE_TCL
1486 Py_INCREF(Py_None);
1487 return Py_None;
1492 /** Tcl Variable **/
1494 TCL_DECLARE_MUTEX(var_mutex)
1496 typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1497 typedef struct VarEvent {
1498 Tcl_Event ev; /* must be first */
1499 PyObject *self;
1500 PyObject *args;
1501 int flags;
1502 EventFunc func;
1503 PyObject **res;
1504 PyObject **exc_type;
1505 PyObject **exc_val;
1506 Tcl_Condition cond;
1507 } VarEvent;
1509 static int
1510 varname_converter(PyObject *in, void *_out)
1512 char **out = (char**)_out;
1513 if (PyString_Check(in)) {
1514 *out = PyString_AsString(in);
1515 return 1;
1517 if (PyTclObject_Check(in)) {
1518 *out = PyTclObject_TclString(in);
1519 return 1;
1521 /* XXX: Should give diagnostics. */
1522 return 0;
1525 static void
1526 var_perform(VarEvent *ev)
1528 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1529 if (!*(ev->res)) {
1530 PyObject *exc, *val, *tb;
1531 PyErr_Fetch(&exc, &val, &tb);
1532 PyErr_NormalizeException(&exc, &val, &tb);
1533 *(ev->exc_type) = exc;
1534 *(ev->exc_val) = val;
1535 Py_DECREF(tb);
1540 static int
1541 var_proc(VarEvent* ev, int flags)
1543 ENTER_PYTHON
1544 var_perform(ev);
1545 Tcl_MutexLock(&var_mutex);
1546 Tcl_ConditionNotify(&ev->cond);
1547 Tcl_MutexUnlock(&var_mutex);
1548 LEAVE_PYTHON
1549 return 1;
1552 static PyObject*
1553 var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
1555 TkappObject *self = (TkappObject*)selfptr;
1556 #ifdef WITH_THREAD
1557 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1558 TkappObject *self = (TkappObject*)selfptr;
1559 VarEvent *ev;
1560 PyObject *res, *exc_type, *exc_val;
1562 /* The current thread is not the interpreter thread. Marshal
1563 the call to the interpreter thread, then wait for
1564 completion. */
1565 if (!WaitForMainloop(self))
1566 return NULL;
1568 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1570 ev->self = selfptr;
1571 ev->args = args;
1572 ev->flags = flags;
1573 ev->func = func;
1574 ev->res = &res;
1575 ev->exc_type = &exc_type;
1576 ev->exc_val = &exc_val;
1577 ev->cond = NULL;
1578 ev->ev.proc = (Tcl_EventProc*)var_proc;
1579 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->cond, &var_mutex);
1580 if (!res) {
1581 PyErr_SetObject(exc_type, exc_val);
1582 Py_DECREF(exc_type);
1583 Py_DECREF(exc_val);
1584 return NULL;
1586 return res;
1588 #endif
1589 /* Tcl is not threaded, or this is the interpreter thread. */
1590 return func(selfptr, args, flags);
1593 static PyObject *
1594 SetVar(PyObject *self, PyObject *args, int flags)
1596 char *name1, *name2;
1597 PyObject *newValue;
1598 PyObject *res = NULL;
1599 Tcl_Obj *newval, *ok;
1601 if (PyArg_ParseTuple(args, "O&O:setvar",
1602 varname_converter, &name1, &newValue)) {
1603 /* XXX Acquire tcl lock??? */
1604 newval = AsObj(newValue);
1605 if (newval == NULL)
1606 return NULL;
1607 ENTER_TCL
1608 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1609 newval, flags);
1610 ENTER_OVERLAP
1611 if (!ok)
1612 Tkinter_Error(self);
1613 else {
1614 res = Py_None;
1615 Py_INCREF(res);
1617 LEAVE_OVERLAP_TCL
1619 else {
1620 PyErr_Clear();
1621 if (PyArg_ParseTuple(args, "ssO:setvar",
1622 &name1, &name2, &newValue)) {
1623 /* XXX must hold tcl lock already??? */
1624 newval = AsObj(newValue);
1625 ENTER_TCL
1626 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1627 ENTER_OVERLAP
1628 if (!ok)
1629 Tkinter_Error(self);
1630 else {
1631 res = Py_None;
1632 Py_INCREF(res);
1634 LEAVE_OVERLAP_TCL
1636 else {
1637 return NULL;
1640 return res;
1643 static PyObject *
1644 Tkapp_SetVar(PyObject *self, PyObject *args)
1646 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1649 static PyObject *
1650 Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
1652 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1657 static PyObject *
1658 GetVar(PyObject *self, PyObject *args, int flags)
1660 char *name1, *name2=NULL;
1661 PyObject *res = NULL;
1662 Tcl_Obj *tres;
1664 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1665 varname_converter, &name1, &name2))
1666 return NULL;
1668 ENTER_TCL
1669 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1670 ENTER_OVERLAP
1671 if (tres == NULL) {
1672 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1673 } else {
1674 if (((TkappObject*)self)->wantobjects) {
1675 res = FromObj(self, tres);
1677 else {
1678 res = PyString_FromString(Tcl_GetString(tres));
1681 LEAVE_OVERLAP_TCL
1682 return res;
1685 static PyObject *
1686 Tkapp_GetVar(PyObject *self, PyObject *args)
1688 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1691 static PyObject *
1692 Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1694 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1699 static PyObject *
1700 UnsetVar(PyObject *self, PyObject *args, int flags)
1702 char *name1, *name2=NULL;
1703 int code;
1704 PyObject *res = NULL;
1706 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1707 return NULL;
1709 ENTER_TCL
1710 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1711 ENTER_OVERLAP
1712 if (code == TCL_ERROR)
1713 res = Tkinter_Error(self);
1714 else {
1715 Py_INCREF(Py_None);
1716 res = Py_None;
1718 LEAVE_OVERLAP_TCL
1719 return res;
1722 static PyObject *
1723 Tkapp_UnsetVar(PyObject *self, PyObject *args)
1725 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1728 static PyObject *
1729 Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1731 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1736 /** Tcl to Python **/
1738 static PyObject *
1739 Tkapp_GetInt(PyObject *self, PyObject *args)
1741 char *s;
1742 int v;
1744 if (PyTuple_Size(args) == 1) {
1745 PyObject* o = PyTuple_GetItem(args, 0);
1746 if (PyInt_Check(o)) {
1747 Py_INCREF(o);
1748 return o;
1751 if (!PyArg_ParseTuple(args, "s:getint", &s))
1752 return NULL;
1753 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1754 return Tkinter_Error(self);
1755 return Py_BuildValue("i", v);
1758 static PyObject *
1759 Tkapp_GetDouble(PyObject *self, PyObject *args)
1761 char *s;
1762 double v;
1764 if (PyTuple_Size(args) == 1) {
1765 PyObject *o = PyTuple_GetItem(args, 0);
1766 if (PyFloat_Check(o)) {
1767 Py_INCREF(o);
1768 return o;
1771 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1772 return NULL;
1773 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1774 return Tkinter_Error(self);
1775 return Py_BuildValue("d", v);
1778 static PyObject *
1779 Tkapp_GetBoolean(PyObject *self, PyObject *args)
1781 char *s;
1782 int v;
1784 if (PyTuple_Size(args) == 1) {
1785 PyObject *o = PyTuple_GetItem(args, 0);
1786 if (PyInt_Check(o)) {
1787 Py_INCREF(o);
1788 return o;
1791 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1792 return NULL;
1793 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1794 return Tkinter_Error(self);
1795 return PyBool_FromLong(v);
1798 static PyObject *
1799 Tkapp_ExprString(PyObject *self, PyObject *args)
1801 char *s;
1802 PyObject *res = NULL;
1803 int retval;
1805 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1806 return NULL;
1808 CHECK_TCL_APPARTMENT;
1810 ENTER_TCL
1811 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1812 ENTER_OVERLAP
1813 if (retval == TCL_ERROR)
1814 res = Tkinter_Error(self);
1815 else
1816 res = Py_BuildValue("s", Tkapp_Result(self));
1817 LEAVE_OVERLAP_TCL
1818 return res;
1821 static PyObject *
1822 Tkapp_ExprLong(PyObject *self, PyObject *args)
1824 char *s;
1825 PyObject *res = NULL;
1826 int retval;
1827 long v;
1829 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1830 return NULL;
1832 CHECK_TCL_APPARTMENT;
1834 ENTER_TCL
1835 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1836 ENTER_OVERLAP
1837 if (retval == TCL_ERROR)
1838 res = Tkinter_Error(self);
1839 else
1840 res = Py_BuildValue("l", v);
1841 LEAVE_OVERLAP_TCL
1842 return res;
1845 static PyObject *
1846 Tkapp_ExprDouble(PyObject *self, PyObject *args)
1848 char *s;
1849 PyObject *res = NULL;
1850 double v;
1851 int retval;
1853 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1854 return NULL;
1855 CHECK_TCL_APPARTMENT;
1856 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1857 ENTER_TCL
1858 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1859 ENTER_OVERLAP
1860 PyFPE_END_PROTECT(retval)
1861 if (retval == TCL_ERROR)
1862 res = Tkinter_Error(self);
1863 else
1864 res = Py_BuildValue("d", v);
1865 LEAVE_OVERLAP_TCL
1866 return res;
1869 static PyObject *
1870 Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1872 char *s;
1873 PyObject *res = NULL;
1874 int retval;
1875 int v;
1877 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1878 return NULL;
1879 CHECK_TCL_APPARTMENT;
1880 ENTER_TCL
1881 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1882 ENTER_OVERLAP
1883 if (retval == TCL_ERROR)
1884 res = Tkinter_Error(self);
1885 else
1886 res = Py_BuildValue("i", v);
1887 LEAVE_OVERLAP_TCL
1888 return res;
1893 static PyObject *
1894 Tkapp_SplitList(PyObject *self, PyObject *args)
1896 char *list;
1897 int argc;
1898 char **argv;
1899 PyObject *v;
1900 int i;
1902 if (PyTuple_Size(args) == 1) {
1903 v = PyTuple_GetItem(args, 0);
1904 if (PyTuple_Check(v)) {
1905 Py_INCREF(v);
1906 return v;
1909 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1910 return NULL;
1912 if (Tcl_SplitList(Tkapp_Interp(self), list,
1913 &argc, &argv) == TCL_ERROR) {
1914 PyMem_Free(list);
1915 return Tkinter_Error(self);
1918 if (!(v = PyTuple_New(argc)))
1919 goto finally;
1921 for (i = 0; i < argc; i++) {
1922 PyObject *s = PyString_FromString(argv[i]);
1923 if (!s || PyTuple_SetItem(v, i, s)) {
1924 Py_DECREF(v);
1925 v = NULL;
1926 goto finally;
1930 finally:
1931 ckfree(FREECAST argv);
1932 PyMem_Free(list);
1933 return v;
1936 static PyObject *
1937 Tkapp_Split(PyObject *self, PyObject *args)
1939 PyObject *v;
1940 char *list;
1942 if (PyTuple_Size(args) == 1) {
1943 PyObject* o = PyTuple_GetItem(args, 0);
1944 if (PyTuple_Check(o)) {
1945 o = SplitObj(o);
1946 return o;
1949 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
1950 return NULL;
1951 v = Split(list);
1952 PyMem_Free(list);
1953 return v;
1956 static PyObject *
1957 Tkapp_Merge(PyObject *self, PyObject *args)
1959 char *s = Merge(args);
1960 PyObject *res = NULL;
1962 if (s) {
1963 res = PyString_FromString(s);
1964 ckfree(s);
1967 return res;
1972 /** Tcl Command **/
1974 /* Client data struct */
1975 typedef struct {
1976 PyObject *self;
1977 PyObject *func;
1978 } PythonCmd_ClientData;
1980 static int
1981 PythonCmd_Error(Tcl_Interp *interp)
1983 errorInCmd = 1;
1984 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1985 LEAVE_PYTHON
1986 return TCL_ERROR;
1989 /* This is the Tcl command that acts as a wrapper for Python
1990 * function or method.
1992 static int
1993 PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1995 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1996 PyObject *self, *func, *arg, *res;
1997 int i, rv;
1998 Tcl_Obj *obj_res;
2000 ENTER_PYTHON
2002 /* TBD: no error checking here since we know, via the
2003 * Tkapp_CreateCommand() that the client data is a two-tuple
2005 self = data->self;
2006 func = data->func;
2008 /* Create argument list (argv1, ..., argvN) */
2009 if (!(arg = PyTuple_New(argc - 1)))
2010 return PythonCmd_Error(interp);
2012 for (i = 0; i < (argc - 1); i++) {
2013 PyObject *s = PyString_FromString(argv[i + 1]);
2014 if (!s || PyTuple_SetItem(arg, i, s)) {
2015 Py_DECREF(arg);
2016 return PythonCmd_Error(interp);
2019 res = PyEval_CallObject(func, arg);
2020 Py_DECREF(arg);
2022 if (res == NULL)
2023 return PythonCmd_Error(interp);
2025 obj_res = AsObj(res);
2026 if (obj_res == NULL) {
2027 Py_DECREF(res);
2028 return PythonCmd_Error(interp);
2030 else {
2031 Tcl_SetObjResult(Tkapp_Interp(self), obj_res);
2032 rv = TCL_OK;
2035 Py_DECREF(res);
2037 LEAVE_PYTHON
2039 return rv;
2042 static void
2043 PythonCmdDelete(ClientData clientData)
2045 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2047 ENTER_PYTHON
2048 Py_XDECREF(data->self);
2049 Py_XDECREF(data->func);
2050 PyMem_DEL(data);
2051 LEAVE_PYTHON
2057 TCL_DECLARE_MUTEX(command_mutex)
2059 typedef struct CommandEvent{
2060 Tcl_Event ev;
2061 Tcl_Interp* interp;
2062 char *name;
2063 int create;
2064 int *status;
2065 ClientData *data;
2066 Tcl_Condition done;
2067 } CommandEvent;
2069 static int
2070 Tkapp_CommandProc(CommandEvent *ev, int flags)
2072 if (ev->create)
2073 *ev->status = Tcl_CreateCommand(
2074 ev->interp, ev->name, PythonCmd,
2075 ev->data, PythonCmdDelete) == NULL;
2076 else
2077 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2078 Tcl_MutexLock(&command_mutex);
2079 Tcl_ConditionNotify(&ev->done);
2080 Tcl_MutexUnlock(&command_mutex);
2081 return 1;
2084 static PyObject *
2085 Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2087 TkappObject *self = (TkappObject*)selfptr;
2088 PythonCmd_ClientData *data;
2089 char *cmdName;
2090 PyObject *func;
2091 int err;
2093 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2094 return NULL;
2095 if (!PyCallable_Check(func)) {
2096 PyErr_SetString(PyExc_TypeError, "command not callable");
2097 return NULL;
2100 #ifdef WITH_THREAD
2101 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2102 !WaitForMainloop(self))
2103 return NULL;
2104 #endif
2106 data = PyMem_NEW(PythonCmd_ClientData, 1);
2107 if (!data)
2108 return PyErr_NoMemory();
2109 Py_INCREF(self);
2110 Py_INCREF(func);
2111 data->self = selfptr;
2112 data->func = func;
2114 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2115 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2116 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2117 ev->interp = self->interp;
2118 ev->create = 1;
2119 ev->name = cmdName;
2120 ev->data = (ClientData)data;
2121 ev->status = &err;
2122 ev->done = NULL;
2123 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done, &command_mutex);
2125 else {
2126 ENTER_TCL
2127 err = Tcl_CreateCommand(
2128 Tkapp_Interp(self), cmdName, PythonCmd,
2129 (ClientData)data, PythonCmdDelete) == NULL;
2130 LEAVE_TCL
2132 if (err) {
2133 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2134 PyMem_DEL(data);
2135 return NULL;
2138 Py_INCREF(Py_None);
2139 return Py_None;
2144 static PyObject *
2145 Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2147 TkappObject *self = (TkappObject*)selfptr;
2148 char *cmdName;
2149 int err;
2151 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2152 return NULL;
2153 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2154 CommandEvent *ev;
2155 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2156 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2157 ev->interp = self->interp;
2158 ev->create = 0;
2159 ev->name = cmdName;
2160 ev->status = &err;
2161 ev->done = NULL;
2162 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &ev->done,
2163 &command_mutex);
2165 else {
2166 ENTER_TCL
2167 err = Tcl_DeleteCommand(self->interp, cmdName);
2168 LEAVE_TCL
2170 if (err == -1) {
2171 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2172 return NULL;
2174 Py_INCREF(Py_None);
2175 return Py_None;
2180 #ifdef HAVE_CREATEFILEHANDLER
2181 /** File Handler **/
2183 typedef struct _fhcdata {
2184 PyObject *func;
2185 PyObject *file;
2186 int id;
2187 struct _fhcdata *next;
2188 } FileHandler_ClientData;
2190 static FileHandler_ClientData *HeadFHCD;
2192 static FileHandler_ClientData *
2193 NewFHCD(PyObject *func, PyObject *file, int id)
2195 FileHandler_ClientData *p;
2196 p = PyMem_NEW(FileHandler_ClientData, 1);
2197 if (p != NULL) {
2198 Py_XINCREF(func);
2199 Py_XINCREF(file);
2200 p->func = func;
2201 p->file = file;
2202 p->id = id;
2203 p->next = HeadFHCD;
2204 HeadFHCD = p;
2206 return p;
2209 static void
2210 DeleteFHCD(int id)
2212 FileHandler_ClientData *p, **pp;
2214 pp = &HeadFHCD;
2215 while ((p = *pp) != NULL) {
2216 if (p->id == id) {
2217 *pp = p->next;
2218 Py_XDECREF(p->func);
2219 Py_XDECREF(p->file);
2220 PyMem_DEL(p);
2222 else
2223 pp = &p->next;
2227 static void
2228 FileHandler(ClientData clientData, int mask)
2230 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2231 PyObject *func, *file, *arg, *res;
2233 ENTER_PYTHON
2234 func = data->func;
2235 file = data->file;
2237 arg = Py_BuildValue("(Oi)", file, (long) mask);
2238 res = PyEval_CallObject(func, arg);
2239 Py_DECREF(arg);
2241 if (res == NULL) {
2242 errorInCmd = 1;
2243 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2245 Py_XDECREF(res);
2246 LEAVE_PYTHON
2249 static PyObject *
2250 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2251 /* args is (file, mask, func) */
2253 FileHandler_ClientData *data;
2254 PyObject *file, *func;
2255 int mask, tfile;
2257 if (!self && Py_Py3kWarningFlag) {
2258 if (PyErr_Warn(PyExc_DeprecationWarning,
2259 "_tkinter.createfilehandler is gone in 3.x") < 0)
2260 return NULL;
2263 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2264 &file, &mask, &func))
2265 return NULL;
2267 #ifdef WITH_THREAD
2268 if (!self && !tcl_lock) {
2269 /* We don't have the Tcl lock since Tcl is threaded. */
2270 PyErr_SetString(PyExc_RuntimeError,
2271 "_tkinter.createfilehandler not supported "
2272 "for threaded Tcl");
2273 return NULL;
2275 #endif
2277 if (self) {
2278 CHECK_TCL_APPARTMENT;
2281 tfile = PyObject_AsFileDescriptor(file);
2282 if (tfile < 0)
2283 return NULL;
2284 if (!PyCallable_Check(func)) {
2285 PyErr_SetString(PyExc_TypeError, "bad argument list");
2286 return NULL;
2289 data = NewFHCD(func, file, tfile);
2290 if (data == NULL)
2291 return NULL;
2293 /* Ought to check for null Tcl_File object... */
2294 ENTER_TCL
2295 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2296 LEAVE_TCL
2297 Py_INCREF(Py_None);
2298 return Py_None;
2301 static PyObject *
2302 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2304 PyObject *file;
2305 int tfile;
2307 if (!self && Py_Py3kWarningFlag) {
2308 if (PyErr_Warn(PyExc_DeprecationWarning,
2309 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2310 return NULL;
2313 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2314 return NULL;
2316 #ifdef WITH_THREAD
2317 if (!self && !tcl_lock) {
2318 /* We don't have the Tcl lock since Tcl is threaded. */
2319 PyErr_SetString(PyExc_RuntimeError,
2320 "_tkinter.deletefilehandler not supported "
2321 "for threaded Tcl");
2322 return NULL;
2324 #endif
2326 if (self) {
2327 CHECK_TCL_APPARTMENT;
2330 tfile = PyObject_AsFileDescriptor(file);
2331 if (tfile < 0)
2332 return NULL;
2334 DeleteFHCD(tfile);
2336 /* Ought to check for null Tcl_File object... */
2337 ENTER_TCL
2338 Tcl_DeleteFileHandler(tfile);
2339 LEAVE_TCL
2340 Py_INCREF(Py_None);
2341 return Py_None;
2343 #endif /* HAVE_CREATEFILEHANDLER */
2346 /**** Tktt Object (timer token) ****/
2348 static PyTypeObject Tktt_Type;
2350 typedef struct {
2351 PyObject_HEAD
2352 Tcl_TimerToken token;
2353 PyObject *func;
2354 } TkttObject;
2356 static PyObject *
2357 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2359 TkttObject *v = (TkttObject *)self;
2360 PyObject *func = v->func;
2362 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2363 return NULL;
2364 if (v->token != NULL) {
2365 Tcl_DeleteTimerHandler(v->token);
2366 v->token = NULL;
2368 if (func != NULL) {
2369 v->func = NULL;
2370 Py_DECREF(func);
2371 Py_DECREF(v); /* See Tktt_New() */
2373 Py_INCREF(Py_None);
2374 return Py_None;
2377 static PyMethodDef Tktt_methods[] =
2379 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2380 {NULL, NULL}
2383 static TkttObject *
2384 Tktt_New(PyObject *func)
2386 TkttObject *v;
2388 v = PyObject_New(TkttObject, &Tktt_Type);
2389 if (v == NULL)
2390 return NULL;
2392 Py_INCREF(func);
2393 v->token = NULL;
2394 v->func = func;
2396 /* Extra reference, deleted when called or when handler is deleted */
2397 Py_INCREF(v);
2398 return v;
2401 static void
2402 Tktt_Dealloc(PyObject *self)
2404 TkttObject *v = (TkttObject *)self;
2405 PyObject *func = v->func;
2407 Py_XDECREF(func);
2409 PyObject_Del(self);
2412 static PyObject *
2413 Tktt_Repr(PyObject *self)
2415 TkttObject *v = (TkttObject *)self;
2416 char buf[100];
2418 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2419 v->func == NULL ? ", handler deleted" : "");
2420 return PyString_FromString(buf);
2423 static PyObject *
2424 Tktt_GetAttr(PyObject *self, char *name)
2426 return Py_FindMethod(Tktt_methods, self, name);
2429 static PyTypeObject Tktt_Type =
2431 PyVarObject_HEAD_INIT(NULL, 0)
2432 "tktimertoken", /*tp_name */
2433 sizeof(TkttObject), /*tp_basicsize */
2434 0, /*tp_itemsize */
2435 Tktt_Dealloc, /*tp_dealloc */
2436 0, /*tp_print */
2437 Tktt_GetAttr, /*tp_getattr */
2438 0, /*tp_setattr */
2439 0, /*tp_compare */
2440 Tktt_Repr, /*tp_repr */
2441 0, /*tp_as_number */
2442 0, /*tp_as_sequence */
2443 0, /*tp_as_mapping */
2444 0, /*tp_hash */
2449 /** Timer Handler **/
2451 static void
2452 TimerHandler(ClientData clientData)
2454 TkttObject *v = (TkttObject *)clientData;
2455 PyObject *func = v->func;
2456 PyObject *res;
2458 if (func == NULL)
2459 return;
2461 v->func = NULL;
2463 ENTER_PYTHON
2465 res = PyEval_CallObject(func, NULL);
2466 Py_DECREF(func);
2467 Py_DECREF(v); /* See Tktt_New() */
2469 if (res == NULL) {
2470 errorInCmd = 1;
2471 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2473 else
2474 Py_DECREF(res);
2476 LEAVE_PYTHON
2479 static PyObject *
2480 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2482 int milliseconds;
2483 PyObject *func;
2484 TkttObject *v;
2486 if (!self && Py_Py3kWarningFlag) {
2487 if (PyErr_Warn(PyExc_DeprecationWarning,
2488 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2489 return NULL;
2492 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2493 &milliseconds, &func))
2494 return NULL;
2495 if (!PyCallable_Check(func)) {
2496 PyErr_SetString(PyExc_TypeError, "bad argument list");
2497 return NULL;
2500 #ifdef WITH_THREAD
2501 if (!self && !tcl_lock) {
2502 /* We don't have the Tcl lock since Tcl is threaded. */
2503 PyErr_SetString(PyExc_RuntimeError,
2504 "_tkinter.createtimerhandler not supported "
2505 "for threaded Tcl");
2506 return NULL;
2508 #endif
2510 if (self) {
2511 CHECK_TCL_APPARTMENT;
2514 v = Tktt_New(func);
2515 if (v) {
2516 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2517 (ClientData)v);
2520 return (PyObject *) v;
2524 /** Event Loop **/
2526 static PyObject *
2527 Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
2529 int threshold = 0;
2530 TkappObject *self = (TkappObject*)selfptr;
2531 #ifdef WITH_THREAD
2532 PyThreadState *tstate = PyThreadState_Get();
2533 #endif
2535 if (!self && Py_Py3kWarningFlag) {
2536 if (PyErr_Warn(PyExc_DeprecationWarning,
2537 "_tkinter.mainloop is gone in 3.x") < 0)
2538 return NULL;
2541 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2542 return NULL;
2544 #ifdef WITH_THREAD
2545 if (!self && !tcl_lock) {
2546 /* We don't have the Tcl lock since Tcl is threaded. */
2547 PyErr_SetString(PyExc_RuntimeError,
2548 "_tkinter.mainloop not supported "
2549 "for threaded Tcl");
2550 return NULL;
2552 #endif
2554 if (self) {
2555 CHECK_TCL_APPARTMENT;
2556 self->dispatching = 1;
2559 quitMainLoop = 0;
2560 while (Tk_GetNumMainWindows() > threshold &&
2561 !quitMainLoop &&
2562 !errorInCmd)
2564 int result;
2566 #ifdef WITH_THREAD
2567 if (self && self->threaded) {
2568 /* Allow other Python threads to run. */
2569 ENTER_TCL
2570 result = Tcl_DoOneEvent(0);
2571 LEAVE_TCL
2573 else {
2574 Py_BEGIN_ALLOW_THREADS
2575 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2576 tcl_tstate = tstate;
2577 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2578 tcl_tstate = NULL;
2579 if(tcl_lock)PyThread_release_lock(tcl_lock);
2580 if (result == 0)
2581 Sleep(Tkinter_busywaitinterval);
2582 Py_END_ALLOW_THREADS
2584 #else
2585 result = Tcl_DoOneEvent(0);
2586 #endif
2588 if (PyErr_CheckSignals() != 0) {
2589 if (self)
2590 self->dispatching = 0;
2591 return NULL;
2593 if (result < 0)
2594 break;
2596 if (self)
2597 self->dispatching = 0;
2598 quitMainLoop = 0;
2600 if (errorInCmd) {
2601 errorInCmd = 0;
2602 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2603 excInCmd = valInCmd = trbInCmd = NULL;
2604 return NULL;
2606 Py_INCREF(Py_None);
2607 return Py_None;
2610 static PyObject *
2611 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
2613 int flags = 0;
2614 int rv;
2616 if (!self && Py_Py3kWarningFlag) {
2617 if (PyErr_Warn(PyExc_DeprecationWarning,
2618 "_tkinter.dooneevent is gone in 3.x") < 0)
2619 return NULL;
2622 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2623 return NULL;
2625 ENTER_TCL
2626 rv = Tcl_DoOneEvent(flags);
2627 LEAVE_TCL
2628 return Py_BuildValue("i", rv);
2631 static PyObject *
2632 Tkapp_Quit(PyObject *self, PyObject *args)
2635 if (!self && Py_Py3kWarningFlag) {
2636 if (PyErr_Warn(PyExc_DeprecationWarning,
2637 "_tkinter.createfilehandler is gone in 3.x") < 0)
2638 return NULL;
2641 if (!PyArg_ParseTuple(args, ":quit"))
2642 return NULL;
2644 quitMainLoop = 1;
2645 Py_INCREF(Py_None);
2646 return Py_None;
2649 static PyObject *
2650 Tkapp_InterpAddr(PyObject *self, PyObject *args)
2653 if (!PyArg_ParseTuple(args, ":interpaddr"))
2654 return NULL;
2656 return PyInt_FromLong((long)Tkapp_Interp(self));
2659 static PyObject *
2660 Tkapp_TkInit(PyObject *self, PyObject *args)
2662 static int has_failed;
2663 Tcl_Interp *interp = Tkapp_Interp(self);
2664 Tk_Window main_window;
2665 const char * _tk_exists = NULL;
2666 int err;
2667 main_window = Tk_MainWindow(interp);
2669 /* In all current versions of Tk (including 8.4.13), Tk_Init
2670 deadlocks on the second call when the first call failed.
2671 To avoid the deadlock, we just refuse the second call through
2672 a static variable. */
2673 if (has_failed) {
2674 PyErr_SetString(Tkinter_TclError,
2675 "Calling Tk_Init again after a previous call failed might deadlock");
2676 return NULL;
2679 /* We want to guard against calling Tk_Init() multiple times */
2680 CHECK_TCL_APPARTMENT;
2681 ENTER_TCL
2682 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2683 ENTER_OVERLAP
2684 if (err == TCL_ERROR) {
2685 /* This sets an exception, but we cannot return right
2686 away because we need to exit the overlap first. */
2687 Tkinter_Error(self);
2688 } else {
2689 _tk_exists = Tkapp_Result(self);
2691 LEAVE_OVERLAP_TCL
2692 if (err == TCL_ERROR) {
2693 return NULL;
2695 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2696 if (Tk_Init(interp) == TCL_ERROR) {
2697 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2698 has_failed = 1;
2699 return NULL;
2702 Py_INCREF(Py_None);
2703 return Py_None;
2706 static PyObject *
2707 Tkapp_WantObjects(PyObject *self, PyObject *args)
2710 int wantobjects = -1;
2711 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2712 return NULL;
2713 if (wantobjects == -1)
2714 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2715 ((TkappObject*)self)->wantobjects = wantobjects;
2717 Py_INCREF(Py_None);
2718 return Py_None;
2721 static PyObject *
2722 Tkapp_WillDispatch(PyObject *self, PyObject *args)
2725 ((TkappObject*)self)->dispatching = 1;
2727 Py_INCREF(Py_None);
2728 return Py_None;
2732 /**** Tkapp Method List ****/
2734 static PyMethodDef Tkapp_methods[] =
2736 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2737 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2738 {"call", Tkapp_Call, METH_VARARGS},
2739 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2740 {"eval", Tkapp_Eval, METH_VARARGS},
2741 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2742 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2743 {"record", Tkapp_Record, METH_VARARGS},
2744 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2745 {"setvar", Tkapp_SetVar, METH_VARARGS},
2746 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2747 {"getvar", Tkapp_GetVar, METH_VARARGS},
2748 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2749 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2750 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2751 {"getint", Tkapp_GetInt, METH_VARARGS},
2752 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2753 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2754 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2755 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2756 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2757 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2758 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2759 {"split", Tkapp_Split, METH_VARARGS},
2760 {"merge", Tkapp_Merge, METH_VARARGS},
2761 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2762 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2763 #ifdef HAVE_CREATEFILEHANDLER
2764 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2765 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2766 #endif
2767 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2768 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2769 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2770 {"quit", Tkapp_Quit, METH_VARARGS},
2771 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2772 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2773 {NULL, NULL}
2778 /**** Tkapp Type Methods ****/
2780 static void
2781 Tkapp_Dealloc(PyObject *self)
2783 /*CHECK_TCL_APPARTMENT;*/
2784 ENTER_TCL
2785 Tcl_DeleteInterp(Tkapp_Interp(self));
2786 LEAVE_TCL
2787 PyObject_Del(self);
2788 DisableEventHook();
2791 static PyObject *
2792 Tkapp_GetAttr(PyObject *self, char *name)
2794 return Py_FindMethod(Tkapp_methods, self, name);
2797 static PyTypeObject Tkapp_Type =
2799 PyVarObject_HEAD_INIT(NULL, 0)
2800 "tkapp", /*tp_name */
2801 sizeof(TkappObject), /*tp_basicsize */
2802 0, /*tp_itemsize */
2803 Tkapp_Dealloc, /*tp_dealloc */
2804 0, /*tp_print */
2805 Tkapp_GetAttr, /*tp_getattr */
2806 0, /*tp_setattr */
2807 0, /*tp_compare */
2808 0, /*tp_repr */
2809 0, /*tp_as_number */
2810 0, /*tp_as_sequence */
2811 0, /*tp_as_mapping */
2812 0, /*tp_hash */
2817 /**** Tkinter Module ****/
2819 typedef struct {
2820 PyObject* tuple;
2821 int size; /* current size */
2822 int maxsize; /* allocated size */
2823 } FlattenContext;
2825 static int
2826 _bump(FlattenContext* context, int size)
2828 /* expand tuple to hold (at least) size new items.
2829 return true if successful, false if an exception was raised */
2831 int maxsize = context->maxsize * 2;
2833 if (maxsize < context->size + size)
2834 maxsize = context->size + size;
2836 context->maxsize = maxsize;
2838 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2841 static int
2842 _flatten1(FlattenContext* context, PyObject* item, int depth)
2844 /* add tuple or list to argument tuple (recursively) */
2846 int i, size;
2848 if (depth > 1000) {
2849 PyErr_SetString(PyExc_ValueError,
2850 "nesting too deep in _flatten");
2851 return 0;
2852 } else if (PyList_Check(item)) {
2853 size = PyList_GET_SIZE(item);
2854 /* preallocate (assume no nesting) */
2855 if (context->size + size > context->maxsize &&
2856 !_bump(context, size))
2857 return 0;
2858 /* copy items to output tuple */
2859 for (i = 0; i < size; i++) {
2860 PyObject *o = PyList_GET_ITEM(item, i);
2861 if (PyList_Check(o) || PyTuple_Check(o)) {
2862 if (!_flatten1(context, o, depth + 1))
2863 return 0;
2864 } else if (o != Py_None) {
2865 if (context->size + 1 > context->maxsize &&
2866 !_bump(context, 1))
2867 return 0;
2868 Py_INCREF(o);
2869 PyTuple_SET_ITEM(context->tuple,
2870 context->size++, o);
2873 } else if (PyTuple_Check(item)) {
2874 /* same, for tuples */
2875 size = PyTuple_GET_SIZE(item);
2876 if (context->size + size > context->maxsize &&
2877 !_bump(context, size))
2878 return 0;
2879 for (i = 0; i < size; i++) {
2880 PyObject *o = PyTuple_GET_ITEM(item, i);
2881 if (PyList_Check(o) || PyTuple_Check(o)) {
2882 if (!_flatten1(context, o, depth + 1))
2883 return 0;
2884 } else if (o != Py_None) {
2885 if (context->size + 1 > context->maxsize &&
2886 !_bump(context, 1))
2887 return 0;
2888 Py_INCREF(o);
2889 PyTuple_SET_ITEM(context->tuple,
2890 context->size++, o);
2893 } else {
2894 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2895 return 0;
2897 return 1;
2900 static PyObject *
2901 Tkinter_Flatten(PyObject* self, PyObject* args)
2903 FlattenContext context;
2904 PyObject* item;
2906 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2907 return NULL;
2909 context.maxsize = PySequence_Size(item);
2910 if (context.maxsize < 0)
2911 return NULL;
2912 if (context.maxsize == 0)
2913 return PyTuple_New(0);
2915 context.tuple = PyTuple_New(context.maxsize);
2916 if (!context.tuple)
2917 return NULL;
2919 context.size = 0;
2921 if (!_flatten1(&context, item,0))
2922 return NULL;
2924 if (_PyTuple_Resize(&context.tuple, context.size))
2925 return NULL;
2927 return context.tuple;
2930 static PyObject *
2931 Tkinter_Create(PyObject *self, PyObject *args)
2933 char *screenName = NULL;
2934 char *baseName = NULL;
2935 char *className = NULL;
2936 int interactive = 0;
2937 int wantobjects = 0;
2938 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2939 int sync = 0; /* pass -sync to wish */
2940 char *use = NULL; /* pass -use to wish */
2942 baseName = strrchr(Py_GetProgramName(), '/');
2943 if (baseName != NULL)
2944 baseName++;
2945 else
2946 baseName = Py_GetProgramName();
2947 className = "Tk";
2949 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2950 &screenName, &baseName, &className,
2951 &interactive, &wantobjects, &wantTk,
2952 &sync, &use))
2953 return NULL;
2955 return (PyObject *) Tkapp_New(screenName, baseName, className,
2956 interactive, wantobjects, wantTk,
2957 sync, use);
2960 static PyObject *
2961 Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2963 int new_val;
2964 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2965 return NULL;
2966 if (new_val < 0) {
2967 PyErr_SetString(PyExc_ValueError,
2968 "busywaitinterval must be >= 0");
2969 return NULL;
2971 Tkinter_busywaitinterval = new_val;
2972 Py_INCREF(Py_None);
2973 return Py_None;
2976 static char setbusywaitinterval_doc[] =
2977 "setbusywaitinterval(n) -> None\n\
2979 Set the busy-wait interval in milliseconds between successive\n\
2980 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2981 It should be set to a divisor of the maximum time between\n\
2982 frames in an animation.";
2984 static PyObject *
2985 Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
2987 return PyInt_FromLong(Tkinter_busywaitinterval);
2990 static char getbusywaitinterval_doc[] =
2991 "getbusywaitinterval() -> int\n\
2993 Return the current busy-wait interval between successive\n\
2994 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2996 static PyMethodDef moduleMethods[] =
2998 {"_flatten", Tkinter_Flatten, METH_VARARGS},
2999 {"create", Tkinter_Create, METH_VARARGS},
3000 #ifdef HAVE_CREATEFILEHANDLER
3001 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3002 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
3003 #endif
3004 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3005 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3006 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3007 {"quit", Tkapp_Quit, METH_VARARGS},
3008 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3009 setbusywaitinterval_doc},
3010 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3011 METH_NOARGS, getbusywaitinterval_doc},
3012 {NULL, NULL}
3015 #ifdef WAIT_FOR_STDIN
3017 static int stdin_ready = 0;
3019 #ifndef MS_WINDOWS
3020 static void
3021 MyFileProc(void *clientData, int mask)
3023 stdin_ready = 1;
3025 #endif
3027 #ifdef WITH_THREAD
3028 static PyThreadState *event_tstate = NULL;
3029 #endif
3031 static int
3032 EventHook(void)
3034 #ifndef MS_WINDOWS
3035 int tfile;
3036 #endif
3037 #ifdef WITH_THREAD
3038 PyEval_RestoreThread(event_tstate);
3039 #endif
3040 stdin_ready = 0;
3041 errorInCmd = 0;
3042 #ifndef MS_WINDOWS
3043 tfile = fileno(stdin);
3044 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
3045 #endif
3046 while (!errorInCmd && !stdin_ready) {
3047 int result;
3048 #ifdef MS_WINDOWS
3049 if (_kbhit()) {
3050 stdin_ready = 1;
3051 break;
3053 #endif
3054 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3055 Py_BEGIN_ALLOW_THREADS
3056 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3057 tcl_tstate = event_tstate;
3059 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3061 tcl_tstate = NULL;
3062 if(tcl_lock)PyThread_release_lock(tcl_lock);
3063 if (result == 0)
3064 Sleep(Tkinter_busywaitinterval);
3065 Py_END_ALLOW_THREADS
3066 #else
3067 result = Tcl_DoOneEvent(0);
3068 #endif
3070 if (result < 0)
3071 break;
3073 #ifndef MS_WINDOWS
3074 Tcl_DeleteFileHandler(tfile);
3075 #endif
3076 if (errorInCmd) {
3077 errorInCmd = 0;
3078 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3079 excInCmd = valInCmd = trbInCmd = NULL;
3080 PyErr_Print();
3082 #ifdef WITH_THREAD
3083 PyEval_SaveThread();
3084 #endif
3085 return 0;
3088 #endif
3090 static void
3091 EnableEventHook(void)
3093 #ifdef WAIT_FOR_STDIN
3094 if (PyOS_InputHook == NULL) {
3095 #ifdef WITH_THREAD
3096 event_tstate = PyThreadState_Get();
3097 #endif
3098 PyOS_InputHook = EventHook;
3100 #endif
3103 static void
3104 DisableEventHook(void)
3106 #ifdef WAIT_FOR_STDIN
3107 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3108 PyOS_InputHook = NULL;
3110 #endif
3114 /* all errors will be checked in one fell swoop in init_tkinter() */
3115 static void
3116 ins_long(PyObject *d, char *name, long val)
3118 PyObject *v = PyInt_FromLong(val);
3119 if (v) {
3120 PyDict_SetItemString(d, name, v);
3121 Py_DECREF(v);
3124 static void
3125 ins_string(PyObject *d, char *name, char *val)
3127 PyObject *v = PyString_FromString(val);
3128 if (v) {
3129 PyDict_SetItemString(d, name, v);
3130 Py_DECREF(v);
3135 PyMODINIT_FUNC
3136 init_tkinter(void)
3138 PyObject *m, *d;
3140 Py_TYPE(&Tkapp_Type) = &PyType_Type;
3142 #ifdef WITH_THREAD
3143 tcl_lock = PyThread_allocate_lock();
3144 #endif
3146 m = Py_InitModule("_tkinter", moduleMethods);
3147 if (m == NULL)
3148 return;
3150 d = PyModule_GetDict(m);
3151 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3152 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3154 ins_long(d, "READABLE", TCL_READABLE);
3155 ins_long(d, "WRITABLE", TCL_WRITABLE);
3156 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3157 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3158 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3159 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3160 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3161 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3162 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3163 ins_string(d, "TK_VERSION", TK_VERSION);
3164 ins_string(d, "TCL_VERSION", TCL_VERSION);
3166 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3168 Py_TYPE(&Tktt_Type) = &PyType_Type;
3169 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3171 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3172 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3174 #ifdef TK_AQUA
3175 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3176 * start waking up. Note that Tcl_FindExecutable will do this, this
3177 * code must be above it! The original warning from
3178 * tkMacOSXAppInit.c is copied below.
3180 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3181 * Tcl interpreter for now. It probably should work to do this
3182 * in the other order, but for now it doesn't seem to.
3185 Tk_MacOSXSetupTkNotifier();
3186 #endif
3189 /* This helps the dynamic loader; in Unicode aware Tcl versions
3190 it also helps Tcl find its encodings. */
3191 Tcl_FindExecutable(Py_GetProgramName());
3193 if (PyErr_Occurred())
3194 return;
3196 #if 0
3197 /* This was not a good idea; through <Destroy> bindings,
3198 Tcl_Finalize() may invoke Python code but at that point the
3199 interpreter and thread state have already been destroyed! */
3200 Py_AtExit(Tcl_Finalize);
3201 #endif