Files for 2.1b1 distribution.
[python/dscho.git] / Modules / _tkinter.c
blob86b5c220e319dc796bd1590b828b33bac2faa6bf
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.0 and later are supported. Older versions are not
13 supported. (Use Python 1.5.2 if you cannot upgrade your Tcl/Tk
14 libraries.)
17 /* XXX Further speed-up ideas, involving Tcl 8.0 features:
19 - In Tcl_Call(), create Tcl objects from the arguments, possibly using
20 intelligent mappings between Python objects and Tcl objects (e.g. ints,
21 floats and Tcl window pointers could be handled specially).
23 - Register a new Tcl type, "Python callable", which can be called more
24 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
29 #include "Python.h"
30 #include <ctype.h>
32 #ifdef WITH_THREAD
33 #include "pythread.h"
34 #endif
36 #ifdef MS_WINDOWS
37 #include <windows.h>
38 #endif
40 #ifdef macintosh
41 #define MAC_TCL
42 #endif
44 #include <tcl.h>
45 #include <tk.h>
47 #define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
49 #if TKMAJORMINOR < 8000
50 #error "Tk older than 8.0 not supported"
51 #endif
53 #if defined(macintosh)
54 /* Sigh, we have to include this to get at the tcl qd pointer */
55 #include <tkMac.h>
56 /* And this one we need to clear the menu bar */
57 #include <Menus.h>
58 #endif
60 #if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
61 #define HAVE_CREATEFILEHANDLER
62 #endif
64 #ifdef HAVE_CREATEFILEHANDLER
66 /* Tcl_CreateFileHandler() changed several times; these macros deal with the
67 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
68 Unix, only because Jack added it back); when available on Windows, it only
69 applies to sockets. */
71 #ifdef MS_WINDOWS
72 #define FHANDLETYPE TCL_WIN_SOCKET
73 #else
74 #define FHANDLETYPE TCL_UNIX_FD
75 #endif
77 /* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
78 which uses this to handle Tcl events while the user is typing commands. */
80 #if FHANDLETYPE == TCL_UNIX_FD
81 #define WAIT_FOR_STDIN
82 #endif
84 #endif /* HAVE_CREATEFILEHANDLER */
86 #ifdef MS_WINDOWS
87 #include <conio.h>
88 #define WAIT_FOR_STDIN
89 #endif
91 #ifdef WITH_THREAD
93 /* The threading situation is complicated. Tcl is not thread-safe, except for
94 Tcl 8.1, which will probably remain in alpha status for another 6 months
95 (and the README says that Tk will probably remain thread-unsafe forever).
96 So we need to use a lock around all uses of Tcl. Previously, the Python
97 interpreter lock was used for this. However, this causes problems when
98 other Python threads need to run while Tcl is blocked waiting for events.
100 To solve this problem, a separate lock for Tcl is introduced. Holding it
101 is incompatible with holding Python's interpreter lock. The following four
102 macros manipulate both locks together.
104 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
105 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
106 that could call an event handler, or otherwise affect the state of a Tcl
107 interpreter. These assume that the surrounding code has the Python
108 interpreter lock; inside the brackets, the Python interpreter lock has been
109 released and the lock for Tcl has been acquired.
111 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
112 (For example, when transferring data from the Tcl interpreter result to a
113 Python string object.) This can be done by using different macros to close
114 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
115 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
116 releases the Tcl lock.
118 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
119 handlers when the handler needs to use Python. Such event handlers are
120 entered while the lock for Tcl is held; the event handler presumably needs
121 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
122 the Python interpreter lock, restoring the appropriate thread state, and
123 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
124 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
125 the code between ENTER_PYTHON and LEAVE_PYTHON.
127 These locks expand to several statements and brackets; they should not be
128 used in branches of if statements and the like.
132 static PyThread_type_lock tcl_lock = 0;
133 static PyThreadState *tcl_tstate = NULL;
135 #define ENTER_TCL \
136 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
137 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
139 #define LEAVE_TCL \
140 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
142 #define ENTER_OVERLAP \
143 Py_END_ALLOW_THREADS
145 #define LEAVE_OVERLAP_TCL \
146 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); }
148 #define ENTER_PYTHON \
149 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
150 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
152 #define LEAVE_PYTHON \
153 { PyThreadState *tstate = PyEval_SaveThread(); \
154 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
156 #else
158 #define ENTER_TCL
159 #define LEAVE_TCL
160 #define ENTER_OVERLAP
161 #define LEAVE_OVERLAP_TCL
162 #define ENTER_PYTHON
163 #define LEAVE_PYTHON
165 #endif
167 #ifdef macintosh
170 ** Additional cruft needed by Tcl/Tk on the Mac.
171 ** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
174 /* ckfree() expects a char* */
175 #define FREECAST (char *)
177 #include <Events.h> /* For EventRecord */
179 typedef int (*TclMacConvertEventPtr) (EventRecord *eventPtr);
180 void Tcl_MacSetEventProc(TclMacConvertEventPtr procPtr);
181 int TkMacConvertEvent(EventRecord *eventPtr);
183 staticforward int PyMacConvertEvent(EventRecord *eventPtr);
185 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
186 #pragma import on
187 #endif
189 #include <SIOUX.h>
190 extern int SIOUXIsAppWindow(WindowPtr);
192 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
193 #pragma import reset
194 #endif
195 #endif /* macintosh */
197 #ifndef FREECAST
198 #define FREECAST (char *)
199 #endif
201 /**** Tkapp Object Declaration ****/
203 staticforward PyTypeObject Tkapp_Type;
205 typedef struct {
206 PyObject_HEAD
207 Tcl_Interp *interp;
208 } TkappObject;
210 #define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
211 #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
212 #define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
214 #define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
215 (void *) v, ((PyObject *) v)->ob_refcnt))
219 /**** Error Handling ****/
221 static PyObject *Tkinter_TclError;
222 static int quitMainLoop = 0;
223 static int errorInCmd = 0;
224 static PyObject *excInCmd;
225 static PyObject *valInCmd;
226 static PyObject *trbInCmd;
230 static PyObject *
231 Tkinter_Error(PyObject *v)
233 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
234 return NULL;
239 /**** Utils ****/
241 #ifdef WITH_THREAD
242 #ifndef MS_WINDOWS
244 /* Millisecond sleep() for Unix platforms. */
246 static void
247 Sleep(int milli)
249 /* XXX Too bad if you don't have select(). */
250 struct timeval t;
251 t.tv_sec = milli/1000;
252 t.tv_usec = (milli%1000) * 1000;
253 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
255 #endif /* MS_WINDOWS */
256 #endif /* WITH_THREAD */
259 static char *
260 AsString(PyObject *value, PyObject *tmp)
262 if (PyString_Check(value))
263 return PyString_AsString(value);
264 else if (PyUnicode_Check(value)) {
265 PyObject *v = PyUnicode_AsUTF8String(value);
266 if (v == NULL)
267 return NULL;
268 if (PyList_Append(tmp, v) != 0) {
269 Py_DECREF(v);
270 return NULL;
272 Py_DECREF(v);
273 return PyString_AsString(v);
275 else {
276 PyObject *v = PyObject_Str(value);
277 if (v == NULL)
278 return NULL;
279 if (PyList_Append(tmp, v) != 0) {
280 Py_DECREF(v);
281 return NULL;
283 Py_DECREF(v);
284 return PyString_AsString(v);
290 #define ARGSZ 64
292 static char *
293 Merge(PyObject *args)
295 PyObject *tmp = NULL;
296 char *argvStore[ARGSZ];
297 char **argv = NULL;
298 int fvStore[ARGSZ];
299 int *fv = NULL;
300 int argc = 0, fvc = 0, i;
301 char *res = NULL;
303 if (!(tmp = PyList_New(0)))
304 return NULL;
306 argv = argvStore;
307 fv = fvStore;
309 if (args == NULL)
310 argc = 0;
312 else if (!PyTuple_Check(args)) {
313 argc = 1;
314 fv[0] = 0;
315 if (!(argv[0] = AsString(args, tmp)))
316 goto finally;
318 else {
319 argc = PyTuple_Size(args);
321 if (argc > ARGSZ) {
322 argv = (char **)ckalloc(argc * sizeof(char *));
323 fv = (int *)ckalloc(argc * sizeof(int));
324 if (argv == NULL || fv == NULL) {
325 PyErr_NoMemory();
326 goto finally;
330 for (i = 0; i < argc; i++) {
331 PyObject *v = PyTuple_GetItem(args, i);
332 if (PyTuple_Check(v)) {
333 fv[i] = 1;
334 if (!(argv[i] = Merge(v)))
335 goto finally;
336 fvc++;
338 else if (v == Py_None) {
339 argc = i;
340 break;
342 else {
343 fv[i] = 0;
344 if (!(argv[i] = AsString(v, tmp)))
345 goto finally;
346 fvc++;
350 res = Tcl_Merge(argc, argv);
351 if (res == NULL)
352 PyErr_SetString(Tkinter_TclError, "merge failed");
354 finally:
355 for (i = 0; i < fvc; i++)
356 if (fv[i]) {
357 ckfree(argv[i]);
359 if (argv != argvStore)
360 ckfree(FREECAST argv);
361 if (fv != fvStore)
362 ckfree(FREECAST fv);
364 Py_DECREF(tmp);
365 return res;
370 static PyObject *
371 Split(char *list)
373 int argc;
374 char **argv;
375 PyObject *v;
377 if (list == NULL) {
378 Py_INCREF(Py_None);
379 return Py_None;
382 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
383 /* Not a list.
384 * Could be a quoted string containing funnies, e.g. {"}.
385 * Return the string itself.
387 return PyString_FromString(list);
390 if (argc == 0)
391 v = PyString_FromString("");
392 else if (argc == 1)
393 v = PyString_FromString(argv[0]);
394 else if ((v = PyTuple_New(argc)) != NULL) {
395 int i;
396 PyObject *w;
398 for (i = 0; i < argc; i++) {
399 if ((w = Split(argv[i])) == NULL) {
400 Py_DECREF(v);
401 v = NULL;
402 break;
404 PyTuple_SetItem(v, i, w);
407 Tcl_Free(FREECAST argv);
408 return v;
413 /**** Tkapp Object ****/
415 #ifndef WITH_APPINIT
417 Tcl_AppInit(Tcl_Interp *interp)
419 Tk_Window main;
421 main = Tk_MainWindow(interp);
422 if (Tcl_Init(interp) == TCL_ERROR) {
423 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
424 return TCL_ERROR;
426 if (Tk_Init(interp) == TCL_ERROR) {
427 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
428 return TCL_ERROR;
430 return TCL_OK;
432 #endif /* !WITH_APPINIT */
437 /* Initialize the Tk application; see the `main' function in
438 * `tkMain.c'.
441 static void EnableEventHook(void); /* Forward */
442 static void DisableEventHook(void); /* Forward */
444 static TkappObject *
445 Tkapp_New(char *screenName, char *baseName, char *className, int interactive)
447 TkappObject *v;
448 char *argv0;
450 v = PyObject_New(TkappObject, &Tkapp_Type);
451 if (v == NULL)
452 return NULL;
454 v->interp = Tcl_CreateInterp();
456 #if defined(macintosh)
457 /* This seems to be needed */
458 ClearMenuBar();
459 TkMacInitMenus(v->interp);
460 #endif
461 /* Delete the 'exit' command, which can screw things up */
462 Tcl_DeleteCommand(v->interp, "exit");
464 if (screenName != NULL)
465 Tcl_SetVar2(v->interp, "env", "DISPLAY",
466 screenName, TCL_GLOBAL_ONLY);
468 if (interactive)
469 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
470 else
471 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
473 /* This is used to get the application class for Tk 4.1 and up */
474 argv0 = (char*)ckalloc(strlen(className) + 1);
475 if (!argv0) {
476 PyErr_NoMemory();
477 Py_DECREF(v);
478 return NULL;
481 strcpy(argv0, className);
482 if (isupper((int)(argv0[0])))
483 argv0[0] = tolower(argv0[0]);
484 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
485 ckfree(argv0);
487 if (Tcl_AppInit(v->interp) != TCL_OK)
488 return (TkappObject *)Tkinter_Error((PyObject *)v);
490 EnableEventHook();
492 return v;
497 /** Tcl Eval **/
499 #if TKMAJORMINOR >= 8001
500 #define USING_OBJECTS
501 #endif
503 #ifdef USING_OBJECTS
505 static Tcl_Obj*
506 AsObj(PyObject *value)
508 Tcl_Obj *result;
510 if (PyString_Check(value))
511 return Tcl_NewStringObj(PyString_AS_STRING(value),
512 PyString_GET_SIZE(value));
513 else if (PyInt_Check(value))
514 return Tcl_NewLongObj(PyInt_AS_LONG(value));
515 else if (PyFloat_Check(value))
516 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
517 else if (PyTuple_Check(value)) {
518 Tcl_Obj **argv = (Tcl_Obj**)
519 ckalloc(PyTuple_Size(value)*sizeof(Tcl_Obj*));
520 int i;
521 if(!argv)
522 return 0;
523 for(i=0;i<PyTuple_Size(value);i++)
524 argv[i] = AsObj(PyTuple_GetItem(value,i));
525 result = Tcl_NewListObj(PyTuple_Size(value), argv);
526 ckfree(FREECAST argv);
527 return result;
529 else if (PyUnicode_Check(value)) {
530 #if TKMAJORMINOR <= 8001
531 /* In Tcl 8.1 we must use UTF-8 */
532 PyObject* utf8 = PyUnicode_AsUTF8String(value);
533 if (!utf8)
534 return 0;
535 result = Tcl_NewStringObj(PyString_AS_STRING(utf8),
536 PyString_GET_SIZE(utf8));
537 Py_DECREF(utf8);
538 return result;
539 #else /* TKMAJORMINOR > 8001 */
540 /* In Tcl 8.2 and later, use Tcl_NewUnicodeObj() */
541 if (sizeof(Py_UNICODE) != sizeof(Tcl_UniChar)) {
542 /* XXX Should really test this at compile time */
543 PyErr_SetString(PyExc_SystemError,
544 "Py_UNICODE and Tcl_UniChar differ in size");
545 return 0;
547 return Tcl_NewUnicodeObj(PyUnicode_AS_UNICODE(value),
548 PyUnicode_GET_SIZE(value));
549 #endif /* TKMAJORMINOR > 8001 */
551 else {
552 PyObject *v = PyObject_Str(value);
553 if (!v)
554 return 0;
555 result = AsObj(v);
556 Py_DECREF(v);
557 return result;
561 static PyObject *
562 Tkapp_Call(PyObject *self, PyObject *args)
564 Tcl_Obj *objStore[ARGSZ];
565 Tcl_Obj **objv = NULL;
566 int objc = 0, i;
567 PyObject *res = NULL;
568 Tcl_Interp *interp = Tkapp_Interp(self);
569 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
570 int flags = TCL_EVAL_DIRECT;
572 objv = objStore;
574 if (args == NULL)
575 /* do nothing */;
577 else if (!PyTuple_Check(args)) {
578 objv[0] = AsObj(args);
579 if (objv[0] == 0)
580 goto finally;
581 objc = 1;
582 Tcl_IncrRefCount(objv[0]);
584 else {
585 objc = PyTuple_Size(args);
587 if (objc > ARGSZ) {
588 objv = (Tcl_Obj **)ckalloc(objc * sizeof(char *));
589 if (objv == NULL) {
590 PyErr_NoMemory();
591 objc = 0;
592 goto finally;
596 for (i = 0; i < objc; i++) {
597 PyObject *v = PyTuple_GetItem(args, i);
598 if (v == Py_None) {
599 objc = i;
600 break;
602 objv[i] = AsObj(v);
603 if (!objv[i]) {
604 /* Reset objc, so it attempts to clear
605 objects only up to i. */
606 objc = i;
607 goto finally;
609 Tcl_IncrRefCount(objv[i]);
613 ENTER_TCL
615 i = Tcl_EvalObjv(interp, objc, objv, flags);
617 ENTER_OVERLAP
618 if (i == TCL_ERROR)
619 Tkinter_Error(self);
620 else {
621 /* We could request the object result here, but doing
622 so would confuse applications that expect a string. */
623 char *s = Tcl_GetStringResult(interp);
624 char *p = s;
625 /* If the result contains any bytes with the top bit set,
626 it's UTF-8 and we should decode it to Unicode */
627 while (*p != '\0') {
628 if (*p & 0x80)
629 break;
630 p++;
632 if (*p == '\0')
633 res = PyString_FromStringAndSize(s, (int)(p-s));
634 else {
635 /* Convert UTF-8 to Unicode string */
636 p = strchr(p, '\0');
637 res = PyUnicode_DecodeUTF8(s, (int)(p-s), "strict");
638 if (res == NULL) {
639 PyErr_Clear();
640 res = PyString_FromStringAndSize(s, (int)(p-s));
645 LEAVE_OVERLAP_TCL
647 finally:
648 for (i = 0; i < objc; i++)
649 Tcl_DecrRefCount(objv[i]);
650 if (objv != objStore)
651 ckfree(FREECAST objv);
652 return res;
655 #else /* !USING_OBJECTS */
657 static PyObject *
658 Tkapp_Call(PyObject *self, PyObject *args)
660 /* This is copied from Merge() */
661 PyObject *tmp = NULL;
662 char *argvStore[ARGSZ];
663 char **argv = NULL;
664 int fvStore[ARGSZ];
665 int *fv = NULL;
666 int argc = 0, fvc = 0, i;
667 PyObject *res = NULL; /* except this has a different type */
668 Tcl_CmdInfo info; /* and this is added */
669 Tcl_Interp *interp = Tkapp_Interp(self); /* and this too */
671 if (!(tmp = PyList_New(0)))
672 return NULL;
674 argv = argvStore;
675 fv = fvStore;
677 if (args == NULL)
678 argc = 0;
680 else if (!PyTuple_Check(args)) {
681 argc = 1;
682 fv[0] = 0;
683 if (!(argv[0] = AsString(args, tmp)))
684 goto finally;
686 else {
687 argc = PyTuple_Size(args);
689 if (argc > ARGSZ) {
690 argv = (char **)ckalloc(argc * sizeof(char *));
691 fv = (int *)ckalloc(argc * sizeof(int));
692 if (argv == NULL || fv == NULL) {
693 PyErr_NoMemory();
694 goto finally;
698 for (i = 0; i < argc; i++) {
699 PyObject *v = PyTuple_GetItem(args, i);
700 if (PyTuple_Check(v)) {
701 fv[i] = 1;
702 if (!(argv[i] = Merge(v)))
703 goto finally;
704 fvc++;
706 else if (v == Py_None) {
707 argc = i;
708 break;
710 else {
711 fv[i] = 0;
712 if (!(argv[i] = AsString(v, tmp)))
713 goto finally;
714 fvc++;
718 /* End code copied from Merge() */
720 /* All this to avoid a call to Tcl_Merge() and the corresponding call
721 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
722 if (Py_VerboseFlag >= 2) {
723 for (i = 0; i < argc; i++)
724 PySys_WriteStderr("%s ", argv[i]);
726 ENTER_TCL
727 info.proc = NULL;
728 if (argc < 1 ||
729 !Tcl_GetCommandInfo(interp, argv[0], &info) ||
730 info.proc == NULL)
732 char *cmd;
733 cmd = Tcl_Merge(argc, argv);
734 i = Tcl_Eval(interp, cmd);
735 ckfree(cmd);
737 else {
738 Tcl_ResetResult(interp);
739 i = (*info.proc)(info.clientData, interp, argc, argv);
741 ENTER_OVERLAP
742 if (info.proc == NULL && Py_VerboseFlag >= 2)
743 PySys_WriteStderr("... use TclEval ");
744 if (i == TCL_ERROR) {
745 if (Py_VerboseFlag >= 2)
746 PySys_WriteStderr("... error: '%s'\n",
747 Tcl_GetStringResult(interp));
748 Tkinter_Error(self);
750 else {
751 if (Py_VerboseFlag >= 2)
752 PySys_WriteStderr("-> '%s'\n", Tcl_GetStringResult(interp));
753 res = PyString_FromString(Tcl_GetStringResult(interp));
755 LEAVE_OVERLAP_TCL
757 /* Copied from Merge() again */
758 finally:
759 for (i = 0; i < fvc; i++)
760 if (fv[i]) {
761 ckfree(argv[i]);
763 if (argv != argvStore)
764 ckfree(FREECAST argv);
765 if (fv != fvStore)
766 ckfree(FREECAST fv);
768 Py_DECREF(tmp);
769 return res;
772 #endif /* !USING_OBJECTS */
774 static PyObject *
775 Tkapp_GlobalCall(PyObject *self, PyObject *args)
777 /* Could do the same here as for Tkapp_Call(), but this is not used
778 much, so I can't be bothered. Unfortunately Tcl doesn't export a
779 way for the user to do what all its Global* variants do (save and
780 reset the scope pointer, call the local version, restore the saved
781 scope pointer). */
783 char *cmd;
784 PyObject *res = NULL;
786 cmd = Merge(args);
787 if (cmd) {
788 int err;
789 ENTER_TCL
790 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
791 ENTER_OVERLAP
792 if (err == TCL_ERROR)
793 res = Tkinter_Error(self);
794 else
795 res = PyString_FromString(Tkapp_Result(self));
796 LEAVE_OVERLAP_TCL
797 ckfree(cmd);
800 return res;
803 static PyObject *
804 Tkapp_Eval(PyObject *self, PyObject *args)
806 char *script;
807 PyObject *res = NULL;
808 int err;
810 if (!PyArg_ParseTuple(args, "s:eval", &script))
811 return NULL;
813 ENTER_TCL
814 err = Tcl_Eval(Tkapp_Interp(self), script);
815 ENTER_OVERLAP
816 if (err == TCL_ERROR)
817 res = Tkinter_Error(self);
818 else
819 res = PyString_FromString(Tkapp_Result(self));
820 LEAVE_OVERLAP_TCL
821 return res;
824 static PyObject *
825 Tkapp_GlobalEval(PyObject *self, PyObject *args)
827 char *script;
828 PyObject *res = NULL;
829 int err;
831 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
832 return NULL;
834 ENTER_TCL
835 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
836 ENTER_OVERLAP
837 if (err == TCL_ERROR)
838 res = Tkinter_Error(self);
839 else
840 res = PyString_FromString(Tkapp_Result(self));
841 LEAVE_OVERLAP_TCL
842 return res;
845 static PyObject *
846 Tkapp_EvalFile(PyObject *self, PyObject *args)
848 char *fileName;
849 PyObject *res = NULL;
850 int err;
852 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
853 return NULL;
855 ENTER_TCL
856 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
857 ENTER_OVERLAP
858 if (err == TCL_ERROR)
859 res = Tkinter_Error(self);
861 else
862 res = PyString_FromString(Tkapp_Result(self));
863 LEAVE_OVERLAP_TCL
864 return res;
867 static PyObject *
868 Tkapp_Record(PyObject *self, PyObject *args)
870 char *script;
871 PyObject *res = NULL;
872 int err;
874 if (!PyArg_ParseTuple(args, "s", &script))
875 return NULL;
877 ENTER_TCL
878 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
879 ENTER_OVERLAP
880 if (err == TCL_ERROR)
881 res = Tkinter_Error(self);
882 else
883 res = PyString_FromString(Tkapp_Result(self));
884 LEAVE_OVERLAP_TCL
885 return res;
888 static PyObject *
889 Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
891 char *msg;
893 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
894 return NULL;
895 ENTER_TCL
896 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
897 LEAVE_TCL
899 Py_INCREF(Py_None);
900 return Py_None;
905 /** Tcl Variable **/
907 static PyObject *
908 SetVar(PyObject *self, PyObject *args, int flags)
910 char *name1, *name2, *ok, *s;
911 PyObject *newValue;
912 PyObject *tmp;
914 tmp = PyList_New(0);
915 if (!tmp)
916 return NULL;
918 if (PyArg_ParseTuple(args, "sO:setvar", &name1, &newValue)) {
919 /* XXX Merge? */
920 s = AsString(newValue, tmp);
921 if (s == NULL)
922 return NULL;
923 ENTER_TCL
924 ok = Tcl_SetVar(Tkapp_Interp(self), name1, s, flags);
925 LEAVE_TCL
927 else {
928 PyErr_Clear();
929 if (PyArg_ParseTuple(args, "ssO:setvar",
930 &name1, &name2, &newValue)) {
931 s = AsString(newValue, tmp);
932 if (s == NULL)
933 return NULL;
934 ENTER_TCL
935 ok = Tcl_SetVar2(Tkapp_Interp(self), name1, name2,
936 s, flags);
937 LEAVE_TCL
939 else {
940 Py_DECREF(tmp);
941 return NULL;
944 Py_DECREF(tmp);
946 if (!ok)
947 return Tkinter_Error(self);
949 Py_INCREF(Py_None);
950 return Py_None;
953 static PyObject *
954 Tkapp_SetVar(PyObject *self, PyObject *args)
956 return SetVar(self, args, TCL_LEAVE_ERR_MSG);
959 static PyObject *
960 Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
962 return SetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
967 static PyObject *
968 GetVar(PyObject *self, PyObject *args, int flags)
970 char *name1, *name2=NULL, *s;
971 PyObject *res = NULL;
973 if (!PyArg_ParseTuple(args, "s|s:getvar", &name1, &name2))
974 return NULL;
975 ENTER_TCL
976 if (name2 == NULL)
977 s = Tcl_GetVar(Tkapp_Interp(self), name1, flags);
979 else
980 s = Tcl_GetVar2(Tkapp_Interp(self), name1, name2, flags);
981 ENTER_OVERLAP
983 if (s == NULL)
984 res = Tkinter_Error(self);
985 else
986 res = PyString_FromString(s);
987 LEAVE_OVERLAP_TCL
988 return res;
991 static PyObject *
992 Tkapp_GetVar(PyObject *self, PyObject *args)
994 return GetVar(self, args, TCL_LEAVE_ERR_MSG);
997 static PyObject *
998 Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
1000 return GetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1005 static PyObject *
1006 UnsetVar(PyObject *self, PyObject *args, int flags)
1008 char *name1, *name2=NULL;
1009 PyObject *res = NULL;
1010 int code;
1012 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1013 return NULL;
1014 ENTER_TCL
1015 if (name2 == NULL)
1016 code = Tcl_UnsetVar(Tkapp_Interp(self), name1, flags);
1018 else
1019 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1020 ENTER_OVERLAP
1022 if (code == TCL_ERROR)
1023 res = Tkinter_Error(self);
1024 else {
1025 Py_INCREF(Py_None);
1026 res = Py_None;
1028 LEAVE_OVERLAP_TCL
1029 return res;
1032 static PyObject *
1033 Tkapp_UnsetVar(PyObject *self, PyObject *args)
1035 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG);
1038 static PyObject *
1039 Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
1041 return UnsetVar(self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
1046 /** Tcl to Python **/
1048 static PyObject *
1049 Tkapp_GetInt(PyObject *self, PyObject *args)
1051 char *s;
1052 int v;
1054 if (!PyArg_ParseTuple(args, "s:getint", &s))
1055 return NULL;
1056 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1057 return Tkinter_Error(self);
1058 return Py_BuildValue("i", v);
1061 static PyObject *
1062 Tkapp_GetDouble(PyObject *self, PyObject *args)
1064 char *s;
1065 double v;
1067 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1068 return NULL;
1069 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1070 return Tkinter_Error(self);
1071 return Py_BuildValue("d", v);
1074 static PyObject *
1075 Tkapp_GetBoolean(PyObject *self, PyObject *args)
1077 char *s;
1078 int v;
1080 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1081 return NULL;
1082 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1083 return Tkinter_Error(self);
1084 return Py_BuildValue("i", v);
1087 static PyObject *
1088 Tkapp_ExprString(PyObject *self, PyObject *args)
1090 char *s;
1091 PyObject *res = NULL;
1092 int retval;
1094 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1095 return NULL;
1096 ENTER_TCL
1097 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1098 ENTER_OVERLAP
1099 if (retval == TCL_ERROR)
1100 res = Tkinter_Error(self);
1101 else
1102 res = Py_BuildValue("s", Tkapp_Result(self));
1103 LEAVE_OVERLAP_TCL
1104 return res;
1107 static PyObject *
1108 Tkapp_ExprLong(PyObject *self, PyObject *args)
1110 char *s;
1111 PyObject *res = NULL;
1112 int retval;
1113 long v;
1115 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1116 return NULL;
1117 ENTER_TCL
1118 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1119 ENTER_OVERLAP
1120 if (retval == TCL_ERROR)
1121 res = Tkinter_Error(self);
1122 else
1123 res = Py_BuildValue("l", v);
1124 LEAVE_OVERLAP_TCL
1125 return res;
1128 static PyObject *
1129 Tkapp_ExprDouble(PyObject *self, PyObject *args)
1131 char *s;
1132 PyObject *res = NULL;
1133 double v;
1134 int retval;
1136 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1137 return NULL;
1138 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1139 ENTER_TCL
1140 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1141 ENTER_OVERLAP
1142 PyFPE_END_PROTECT(retval)
1143 if (retval == TCL_ERROR)
1144 res = Tkinter_Error(self);
1145 else
1146 res = Py_BuildValue("d", v);
1147 LEAVE_OVERLAP_TCL
1148 return res;
1151 static PyObject *
1152 Tkapp_ExprBoolean(PyObject *self, PyObject *args)
1154 char *s;
1155 PyObject *res = NULL;
1156 int retval;
1157 int v;
1159 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1160 return NULL;
1161 ENTER_TCL
1162 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1163 ENTER_OVERLAP
1164 if (retval == TCL_ERROR)
1165 res = Tkinter_Error(self);
1166 else
1167 res = Py_BuildValue("i", v);
1168 LEAVE_OVERLAP_TCL
1169 return res;
1174 static PyObject *
1175 Tkapp_SplitList(PyObject *self, PyObject *args)
1177 char *list;
1178 int argc;
1179 char **argv;
1180 PyObject *v;
1181 int i;
1183 if (!PyArg_ParseTuple(args, "s:splitlist", &list))
1184 return NULL;
1186 if (Tcl_SplitList(Tkapp_Interp(self), list, &argc, &argv) == TCL_ERROR)
1187 return Tkinter_Error(self);
1189 if (!(v = PyTuple_New(argc)))
1190 return NULL;
1192 for (i = 0; i < argc; i++) {
1193 PyObject *s = PyString_FromString(argv[i]);
1194 if (!s || PyTuple_SetItem(v, i, s)) {
1195 Py_DECREF(v);
1196 v = NULL;
1197 goto finally;
1201 finally:
1202 ckfree(FREECAST argv);
1203 return v;
1206 static PyObject *
1207 Tkapp_Split(PyObject *self, PyObject *args)
1209 char *list;
1211 if (!PyArg_ParseTuple(args, "s:split", &list))
1212 return NULL;
1213 return Split(list);
1216 static PyObject *
1217 Tkapp_Merge(PyObject *self, PyObject *args)
1219 char *s = Merge(args);
1220 PyObject *res = NULL;
1222 if (s) {
1223 res = PyString_FromString(s);
1224 ckfree(s);
1227 return res;
1232 /** Tcl Command **/
1234 /* Client data struct */
1235 typedef struct {
1236 PyObject *self;
1237 PyObject *func;
1238 } PythonCmd_ClientData;
1240 static int
1241 PythonCmd_Error(Tcl_Interp *interp)
1243 errorInCmd = 1;
1244 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1245 LEAVE_PYTHON
1246 return TCL_ERROR;
1249 /* This is the Tcl command that acts as a wrapper for Python
1250 * function or method.
1252 static int
1253 PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
1255 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1256 PyObject *self, *func, *arg, *res, *tmp;
1257 int i, rv;
1258 char *s;
1260 ENTER_PYTHON
1262 /* TBD: no error checking here since we know, via the
1263 * Tkapp_CreateCommand() that the client data is a two-tuple
1265 self = data->self;
1266 func = data->func;
1268 /* Create argument list (argv1, ..., argvN) */
1269 if (!(arg = PyTuple_New(argc - 1)))
1270 return PythonCmd_Error(interp);
1272 for (i = 0; i < (argc - 1); i++) {
1273 PyObject *s = PyString_FromString(argv[i + 1]);
1274 if (!s || PyTuple_SetItem(arg, i, s)) {
1275 Py_DECREF(arg);
1276 return PythonCmd_Error(interp);
1279 res = PyEval_CallObject(func, arg);
1280 Py_DECREF(arg);
1282 if (res == NULL)
1283 return PythonCmd_Error(interp);
1285 if (!(tmp = PyList_New(0))) {
1286 Py_DECREF(res);
1287 return PythonCmd_Error(interp);
1290 s = AsString(res, tmp);
1291 if (s == NULL) {
1292 rv = PythonCmd_Error(interp);
1294 else {
1295 Tcl_SetResult(Tkapp_Interp(self), s, TCL_VOLATILE);
1296 rv = TCL_OK;
1299 Py_DECREF(res);
1300 Py_DECREF(tmp);
1302 LEAVE_PYTHON
1304 return rv;
1307 static void
1308 PythonCmdDelete(ClientData clientData)
1310 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
1312 ENTER_PYTHON
1313 Py_XDECREF(data->self);
1314 Py_XDECREF(data->func);
1315 PyMem_DEL(data);
1316 LEAVE_PYTHON
1321 static PyObject *
1322 Tkapp_CreateCommand(PyObject *self, PyObject *args)
1324 PythonCmd_ClientData *data;
1325 char *cmdName;
1326 PyObject *func;
1327 Tcl_Command err;
1329 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
1330 return NULL;
1331 if (!PyCallable_Check(func)) {
1332 PyErr_SetString(PyExc_TypeError, "command not callable");
1333 return NULL;
1336 data = PyMem_NEW(PythonCmd_ClientData, 1);
1337 if (!data)
1338 return NULL;
1339 Py_XINCREF(self);
1340 Py_XINCREF(func);
1341 data->self = self;
1342 data->func = func;
1344 ENTER_TCL
1345 err = Tcl_CreateCommand(Tkapp_Interp(self), cmdName, PythonCmd,
1346 (ClientData)data, PythonCmdDelete);
1347 LEAVE_TCL
1348 if (err == NULL) {
1349 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
1350 PyMem_DEL(data);
1351 return NULL;
1354 Py_INCREF(Py_None);
1355 return Py_None;
1360 static PyObject *
1361 Tkapp_DeleteCommand(PyObject *self, PyObject *args)
1363 char *cmdName;
1364 int err;
1366 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
1367 return NULL;
1368 ENTER_TCL
1369 err = Tcl_DeleteCommand(Tkapp_Interp(self), cmdName);
1370 LEAVE_TCL
1371 if (err == -1) {
1372 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
1373 return NULL;
1375 Py_INCREF(Py_None);
1376 return Py_None;
1381 #ifdef HAVE_CREATEFILEHANDLER
1382 /** File Handler **/
1384 typedef struct _fhcdata {
1385 PyObject *func;
1386 PyObject *file;
1387 int id;
1388 struct _fhcdata *next;
1389 } FileHandler_ClientData;
1391 static FileHandler_ClientData *HeadFHCD;
1393 static FileHandler_ClientData *
1394 NewFHCD(PyObject *func, PyObject *file, int id)
1396 FileHandler_ClientData *p;
1397 p = PyMem_NEW(FileHandler_ClientData, 1);
1398 if (p != NULL) {
1399 Py_XINCREF(func);
1400 Py_XINCREF(file);
1401 p->func = func;
1402 p->file = file;
1403 p->id = id;
1404 p->next = HeadFHCD;
1405 HeadFHCD = p;
1407 return p;
1410 static void
1411 DeleteFHCD(int id)
1413 FileHandler_ClientData *p, **pp;
1415 pp = &HeadFHCD;
1416 while ((p = *pp) != NULL) {
1417 if (p->id == id) {
1418 *pp = p->next;
1419 Py_XDECREF(p->func);
1420 Py_XDECREF(p->file);
1421 PyMem_DEL(p);
1423 else
1424 pp = &p->next;
1428 static void
1429 FileHandler(ClientData clientData, int mask)
1431 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
1432 PyObject *func, *file, *arg, *res;
1434 ENTER_PYTHON
1435 func = data->func;
1436 file = data->file;
1438 arg = Py_BuildValue("(Oi)", file, (long) mask);
1439 res = PyEval_CallObject(func, arg);
1440 Py_DECREF(arg);
1442 if (res == NULL) {
1443 errorInCmd = 1;
1444 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1446 Py_XDECREF(res);
1447 LEAVE_PYTHON
1450 static PyObject *
1451 Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
1452 /* args is (file, mask, func) */
1454 FileHandler_ClientData *data;
1455 PyObject *file, *func;
1456 int mask, tfile;
1458 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
1459 &file, &mask, &func))
1460 return NULL;
1461 tfile = PyObject_AsFileDescriptor(file);
1462 if (tfile < 0)
1463 return NULL;
1464 if (!PyCallable_Check(func)) {
1465 PyErr_SetString(PyExc_TypeError, "bad argument list");
1466 return NULL;
1469 data = NewFHCD(func, file, tfile);
1470 if (data == NULL)
1471 return NULL;
1473 /* Ought to check for null Tcl_File object... */
1474 ENTER_TCL
1475 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
1476 LEAVE_TCL
1477 Py_INCREF(Py_None);
1478 return Py_None;
1481 static PyObject *
1482 Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
1484 PyObject *file;
1485 int tfile;
1487 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
1488 return NULL;
1489 tfile = PyObject_AsFileDescriptor(file);
1490 if (tfile < 0)
1491 return NULL;
1493 DeleteFHCD(tfile);
1495 /* Ought to check for null Tcl_File object... */
1496 ENTER_TCL
1497 Tcl_DeleteFileHandler(tfile);
1498 LEAVE_TCL
1499 Py_INCREF(Py_None);
1500 return Py_None;
1502 #endif /* HAVE_CREATEFILEHANDLER */
1505 /**** Tktt Object (timer token) ****/
1507 staticforward PyTypeObject Tktt_Type;
1509 typedef struct {
1510 PyObject_HEAD
1511 Tcl_TimerToken token;
1512 PyObject *func;
1513 } TkttObject;
1515 static PyObject *
1516 Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
1518 TkttObject *v = (TkttObject *)self;
1519 PyObject *func = v->func;
1521 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
1522 return NULL;
1523 if (v->token != NULL) {
1524 Tcl_DeleteTimerHandler(v->token);
1525 v->token = NULL;
1527 if (func != NULL) {
1528 v->func = NULL;
1529 Py_DECREF(func);
1530 Py_DECREF(v); /* See Tktt_New() */
1532 Py_INCREF(Py_None);
1533 return Py_None;
1536 static PyMethodDef Tktt_methods[] =
1538 {"deletetimerhandler", Tktt_DeleteTimerHandler, 1},
1539 {NULL, NULL}
1542 static TkttObject *
1543 Tktt_New(PyObject *func)
1545 TkttObject *v;
1547 v = PyObject_New(TkttObject, &Tktt_Type);
1548 if (v == NULL)
1549 return NULL;
1551 Py_INCREF(func);
1552 v->token = NULL;
1553 v->func = func;
1555 /* Extra reference, deleted when called or when handler is deleted */
1556 Py_INCREF(v);
1557 return v;
1560 static void
1561 Tktt_Dealloc(PyObject *self)
1563 TkttObject *v = (TkttObject *)self;
1564 PyObject *func = v->func;
1566 Py_XDECREF(func);
1568 PyObject_Del(self);
1571 static PyObject *
1572 Tktt_Repr(PyObject *self)
1574 TkttObject *v = (TkttObject *)self;
1575 char buf[100];
1577 sprintf(buf, "<tktimertoken at %p%s>", v,
1578 v->func == NULL ? ", handler deleted" : "");
1579 return PyString_FromString(buf);
1582 static PyObject *
1583 Tktt_GetAttr(PyObject *self, char *name)
1585 return Py_FindMethod(Tktt_methods, self, name);
1588 static PyTypeObject Tktt_Type =
1590 PyObject_HEAD_INIT(NULL)
1591 0, /*ob_size */
1592 "tktimertoken", /*tp_name */
1593 sizeof(TkttObject), /*tp_basicsize */
1594 0, /*tp_itemsize */
1595 Tktt_Dealloc, /*tp_dealloc */
1596 0, /*tp_print */
1597 Tktt_GetAttr, /*tp_getattr */
1598 0, /*tp_setattr */
1599 0, /*tp_compare */
1600 Tktt_Repr, /*tp_repr */
1601 0, /*tp_as_number */
1602 0, /*tp_as_sequence */
1603 0, /*tp_as_mapping */
1604 0, /*tp_hash */
1609 /** Timer Handler **/
1611 static void
1612 TimerHandler(ClientData clientData)
1614 TkttObject *v = (TkttObject *)clientData;
1615 PyObject *func = v->func;
1616 PyObject *res;
1618 if (func == NULL)
1619 return;
1621 v->func = NULL;
1623 ENTER_PYTHON
1625 res = PyEval_CallObject(func, NULL);
1626 Py_DECREF(func);
1627 Py_DECREF(v); /* See Tktt_New() */
1629 if (res == NULL) {
1630 errorInCmd = 1;
1631 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
1633 else
1634 Py_DECREF(res);
1636 LEAVE_PYTHON
1639 static PyObject *
1640 Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
1642 int milliseconds;
1643 PyObject *func;
1644 TkttObject *v;
1646 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
1647 &milliseconds, &func))
1648 return NULL;
1649 if (!PyCallable_Check(func)) {
1650 PyErr_SetString(PyExc_TypeError, "bad argument list");
1651 return NULL;
1653 v = Tktt_New(func);
1654 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
1655 (ClientData)v);
1657 return (PyObject *) v;
1661 /** Event Loop **/
1663 static PyObject *
1664 Tkapp_MainLoop(PyObject *self, PyObject *args)
1666 int threshold = 0;
1667 #ifdef WITH_THREAD
1668 PyThreadState *tstate = PyThreadState_Get();
1669 #endif
1671 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
1672 return NULL;
1674 quitMainLoop = 0;
1675 while (Tk_GetNumMainWindows() > threshold &&
1676 !quitMainLoop &&
1677 !errorInCmd)
1679 int result;
1681 #ifdef WITH_THREAD
1682 Py_BEGIN_ALLOW_THREADS
1683 PyThread_acquire_lock(tcl_lock, 1);
1684 tcl_tstate = tstate;
1685 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
1686 tcl_tstate = NULL;
1687 PyThread_release_lock(tcl_lock);
1688 if (result == 0)
1689 Sleep(20);
1690 Py_END_ALLOW_THREADS
1691 #else
1692 result = Tcl_DoOneEvent(0);
1693 #endif
1695 if (PyErr_CheckSignals() != 0)
1696 return NULL;
1697 if (result < 0)
1698 break;
1700 quitMainLoop = 0;
1702 if (errorInCmd) {
1703 errorInCmd = 0;
1704 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
1705 excInCmd = valInCmd = trbInCmd = NULL;
1706 return NULL;
1708 Py_INCREF(Py_None);
1709 return Py_None;
1712 static PyObject *
1713 Tkapp_DoOneEvent(PyObject *self, PyObject *args)
1715 int flags = 0;
1716 int rv;
1718 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
1719 return NULL;
1721 ENTER_TCL
1722 rv = Tcl_DoOneEvent(flags);
1723 LEAVE_TCL
1724 return Py_BuildValue("i", rv);
1727 static PyObject *
1728 Tkapp_Quit(PyObject *self, PyObject *args)
1731 if (!PyArg_ParseTuple(args, ":quit"))
1732 return NULL;
1734 quitMainLoop = 1;
1735 Py_INCREF(Py_None);
1736 return Py_None;
1739 static PyObject *
1740 Tkapp_InterpAddr(PyObject *self, PyObject *args)
1743 if (!PyArg_ParseTuple(args, ":interpaddr"))
1744 return NULL;
1746 return PyInt_FromLong((long)Tkapp_Interp(self));
1751 /**** Tkapp Method List ****/
1753 static PyMethodDef Tkapp_methods[] =
1755 {"call", Tkapp_Call, 0},
1756 {"globalcall", Tkapp_GlobalCall, 0},
1757 {"eval", Tkapp_Eval, 1},
1758 {"globaleval", Tkapp_GlobalEval, 1},
1759 {"evalfile", Tkapp_EvalFile, 1},
1760 {"record", Tkapp_Record, 1},
1761 {"adderrorinfo", Tkapp_AddErrorInfo, 1},
1762 {"setvar", Tkapp_SetVar, 1},
1763 {"globalsetvar", Tkapp_GlobalSetVar, 1},
1764 {"getvar", Tkapp_GetVar, 1},
1765 {"globalgetvar", Tkapp_GlobalGetVar, 1},
1766 {"unsetvar", Tkapp_UnsetVar, 1},
1767 {"globalunsetvar", Tkapp_GlobalUnsetVar, 1},
1768 {"getint", Tkapp_GetInt, 1},
1769 {"getdouble", Tkapp_GetDouble, 1},
1770 {"getboolean", Tkapp_GetBoolean, 1},
1771 {"exprstring", Tkapp_ExprString, 1},
1772 {"exprlong", Tkapp_ExprLong, 1},
1773 {"exprdouble", Tkapp_ExprDouble, 1},
1774 {"exprboolean", Tkapp_ExprBoolean, 1},
1775 {"splitlist", Tkapp_SplitList, 1},
1776 {"split", Tkapp_Split, 1},
1777 {"merge", Tkapp_Merge, 0},
1778 {"createcommand", Tkapp_CreateCommand, 1},
1779 {"deletecommand", Tkapp_DeleteCommand, 1},
1780 #ifdef HAVE_CREATEFILEHANDLER
1781 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1782 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
1783 #endif
1784 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
1785 {"mainloop", Tkapp_MainLoop, 1},
1786 {"dooneevent", Tkapp_DoOneEvent, 1},
1787 {"quit", Tkapp_Quit, 1},
1788 {"interpaddr", Tkapp_InterpAddr, 1},
1789 {NULL, NULL}
1794 /**** Tkapp Type Methods ****/
1796 static void
1797 Tkapp_Dealloc(PyObject *self)
1799 ENTER_TCL
1800 Tcl_DeleteInterp(Tkapp_Interp(self));
1801 LEAVE_TCL
1802 PyObject_Del(self);
1803 DisableEventHook();
1806 static PyObject *
1807 Tkapp_GetAttr(PyObject *self, char *name)
1809 return Py_FindMethod(Tkapp_methods, self, name);
1812 static PyTypeObject Tkapp_Type =
1814 PyObject_HEAD_INIT(NULL)
1815 0, /*ob_size */
1816 "tkapp", /*tp_name */
1817 sizeof(TkappObject), /*tp_basicsize */
1818 0, /*tp_itemsize */
1819 Tkapp_Dealloc, /*tp_dealloc */
1820 0, /*tp_print */
1821 Tkapp_GetAttr, /*tp_getattr */
1822 0, /*tp_setattr */
1823 0, /*tp_compare */
1824 0, /*tp_repr */
1825 0, /*tp_as_number */
1826 0, /*tp_as_sequence */
1827 0, /*tp_as_mapping */
1828 0, /*tp_hash */
1833 /**** Tkinter Module ****/
1835 typedef struct {
1836 PyObject* tuple;
1837 int size; /* current size */
1838 int maxsize; /* allocated size */
1839 } FlattenContext;
1841 static int
1842 _bump(FlattenContext* context, int size)
1844 /* expand tuple to hold (at least) size new items.
1845 return true if successful, false if an exception was raised */
1847 int maxsize = context->maxsize * 2;
1849 if (maxsize < context->size + size)
1850 maxsize = context->size + size;
1852 context->maxsize = maxsize;
1854 return _PyTuple_Resize(&context->tuple, maxsize, 0) >= 0;
1857 static int
1858 _flatten1(FlattenContext* context, PyObject* item, int depth)
1860 /* add tuple or list to argument tuple (recursively) */
1862 int i, size;
1864 if (depth > 1000) {
1865 PyErr_SetString(PyExc_ValueError,
1866 "nesting too deep in _flatten");
1867 return 0;
1868 } else if (PyList_Check(item)) {
1869 size = PyList_GET_SIZE(item);
1870 /* preallocate (assume no nesting) */
1871 if (context->size + size > context->maxsize &&
1872 !_bump(context, size))
1873 return 0;
1874 /* copy items to output tuple */
1875 for (i = 0; i < size; i++) {
1876 PyObject *o = PyList_GET_ITEM(item, i);
1877 if (PyList_Check(o) || PyTuple_Check(o)) {
1878 if (!_flatten1(context, o, depth + 1))
1879 return 0;
1880 } else if (o != Py_None) {
1881 if (context->size + 1 > context->maxsize &&
1882 !_bump(context, 1))
1883 return 0;
1884 Py_INCREF(o);
1885 PyTuple_SET_ITEM(context->tuple,
1886 context->size++, o);
1889 } else if (PyTuple_Check(item)) {
1890 /* same, for tuples */
1891 size = PyTuple_GET_SIZE(item);
1892 if (context->size + size > context->maxsize &&
1893 !_bump(context, size))
1894 return 0;
1895 for (i = 0; i < size; i++) {
1896 PyObject *o = PyTuple_GET_ITEM(item, i);
1897 if (PyList_Check(o) || PyTuple_Check(o)) {
1898 if (!_flatten1(context, o, depth + 1))
1899 return 0;
1900 } else if (o != Py_None) {
1901 if (context->size + 1 > context->maxsize &&
1902 !_bump(context, 1))
1903 return 0;
1904 Py_INCREF(o);
1905 PyTuple_SET_ITEM(context->tuple,
1906 context->size++, o);
1909 } else {
1910 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
1911 return 0;
1913 return 1;
1916 static PyObject *
1917 Tkinter_Flatten(PyObject* self, PyObject* args)
1919 FlattenContext context;
1920 PyObject* item;
1922 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
1923 return NULL;
1925 context.maxsize = PySequence_Size(item);
1926 if (context.maxsize <= 0)
1927 return PyTuple_New(0);
1929 context.tuple = PyTuple_New(context.maxsize);
1930 if (!context.tuple)
1931 return NULL;
1933 context.size = 0;
1935 if (!_flatten1(&context, item,0))
1936 return NULL;
1938 if (_PyTuple_Resize(&context.tuple, context.size, 0))
1939 return NULL;
1941 return context.tuple;
1944 static PyObject *
1945 Tkinter_Create(PyObject *self, PyObject *args)
1947 char *screenName = NULL;
1948 char *baseName = NULL;
1949 char *className = NULL;
1950 int interactive = 0;
1952 baseName = strrchr(Py_GetProgramName(), '/');
1953 if (baseName != NULL)
1954 baseName++;
1955 else
1956 baseName = Py_GetProgramName();
1957 className = "Tk";
1959 if (!PyArg_ParseTuple(args, "|zssi:create",
1960 &screenName, &baseName, &className,
1961 &interactive))
1962 return NULL;
1964 return (PyObject *) Tkapp_New(screenName, baseName, className,
1965 interactive);
1968 static PyMethodDef moduleMethods[] =
1970 {"_flatten", Tkinter_Flatten, 1},
1971 {"create", Tkinter_Create, 1},
1972 #ifdef HAVE_CREATEFILEHANDLER
1973 {"createfilehandler", Tkapp_CreateFileHandler, 1},
1974 {"deletefilehandler", Tkapp_DeleteFileHandler, 1},
1975 #endif
1976 {"createtimerhandler", Tkapp_CreateTimerHandler, 1},
1977 {"mainloop", Tkapp_MainLoop, 1},
1978 {"dooneevent", Tkapp_DoOneEvent, 1},
1979 {"quit", Tkapp_Quit, 1},
1980 {NULL, NULL}
1983 #ifdef WAIT_FOR_STDIN
1985 static int stdin_ready = 0;
1987 #ifndef MS_WINDOWS
1988 static void
1989 MyFileProc(void *clientData, int mask)
1991 stdin_ready = 1;
1993 #endif
1995 static PyThreadState *event_tstate = NULL;
1997 static int
1998 EventHook(void)
2000 #ifndef MS_WINDOWS
2001 int tfile;
2002 #endif
2003 #ifdef WITH_THREAD
2004 PyEval_RestoreThread(event_tstate);
2005 #endif
2006 stdin_ready = 0;
2007 errorInCmd = 0;
2008 #ifndef MS_WINDOWS
2009 tfile = fileno(stdin);
2010 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
2011 #endif
2012 while (!errorInCmd && !stdin_ready) {
2013 int result;
2014 #ifdef MS_WINDOWS
2015 if (_kbhit()) {
2016 stdin_ready = 1;
2017 break;
2019 #endif
2020 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
2021 Py_BEGIN_ALLOW_THREADS
2022 PyThread_acquire_lock(tcl_lock, 1);
2023 tcl_tstate = event_tstate;
2025 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2027 tcl_tstate = NULL;
2028 PyThread_release_lock(tcl_lock);
2029 if (result == 0)
2030 Sleep(20);
2031 Py_END_ALLOW_THREADS
2032 #else
2033 result = Tcl_DoOneEvent(0);
2034 #endif
2036 if (result < 0)
2037 break;
2039 #ifndef MS_WINDOWS
2040 Tcl_DeleteFileHandler(tfile);
2041 #endif
2042 if (errorInCmd) {
2043 errorInCmd = 0;
2044 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2045 excInCmd = valInCmd = trbInCmd = NULL;
2046 PyErr_Print();
2048 #ifdef WITH_THREAD
2049 PyEval_SaveThread();
2050 #endif
2051 return 0;
2054 #endif
2056 static void
2057 EnableEventHook(void)
2059 #ifdef WAIT_FOR_STDIN
2060 if (PyOS_InputHook == NULL) {
2061 #ifdef WITH_THREAD
2062 event_tstate = PyThreadState_Get();
2063 #endif
2064 PyOS_InputHook = EventHook;
2066 #endif
2069 static void
2070 DisableEventHook(void)
2072 #ifdef WAIT_FOR_STDIN
2073 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
2074 PyOS_InputHook = NULL;
2076 #endif
2080 /* all errors will be checked in one fell swoop in init_tkinter() */
2081 static void
2082 ins_long(PyObject *d, char *name, long val)
2084 PyObject *v = PyInt_FromLong(val);
2085 if (v) {
2086 PyDict_SetItemString(d, name, v);
2087 Py_DECREF(v);
2090 static void
2091 ins_string(PyObject *d, char *name, char *val)
2093 PyObject *v = PyString_FromString(val);
2094 if (v) {
2095 PyDict_SetItemString(d, name, v);
2096 Py_DECREF(v);
2101 DL_EXPORT(void)
2102 init_tkinter(void)
2104 PyObject *m, *d;
2106 Tkapp_Type.ob_type = &PyType_Type;
2108 #ifdef WITH_THREAD
2109 tcl_lock = PyThread_allocate_lock();
2110 #endif
2112 m = Py_InitModule("_tkinter", moduleMethods);
2114 d = PyModule_GetDict(m);
2115 Tkinter_TclError = Py_BuildValue("s", "TclError");
2116 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
2118 ins_long(d, "READABLE", TCL_READABLE);
2119 ins_long(d, "WRITABLE", TCL_WRITABLE);
2120 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
2121 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
2122 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
2123 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
2124 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
2125 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
2126 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
2127 ins_string(d, "TK_VERSION", TK_VERSION);
2128 ins_string(d, "TCL_VERSION", TCL_VERSION);
2130 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
2132 Tktt_Type.ob_type = &PyType_Type;
2133 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
2135 /* This helps the dynamic loader; in Unicode aware Tcl versions
2136 it also helps Tcl find its encodings. */
2137 Tcl_FindExecutable(Py_GetProgramName());
2139 if (PyErr_Occurred())
2140 return;
2142 #if 0
2143 /* This was not a good idea; through <Destroy> bindings,
2144 Tcl_Finalize() may invoke Python code but at that point the
2145 interpreter and thread state have already been destroyed! */
2146 Py_AtExit(Tcl_Finalize);
2147 #endif
2149 #ifdef macintosh
2151 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2152 ** Most of the initializations in that routine (toolbox init calls and
2153 ** such) have already been done for us, so we only need these.
2155 tcl_macQdPtr = &qd;
2157 Tcl_MacSetEventProc(PyMacConvertEvent);
2158 #if GENERATINGCFM
2159 mac_addlibresources();
2160 #endif /* GENERATINGCFM */
2161 #endif /* macintosh */
2166 #ifdef macintosh
2169 ** Anyone who embeds Tcl/Tk on the Mac must define panic().
2172 void
2173 panic(char * format, ...)
2175 va_list varg;
2177 va_start(varg, format);
2179 vfprintf(stderr, format, varg);
2180 (void) fflush(stderr);
2182 va_end(varg);
2184 Py_FatalError("Tcl/Tk panic");
2188 ** Pass events to SIOUX before passing them to Tk.
2191 static int
2192 PyMacConvertEvent(EventRecord *eventPtr)
2194 WindowPtr frontwin;
2196 ** Sioux eats too many events, so we don't pass it everything. We
2197 ** always pass update events to Sioux, and we only pass other events if
2198 ** the Sioux window is frontmost. This means that Tk menus don't work
2199 ** in that case, but at least we can scroll the sioux window.
2200 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2201 ** part of the external interface of Sioux...
2203 frontwin = FrontWindow();
2204 if ( eventPtr->what == updateEvt || SIOUXIsAppWindow(frontwin) ) {
2205 if (SIOUXHandleOneEvent(eventPtr))
2206 return 0; /* Nothing happened to the Tcl event queue */
2208 return TkMacConvertEvent(eventPtr);
2211 #if GENERATINGCFM
2214 ** Additional Mac specific code for dealing with shared libraries.
2217 #include <Resources.h>
2218 #include <CodeFragments.h>
2220 static int loaded_from_shlib = 0;
2221 static FSSpec library_fss;
2224 ** If this module is dynamically loaded the following routine should
2225 ** be the init routine. It takes care of adding the shared library to
2226 ** the resource-file chain, so that the tk routines can find their
2227 ** resources.
2229 OSErr pascal
2230 init_tkinter_shlib(CFragInitBlockPtr data)
2232 __initialize();
2233 if ( data == nil ) return noErr;
2234 if ( data->fragLocator.where == kDataForkCFragLocator ) {
2235 library_fss = *data->fragLocator.u.onDisk.fileSpec;
2236 loaded_from_shlib = 1;
2237 } else if ( data->fragLocator.where == kResourceCFragLocator ) {
2238 library_fss = *data->fragLocator.u.inSegs.fileSpec;
2239 loaded_from_shlib = 1;
2241 return noErr;
2245 ** Insert the library resources into the search path. Put them after
2246 ** the resources from the application. Again, we ignore errors.
2248 static
2249 mac_addlibresources(void)
2251 if ( !loaded_from_shlib )
2252 return;
2253 (void)FSpOpenResFile(&library_fss, fsRdPerm);
2256 #endif /* GENERATINGCFM */
2257 #endif /* macintosh */