move sections
[python/dscho.git] / Modules / _tkinter.c
blob01d628435a086f580af979bd4fc3dd7578d04d30
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 *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 func = data->func;
2063 /* Create argument list (argv1, ..., argvN) */
2064 if (!(arg = PyTuple_New(argc - 1)))
2065 return PythonCmd_Error(interp);
2067 for (i = 0; i < (argc - 1); i++) {
2068 PyObject *s = PyString_FromString(argv[i + 1]);
2069 if (!s || PyTuple_SetItem(arg, i, s)) {
2070 Py_DECREF(arg);
2071 return PythonCmd_Error(interp);
2074 res = PyEval_CallObject(func, arg);
2075 Py_DECREF(arg);
2077 if (res == NULL)
2078 return PythonCmd_Error(interp);
2080 obj_res = AsObj(res);
2081 if (obj_res == NULL) {
2082 Py_DECREF(res);
2083 return PythonCmd_Error(interp);
2085 else {
2086 Tcl_SetObjResult(interp, obj_res);
2087 rv = TCL_OK;
2090 Py_DECREF(res);
2092 LEAVE_PYTHON
2094 return rv;
2097 static void
2098 PythonCmdDelete(ClientData clientData)
2100 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2102 ENTER_PYTHON
2103 Py_XDECREF(data->self);
2104 Py_XDECREF(data->func);
2105 PyMem_DEL(data);
2106 LEAVE_PYTHON
2112 #ifdef WITH_THREAD
2113 TCL_DECLARE_MUTEX(command_mutex)
2115 typedef struct CommandEvent{
2116 Tcl_Event ev;
2117 Tcl_Interp* interp;
2118 char *name;
2119 int create;
2120 int *status;
2121 ClientData *data;
2122 Tcl_Condition *done;
2123 } CommandEvent;
2125 static int
2126 Tkapp_CommandProc(CommandEvent *ev, int flags)
2128 if (ev->create)
2129 *ev->status = Tcl_CreateCommand(
2130 ev->interp, ev->name, PythonCmd,
2131 ev->data, PythonCmdDelete) == NULL;
2132 else
2133 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2134 Tcl_MutexLock(&command_mutex);
2135 Tcl_ConditionNotify(ev->done);
2136 Tcl_MutexUnlock(&command_mutex);
2137 return 1;
2139 #endif
2141 static PyObject *
2142 Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
2144 TkappObject *self = (TkappObject*)selfptr;
2145 PythonCmd_ClientData *data;
2146 char *cmdName;
2147 PyObject *func;
2148 int err;
2150 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2151 return NULL;
2152 if (!PyCallable_Check(func)) {
2153 PyErr_SetString(PyExc_TypeError, "command not callable");
2154 return NULL;
2157 #ifdef WITH_THREAD
2158 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2159 !WaitForMainloop(self))
2160 return NULL;
2161 #endif
2163 data = PyMem_NEW(PythonCmd_ClientData, 1);
2164 if (!data)
2165 return PyErr_NoMemory();
2166 Py_INCREF(self);
2167 Py_INCREF(func);
2168 data->self = selfptr;
2169 data->func = func;
2171 #ifdef WITH_THREAD
2172 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2173 Tcl_Condition cond = NULL;
2174 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2175 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2176 ev->interp = self->interp;
2177 ev->create = 1;
2178 ev->name = cmdName;
2179 ev->data = (ClientData)data;
2180 ev->status = &err;
2181 ev->done = &cond;
2182 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2183 Tcl_ConditionFinalize(&cond);
2185 else
2186 #endif
2188 ENTER_TCL
2189 err = Tcl_CreateCommand(
2190 Tkapp_Interp(self), cmdName, PythonCmd,
2191 (ClientData)data, PythonCmdDelete) == NULL;
2192 LEAVE_TCL
2194 if (err) {
2195 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2196 PyMem_DEL(data);
2197 return NULL;
2200 Py_INCREF(Py_None);
2201 return Py_None;
2206 static PyObject *
2207 Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
2209 TkappObject *self = (TkappObject*)selfptr;
2210 char *cmdName;
2211 int err;
2213 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2214 return NULL;
2216 #ifdef WITH_THREAD
2217 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2218 Tcl_Condition cond = NULL;
2219 CommandEvent *ev;
2220 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2221 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2222 ev->interp = self->interp;
2223 ev->create = 0;
2224 ev->name = cmdName;
2225 ev->status = &err;
2226 ev->done = &cond;
2227 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2228 &command_mutex);
2229 Tcl_ConditionFinalize(&cond);
2231 else
2232 #endif
2234 ENTER_TCL
2235 err = Tcl_DeleteCommand(self->interp, cmdName);
2236 LEAVE_TCL
2238 if (err == -1) {
2239 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2240 return NULL;
2242 Py_INCREF(Py_None);
2243 return Py_None;
2248 #ifdef HAVE_CREATEFILEHANDLER
2249 /** File Handler **/
2251 typedef struct _fhcdata {
2252 PyObject *func;
2253 PyObject *file;
2254 int id;
2255 struct _fhcdata *next;
2256 } FileHandler_ClientData;
2258 static FileHandler_ClientData *HeadFHCD;
2260 static FileHandler_ClientData *
2261 NewFHCD(PyObject *func, PyObject *file, int id)
2263 FileHandler_ClientData *p;
2264 p = PyMem_NEW(FileHandler_ClientData, 1);
2265 if (p != NULL) {
2266 Py_XINCREF(func);
2267 Py_XINCREF(file);
2268 p->func = func;
2269 p->file = file;
2270 p->id = id;
2271 p->next = HeadFHCD;
2272 HeadFHCD = p;
2274 return p;
2277 static void
2278 DeleteFHCD(int id)
2280 FileHandler_ClientData *p, **pp;
2282 pp = &HeadFHCD;
2283 while ((p = *pp) != NULL) {
2284 if (p->id == id) {
2285 *pp = p->next;
2286 Py_XDECREF(p->func);
2287 Py_XDECREF(p->file);
2288 PyMem_DEL(p);
2290 else
2291 pp = &p->next;
2295 static void
2296 FileHandler(ClientData clientData, int mask)
2298 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2299 PyObject *func, *file, *arg, *res;
2301 ENTER_PYTHON
2302 func = data->func;
2303 file = data->file;
2305 arg = Py_BuildValue("(Oi)", file, (long) mask);
2306 res = PyEval_CallObject(func, arg);
2307 Py_DECREF(arg);
2309 if (res == NULL) {
2310 errorInCmd = 1;
2311 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2313 Py_XDECREF(res);
2314 LEAVE_PYTHON
2317 static PyObject *
2318 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2319 /* args is (file, mask, func) */
2321 FileHandler_ClientData *data;
2322 PyObject *file, *func;
2323 int mask, tfile;
2325 if (!self && Py_Py3kWarningFlag) {
2326 if (PyErr_Warn(PyExc_DeprecationWarning,
2327 "_tkinter.createfilehandler is gone in 3.x") < 0)
2328 return NULL;
2331 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2332 &file, &mask, &func))
2333 return NULL;
2335 #ifdef WITH_THREAD
2336 if (!self && !tcl_lock) {
2337 /* We don't have the Tcl lock since Tcl is threaded. */
2338 PyErr_SetString(PyExc_RuntimeError,
2339 "_tkinter.createfilehandler not supported "
2340 "for threaded Tcl");
2341 return NULL;
2343 #endif
2345 if (self) {
2346 CHECK_TCL_APPARTMENT;
2349 tfile = PyObject_AsFileDescriptor(file);
2350 if (tfile < 0)
2351 return NULL;
2352 if (!PyCallable_Check(func)) {
2353 PyErr_SetString(PyExc_TypeError, "bad argument list");
2354 return NULL;
2357 data = NewFHCD(func, file, tfile);
2358 if (data == NULL)
2359 return NULL;
2361 /* Ought to check for null Tcl_File object... */
2362 ENTER_TCL
2363 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2364 LEAVE_TCL
2365 Py_INCREF(Py_None);
2366 return Py_None;
2369 static PyObject *
2370 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
2372 PyObject *file;
2373 int tfile;
2375 if (!self && Py_Py3kWarningFlag) {
2376 if (PyErr_Warn(PyExc_DeprecationWarning,
2377 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2378 return NULL;
2381 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2382 return NULL;
2384 #ifdef WITH_THREAD
2385 if (!self && !tcl_lock) {
2386 /* We don't have the Tcl lock since Tcl is threaded. */
2387 PyErr_SetString(PyExc_RuntimeError,
2388 "_tkinter.deletefilehandler not supported "
2389 "for threaded Tcl");
2390 return NULL;
2392 #endif
2394 if (self) {
2395 CHECK_TCL_APPARTMENT;
2398 tfile = PyObject_AsFileDescriptor(file);
2399 if (tfile < 0)
2400 return NULL;
2402 DeleteFHCD(tfile);
2404 /* Ought to check for null Tcl_File object... */
2405 ENTER_TCL
2406 Tcl_DeleteFileHandler(tfile);
2407 LEAVE_TCL
2408 Py_INCREF(Py_None);
2409 return Py_None;
2411 #endif /* HAVE_CREATEFILEHANDLER */
2414 /**** Tktt Object (timer token) ****/
2416 static PyTypeObject Tktt_Type;
2418 typedef struct {
2419 PyObject_HEAD
2420 Tcl_TimerToken token;
2421 PyObject *func;
2422 } TkttObject;
2424 static PyObject *
2425 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
2427 TkttObject *v = (TkttObject *)self;
2428 PyObject *func = v->func;
2430 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2431 return NULL;
2432 if (v->token != NULL) {
2433 Tcl_DeleteTimerHandler(v->token);
2434 v->token = NULL;
2436 if (func != NULL) {
2437 v->func = NULL;
2438 Py_DECREF(func);
2439 Py_DECREF(v); /* See Tktt_New() */
2441 Py_INCREF(Py_None);
2442 return Py_None;
2445 static PyMethodDef Tktt_methods[] =
2447 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2448 {NULL, NULL}
2451 static TkttObject *
2452 Tktt_New(PyObject *func)
2454 TkttObject *v;
2456 v = PyObject_New(TkttObject, &Tktt_Type);
2457 if (v == NULL)
2458 return NULL;
2460 Py_INCREF(func);
2461 v->token = NULL;
2462 v->func = func;
2464 /* Extra reference, deleted when called or when handler is deleted */
2465 Py_INCREF(v);
2466 return v;
2469 static void
2470 Tktt_Dealloc(PyObject *self)
2472 TkttObject *v = (TkttObject *)self;
2473 PyObject *func = v->func;
2475 Py_XDECREF(func);
2477 PyObject_Del(self);
2480 static PyObject *
2481 Tktt_Repr(PyObject *self)
2483 TkttObject *v = (TkttObject *)self;
2484 char buf[100];
2486 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2487 v->func == NULL ? ", handler deleted" : "");
2488 return PyString_FromString(buf);
2491 static PyObject *
2492 Tktt_GetAttr(PyObject *self, char *name)
2494 return Py_FindMethod(Tktt_methods, self, name);
2497 static PyTypeObject Tktt_Type =
2499 PyVarObject_HEAD_INIT(NULL, 0)
2500 "tktimertoken", /*tp_name */
2501 sizeof(TkttObject), /*tp_basicsize */
2502 0, /*tp_itemsize */
2503 Tktt_Dealloc, /*tp_dealloc */
2504 0, /*tp_print */
2505 Tktt_GetAttr, /*tp_getattr */
2506 0, /*tp_setattr */
2507 0, /*tp_compare */
2508 Tktt_Repr, /*tp_repr */
2509 0, /*tp_as_number */
2510 0, /*tp_as_sequence */
2511 0, /*tp_as_mapping */
2512 0, /*tp_hash */
2517 /** Timer Handler **/
2519 static void
2520 TimerHandler(ClientData clientData)
2522 TkttObject *v = (TkttObject *)clientData;
2523 PyObject *func = v->func;
2524 PyObject *res;
2526 if (func == NULL)
2527 return;
2529 v->func = NULL;
2531 ENTER_PYTHON
2533 res = PyEval_CallObject(func, NULL);
2534 Py_DECREF(func);
2535 Py_DECREF(v); /* See Tktt_New() */
2537 if (res == NULL) {
2538 errorInCmd = 1;
2539 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2541 else
2542 Py_DECREF(res);
2544 LEAVE_PYTHON
2547 static PyObject *
2548 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
2550 int milliseconds;
2551 PyObject *func;
2552 TkttObject *v;
2554 if (!self && Py_Py3kWarningFlag) {
2555 if (PyErr_Warn(PyExc_DeprecationWarning,
2556 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2557 return NULL;
2560 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2561 &milliseconds, &func))
2562 return NULL;
2563 if (!PyCallable_Check(func)) {
2564 PyErr_SetString(PyExc_TypeError, "bad argument list");
2565 return NULL;
2568 #ifdef WITH_THREAD
2569 if (!self && !tcl_lock) {
2570 /* We don't have the Tcl lock since Tcl is threaded. */
2571 PyErr_SetString(PyExc_RuntimeError,
2572 "_tkinter.createtimerhandler not supported "
2573 "for threaded Tcl");
2574 return NULL;
2576 #endif
2578 if (self) {
2579 CHECK_TCL_APPARTMENT;
2582 v = Tktt_New(func);
2583 if (v) {
2584 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2585 (ClientData)v);
2588 return (PyObject *) v;
2592 /** Event Loop **/
2594 static PyObject *
2595 Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
2597 int threshold = 0;
2598 TkappObject *self = (TkappObject*)selfptr;
2599 #ifdef WITH_THREAD
2600 PyThreadState *tstate = PyThreadState_Get();
2601 #endif
2603 if (!self && Py_Py3kWarningFlag) {
2604 if (PyErr_Warn(PyExc_DeprecationWarning,
2605 "_tkinter.mainloop is gone in 3.x") < 0)
2606 return NULL;
2609 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2610 return NULL;
2612 #ifdef WITH_THREAD
2613 if (!self && !tcl_lock) {
2614 /* We don't have the Tcl lock since Tcl is threaded. */
2615 PyErr_SetString(PyExc_RuntimeError,
2616 "_tkinter.mainloop not supported "
2617 "for threaded Tcl");
2618 return NULL;
2620 #endif
2622 if (self) {
2623 CHECK_TCL_APPARTMENT;
2624 self->dispatching = 1;
2627 quitMainLoop = 0;
2628 while (Tk_GetNumMainWindows() > threshold &&
2629 !quitMainLoop &&
2630 !errorInCmd)
2632 int result;
2634 #ifdef WITH_THREAD
2635 if (self && self->threaded) {
2636 /* Allow other Python threads to run. */
2637 ENTER_TCL
2638 result = Tcl_DoOneEvent(0);
2639 LEAVE_TCL
2641 else {
2642 Py_BEGIN_ALLOW_THREADS
2643 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2644 tcl_tstate = tstate;
2645 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2646 tcl_tstate = NULL;
2647 if(tcl_lock)PyThread_release_lock(tcl_lock);
2648 if (result == 0)
2649 Sleep(Tkinter_busywaitinterval);
2650 Py_END_ALLOW_THREADS
2652 #else
2653 result = Tcl_DoOneEvent(0);
2654 #endif
2656 if (PyErr_CheckSignals() != 0) {
2657 if (self)
2658 self->dispatching = 0;
2659 return NULL;
2661 if (result < 0)
2662 break;
2664 if (self)
2665 self->dispatching = 0;
2666 quitMainLoop = 0;
2668 if (errorInCmd) {
2669 errorInCmd = 0;
2670 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2671 excInCmd = valInCmd = trbInCmd = NULL;
2672 return NULL;
2674 Py_INCREF(Py_None);
2675 return Py_None;
2678 static PyObject *
2679 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
2681 int flags = 0;
2682 int rv;
2684 if (!self && Py_Py3kWarningFlag) {
2685 if (PyErr_Warn(PyExc_DeprecationWarning,
2686 "_tkinter.dooneevent is gone in 3.x") < 0)
2687 return NULL;
2690 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2691 return NULL;
2693 ENTER_TCL
2694 rv = Tcl_DoOneEvent(flags);
2695 LEAVE_TCL
2696 return Py_BuildValue("i", rv);
2699 static PyObject *
2700 Tkapp_Quit(PyObject *self, PyObject *args)
2703 if (!self && Py_Py3kWarningFlag) {
2704 if (PyErr_Warn(PyExc_DeprecationWarning,
2705 "_tkinter.quit is gone in 3.x") < 0)
2706 return NULL;
2709 if (!PyArg_ParseTuple(args, ":quit"))
2710 return NULL;
2712 quitMainLoop = 1;
2713 Py_INCREF(Py_None);
2714 return Py_None;
2717 static PyObject *
2718 Tkapp_InterpAddr(PyObject *self, PyObject *args)
2721 if (!PyArg_ParseTuple(args, ":interpaddr"))
2722 return NULL;
2724 return PyInt_FromLong((long)Tkapp_Interp(self));
2727 static PyObject *
2728 Tkapp_TkInit(PyObject *self, PyObject *args)
2730 Tcl_Interp *interp = Tkapp_Interp(self);
2731 const char * _tk_exists = NULL;
2732 int err;
2734 #ifdef TKINTER_PROTECT_LOADTK
2735 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2736 * first call failed.
2737 * To avoid the deadlock, we just refuse the second call through
2738 * a static variable.
2740 if (tk_load_failed) {
2741 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2742 return NULL;
2744 #endif
2746 /* We want to guard against calling Tk_Init() multiple times */
2747 CHECK_TCL_APPARTMENT;
2748 ENTER_TCL
2749 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2750 ENTER_OVERLAP
2751 if (err == TCL_ERROR) {
2752 /* This sets an exception, but we cannot return right
2753 away because we need to exit the overlap first. */
2754 Tkinter_Error(self);
2755 } else {
2756 _tk_exists = Tkapp_Result(self);
2758 LEAVE_OVERLAP_TCL
2759 if (err == TCL_ERROR) {
2760 return NULL;
2762 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2763 if (Tk_Init(interp) == TCL_ERROR) {
2764 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2765 #ifdef TKINTER_PROTECT_LOADTK
2766 tk_load_failed = 1;
2767 #endif
2768 return NULL;
2771 Py_INCREF(Py_None);
2772 return Py_None;
2775 static PyObject *
2776 Tkapp_WantObjects(PyObject *self, PyObject *args)
2779 int wantobjects = -1;
2780 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2781 return NULL;
2782 if (wantobjects == -1)
2783 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2784 ((TkappObject*)self)->wantobjects = wantobjects;
2786 Py_INCREF(Py_None);
2787 return Py_None;
2790 static PyObject *
2791 Tkapp_WillDispatch(PyObject *self, PyObject *args)
2794 ((TkappObject*)self)->dispatching = 1;
2796 Py_INCREF(Py_None);
2797 return Py_None;
2801 /**** Tkapp Method List ****/
2803 static PyMethodDef Tkapp_methods[] =
2805 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2806 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2807 {"call", Tkapp_Call, METH_VARARGS},
2808 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2809 {"eval", Tkapp_Eval, METH_VARARGS},
2810 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2811 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2812 {"record", Tkapp_Record, METH_VARARGS},
2813 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2814 {"setvar", Tkapp_SetVar, METH_VARARGS},
2815 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2816 {"getvar", Tkapp_GetVar, METH_VARARGS},
2817 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2818 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2819 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2820 {"getint", Tkapp_GetInt, METH_VARARGS},
2821 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2822 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2823 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2824 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2825 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2826 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2827 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2828 {"split", Tkapp_Split, METH_VARARGS},
2829 {"merge", Tkapp_Merge, METH_VARARGS},
2830 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2831 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
2832 #ifdef HAVE_CREATEFILEHANDLER
2833 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2834 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
2835 #endif
2836 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2837 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2838 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2839 {"quit", Tkapp_Quit, METH_VARARGS},
2840 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2841 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2842 {NULL, NULL}
2847 /**** Tkapp Type Methods ****/
2849 static void
2850 Tkapp_Dealloc(PyObject *self)
2852 /*CHECK_TCL_APPARTMENT;*/
2853 ENTER_TCL
2854 Tcl_DeleteInterp(Tkapp_Interp(self));
2855 LEAVE_TCL
2856 PyObject_Del(self);
2857 DisableEventHook();
2860 static PyObject *
2861 Tkapp_GetAttr(PyObject *self, char *name)
2863 return Py_FindMethod(Tkapp_methods, self, name);
2866 static PyTypeObject Tkapp_Type =
2868 PyVarObject_HEAD_INIT(NULL, 0)
2869 "tkapp", /*tp_name */
2870 sizeof(TkappObject), /*tp_basicsize */
2871 0, /*tp_itemsize */
2872 Tkapp_Dealloc, /*tp_dealloc */
2873 0, /*tp_print */
2874 Tkapp_GetAttr, /*tp_getattr */
2875 0, /*tp_setattr */
2876 0, /*tp_compare */
2877 0, /*tp_repr */
2878 0, /*tp_as_number */
2879 0, /*tp_as_sequence */
2880 0, /*tp_as_mapping */
2881 0, /*tp_hash */
2886 /**** Tkinter Module ****/
2888 typedef struct {
2889 PyObject* tuple;
2890 int size; /* current size */
2891 int maxsize; /* allocated size */
2892 } FlattenContext;
2894 static int
2895 _bump(FlattenContext* context, int size)
2897 /* expand tuple to hold (at least) size new items.
2898 return true if successful, false if an exception was raised */
2900 int maxsize = context->maxsize * 2;
2902 if (maxsize < context->size + size)
2903 maxsize = context->size + size;
2905 context->maxsize = maxsize;
2907 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
2910 static int
2911 _flatten1(FlattenContext* context, PyObject* item, int depth)
2913 /* add tuple or list to argument tuple (recursively) */
2915 int i, size;
2917 if (depth > 1000) {
2918 PyErr_SetString(PyExc_ValueError,
2919 "nesting too deep in _flatten");
2920 return 0;
2921 } else if (PyList_Check(item)) {
2922 size = PyList_GET_SIZE(item);
2923 /* preallocate (assume no nesting) */
2924 if (context->size + size > context->maxsize &&
2925 !_bump(context, size))
2926 return 0;
2927 /* copy items to output tuple */
2928 for (i = 0; i < size; i++) {
2929 PyObject *o = PyList_GET_ITEM(item, i);
2930 if (PyList_Check(o) || PyTuple_Check(o)) {
2931 if (!_flatten1(context, o, depth + 1))
2932 return 0;
2933 } else if (o != Py_None) {
2934 if (context->size + 1 > context->maxsize &&
2935 !_bump(context, 1))
2936 return 0;
2937 Py_INCREF(o);
2938 PyTuple_SET_ITEM(context->tuple,
2939 context->size++, o);
2942 } else if (PyTuple_Check(item)) {
2943 /* same, for tuples */
2944 size = PyTuple_GET_SIZE(item);
2945 if (context->size + size > context->maxsize &&
2946 !_bump(context, size))
2947 return 0;
2948 for (i = 0; i < size; i++) {
2949 PyObject *o = PyTuple_GET_ITEM(item, i);
2950 if (PyList_Check(o) || PyTuple_Check(o)) {
2951 if (!_flatten1(context, o, depth + 1))
2952 return 0;
2953 } else if (o != Py_None) {
2954 if (context->size + 1 > context->maxsize &&
2955 !_bump(context, 1))
2956 return 0;
2957 Py_INCREF(o);
2958 PyTuple_SET_ITEM(context->tuple,
2959 context->size++, o);
2962 } else {
2963 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2964 return 0;
2966 return 1;
2969 static PyObject *
2970 Tkinter_Flatten(PyObject* self, PyObject* args)
2972 FlattenContext context;
2973 PyObject* item;
2975 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2976 return NULL;
2978 context.maxsize = PySequence_Size(item);
2979 if (context.maxsize < 0)
2980 return NULL;
2981 if (context.maxsize == 0)
2982 return PyTuple_New(0);
2984 context.tuple = PyTuple_New(context.maxsize);
2985 if (!context.tuple)
2986 return NULL;
2988 context.size = 0;
2990 if (!_flatten1(&context, item,0))
2991 return NULL;
2993 if (_PyTuple_Resize(&context.tuple, context.size))
2994 return NULL;
2996 return context.tuple;
2999 static PyObject *
3000 Tkinter_Create(PyObject *self, PyObject *args)
3002 char *screenName = NULL;
3003 char *baseName = NULL;
3004 char *className = NULL;
3005 int interactive = 0;
3006 int wantobjects = 0;
3007 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3008 int sync = 0; /* pass -sync to wish */
3009 char *use = NULL; /* pass -use to wish */
3011 baseName = strrchr(Py_GetProgramName(), '/');
3012 if (baseName != NULL)
3013 baseName++;
3014 else
3015 baseName = Py_GetProgramName();
3016 className = "Tk";
3018 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3019 &screenName, &baseName, &className,
3020 &interactive, &wantobjects, &wantTk,
3021 &sync, &use))
3022 return NULL;
3024 return (PyObject *) Tkapp_New(screenName, baseName, className,
3025 interactive, wantobjects, wantTk,
3026 sync, use);
3029 static PyObject *
3030 Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3032 int new_val;
3033 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3034 return NULL;
3035 if (new_val < 0) {
3036 PyErr_SetString(PyExc_ValueError,
3037 "busywaitinterval must be >= 0");
3038 return NULL;
3040 Tkinter_busywaitinterval = new_val;
3041 Py_INCREF(Py_None);
3042 return Py_None;
3045 static char setbusywaitinterval_doc[] =
3046 "setbusywaitinterval(n) -> None\n\
3048 Set the busy-wait interval in milliseconds between successive\n\
3049 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3050 It should be set to a divisor of the maximum time between\n\
3051 frames in an animation.";
3053 static PyObject *
3054 Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3056 return PyInt_FromLong(Tkinter_busywaitinterval);
3059 static char getbusywaitinterval_doc[] =
3060 "getbusywaitinterval() -> int\n\
3062 Return the current busy-wait interval between successive\n\
3063 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3065 static PyMethodDef moduleMethods[] =
3067 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3068 {"create", Tkinter_Create, METH_VARARGS},
3069 #ifdef HAVE_CREATEFILEHANDLER
3070 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3071 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
3072 #endif
3073 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3074 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3075 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3076 {"quit", Tkapp_Quit, METH_VARARGS},
3077 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3078 setbusywaitinterval_doc},
3079 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3080 METH_NOARGS, getbusywaitinterval_doc},
3081 {NULL, NULL}
3084 #ifdef WAIT_FOR_STDIN
3086 static int stdin_ready = 0;
3088 #ifndef MS_WINDOWS
3089 static void
3090 MyFileProc(void *clientData, int mask)
3092 stdin_ready = 1;
3094 #endif
3096 #ifdef WITH_THREAD
3097 static PyThreadState *event_tstate = NULL;
3098 #endif
3100 static int
3101 EventHook(void)
3103 #ifndef MS_WINDOWS
3104 int tfile;
3105 #endif
3106 #ifdef WITH_THREAD
3107 PyEval_RestoreThread(event_tstate);
3108 #endif
3109 stdin_ready = 0;
3110 errorInCmd = 0;
3111 #ifndef MS_WINDOWS
3112 tfile = fileno(stdin);
3113 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
3114 #endif
3115 while (!errorInCmd && !stdin_ready) {
3116 int result;
3117 #ifdef MS_WINDOWS
3118 if (_kbhit()) {
3119 stdin_ready = 1;
3120 break;
3122 #endif
3123 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3124 Py_BEGIN_ALLOW_THREADS
3125 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3126 tcl_tstate = event_tstate;
3128 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3130 tcl_tstate = NULL;
3131 if(tcl_lock)PyThread_release_lock(tcl_lock);
3132 if (result == 0)
3133 Sleep(Tkinter_busywaitinterval);
3134 Py_END_ALLOW_THREADS
3135 #else
3136 result = Tcl_DoOneEvent(0);
3137 #endif
3139 if (result < 0)
3140 break;
3142 #ifndef MS_WINDOWS
3143 Tcl_DeleteFileHandler(tfile);
3144 #endif
3145 if (errorInCmd) {
3146 errorInCmd = 0;
3147 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3148 excInCmd = valInCmd = trbInCmd = NULL;
3149 PyErr_Print();
3151 #ifdef WITH_THREAD
3152 PyEval_SaveThread();
3153 #endif
3154 return 0;
3157 #endif
3159 static void
3160 EnableEventHook(void)
3162 #ifdef WAIT_FOR_STDIN
3163 if (PyOS_InputHook == NULL) {
3164 #ifdef WITH_THREAD
3165 event_tstate = PyThreadState_Get();
3166 #endif
3167 PyOS_InputHook = EventHook;
3169 #endif
3172 static void
3173 DisableEventHook(void)
3175 #ifdef WAIT_FOR_STDIN
3176 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3177 PyOS_InputHook = NULL;
3179 #endif
3183 /* all errors will be checked in one fell swoop in init_tkinter() */
3184 static void
3185 ins_long(PyObject *d, char *name, long val)
3187 PyObject *v = PyInt_FromLong(val);
3188 if (v) {
3189 PyDict_SetItemString(d, name, v);
3190 Py_DECREF(v);
3193 static void
3194 ins_string(PyObject *d, char *name, char *val)
3196 PyObject *v = PyString_FromString(val);
3197 if (v) {
3198 PyDict_SetItemString(d, name, v);
3199 Py_DECREF(v);
3204 PyMODINIT_FUNC
3205 init_tkinter(void)
3207 PyObject *m, *d;
3209 Py_TYPE(&Tkapp_Type) = &PyType_Type;
3211 #ifdef WITH_THREAD
3212 tcl_lock = PyThread_allocate_lock();
3213 #endif
3215 m = Py_InitModule("_tkinter", moduleMethods);
3216 if (m == NULL)
3217 return;
3219 d = PyModule_GetDict(m);
3220 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3221 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
3223 ins_long(d, "READABLE", TCL_READABLE);
3224 ins_long(d, "WRITABLE", TCL_WRITABLE);
3225 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3226 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3227 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3228 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3229 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3230 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3231 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3232 ins_string(d, "TK_VERSION", TK_VERSION);
3233 ins_string(d, "TCL_VERSION", TCL_VERSION);
3235 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
3237 Py_TYPE(&Tktt_Type) = &PyType_Type;
3238 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
3240 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3241 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
3243 #ifdef TK_AQUA
3244 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3245 * start waking up. Note that Tcl_FindExecutable will do this, this
3246 * code must be above it! The original warning from
3247 * tkMacOSXAppInit.c is copied below.
3249 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3250 * Tcl interpreter for now. It probably should work to do this
3251 * in the other order, but for now it doesn't seem to.
3254 Tk_MacOSXSetupTkNotifier();
3255 #endif
3258 /* This helps the dynamic loader; in Unicode aware Tcl versions
3259 it also helps Tcl find its encodings. */
3260 Tcl_FindExecutable(Py_GetProgramName());
3262 if (PyErr_Occurred())
3263 return;
3265 #if 0
3266 /* This was not a good idea; through <Destroy> bindings,
3267 Tcl_Finalize() may invoke Python code but at that point the
3268 interpreter and thread state have already been destroyed! */
3269 Py_AtExit(Tcl_Finalize);
3270 #endif