1 /***********************************************************
2 Copyright (C) 1994 Steen Lumholt.
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
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).
47 #define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
49 #if TKMAJORMINOR < 8000
50 #error "Tk older than 8.0 not supported"
53 #if defined(macintosh)
54 /* Sigh, we have to include this to get at the tcl qd pointer */
56 /* And this one we need to clear the menu bar */
60 #if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
61 #define HAVE_CREATEFILEHANDLER
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. */
72 #define FHANDLETYPE TCL_WIN_SOCKET
74 #define FHANDLETYPE TCL_UNIX_FD
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
84 #endif /* HAVE_CREATEFILEHANDLER */
88 #define WAIT_FOR_STDIN
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
;
136 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
137 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
140 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
142 #define ENTER_OVERLAP \
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; }
160 #define ENTER_OVERLAP
161 #define LEAVE_OVERLAP_TCL
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__)
190 extern int SIOUXIsAppWindow(WindowPtr
);
192 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
195 #endif /* macintosh */
198 #define FREECAST (char *)
201 /**** Tkapp Object Declaration ****/
203 staticforward PyTypeObject Tkapp_Type
;
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
;
231 Tkinter_Error(PyObject
*v
)
233 PyErr_SetString(Tkinter_TclError
, Tkapp_Result(v
));
244 /* Millisecond sleep() for Unix platforms. */
249 /* XXX Too bad if you don't have select(). */
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 */
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
);
268 if (PyList_Append(tmp
, v
) != 0) {
273 return PyString_AsString(v
);
276 PyObject
*v
= PyObject_Str(value
);
279 if (PyList_Append(tmp
, v
) != 0) {
284 return PyString_AsString(v
);
293 Merge(PyObject
*args
)
295 PyObject
*tmp
= NULL
;
296 char *argvStore
[ARGSZ
];
300 int argc
= 0, fvc
= 0, i
;
303 if (!(tmp
= PyList_New(0)))
312 else if (!PyTuple_Check(args
)) {
315 if (!(argv
[0] = AsString(args
, tmp
)))
319 argc
= PyTuple_Size(args
);
322 argv
= (char **)ckalloc(argc
* sizeof(char *));
323 fv
= (int *)ckalloc(argc
* sizeof(int));
324 if (argv
== NULL
|| fv
== NULL
) {
330 for (i
= 0; i
< argc
; i
++) {
331 PyObject
*v
= PyTuple_GetItem(args
, i
);
332 if (PyTuple_Check(v
)) {
334 if (!(argv
[i
] = Merge(v
)))
338 else if (v
== Py_None
) {
344 if (!(argv
[i
] = AsString(v
, tmp
)))
350 res
= Tcl_Merge(argc
, argv
);
352 PyErr_SetString(Tkinter_TclError
, "merge failed");
355 for (i
= 0; i
< fvc
; i
++)
359 if (argv
!= argvStore
)
360 ckfree(FREECAST argv
);
382 if (Tcl_SplitList((Tcl_Interp
*)NULL
, list
, &argc
, &argv
) != TCL_OK
) {
384 * Could be a quoted string containing funnies, e.g. {"}.
385 * Return the string itself.
387 return PyString_FromString(list
);
391 v
= PyString_FromString("");
393 v
= PyString_FromString(argv
[0]);
394 else if ((v
= PyTuple_New(argc
)) != NULL
) {
398 for (i
= 0; i
< argc
; i
++) {
399 if ((w
= Split(argv
[i
])) == NULL
) {
404 PyTuple_SetItem(v
, i
, w
);
407 Tcl_Free(FREECAST argv
);
413 /**** Tkapp Object ****/
417 Tcl_AppInit(Tcl_Interp
*interp
)
421 main
= Tk_MainWindow(interp
);
422 if (Tcl_Init(interp
) == TCL_ERROR
) {
423 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp
));
426 if (Tk_Init(interp
) == TCL_ERROR
) {
427 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp
));
432 #endif /* !WITH_APPINIT */
437 /* Initialize the Tk application; see the `main' function in
441 static void EnableEventHook(void); /* Forward */
442 static void DisableEventHook(void); /* Forward */
445 Tkapp_New(char *screenName
, char *baseName
, char *className
, int interactive
)
450 v
= PyObject_New(TkappObject
, &Tkapp_Type
);
454 v
->interp
= Tcl_CreateInterp();
456 #if defined(macintosh)
457 /* This seems to be needed */
459 TkMacInitMenus(v
->interp
);
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
);
469 Tcl_SetVar(v
->interp
, "tcl_interactive", "1", TCL_GLOBAL_ONLY
);
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);
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
);
487 if (Tcl_AppInit(v
->interp
) != TCL_OK
)
488 return (TkappObject
*)Tkinter_Error((PyObject
*)v
);
499 #if TKMAJORMINOR >= 8001
500 #define USING_OBJECTS
506 AsObj(PyObject
*value
)
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
*));
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
);
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
);
535 result
= Tcl_NewStringObj(PyString_AS_STRING(utf8
),
536 PyString_GET_SIZE(utf8
));
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");
547 return Tcl_NewUnicodeObj(PyUnicode_AS_UNICODE(value
),
548 PyUnicode_GET_SIZE(value
));
549 #endif /* TKMAJORMINOR > 8001 */
552 PyObject
*v
= PyObject_Str(value
);
562 Tkapp_Call(PyObject
*self
, PyObject
*args
)
564 Tcl_Obj
*objStore
[ARGSZ
];
565 Tcl_Obj
**objv
= NULL
;
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
;
577 else if (!PyTuple_Check(args
)) {
578 objv
[0] = AsObj(args
);
582 Tcl_IncrRefCount(objv
[0]);
585 objc
= PyTuple_Size(args
);
588 objv
= (Tcl_Obj
**)ckalloc(objc
* sizeof(char *));
596 for (i
= 0; i
< objc
; i
++) {
597 PyObject
*v
= PyTuple_GetItem(args
, i
);
604 /* Reset objc, so it attempts to clear
605 objects only up to i. */
609 Tcl_IncrRefCount(objv
[i
]);
615 i
= Tcl_EvalObjv(interp
, objc
, objv
, flags
);
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
);
625 /* If the result contains any bytes with the top bit set,
626 it's UTF-8 and we should decode it to Unicode */
633 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
635 /* Convert UTF-8 to Unicode string */
637 res
= PyUnicode_DecodeUTF8(s
, (int)(p
-s
), "strict");
640 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
648 for (i
= 0; i
< objc
; i
++)
649 Tcl_DecrRefCount(objv
[i
]);
650 if (objv
!= objStore
)
651 ckfree(FREECAST objv
);
655 #else /* !USING_OBJECTS */
658 Tkapp_Call(PyObject
*self
, PyObject
*args
)
660 /* This is copied from Merge() */
661 PyObject
*tmp
= NULL
;
662 char *argvStore
[ARGSZ
];
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)))
680 else if (!PyTuple_Check(args
)) {
683 if (!(argv
[0] = AsString(args
, tmp
)))
687 argc
= PyTuple_Size(args
);
690 argv
= (char **)ckalloc(argc
* sizeof(char *));
691 fv
= (int *)ckalloc(argc
* sizeof(int));
692 if (argv
== NULL
|| fv
== NULL
) {
698 for (i
= 0; i
< argc
; i
++) {
699 PyObject
*v
= PyTuple_GetItem(args
, i
);
700 if (PyTuple_Check(v
)) {
702 if (!(argv
[i
] = Merge(v
)))
706 else if (v
== Py_None
) {
712 if (!(argv
[i
] = AsString(v
, tmp
)))
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
]);
729 !Tcl_GetCommandInfo(interp
, argv
[0], &info
) ||
733 cmd
= Tcl_Merge(argc
, argv
);
734 i
= Tcl_Eval(interp
, cmd
);
738 Tcl_ResetResult(interp
);
739 i
= (*info
.proc
)(info
.clientData
, interp
, argc
, argv
);
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
));
751 if (Py_VerboseFlag
>= 2)
752 PySys_WriteStderr("-> '%s'\n", Tcl_GetStringResult(interp
));
753 res
= PyString_FromString(Tcl_GetStringResult(interp
));
757 /* Copied from Merge() again */
759 for (i
= 0; i
< fvc
; i
++)
763 if (argv
!= argvStore
)
764 ckfree(FREECAST argv
);
772 #endif /* !USING_OBJECTS */
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
784 PyObject
*res
= NULL
;
790 err
= Tcl_GlobalEval(Tkapp_Interp(self
), cmd
);
792 if (err
== TCL_ERROR
)
793 res
= Tkinter_Error(self
);
795 res
= PyString_FromString(Tkapp_Result(self
));
804 Tkapp_Eval(PyObject
*self
, PyObject
*args
)
807 PyObject
*res
= NULL
;
810 if (!PyArg_ParseTuple(args
, "s:eval", &script
))
814 err
= Tcl_Eval(Tkapp_Interp(self
), script
);
816 if (err
== TCL_ERROR
)
817 res
= Tkinter_Error(self
);
819 res
= PyString_FromString(Tkapp_Result(self
));
825 Tkapp_GlobalEval(PyObject
*self
, PyObject
*args
)
828 PyObject
*res
= NULL
;
831 if (!PyArg_ParseTuple(args
, "s:globaleval", &script
))
835 err
= Tcl_GlobalEval(Tkapp_Interp(self
), script
);
837 if (err
== TCL_ERROR
)
838 res
= Tkinter_Error(self
);
840 res
= PyString_FromString(Tkapp_Result(self
));
846 Tkapp_EvalFile(PyObject
*self
, PyObject
*args
)
849 PyObject
*res
= NULL
;
852 if (!PyArg_ParseTuple(args
, "s:evalfile", &fileName
))
856 err
= Tcl_EvalFile(Tkapp_Interp(self
), fileName
);
858 if (err
== TCL_ERROR
)
859 res
= Tkinter_Error(self
);
862 res
= PyString_FromString(Tkapp_Result(self
));
868 Tkapp_Record(PyObject
*self
, PyObject
*args
)
871 PyObject
*res
= NULL
;
874 if (!PyArg_ParseTuple(args
, "s", &script
))
878 err
= Tcl_RecordAndEval(Tkapp_Interp(self
), script
, TCL_NO_EVAL
);
880 if (err
== TCL_ERROR
)
881 res
= Tkinter_Error(self
);
883 res
= PyString_FromString(Tkapp_Result(self
));
889 Tkapp_AddErrorInfo(PyObject
*self
, PyObject
*args
)
893 if (!PyArg_ParseTuple(args
, "s:adderrorinfo", &msg
))
896 Tcl_AddErrorInfo(Tkapp_Interp(self
), msg
);
908 SetVar(PyObject
*self
, PyObject
*args
, int flags
)
910 char *name1
, *name2
, *ok
, *s
;
918 if (PyArg_ParseTuple(args
, "sO:setvar", &name1
, &newValue
)) {
920 s
= AsString(newValue
, tmp
);
924 ok
= Tcl_SetVar(Tkapp_Interp(self
), name1
, s
, flags
);
929 if (PyArg_ParseTuple(args
, "ssO:setvar",
930 &name1
, &name2
, &newValue
)) {
931 s
= AsString(newValue
, tmp
);
935 ok
= Tcl_SetVar2(Tkapp_Interp(self
), name1
, name2
,
947 return Tkinter_Error(self
);
954 Tkapp_SetVar(PyObject
*self
, PyObject
*args
)
956 return SetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
960 Tkapp_GlobalSetVar(PyObject
*self
, PyObject
*args
)
962 return SetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
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
))
977 s
= Tcl_GetVar(Tkapp_Interp(self
), name1
, flags
);
980 s
= Tcl_GetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
984 res
= Tkinter_Error(self
);
986 res
= PyString_FromString(s
);
992 Tkapp_GetVar(PyObject
*self
, PyObject
*args
)
994 return GetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
998 Tkapp_GlobalGetVar(PyObject
*self
, PyObject
*args
)
1000 return GetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1006 UnsetVar(PyObject
*self
, PyObject
*args
, int flags
)
1008 char *name1
, *name2
=NULL
;
1009 PyObject
*res
= NULL
;
1012 if (!PyArg_ParseTuple(args
, "s|s:unsetvar", &name1
, &name2
))
1016 code
= Tcl_UnsetVar(Tkapp_Interp(self
), name1
, flags
);
1019 code
= Tcl_UnsetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
1022 if (code
== TCL_ERROR
)
1023 res
= Tkinter_Error(self
);
1033 Tkapp_UnsetVar(PyObject
*self
, PyObject
*args
)
1035 return UnsetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
1039 Tkapp_GlobalUnsetVar(PyObject
*self
, PyObject
*args
)
1041 return UnsetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1046 /** Tcl to Python **/
1049 Tkapp_GetInt(PyObject
*self
, PyObject
*args
)
1054 if (!PyArg_ParseTuple(args
, "s:getint", &s
))
1056 if (Tcl_GetInt(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1057 return Tkinter_Error(self
);
1058 return Py_BuildValue("i", v
);
1062 Tkapp_GetDouble(PyObject
*self
, PyObject
*args
)
1067 if (!PyArg_ParseTuple(args
, "s:getdouble", &s
))
1069 if (Tcl_GetDouble(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1070 return Tkinter_Error(self
);
1071 return Py_BuildValue("d", v
);
1075 Tkapp_GetBoolean(PyObject
*self
, PyObject
*args
)
1080 if (!PyArg_ParseTuple(args
, "s:getboolean", &s
))
1082 if (Tcl_GetBoolean(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1083 return Tkinter_Error(self
);
1084 return Py_BuildValue("i", v
);
1088 Tkapp_ExprString(PyObject
*self
, PyObject
*args
)
1091 PyObject
*res
= NULL
;
1094 if (!PyArg_ParseTuple(args
, "s:exprstring", &s
))
1097 retval
= Tcl_ExprString(Tkapp_Interp(self
), s
);
1099 if (retval
== TCL_ERROR
)
1100 res
= Tkinter_Error(self
);
1102 res
= Py_BuildValue("s", Tkapp_Result(self
));
1108 Tkapp_ExprLong(PyObject
*self
, PyObject
*args
)
1111 PyObject
*res
= NULL
;
1115 if (!PyArg_ParseTuple(args
, "s:exprlong", &s
))
1118 retval
= Tcl_ExprLong(Tkapp_Interp(self
), s
, &v
);
1120 if (retval
== TCL_ERROR
)
1121 res
= Tkinter_Error(self
);
1123 res
= Py_BuildValue("l", v
);
1129 Tkapp_ExprDouble(PyObject
*self
, PyObject
*args
)
1132 PyObject
*res
= NULL
;
1136 if (!PyArg_ParseTuple(args
, "s:exprdouble", &s
))
1138 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1140 retval
= Tcl_ExprDouble(Tkapp_Interp(self
), s
, &v
);
1142 PyFPE_END_PROTECT(retval
)
1143 if (retval
== TCL_ERROR
)
1144 res
= Tkinter_Error(self
);
1146 res
= Py_BuildValue("d", v
);
1152 Tkapp_ExprBoolean(PyObject
*self
, PyObject
*args
)
1155 PyObject
*res
= NULL
;
1159 if (!PyArg_ParseTuple(args
, "s:exprboolean", &s
))
1162 retval
= Tcl_ExprBoolean(Tkapp_Interp(self
), s
, &v
);
1164 if (retval
== TCL_ERROR
)
1165 res
= Tkinter_Error(self
);
1167 res
= Py_BuildValue("i", v
);
1175 Tkapp_SplitList(PyObject
*self
, PyObject
*args
)
1183 if (!PyArg_ParseTuple(args
, "s:splitlist", &list
))
1186 if (Tcl_SplitList(Tkapp_Interp(self
), list
, &argc
, &argv
) == TCL_ERROR
)
1187 return Tkinter_Error(self
);
1189 if (!(v
= PyTuple_New(argc
)))
1192 for (i
= 0; i
< argc
; i
++) {
1193 PyObject
*s
= PyString_FromString(argv
[i
]);
1194 if (!s
|| PyTuple_SetItem(v
, i
, s
)) {
1202 ckfree(FREECAST argv
);
1207 Tkapp_Split(PyObject
*self
, PyObject
*args
)
1211 if (!PyArg_ParseTuple(args
, "s:split", &list
))
1217 Tkapp_Merge(PyObject
*self
, PyObject
*args
)
1219 char *s
= Merge(args
);
1220 PyObject
*res
= NULL
;
1223 res
= PyString_FromString(s
);
1234 /* Client data struct */
1238 } PythonCmd_ClientData
;
1241 PythonCmd_Error(Tcl_Interp
*interp
)
1244 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1249 /* This is the Tcl command that acts as a wrapper for Python
1250 * function or method.
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
;
1262 /* TBD: no error checking here since we know, via the
1263 * Tkapp_CreateCommand() that the client data is a two-tuple
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
)) {
1276 return PythonCmd_Error(interp
);
1279 res
= PyEval_CallObject(func
, arg
);
1283 return PythonCmd_Error(interp
);
1285 if (!(tmp
= PyList_New(0))) {
1287 return PythonCmd_Error(interp
);
1290 s
= AsString(res
, tmp
);
1292 rv
= PythonCmd_Error(interp
);
1295 Tcl_SetResult(Tkapp_Interp(self
), s
, TCL_VOLATILE
);
1308 PythonCmdDelete(ClientData clientData
)
1310 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1313 Py_XDECREF(data
->self
);
1314 Py_XDECREF(data
->func
);
1322 Tkapp_CreateCommand(PyObject
*self
, PyObject
*args
)
1324 PythonCmd_ClientData
*data
;
1329 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
1331 if (!PyCallable_Check(func
)) {
1332 PyErr_SetString(PyExc_TypeError
, "command not callable");
1336 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
1345 err
= Tcl_CreateCommand(Tkapp_Interp(self
), cmdName
, PythonCmd
,
1346 (ClientData
)data
, PythonCmdDelete
);
1349 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
1361 Tkapp_DeleteCommand(PyObject
*self
, PyObject
*args
)
1366 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
1369 err
= Tcl_DeleteCommand(Tkapp_Interp(self
), cmdName
);
1372 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
1381 #ifdef HAVE_CREATEFILEHANDLER
1382 /** File Handler **/
1384 typedef struct _fhcdata
{
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);
1413 FileHandler_ClientData
*p
, **pp
;
1416 while ((p
= *pp
) != NULL
) {
1419 Py_XDECREF(p
->func
);
1420 Py_XDECREF(p
->file
);
1429 FileHandler(ClientData clientData
, int mask
)
1431 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
1432 PyObject
*func
, *file
, *arg
, *res
;
1438 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
1439 res
= PyEval_CallObject(func
, arg
);
1444 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1451 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
1452 /* args is (file, mask, func) */
1454 FileHandler_ClientData
*data
;
1455 PyObject
*file
, *func
;
1458 if (!PyArg_ParseTuple(args
, "OiO:createfilehandler",
1459 &file
, &mask
, &func
))
1461 tfile
= PyObject_AsFileDescriptor(file
);
1464 if (!PyCallable_Check(func
)) {
1465 PyErr_SetString(PyExc_TypeError
, "bad argument list");
1469 data
= NewFHCD(func
, file
, tfile
);
1473 /* Ought to check for null Tcl_File object... */
1475 Tcl_CreateFileHandler(tfile
, mask
, FileHandler
, (ClientData
) data
);
1482 Tkapp_DeleteFileHandler(PyObject
*self
, PyObject
*args
)
1487 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
1489 tfile
= PyObject_AsFileDescriptor(file
);
1495 /* Ought to check for null Tcl_File object... */
1497 Tcl_DeleteFileHandler(tfile
);
1502 #endif /* HAVE_CREATEFILEHANDLER */
1505 /**** Tktt Object (timer token) ****/
1507 staticforward PyTypeObject Tktt_Type
;
1511 Tcl_TimerToken token
;
1516 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
1518 TkttObject
*v
= (TkttObject
*)self
;
1519 PyObject
*func
= v
->func
;
1521 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
1523 if (v
->token
!= NULL
) {
1524 Tcl_DeleteTimerHandler(v
->token
);
1530 Py_DECREF(v
); /* See Tktt_New() */
1536 static PyMethodDef Tktt_methods
[] =
1538 {"deletetimerhandler", Tktt_DeleteTimerHandler
, 1},
1543 Tktt_New(PyObject
*func
)
1547 v
= PyObject_New(TkttObject
, &Tktt_Type
);
1555 /* Extra reference, deleted when called or when handler is deleted */
1561 Tktt_Dealloc(PyObject
*self
)
1563 TkttObject
*v
= (TkttObject
*)self
;
1564 PyObject
*func
= v
->func
;
1572 Tktt_Repr(PyObject
*self
)
1574 TkttObject
*v
= (TkttObject
*)self
;
1577 sprintf(buf
, "<tktimertoken at %p%s>", v
,
1578 v
->func
== NULL
? ", handler deleted" : "");
1579 return PyString_FromString(buf
);
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
)
1592 "tktimertoken", /*tp_name */
1593 sizeof(TkttObject
), /*tp_basicsize */
1595 Tktt_Dealloc
, /*tp_dealloc */
1597 Tktt_GetAttr
, /*tp_getattr */
1600 Tktt_Repr
, /*tp_repr */
1601 0, /*tp_as_number */
1602 0, /*tp_as_sequence */
1603 0, /*tp_as_mapping */
1609 /** Timer Handler **/
1612 TimerHandler(ClientData clientData
)
1614 TkttObject
*v
= (TkttObject
*)clientData
;
1615 PyObject
*func
= v
->func
;
1625 res
= PyEval_CallObject(func
, NULL
);
1627 Py_DECREF(v
); /* See Tktt_New() */
1631 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1640 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
1646 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler",
1647 &milliseconds
, &func
))
1649 if (!PyCallable_Check(func
)) {
1650 PyErr_SetString(PyExc_TypeError
, "bad argument list");
1654 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
1657 return (PyObject
*) v
;
1664 Tkapp_MainLoop(PyObject
*self
, PyObject
*args
)
1668 PyThreadState
*tstate
= PyThreadState_Get();
1671 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
1675 while (Tk_GetNumMainWindows() > threshold
&&
1682 Py_BEGIN_ALLOW_THREADS
1683 PyThread_acquire_lock(tcl_lock
, 1);
1684 tcl_tstate
= tstate
;
1685 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
1687 PyThread_release_lock(tcl_lock
);
1690 Py_END_ALLOW_THREADS
1692 result
= Tcl_DoOneEvent(0);
1695 if (PyErr_CheckSignals() != 0)
1704 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
1705 excInCmd
= valInCmd
= trbInCmd
= NULL
;
1713 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
1718 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
1722 rv
= Tcl_DoOneEvent(flags
);
1724 return Py_BuildValue("i", rv
);
1728 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
1731 if (!PyArg_ParseTuple(args
, ":quit"))
1740 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
1743 if (!PyArg_ParseTuple(args
, ":interpaddr"))
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},
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},
1794 /**** Tkapp Type Methods ****/
1797 Tkapp_Dealloc(PyObject
*self
)
1800 Tcl_DeleteInterp(Tkapp_Interp(self
));
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
)
1816 "tkapp", /*tp_name */
1817 sizeof(TkappObject
), /*tp_basicsize */
1819 Tkapp_Dealloc
, /*tp_dealloc */
1821 Tkapp_GetAttr
, /*tp_getattr */
1825 0, /*tp_as_number */
1826 0, /*tp_as_sequence */
1827 0, /*tp_as_mapping */
1833 /**** Tkinter Module ****/
1837 int size
; /* current size */
1838 int maxsize
; /* allocated size */
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;
1858 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
1860 /* add tuple or list to argument tuple (recursively) */
1865 PyErr_SetString(PyExc_ValueError
,
1866 "nesting too deep in _flatten");
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
))
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))
1880 } else if (o
!= Py_None
) {
1881 if (context
->size
+ 1 > context
->maxsize
&&
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
))
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))
1900 } else if (o
!= Py_None
) {
1901 if (context
->size
+ 1 > context
->maxsize
&&
1905 PyTuple_SET_ITEM(context
->tuple
,
1906 context
->size
++, o
);
1910 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
1917 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
1919 FlattenContext context
;
1922 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
1925 context
.maxsize
= PySequence_Size(item
);
1926 if (context
.maxsize
<= 0)
1927 return PyTuple_New(0);
1929 context
.tuple
= PyTuple_New(context
.maxsize
);
1935 if (!_flatten1(&context
, item
,0))
1938 if (_PyTuple_Resize(&context
.tuple
, context
.size
, 0))
1941 return context
.tuple
;
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
)
1956 baseName
= Py_GetProgramName();
1959 if (!PyArg_ParseTuple(args
, "|zssi:create",
1960 &screenName
, &baseName
, &className
,
1964 return (PyObject
*) Tkapp_New(screenName
, baseName
, className
,
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},
1976 {"createtimerhandler", Tkapp_CreateTimerHandler
, 1},
1977 {"mainloop", Tkapp_MainLoop
, 1},
1978 {"dooneevent", Tkapp_DoOneEvent
, 1},
1979 {"quit", Tkapp_Quit
, 1},
1983 #ifdef WAIT_FOR_STDIN
1985 static int stdin_ready
= 0;
1989 MyFileProc(void *clientData
, int mask
)
1995 static PyThreadState
*event_tstate
= NULL
;
2004 PyEval_RestoreThread(event_tstate
);
2009 tfile
= fileno(stdin
);
2010 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
2012 while (!errorInCmd
&& !stdin_ready
) {
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
);
2028 PyThread_release_lock(tcl_lock
);
2031 Py_END_ALLOW_THREADS
2033 result
= Tcl_DoOneEvent(0);
2040 Tcl_DeleteFileHandler(tfile
);
2044 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2045 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2049 PyEval_SaveThread();
2057 EnableEventHook(void)
2059 #ifdef WAIT_FOR_STDIN
2060 if (PyOS_InputHook
== NULL
) {
2062 event_tstate
= PyThreadState_Get();
2064 PyOS_InputHook
= EventHook
;
2070 DisableEventHook(void)
2072 #ifdef WAIT_FOR_STDIN
2073 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
2074 PyOS_InputHook
= NULL
;
2080 /* all errors will be checked in one fell swoop in init_tkinter() */
2082 ins_long(PyObject
*d
, char *name
, long val
)
2084 PyObject
*v
= PyInt_FromLong(val
);
2086 PyDict_SetItemString(d
, name
, v
);
2091 ins_string(PyObject
*d
, char *name
, char *val
)
2093 PyObject
*v
= PyString_FromString(val
);
2095 PyDict_SetItemString(d
, name
, v
);
2106 Tkapp_Type
.ob_type
= &PyType_Type
;
2109 tcl_lock
= PyThread_allocate_lock();
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())
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
);
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.
2157 Tcl_MacSetEventProc(PyMacConvertEvent
);
2159 mac_addlibresources();
2160 #endif /* GENERATINGCFM */
2161 #endif /* macintosh */
2169 ** Anyone who embeds Tcl/Tk on the Mac must define panic().
2173 panic(char * format
, ...)
2177 va_start(varg
, format
);
2179 vfprintf(stderr
, format
, varg
);
2180 (void) fflush(stderr
);
2184 Py_FatalError("Tcl/Tk panic");
2188 ** Pass events to SIOUX before passing them to Tk.
2192 PyMacConvertEvent(EventRecord
*eventPtr
)
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
);
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
2230 init_tkinter_shlib(CFragInitBlockPtr data
)
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;
2245 ** Insert the library resources into the search path. Put them after
2246 ** the resources from the application. Again, we ignore errors.
2249 mac_addlibresources(void)
2251 if ( !loaded_from_shlib
)
2253 (void)FSpOpenResFile(&library_fss
, fsRdPerm
);
2256 #endif /* GENERATINGCFM */
2257 #endif /* macintosh */