Fix compilation error with gcc 4.3.2
[python.git] / Modules / _tkinter.c
blobea36297c382c977848c94c592946827bc120a43b
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.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
14 Tcl/Tk 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 #include "tkinter.h"
72 /* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
73 #ifndef CONST84_RETURN
74 #define CONST84_RETURN
75 #undef CONST
76 #define CONST
77 #endif
79 #if TK_VERSION_HEX < 0x08030102
80 #error "Tk older than 8.3.1 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;
283 #ifdef TKINTER_PROTECT_LOADTK
284 static int tk_load_failed;
285 #endif
288 static PyObject *
289 Tkinter_Error(PyObject *v)
291 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
292 return NULL;
297 /**** Utils ****/
299 static int Tkinter_busywaitinterval = 20;
301 #ifdef WITH_THREAD
302 #ifndef MS_WINDOWS
304 /* Millisecond sleep() for Unix platforms. */
306 static void
307 Sleep(int milli)
309 /* XXX Too bad if you don't have select(). */
310 struct timeval t;
311 t.tv_sec = milli/1000;
312 t.tv_usec = (milli%1000) * 1000;
313 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
315 #endif /* MS_WINDOWS */
317 /* Wait up to 1s for the mainloop to come up. */
319 static int
320 WaitForMainloop(TkappObject* self)
322 int i;
323 for (i = 0; i < 10; i++) {
324 if (self->dispatching)
325 return 1;
326 Py_BEGIN_ALLOW_THREADS
327 Sleep(100);
328 Py_END_ALLOW_THREADS
330 if (self->dispatching)
331 return 1;
332 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
333 return 0;
335 #endif /* WITH_THREAD */
338 static char *
339 AsString(PyObject *value, PyObject *tmp)
341 if (PyString_Check(value))
342 return PyString_AsString(value);
343 #ifdef Py_USING_UNICODE
344 else if (PyUnicode_Check(value)) {
345 PyObject *v = PyUnicode_AsUTF8String(value);
346 if (v == NULL)
347 return NULL;
348 if (PyList_Append(tmp, v) != 0) {
349 Py_DECREF(v);
350 return NULL;
352 Py_DECREF(v);
353 return PyString_AsString(v);
355 #endif
356 else {
357 PyObject *v = PyObject_Str(value);
358 if (v == NULL)
359 return NULL;
360 if (PyList_Append(tmp, v) != 0) {
361 Py_DECREF(v);
362 return NULL;
364 Py_DECREF(v);
365 return PyString_AsString(v);
371 #define ARGSZ 64
373 static char *
374 Merge(PyObject *args)
376 PyObject *tmp = NULL;
377 char *argvStore[ARGSZ];
378 char **argv = NULL;
379 int fvStore[ARGSZ];
380 int *fv = NULL;
381 int argc = 0, fvc = 0, i;
382 char *res = NULL;
384 if (!(tmp = PyList_New(0)))
385 return NULL;
387 argv = argvStore;
388 fv = fvStore;
390 if (args == NULL)
391 argc = 0;
393 else if (!PyTuple_Check(args)) {
394 argc = 1;
395 fv[0] = 0;
396 if (!(argv[0] = AsString(args, tmp)))
397 goto finally;
399 else {
400 argc = PyTuple_Size(args);
402 if (argc > ARGSZ) {
403 argv = (char **)ckalloc(argc * sizeof(char *));
404 fv = (int *)ckalloc(argc * sizeof(int));
405 if (argv == NULL || fv == NULL) {
406 PyErr_NoMemory();
407 goto finally;
411 for (i = 0; i < argc; i++) {
412 PyObject *v = PyTuple_GetItem(args, i);
413 if (PyTuple_Check(v)) {
414 fv[i] = 1;
415 if (!(argv[i] = Merge(v)))
416 goto finally;
417 fvc++;
419 else if (v == Py_None) {
420 argc = i;
421 break;
423 else {
424 fv[i] = 0;
425 if (!(argv[i] = AsString(v, tmp)))
426 goto finally;
427 fvc++;
431 res = Tcl_Merge(argc, argv);
432 if (res == NULL)
433 PyErr_SetString(Tkinter_TclError, "merge failed");
435 finally:
436 for (i = 0; i < fvc; i++)
437 if (fv[i]) {
438 ckfree(argv[i]);
440 if (argv != argvStore)
441 ckfree(FREECAST argv);
442 if (fv != fvStore)
443 ckfree(FREECAST fv);
445 Py_DECREF(tmp);
446 return res;
451 static PyObject *
452 Split(char *list)
454 int argc;
455 char **argv;
456 PyObject *v;
458 if (list == NULL) {
459 Py_INCREF(Py_None);
460 return Py_None;
463 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
464 /* Not a list.
465 * Could be a quoted string containing funnies, e.g. {"}.
466 * Return the string itself.
468 return PyString_FromString(list);
471 if (argc == 0)
472 v = PyString_FromString("");
473 else if (argc == 1)
474 v = PyString_FromString(argv[0]);
475 else if ((v = PyTuple_New(argc)) != NULL) {
476 int i;
477 PyObject *w;
479 for (i = 0; i < argc; i++) {
480 if ((w = Split(argv[i])) == NULL) {
481 Py_DECREF(v);
482 v = NULL;
483 break;
485 PyTuple_SetItem(v, i, w);
488 Tcl_Free(FREECAST argv);
489 return v;
492 /* In some cases, Tcl will still return strings that are supposed to be
493 lists. SplitObj walks through a nested tuple, finding string objects that
494 need to be split. */
496 static PyObject *
497 SplitObj(PyObject *arg)
499 if (PyTuple_Check(arg)) {
500 int i, size;
501 PyObject *elem, *newelem, *result;
503 size = PyTuple_Size(arg);
504 result = NULL;
505 /* Recursively invoke SplitObj for all tuple items.
506 If this does not return a new object, no action is
507 needed. */
508 for(i = 0; i < size; i++) {
509 elem = PyTuple_GetItem(arg, i);
510 newelem = SplitObj(elem);
511 if (!newelem) {
512 Py_XDECREF(result);
513 return NULL;
515 if (!result) {
516 int k;
517 if (newelem == elem) {
518 Py_DECREF(newelem);
519 continue;
521 result = PyTuple_New(size);
522 if (!result)
523 return NULL;
524 for(k = 0; k < i; k++) {
525 elem = PyTuple_GetItem(arg, k);
526 Py_INCREF(elem);
527 PyTuple_SetItem(result, k, elem);
530 PyTuple_SetItem(result, i, newelem);
532 if (result)
533 return result;
534 /* Fall through, returning arg. */
536 else if (PyString_Check(arg)) {
537 int argc;
538 char **argv;
539 char *list = PyString_AsString(arg);
541 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
542 Py_INCREF(arg);
543 return arg;
545 Tcl_Free(FREECAST argv);
546 if (argc > 1)
547 return Split(PyString_AsString(arg));
548 /* Fall through, returning arg. */
550 Py_INCREF(arg);
551 return arg;
555 /**** Tkapp Object ****/
557 #ifndef WITH_APPINIT
559 Tcl_AppInit(Tcl_Interp *interp)
561 const char * _tkinter_skip_tk_init;
563 if (Tcl_Init(interp) == TCL_ERROR) {
564 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
565 return TCL_ERROR;
568 _tkinter_skip_tk_init = Tcl_GetVar(interp,
569 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
570 if (_tkinter_skip_tk_init != NULL &&
571 strcmp(_tkinter_skip_tk_init, "1") == 0) {
572 return TCL_OK;
575 #ifdef TKINTER_PROTECT_LOADTK
576 if (tk_load_failed) {
577 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
578 return TCL_ERROR;
580 #endif
582 if (Tk_Init(interp) == TCL_ERROR) {
583 #ifdef TKINTER_PROTECT_LOADTK
584 tk_load_failed = 1;
585 #endif
586 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
587 return TCL_ERROR;
590 return TCL_OK;
592 #endif /* !WITH_APPINIT */
597 /* Initialize the Tk application; see the `main' function in
598 * `tkMain.c'.
601 static void EnableEventHook(void); /* Forward */
602 static void DisableEventHook(void); /* Forward */
604 static TkappObject *
605 Tkapp_New(char *screenName, char *baseName, char *className,
606 int interactive, int wantobjects, int wantTk, int sync, char *use)
608 TkappObject *v;
609 char *argv0;
611 v = PyObject_New(TkappObject, &Tkapp_Type);
612 if (v == NULL)
613 return NULL;
615 v->interp = Tcl_CreateInterp();
616 v->wantobjects = wantobjects;
617 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
618 TCL_GLOBAL_ONLY) != NULL;
619 v->thread_id = Tcl_GetCurrentThread();
620 v->dispatching = 0;
622 #ifndef TCL_THREADS
623 if (v->threaded) {
624 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
625 Py_DECREF(v);
626 return 0;
628 #endif
629 #ifdef WITH_THREAD
630 if (v->threaded && tcl_lock) {
631 /* If Tcl is threaded, we don't need the lock. */
632 PyThread_free_lock(tcl_lock);
633 tcl_lock = NULL;
635 #endif
637 v->BooleanType = Tcl_GetObjType("boolean");
638 v->ByteArrayType = Tcl_GetObjType("bytearray");
639 v->DoubleType = Tcl_GetObjType("double");
640 v->IntType = Tcl_GetObjType("int");
641 v->ListType = Tcl_GetObjType("list");
642 v->ProcBodyType = Tcl_GetObjType("procbody");
643 v->StringType = Tcl_GetObjType("string");
645 /* Delete the 'exit' command, which can screw things up */
646 Tcl_DeleteCommand(v->interp, "exit");
648 if (screenName != NULL)
649 Tcl_SetVar2(v->interp, "env", "DISPLAY",
650 screenName, TCL_GLOBAL_ONLY);
652 if (interactive)
653 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
654 else
655 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
657 /* This is used to get the application class for Tk 4.1 and up */
658 argv0 = (char*)ckalloc(strlen(className) + 1);
659 if (!argv0) {
660 PyErr_NoMemory();
661 Py_DECREF(v);
662 return NULL;
665 strcpy(argv0, className);
666 if (isupper(Py_CHARMASK(argv0[0])))
667 argv0[0] = tolower(Py_CHARMASK(argv0[0]));
668 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
669 ckfree(argv0);
671 if (! wantTk) {
672 Tcl_SetVar(v->interp,
673 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
675 #ifdef TKINTER_PROTECT_LOADTK
676 else if (tk_load_failed) {
677 Tcl_SetVar(v->interp,
678 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
680 #endif
682 /* some initial arguments need to be in argv */
683 if (sync || use) {
684 char *args;
685 int len = 0;
687 if (sync)
688 len += sizeof "-sync";
689 if (use)
690 len += strlen(use) + sizeof "-use ";
692 args = (char*)ckalloc(len);
693 if (!args) {
694 PyErr_NoMemory();
695 Py_DECREF(v);
696 return NULL;
699 args[0] = '\0';
700 if (sync)
701 strcat(args, "-sync");
702 if (use) {
703 if (sync)
704 strcat(args, " ");
705 strcat(args, "-use ");
706 strcat(args, use);
709 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
710 ckfree(args);
713 if (Tcl_AppInit(v->interp) != TCL_OK) {
714 PyObject *result = Tkinter_Error((PyObject *)v);
715 #ifdef TKINTER_PROTECT_LOADTK
716 if (wantTk) {
717 const char *_tkinter_tk_failed;
718 _tkinter_tk_failed = Tcl_GetVar(v->interp,
719 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
721 if ( _tkinter_tk_failed != NULL &&
722 strcmp(_tkinter_tk_failed, "1") == 0) {
723 tk_load_failed = 1;
726 #endif
727 Py_DECREF((PyObject *)v);
728 return (TkappObject *)result;
731 EnableEventHook();
733 return v;
737 #ifdef WITH_THREAD
738 static void
739 Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
740 Tcl_Condition *cond, Tcl_Mutex *mutex)
742 Py_BEGIN_ALLOW_THREADS;
743 Tcl_MutexLock(mutex);
744 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
745 Tcl_ThreadAlert(self->thread_id);
746 Tcl_ConditionWait(cond, mutex, NULL);
747 Tcl_MutexUnlock(mutex);
748 Py_END_ALLOW_THREADS
750 #endif
753 /** Tcl Eval **/
755 typedef struct {
756 PyObject_HEAD
757 Tcl_Obj *value;
758 PyObject *string; /* This cannot cause cycles. */
759 } PyTclObject;
761 staticforward PyTypeObject PyTclObject_Type;
762 #define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
764 static PyObject *
765 newPyTclObject(Tcl_Obj *arg)
767 PyTclObject *self;
768 self = PyObject_New(PyTclObject, &PyTclObject_Type);
769 if (self == NULL)
770 return NULL;
771 Tcl_IncrRefCount(arg);
772 self->value = arg;
773 self->string = NULL;
774 return (PyObject*)self;
777 static void
778 PyTclObject_dealloc(PyTclObject *self)
780 Tcl_DecrRefCount(self->value);
781 Py_XDECREF(self->string);
782 PyObject_Del(self);
785 static PyObject *
786 PyTclObject_str(PyTclObject *self)
788 if (self->string && PyString_Check(self->string)) {
789 Py_INCREF(self->string);
790 return self->string;
792 /* XXX Could cache value if it is an ASCII string. */
793 return PyString_FromString(Tcl_GetString(self->value));
796 static char*
797 PyTclObject_TclString(PyObject *self)
799 return Tcl_GetString(((PyTclObject*)self)->value);
802 /* Like _str, but create Unicode if necessary. */
803 PyDoc_STRVAR(PyTclObject_string__doc__,
804 "the string representation of this object, either as string or Unicode");
806 static PyObject *
807 PyTclObject_string(PyTclObject *self, void *ignored)
809 char *s;
810 int i, len;
811 if (!self->string) {
812 s = Tcl_GetStringFromObj(self->value, &len);
813 for (i = 0; i < len; i++)
814 if (s[i] & 0x80)
815 break;
816 #ifdef Py_USING_UNICODE
817 if (i == len)
818 /* It is an ASCII string. */
819 self->string = PyString_FromStringAndSize(s, len);
820 else {
821 self->string = PyUnicode_DecodeUTF8(s, len, "strict");
822 if (!self->string) {
823 PyErr_Clear();
824 self->string = PyString_FromStringAndSize(s, len);
827 #else
828 self->string = PyString_FromStringAndSize(s, len);
829 #endif
830 if (!self->string)
831 return NULL;
833 Py_INCREF(self->string);
834 return self->string;
837 #ifdef Py_USING_UNICODE
838 PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
840 static PyObject *
841 PyTclObject_unicode(PyTclObject *self, void *ignored)
843 char *s;
844 int len;
845 if (self->string && PyUnicode_Check(self->string)) {
846 Py_INCREF(self->string);
847 return self->string;
849 /* XXX Could chache result if it is non-ASCII. */
850 s = Tcl_GetStringFromObj(self->value, &len);
851 return PyUnicode_DecodeUTF8(s, len, "strict");
853 #endif
855 static PyObject *
856 PyTclObject_repr(PyTclObject *self)
858 char buf[50];
859 PyOS_snprintf(buf, 50, "<%s object at %p>",
860 self->value->typePtr->name, self->value);
861 return PyString_FromString(buf);
864 static int
865 PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
867 int res;
868 res = strcmp(Tcl_GetString(self->value),
869 Tcl_GetString(other->value));
870 if (res < 0) return -1;
871 if (res > 0) return 1;
872 return 0;
875 PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
877 static PyObject*
878 get_typename(PyTclObject* obj, void* ignored)
880 return PyString_FromString(obj->value->typePtr->name);
884 static PyGetSetDef PyTclObject_getsetlist[] = {
885 {"typename", (getter)get_typename, NULL, get_typename__doc__},
886 {"string", (getter)PyTclObject_string, NULL,
887 PyTclObject_string__doc__},
888 {0},
891 static PyMethodDef PyTclObject_methods[] = {
892 #ifdef Py_USING_UNICODE
893 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
894 PyTclObject_unicode__doc__},
895 #endif
899 statichere PyTypeObject PyTclObject_Type = {
900 PyObject_HEAD_INIT(NULL)
901 0, /*ob_size*/
902 "_tkinter.Tcl_Obj", /*tp_name*/
903 sizeof(PyTclObject), /*tp_basicsize*/
904 0, /*tp_itemsize*/
905 /* methods */
906 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
907 0, /*tp_print*/
908 0, /*tp_getattr*/
909 0, /*tp_setattr*/
910 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
911 (reprfunc)PyTclObject_repr, /*tp_repr*/
912 0, /*tp_as_number*/
913 0, /*tp_as_sequence*/
914 0, /*tp_as_mapping*/
915 0, /*tp_hash*/
916 0, /*tp_call*/
917 (reprfunc)PyTclObject_str, /*tp_str*/
918 PyObject_GenericGetAttr,/*tp_getattro*/
919 0, /*tp_setattro*/
920 0, /*tp_as_buffer*/
921 Py_TPFLAGS_DEFAULT, /*tp_flags*/
922 0, /*tp_doc*/
923 0, /*tp_traverse*/
924 0, /*tp_clear*/
925 0, /*tp_richcompare*/
926 0, /*tp_weaklistoffset*/
927 0, /*tp_iter*/
928 0, /*tp_iternext*/
929 PyTclObject_methods, /*tp_methods*/
930 0, /*tp_members*/
931 PyTclObject_getsetlist, /*tp_getset*/
932 0, /*tp_base*/
933 0, /*tp_dict*/
934 0, /*tp_descr_get*/
935 0, /*tp_descr_set*/
936 0, /*tp_dictoffset*/
937 0, /*tp_init*/
938 0, /*tp_alloc*/
939 0, /*tp_new*/
940 0, /*tp_free*/
941 0, /*tp_is_gc*/
944 static Tcl_Obj*
945 AsObj(PyObject *value)
947 Tcl_Obj *result;
949 if (PyString_Check(value))
950 return Tcl_NewStringObj(PyString_AS_STRING(value),
951 PyString_GET_SIZE(value));
952 else if (PyBool_Check(value))
953 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
954 else if (PyInt_Check(value))
955 return Tcl_NewLongObj(PyInt_AS_LONG(value));
956 else if (PyFloat_Check(value))
957 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
958 else if (PyTuple_Check(value)) {
959 Tcl_Obj **argv = (Tcl_Obj**)
960 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
961 int i;
962 if(!argv)
963 return 0;
964 for(i=0;i<PyTuple_Size(value);i++)
965 argv[i] = AsObj(PyTuple_GetItem(value,i));
966 result = Tcl_NewListObj(PyTuple_Size(value), argv);
967 ckfree(FREECAST argv);
968 return result;
970 #ifdef Py_USING_UNICODE
971 else if (PyUnicode_Check(value)) {
972 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
973 Py_ssize_t size = PyUnicode_GET_SIZE(value);
974 /* This #ifdef assumes that Tcl uses UCS-2.
975 See TCL_UTF_MAX test above. */
976 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
977 Tcl_UniChar *outbuf = NULL;
978 Py_ssize_t i;
979 size_t allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
980 if (allocsize >= size)
981 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
982 /* Else overflow occurred, and we take the next exit */
983 if (!outbuf) {
984 PyErr_NoMemory();
985 return NULL;
987 for (i = 0; i < size; i++) {
988 if (inbuf[i] >= 0x10000) {
989 /* Tcl doesn't do UTF-16, yet. */
990 PyErr_SetString(PyExc_ValueError,
991 "unsupported character");
992 ckfree(FREECAST outbuf);
993 return NULL;
995 outbuf[i] = inbuf[i];
997 result = Tcl_NewUnicodeObj(outbuf, size);
998 ckfree(FREECAST outbuf);
999 return result;
1000 #else
1001 return Tcl_NewUnicodeObj(inbuf, size);
1002 #endif
1005 #endif
1006 else if(PyTclObject_Check(value)) {
1007 Tcl_Obj *v = ((PyTclObject*)value)->value;
1008 Tcl_IncrRefCount(v);
1009 return v;
1011 else {
1012 PyObject *v = PyObject_Str(value);
1013 if (!v)
1014 return 0;
1015 result = AsObj(v);
1016 Py_DECREF(v);
1017 return result;
1021 static PyObject*
1022 FromObj(PyObject* tkapp, Tcl_Obj *value)
1024 PyObject *result = NULL;
1025 TkappObject *app = (TkappObject*)tkapp;
1027 if (value->typePtr == NULL) {
1028 /* If the result contains any bytes with the top bit set,
1029 it's UTF-8 and we should decode it to Unicode */
1030 #ifdef Py_USING_UNICODE
1031 int i;
1032 char *s = value->bytes;
1033 int len = value->length;
1034 for (i = 0; i < len; i++) {
1035 if (value->bytes[i] & 0x80)
1036 break;
1039 if (i == value->length)
1040 result = PyString_FromStringAndSize(s, len);
1041 else {
1042 /* Convert UTF-8 to Unicode string */
1043 result = PyUnicode_DecodeUTF8(s, len, "strict");
1044 if (result == NULL) {
1045 PyErr_Clear();
1046 result = PyString_FromStringAndSize(s, len);
1049 #else
1050 result = PyString_FromStringAndSize(value->bytes, value->length);
1051 #endif
1052 return result;
1055 if (value->typePtr == app->BooleanType) {
1056 result = value->internalRep.longValue ? Py_True : Py_False;
1057 Py_INCREF(result);
1058 return result;
1061 if (value->typePtr == app->ByteArrayType) {
1062 int size;
1063 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1064 return PyString_FromStringAndSize(data, size);
1067 if (value->typePtr == app->DoubleType) {
1068 return PyFloat_FromDouble(value->internalRep.doubleValue);
1071 if (value->typePtr == app->IntType) {
1072 return PyInt_FromLong(value->internalRep.longValue);
1075 if (value->typePtr == app->ListType) {
1076 int size;
1077 int i, status;
1078 PyObject *elem;
1079 Tcl_Obj *tcl_elem;
1081 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1082 if (status == TCL_ERROR)
1083 return Tkinter_Error(tkapp);
1084 result = PyTuple_New(size);
1085 if (!result)
1086 return NULL;
1087 for (i = 0; i < size; i++) {
1088 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1089 value, i, &tcl_elem);
1090 if (status == TCL_ERROR) {
1091 Py_DECREF(result);
1092 return Tkinter_Error(tkapp);
1094 elem = FromObj(tkapp, tcl_elem);
1095 if (!elem) {
1096 Py_DECREF(result);
1097 return NULL;
1099 PyTuple_SetItem(result, i, elem);
1101 return result;
1104 if (value->typePtr == app->ProcBodyType) {
1105 /* fall through: return tcl object. */
1108 if (value->typePtr == app->StringType) {
1109 #ifdef Py_USING_UNICODE
1110 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1111 PyObject *result;
1112 int size;
1113 Tcl_UniChar *input;
1114 Py_UNICODE *output;
1116 size = Tcl_GetCharLength(value);
1117 result = PyUnicode_FromUnicode(NULL, size);
1118 if (!result)
1119 return NULL;
1120 input = Tcl_GetUnicode(value);
1121 output = PyUnicode_AS_UNICODE(result);
1122 while (size--)
1123 *output++ = *input++;
1124 return result;
1125 #else
1126 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1127 Tcl_GetCharLength(value));
1128 #endif
1129 #else
1130 int size;
1131 char *c;
1132 c = Tcl_GetStringFromObj(value, &size);
1133 return PyString_FromStringAndSize(c, size);
1134 #endif
1137 return newPyTclObject(value);
1140 #ifdef WITH_THREAD
1141 /* This mutex synchronizes inter-thread command calls. */
1142 TCL_DECLARE_MUTEX(call_mutex)
1144 typedef struct Tkapp_CallEvent {
1145 Tcl_Event ev; /* Must be first */
1146 TkappObject *self;
1147 PyObject *args;
1148 int flags;
1149 PyObject **res;
1150 PyObject **exc_type, **exc_value, **exc_tb;
1151 Tcl_Condition *done;
1152 } Tkapp_CallEvent;
1153 #endif
1155 void
1156 Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
1158 int i;
1159 for (i = 0; i < objc; i++)
1160 Tcl_DecrRefCount(objv[i]);
1161 if (objv != objStore)
1162 ckfree(FREECAST objv);
1165 /* Convert Python objects to Tcl objects. This must happen in the
1166 interpreter thread, which may or may not be the calling thread. */
1168 static Tcl_Obj**
1169 Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1171 Tcl_Obj **objv = objStore;
1172 int objc = 0, i;
1173 if (args == NULL)
1174 /* do nothing */;
1176 else if (!PyTuple_Check(args)) {
1177 objv[0] = AsObj(args);
1178 if (objv[0] == 0)
1179 goto finally;
1180 objc = 1;
1181 Tcl_IncrRefCount(objv[0]);
1183 else {
1184 objc = PyTuple_Size(args);
1186 if (objc > ARGSZ) {
1187 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
1188 if (objv == NULL) {
1189 PyErr_NoMemory();
1190 objc = 0;
1191 goto finally;
1195 for (i = 0; i < objc; i++) {
1196 PyObject *v = PyTuple_GetItem(args, i);
1197 if (v == Py_None) {
1198 objc = i;
1199 break;
1201 objv[i] = AsObj(v);
1202 if (!objv[i]) {
1203 /* Reset objc, so it attempts to clear
1204 objects only up to i. */
1205 objc = i;
1206 goto finally;
1208 Tcl_IncrRefCount(objv[i]);
1211 *pobjc = objc;
1212 return objv;
1213 finally:
1214 Tkapp_CallDeallocArgs(objv, objStore, objc);
1215 return NULL;
1218 /* Convert the results of a command call into a Python objects. */
1220 static PyObject*
1221 Tkapp_CallResult(TkappObject *self)
1223 PyObject *res = NULL;
1224 if(self->wantobjects) {
1225 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1226 /* Not sure whether the IncrRef is necessary, but something
1227 may overwrite the interpreter result while we are
1228 converting it. */
1229 Tcl_IncrRefCount(value);
1230 res = FromObj((PyObject*)self, value);
1231 Tcl_DecrRefCount(value);
1232 } else {
1233 const char *s = Tcl_GetStringResult(self->interp);
1234 const char *p = s;
1236 /* If the result contains any bytes with the top bit set,
1237 it's UTF-8 and we should decode it to Unicode */
1238 #ifdef Py_USING_UNICODE
1239 while (*p != '\0') {
1240 if (*p & 0x80)
1241 break;
1242 p++;
1245 if (*p == '\0')
1246 res = PyString_FromStringAndSize(s, (int)(p-s));
1247 else {
1248 /* Convert UTF-8 to Unicode string */
1249 p = strchr(p, '\0');
1250 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
1251 if (res == NULL) {
1252 PyErr_Clear();
1253 res = PyString_FromStringAndSize(s, (int)(p-s));
1256 #else
1257 p = strchr(p, '\0');
1258 res = PyString_FromStringAndSize(s, (int)(p-s));
1259 #endif
1261 return res;
1264 #ifdef WITH_THREAD
1266 /* Tkapp_CallProc is the event procedure that is executed in the context of
1267 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1268 hold the Python lock. */
1270 static int
1271 Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1273 Tcl_Obj *objStore[ARGSZ];
1274 Tcl_Obj **objv;
1275 int objc;
1276 int i;
1277 ENTER_PYTHON
1278 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1279 if (!objv) {
1280 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1281 *(e->res) = NULL;
1283 LEAVE_PYTHON
1284 if (!objv)
1285 goto done;
1286 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1287 ENTER_PYTHON
1288 if (i == TCL_ERROR) {
1289 *(e->res) = NULL;
1290 *(e->exc_type) = NULL;
1291 *(e->exc_tb) = NULL;
1292 *(e->exc_value) = PyObject_CallFunction(
1293 Tkinter_TclError, "s",
1294 Tcl_GetStringResult(e->self->interp));
1296 else {
1297 *(e->res) = Tkapp_CallResult(e->self);
1299 LEAVE_PYTHON
1301 Tkapp_CallDeallocArgs(objv, objStore, objc);
1302 done:
1303 /* Wake up calling thread. */
1304 Tcl_MutexLock(&call_mutex);
1305 Tcl_ConditionNotify(e->done);
1306 Tcl_MutexUnlock(&call_mutex);
1307 return 1;
1310 #endif
1312 /* This is the main entry point for calling a Tcl command.
1313 It supports three cases, with regard to threading:
1314 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1315 the context of the calling thread.
1316 2. Tcl is threaded, caller of the command is in the interpreter thread:
1317 Execute the command in the calling thread. Since the Tcl lock will
1318 not be used, we can merge that with case 1.
1319 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1320 the interpreter thread. Allocation of Tcl objects needs to occur in the
1321 interpreter thread, so we ship the PyObject* args to the target thread,
1322 and perform processing there. */
1324 static PyObject *
1325 Tkapp_Call(PyObject *selfptr, PyObject *args)
1327 Tcl_Obj *objStore[ARGSZ];
1328 Tcl_Obj **objv = NULL;
1329 int objc, i;
1330 PyObject *res = NULL;
1331 TkappObject *self = (TkappObject*)selfptr;
1332 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
1334 /* If args is a single tuple, replace with contents of tuple */
1335 if (1 == PyTuple_Size(args)){
1336 PyObject* item = PyTuple_GetItem(args, 0);
1337 if (PyTuple_Check(item))
1338 args = item;
1340 #ifdef WITH_THREAD
1341 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1342 /* We cannot call the command directly. Instead, we must
1343 marshal the parameters to the interpreter thread. */
1344 Tkapp_CallEvent *ev;
1345 Tcl_Condition cond = NULL;
1346 PyObject *exc_type, *exc_value, *exc_tb;
1347 if (!WaitForMainloop(self))
1348 return NULL;
1349 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1350 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1351 ev->self = self;
1352 ev->args = args;
1353 ev->res = &res;
1354 ev->exc_type = &exc_type;
1355 ev->exc_value = &exc_value;
1356 ev->exc_tb = &exc_tb;
1357 ev->done = &cond;
1359 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
1361 if (res == NULL) {
1362 if (exc_type)
1363 PyErr_Restore(exc_type, exc_value, exc_tb);
1364 else
1365 PyErr_SetObject(Tkinter_TclError, exc_value);
1367 Tcl_ConditionFinalize(&cond);
1369 else
1370 #endif
1373 objv = Tkapp_CallArgs(args, objStore, &objc);
1374 if (!objv)
1375 return NULL;
1377 ENTER_TCL
1379 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
1381 ENTER_OVERLAP
1383 if (i == TCL_ERROR)
1384 Tkinter_Error(selfptr);
1385 else
1386 res = Tkapp_CallResult(self);
1388 LEAVE_OVERLAP_TCL
1390 Tkapp_CallDeallocArgs(objv, objStore, objc);
1392 return res;
1396 static PyObject *
1397 Tkapp_GlobalCall(PyObject *self, PyObject *args)
1399 /* Could do the same here as for Tkapp_Call(), but this is not used
1400 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1401 way for the user to do what all its Global* variants do (save and
1402 reset the scope pointer, call the local version, restore the saved
1403 scope pointer). */
1405 char *cmd;
1406 PyObject *res = NULL;
1408 CHECK_TCL_APPARTMENT;
1410 cmd = Merge(args);
1411 if (cmd) {
1412 int err;
1413 ENTER_TCL
1414 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1415 ENTER_OVERLAP
1416 if (err == TCL_ERROR)
1417 res = Tkinter_Error(self);
1418 else
1419 res = PyString_FromString(Tkapp_Result(self));
1420 LEAVE_OVERLAP_TCL
1421 ckfree(cmd);
1424 return res;
1427 static PyObject *
1428 Tkapp_Eval(PyObject *self, PyObject *args)
1430 char *script;
1431 PyObject *res = NULL;
1432 int err;
1434 if (!PyArg_ParseTuple(args, "s:eval", &script))
1435 return NULL;
1437 CHECK_TCL_APPARTMENT;
1439 ENTER_TCL
1440 err = Tcl_Eval(Tkapp_Interp(self), script);
1441 ENTER_OVERLAP
1442 if (err == TCL_ERROR)
1443 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_GlobalEval(PyObject *self, PyObject *args)
1453 char *script;
1454 PyObject *res = NULL;
1455 int err;
1457 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1458 return NULL;
1460 CHECK_TCL_APPARTMENT;
1462 ENTER_TCL
1463 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
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_EvalFile(PyObject *self, PyObject *args)
1476 char *fileName;
1477 PyObject *res = NULL;
1478 int err;
1480 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1481 return NULL;
1483 CHECK_TCL_APPARTMENT;
1485 ENTER_TCL
1486 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1487 ENTER_OVERLAP
1488 if (err == TCL_ERROR)
1489 res = Tkinter_Error(self);
1491 else
1492 res = PyString_FromString(Tkapp_Result(self));
1493 LEAVE_OVERLAP_TCL
1494 return res;
1497 static PyObject *
1498 Tkapp_Record(PyObject *self, PyObject *args)
1500 char *script;
1501 PyObject *res = NULL;
1502 int err;
1504 if (!PyArg_ParseTuple(args, "s", &script))
1505 return NULL;
1507 CHECK_TCL_APPARTMENT;
1509 ENTER_TCL
1510 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1511 ENTER_OVERLAP
1512 if (err == TCL_ERROR)
1513 res = Tkinter_Error(self);
1514 else
1515 res = PyString_FromString(Tkapp_Result(self));
1516 LEAVE_OVERLAP_TCL
1517 return res;
1520 static PyObject *
1521 Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
1523 char *msg;
1525 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1526 return NULL;
1527 CHECK_TCL_APPARTMENT;
1529 ENTER_TCL
1530 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1531 LEAVE_TCL
1533 Py_INCREF(Py_None);
1534 return Py_None;
1539 /** Tcl Variable **/
1541 typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1543 #ifdef WITH_THREAD
1544 TCL_DECLARE_MUTEX(var_mutex)
1546 typedef struct VarEvent {
1547 Tcl_Event ev; /* must be first */
1548 PyObject *self;
1549 PyObject *args;
1550 int flags;
1551 EventFunc func;
1552 PyObject **res;
1553 PyObject **exc_type;
1554 PyObject **exc_val;
1555 Tcl_Condition *cond;
1556 } VarEvent;
1557 #endif
1559 static int
1560 varname_converter(PyObject *in, void *_out)
1562 char **out = (char**)_out;
1563 if (PyString_Check(in)) {
1564 *out = PyString_AsString(in);
1565 return 1;
1567 if (PyTclObject_Check(in)) {
1568 *out = PyTclObject_TclString(in);
1569 return 1;
1571 /* XXX: Should give diagnostics. */
1572 return 0;
1575 #ifdef WITH_THREAD
1577 static void
1578 var_perform(VarEvent *ev)
1580 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1581 if (!*(ev->res)) {
1582 PyObject *exc, *val, *tb;
1583 PyErr_Fetch(&exc, &val, &tb);
1584 PyErr_NormalizeException(&exc, &val, &tb);
1585 *(ev->exc_type) = exc;
1586 *(ev->exc_val) = val;
1587 Py_DECREF(tb);
1592 static int
1593 var_proc(VarEvent* ev, int flags)
1595 ENTER_PYTHON
1596 var_perform(ev);
1597 Tcl_MutexLock(&var_mutex);
1598 Tcl_ConditionNotify(ev->cond);
1599 Tcl_MutexUnlock(&var_mutex);
1600 LEAVE_PYTHON
1601 return 1;
1604 #endif
1606 static PyObject*
1607 var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
1609 #ifdef WITH_THREAD
1610 TkappObject *self = (TkappObject*)selfptr;
1611 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1612 TkappObject *self = (TkappObject*)selfptr;
1613 VarEvent *ev;
1614 PyObject *res, *exc_type, *exc_val;
1615 Tcl_Condition cond = NULL;
1617 /* The current thread is not the interpreter thread. Marshal
1618 the call to the interpreter thread, then wait for
1619 completion. */
1620 if (!WaitForMainloop(self))
1621 return NULL;
1623 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
1625 ev->self = selfptr;
1626 ev->args = args;
1627 ev->flags = flags;
1628 ev->func = func;
1629 ev->res = &res;
1630 ev->exc_type = &exc_type;
1631 ev->exc_val = &exc_val;
1632 ev->cond = &cond;
1633 ev->ev.proc = (Tcl_EventProc*)var_proc;
1634 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1635 Tcl_ConditionFinalize(&cond);
1636 if (!res) {
1637 PyErr_SetObject(exc_type, exc_val);
1638 Py_DECREF(exc_type);
1639 Py_DECREF(exc_val);
1640 return NULL;
1642 return res;
1644 #endif
1645 /* Tcl is not threaded, or this is the interpreter thread. */
1646 return func(selfptr, args, flags);
1649 static PyObject *
1650 SetVar(PyObject *self, PyObject *args, int flags)
1652 char *name1, *name2;
1653 PyObject *newValue;
1654 PyObject *res = NULL;
1655 Tcl_Obj *newval, *ok;
1657 if (PyArg_ParseTuple(args, "O&O:setvar",
1658 varname_converter, &name1, &newValue)) {
1659 /* XXX Acquire tcl lock??? */
1660 newval = AsObj(newValue);
1661 if (newval == NULL)
1662 return NULL;
1663 ENTER_TCL
1664 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1665 newval, flags);
1666 ENTER_OVERLAP
1667 if (!ok)
1668 Tkinter_Error(self);
1669 else {
1670 res = Py_None;
1671 Py_INCREF(res);
1673 LEAVE_OVERLAP_TCL
1675 else {
1676 PyErr_Clear();
1677 if (PyArg_ParseTuple(args, "ssO:setvar",
1678 &name1, &name2, &newValue)) {
1679 /* XXX must hold tcl lock already??? */
1680 newval = AsObj(newValue);
1681 ENTER_TCL
1682 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1683 ENTER_OVERLAP
1684 if (!ok)
1685 Tkinter_Error(self);
1686 else {
1687 res = Py_None;
1688 Py_INCREF(res);
1690 LEAVE_OVERLAP_TCL
1692 else {
1693 return NULL;
1696 return res;
1699 static PyObject *
1700 Tkapp_SetVar(PyObject *self, PyObject *args)
1702 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
1705 static PyObject *
1706 Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
1708 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1713 static PyObject *
1714 GetVar(PyObject *self, PyObject *args, int flags)
1716 char *name1, *name2=NULL;
1717 PyObject *res = NULL;
1718 Tcl_Obj *tres;
1720 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1721 varname_converter, &name1, &name2))
1722 return NULL;
1724 ENTER_TCL
1725 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1726 ENTER_OVERLAP
1727 if (tres == NULL) {
1728 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1729 } else {
1730 if (((TkappObject*)self)->wantobjects) {
1731 res = FromObj(self, tres);
1733 else {
1734 res = PyString_FromString(Tcl_GetString(tres));
1737 LEAVE_OVERLAP_TCL
1738 return res;
1741 static PyObject *
1742 Tkapp_GetVar(PyObject *self, PyObject *args)
1744 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
1747 static PyObject *
1748 Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1750 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1755 static PyObject *
1756 UnsetVar(PyObject *self, PyObject *args, int flags)
1758 char *name1, *name2=NULL;
1759 int code;
1760 PyObject *res = NULL;
1762 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1763 return NULL;
1765 ENTER_TCL
1766 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1767 ENTER_OVERLAP
1768 if (code == TCL_ERROR)
1769 res = Tkinter_Error(self);
1770 else {
1771 Py_INCREF(Py_None);
1772 res = Py_None;
1774 LEAVE_OVERLAP_TCL
1775 return res;
1778 static PyObject *
1779 Tkapp_UnsetVar(PyObject *self, PyObject *args)
1781 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
1784 static PyObject *
1785 Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1787 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1792 /** Tcl to Python **/
1794 static PyObject *
1795 Tkapp_GetInt(PyObject *self, PyObject *args)
1797 char *s;
1798 int v;
1800 if (PyTuple_Size(args) == 1) {
1801 PyObject* o = PyTuple_GetItem(args, 0);
1802 if (PyInt_Check(o)) {
1803 Py_INCREF(o);
1804 return o;
1807 if (!PyArg_ParseTuple(args, "s:getint", &s))
1808 return NULL;
1809 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1810 return Tkinter_Error(self);
1811 return Py_BuildValue("i", v);
1814 static PyObject *
1815 Tkapp_GetDouble(PyObject *self, PyObject *args)
1817 char *s;
1818 double v;
1820 if (PyTuple_Size(args) == 1) {
1821 PyObject *o = PyTuple_GetItem(args, 0);
1822 if (PyFloat_Check(o)) {
1823 Py_INCREF(o);
1824 return o;
1827 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1828 return NULL;
1829 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1830 return Tkinter_Error(self);
1831 return Py_BuildValue("d", v);
1834 static PyObject *
1835 Tkapp_GetBoolean(PyObject *self, PyObject *args)
1837 char *s;
1838 int v;
1840 if (PyTuple_Size(args) == 1) {
1841 PyObject *o = PyTuple_GetItem(args, 0);
1842 if (PyInt_Check(o)) {
1843 Py_INCREF(o);
1844 return o;
1847 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1848 return NULL;
1849 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1850 return Tkinter_Error(self);
1851 return PyBool_FromLong(v);
1854 static PyObject *
1855 Tkapp_ExprString(PyObject *self, PyObject *args)
1857 char *s;
1858 PyObject *res = NULL;
1859 int retval;
1861 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1862 return NULL;
1864 CHECK_TCL_APPARTMENT;
1866 ENTER_TCL
1867 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1868 ENTER_OVERLAP
1869 if (retval == TCL_ERROR)
1870 res = Tkinter_Error(self);
1871 else
1872 res = Py_BuildValue("s", Tkapp_Result(self));
1873 LEAVE_OVERLAP_TCL
1874 return res;
1877 static PyObject *
1878 Tkapp_ExprLong(PyObject *self, PyObject *args)
1880 char *s;
1881 PyObject *res = NULL;
1882 int retval;
1883 long v;
1885 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1886 return NULL;
1888 CHECK_TCL_APPARTMENT;
1890 ENTER_TCL
1891 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1892 ENTER_OVERLAP
1893 if (retval == TCL_ERROR)
1894 res = Tkinter_Error(self);
1895 else
1896 res = Py_BuildValue("l", v);
1897 LEAVE_OVERLAP_TCL
1898 return res;
1901 static PyObject *
1902 Tkapp_ExprDouble(PyObject *self, PyObject *args)
1904 char *s;
1905 PyObject *res = NULL;
1906 double v;
1907 int retval;
1909 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1910 return NULL;
1911 CHECK_TCL_APPARTMENT;
1912 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1913 ENTER_TCL
1914 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1915 ENTER_OVERLAP
1916 PyFPE_END_PROTECT(retval)
1917 if (retval == TCL_ERROR)
1918 res = Tkinter_Error(self);
1919 else
1920 res = Py_BuildValue("d", v);
1921 LEAVE_OVERLAP_TCL
1922 return res;
1925 static PyObject *
1926 Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1928 char *s;
1929 PyObject *res = NULL;
1930 int retval;
1931 int v;
1933 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1934 return NULL;
1935 CHECK_TCL_APPARTMENT;
1936 ENTER_TCL
1937 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1938 ENTER_OVERLAP
1939 if (retval == TCL_ERROR)
1940 res = Tkinter_Error(self);
1941 else
1942 res = Py_BuildValue("i", v);
1943 LEAVE_OVERLAP_TCL
1944 return res;
1949 static PyObject *
1950 Tkapp_SplitList(PyObject *self, PyObject *args)
1952 char *list;
1953 int argc;
1954 char **argv;
1955 PyObject *v;
1956 int i;
1958 if (PyTuple_Size(args) == 1) {
1959 v = PyTuple_GetItem(args, 0);
1960 if (PyTuple_Check(v)) {
1961 Py_INCREF(v);
1962 return v;
1965 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1966 return NULL;
1968 if (Tcl_SplitList(Tkapp_Interp(self), list,
1969 &argc, &argv) == TCL_ERROR) {
1970 PyMem_Free(list);
1971 return Tkinter_Error(self);
1974 if (!(v = PyTuple_New(argc)))
1975 goto finally;
1977 for (i = 0; i < argc; i++) {
1978 PyObject *s = PyString_FromString(argv[i]);
1979 if (!s || PyTuple_SetItem(v, i, s)) {
1980 Py_DECREF(v);
1981 v = NULL;
1982 goto finally;
1986 finally:
1987 ckfree(FREECAST argv);
1988 PyMem_Free(list);
1989 return v;
1992 static PyObject *
1993 Tkapp_Split(PyObject *self, PyObject *args)
1995 PyObject *v;
1996 char *list;
1998 if (PyTuple_Size(args) == 1) {
1999 PyObject* o = PyTuple_GetItem(args, 0);
2000 if (PyTuple_Check(o)) {
2001 o = SplitObj(o);
2002 return o;
2005 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2006 return NULL;
2007 v = Split(list);
2008 PyMem_Free(list);
2009 return v;
2012 static PyObject *
2013 Tkapp_Merge(PyObject *self, PyObject *args)
2015 char *s = Merge(args);
2016 PyObject *res = NULL;
2018 if (s) {
2019 res = PyString_FromString(s);
2020 ckfree(s);
2023 return res;
2028 /** Tcl Command **/
2030 /* Client data struct */
2031 typedef struct {
2032 PyObject *self;
2033 PyObject *func;
2034 } PythonCmd_ClientData;
2036 static int
2037 PythonCmd_Error(Tcl_Interp *interp)
2039 errorInCmd = 1;
2040 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2041 LEAVE_PYTHON
2042 return TCL_ERROR;
2045 /* This is the Tcl command that acts as a wrapper for Python
2046 * function or method.
2048 static int
2049 PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
2051 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2052 PyObject *self, *func, *arg, *res;
2053 int i, rv;
2054 Tcl_Obj *obj_res;
2056 ENTER_PYTHON
2058 /* TBD: no error checking here since we know, via the
2059 * Tkapp_CreateCommand() that the client data is a two-tuple
2061 self = data->self;
2062 func = data->func;
2064 /* Create argument list (argv1, ..., argvN) */
2065 if (!(arg = PyTuple_New(argc - 1)))
2066 return PythonCmd_Error(interp);
2068 for (i = 0; i < (argc - 1); i++) {
2069 PyObject *s = PyString_FromString(argv[i + 1]);
2070 if (!s || PyTuple_SetItem(arg, i, s)) {
2071 Py_DECREF(arg);
2072 return PythonCmd_Error(interp);
2075 res = PyEval_CallObject(func, arg);
2076 Py_DECREF(arg);
2078 if (res == NULL)
2079 return PythonCmd_Error(interp);
2081 obj_res = AsObj(res);
2082 if (obj_res == NULL) {
2083 Py_DECREF(res);
2084 return PythonCmd_Error(interp);
2086 else {
2087 Tcl_SetObjResult(interp, obj_res);
2088 rv = TCL_OK;
2091 Py_DECREF(res);
2093 LEAVE_PYTHON
2095 return rv;
2098 static void
2099 PythonCmdDelete(ClientData clientData)
2101 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2103 ENTER_PYTHON
2104 Py_XDECREF(data->self);
2105 Py_XDECREF(data->func);
2106 PyMem_DEL(data);
2107 LEAVE_PYTHON
2113 #ifdef WITH_THREAD
2114 TCL_DECLARE_MUTEX(command_mutex)
2116 typedef struct CommandEvent{
2117 Tcl_Event ev;
2118 Tcl_Interp* interp;
2119 char *name;
2120 int create;
2121 int *status;
2122 ClientData *data;
2123 Tcl_Condition *done;
2124 } CommandEvent;
2126 static int
2127 Tkapp_CommandProc(CommandEvent *ev, int flags)
2129 if (ev->create)
2130 *ev->status = Tcl_CreateCommand(
2131 ev->interp, ev->name, PythonCmd,
2132 ev->data, PythonCmdDelete) == NULL;
2133 else
2134 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2135 Tcl_MutexLock(&command_mutex);
2136 Tcl_ConditionNotify(ev->done);
2137 Tcl_MutexUnlock(&command_mutex);
2138 return 1;
2140 #endif
2142 static PyObject *
2143 Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2145 TkappObject *self = (TkappObject*)selfptr;
2146 PythonCmd_ClientData *data;
2147 char *cmdName;
2148 PyObject *func;
2149 int err;
2151 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2152 return NULL;
2153 if (!PyCallable_Check(func)) {
2154 PyErr_SetString(PyExc_TypeError, "command not callable");
2155 return NULL;
2158 #ifdef WITH_THREAD
2159 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2160 !WaitForMainloop(self))
2161 return NULL;
2162 #endif
2164 data = PyMem_NEW(PythonCmd_ClientData, 1);
2165 if (!data)
2166 return PyErr_NoMemory();
2167 Py_INCREF(self);
2168 Py_INCREF(func);
2169 data->self = selfptr;
2170 data->func = func;
2172 #ifdef WITH_THREAD
2173 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2174 Tcl_Condition cond = NULL;
2175 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2176 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2177 ev->interp = self->interp;
2178 ev->create = 1;
2179 ev->name = cmdName;
2180 ev->data = (ClientData)data;
2181 ev->status = &err;
2182 ev->done = &cond;
2183 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2184 Tcl_ConditionFinalize(&cond);
2186 else
2187 #endif
2189 ENTER_TCL
2190 err = Tcl_CreateCommand(
2191 Tkapp_Interp(self), cmdName, PythonCmd,
2192 (ClientData)data, PythonCmdDelete) == NULL;
2193 LEAVE_TCL
2195 if (err) {
2196 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2197 PyMem_DEL(data);
2198 return NULL;
2201 Py_INCREF(Py_None);
2202 return Py_None;
2207 static PyObject *
2208 Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2210 TkappObject *self = (TkappObject*)selfptr;
2211 char *cmdName;
2212 int err;
2214 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2215 return NULL;
2217 #ifdef WITH_THREAD
2218 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2219 Tcl_Condition cond = NULL;
2220 CommandEvent *ev;
2221 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2222 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2223 ev->interp = self->interp;
2224 ev->create = 0;
2225 ev->name = cmdName;
2226 ev->status = &err;
2227 ev->done = &cond;
2228 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2229 &command_mutex);
2230 Tcl_ConditionFinalize(&cond);
2232 else
2233 #endif
2235 ENTER_TCL
2236 err = Tcl_DeleteCommand(self->interp, cmdName);
2237 LEAVE_TCL
2239 if (err == -1) {
2240 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2241 return NULL;
2243 Py_INCREF(Py_None);
2244 return Py_None;
2249 #ifdef HAVE_CREATEFILEHANDLER
2250 /** File Handler **/
2252 typedef struct _fhcdata {
2253 PyObject *func;
2254 PyObject *file;
2255 int id;
2256 struct _fhcdata *next;
2257 } FileHandler_ClientData;
2259 static FileHandler_ClientData *HeadFHCD;
2261 static FileHandler_ClientData *
2262 NewFHCD(PyObject *func, PyObject *file, int id)
2264 FileHandler_ClientData *p;
2265 p = PyMem_NEW(FileHandler_ClientData, 1);
2266 if (p != NULL) {
2267 Py_XINCREF(func);
2268 Py_XINCREF(file);
2269 p->func = func;
2270 p->file = file;
2271 p->id = id;
2272 p->next = HeadFHCD;
2273 HeadFHCD = p;
2275 return p;
2278 static void
2279 DeleteFHCD(int id)
2281 FileHandler_ClientData *p, **pp;
2283 pp = &HeadFHCD;
2284 while ((p = *pp) != NULL) {
2285 if (p->id == id) {
2286 *pp = p->next;
2287 Py_XDECREF(p->func);
2288 Py_XDECREF(p->file);
2289 PyMem_DEL(p);
2291 else
2292 pp = &p->next;
2296 static void
2297 FileHandler(ClientData clientData, int mask)
2299 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2300 PyObject *func, *file, *arg, *res;
2302 ENTER_PYTHON
2303 func = data->func;
2304 file = data->file;
2306 arg = Py_BuildValue("(Oi)", file, (long) mask);
2307 res = PyEval_CallObject(func, arg);
2308 Py_DECREF(arg);
2310 if (res == NULL) {
2311 errorInCmd = 1;
2312 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2314 Py_XDECREF(res);
2315 LEAVE_PYTHON
2318 static PyObject *
2319 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2320 /* args is (file, mask, func) */
2322 FileHandler_ClientData *data;
2323 PyObject *file, *func;
2324 int mask, tfile;
2326 if (!self && Py_Py3kWarningFlag) {
2327 if (PyErr_Warn(PyExc_DeprecationWarning,
2328 "_tkinter.createfilehandler is gone in 3.x") < 0)
2329 return NULL;
2332 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2333 &file, &mask, &func))
2334 return NULL;
2336 #ifdef WITH_THREAD
2337 if (!self && !tcl_lock) {
2338 /* We don't have the Tcl lock since Tcl is threaded. */
2339 PyErr_SetString(PyExc_RuntimeError,
2340 "_tkinter.createfilehandler not supported "
2341 "for threaded Tcl");
2342 return NULL;
2344 #endif
2346 if (self) {
2347 CHECK_TCL_APPARTMENT;
2350 tfile = PyObject_AsFileDescriptor(file);
2351 if (tfile < 0)
2352 return NULL;
2353 if (!PyCallable_Check(func)) {
2354 PyErr_SetString(PyExc_TypeError, "bad argument list");
2355 return NULL;
2358 data = NewFHCD(func, file, tfile);
2359 if (data == NULL)
2360 return NULL;
2362 /* Ought to check for null Tcl_File object... */
2363 ENTER_TCL
2364 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2365 LEAVE_TCL
2366 Py_INCREF(Py_None);
2367 return Py_None;
2370 static PyObject *
2371 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2373 PyObject *file;
2374 int tfile;
2376 if (!self && Py_Py3kWarningFlag) {
2377 if (PyErr_Warn(PyExc_DeprecationWarning,
2378 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2379 return NULL;
2382 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2383 return NULL;
2385 #ifdef WITH_THREAD
2386 if (!self && !tcl_lock) {
2387 /* We don't have the Tcl lock since Tcl is threaded. */
2388 PyErr_SetString(PyExc_RuntimeError,
2389 "_tkinter.deletefilehandler not supported "
2390 "for threaded Tcl");
2391 return NULL;
2393 #endif
2395 if (self) {
2396 CHECK_TCL_APPARTMENT;
2399 tfile = PyObject_AsFileDescriptor(file);
2400 if (tfile < 0)
2401 return NULL;
2403 DeleteFHCD(tfile);
2405 /* Ought to check for null Tcl_File object... */
2406 ENTER_TCL
2407 Tcl_DeleteFileHandler(tfile);
2408 LEAVE_TCL
2409 Py_INCREF(Py_None);
2410 return Py_None;
2412 #endif /* HAVE_CREATEFILEHANDLER */
2415 /**** Tktt Object (timer token) ****/
2417 static PyTypeObject Tktt_Type;
2419 typedef struct {
2420 PyObject_HEAD
2421 Tcl_TimerToken token;
2422 PyObject *func;
2423 } TkttObject;
2425 static PyObject *
2426 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2428 TkttObject *v = (TkttObject *)self;
2429 PyObject *func = v->func;
2431 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2432 return NULL;
2433 if (v->token != NULL) {
2434 Tcl_DeleteTimerHandler(v->token);
2435 v->token = NULL;
2437 if (func != NULL) {
2438 v->func = NULL;
2439 Py_DECREF(func);
2440 Py_DECREF(v); /* See Tktt_New() */
2442 Py_INCREF(Py_None);
2443 return Py_None;
2446 static PyMethodDef Tktt_methods[] =
2448 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2449 {NULL, NULL}
2452 static TkttObject *
2453 Tktt_New(PyObject *func)
2455 TkttObject *v;
2457 v = PyObject_New(TkttObject, &Tktt_Type);
2458 if (v == NULL)
2459 return NULL;
2461 Py_INCREF(func);
2462 v->token = NULL;
2463 v->func = func;
2465 /* Extra reference, deleted when called or when handler is deleted */
2466 Py_INCREF(v);
2467 return v;
2470 static void
2471 Tktt_Dealloc(PyObject *self)
2473 TkttObject *v = (TkttObject *)self;
2474 PyObject *func = v->func;
2476 Py_XDECREF(func);
2478 PyObject_Del(self);
2481 static PyObject *
2482 Tktt_Repr(PyObject *self)
2484 TkttObject *v = (TkttObject *)self;
2485 char buf[100];
2487 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2488 v->func == NULL ? ", handler deleted" : "");
2489 return PyString_FromString(buf);
2492 static PyObject *
2493 Tktt_GetAttr(PyObject *self, char *name)
2495 return Py_FindMethod(Tktt_methods, self, name);
2498 static PyTypeObject Tktt_Type =
2500 PyVarObject_HEAD_INIT(NULL, 0)
2501 "tktimertoken", /*tp_name */
2502 sizeof(TkttObject), /*tp_basicsize */
2503 0, /*tp_itemsize */
2504 Tktt_Dealloc, /*tp_dealloc */
2505 0, /*tp_print */
2506 Tktt_GetAttr, /*tp_getattr */
2507 0, /*tp_setattr */
2508 0, /*tp_compare */
2509 Tktt_Repr, /*tp_repr */
2510 0, /*tp_as_number */
2511 0, /*tp_as_sequence */
2512 0, /*tp_as_mapping */
2513 0, /*tp_hash */
2518 /** Timer Handler **/
2520 static void
2521 TimerHandler(ClientData clientData)
2523 TkttObject *v = (TkttObject *)clientData;
2524 PyObject *func = v->func;
2525 PyObject *res;
2527 if (func == NULL)
2528 return;
2530 v->func = NULL;
2532 ENTER_PYTHON
2534 res = PyEval_CallObject(func, NULL);
2535 Py_DECREF(func);
2536 Py_DECREF(v); /* See Tktt_New() */
2538 if (res == NULL) {
2539 errorInCmd = 1;
2540 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2542 else
2543 Py_DECREF(res);
2545 LEAVE_PYTHON
2548 static PyObject *
2549 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2551 int milliseconds;
2552 PyObject *func;
2553 TkttObject *v;
2555 if (!self && Py_Py3kWarningFlag) {
2556 if (PyErr_Warn(PyExc_DeprecationWarning,
2557 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2558 return NULL;
2561 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2562 &milliseconds, &func))
2563 return NULL;
2564 if (!PyCallable_Check(func)) {
2565 PyErr_SetString(PyExc_TypeError, "bad argument list");
2566 return NULL;
2569 #ifdef WITH_THREAD
2570 if (!self && !tcl_lock) {
2571 /* We don't have the Tcl lock since Tcl is threaded. */
2572 PyErr_SetString(PyExc_RuntimeError,
2573 "_tkinter.createtimerhandler not supported "
2574 "for threaded Tcl");
2575 return NULL;
2577 #endif
2579 if (self) {
2580 CHECK_TCL_APPARTMENT;
2583 v = Tktt_New(func);
2584 if (v) {
2585 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2586 (ClientData)v);
2589 return (PyObject *) v;
2593 /** Event Loop **/
2595 static PyObject *
2596 Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
2598 int threshold = 0;
2599 TkappObject *self = (TkappObject*)selfptr;
2600 #ifdef WITH_THREAD
2601 PyThreadState *tstate = PyThreadState_Get();
2602 #endif
2604 if (!self && Py_Py3kWarningFlag) {
2605 if (PyErr_Warn(PyExc_DeprecationWarning,
2606 "_tkinter.mainloop is gone in 3.x") < 0)
2607 return NULL;
2610 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2611 return NULL;
2613 #ifdef WITH_THREAD
2614 if (!self && !tcl_lock) {
2615 /* We don't have the Tcl lock since Tcl is threaded. */
2616 PyErr_SetString(PyExc_RuntimeError,
2617 "_tkinter.mainloop not supported "
2618 "for threaded Tcl");
2619 return NULL;
2621 #endif
2623 if (self) {
2624 CHECK_TCL_APPARTMENT;
2625 self->dispatching = 1;
2628 quitMainLoop = 0;
2629 while (Tk_GetNumMainWindows() > threshold &&
2630 !quitMainLoop &&
2631 !errorInCmd)
2633 int result;
2635 #ifdef WITH_THREAD
2636 if (self && self->threaded) {
2637 /* Allow other Python threads to run. */
2638 ENTER_TCL
2639 result = Tcl_DoOneEvent(0);
2640 LEAVE_TCL
2642 else {
2643 Py_BEGIN_ALLOW_THREADS
2644 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2645 tcl_tstate = tstate;
2646 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2647 tcl_tstate = NULL;
2648 if(tcl_lock)PyThread_release_lock(tcl_lock);
2649 if (result == 0)
2650 Sleep(Tkinter_busywaitinterval);
2651 Py_END_ALLOW_THREADS
2653 #else
2654 result = Tcl_DoOneEvent(0);
2655 #endif
2657 if (PyErr_CheckSignals() != 0) {
2658 if (self)
2659 self->dispatching = 0;
2660 return NULL;
2662 if (result < 0)
2663 break;
2665 if (self)
2666 self->dispatching = 0;
2667 quitMainLoop = 0;
2669 if (errorInCmd) {
2670 errorInCmd = 0;
2671 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2672 excInCmd = valInCmd = trbInCmd = NULL;
2673 return NULL;
2675 Py_INCREF(Py_None);
2676 return Py_None;
2679 static PyObject *
2680 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
2682 int flags = 0;
2683 int rv;
2685 if (!self && Py_Py3kWarningFlag) {
2686 if (PyErr_Warn(PyExc_DeprecationWarning,
2687 "_tkinter.dooneevent is gone in 3.x") < 0)
2688 return NULL;
2691 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2692 return NULL;
2694 ENTER_TCL
2695 rv = Tcl_DoOneEvent(flags);
2696 LEAVE_TCL
2697 return Py_BuildValue("i", rv);
2700 static PyObject *
2701 Tkapp_Quit(PyObject *self, PyObject *args)
2704 if (!self && Py_Py3kWarningFlag) {
2705 if (PyErr_Warn(PyExc_DeprecationWarning,
2706 "_tkinter.quit is gone in 3.x") < 0)
2707 return NULL;
2710 if (!PyArg_ParseTuple(args, ":quit"))
2711 return NULL;
2713 quitMainLoop = 1;
2714 Py_INCREF(Py_None);
2715 return Py_None;
2718 static PyObject *
2719 Tkapp_InterpAddr(PyObject *self, PyObject *args)
2722 if (!PyArg_ParseTuple(args, ":interpaddr"))
2723 return NULL;
2725 return PyInt_FromLong((long)Tkapp_Interp(self));
2728 static PyObject *
2729 Tkapp_TkInit(PyObject *self, PyObject *args)
2731 Tcl_Interp *interp = Tkapp_Interp(self);
2732 const char * _tk_exists = NULL;
2733 int err;
2735 #ifdef TKINTER_PROTECT_LOADTK
2736 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2737 * first call failed.
2738 * To avoid the deadlock, we just refuse the second call through
2739 * a static variable.
2741 if (tk_load_failed) {
2742 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2743 return NULL;
2745 #endif
2747 /* We want to guard against calling Tk_Init() multiple times */
2748 CHECK_TCL_APPARTMENT;
2749 ENTER_TCL
2750 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2751 ENTER_OVERLAP
2752 if (err == TCL_ERROR) {
2753 /* This sets an exception, but we cannot return right
2754 away because we need to exit the overlap first. */
2755 Tkinter_Error(self);
2756 } else {
2757 _tk_exists = Tkapp_Result(self);
2759 LEAVE_OVERLAP_TCL
2760 if (err == TCL_ERROR) {
2761 return NULL;
2763 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2764 if (Tk_Init(interp) == TCL_ERROR) {
2765 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2766 #ifdef TKINTER_PROTECT_LOADTK
2767 tk_load_failed = 1;
2768 #endif
2769 return NULL;
2772 Py_INCREF(Py_None);
2773 return Py_None;
2776 static PyObject *
2777 Tkapp_WantObjects(PyObject *self, PyObject *args)
2780 int wantobjects = -1;
2781 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2782 return NULL;
2783 if (wantobjects == -1)
2784 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2785 ((TkappObject*)self)->wantobjects = wantobjects;
2787 Py_INCREF(Py_None);
2788 return Py_None;
2791 static PyObject *
2792 Tkapp_WillDispatch(PyObject *self, PyObject *args)
2795 ((TkappObject*)self)->dispatching = 1;
2797 Py_INCREF(Py_None);
2798 return Py_None;
2802 /**** Tkapp Method List ****/
2804 static PyMethodDef Tkapp_methods[] =
2806 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2807 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2808 {"call", Tkapp_Call, METH_VARARGS},
2809 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2810 {"eval", Tkapp_Eval, METH_VARARGS},
2811 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2812 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2813 {"record", Tkapp_Record, METH_VARARGS},
2814 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2815 {"setvar", Tkapp_SetVar, METH_VARARGS},
2816 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2817 {"getvar", Tkapp_GetVar, METH_VARARGS},
2818 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2819 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2820 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2821 {"getint", Tkapp_GetInt, METH_VARARGS},
2822 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2823 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2824 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2825 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2826 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2827 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2828 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2829 {"split", Tkapp_Split, METH_VARARGS},
2830 {"merge", Tkapp_Merge, METH_VARARGS},
2831 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2832 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2833 #ifdef HAVE_CREATEFILEHANDLER
2834 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2835 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2836 #endif
2837 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2838 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2839 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2840 {"quit", Tkapp_Quit, METH_VARARGS},
2841 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2842 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2843 {NULL, NULL}
2848 /**** Tkapp Type Methods ****/
2850 static void
2851 Tkapp_Dealloc(PyObject *self)
2853 /*CHECK_TCL_APPARTMENT;*/
2854 ENTER_TCL
2855 Tcl_DeleteInterp(Tkapp_Interp(self));
2856 LEAVE_TCL
2857 PyObject_Del(self);
2858 DisableEventHook();
2861 static PyObject *
2862 Tkapp_GetAttr(PyObject *self, char *name)
2864 return Py_FindMethod(Tkapp_methods, self, name);
2867 static PyTypeObject Tkapp_Type =
2869 PyVarObject_HEAD_INIT(NULL, 0)
2870 "tkapp", /*tp_name */
2871 sizeof(TkappObject), /*tp_basicsize */
2872 0, /*tp_itemsize */
2873 Tkapp_Dealloc, /*tp_dealloc */
2874 0, /*tp_print */
2875 Tkapp_GetAttr, /*tp_getattr */
2876 0, /*tp_setattr */
2877 0, /*tp_compare */
2878 0, /*tp_repr */
2879 0, /*tp_as_number */
2880 0, /*tp_as_sequence */
2881 0, /*tp_as_mapping */
2882 0, /*tp_hash */
2887 /**** Tkinter Module ****/
2889 typedef struct {
2890 PyObject* tuple;
2891 int size; /* current size */
2892 int maxsize; /* allocated size */
2893 } FlattenContext;
2895 static int
2896 _bump(FlattenContext* context, int size)
2898 /* expand tuple to hold (at least) size new items.
2899 return true if successful, false if an exception was raised */
2901 int maxsize = context->maxsize * 2;
2903 if (maxsize < context->size + size)
2904 maxsize = context->size + size;
2906 context->maxsize = maxsize;
2908 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2911 static int
2912 _flatten1(FlattenContext* context, PyObject* item, int depth)
2914 /* add tuple or list to argument tuple (recursively) */
2916 int i, size;
2918 if (depth > 1000) {
2919 PyErr_SetString(PyExc_ValueError,
2920 "nesting too deep in _flatten");
2921 return 0;
2922 } else if (PyList_Check(item)) {
2923 size = PyList_GET_SIZE(item);
2924 /* preallocate (assume no nesting) */
2925 if (context->size + size > context->maxsize &&
2926 !_bump(context, size))
2927 return 0;
2928 /* copy items to output tuple */
2929 for (i = 0; i < size; i++) {
2930 PyObject *o = PyList_GET_ITEM(item, i);
2931 if (PyList_Check(o) || PyTuple_Check(o)) {
2932 if (!_flatten1(context, o, depth + 1))
2933 return 0;
2934 } else if (o != Py_None) {
2935 if (context->size + 1 > context->maxsize &&
2936 !_bump(context, 1))
2937 return 0;
2938 Py_INCREF(o);
2939 PyTuple_SET_ITEM(context->tuple,
2940 context->size++, o);
2943 } else if (PyTuple_Check(item)) {
2944 /* same, for tuples */
2945 size = PyTuple_GET_SIZE(item);
2946 if (context->size + size > context->maxsize &&
2947 !_bump(context, size))
2948 return 0;
2949 for (i = 0; i < size; i++) {
2950 PyObject *o = PyTuple_GET_ITEM(item, i);
2951 if (PyList_Check(o) || PyTuple_Check(o)) {
2952 if (!_flatten1(context, o, depth + 1))
2953 return 0;
2954 } else if (o != Py_None) {
2955 if (context->size + 1 > context->maxsize &&
2956 !_bump(context, 1))
2957 return 0;
2958 Py_INCREF(o);
2959 PyTuple_SET_ITEM(context->tuple,
2960 context->size++, o);
2963 } else {
2964 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2965 return 0;
2967 return 1;
2970 static PyObject *
2971 Tkinter_Flatten(PyObject* self, PyObject* args)
2973 FlattenContext context;
2974 PyObject* item;
2976 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2977 return NULL;
2979 context.maxsize = PySequence_Size(item);
2980 if (context.maxsize < 0)
2981 return NULL;
2982 if (context.maxsize == 0)
2983 return PyTuple_New(0);
2985 context.tuple = PyTuple_New(context.maxsize);
2986 if (!context.tuple)
2987 return NULL;
2989 context.size = 0;
2991 if (!_flatten1(&context, item,0))
2992 return NULL;
2994 if (_PyTuple_Resize(&context.tuple, context.size))
2995 return NULL;
2997 return context.tuple;
3000 static PyObject *
3001 Tkinter_Create(PyObject *self, PyObject *args)
3003 char *screenName = NULL;
3004 char *baseName = NULL;
3005 char *className = NULL;
3006 int interactive = 0;
3007 int wantobjects = 0;
3008 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3009 int sync = 0; /* pass -sync to wish */
3010 char *use = NULL; /* pass -use to wish */
3012 baseName = strrchr(Py_GetProgramName(), '/');
3013 if (baseName != NULL)
3014 baseName++;
3015 else
3016 baseName = Py_GetProgramName();
3017 className = "Tk";
3019 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3020 &screenName, &baseName, &className,
3021 &interactive, &wantobjects, &wantTk,
3022 &sync, &use))
3023 return NULL;
3025 return (PyObject *) Tkapp_New(screenName, baseName, className,
3026 interactive, wantobjects, wantTk,
3027 sync, use);
3030 static PyObject *
3031 Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3033 int new_val;
3034 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3035 return NULL;
3036 if (new_val < 0) {
3037 PyErr_SetString(PyExc_ValueError,
3038 "busywaitinterval must be >= 0");
3039 return NULL;
3041 Tkinter_busywaitinterval = new_val;
3042 Py_INCREF(Py_None);
3043 return Py_None;
3046 static char setbusywaitinterval_doc[] =
3047 "setbusywaitinterval(n) -> None\n\
3049 Set the busy-wait interval in milliseconds between successive\n\
3050 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3051 It should be set to a divisor of the maximum time between\n\
3052 frames in an animation.";
3054 static PyObject *
3055 Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3057 return PyInt_FromLong(Tkinter_busywaitinterval);
3060 static char getbusywaitinterval_doc[] =
3061 "getbusywaitinterval() -> int\n\
3063 Return the current busy-wait interval between successive\n\
3064 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3066 static PyMethodDef moduleMethods[] =
3068 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3069 {"create", Tkinter_Create, METH_VARARGS},
3070 #ifdef HAVE_CREATEFILEHANDLER
3071 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3072 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
3073 #endif
3074 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3075 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3076 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3077 {"quit", Tkapp_Quit, METH_VARARGS},
3078 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3079 setbusywaitinterval_doc},
3080 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3081 METH_NOARGS, getbusywaitinterval_doc},
3082 {NULL, NULL}
3085 #ifdef WAIT_FOR_STDIN
3087 static int stdin_ready = 0;
3089 #ifndef MS_WINDOWS
3090 static void
3091 MyFileProc(void *clientData, int mask)
3093 stdin_ready = 1;
3095 #endif
3097 #ifdef WITH_THREAD
3098 static PyThreadState *event_tstate = NULL;
3099 #endif
3101 static int
3102 EventHook(void)
3104 #ifndef MS_WINDOWS
3105 int tfile;
3106 #endif
3107 #ifdef WITH_THREAD
3108 PyEval_RestoreThread(event_tstate);
3109 #endif
3110 stdin_ready = 0;
3111 errorInCmd = 0;
3112 #ifndef MS_WINDOWS
3113 tfile = fileno(stdin);
3114 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
3115 #endif
3116 while (!errorInCmd && !stdin_ready) {
3117 int result;
3118 #ifdef MS_WINDOWS
3119 if (_kbhit()) {
3120 stdin_ready = 1;
3121 break;
3123 #endif
3124 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3125 Py_BEGIN_ALLOW_THREADS
3126 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3127 tcl_tstate = event_tstate;
3129 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3131 tcl_tstate = NULL;
3132 if(tcl_lock)PyThread_release_lock(tcl_lock);
3133 if (result == 0)
3134 Sleep(Tkinter_busywaitinterval);
3135 Py_END_ALLOW_THREADS
3136 #else
3137 result = Tcl_DoOneEvent(0);
3138 #endif
3140 if (result < 0)
3141 break;
3143 #ifndef MS_WINDOWS
3144 Tcl_DeleteFileHandler(tfile);
3145 #endif
3146 if (errorInCmd) {
3147 errorInCmd = 0;
3148 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3149 excInCmd = valInCmd = trbInCmd = NULL;
3150 PyErr_Print();
3152 #ifdef WITH_THREAD
3153 PyEval_SaveThread();
3154 #endif
3155 return 0;
3158 #endif
3160 static void
3161 EnableEventHook(void)
3163 #ifdef WAIT_FOR_STDIN
3164 if (PyOS_InputHook == NULL) {
3165 #ifdef WITH_THREAD
3166 event_tstate = PyThreadState_Get();
3167 #endif
3168 PyOS_InputHook = EventHook;
3170 #endif
3173 static void
3174 DisableEventHook(void)
3176 #ifdef WAIT_FOR_STDIN
3177 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3178 PyOS_InputHook = NULL;
3180 #endif
3184 /* all errors will be checked in one fell swoop in init_tkinter() */
3185 static void
3186 ins_long(PyObject *d, char *name, long val)
3188 PyObject *v = PyInt_FromLong(val);
3189 if (v) {
3190 PyDict_SetItemString(d, name, v);
3191 Py_DECREF(v);
3194 static void
3195 ins_string(PyObject *d, char *name, char *val)
3197 PyObject *v = PyString_FromString(val);
3198 if (v) {
3199 PyDict_SetItemString(d, name, v);
3200 Py_DECREF(v);
3205 PyMODINIT_FUNC
3206 init_tkinter(void)
3208 PyObject *m, *d;
3210 Py_TYPE(&Tkapp_Type) = &PyType_Type;
3212 #ifdef WITH_THREAD
3213 tcl_lock = PyThread_allocate_lock();
3214 #endif
3216 m = Py_InitModule("_tkinter", moduleMethods);
3217 if (m == NULL)
3218 return;
3220 d = PyModule_GetDict(m);
3221 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3222 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3224 ins_long(d, "READABLE", TCL_READABLE);
3225 ins_long(d, "WRITABLE", TCL_WRITABLE);
3226 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3227 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3228 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3229 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3230 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3231 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3232 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3233 ins_string(d, "TK_VERSION", TK_VERSION);
3234 ins_string(d, "TCL_VERSION", TCL_VERSION);
3236 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3238 Py_TYPE(&Tktt_Type) = &PyType_Type;
3239 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3241 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3242 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3244 #ifdef TK_AQUA
3245 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3246 * start waking up. Note that Tcl_FindExecutable will do this, this
3247 * code must be above it! The original warning from
3248 * tkMacOSXAppInit.c is copied below.
3250 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3251 * Tcl interpreter for now. It probably should work to do this
3252 * in the other order, but for now it doesn't seem to.
3255 Tk_MacOSXSetupTkNotifier();
3256 #endif
3259 /* This helps the dynamic loader; in Unicode aware Tcl versions
3260 it also helps Tcl find its encodings. */
3261 Tcl_FindExecutable(Py_GetProgramName());
3263 if (PyErr_Occurred())
3264 return;
3266 #if 0
3267 /* This was not a good idea; through <Destroy> bindings,
3268 Tcl_Finalize() may invoke Python code but at that point the
3269 interpreter and thread state have already been destroyed! */
3270 Py_AtExit(Tcl_Finalize);
3271 #endif