Bump version to 0.9.1.
[python/dscho.git] / Modules / _tkinter.c
blob9601f0680f504e5e17aad5309efdc3371ebf6bd0
1 /***********************************************************
2 Copyright (C) 1994 Steen Lumholt.
3 Copyright 1994-1995 by Stichting Mathematisch Centrum, Amsterdam,
4 The Netherlands.
6 All Rights Reserved
8 Copyright (c) 2000, BeOpen.com.
9 Copyright (c) 1995-2000, Corporation for National Research Initiatives.
10 Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
11 All rights reserved.
13 See the file "Misc/COPYRIGHT" for information on usage and
14 redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 ******************************************************************/
18 /* _tkinter.c -- Interface to libtk.a and libtcl.a. */
20 /* TCL/TK VERSION INFO:
22 Only Tcl/Tk 8.0 and later are supported. Older versions are not
23 supported. (Use Python 1.5.2 if you cannot upgrade your Tcl/Tk
24 libraries.)
27 /* XXX Further speed-up ideas, involving Tcl 8.0 features:
29 - In Tcl_Call(), create Tcl objects from the arguments, possibly using
30 intelligent mappings between Python objects and Tcl objects (e.g. ints,
31 floats and Tcl window pointers could be handled specially).
33 - Register a new Tcl type, "Python callable", which can be called more
34 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
39 #include "Python.h"
40 #include <ctype.h>
42 #ifdef WITH_THREAD
43 #include "pythread.h"
44 #endif
46 #ifdef MS_WINDOWS
47 #include <windows.h>
48 #endif
50 #ifdef macintosh
51 #define MAC_TCL
52 #endif
54 #include <tcl.h>
55 #include <tk.h>
57 #define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
59 #if TKMAJORMINOR < 8000
60 #error "Tk older than 8.0 not supported"
61 #endif
63 #if defined(macintosh)
64 /* Sigh, we have to include this to get at the tcl qd pointer */
65 #include <tkMac.h>
66 /* And this one we need to clear the menu bar */
67 #include <Menus.h>
68 #endif
70 #if !defined(MS_WINDOWS)
71 #define HAVE_CREATEFILEHANDLER
72 #endif
74 #ifdef HAVE_CREATEFILEHANDLER
76 /* Tcl_CreateFileHandler() changed several times; these macros deal with the
77 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
78 Unix, only because Jack added it back); when available on Windows, it only
79 applies to sockets. */
81 #ifdef MS_WINDOWS
82 #define FHANDLETYPE TCL_WIN_SOCKET
83 #else
84 #define FHANDLETYPE TCL_UNIX_FD
85 #endif
87 /* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
88 which uses this to handle Tcl events while the user is typing commands. */
90 #if FHANDLETYPE == TCL_UNIX_FD
91 #define WAIT_FOR_STDIN
92 #endif
94 #endif /* HAVE_CREATEFILEHANDLER */
96 #ifdef MS_WINDOWS
97 #include <conio.h>
98 #define WAIT_FOR_STDIN
99 #endif
101 #ifdef WITH_THREAD
103 /* The threading situation is complicated. Tcl is not thread-safe, except for
104 Tcl 8.1, which will probably remain in alpha status for another 6 months
105 (and the README says that Tk will probably remain thread-unsafe forever).
106 So we need to use a lock around all uses of Tcl. Previously, the Python
107 interpreter lock was used for this. However, this causes problems when
108 other Python threads need to run while Tcl is blocked waiting for events.
110 To solve this problem, a separate lock for Tcl is introduced. Holding it
111 is incompatible with holding Python's interpreter lock. The following four
112 macros manipulate both locks together.
114 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
115 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
116 that could call an event handler, or otherwise affect the state of a Tcl
117 interpreter. These assume that the surrounding code has the Python
118 interpreter lock; inside the brackets, the Python interpreter lock has been
119 released and the lock for Tcl has been acquired.
121 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
122 (For example, when transferring data from the Tcl interpreter result to a
123 Python string object.) This can be done by using different macros to close
124 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
125 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
126 releases the Tcl lock.
128 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
129 handlers when the handler needs to use Python. Such event handlers are
130 entered while the lock for Tcl is held; the event handler presumably needs
131 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
132 the Python interpreter lock, restoring the appropriate thread state, and
133 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
134 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
135 the code between ENTER_PYTHON and LEAVE_PYTHON.
137 These locks expand to several statements and brackets; they should not be
138 used in branches of if statements and the like.
142 static PyThread_type_lock tcl_lock = 0;
143 static PyThreadState *tcl_tstate = NULL;
145 #define ENTER_TCL \
146 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
147 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
149 #define LEAVE_TCL \
150 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
152 #define ENTER_OVERLAP \
153 Py_END_ALLOW_THREADS
155 #define LEAVE_OVERLAP_TCL \
156 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); }
158 #define ENTER_PYTHON \
159 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
160 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
162 #define LEAVE_PYTHON \
163 { PyThreadState *tstate = PyEval_SaveThread(); \
164 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
166 #else
168 #define ENTER_TCL
169 #define LEAVE_TCL
170 #define ENTER_OVERLAP
171 #define LEAVE_OVERLAP_TCL
172 #define ENTER_PYTHON
173 #define LEAVE_PYTHON
175 #endif
177 #ifdef macintosh
180 ** Additional cruft needed by Tcl/Tk on the Mac.
181 ** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
184 /* ckfree() expects a char* */
185 #define FREECAST (char *)
187 #include <Events.h> /* For EventRecord */
189 typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
190 void Tcl_MacSetEventProc (TclMacConvertEventPtr procPtr);
191 int TkMacConvertEvent (EventRecord *eventPtr);
193 staticforward int PyMacConvertEvent (EventRecord *eventPtr);
195 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
196 #pragma import on
197 #endif
199 #include <SIOUX.h>
200 extern int SIOUXIsAppWindow(WindowPtr);
202 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
203 #pragma import reset
204 #endif
205 #endif /* macintosh */
207 #ifndef FREECAST
208 #define FREECAST (char *)
209 #endif
211 /**** Tkapp Object Declaration ****/
213 staticforward PyTypeObject Tkapp_Type;
215 typedef struct {
216 PyObject_HEAD
217 Tcl_Interp *interp;
218 } TkappObject;
220 #define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
221 #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
222 #define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
224 #define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
225 (void *) v, ((PyObject *) v)->ob_refcnt))
229 /**** Error Handling ****/
231 static PyObject *Tkinter_TclError;
232 static int quitMainLoop = 0;
233 static int errorInCmd = 0;
234 static PyObject *excInCmd;
235 static PyObject *valInCmd;
236 static PyObject *trbInCmd;
240 static PyObject *
241 Tkinter_Error(PyObject *v)
243 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
244 return NULL;
249 /**** Utils ****/
251 #ifdef WITH_THREAD
252 #ifndef MS_WINDOWS
254 /* Millisecond sleep() for Unix platforms. */
256 static void
257 Sleep(int milli)
259 /* XXX Too bad if you don't have select(). */
260 struct timeval t;
261 t.tv_sec = milli/1000;
262 t.tv_usec = (milli%1000) * 1000;
263 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
265 #endif /* MS_WINDOWS */
266 #endif /* WITH_THREAD */
269 static char *
270 AsString(PyObject *value, PyObject *tmp)
272 if (PyString_Check(value))
273 return PyString_AsString(value);
274 else {
275 PyObject *v = PyObject_Str(value);
276 PyList_Append(tmp, v);
277 Py_DECREF(v);
278 return PyString_AsString(v);
284 #define ARGSZ 64
286 static char *
287 Merge(PyObject *args)
289 PyObject *tmp = NULL;
290 char *argvStore[ARGSZ];
291 char **argv = NULL;
292 int fvStore[ARGSZ];
293 int *fv = NULL;
294 int argc = 0, i;
295 char *res = NULL;
297 if (!(tmp = PyList_New(0)))
298 return NULL;
300 argv = argvStore;
301 fv = fvStore;
303 if (args == NULL)
304 argc = 0;
306 else if (!PyTuple_Check(args)) {
307 argc = 1;
308 fv[0] = 0;
309 argv[0] = AsString(args, tmp);
311 else {
312 argc = PyTuple_Size(args);
314 if (argc > ARGSZ) {
315 argv = (char **)ckalloc(argc * sizeof(char *));
316 fv = (int *)ckalloc(argc * sizeof(int));
317 if (argv == NULL || fv == NULL) {
318 PyErr_NoMemory();
319 goto finally;
323 for (i = 0; i < argc; i++) {
324 PyObject *v = PyTuple_GetItem(args, i);
325 if (PyTuple_Check(v)) {
326 fv[i] = 1;
327 if (!(argv[i] = Merge(v)))
328 goto finally;
330 else if (v == Py_None) {
331 argc = i;
332 break;
334 else {
335 fv[i] = 0;
336 argv[i] = AsString(v, tmp);
340 res = Tcl_Merge(argc, argv);
342 finally:
343 for (i = 0; i < argc; i++)
344 if (fv[i]) {
345 ckfree(argv[i]);
347 if (argv != argvStore)
348 ckfree(FREECAST argv);
349 if (fv != fvStore)
350 ckfree(FREECAST fv);
352 Py_DECREF(tmp);
353 return res;
358 static PyObject *
359 Split(char *list)
361 int argc;
362 char **argv;
363 PyObject *v;
365 if (list == NULL) {
366 Py_INCREF(Py_None);
367 return Py_None;
370 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
371 /* Not a list.
372 * Could be a quoted string containing funnies, e.g. {"}.
373 * Return the string itself.
375 return PyString_FromString(list);
378 if (argc == 0)
379 v = PyString_FromString("");
380 else if (argc == 1)
381 v = PyString_FromString(argv[0]);
382 else if ((v = PyTuple_New(argc)) != NULL) {
383 int i;
384 PyObject *w;
386 for (i = 0; i < argc; i++) {
387 if ((w = Split(argv[i])) == NULL) {
388 Py_DECREF(v);
389 v = NULL;
390 break;
392 PyTuple_SetItem(v, i, w);
395 Tcl_Free(FREECAST argv);
396 return v;
401 /**** Tkapp Object ****/
403 #ifndef WITH_APPINIT
405 Tcl_AppInit(Tcl_Interp *interp)
407 Tk_Window main;
409 main = Tk_MainWindow(interp);
410 if (Tcl_Init(interp) == TCL_ERROR) {
411 PySys_WriteStderr("Tcl_Init error: %s\n", interp->result);
412 return TCL_ERROR;
414 if (Tk_Init(interp) == TCL_ERROR) {
415 PySys_WriteStderr("Tk_Init error: %s\n", interp->result);
416 return TCL_ERROR;
418 return TCL_OK;
420 #endif /* !WITH_APPINIT */
425 /* Initialize the Tk application; see the `main' function in
426 * `tkMain.c'.
429 static void EnableEventHook(void); /* Forward */
430 static void DisableEventHook(void); /* Forward */
432 static TkappObject *
433 Tkapp_New(char *screenName, char *baseName, char *className, int interactive)
435 TkappObject *v;
436 char *argv0;
438 v = PyObject_New(TkappObject, &Tkapp_Type);
439 if (v == NULL)
440 return NULL;
442 v->interp = Tcl_CreateInterp();
444 #if defined(macintosh)
445 /* This seems to be needed */
446 ClearMenuBar();
447 TkMacInitMenus(v->interp);
448 #endif
449 /* Delete the 'exit' command, which can screw things up */
450 Tcl_DeleteCommand(v->interp, "exit");
452 if (screenName != NULL)
453 Tcl_SetVar2(v->interp, "env", "DISPLAY",
454 screenName, TCL_GLOBAL_ONLY);
456 if (interactive)
457 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
458 else
459 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
461 /* This is used to get the application class for Tk 4.1 and up */
462 argv0 = (char*)ckalloc(strlen(className) + 1);
463 if (!argv0) {
464 PyErr_NoMemory();
465 Py_DECREF(v);
466 return NULL;
469 strcpy(argv0, className);
470 if (isupper((int)(argv0[0])))
471 argv0[0] = tolower(argv0[0]);
472 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
473 ckfree(argv0);
475 if (Tcl_AppInit(v->interp) != TCL_OK)
476 return (TkappObject *)Tkinter_Error((PyObject *)v);
478 EnableEventHook();
480 return v;
485 /** Tcl Eval **/
487 #if TKMAJORMINOR >= 8001
488 #define USING_OBJECTS
489 #endif
491 #ifdef USING_OBJECTS
493 static Tcl_Obj*
494 AsObj(PyObject *value)
496 Tcl_Obj *result;
498 if (PyString_Check(value))
499 return Tcl_NewStringObj(PyString_AS_STRING(value),
500 PyString_GET_SIZE(value));
501 else if (PyInt_Check(value))
502 return Tcl_NewLongObj(PyInt_AS_LONG(value));
503 else if (PyFloat_Check(value))
504 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
505 else if (PyTuple_Check(value)) {
506 Tcl_Obj **argv = (Tcl_Obj**)
507 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
508 int i;
509 if(!argv)
510 return 0;
511 for(i=0;i<PyTuple_Size(value);i++)
512 argv[i] = AsObj(PyTuple_GetItem(value,i));
513 result = Tcl_NewListObj(PyTuple_Size(value), argv);
514 ckfree(FREECAST argv);
515 return result;
517 else if (PyUnicode_Check(value)) {
518 #if TKMAJORMINOR <= 8001
519 /* In Tcl 8.1 we must use UTF-8 */
520 PyObject* utf8 = PyUnicode_AsUTF8String (value);
521 if (!utf8)
522 return 0;
523 result = Tcl_NewStringObj (PyString_AS_STRING (utf8),
524 PyString_GET_SIZE (utf8));
525 Py_DECREF(utf8);
526 return result;
527 #else /* TKMAJORMINOR > 8001 */
528 /* In Tcl 8.2 and later, use Tcl_NewUnicodeObj() */
529 if (sizeof(Py_UNICODE) != sizeof(Tcl_UniChar)) {
530 /* XXX Should really test this at compile time */
531 PyErr_SetString(PyExc_SystemError,
532 "Py_UNICODE and Tcl_UniChar differ in size");
533 return 0;
535 return Tcl_NewUnicodeObj(PyUnicode_AS_UNICODE(value),
536 PyUnicode_GET_SIZE(value));
537 #endif /* TKMAJORMINOR > 8001 */
539 else {
540 PyObject *v = PyObject_Str(value);
541 if (!v)
542 return 0;
543 result = AsObj(v);
544 Py_DECREF(v);
545 return result;
549 static PyObject *
550 Tkapp_Call(PyObject *self, PyObject *args)
552 Tcl_Obj *objStore[ARGSZ];
553 Tcl_Obj **objv = NULL;
554 int objc = 0, i;
555 PyObject *res = NULL;
556 Tcl_Interp *interp = Tkapp_Interp(self);
557 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
558 int flags = TCL_EVAL_DIRECT;
560 objv = objStore;
562 if (args == NULL)
563 objc = 0;
565 else if (!PyTuple_Check(args)) {
566 objc = 1;
567 objv[0] = AsObj(args);
568 if (objv[0] == 0)
569 goto finally;
570 Tcl_IncrRefCount(objv[0]);
572 else {
573 objc = PyTuple_Size(args);
575 if (objc > ARGSZ) {
576 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
577 if (objv == NULL) {
578 PyErr_NoMemory();
579 goto finally;
583 for (i = 0; i < objc; i++) {
584 PyObject *v = PyTuple_GetItem(args, i);
585 if (v == Py_None) {
586 objc = i;
587 break;
589 objv[i] = AsObj(v);
590 if (!objv[i])
591 goto finally;
592 Tcl_IncrRefCount(objv[i]);
596 ENTER_TCL
598 i = Tcl_EvalObjv(interp, objc, objv, flags);
600 ENTER_OVERLAP
601 if (i == TCL_ERROR)
602 Tkinter_Error(self);
603 else {
604 /* We could request the object result here, but doing
605 so would confuse applications that expect a string. */
606 char *s = Tcl_GetStringResult(interp);
607 char *p = s;
608 /* If the result contains any bytes with the top bit set,
609 it's UTF-8 and we should decode it to Unicode */
610 while (*p != '\0') {
611 if (*p & 0x80)
612 break;
613 p++;
615 if (*p == '\0')
616 res = PyString_FromStringAndSize(s, (int)(p-s));
617 else {
618 /* Convert UTF-8 to Unicode string */
619 p = strchr(p, '\0');
620 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
621 if (res == NULL) {
622 PyErr_Clear();
623 res = PyString_FromStringAndSize(s, (int)(p-s));
628 LEAVE_OVERLAP_TCL
630 finally:
631 for (i = 0; i < objc; i++)
632 Tcl_DecrRefCount(objv[i]);
633 if (objv != objStore)
634 ckfree(FREECAST objv);
635 return res;
638 #else /* !USING_OBJECTS */
640 static PyObject *
641 Tkapp_Call(PyObject *self, PyObject *args)
643 /* This is copied from Merge() */
644 PyObject *tmp = NULL;
645 char *argvStore[ARGSZ];
646 char **argv = NULL;
647 int fvStore[ARGSZ];
648 int *fv = NULL;
649 int argc = 0, i;
650 PyObject *res = NULL; /* except this has a different type */
651 Tcl_CmdInfo info; /* and this is added */
652 Tcl_Interp *interp = Tkapp_Interp(self); /* and this too */
654 if (!(tmp = PyList_New(0)))
655 return NULL;
657 argv = argvStore;
658 fv = fvStore;
660 if (args == NULL)
661 argc = 0;
663 else if (!PyTuple_Check(args)) {
664 argc = 1;
665 fv[0] = 0;
666 argv[0] = AsString(args, tmp);
668 else {
669 argc = PyTuple_Size(args);
671 if (argc > ARGSZ) {
672 argv = (char **)ckalloc(argc * sizeof(char *));
673 fv = (int *)ckalloc(argc * sizeof(int));
674 if (argv == NULL || fv == NULL) {
675 PyErr_NoMemory();
676 goto finally;
680 for (i = 0; i < argc; i++) {
681 PyObject *v = PyTuple_GetItem(args, i);
682 if (PyTuple_Check(v)) {
683 fv[i] = 1;
684 if (!(argv[i] = Merge(v)))
685 goto finally;
687 else if (v == Py_None) {
688 argc = i;
689 break;
691 else {
692 fv[i] = 0;
693 argv[i] = AsString(v, tmp);
697 /* End code copied from Merge() */
699 /* All this to avoid a call to Tcl_Merge() and the corresponding call
700 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
701 if (Py_VerboseFlag >= 2) {
702 for (i = 0; i < argc; i++)
703 PySys_WriteStderr("%s ", argv[i]);
705 ENTER_TCL
706 info.proc = NULL;
707 if (argc < 1 ||
708 !Tcl_GetCommandInfo(interp, argv[0], &info) ||
709 info.proc == NULL)
711 char *cmd;
712 cmd = Tcl_Merge(argc, argv);
713 i = Tcl_Eval(interp, cmd);
714 ckfree(cmd);
716 else {
717 Tcl_ResetResult(interp);
718 i = (*info.proc)(info.clientData, interp, argc, argv);
720 ENTER_OVERLAP
721 if (info.proc == NULL && Py_VerboseFlag >= 2)
722 PySys_WriteStderr("... use TclEval ");
723 if (i == TCL_ERROR) {
724 if (Py_VerboseFlag >= 2)
725 PySys_WriteStderr("... error: '%s'\n",
726 interp->result);
727 Tkinter_Error(self);
729 else {
730 if (Py_VerboseFlag >= 2)
731 PySys_WriteStderr("-> '%s'\n", interp->result);
732 res = PyString_FromString(interp->result);
734 LEAVE_OVERLAP_TCL
736 /* Copied from Merge() again */
737 finally:
738 for (i = 0; i < argc; i++)
739 if (fv[i]) {
740 ckfree(argv[i]);
742 if (argv != argvStore)
743 ckfree(FREECAST argv);
744 if (fv != fvStore)
745 ckfree(FREECAST fv);
747 Py_DECREF(tmp);
748 return res;
751 #endif /* !USING_OBJECTS */
753 static PyObject *
754 Tkapp_GlobalCall(PyObject *self, PyObject *args)
756 /* Could do the same here as for Tkapp_Call(), but this is not used
757 much, so I can't be bothered. Unfortunately Tcl doesn't export a
758 way for the user to do what all its Global* variants do (save and
759 reset the scope pointer, call the local version, restore the saved
760 scope pointer). */
762 char *cmd;
763 PyObject *res = NULL;
765 cmd = Merge(args);
766 if (!cmd)
767 PyErr_SetString(Tkinter_TclError, "merge failed");
769 else {
770 int err;
771 ENTER_TCL
772 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
773 ENTER_OVERLAP
774 if (err == TCL_ERROR)
775 res = Tkinter_Error(self);
776 else
777 res = PyString_FromString(Tkapp_Result(self));
778 LEAVE_OVERLAP_TCL
781 if (cmd)
782 ckfree(cmd);
784 return res;
787 static PyObject *
788 Tkapp_Eval(PyObject *self, PyObject *args)
790 char *script;
791 PyObject *res = NULL;
792 int err;
794 if (!PyArg_ParseTuple(args, "s:eval", &script))
795 return NULL;
797 ENTER_TCL
798 err = Tcl_Eval(Tkapp_Interp(self), script);
799 ENTER_OVERLAP
800 if (err == TCL_ERROR)
801 res = Tkinter_Error(self);
802 else
803 res = PyString_FromString(Tkapp_Result(self));
804 LEAVE_OVERLAP_TCL
805 return res;
808 static PyObject *
809 Tkapp_GlobalEval(PyObject *self, PyObject *args)
811 char *script;
812 PyObject *res = NULL;
813 int err;
815 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
816 return NULL;
818 ENTER_TCL
819 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
820 ENTER_OVERLAP
821 if (err == TCL_ERROR)
822 res = Tkinter_Error(self);
823 else
824 res = PyString_FromString(Tkapp_Result(self));
825 LEAVE_OVERLAP_TCL
826 return res;
829 static PyObject *
830 Tkapp_EvalFile(PyObject *self, PyObject *args)
832 char *fileName;
833 PyObject *res = NULL;
834 int err;
836 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
837 return NULL;
839 ENTER_TCL
840 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
841 ENTER_OVERLAP
842 if (err == TCL_ERROR)
843 res = Tkinter_Error(self);
845 else
846 res = PyString_FromString(Tkapp_Result(self));
847 LEAVE_OVERLAP_TCL
848 return res;
851 static PyObject *
852 Tkapp_Record(PyObject *self, PyObject *args)
854 char *script;
855 PyObject *res = NULL;
856 int err;
858 if (!PyArg_ParseTuple(args, "s", &script))
859 return NULL;
861 ENTER_TCL
862 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
863 ENTER_OVERLAP
864 if (err == TCL_ERROR)
865 res = Tkinter_Error(self);
866 else
867 res = PyString_FromString(Tkapp_Result(self));
868 LEAVE_OVERLAP_TCL
869 return res;
872 static PyObject *
873 Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
875 char *msg;
877 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
878 return NULL;
879 ENTER_TCL
880 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
881 LEAVE_TCL
883 Py_INCREF(Py_None);
884 return Py_None;
889 /** Tcl Variable **/
891 static PyObject *
892 SetVar(PyObject *self, PyObject *args, int flags)
894 char *name1, *name2, *ok, *s;
895 PyObject *newValue;
896 PyObject *tmp;
898 tmp = PyList_New(0);
899 if (!tmp)
900 return NULL;
902 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
903 /* XXX Merge? */
904 s = AsString(newValue, tmp);
905 ENTER_TCL
906 ok = Tcl_SetVar(Tkapp_Interp(self), name1, s, flags);
907 LEAVE_TCL
909 else {
910 PyErr_Clear();
911 if (PyArg_ParseTuple(args, "ssO:setvar", &name1, &name2, &newValue)) {
912 s = AsString (newValue, tmp);
913 ENTER_TCL
914 ok = Tcl_SetVar2(Tkapp_Interp(self), name1, name2,
915 s, flags);
916 LEAVE_TCL
918 else {
919 Py_DECREF(tmp);
920 return NULL;
923 Py_DECREF(tmp);
925 if (!ok)
926 return Tkinter_Error(self);
928 Py_INCREF(Py_None);
929 return Py_None;
932 static PyObject *
933 Tkapp_SetVar(PyObject *self, PyObject *args)
935 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
938 static PyObject *
939 Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
941 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
946 static PyObject *
947 GetVar(PyObject *self, PyObject *args, int flags)
949 char *name1, *name2=NULL, *s;
950 PyObject *res = NULL;
952 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
953 return NULL;
954 ENTER_TCL
955 if (name2 == NULL)
956 s = Tcl_GetVar(Tkapp_Interp(self), name1, flags);
958 else
959 s = Tcl_GetVar2(Tkapp_Interp(self), name1, name2, flags);
960 ENTER_OVERLAP
962 if (s == NULL)
963 res = Tkinter_Error(self);
964 else
965 res = PyString_FromString(s);
966 LEAVE_OVERLAP_TCL
967 return res;
970 static PyObject *
971 Tkapp_GetVar(PyObject *self, PyObject *args)
973 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
976 static PyObject *
977 Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
979 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
984 static PyObject *
985 UnsetVar(PyObject *self, PyObject *args, int flags)
987 char *name1, *name2=NULL;
988 PyObject *res = NULL;
989 int code;
991 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
992 return NULL;
993 ENTER_TCL
994 if (name2 == NULL)
995 code = Tcl_UnsetVar(Tkapp_Interp(self), name1, flags);
997 else
998 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
999 ENTER_OVERLAP
1001 if (code == TCL_ERROR)
1002 res = Tkinter_Error(self);
1003 else {
1004 Py_INCREF(Py_None);
1005 res = Py_None;
1007 LEAVE_OVERLAP_TCL
1008 return res;
1011 static PyObject *
1012 Tkapp_UnsetVar(PyObject *self, PyObject *args)
1014 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
1017 static PyObject *
1018 Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1020 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1025 /** Tcl to Python **/
1027 static PyObject *
1028 Tkapp_GetInt(PyObject *self, PyObject *args)
1030 char *s;
1031 int v;
1033 if (!PyArg_ParseTuple(args, "s:getint", &s))
1034 return NULL;
1035 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1036 return Tkinter_Error(self);
1037 return Py_BuildValue("i", v);
1040 static PyObject *
1041 Tkapp_GetDouble(PyObject *self, PyObject *args)
1043 char *s;
1044 double v;
1046 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1047 return NULL;
1048 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1049 return Tkinter_Error(self);
1050 return Py_BuildValue("d", v);
1053 static PyObject *
1054 Tkapp_GetBoolean(PyObject *self, PyObject *args)
1056 char *s;
1057 int v;
1059 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1060 return NULL;
1061 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1062 return Tkinter_Error(self);
1063 return Py_BuildValue("i", v);
1066 static PyObject *
1067 Tkapp_ExprString(PyObject *self, PyObject *args)
1069 char *s;
1070 PyObject *res = NULL;
1071 int retval;
1073 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1074 return NULL;
1075 ENTER_TCL
1076 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1077 ENTER_OVERLAP
1078 if (retval == TCL_ERROR)
1079 res = Tkinter_Error(self);
1080 else
1081 res = Py_BuildValue("s", Tkapp_Result(self));
1082 LEAVE_OVERLAP_TCL
1083 return res;
1086 static PyObject *
1087 Tkapp_ExprLong(PyObject *self, PyObject *args)
1089 char *s;
1090 PyObject *res = NULL;
1091 int retval;
1092 long v;
1094 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1095 return NULL;
1096 ENTER_TCL
1097 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1098 ENTER_OVERLAP
1099 if (retval == TCL_ERROR)
1100 res = Tkinter_Error(self);
1101 else
1102 res = Py_BuildValue("l", v);
1103 LEAVE_OVERLAP_TCL
1104 return res;
1107 static PyObject *
1108 Tkapp_ExprDouble(PyObject *self, PyObject *args)
1110 char *s;
1111 PyObject *res = NULL;
1112 double v;
1113 int retval;
1115 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1116 return NULL;
1117 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1118 ENTER_TCL
1119 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1120 ENTER_OVERLAP
1121 PyFPE_END_PROTECT(retval)
1122 if (retval == TCL_ERROR)
1123 res = Tkinter_Error(self);
1124 else
1125 res = Py_BuildValue("d", v);
1126 LEAVE_OVERLAP_TCL
1127 return res;
1130 static PyObject *
1131 Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1133 char *s;
1134 PyObject *res = NULL;
1135 int retval;
1136 int v;
1138 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1139 return NULL;
1140 ENTER_TCL
1141 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1142 ENTER_OVERLAP
1143 if (retval == TCL_ERROR)
1144 res = Tkinter_Error(self);
1145 else
1146 res = Py_BuildValue("i", v);
1147 LEAVE_OVERLAP_TCL
1148 return res;
1153 static PyObject *
1154 Tkapp_SplitList(PyObject *self, PyObject *args)
1156 char *list;
1157 int argc;
1158 char **argv;
1159 PyObject *v;
1160 int i;
1162 if (!PyArg_ParseTuple(args, "s:splitlist", &list))
1163 return NULL;
1165 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1166 return Tkinter_Error(self);
1168 if (!(v = PyTuple_New(argc)))
1169 return NULL;
1171 for (i = 0; i < argc; i++) {
1172 PyObject *s = PyString_FromString(argv[i]);
1173 if (!s || PyTuple_SetItem(v, i, s)) {
1174 Py_DECREF(v);
1175 v = NULL;
1176 goto finally;
1180 finally:
1181 ckfree(FREECAST argv);
1182 return v;
1185 static PyObject *
1186 Tkapp_Split(PyObject *self, PyObject *args)
1188 char *list;
1190 if (!PyArg_ParseTuple(args, "s:split", &list))
1191 return NULL;
1192 return Split(list);
1195 static PyObject *
1196 Tkapp_Merge(PyObject *self, PyObject *args)
1198 char *s = Merge(args);
1199 PyObject *res = NULL;
1201 if (s) {
1202 res = PyString_FromString(s);
1203 ckfree(s);
1205 else
1206 PyErr_SetString(Tkinter_TclError, "merge failed");
1208 return res;
1213 /** Tcl Command **/
1215 /* Client data struct */
1216 typedef struct {
1217 PyObject *self;
1218 PyObject *func;
1219 } PythonCmd_ClientData;
1221 static int
1222 PythonCmd_Error(Tcl_Interp *interp)
1224 errorInCmd = 1;
1225 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1226 LEAVE_PYTHON
1227 return TCL_ERROR;
1230 /* This is the Tcl command that acts as a wrapper for Python
1231 * function or method.
1233 static int
1234 PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1236 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1237 PyObject *self, *func, *arg, *res, *tmp;
1238 int i;
1240 ENTER_PYTHON
1242 /* TBD: no error checking here since we know, via the
1243 * Tkapp_CreateCommand() that the client data is a two-tuple
1245 self = data->self;
1246 func = data->func;
1248 /* Create argument list (argv1, ..., argvN) */
1249 if (!(arg = PyTuple_New(argc - 1)))
1250 return PythonCmd_Error(interp);
1252 for (i = 0; i < (argc - 1); i++) {
1253 PyObject *s = PyString_FromString(argv[i + 1]);
1254 if (!s || PyTuple_SetItem(arg, i, s)) {
1255 Py_DECREF(arg);
1256 return PythonCmd_Error(interp);
1259 res = PyEval_CallObject(func, arg);
1260 Py_DECREF(arg);
1262 if (res == NULL)
1263 return PythonCmd_Error(interp);
1265 if (!(tmp = PyList_New(0))) {
1266 Py_DECREF(res);
1267 return PythonCmd_Error(interp);
1270 Tcl_SetResult(Tkapp_Interp(self), AsString(res, tmp), TCL_VOLATILE);
1271 Py_DECREF(res);
1272 Py_DECREF(tmp);
1274 LEAVE_PYTHON
1276 return TCL_OK;
1279 static void
1280 PythonCmdDelete(ClientData clientData)
1282 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1284 ENTER_PYTHON
1285 Py_XDECREF(data->self);
1286 Py_XDECREF(data->func);
1287 PyMem_DEL(data);
1288 LEAVE_PYTHON
1293 static PyObject *
1294 Tkapp_CreateCommand(PyObject *self, PyObject *args)
1296 PythonCmd_ClientData *data;
1297 char *cmdName;
1298 PyObject *func;
1299 Tcl_Command err;
1301 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
1302 return NULL;
1303 if (!PyCallable_Check(func)) {
1304 PyErr_SetString(PyExc_TypeError, "command not callable");
1305 return NULL;
1308 data = PyMem_NEW(PythonCmd_ClientData, 1);
1309 if (!data)
1310 return NULL;
1311 Py_XINCREF(self);
1312 Py_XINCREF(func);
1313 data->self = self;
1314 data->func = func;
1316 ENTER_TCL
1317 err = Tcl_CreateCommand(Tkapp_Interp(self), cmdName, PythonCmd,
1318 (ClientData)data, PythonCmdDelete);
1319 LEAVE_TCL
1320 if (err == NULL) {
1321 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
1322 PyMem_DEL(data);
1323 return NULL;
1326 Py_INCREF(Py_None);
1327 return Py_None;
1332 static PyObject *
1333 Tkapp_DeleteCommand(PyObject *self, PyObject *args)
1335 char *cmdName;
1336 int err;
1338 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
1339 return NULL;
1340 ENTER_TCL
1341 err = Tcl_DeleteCommand(Tkapp_Interp(self), cmdName);
1342 LEAVE_TCL
1343 if (err == -1) {
1344 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
1345 return NULL;
1347 Py_INCREF(Py_None);
1348 return Py_None;
1353 #ifdef HAVE_CREATEFILEHANDLER
1354 /** File Handler **/
1356 typedef struct _fhcdata {
1357 PyObject *func;
1358 PyObject *file;
1359 int id;
1360 struct _fhcdata *next;
1361 } FileHandler_ClientData;
1363 static FileHandler_ClientData *HeadFHCD;
1365 static FileHandler_ClientData *
1366 NewFHCD(PyObject *func, PyObject *file, int id)
1368 FileHandler_ClientData *p;
1369 p = PyMem_NEW(FileHandler_ClientData, 1);
1370 if (p != NULL) {
1371 Py_XINCREF(func);
1372 Py_XINCREF(file);
1373 p->func = func;
1374 p->file = file;
1375 p->id = id;
1376 p->next = HeadFHCD;
1377 HeadFHCD = p;
1379 return p;
1382 static void
1383 DeleteFHCD(int id)
1385 FileHandler_ClientData *p, **pp;
1387 pp = &HeadFHCD;
1388 while ((p = *pp) != NULL) {
1389 if (p->id == id) {
1390 *pp = p->next;
1391 Py_XDECREF(p->func);
1392 Py_XDECREF(p->file);
1393 PyMem_DEL(p);
1395 else
1396 pp = &p->next;
1400 static void
1401 FileHandler(ClientData clientData, int mask)
1403 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
1404 PyObject *func, *file, *arg, *res;
1406 ENTER_PYTHON
1407 func = data->func;
1408 file = data->file;
1410 arg = Py_BuildValue("(Oi)", file, (long) mask);
1411 res = PyEval_CallObject(func, arg);
1412 Py_DECREF(arg);
1414 if (res == NULL) {
1415 errorInCmd = 1;
1416 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1418 Py_XDECREF(res);
1419 LEAVE_PYTHON
1422 static PyObject *
1423 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
1424 /* args is (file, mask, func) */
1426 FileHandler_ClientData *data;
1427 PyObject *file, *func;
1428 int mask, tfile;
1430 if (!PyArg_ParseTuple(args, "OiO:createfilehandler", &file, &mask, &func))
1431 return NULL;
1432 tfile = PyObject_AsFileDescriptor(file);
1433 if (tfile < 0)
1434 return NULL;
1435 if (!PyCallable_Check(func)) {
1436 PyErr_SetString(PyExc_TypeError, "bad argument list");
1437 return NULL;
1440 data = NewFHCD(func, file, tfile);
1441 if (data == NULL)
1442 return NULL;
1444 /* Ought to check for null Tcl_File object... */
1445 ENTER_TCL
1446 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
1447 LEAVE_TCL
1448 Py_INCREF(Py_None);
1449 return Py_None;
1452 static PyObject *
1453 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
1455 PyObject *file;
1456 int tfile;
1458 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
1459 return NULL;
1460 tfile = PyObject_AsFileDescriptor(file);
1461 if (tfile < 0)
1462 return NULL;
1464 DeleteFHCD(tfile);
1466 /* Ought to check for null Tcl_File object... */
1467 ENTER_TCL
1468 Tcl_DeleteFileHandler(tfile);
1469 LEAVE_TCL
1470 Py_INCREF(Py_None);
1471 return Py_None;
1473 #endif /* HAVE_CREATEFILEHANDLER */
1476 /**** Tktt Object (timer token) ****/
1478 staticforward PyTypeObject Tktt_Type;
1480 typedef struct {
1481 PyObject_HEAD
1482 Tcl_TimerToken token;
1483 PyObject *func;
1484 } TkttObject;
1486 static PyObject *
1487 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
1489 TkttObject *v = (TkttObject *)self;
1490 PyObject *func = v->func;
1492 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
1493 return NULL;
1494 if (v->token != NULL) {
1495 Tcl_DeleteTimerHandler(v->token);
1496 v->token = NULL;
1498 if (func != NULL) {
1499 v->func = NULL;
1500 Py_DECREF(func);
1501 Py_DECREF(v); /* See Tktt_New() */
1503 Py_INCREF(Py_None);
1504 return Py_None;
1507 static PyMethodDef Tktt_methods[] =
1509 {"deletetimerhandler", Tktt_DeleteTimerHandler, 1},
1510 {NULL, NULL}
1513 static TkttObject *
1514 Tktt_New(PyObject *func)
1516 TkttObject *v;
1518 v = PyObject_New(TkttObject, &Tktt_Type);
1519 if (v == NULL)
1520 return NULL;
1522 Py_INCREF(func);
1523 v->token = NULL;
1524 v->func = func;
1526 /* Extra reference, deleted when called or when handler is deleted */
1527 Py_INCREF(v);
1528 return v;
1531 static void
1532 Tktt_Dealloc(PyObject *self)
1534 TkttObject *v = (TkttObject *)self;
1535 PyObject *func = v->func;
1537 Py_XDECREF(func);
1539 PyObject_Del(self);
1542 static PyObject *
1543 Tktt_Repr(PyObject *self)
1545 TkttObject *v = (TkttObject *)self;
1546 char buf[100];
1548 sprintf(buf, "<tktimertoken at %p%s>", v,
1549 v->func == NULL ? ", handler deleted" : "");
1550 return PyString_FromString(buf);
1553 static PyObject *
1554 Tktt_GetAttr(PyObject *self, char *name)
1556 return Py_FindMethod(Tktt_methods, self, name);
1559 static PyTypeObject Tktt_Type =
1561 PyObject_HEAD_INIT(NULL)
1562 0, /*ob_size */
1563 "tktimertoken", /*tp_name */
1564 sizeof(TkttObject), /*tp_basicsize */
1565 0, /*tp_itemsize */
1566 Tktt_Dealloc, /*tp_dealloc */
1567 0, /*tp_print */
1568 Tktt_GetAttr, /*tp_getattr */
1569 0, /*tp_setattr */
1570 0, /*tp_compare */
1571 Tktt_Repr, /*tp_repr */
1572 0, /*tp_as_number */
1573 0, /*tp_as_sequence */
1574 0, /*tp_as_mapping */
1575 0, /*tp_hash */
1580 /** Timer Handler **/
1582 static void
1583 TimerHandler(ClientData clientData)
1585 TkttObject *v = (TkttObject *)clientData;
1586 PyObject *func = v->func;
1587 PyObject *res;
1589 if (func == NULL)
1590 return;
1592 v->func = NULL;
1594 ENTER_PYTHON
1596 res = PyEval_CallObject(func, NULL);
1597 Py_DECREF(func);
1598 Py_DECREF(v); /* See Tktt_New() */
1600 if (res == NULL) {
1601 errorInCmd = 1;
1602 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1604 else
1605 Py_DECREF(res);
1607 LEAVE_PYTHON
1610 static PyObject *
1611 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
1613 int milliseconds;
1614 PyObject *func;
1615 TkttObject *v;
1617 if (!PyArg_ParseTuple(args, "iO:createtimerhandler", &milliseconds, &func))
1618 return NULL;
1619 if (!PyCallable_Check(func)) {
1620 PyErr_SetString(PyExc_TypeError, "bad argument list");
1621 return NULL;
1623 v = Tktt_New(func);
1624 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
1625 (ClientData)v);
1627 return (PyObject *) v;
1631 /** Event Loop **/
1633 static PyObject *
1634 Tkapp_MainLoop(PyObject *self, PyObject *args)
1636 int threshold = 0;
1637 #ifdef WITH_THREAD
1638 PyThreadState *tstate = PyThreadState_Get();
1639 #endif
1641 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
1642 return NULL;
1644 quitMainLoop = 0;
1645 while (Tk_GetNumMainWindows() > threshold &&
1646 !quitMainLoop &&
1647 !errorInCmd)
1649 int result;
1651 #ifdef WITH_THREAD
1652 Py_BEGIN_ALLOW_THREADS
1653 PyThread_acquire_lock(tcl_lock, 1);
1654 tcl_tstate = tstate;
1655 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
1656 tcl_tstate = NULL;
1657 PyThread_release_lock(tcl_lock);
1658 if (result == 0)
1659 Sleep(20);
1660 Py_END_ALLOW_THREADS
1661 #else
1662 result = Tcl_DoOneEvent(0);
1663 #endif
1665 if (PyErr_CheckSignals() != 0)
1666 return NULL;
1667 if (result < 0)
1668 break;
1670 quitMainLoop = 0;
1672 if (errorInCmd) {
1673 errorInCmd = 0;
1674 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1675 excInCmd = valInCmd = trbInCmd = NULL;
1676 return NULL;
1678 Py_INCREF(Py_None);
1679 return Py_None;
1682 static PyObject *
1683 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
1685 int flags = 0;
1686 int rv;
1688 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
1689 return NULL;
1691 ENTER_TCL
1692 rv = Tcl_DoOneEvent(flags);
1693 LEAVE_TCL
1694 return Py_BuildValue("i", rv);
1697 static PyObject *
1698 Tkapp_Quit(PyObject *self, PyObject *args)
1701 if (!PyArg_ParseTuple(args, ":quit"))
1702 return NULL;
1704 quitMainLoop = 1;
1705 Py_INCREF(Py_None);
1706 return Py_None;
1709 static PyObject *
1710 Tkapp_InterpAddr(PyObject *self, PyObject *args)
1713 if (!PyArg_ParseTuple(args, ":interpaddr"))
1714 return NULL;
1716 return PyInt_FromLong((long)Tkapp_Interp(self));
1721 /**** Tkapp Method List ****/
1723 static PyMethodDef Tkapp_methods[] =
1725 {"call", Tkapp_Call, 0},
1726 {"globalcall", Tkapp_GlobalCall, 0},
1727 {"eval", Tkapp_Eval, 1},
1728 {"globaleval", Tkapp_GlobalEval, 1},
1729 {"evalfile", Tkapp_EvalFile, 1},
1730 {"record", Tkapp_Record, 1},
1731 {"adderrorinfo", Tkapp_AddErrorInfo, 1},
1732 {"setvar", Tkapp_SetVar, 1},
1733 {"globalsetvar", Tkapp_GlobalSetVar, 1},
1734 {"getvar", Tkapp_GetVar, 1},
1735 {"globalgetvar", Tkapp_GlobalGetVar, 1},
1736 {"unsetvar", Tkapp_UnsetVar, 1},
1737 {"globalunsetvar", Tkapp_GlobalUnsetVar, 1},
1738 {"getint", Tkapp_GetInt, 1},
1739 {"getdouble", Tkapp_GetDouble, 1},
1740 {"getboolean", Tkapp_GetBoolean, 1},
1741 {"exprstring", Tkapp_ExprString, 1},
1742 {"exprlong", Tkapp_ExprLong, 1},
1743 {"exprdouble", Tkapp_ExprDouble, 1},
1744 {"exprboolean", Tkapp_ExprBoolean, 1},
1745 {"splitlist", Tkapp_SplitList, 1},
1746 {"split", Tkapp_Split, 1},
1747 {"merge", Tkapp_Merge, 0},
1748 {"createcommand", Tkapp_CreateCommand, 1},
1749 {"deletecommand", Tkapp_DeleteCommand, 1},
1750 #ifdef HAVE_CREATEFILEHANDLER
1751 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1752 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
1753 #endif
1754 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
1755 {"mainloop", Tkapp_MainLoop, 1},
1756 {"dooneevent", Tkapp_DoOneEvent, 1},
1757 {"quit", Tkapp_Quit, 1},
1758 {"interpaddr", Tkapp_InterpAddr, 1},
1759 {NULL, NULL}
1764 /**** Tkapp Type Methods ****/
1766 static void
1767 Tkapp_Dealloc(PyObject *self)
1769 ENTER_TCL
1770 Tcl_DeleteInterp(Tkapp_Interp(self));
1771 LEAVE_TCL
1772 PyObject_Del(self);
1773 DisableEventHook();
1776 static PyObject *
1777 Tkapp_GetAttr(PyObject *self, char *name)
1779 return Py_FindMethod(Tkapp_methods, self, name);
1782 static PyTypeObject Tkapp_Type =
1784 PyObject_HEAD_INIT(NULL)
1785 0, /*ob_size */
1786 "tkapp", /*tp_name */
1787 sizeof(TkappObject), /*tp_basicsize */
1788 0, /*tp_itemsize */
1789 Tkapp_Dealloc, /*tp_dealloc */
1790 0, /*tp_print */
1791 Tkapp_GetAttr, /*tp_getattr */
1792 0, /*tp_setattr */
1793 0, /*tp_compare */
1794 0, /*tp_repr */
1795 0, /*tp_as_number */
1796 0, /*tp_as_sequence */
1797 0, /*tp_as_mapping */
1798 0, /*tp_hash */
1803 /**** Tkinter Module ****/
1805 typedef struct {
1806 PyObject* tuple;
1807 int size; /* current size */
1808 int maxsize; /* allocated size */
1809 } FlattenContext;
1811 static int
1812 _bump(FlattenContext* context, int size)
1814 /* expand tuple to hold (at least) size new items. return true if
1815 successful, false if an exception was raised*/
1817 int maxsize = context->maxsize * 2;
1819 if (maxsize < context->size + size)
1820 maxsize = context->size + size;
1822 context->maxsize = maxsize;
1824 return _PyTuple_Resize(&context->tuple, maxsize, 0) >= 0;
1827 static int
1828 _flatten1(FlattenContext* context, PyObject* item, int depth)
1830 /* add tuple or list to argument tuple (recursively) */
1832 int i, size;
1834 if (depth > 1000) {
1835 PyErr_SetString(PyExc_ValueError,"nesting too deep in _flatten");
1836 return 0;
1837 } else if (PyList_Check(item)) {
1838 size = PyList_GET_SIZE(item);
1839 /* preallocate (assume no nesting) */
1840 if (context->size + size > context->maxsize && !_bump(context, size))
1841 return 0;
1842 /* copy items to output tuple */
1843 for (i = 0; i < size; i++) {
1844 PyObject *o = PyList_GET_ITEM(item, i);
1845 if (PyList_Check(o) || PyTuple_Check(o)) {
1846 if (!_flatten1(context, o, depth + 1))
1847 return 0;
1848 } else if (o != Py_None) {
1849 if (context->size + 1 > context->maxsize && !_bump(context, 1))
1850 return 0;
1851 Py_INCREF(o);
1852 PyTuple_SET_ITEM(context->tuple, context->size++, o);
1855 } else if (PyTuple_Check(item)) {
1856 /* same, for tuples */
1857 size = PyTuple_GET_SIZE(item);
1858 if (context->size + size > context->maxsize && !_bump(context, size))
1859 return 0;
1860 for (i = 0; i < size; i++) {
1861 PyObject *o = PyTuple_GET_ITEM(item, i);
1862 if (PyList_Check(o) || PyTuple_Check(o)) {
1863 if (!_flatten1(context, o, depth + 1))
1864 return 0;
1865 } else if (o != Py_None) {
1866 if (context->size + 1 > context->maxsize && !_bump(context, 1))
1867 return 0;
1868 Py_INCREF(o);
1869 PyTuple_SET_ITEM(context->tuple, context->size++, o);
1872 } else {
1873 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
1874 return 0;
1876 return 1;
1879 static PyObject *
1880 Tkinter_Flatten(PyObject* self, PyObject* args)
1882 FlattenContext context;
1883 PyObject* item;
1885 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
1886 return NULL;
1888 context.maxsize = PySequence_Size(item);
1889 if (context.maxsize <= 0)
1890 return PyTuple_New(0);
1892 context.tuple = PyTuple_New(context.maxsize);
1893 if (!context.tuple)
1894 return NULL;
1896 context.size = 0;
1898 if (!_flatten1(&context, item,0))
1899 return NULL;
1901 if (_PyTuple_Resize(&context.tuple, context.size, 0))
1902 return NULL;
1904 return context.tuple;
1907 static PyObject *
1908 Tkinter_Create(PyObject *self, PyObject *args)
1910 char *screenName = NULL;
1911 char *baseName = NULL;
1912 char *className = NULL;
1913 int interactive = 0;
1915 baseName = strrchr(Py_GetProgramName(), '/');
1916 if (baseName != NULL)
1917 baseName++;
1918 else
1919 baseName = Py_GetProgramName();
1920 className = "Tk";
1922 if (!PyArg_ParseTuple(args, "|zssi:create",
1923 &screenName, &baseName, &className,
1924 &interactive))
1925 return NULL;
1927 return (PyObject *) Tkapp_New(screenName, baseName, className,
1928 interactive);
1931 static PyMethodDef moduleMethods[] =
1933 {"_flatten", Tkinter_Flatten, 1},
1934 {"create", Tkinter_Create, 1},
1935 #ifdef HAVE_CREATEFILEHANDLER
1936 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1937 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
1938 #endif
1939 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
1940 {"mainloop", Tkapp_MainLoop, 1},
1941 {"dooneevent", Tkapp_DoOneEvent, 1},
1942 {"quit", Tkapp_Quit, 1},
1943 {NULL, NULL}
1946 #ifdef WAIT_FOR_STDIN
1948 static int stdin_ready = 0;
1950 #ifndef MS_WINDOWS
1951 static void
1952 MyFileProc(void *clientData, int mask)
1954 stdin_ready = 1;
1956 #endif
1958 static PyThreadState *event_tstate = NULL;
1960 static int
1961 EventHook(void)
1963 #ifndef MS_WINDOWS
1964 int tfile;
1965 #endif
1966 #ifdef WITH_THREAD
1967 PyEval_RestoreThread(event_tstate);
1968 #endif
1969 stdin_ready = 0;
1970 errorInCmd = 0;
1971 #ifndef MS_WINDOWS
1972 tfile = fileno(stdin);
1973 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
1974 #endif
1975 while (!errorInCmd && !stdin_ready) {
1976 int result;
1977 #ifdef MS_WINDOWS
1978 if (_kbhit()) {
1979 stdin_ready = 1;
1980 break;
1982 #endif
1983 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
1984 Py_BEGIN_ALLOW_THREADS
1985 PyThread_acquire_lock(tcl_lock, 1);
1986 tcl_tstate = event_tstate;
1988 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
1990 tcl_tstate = NULL;
1991 PyThread_release_lock(tcl_lock);
1992 if (result == 0)
1993 Sleep(20);
1994 Py_END_ALLOW_THREADS
1995 #else
1996 result = Tcl_DoOneEvent(0);
1997 #endif
1999 if (result < 0)
2000 break;
2002 #ifndef MS_WINDOWS
2003 Tcl_DeleteFileHandler(tfile);
2004 #endif
2005 if (errorInCmd) {
2006 errorInCmd = 0;
2007 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2008 excInCmd = valInCmd = trbInCmd = NULL;
2009 PyErr_Print();
2011 #ifdef WITH_THREAD
2012 PyEval_SaveThread();
2013 #endif
2014 return 0;
2017 #endif
2019 static void
2020 EnableEventHook(void)
2022 #ifdef WAIT_FOR_STDIN
2023 if (PyOS_InputHook == NULL) {
2024 #ifdef WITH_THREAD
2025 event_tstate = PyThreadState_Get();
2026 #endif
2027 PyOS_InputHook = EventHook;
2029 #endif
2032 static void
2033 DisableEventHook(void)
2035 #ifdef WAIT_FOR_STDIN
2036 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2037 PyOS_InputHook = NULL;
2039 #endif
2043 /* all errors will be checked in one fell swoop in init_tkinter() */
2044 static void
2045 ins_long(PyObject *d, char *name, long val)
2047 PyObject *v = PyInt_FromLong(val);
2048 if (v) {
2049 PyDict_SetItemString(d, name, v);
2050 Py_DECREF(v);
2053 static void
2054 ins_string(PyObject *d, char *name, char *val)
2056 PyObject *v = PyString_FromString(val);
2057 if (v) {
2058 PyDict_SetItemString(d, name, v);
2059 Py_DECREF(v);
2064 DL_EXPORT(void)
2065 init_tkinter(void)
2067 PyObject *m, *d;
2069 Tkapp_Type.ob_type = &PyType_Type;
2071 #ifdef WITH_THREAD
2072 tcl_lock = PyThread_allocate_lock();
2073 #endif
2075 m = Py_InitModule("_tkinter", moduleMethods);
2077 d = PyModule_GetDict(m);
2078 Tkinter_TclError = Py_BuildValue("s", "TclError");
2079 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
2081 ins_long(d, "READABLE", TCL_READABLE);
2082 ins_long(d, "WRITABLE", TCL_WRITABLE);
2083 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2084 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2085 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2086 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2087 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2088 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2089 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
2090 ins_string(d, "TK_VERSION", TK_VERSION);
2091 ins_string(d, "TCL_VERSION", TCL_VERSION);
2093 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
2095 Tktt_Type.ob_type = &PyType_Type;
2096 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2098 /* This helps the dynamic loader; in Unicode aware Tcl versions
2099 it also helps Tcl find its encodings. */
2100 Tcl_FindExecutable(Py_GetProgramName());
2102 if (PyErr_Occurred())
2103 return;
2105 #if 0
2106 /* This was not a good idea; through <Destroy> bindings,
2107 Tcl_Finalize() may invoke Python code but at that point the
2108 interpreter and thread state have already been destroyed! */
2109 Py_AtExit(Tcl_Finalize);
2110 #endif
2112 #ifdef macintosh
2114 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2115 ** Most of the initializations in that routine (toolbox init calls and
2116 ** such) have already been done for us, so we only need these.
2118 tcl_macQdPtr = &qd;
2120 Tcl_MacSetEventProc(PyMacConvertEvent);
2121 #if GENERATINGCFM
2122 mac_addlibresources();
2123 #endif /* GENERATINGCFM */
2124 #endif /* macintosh */
2129 #ifdef macintosh
2132 ** Anyone who embeds Tcl/Tk on the Mac must define panic().
2135 void
2136 panic(char * format, ...)
2138 va_list varg;
2140 va_start(varg, format);
2142 vfprintf(stderr, format, varg);
2143 (void) fflush(stderr);
2145 va_end(varg);
2147 Py_FatalError("Tcl/Tk panic");
2151 ** Pass events to SIOUX before passing them to Tk.
2154 static int
2155 PyMacConvertEvent(EventRecord *eventPtr)
2157 WindowPtr frontwin;
2159 ** Sioux eats too many events, so we don't pass it everything. We
2160 ** always pass update events to Sioux, and we only pass other events if
2161 ** the Sioux window is frontmost. This means that Tk menus don't work
2162 ** in that case, but at least we can scroll the sioux window.
2163 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2164 ** part of the external interface of Sioux...
2166 frontwin = FrontWindow();
2167 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2168 if (SIOUXHandleOneEvent(eventPtr))
2169 return 0; /* Nothing happened to the Tcl event queue */
2171 return TkMacConvertEvent(eventPtr);
2174 #if GENERATINGCFM
2177 ** Additional Mac specific code for dealing with shared libraries.
2180 #include <Resources.h>
2181 #include <CodeFragments.h>
2183 static int loaded_from_shlib = 0;
2184 static FSSpec library_fss;
2187 ** If this module is dynamically loaded the following routine should
2188 ** be the init routine. It takes care of adding the shared library to
2189 ** the resource-file chain, so that the tk routines can find their
2190 ** resources.
2192 OSErr pascal
2193 init_tkinter_shlib(CFragInitBlockPtr data)
2195 __initialize();
2196 if ( data == nil ) return noErr;
2197 if ( data->fragLocator.where == kDataForkCFragLocator ) {
2198 library_fss = *data->fragLocator.u.onDisk.fileSpec;
2199 loaded_from_shlib = 1;
2200 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
2201 library_fss = *data->fragLocator.u.inSegs.fileSpec;
2202 loaded_from_shlib = 1;
2204 return noErr;
2208 ** Insert the library resources into the search path. Put them after
2209 ** the resources from the application. Again, we ignore errors.
2211 static
2212 mac_addlibresources(void)
2214 if ( !loaded_from_shlib )
2215 return;
2216 (void)FSpOpenResFile(&library_fss, fsRdPerm);
2219 #endif /* GENERATINGCFM */
2220 #endif /* macintosh */