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__) || defined(macintosh))
61 /* Mac has it, but it doesn't really work:-( */
62 #define HAVE_CREATEFILEHANDLER
65 #ifdef HAVE_CREATEFILEHANDLER
67 /* Tcl_CreateFileHandler() changed several times; these macros deal with the
68 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
69 Unix, only because Jack added it back); when available on Windows, it only
70 applies to sockets. */
73 #define FHANDLETYPE TCL_WIN_SOCKET
75 #define FHANDLETYPE TCL_UNIX_FD
78 /* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
79 which uses this to handle Tcl events while the user is typing commands. */
81 #if FHANDLETYPE == TCL_UNIX_FD
82 #define WAIT_FOR_STDIN
85 #endif /* HAVE_CREATEFILEHANDLER */
89 #define WAIT_FOR_STDIN
94 /* The threading situation is complicated. Tcl is not thread-safe, except for
95 Tcl 8.1, which will probably remain in alpha status for another 6 months
96 (and the README says that Tk will probably remain thread-unsafe forever).
97 So we need to use a lock around all uses of Tcl. Previously, the Python
98 interpreter lock was used for this. However, this causes problems when
99 other Python threads need to run while Tcl is blocked waiting for events.
101 To solve this problem, a separate lock for Tcl is introduced. Holding it
102 is incompatible with holding Python's interpreter lock. The following four
103 macros manipulate both locks together.
105 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
106 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
107 that could call an event handler, or otherwise affect the state of a Tcl
108 interpreter. These assume that the surrounding code has the Python
109 interpreter lock; inside the brackets, the Python interpreter lock has been
110 released and the lock for Tcl has been acquired.
112 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
113 (For example, when transferring data from the Tcl interpreter result to a
114 Python string object.) This can be done by using different macros to close
115 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
116 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
117 releases the Tcl lock.
119 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
120 handlers when the handler needs to use Python. Such event handlers are
121 entered while the lock for Tcl is held; the event handler presumably needs
122 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
123 the Python interpreter lock, restoring the appropriate thread state, and
124 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
125 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
126 the code between ENTER_PYTHON and LEAVE_PYTHON.
128 These locks expand to several statements and brackets; they should not be
129 used in branches of if statements and the like.
133 static PyThread_type_lock tcl_lock
= 0;
134 static PyThreadState
*tcl_tstate
= NULL
;
137 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
138 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
141 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
143 #define ENTER_OVERLAP \
146 #define LEAVE_OVERLAP_TCL \
147 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); }
149 #define ENTER_PYTHON \
150 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
151 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
153 #define LEAVE_PYTHON \
154 { PyThreadState *tstate = PyEval_SaveThread(); \
155 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
161 #define ENTER_OVERLAP
162 #define LEAVE_OVERLAP_TCL
171 ** Additional cruft needed by Tcl/Tk on the Mac.
172 ** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
175 /* ckfree() expects a char* */
176 #define FREECAST (char *)
178 #include <Events.h> /* For EventRecord */
180 typedef int (*TclMacConvertEventPtr
) (EventRecord
*eventPtr
);
181 void Tcl_MacSetEventProc(TclMacConvertEventPtr procPtr
);
182 int TkMacConvertEvent(EventRecord
*eventPtr
);
184 staticforward
int PyMacConvertEvent(EventRecord
*eventPtr
);
186 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
191 extern int SIOUXIsAppWindow(WindowPtr
);
193 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
196 #endif /* macintosh */
199 #define FREECAST (char *)
202 /**** Tkapp Object Declaration ****/
204 staticforward PyTypeObject Tkapp_Type
;
211 #define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
212 #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
213 #define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
215 #define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
216 (void *) v, ((PyObject *) v)->ob_refcnt))
220 /**** Error Handling ****/
222 static PyObject
*Tkinter_TclError
;
223 static int quitMainLoop
= 0;
224 static int errorInCmd
= 0;
225 static PyObject
*excInCmd
;
226 static PyObject
*valInCmd
;
227 static PyObject
*trbInCmd
;
232 Tkinter_Error(PyObject
*v
)
234 PyErr_SetString(Tkinter_TclError
, Tkapp_Result(v
));
245 /* Millisecond sleep() for Unix platforms. */
250 /* XXX Too bad if you don't have select(). */
252 t
.tv_sec
= milli
/1000;
253 t
.tv_usec
= (milli
%1000) * 1000;
254 select(0, (fd_set
*)0, (fd_set
*)0, (fd_set
*)0, &t
);
256 #endif /* MS_WINDOWS */
257 #endif /* WITH_THREAD */
261 AsString(PyObject
*value
, PyObject
*tmp
)
263 if (PyString_Check(value
))
264 return PyString_AsString(value
);
265 else if (PyUnicode_Check(value
)) {
266 PyObject
*v
= PyUnicode_AsUTF8String(value
);
269 if (PyList_Append(tmp
, v
) != 0) {
274 return PyString_AsString(v
);
277 PyObject
*v
= PyObject_Str(value
);
280 if (PyList_Append(tmp
, v
) != 0) {
285 return PyString_AsString(v
);
294 Merge(PyObject
*args
)
296 PyObject
*tmp
= NULL
;
297 char *argvStore
[ARGSZ
];
301 int argc
= 0, fvc
= 0, i
;
304 if (!(tmp
= PyList_New(0)))
313 else if (!PyTuple_Check(args
)) {
316 if (!(argv
[0] = AsString(args
, tmp
)))
320 argc
= PyTuple_Size(args
);
323 argv
= (char **)ckalloc(argc
* sizeof(char *));
324 fv
= (int *)ckalloc(argc
* sizeof(int));
325 if (argv
== NULL
|| fv
== NULL
) {
331 for (i
= 0; i
< argc
; i
++) {
332 PyObject
*v
= PyTuple_GetItem(args
, i
);
333 if (PyTuple_Check(v
)) {
335 if (!(argv
[i
] = Merge(v
)))
339 else if (v
== Py_None
) {
345 if (!(argv
[i
] = AsString(v
, tmp
)))
351 res
= Tcl_Merge(argc
, argv
);
353 PyErr_SetString(Tkinter_TclError
, "merge failed");
356 for (i
= 0; i
< fvc
; i
++)
360 if (argv
!= argvStore
)
361 ckfree(FREECAST argv
);
383 if (Tcl_SplitList((Tcl_Interp
*)NULL
, list
, &argc
, &argv
) != TCL_OK
) {
385 * Could be a quoted string containing funnies, e.g. {"}.
386 * Return the string itself.
388 return PyString_FromString(list
);
392 v
= PyString_FromString("");
394 v
= PyString_FromString(argv
[0]);
395 else if ((v
= PyTuple_New(argc
)) != NULL
) {
399 for (i
= 0; i
< argc
; i
++) {
400 if ((w
= Split(argv
[i
])) == NULL
) {
405 PyTuple_SetItem(v
, i
, w
);
408 Tcl_Free(FREECAST argv
);
414 /**** Tkapp Object ****/
418 Tcl_AppInit(Tcl_Interp
*interp
)
422 main
= Tk_MainWindow(interp
);
423 if (Tcl_Init(interp
) == TCL_ERROR
) {
424 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp
));
427 if (Tk_Init(interp
) == TCL_ERROR
) {
428 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp
));
433 #endif /* !WITH_APPINIT */
438 /* Initialize the Tk application; see the `main' function in
442 static void EnableEventHook(void); /* Forward */
443 static void DisableEventHook(void); /* Forward */
446 Tkapp_New(char *screenName
, char *baseName
, char *className
, int interactive
)
451 v
= PyObject_New(TkappObject
, &Tkapp_Type
);
455 v
->interp
= Tcl_CreateInterp();
457 #if defined(macintosh)
458 /* This seems to be needed */
460 TkMacInitMenus(v
->interp
);
462 /* Delete the 'exit' command, which can screw things up */
463 Tcl_DeleteCommand(v
->interp
, "exit");
465 if (screenName
!= NULL
)
466 Tcl_SetVar2(v
->interp
, "env", "DISPLAY",
467 screenName
, TCL_GLOBAL_ONLY
);
470 Tcl_SetVar(v
->interp
, "tcl_interactive", "1", TCL_GLOBAL_ONLY
);
472 Tcl_SetVar(v
->interp
, "tcl_interactive", "0", TCL_GLOBAL_ONLY
);
474 /* This is used to get the application class for Tk 4.1 and up */
475 argv0
= (char*)ckalloc(strlen(className
) + 1);
482 strcpy(argv0
, className
);
483 if (isupper((int)(argv0
[0])))
484 argv0
[0] = tolower(argv0
[0]);
485 Tcl_SetVar(v
->interp
, "argv0", argv0
, TCL_GLOBAL_ONLY
);
488 if (Tcl_AppInit(v
->interp
) != TCL_OK
)
489 return (TkappObject
*)Tkinter_Error((PyObject
*)v
);
500 #if TKMAJORMINOR >= 8001
501 #define USING_OBJECTS
507 AsObj(PyObject
*value
)
511 if (PyString_Check(value
))
512 return Tcl_NewStringObj(PyString_AS_STRING(value
),
513 PyString_GET_SIZE(value
));
514 else if (PyInt_Check(value
))
515 return Tcl_NewLongObj(PyInt_AS_LONG(value
));
516 else if (PyFloat_Check(value
))
517 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value
));
518 else if (PyTuple_Check(value
)) {
519 Tcl_Obj
**argv
= (Tcl_Obj
**)
520 ckalloc(PyTuple_Size(value
)*sizeof(Tcl_Obj
*));
524 for(i
=0;i
<PyTuple_Size(value
);i
++)
525 argv
[i
] = AsObj(PyTuple_GetItem(value
,i
));
526 result
= Tcl_NewListObj(PyTuple_Size(value
), argv
);
527 ckfree(FREECAST argv
);
530 else if (PyUnicode_Check(value
)) {
531 #if TKMAJORMINOR <= 8001
532 /* In Tcl 8.1 we must use UTF-8 */
533 PyObject
* utf8
= PyUnicode_AsUTF8String(value
);
536 result
= Tcl_NewStringObj(PyString_AS_STRING(utf8
),
537 PyString_GET_SIZE(utf8
));
540 #else /* TKMAJORMINOR > 8001 */
541 /* In Tcl 8.2 and later, use Tcl_NewUnicodeObj() */
542 if (sizeof(Py_UNICODE
) != sizeof(Tcl_UniChar
)) {
543 /* XXX Should really test this at compile time */
544 PyErr_SetString(PyExc_SystemError
,
545 "Py_UNICODE and Tcl_UniChar differ in size");
548 return Tcl_NewUnicodeObj(PyUnicode_AS_UNICODE(value
),
549 PyUnicode_GET_SIZE(value
));
550 #endif /* TKMAJORMINOR > 8001 */
553 PyObject
*v
= PyObject_Str(value
);
563 Tkapp_Call(PyObject
*self
, PyObject
*args
)
565 Tcl_Obj
*objStore
[ARGSZ
];
566 Tcl_Obj
**objv
= NULL
;
568 PyObject
*res
= NULL
;
569 Tcl_Interp
*interp
= Tkapp_Interp(self
);
570 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
571 int flags
= TCL_EVAL_DIRECT
;
578 else if (!PyTuple_Check(args
)) {
579 objv
[0] = AsObj(args
);
583 Tcl_IncrRefCount(objv
[0]);
586 objc
= PyTuple_Size(args
);
589 objv
= (Tcl_Obj
**)ckalloc(objc
* sizeof(char *));
597 for (i
= 0; i
< objc
; i
++) {
598 PyObject
*v
= PyTuple_GetItem(args
, i
);
605 /* Reset objc, so it attempts to clear
606 objects only up to i. */
610 Tcl_IncrRefCount(objv
[i
]);
616 i
= Tcl_EvalObjv(interp
, objc
, objv
, flags
);
622 /* We could request the object result here, but doing
623 so would confuse applications that expect a string. */
624 char *s
= Tcl_GetStringResult(interp
);
626 /* If the result contains any bytes with the top bit set,
627 it's UTF-8 and we should decode it to Unicode */
634 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
636 /* Convert UTF-8 to Unicode string */
638 res
= PyUnicode_DecodeUTF8(s
, (int)(p
-s
), "strict");
641 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
649 for (i
= 0; i
< objc
; i
++)
650 Tcl_DecrRefCount(objv
[i
]);
651 if (objv
!= objStore
)
652 ckfree(FREECAST objv
);
656 #else /* !USING_OBJECTS */
659 Tkapp_Call(PyObject
*self
, PyObject
*args
)
661 /* This is copied from Merge() */
662 PyObject
*tmp
= NULL
;
663 char *argvStore
[ARGSZ
];
667 int argc
= 0, fvc
= 0, i
;
668 PyObject
*res
= NULL
; /* except this has a different type */
669 Tcl_CmdInfo info
; /* and this is added */
670 Tcl_Interp
*interp
= Tkapp_Interp(self
); /* and this too */
672 if (!(tmp
= PyList_New(0)))
681 else if (!PyTuple_Check(args
)) {
684 if (!(argv
[0] = AsString(args
, tmp
)))
688 argc
= PyTuple_Size(args
);
691 argv
= (char **)ckalloc(argc
* sizeof(char *));
692 fv
= (int *)ckalloc(argc
* sizeof(int));
693 if (argv
== NULL
|| fv
== NULL
) {
699 for (i
= 0; i
< argc
; i
++) {
700 PyObject
*v
= PyTuple_GetItem(args
, i
);
701 if (PyTuple_Check(v
)) {
703 if (!(argv
[i
] = Merge(v
)))
707 else if (v
== Py_None
) {
713 if (!(argv
[i
] = AsString(v
, tmp
)))
719 /* End code copied from Merge() */
721 /* All this to avoid a call to Tcl_Merge() and the corresponding call
722 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
723 if (Py_VerboseFlag
>= 2) {
724 for (i
= 0; i
< argc
; i
++)
725 PySys_WriteStderr("%s ", argv
[i
]);
730 !Tcl_GetCommandInfo(interp
, argv
[0], &info
) ||
734 cmd
= Tcl_Merge(argc
, argv
);
735 i
= Tcl_Eval(interp
, cmd
);
739 Tcl_ResetResult(interp
);
740 i
= (*info
.proc
)(info
.clientData
, interp
, argc
, argv
);
743 if (info
.proc
== NULL
&& Py_VerboseFlag
>= 2)
744 PySys_WriteStderr("... use TclEval ");
745 if (i
== TCL_ERROR
) {
746 if (Py_VerboseFlag
>= 2)
747 PySys_WriteStderr("... error: '%s'\n",
748 Tcl_GetStringResult(interp
));
752 if (Py_VerboseFlag
>= 2)
753 PySys_WriteStderr("-> '%s'\n", Tcl_GetStringResult(interp
));
754 res
= PyString_FromString(Tcl_GetStringResult(interp
));
758 /* Copied from Merge() again */
760 for (i
= 0; i
< fvc
; i
++)
764 if (argv
!= argvStore
)
765 ckfree(FREECAST argv
);
773 #endif /* !USING_OBJECTS */
776 Tkapp_GlobalCall(PyObject
*self
, PyObject
*args
)
778 /* Could do the same here as for Tkapp_Call(), but this is not used
779 much, so I can't be bothered. Unfortunately Tcl doesn't export a
780 way for the user to do what all its Global* variants do (save and
781 reset the scope pointer, call the local version, restore the saved
785 PyObject
*res
= NULL
;
791 err
= Tcl_GlobalEval(Tkapp_Interp(self
), cmd
);
793 if (err
== TCL_ERROR
)
794 res
= Tkinter_Error(self
);
796 res
= PyString_FromString(Tkapp_Result(self
));
805 Tkapp_Eval(PyObject
*self
, PyObject
*args
)
808 PyObject
*res
= NULL
;
811 if (!PyArg_ParseTuple(args
, "s:eval", &script
))
815 err
= Tcl_Eval(Tkapp_Interp(self
), script
);
817 if (err
== TCL_ERROR
)
818 res
= Tkinter_Error(self
);
820 res
= PyString_FromString(Tkapp_Result(self
));
826 Tkapp_GlobalEval(PyObject
*self
, PyObject
*args
)
829 PyObject
*res
= NULL
;
832 if (!PyArg_ParseTuple(args
, "s:globaleval", &script
))
836 err
= Tcl_GlobalEval(Tkapp_Interp(self
), script
);
838 if (err
== TCL_ERROR
)
839 res
= Tkinter_Error(self
);
841 res
= PyString_FromString(Tkapp_Result(self
));
847 Tkapp_EvalFile(PyObject
*self
, PyObject
*args
)
850 PyObject
*res
= NULL
;
853 if (!PyArg_ParseTuple(args
, "s:evalfile", &fileName
))
857 err
= Tcl_EvalFile(Tkapp_Interp(self
), fileName
);
859 if (err
== TCL_ERROR
)
860 res
= Tkinter_Error(self
);
863 res
= PyString_FromString(Tkapp_Result(self
));
869 Tkapp_Record(PyObject
*self
, PyObject
*args
)
872 PyObject
*res
= NULL
;
875 if (!PyArg_ParseTuple(args
, "s", &script
))
879 err
= Tcl_RecordAndEval(Tkapp_Interp(self
), script
, TCL_NO_EVAL
);
881 if (err
== TCL_ERROR
)
882 res
= Tkinter_Error(self
);
884 res
= PyString_FromString(Tkapp_Result(self
));
890 Tkapp_AddErrorInfo(PyObject
*self
, PyObject
*args
)
894 if (!PyArg_ParseTuple(args
, "s:adderrorinfo", &msg
))
897 Tcl_AddErrorInfo(Tkapp_Interp(self
), msg
);
909 SetVar(PyObject
*self
, PyObject
*args
, int flags
)
911 char *name1
, *name2
, *ok
, *s
;
919 if (PyArg_ParseTuple(args
, "sO:setvar", &name1
, &newValue
)) {
921 s
= AsString(newValue
, tmp
);
925 ok
= Tcl_SetVar(Tkapp_Interp(self
), name1
, s
, flags
);
930 if (PyArg_ParseTuple(args
, "ssO:setvar",
931 &name1
, &name2
, &newValue
)) {
932 s
= AsString(newValue
, tmp
);
936 ok
= Tcl_SetVar2(Tkapp_Interp(self
), name1
, name2
,
948 return Tkinter_Error(self
);
955 Tkapp_SetVar(PyObject
*self
, PyObject
*args
)
957 return SetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
961 Tkapp_GlobalSetVar(PyObject
*self
, PyObject
*args
)
963 return SetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
969 GetVar(PyObject
*self
, PyObject
*args
, int flags
)
971 char *name1
, *name2
=NULL
, *s
;
972 PyObject
*res
= NULL
;
974 if (!PyArg_ParseTuple(args
, "s|s:getvar", &name1
, &name2
))
978 s
= Tcl_GetVar(Tkapp_Interp(self
), name1
, flags
);
981 s
= Tcl_GetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
985 res
= Tkinter_Error(self
);
987 res
= PyString_FromString(s
);
993 Tkapp_GetVar(PyObject
*self
, PyObject
*args
)
995 return GetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
999 Tkapp_GlobalGetVar(PyObject
*self
, PyObject
*args
)
1001 return GetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1007 UnsetVar(PyObject
*self
, PyObject
*args
, int flags
)
1009 char *name1
, *name2
=NULL
;
1010 PyObject
*res
= NULL
;
1013 if (!PyArg_ParseTuple(args
, "s|s:unsetvar", &name1
, &name2
))
1017 code
= Tcl_UnsetVar(Tkapp_Interp(self
), name1
, flags
);
1020 code
= Tcl_UnsetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
1023 if (code
== TCL_ERROR
)
1024 res
= Tkinter_Error(self
);
1034 Tkapp_UnsetVar(PyObject
*self
, PyObject
*args
)
1036 return UnsetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
1040 Tkapp_GlobalUnsetVar(PyObject
*self
, PyObject
*args
)
1042 return UnsetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1047 /** Tcl to Python **/
1050 Tkapp_GetInt(PyObject
*self
, PyObject
*args
)
1055 if (!PyArg_ParseTuple(args
, "s:getint", &s
))
1057 if (Tcl_GetInt(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1058 return Tkinter_Error(self
);
1059 return Py_BuildValue("i", v
);
1063 Tkapp_GetDouble(PyObject
*self
, PyObject
*args
)
1068 if (!PyArg_ParseTuple(args
, "s:getdouble", &s
))
1070 if (Tcl_GetDouble(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1071 return Tkinter_Error(self
);
1072 return Py_BuildValue("d", v
);
1076 Tkapp_GetBoolean(PyObject
*self
, PyObject
*args
)
1081 if (!PyArg_ParseTuple(args
, "s:getboolean", &s
))
1083 if (Tcl_GetBoolean(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1084 return Tkinter_Error(self
);
1085 return Py_BuildValue("i", v
);
1089 Tkapp_ExprString(PyObject
*self
, PyObject
*args
)
1092 PyObject
*res
= NULL
;
1095 if (!PyArg_ParseTuple(args
, "s:exprstring", &s
))
1098 retval
= Tcl_ExprString(Tkapp_Interp(self
), s
);
1100 if (retval
== TCL_ERROR
)
1101 res
= Tkinter_Error(self
);
1103 res
= Py_BuildValue("s", Tkapp_Result(self
));
1109 Tkapp_ExprLong(PyObject
*self
, PyObject
*args
)
1112 PyObject
*res
= NULL
;
1116 if (!PyArg_ParseTuple(args
, "s:exprlong", &s
))
1119 retval
= Tcl_ExprLong(Tkapp_Interp(self
), s
, &v
);
1121 if (retval
== TCL_ERROR
)
1122 res
= Tkinter_Error(self
);
1124 res
= Py_BuildValue("l", v
);
1130 Tkapp_ExprDouble(PyObject
*self
, PyObject
*args
)
1133 PyObject
*res
= NULL
;
1137 if (!PyArg_ParseTuple(args
, "s:exprdouble", &s
))
1139 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1141 retval
= Tcl_ExprDouble(Tkapp_Interp(self
), s
, &v
);
1143 PyFPE_END_PROTECT(retval
)
1144 if (retval
== TCL_ERROR
)
1145 res
= Tkinter_Error(self
);
1147 res
= Py_BuildValue("d", v
);
1153 Tkapp_ExprBoolean(PyObject
*self
, PyObject
*args
)
1156 PyObject
*res
= NULL
;
1160 if (!PyArg_ParseTuple(args
, "s:exprboolean", &s
))
1163 retval
= Tcl_ExprBoolean(Tkapp_Interp(self
), s
, &v
);
1165 if (retval
== TCL_ERROR
)
1166 res
= Tkinter_Error(self
);
1168 res
= Py_BuildValue("i", v
);
1176 Tkapp_SplitList(PyObject
*self
, PyObject
*args
)
1184 if (!PyArg_ParseTuple(args
, "s:splitlist", &list
))
1187 if (Tcl_SplitList(Tkapp_Interp(self
), list
, &argc
, &argv
) == TCL_ERROR
)
1188 return Tkinter_Error(self
);
1190 if (!(v
= PyTuple_New(argc
)))
1193 for (i
= 0; i
< argc
; i
++) {
1194 PyObject
*s
= PyString_FromString(argv
[i
]);
1195 if (!s
|| PyTuple_SetItem(v
, i
, s
)) {
1203 ckfree(FREECAST argv
);
1208 Tkapp_Split(PyObject
*self
, PyObject
*args
)
1212 if (!PyArg_ParseTuple(args
, "s:split", &list
))
1218 Tkapp_Merge(PyObject
*self
, PyObject
*args
)
1220 char *s
= Merge(args
);
1221 PyObject
*res
= NULL
;
1224 res
= PyString_FromString(s
);
1235 /* Client data struct */
1239 } PythonCmd_ClientData
;
1242 PythonCmd_Error(Tcl_Interp
*interp
)
1245 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1250 /* This is the Tcl command that acts as a wrapper for Python
1251 * function or method.
1254 PythonCmd(ClientData clientData
, Tcl_Interp
*interp
, int argc
, char *argv
[])
1256 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1257 PyObject
*self
, *func
, *arg
, *res
, *tmp
;
1263 /* TBD: no error checking here since we know, via the
1264 * Tkapp_CreateCommand() that the client data is a two-tuple
1269 /* Create argument list (argv1, ..., argvN) */
1270 if (!(arg
= PyTuple_New(argc
- 1)))
1271 return PythonCmd_Error(interp
);
1273 for (i
= 0; i
< (argc
- 1); i
++) {
1274 PyObject
*s
= PyString_FromString(argv
[i
+ 1]);
1275 if (!s
|| PyTuple_SetItem(arg
, i
, s
)) {
1277 return PythonCmd_Error(interp
);
1280 res
= PyEval_CallObject(func
, arg
);
1284 return PythonCmd_Error(interp
);
1286 if (!(tmp
= PyList_New(0))) {
1288 return PythonCmd_Error(interp
);
1291 s
= AsString(res
, tmp
);
1293 rv
= PythonCmd_Error(interp
);
1296 Tcl_SetResult(Tkapp_Interp(self
), s
, TCL_VOLATILE
);
1309 PythonCmdDelete(ClientData clientData
)
1311 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1314 Py_XDECREF(data
->self
);
1315 Py_XDECREF(data
->func
);
1323 Tkapp_CreateCommand(PyObject
*self
, PyObject
*args
)
1325 PythonCmd_ClientData
*data
;
1330 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
1332 if (!PyCallable_Check(func
)) {
1333 PyErr_SetString(PyExc_TypeError
, "command not callable");
1337 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
1346 err
= Tcl_CreateCommand(Tkapp_Interp(self
), cmdName
, PythonCmd
,
1347 (ClientData
)data
, PythonCmdDelete
);
1350 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
1362 Tkapp_DeleteCommand(PyObject
*self
, PyObject
*args
)
1367 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
1370 err
= Tcl_DeleteCommand(Tkapp_Interp(self
), cmdName
);
1373 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
1382 #ifdef HAVE_CREATEFILEHANDLER
1383 /** File Handler **/
1385 typedef struct _fhcdata
{
1389 struct _fhcdata
*next
;
1390 } FileHandler_ClientData
;
1392 static FileHandler_ClientData
*HeadFHCD
;
1394 static FileHandler_ClientData
*
1395 NewFHCD(PyObject
*func
, PyObject
*file
, int id
)
1397 FileHandler_ClientData
*p
;
1398 p
= PyMem_NEW(FileHandler_ClientData
, 1);
1414 FileHandler_ClientData
*p
, **pp
;
1417 while ((p
= *pp
) != NULL
) {
1420 Py_XDECREF(p
->func
);
1421 Py_XDECREF(p
->file
);
1430 FileHandler(ClientData clientData
, int mask
)
1432 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
1433 PyObject
*func
, *file
, *arg
, *res
;
1439 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
1440 res
= PyEval_CallObject(func
, arg
);
1445 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1452 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
1453 /* args is (file, mask, func) */
1455 FileHandler_ClientData
*data
;
1456 PyObject
*file
, *func
;
1459 if (!PyArg_ParseTuple(args
, "OiO:createfilehandler",
1460 &file
, &mask
, &func
))
1462 tfile
= PyObject_AsFileDescriptor(file
);
1465 if (!PyCallable_Check(func
)) {
1466 PyErr_SetString(PyExc_TypeError
, "bad argument list");
1470 data
= NewFHCD(func
, file
, tfile
);
1474 /* Ought to check for null Tcl_File object... */
1476 Tcl_CreateFileHandler(tfile
, mask
, FileHandler
, (ClientData
) data
);
1483 Tkapp_DeleteFileHandler(PyObject
*self
, PyObject
*args
)
1488 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
1490 tfile
= PyObject_AsFileDescriptor(file
);
1496 /* Ought to check for null Tcl_File object... */
1498 Tcl_DeleteFileHandler(tfile
);
1503 #endif /* HAVE_CREATEFILEHANDLER */
1506 /**** Tktt Object (timer token) ****/
1508 staticforward PyTypeObject Tktt_Type
;
1512 Tcl_TimerToken token
;
1517 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
1519 TkttObject
*v
= (TkttObject
*)self
;
1520 PyObject
*func
= v
->func
;
1522 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
1524 if (v
->token
!= NULL
) {
1525 Tcl_DeleteTimerHandler(v
->token
);
1531 Py_DECREF(v
); /* See Tktt_New() */
1537 static PyMethodDef Tktt_methods
[] =
1539 {"deletetimerhandler", Tktt_DeleteTimerHandler
, 1},
1544 Tktt_New(PyObject
*func
)
1548 v
= PyObject_New(TkttObject
, &Tktt_Type
);
1556 /* Extra reference, deleted when called or when handler is deleted */
1562 Tktt_Dealloc(PyObject
*self
)
1564 TkttObject
*v
= (TkttObject
*)self
;
1565 PyObject
*func
= v
->func
;
1573 Tktt_Repr(PyObject
*self
)
1575 TkttObject
*v
= (TkttObject
*)self
;
1578 sprintf(buf
, "<tktimertoken at %p%s>", v
,
1579 v
->func
== NULL
? ", handler deleted" : "");
1580 return PyString_FromString(buf
);
1584 Tktt_GetAttr(PyObject
*self
, char *name
)
1586 return Py_FindMethod(Tktt_methods
, self
, name
);
1589 static PyTypeObject Tktt_Type
=
1591 PyObject_HEAD_INIT(NULL
)
1593 "tktimertoken", /*tp_name */
1594 sizeof(TkttObject
), /*tp_basicsize */
1596 Tktt_Dealloc
, /*tp_dealloc */
1598 Tktt_GetAttr
, /*tp_getattr */
1601 Tktt_Repr
, /*tp_repr */
1602 0, /*tp_as_number */
1603 0, /*tp_as_sequence */
1604 0, /*tp_as_mapping */
1610 /** Timer Handler **/
1613 TimerHandler(ClientData clientData
)
1615 TkttObject
*v
= (TkttObject
*)clientData
;
1616 PyObject
*func
= v
->func
;
1626 res
= PyEval_CallObject(func
, NULL
);
1628 Py_DECREF(v
); /* See Tktt_New() */
1632 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1641 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
1647 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler",
1648 &milliseconds
, &func
))
1650 if (!PyCallable_Check(func
)) {
1651 PyErr_SetString(PyExc_TypeError
, "bad argument list");
1655 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
1658 return (PyObject
*) v
;
1665 Tkapp_MainLoop(PyObject
*self
, PyObject
*args
)
1669 PyThreadState
*tstate
= PyThreadState_Get();
1672 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
1676 while (Tk_GetNumMainWindows() > threshold
&&
1683 Py_BEGIN_ALLOW_THREADS
1684 PyThread_acquire_lock(tcl_lock
, 1);
1685 tcl_tstate
= tstate
;
1686 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
1688 PyThread_release_lock(tcl_lock
);
1691 Py_END_ALLOW_THREADS
1693 result
= Tcl_DoOneEvent(0);
1696 if (PyErr_CheckSignals() != 0)
1705 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
1706 excInCmd
= valInCmd
= trbInCmd
= NULL
;
1714 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
1719 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
1723 rv
= Tcl_DoOneEvent(flags
);
1725 return Py_BuildValue("i", rv
);
1729 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
1732 if (!PyArg_ParseTuple(args
, ":quit"))
1741 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
1744 if (!PyArg_ParseTuple(args
, ":interpaddr"))
1747 return PyInt_FromLong((long)Tkapp_Interp(self
));
1752 /**** Tkapp Method List ****/
1754 static PyMethodDef Tkapp_methods
[] =
1756 {"call", Tkapp_Call
, 0},
1757 {"globalcall", Tkapp_GlobalCall
, 0},
1758 {"eval", Tkapp_Eval
, 1},
1759 {"globaleval", Tkapp_GlobalEval
, 1},
1760 {"evalfile", Tkapp_EvalFile
, 1},
1761 {"record", Tkapp_Record
, 1},
1762 {"adderrorinfo", Tkapp_AddErrorInfo
, 1},
1763 {"setvar", Tkapp_SetVar
, 1},
1764 {"globalsetvar", Tkapp_GlobalSetVar
, 1},
1765 {"getvar", Tkapp_GetVar
, 1},
1766 {"globalgetvar", Tkapp_GlobalGetVar
, 1},
1767 {"unsetvar", Tkapp_UnsetVar
, 1},
1768 {"globalunsetvar", Tkapp_GlobalUnsetVar
, 1},
1769 {"getint", Tkapp_GetInt
, 1},
1770 {"getdouble", Tkapp_GetDouble
, 1},
1771 {"getboolean", Tkapp_GetBoolean
, 1},
1772 {"exprstring", Tkapp_ExprString
, 1},
1773 {"exprlong", Tkapp_ExprLong
, 1},
1774 {"exprdouble", Tkapp_ExprDouble
, 1},
1775 {"exprboolean", Tkapp_ExprBoolean
, 1},
1776 {"splitlist", Tkapp_SplitList
, 1},
1777 {"split", Tkapp_Split
, 1},
1778 {"merge", Tkapp_Merge
, 0},
1779 {"createcommand", Tkapp_CreateCommand
, 1},
1780 {"deletecommand", Tkapp_DeleteCommand
, 1},
1781 #ifdef HAVE_CREATEFILEHANDLER
1782 {"createfilehandler", Tkapp_CreateFileHandler
, 1},
1783 {"deletefilehandler", Tkapp_DeleteFileHandler
, 1},
1785 {"createtimerhandler", Tkapp_CreateTimerHandler
, 1},
1786 {"mainloop", Tkapp_MainLoop
, 1},
1787 {"dooneevent", Tkapp_DoOneEvent
, 1},
1788 {"quit", Tkapp_Quit
, 1},
1789 {"interpaddr", Tkapp_InterpAddr
, 1},
1795 /**** Tkapp Type Methods ****/
1798 Tkapp_Dealloc(PyObject
*self
)
1801 Tcl_DeleteInterp(Tkapp_Interp(self
));
1808 Tkapp_GetAttr(PyObject
*self
, char *name
)
1810 return Py_FindMethod(Tkapp_methods
, self
, name
);
1813 static PyTypeObject Tkapp_Type
=
1815 PyObject_HEAD_INIT(NULL
)
1817 "tkapp", /*tp_name */
1818 sizeof(TkappObject
), /*tp_basicsize */
1820 Tkapp_Dealloc
, /*tp_dealloc */
1822 Tkapp_GetAttr
, /*tp_getattr */
1826 0, /*tp_as_number */
1827 0, /*tp_as_sequence */
1828 0, /*tp_as_mapping */
1834 /**** Tkinter Module ****/
1838 int size
; /* current size */
1839 int maxsize
; /* allocated size */
1843 _bump(FlattenContext
* context
, int size
)
1845 /* expand tuple to hold (at least) size new items.
1846 return true if successful, false if an exception was raised */
1848 int maxsize
= context
->maxsize
* 2;
1850 if (maxsize
< context
->size
+ size
)
1851 maxsize
= context
->size
+ size
;
1853 context
->maxsize
= maxsize
;
1855 return _PyTuple_Resize(&context
->tuple
, maxsize
, 0) >= 0;
1859 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
1861 /* add tuple or list to argument tuple (recursively) */
1866 PyErr_SetString(PyExc_ValueError
,
1867 "nesting too deep in _flatten");
1869 } else if (PyList_Check(item
)) {
1870 size
= PyList_GET_SIZE(item
);
1871 /* preallocate (assume no nesting) */
1872 if (context
->size
+ size
> context
->maxsize
&&
1873 !_bump(context
, size
))
1875 /* copy items to output tuple */
1876 for (i
= 0; i
< size
; i
++) {
1877 PyObject
*o
= PyList_GET_ITEM(item
, i
);
1878 if (PyList_Check(o
) || PyTuple_Check(o
)) {
1879 if (!_flatten1(context
, o
, depth
+ 1))
1881 } else if (o
!= Py_None
) {
1882 if (context
->size
+ 1 > context
->maxsize
&&
1886 PyTuple_SET_ITEM(context
->tuple
,
1887 context
->size
++, o
);
1890 } else if (PyTuple_Check(item
)) {
1891 /* same, for tuples */
1892 size
= PyTuple_GET_SIZE(item
);
1893 if (context
->size
+ size
> context
->maxsize
&&
1894 !_bump(context
, size
))
1896 for (i
= 0; i
< size
; i
++) {
1897 PyObject
*o
= PyTuple_GET_ITEM(item
, i
);
1898 if (PyList_Check(o
) || PyTuple_Check(o
)) {
1899 if (!_flatten1(context
, o
, depth
+ 1))
1901 } else if (o
!= Py_None
) {
1902 if (context
->size
+ 1 > context
->maxsize
&&
1906 PyTuple_SET_ITEM(context
->tuple
,
1907 context
->size
++, o
);
1911 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
1918 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
1920 FlattenContext context
;
1923 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
1926 context
.maxsize
= PySequence_Size(item
);
1927 if (context
.maxsize
<= 0)
1928 return PyTuple_New(0);
1930 context
.tuple
= PyTuple_New(context
.maxsize
);
1936 if (!_flatten1(&context
, item
,0))
1939 if (_PyTuple_Resize(&context
.tuple
, context
.size
, 0))
1942 return context
.tuple
;
1946 Tkinter_Create(PyObject
*self
, PyObject
*args
)
1948 char *screenName
= NULL
;
1949 char *baseName
= NULL
;
1950 char *className
= NULL
;
1951 int interactive
= 0;
1953 baseName
= strrchr(Py_GetProgramName(), '/');
1954 if (baseName
!= NULL
)
1957 baseName
= Py_GetProgramName();
1960 if (!PyArg_ParseTuple(args
, "|zssi:create",
1961 &screenName
, &baseName
, &className
,
1965 return (PyObject
*) Tkapp_New(screenName
, baseName
, className
,
1969 static PyMethodDef moduleMethods
[] =
1971 {"_flatten", Tkinter_Flatten
, 1},
1972 {"create", Tkinter_Create
, 1},
1973 #ifdef HAVE_CREATEFILEHANDLER
1974 {"createfilehandler", Tkapp_CreateFileHandler
, 1},
1975 {"deletefilehandler", Tkapp_DeleteFileHandler
, 1},
1977 {"createtimerhandler", Tkapp_CreateTimerHandler
, 1},
1978 {"mainloop", Tkapp_MainLoop
, 1},
1979 {"dooneevent", Tkapp_DoOneEvent
, 1},
1980 {"quit", Tkapp_Quit
, 1},
1984 #ifdef WAIT_FOR_STDIN
1986 static int stdin_ready
= 0;
1990 MyFileProc(void *clientData
, int mask
)
1996 static PyThreadState
*event_tstate
= NULL
;
2005 PyEval_RestoreThread(event_tstate
);
2010 tfile
= fileno(stdin
);
2011 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
2013 while (!errorInCmd
&& !stdin_ready
) {
2021 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
2022 Py_BEGIN_ALLOW_THREADS
2023 PyThread_acquire_lock(tcl_lock
, 1);
2024 tcl_tstate
= event_tstate
;
2026 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
2029 PyThread_release_lock(tcl_lock
);
2032 Py_END_ALLOW_THREADS
2034 result
= Tcl_DoOneEvent(0);
2041 Tcl_DeleteFileHandler(tfile
);
2045 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2046 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2050 PyEval_SaveThread();
2058 EnableEventHook(void)
2060 #ifdef WAIT_FOR_STDIN
2061 if (PyOS_InputHook
== NULL
) {
2063 event_tstate
= PyThreadState_Get();
2065 PyOS_InputHook
= EventHook
;
2071 DisableEventHook(void)
2073 #ifdef WAIT_FOR_STDIN
2074 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
2075 PyOS_InputHook
= NULL
;
2081 /* all errors will be checked in one fell swoop in init_tkinter() */
2083 ins_long(PyObject
*d
, char *name
, long val
)
2085 PyObject
*v
= PyInt_FromLong(val
);
2087 PyDict_SetItemString(d
, name
, v
);
2092 ins_string(PyObject
*d
, char *name
, char *val
)
2094 PyObject
*v
= PyString_FromString(val
);
2096 PyDict_SetItemString(d
, name
, v
);
2107 Tkapp_Type
.ob_type
= &PyType_Type
;
2110 tcl_lock
= PyThread_allocate_lock();
2113 m
= Py_InitModule("_tkinter", moduleMethods
);
2115 d
= PyModule_GetDict(m
);
2116 Tkinter_TclError
= Py_BuildValue("s", "TclError");
2117 PyDict_SetItemString(d
, "TclError", Tkinter_TclError
);
2119 ins_long(d
, "READABLE", TCL_READABLE
);
2120 ins_long(d
, "WRITABLE", TCL_WRITABLE
);
2121 ins_long(d
, "EXCEPTION", TCL_EXCEPTION
);
2122 ins_long(d
, "WINDOW_EVENTS", TCL_WINDOW_EVENTS
);
2123 ins_long(d
, "FILE_EVENTS", TCL_FILE_EVENTS
);
2124 ins_long(d
, "TIMER_EVENTS", TCL_TIMER_EVENTS
);
2125 ins_long(d
, "IDLE_EVENTS", TCL_IDLE_EVENTS
);
2126 ins_long(d
, "ALL_EVENTS", TCL_ALL_EVENTS
);
2127 ins_long(d
, "DONT_WAIT", TCL_DONT_WAIT
);
2128 ins_string(d
, "TK_VERSION", TK_VERSION
);
2129 ins_string(d
, "TCL_VERSION", TCL_VERSION
);
2131 PyDict_SetItemString(d
, "TkappType", (PyObject
*)&Tkapp_Type
);
2133 Tktt_Type
.ob_type
= &PyType_Type
;
2134 PyDict_SetItemString(d
, "TkttType", (PyObject
*)&Tktt_Type
);
2136 /* This helps the dynamic loader; in Unicode aware Tcl versions
2137 it also helps Tcl find its encodings. */
2138 Tcl_FindExecutable(Py_GetProgramName());
2140 if (PyErr_Occurred())
2144 /* This was not a good idea; through <Destroy> bindings,
2145 Tcl_Finalize() may invoke Python code but at that point the
2146 interpreter and thread state have already been destroyed! */
2147 Py_AtExit(Tcl_Finalize
);
2152 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2153 ** Most of the initializations in that routine (toolbox init calls and
2154 ** such) have already been done for us, so we only need these.
2158 Tcl_MacSetEventProc(PyMacConvertEvent
);
2160 mac_addlibresources();
2161 #endif /* GENERATINGCFM */
2162 #endif /* macintosh */
2170 ** Anyone who embeds Tcl/Tk on the Mac must define panic().
2174 panic(char * format
, ...)
2178 va_start(varg
, format
);
2180 vfprintf(stderr
, format
, varg
);
2181 (void) fflush(stderr
);
2185 Py_FatalError("Tcl/Tk panic");
2189 ** Pass events to SIOUX before passing them to Tk.
2193 PyMacConvertEvent(EventRecord
*eventPtr
)
2197 ** Sioux eats too many events, so we don't pass it everything. We
2198 ** always pass update events to Sioux, and we only pass other events if
2199 ** the Sioux window is frontmost. This means that Tk menus don't work
2200 ** in that case, but at least we can scroll the sioux window.
2201 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2202 ** part of the external interface of Sioux...
2204 frontwin
= FrontWindow();
2205 if ( eventPtr
->what
== updateEvt
|| SIOUXIsAppWindow(frontwin
) ) {
2206 if (SIOUXHandleOneEvent(eventPtr
))
2207 return 0; /* Nothing happened to the Tcl event queue */
2209 return TkMacConvertEvent(eventPtr
);
2215 ** Additional Mac specific code for dealing with shared libraries.
2218 #include <Resources.h>
2219 #include <CodeFragments.h>
2221 static int loaded_from_shlib
= 0;
2222 static FSSpec library_fss
;
2225 ** If this module is dynamically loaded the following routine should
2226 ** be the init routine. It takes care of adding the shared library to
2227 ** the resource-file chain, so that the tk routines can find their
2231 init_tkinter_shlib(CFragInitBlockPtr data
)
2234 if ( data
== nil
) return noErr
;
2235 if ( data
->fragLocator
.where
== kDataForkCFragLocator
) {
2236 library_fss
= *data
->fragLocator
.u
.onDisk
.fileSpec
;
2237 loaded_from_shlib
= 1;
2238 } else if ( data
->fragLocator
.where
== kResourceCFragLocator
) {
2239 library_fss
= *data
->fragLocator
.u
.inSegs
.fileSpec
;
2240 loaded_from_shlib
= 1;
2246 ** Insert the library resources into the search path. Put them after
2247 ** the resources from the application. Again, we ignore errors.
2250 mac_addlibresources(void)
2252 if ( !loaded_from_shlib
)
2254 (void)FSpOpenResFile(&library_fss
, fsRdPerm
);
2257 #endif /* GENERATINGCFM */
2258 #endif /* macintosh */