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
)) {
579 objv
[0] = AsObj(args
);
582 Tcl_IncrRefCount(objv
[0]);
585 objc
= PyTuple_Size(args
);
588 objv
= (Tcl_Obj
**)ckalloc(objc
* sizeof(char *));
595 for (i
= 0; i
< objc
; i
++) {
596 PyObject
*v
= PyTuple_GetItem(args
, i
);
604 Tcl_IncrRefCount(objv
[i
]);
610 i
= Tcl_EvalObjv(interp
, objc
, objv
, flags
);
616 /* We could request the object result here, but doing
617 so would confuse applications that expect a string. */
618 char *s
= Tcl_GetStringResult(interp
);
620 /* If the result contains any bytes with the top bit set,
621 it's UTF-8 and we should decode it to Unicode */
628 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
630 /* Convert UTF-8 to Unicode string */
632 res
= PyUnicode_DecodeUTF8(s
, (int)(p
-s
), "strict");
635 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
643 for (i
= 0; i
< objc
; i
++)
644 Tcl_DecrRefCount(objv
[i
]);
645 if (objv
!= objStore
)
646 ckfree(FREECAST objv
);
650 #else /* !USING_OBJECTS */
653 Tkapp_Call(PyObject
*self
, PyObject
*args
)
655 /* This is copied from Merge() */
656 PyObject
*tmp
= NULL
;
657 char *argvStore
[ARGSZ
];
661 int argc
= 0, fvc
= 0, i
;
662 PyObject
*res
= NULL
; /* except this has a different type */
663 Tcl_CmdInfo info
; /* and this is added */
664 Tcl_Interp
*interp
= Tkapp_Interp(self
); /* and this too */
666 if (!(tmp
= PyList_New(0)))
675 else if (!PyTuple_Check(args
)) {
678 if (!(argv
[0] = AsString(args
, tmp
)))
682 argc
= PyTuple_Size(args
);
685 argv
= (char **)ckalloc(argc
* sizeof(char *));
686 fv
= (int *)ckalloc(argc
* sizeof(int));
687 if (argv
== NULL
|| fv
== NULL
) {
693 for (i
= 0; i
< argc
; i
++) {
694 PyObject
*v
= PyTuple_GetItem(args
, i
);
695 if (PyTuple_Check(v
)) {
697 if (!(argv
[i
] = Merge(v
)))
701 else if (v
== Py_None
) {
707 if (!(argv
[i
] = AsString(v
, tmp
)))
713 /* End code copied from Merge() */
715 /* All this to avoid a call to Tcl_Merge() and the corresponding call
716 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
717 if (Py_VerboseFlag
>= 2) {
718 for (i
= 0; i
< argc
; i
++)
719 PySys_WriteStderr("%s ", argv
[i
]);
724 !Tcl_GetCommandInfo(interp
, argv
[0], &info
) ||
728 cmd
= Tcl_Merge(argc
, argv
);
729 i
= Tcl_Eval(interp
, cmd
);
733 Tcl_ResetResult(interp
);
734 i
= (*info
.proc
)(info
.clientData
, interp
, argc
, argv
);
737 if (info
.proc
== NULL
&& Py_VerboseFlag
>= 2)
738 PySys_WriteStderr("... use TclEval ");
739 if (i
== TCL_ERROR
) {
740 if (Py_VerboseFlag
>= 2)
741 PySys_WriteStderr("... error: '%s'\n",
742 Tcl_GetStringResult(interp
));
746 if (Py_VerboseFlag
>= 2)
747 PySys_WriteStderr("-> '%s'\n", Tcl_GetStringResult(interp
));
748 res
= PyString_FromString(Tcl_GetStringResult(interp
));
752 /* Copied from Merge() again */
754 for (i
= 0; i
< fvc
; i
++)
758 if (argv
!= argvStore
)
759 ckfree(FREECAST argv
);
767 #endif /* !USING_OBJECTS */
770 Tkapp_GlobalCall(PyObject
*self
, PyObject
*args
)
772 /* Could do the same here as for Tkapp_Call(), but this is not used
773 much, so I can't be bothered. Unfortunately Tcl doesn't export a
774 way for the user to do what all its Global* variants do (save and
775 reset the scope pointer, call the local version, restore the saved
779 PyObject
*res
= NULL
;
785 err
= Tcl_GlobalEval(Tkapp_Interp(self
), cmd
);
787 if (err
== TCL_ERROR
)
788 res
= Tkinter_Error(self
);
790 res
= PyString_FromString(Tkapp_Result(self
));
799 Tkapp_Eval(PyObject
*self
, PyObject
*args
)
802 PyObject
*res
= NULL
;
805 if (!PyArg_ParseTuple(args
, "s:eval", &script
))
809 err
= Tcl_Eval(Tkapp_Interp(self
), script
);
811 if (err
== TCL_ERROR
)
812 res
= Tkinter_Error(self
);
814 res
= PyString_FromString(Tkapp_Result(self
));
820 Tkapp_GlobalEval(PyObject
*self
, PyObject
*args
)
823 PyObject
*res
= NULL
;
826 if (!PyArg_ParseTuple(args
, "s:globaleval", &script
))
830 err
= Tcl_GlobalEval(Tkapp_Interp(self
), script
);
832 if (err
== TCL_ERROR
)
833 res
= Tkinter_Error(self
);
835 res
= PyString_FromString(Tkapp_Result(self
));
841 Tkapp_EvalFile(PyObject
*self
, PyObject
*args
)
844 PyObject
*res
= NULL
;
847 if (!PyArg_ParseTuple(args
, "s:evalfile", &fileName
))
851 err
= Tcl_EvalFile(Tkapp_Interp(self
), fileName
);
853 if (err
== TCL_ERROR
)
854 res
= Tkinter_Error(self
);
857 res
= PyString_FromString(Tkapp_Result(self
));
863 Tkapp_Record(PyObject
*self
, PyObject
*args
)
866 PyObject
*res
= NULL
;
869 if (!PyArg_ParseTuple(args
, "s", &script
))
873 err
= Tcl_RecordAndEval(Tkapp_Interp(self
), script
, TCL_NO_EVAL
);
875 if (err
== TCL_ERROR
)
876 res
= Tkinter_Error(self
);
878 res
= PyString_FromString(Tkapp_Result(self
));
884 Tkapp_AddErrorInfo(PyObject
*self
, PyObject
*args
)
888 if (!PyArg_ParseTuple(args
, "s:adderrorinfo", &msg
))
891 Tcl_AddErrorInfo(Tkapp_Interp(self
), msg
);
903 SetVar(PyObject
*self
, PyObject
*args
, int flags
)
905 char *name1
, *name2
, *ok
, *s
;
913 if (PyArg_ParseTuple(args
, "sO:setvar", &name1
, &newValue
)) {
915 s
= AsString(newValue
, tmp
);
919 ok
= Tcl_SetVar(Tkapp_Interp(self
), name1
, s
, flags
);
924 if (PyArg_ParseTuple(args
, "ssO:setvar",
925 &name1
, &name2
, &newValue
)) {
926 s
= AsString(newValue
, tmp
);
930 ok
= Tcl_SetVar2(Tkapp_Interp(self
), name1
, name2
,
942 return Tkinter_Error(self
);
949 Tkapp_SetVar(PyObject
*self
, PyObject
*args
)
951 return SetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
955 Tkapp_GlobalSetVar(PyObject
*self
, PyObject
*args
)
957 return SetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
963 GetVar(PyObject
*self
, PyObject
*args
, int flags
)
965 char *name1
, *name2
=NULL
, *s
;
966 PyObject
*res
= NULL
;
968 if (!PyArg_ParseTuple(args
, "s|s:getvar", &name1
, &name2
))
972 s
= Tcl_GetVar(Tkapp_Interp(self
), name1
, flags
);
975 s
= Tcl_GetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
979 res
= Tkinter_Error(self
);
981 res
= PyString_FromString(s
);
987 Tkapp_GetVar(PyObject
*self
, PyObject
*args
)
989 return GetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
993 Tkapp_GlobalGetVar(PyObject
*self
, PyObject
*args
)
995 return GetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1001 UnsetVar(PyObject
*self
, PyObject
*args
, int flags
)
1003 char *name1
, *name2
=NULL
;
1004 PyObject
*res
= NULL
;
1007 if (!PyArg_ParseTuple(args
, "s|s:unsetvar", &name1
, &name2
))
1011 code
= Tcl_UnsetVar(Tkapp_Interp(self
), name1
, flags
);
1014 code
= Tcl_UnsetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
1017 if (code
== TCL_ERROR
)
1018 res
= Tkinter_Error(self
);
1028 Tkapp_UnsetVar(PyObject
*self
, PyObject
*args
)
1030 return UnsetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
1034 Tkapp_GlobalUnsetVar(PyObject
*self
, PyObject
*args
)
1036 return UnsetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1041 /** Tcl to Python **/
1044 Tkapp_GetInt(PyObject
*self
, PyObject
*args
)
1049 if (!PyArg_ParseTuple(args
, "s:getint", &s
))
1051 if (Tcl_GetInt(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1052 return Tkinter_Error(self
);
1053 return Py_BuildValue("i", v
);
1057 Tkapp_GetDouble(PyObject
*self
, PyObject
*args
)
1062 if (!PyArg_ParseTuple(args
, "s:getdouble", &s
))
1064 if (Tcl_GetDouble(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1065 return Tkinter_Error(self
);
1066 return Py_BuildValue("d", v
);
1070 Tkapp_GetBoolean(PyObject
*self
, PyObject
*args
)
1075 if (!PyArg_ParseTuple(args
, "s:getboolean", &s
))
1077 if (Tcl_GetBoolean(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1078 return Tkinter_Error(self
);
1079 return Py_BuildValue("i", v
);
1083 Tkapp_ExprString(PyObject
*self
, PyObject
*args
)
1086 PyObject
*res
= NULL
;
1089 if (!PyArg_ParseTuple(args
, "s:exprstring", &s
))
1092 retval
= Tcl_ExprString(Tkapp_Interp(self
), s
);
1094 if (retval
== TCL_ERROR
)
1095 res
= Tkinter_Error(self
);
1097 res
= Py_BuildValue("s", Tkapp_Result(self
));
1103 Tkapp_ExprLong(PyObject
*self
, PyObject
*args
)
1106 PyObject
*res
= NULL
;
1110 if (!PyArg_ParseTuple(args
, "s:exprlong", &s
))
1113 retval
= Tcl_ExprLong(Tkapp_Interp(self
), s
, &v
);
1115 if (retval
== TCL_ERROR
)
1116 res
= Tkinter_Error(self
);
1118 res
= Py_BuildValue("l", v
);
1124 Tkapp_ExprDouble(PyObject
*self
, PyObject
*args
)
1127 PyObject
*res
= NULL
;
1131 if (!PyArg_ParseTuple(args
, "s:exprdouble", &s
))
1133 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1135 retval
= Tcl_ExprDouble(Tkapp_Interp(self
), s
, &v
);
1137 PyFPE_END_PROTECT(retval
)
1138 if (retval
== TCL_ERROR
)
1139 res
= Tkinter_Error(self
);
1141 res
= Py_BuildValue("d", v
);
1147 Tkapp_ExprBoolean(PyObject
*self
, PyObject
*args
)
1150 PyObject
*res
= NULL
;
1154 if (!PyArg_ParseTuple(args
, "s:exprboolean", &s
))
1157 retval
= Tcl_ExprBoolean(Tkapp_Interp(self
), s
, &v
);
1159 if (retval
== TCL_ERROR
)
1160 res
= Tkinter_Error(self
);
1162 res
= Py_BuildValue("i", v
);
1170 Tkapp_SplitList(PyObject
*self
, PyObject
*args
)
1178 if (!PyArg_ParseTuple(args
, "s:splitlist", &list
))
1181 if (Tcl_SplitList(Tkapp_Interp(self
), list
, &argc
, &argv
) == TCL_ERROR
)
1182 return Tkinter_Error(self
);
1184 if (!(v
= PyTuple_New(argc
)))
1187 for (i
= 0; i
< argc
; i
++) {
1188 PyObject
*s
= PyString_FromString(argv
[i
]);
1189 if (!s
|| PyTuple_SetItem(v
, i
, s
)) {
1197 ckfree(FREECAST argv
);
1202 Tkapp_Split(PyObject
*self
, PyObject
*args
)
1206 if (!PyArg_ParseTuple(args
, "s:split", &list
))
1212 Tkapp_Merge(PyObject
*self
, PyObject
*args
)
1214 char *s
= Merge(args
);
1215 PyObject
*res
= NULL
;
1218 res
= PyString_FromString(s
);
1229 /* Client data struct */
1233 } PythonCmd_ClientData
;
1236 PythonCmd_Error(Tcl_Interp
*interp
)
1239 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1244 /* This is the Tcl command that acts as a wrapper for Python
1245 * function or method.
1248 PythonCmd(ClientData clientData
, Tcl_Interp
*interp
, int argc
, char *argv
[])
1250 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1251 PyObject
*self
, *func
, *arg
, *res
, *tmp
;
1257 /* TBD: no error checking here since we know, via the
1258 * Tkapp_CreateCommand() that the client data is a two-tuple
1263 /* Create argument list (argv1, ..., argvN) */
1264 if (!(arg
= PyTuple_New(argc
- 1)))
1265 return PythonCmd_Error(interp
);
1267 for (i
= 0; i
< (argc
- 1); i
++) {
1268 PyObject
*s
= PyString_FromString(argv
[i
+ 1]);
1269 if (!s
|| PyTuple_SetItem(arg
, i
, s
)) {
1271 return PythonCmd_Error(interp
);
1274 res
= PyEval_CallObject(func
, arg
);
1278 return PythonCmd_Error(interp
);
1280 if (!(tmp
= PyList_New(0))) {
1282 return PythonCmd_Error(interp
);
1285 s
= AsString(res
, tmp
);
1287 rv
= PythonCmd_Error(interp
);
1290 Tcl_SetResult(Tkapp_Interp(self
), s
, TCL_VOLATILE
);
1303 PythonCmdDelete(ClientData clientData
)
1305 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1308 Py_XDECREF(data
->self
);
1309 Py_XDECREF(data
->func
);
1317 Tkapp_CreateCommand(PyObject
*self
, PyObject
*args
)
1319 PythonCmd_ClientData
*data
;
1324 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
1326 if (!PyCallable_Check(func
)) {
1327 PyErr_SetString(PyExc_TypeError
, "command not callable");
1331 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
1340 err
= Tcl_CreateCommand(Tkapp_Interp(self
), cmdName
, PythonCmd
,
1341 (ClientData
)data
, PythonCmdDelete
);
1344 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
1356 Tkapp_DeleteCommand(PyObject
*self
, PyObject
*args
)
1361 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
1364 err
= Tcl_DeleteCommand(Tkapp_Interp(self
), cmdName
);
1367 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
1376 #ifdef HAVE_CREATEFILEHANDLER
1377 /** File Handler **/
1379 typedef struct _fhcdata
{
1383 struct _fhcdata
*next
;
1384 } FileHandler_ClientData
;
1386 static FileHandler_ClientData
*HeadFHCD
;
1388 static FileHandler_ClientData
*
1389 NewFHCD(PyObject
*func
, PyObject
*file
, int id
)
1391 FileHandler_ClientData
*p
;
1392 p
= PyMem_NEW(FileHandler_ClientData
, 1);
1408 FileHandler_ClientData
*p
, **pp
;
1411 while ((p
= *pp
) != NULL
) {
1414 Py_XDECREF(p
->func
);
1415 Py_XDECREF(p
->file
);
1424 FileHandler(ClientData clientData
, int mask
)
1426 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
1427 PyObject
*func
, *file
, *arg
, *res
;
1433 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
1434 res
= PyEval_CallObject(func
, arg
);
1439 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1446 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
1447 /* args is (file, mask, func) */
1449 FileHandler_ClientData
*data
;
1450 PyObject
*file
, *func
;
1453 if (!PyArg_ParseTuple(args
, "OiO:createfilehandler",
1454 &file
, &mask
, &func
))
1456 tfile
= PyObject_AsFileDescriptor(file
);
1459 if (!PyCallable_Check(func
)) {
1460 PyErr_SetString(PyExc_TypeError
, "bad argument list");
1464 data
= NewFHCD(func
, file
, tfile
);
1468 /* Ought to check for null Tcl_File object... */
1470 Tcl_CreateFileHandler(tfile
, mask
, FileHandler
, (ClientData
) data
);
1477 Tkapp_DeleteFileHandler(PyObject
*self
, PyObject
*args
)
1482 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
1484 tfile
= PyObject_AsFileDescriptor(file
);
1490 /* Ought to check for null Tcl_File object... */
1492 Tcl_DeleteFileHandler(tfile
);
1497 #endif /* HAVE_CREATEFILEHANDLER */
1500 /**** Tktt Object (timer token) ****/
1502 staticforward PyTypeObject Tktt_Type
;
1506 Tcl_TimerToken token
;
1511 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
1513 TkttObject
*v
= (TkttObject
*)self
;
1514 PyObject
*func
= v
->func
;
1516 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
1518 if (v
->token
!= NULL
) {
1519 Tcl_DeleteTimerHandler(v
->token
);
1525 Py_DECREF(v
); /* See Tktt_New() */
1531 static PyMethodDef Tktt_methods
[] =
1533 {"deletetimerhandler", Tktt_DeleteTimerHandler
, 1},
1538 Tktt_New(PyObject
*func
)
1542 v
= PyObject_New(TkttObject
, &Tktt_Type
);
1550 /* Extra reference, deleted when called or when handler is deleted */
1556 Tktt_Dealloc(PyObject
*self
)
1558 TkttObject
*v
= (TkttObject
*)self
;
1559 PyObject
*func
= v
->func
;
1567 Tktt_Repr(PyObject
*self
)
1569 TkttObject
*v
= (TkttObject
*)self
;
1572 sprintf(buf
, "<tktimertoken at %p%s>", v
,
1573 v
->func
== NULL
? ", handler deleted" : "");
1574 return PyString_FromString(buf
);
1578 Tktt_GetAttr(PyObject
*self
, char *name
)
1580 return Py_FindMethod(Tktt_methods
, self
, name
);
1583 static PyTypeObject Tktt_Type
=
1585 PyObject_HEAD_INIT(NULL
)
1587 "tktimertoken", /*tp_name */
1588 sizeof(TkttObject
), /*tp_basicsize */
1590 Tktt_Dealloc
, /*tp_dealloc */
1592 Tktt_GetAttr
, /*tp_getattr */
1595 Tktt_Repr
, /*tp_repr */
1596 0, /*tp_as_number */
1597 0, /*tp_as_sequence */
1598 0, /*tp_as_mapping */
1604 /** Timer Handler **/
1607 TimerHandler(ClientData clientData
)
1609 TkttObject
*v
= (TkttObject
*)clientData
;
1610 PyObject
*func
= v
->func
;
1620 res
= PyEval_CallObject(func
, NULL
);
1622 Py_DECREF(v
); /* See Tktt_New() */
1626 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1635 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
1641 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler",
1642 &milliseconds
, &func
))
1644 if (!PyCallable_Check(func
)) {
1645 PyErr_SetString(PyExc_TypeError
, "bad argument list");
1649 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
1652 return (PyObject
*) v
;
1659 Tkapp_MainLoop(PyObject
*self
, PyObject
*args
)
1663 PyThreadState
*tstate
= PyThreadState_Get();
1666 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
1670 while (Tk_GetNumMainWindows() > threshold
&&
1677 Py_BEGIN_ALLOW_THREADS
1678 PyThread_acquire_lock(tcl_lock
, 1);
1679 tcl_tstate
= tstate
;
1680 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
1682 PyThread_release_lock(tcl_lock
);
1685 Py_END_ALLOW_THREADS
1687 result
= Tcl_DoOneEvent(0);
1690 if (PyErr_CheckSignals() != 0)
1699 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
1700 excInCmd
= valInCmd
= trbInCmd
= NULL
;
1708 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
1713 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
1717 rv
= Tcl_DoOneEvent(flags
);
1719 return Py_BuildValue("i", rv
);
1723 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
1726 if (!PyArg_ParseTuple(args
, ":quit"))
1735 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
1738 if (!PyArg_ParseTuple(args
, ":interpaddr"))
1741 return PyInt_FromLong((long)Tkapp_Interp(self
));
1746 /**** Tkapp Method List ****/
1748 static PyMethodDef Tkapp_methods
[] =
1750 {"call", Tkapp_Call
, 0},
1751 {"globalcall", Tkapp_GlobalCall
, 0},
1752 {"eval", Tkapp_Eval
, 1},
1753 {"globaleval", Tkapp_GlobalEval
, 1},
1754 {"evalfile", Tkapp_EvalFile
, 1},
1755 {"record", Tkapp_Record
, 1},
1756 {"adderrorinfo", Tkapp_AddErrorInfo
, 1},
1757 {"setvar", Tkapp_SetVar
, 1},
1758 {"globalsetvar", Tkapp_GlobalSetVar
, 1},
1759 {"getvar", Tkapp_GetVar
, 1},
1760 {"globalgetvar", Tkapp_GlobalGetVar
, 1},
1761 {"unsetvar", Tkapp_UnsetVar
, 1},
1762 {"globalunsetvar", Tkapp_GlobalUnsetVar
, 1},
1763 {"getint", Tkapp_GetInt
, 1},
1764 {"getdouble", Tkapp_GetDouble
, 1},
1765 {"getboolean", Tkapp_GetBoolean
, 1},
1766 {"exprstring", Tkapp_ExprString
, 1},
1767 {"exprlong", Tkapp_ExprLong
, 1},
1768 {"exprdouble", Tkapp_ExprDouble
, 1},
1769 {"exprboolean", Tkapp_ExprBoolean
, 1},
1770 {"splitlist", Tkapp_SplitList
, 1},
1771 {"split", Tkapp_Split
, 1},
1772 {"merge", Tkapp_Merge
, 0},
1773 {"createcommand", Tkapp_CreateCommand
, 1},
1774 {"deletecommand", Tkapp_DeleteCommand
, 1},
1775 #ifdef HAVE_CREATEFILEHANDLER
1776 {"createfilehandler", Tkapp_CreateFileHandler
, 1},
1777 {"deletefilehandler", Tkapp_DeleteFileHandler
, 1},
1779 {"createtimerhandler", Tkapp_CreateTimerHandler
, 1},
1780 {"mainloop", Tkapp_MainLoop
, 1},
1781 {"dooneevent", Tkapp_DoOneEvent
, 1},
1782 {"quit", Tkapp_Quit
, 1},
1783 {"interpaddr", Tkapp_InterpAddr
, 1},
1789 /**** Tkapp Type Methods ****/
1792 Tkapp_Dealloc(PyObject
*self
)
1795 Tcl_DeleteInterp(Tkapp_Interp(self
));
1802 Tkapp_GetAttr(PyObject
*self
, char *name
)
1804 return Py_FindMethod(Tkapp_methods
, self
, name
);
1807 static PyTypeObject Tkapp_Type
=
1809 PyObject_HEAD_INIT(NULL
)
1811 "tkapp", /*tp_name */
1812 sizeof(TkappObject
), /*tp_basicsize */
1814 Tkapp_Dealloc
, /*tp_dealloc */
1816 Tkapp_GetAttr
, /*tp_getattr */
1820 0, /*tp_as_number */
1821 0, /*tp_as_sequence */
1822 0, /*tp_as_mapping */
1828 /**** Tkinter Module ****/
1832 int size
; /* current size */
1833 int maxsize
; /* allocated size */
1837 _bump(FlattenContext
* context
, int size
)
1839 /* expand tuple to hold (at least) size new items.
1840 return true if successful, false if an exception was raised */
1842 int maxsize
= context
->maxsize
* 2;
1844 if (maxsize
< context
->size
+ size
)
1845 maxsize
= context
->size
+ size
;
1847 context
->maxsize
= maxsize
;
1849 return _PyTuple_Resize(&context
->tuple
, maxsize
, 0) >= 0;
1853 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
1855 /* add tuple or list to argument tuple (recursively) */
1860 PyErr_SetString(PyExc_ValueError
,
1861 "nesting too deep in _flatten");
1863 } else if (PyList_Check(item
)) {
1864 size
= PyList_GET_SIZE(item
);
1865 /* preallocate (assume no nesting) */
1866 if (context
->size
+ size
> context
->maxsize
&&
1867 !_bump(context
, size
))
1869 /* copy items to output tuple */
1870 for (i
= 0; i
< size
; i
++) {
1871 PyObject
*o
= PyList_GET_ITEM(item
, i
);
1872 if (PyList_Check(o
) || PyTuple_Check(o
)) {
1873 if (!_flatten1(context
, o
, depth
+ 1))
1875 } else if (o
!= Py_None
) {
1876 if (context
->size
+ 1 > context
->maxsize
&&
1880 PyTuple_SET_ITEM(context
->tuple
,
1881 context
->size
++, o
);
1884 } else if (PyTuple_Check(item
)) {
1885 /* same, for tuples */
1886 size
= PyTuple_GET_SIZE(item
);
1887 if (context
->size
+ size
> context
->maxsize
&&
1888 !_bump(context
, size
))
1890 for (i
= 0; i
< size
; i
++) {
1891 PyObject
*o
= PyTuple_GET_ITEM(item
, i
);
1892 if (PyList_Check(o
) || PyTuple_Check(o
)) {
1893 if (!_flatten1(context
, o
, depth
+ 1))
1895 } else if (o
!= Py_None
) {
1896 if (context
->size
+ 1 > context
->maxsize
&&
1900 PyTuple_SET_ITEM(context
->tuple
,
1901 context
->size
++, o
);
1905 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
1912 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
1914 FlattenContext context
;
1917 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
1920 context
.maxsize
= PySequence_Size(item
);
1921 if (context
.maxsize
<= 0)
1922 return PyTuple_New(0);
1924 context
.tuple
= PyTuple_New(context
.maxsize
);
1930 if (!_flatten1(&context
, item
,0))
1933 if (_PyTuple_Resize(&context
.tuple
, context
.size
, 0))
1936 return context
.tuple
;
1940 Tkinter_Create(PyObject
*self
, PyObject
*args
)
1942 char *screenName
= NULL
;
1943 char *baseName
= NULL
;
1944 char *className
= NULL
;
1945 int interactive
= 0;
1947 baseName
= strrchr(Py_GetProgramName(), '/');
1948 if (baseName
!= NULL
)
1951 baseName
= Py_GetProgramName();
1954 if (!PyArg_ParseTuple(args
, "|zssi:create",
1955 &screenName
, &baseName
, &className
,
1959 return (PyObject
*) Tkapp_New(screenName
, baseName
, className
,
1963 static PyMethodDef moduleMethods
[] =
1965 {"_flatten", Tkinter_Flatten
, 1},
1966 {"create", Tkinter_Create
, 1},
1967 #ifdef HAVE_CREATEFILEHANDLER
1968 {"createfilehandler", Tkapp_CreateFileHandler
, 1},
1969 {"deletefilehandler", Tkapp_DeleteFileHandler
, 1},
1971 {"createtimerhandler", Tkapp_CreateTimerHandler
, 1},
1972 {"mainloop", Tkapp_MainLoop
, 1},
1973 {"dooneevent", Tkapp_DoOneEvent
, 1},
1974 {"quit", Tkapp_Quit
, 1},
1978 #ifdef WAIT_FOR_STDIN
1980 static int stdin_ready
= 0;
1984 MyFileProc(void *clientData
, int mask
)
1990 static PyThreadState
*event_tstate
= NULL
;
1999 PyEval_RestoreThread(event_tstate
);
2004 tfile
= fileno(stdin
);
2005 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
2007 while (!errorInCmd
&& !stdin_ready
) {
2015 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
2016 Py_BEGIN_ALLOW_THREADS
2017 PyThread_acquire_lock(tcl_lock
, 1);
2018 tcl_tstate
= event_tstate
;
2020 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
2023 PyThread_release_lock(tcl_lock
);
2026 Py_END_ALLOW_THREADS
2028 result
= Tcl_DoOneEvent(0);
2035 Tcl_DeleteFileHandler(tfile
);
2039 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2040 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2044 PyEval_SaveThread();
2052 EnableEventHook(void)
2054 #ifdef WAIT_FOR_STDIN
2055 if (PyOS_InputHook
== NULL
) {
2057 event_tstate
= PyThreadState_Get();
2059 PyOS_InputHook
= EventHook
;
2065 DisableEventHook(void)
2067 #ifdef WAIT_FOR_STDIN
2068 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
2069 PyOS_InputHook
= NULL
;
2075 /* all errors will be checked in one fell swoop in init_tkinter() */
2077 ins_long(PyObject
*d
, char *name
, long val
)
2079 PyObject
*v
= PyInt_FromLong(val
);
2081 PyDict_SetItemString(d
, name
, v
);
2086 ins_string(PyObject
*d
, char *name
, char *val
)
2088 PyObject
*v
= PyString_FromString(val
);
2090 PyDict_SetItemString(d
, name
, v
);
2101 Tkapp_Type
.ob_type
= &PyType_Type
;
2104 tcl_lock
= PyThread_allocate_lock();
2107 m
= Py_InitModule("_tkinter", moduleMethods
);
2109 d
= PyModule_GetDict(m
);
2110 Tkinter_TclError
= Py_BuildValue("s", "TclError");
2111 PyDict_SetItemString(d
, "TclError", Tkinter_TclError
);
2113 ins_long(d
, "READABLE", TCL_READABLE
);
2114 ins_long(d
, "WRITABLE", TCL_WRITABLE
);
2115 ins_long(d
, "EXCEPTION", TCL_EXCEPTION
);
2116 ins_long(d
, "WINDOW_EVENTS", TCL_WINDOW_EVENTS
);
2117 ins_long(d
, "FILE_EVENTS", TCL_FILE_EVENTS
);
2118 ins_long(d
, "TIMER_EVENTS", TCL_TIMER_EVENTS
);
2119 ins_long(d
, "IDLE_EVENTS", TCL_IDLE_EVENTS
);
2120 ins_long(d
, "ALL_EVENTS", TCL_ALL_EVENTS
);
2121 ins_long(d
, "DONT_WAIT", TCL_DONT_WAIT
);
2122 ins_string(d
, "TK_VERSION", TK_VERSION
);
2123 ins_string(d
, "TCL_VERSION", TCL_VERSION
);
2125 PyDict_SetItemString(d
, "TkappType", (PyObject
*)&Tkapp_Type
);
2127 Tktt_Type
.ob_type
= &PyType_Type
;
2128 PyDict_SetItemString(d
, "TkttType", (PyObject
*)&Tktt_Type
);
2130 /* This helps the dynamic loader; in Unicode aware Tcl versions
2131 it also helps Tcl find its encodings. */
2132 Tcl_FindExecutable(Py_GetProgramName());
2134 if (PyErr_Occurred())
2138 /* This was not a good idea; through <Destroy> bindings,
2139 Tcl_Finalize() may invoke Python code but at that point the
2140 interpreter and thread state have already been destroyed! */
2141 Py_AtExit(Tcl_Finalize
);
2146 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2147 ** Most of the initializations in that routine (toolbox init calls and
2148 ** such) have already been done for us, so we only need these.
2152 Tcl_MacSetEventProc(PyMacConvertEvent
);
2154 mac_addlibresources();
2155 #endif /* GENERATINGCFM */
2156 #endif /* macintosh */
2164 ** Anyone who embeds Tcl/Tk on the Mac must define panic().
2168 panic(char * format
, ...)
2172 va_start(varg
, format
);
2174 vfprintf(stderr
, format
, varg
);
2175 (void) fflush(stderr
);
2179 Py_FatalError("Tcl/Tk panic");
2183 ** Pass events to SIOUX before passing them to Tk.
2187 PyMacConvertEvent(EventRecord
*eventPtr
)
2191 ** Sioux eats too many events, so we don't pass it everything. We
2192 ** always pass update events to Sioux, and we only pass other events if
2193 ** the Sioux window is frontmost. This means that Tk menus don't work
2194 ** in that case, but at least we can scroll the sioux window.
2195 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2196 ** part of the external interface of Sioux...
2198 frontwin
= FrontWindow();
2199 if ( eventPtr
->what
== updateEvt
|| SIOUXIsAppWindow(frontwin
) ) {
2200 if (SIOUXHandleOneEvent(eventPtr
))
2201 return 0; /* Nothing happened to the Tcl event queue */
2203 return TkMacConvertEvent(eventPtr
);
2209 ** Additional Mac specific code for dealing with shared libraries.
2212 #include <Resources.h>
2213 #include <CodeFragments.h>
2215 static int loaded_from_shlib
= 0;
2216 static FSSpec library_fss
;
2219 ** If this module is dynamically loaded the following routine should
2220 ** be the init routine. It takes care of adding the shared library to
2221 ** the resource-file chain, so that the tk routines can find their
2225 init_tkinter_shlib(CFragInitBlockPtr data
)
2228 if ( data
== nil
) return noErr
;
2229 if ( data
->fragLocator
.where
== kDataForkCFragLocator
) {
2230 library_fss
= *data
->fragLocator
.u
.onDisk
.fileSpec
;
2231 loaded_from_shlib
= 1;
2232 } else if ( data
->fragLocator
.where
== kResourceCFragLocator
) {
2233 library_fss
= *data
->fragLocator
.u
.inSegs
.fileSpec
;
2234 loaded_from_shlib
= 1;
2240 ** Insert the library resources into the search path. Put them after
2241 ** the resources from the application. Again, we ignore errors.
2244 mac_addlibresources(void)
2246 if ( !loaded_from_shlib
)
2248 (void)FSpOpenResFile(&library_fss
, fsRdPerm
);
2251 #endif /* GENERATINGCFM */
2252 #endif /* macintosh */