1 /***********************************************************
2 Copyright (C) 1994 Steen Lumholt.
3 Copyright 1994-1995 by Stichting Mathematisch Centrum, Amsterdam,
8 Copyright (c) 2000, BeOpen.com.
9 Copyright (c) 1995-2000, Corporation for National Research Initiatives.
10 Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
13 See the file "Misc/COPYRIGHT" for information on usage and
14 redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
16 ******************************************************************/
18 /* _tkinter.c -- Interface to libtk.a and libtcl.a. */
20 /* TCL/TK VERSION INFO:
22 Only Tcl/Tk 8.0 and later are supported. Older versions are not
23 supported. (Use Python 1.5.2 if you cannot upgrade your Tcl/Tk
27 /* XXX Further speed-up ideas, involving Tcl 8.0 features:
29 - In Tcl_Call(), create Tcl objects from the arguments, possibly using
30 intelligent mappings between Python objects and Tcl objects (e.g. ints,
31 floats and Tcl window pointers could be handled specially).
33 - Register a new Tcl type, "Python callable", which can be called more
34 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
57 #define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
59 #if TKMAJORMINOR < 8000
60 #error "Tk older than 8.0 not supported"
63 #if defined(macintosh)
64 /* Sigh, we have to include this to get at the tcl qd pointer */
66 /* And this one we need to clear the menu bar */
70 #if !defined(MS_WINDOWS)
71 #define HAVE_CREATEFILEHANDLER
74 #ifdef HAVE_CREATEFILEHANDLER
76 /* Tcl_CreateFileHandler() changed several times; these macros deal with the
77 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
78 Unix, only because Jack added it back); when available on Windows, it only
79 applies to sockets. */
82 #define FHANDLETYPE TCL_WIN_SOCKET
84 #define FHANDLETYPE TCL_UNIX_FD
87 /* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
88 which uses this to handle Tcl events while the user is typing commands. */
90 #if FHANDLETYPE == TCL_UNIX_FD
91 #define WAIT_FOR_STDIN
94 #endif /* HAVE_CREATEFILEHANDLER */
98 #define WAIT_FOR_STDIN
103 /* The threading situation is complicated. Tcl is not thread-safe, except for
104 Tcl 8.1, which will probably remain in alpha status for another 6 months
105 (and the README says that Tk will probably remain thread-unsafe forever).
106 So we need to use a lock around all uses of Tcl. Previously, the Python
107 interpreter lock was used for this. However, this causes problems when
108 other Python threads need to run while Tcl is blocked waiting for events.
110 To solve this problem, a separate lock for Tcl is introduced. Holding it
111 is incompatible with holding Python's interpreter lock. The following four
112 macros manipulate both locks together.
114 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
115 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
116 that could call an event handler, or otherwise affect the state of a Tcl
117 interpreter. These assume that the surrounding code has the Python
118 interpreter lock; inside the brackets, the Python interpreter lock has been
119 released and the lock for Tcl has been acquired.
121 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
122 (For example, when transferring data from the Tcl interpreter result to a
123 Python string object.) This can be done by using different macros to close
124 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
125 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
126 releases the Tcl lock.
128 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
129 handlers when the handler needs to use Python. Such event handlers are
130 entered while the lock for Tcl is held; the event handler presumably needs
131 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
132 the Python interpreter lock, restoring the appropriate thread state, and
133 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
134 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
135 the code between ENTER_PYTHON and LEAVE_PYTHON.
137 These locks expand to several statements and brackets; they should not be
138 used in branches of if statements and the like.
142 static PyThread_type_lock tcl_lock
= 0;
143 static PyThreadState
*tcl_tstate
= NULL
;
146 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
147 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
150 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
152 #define ENTER_OVERLAP \
155 #define LEAVE_OVERLAP_TCL \
156 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); }
158 #define ENTER_PYTHON \
159 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
160 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
162 #define LEAVE_PYTHON \
163 { PyThreadState *tstate = PyEval_SaveThread(); \
164 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
170 #define ENTER_OVERLAP
171 #define LEAVE_OVERLAP_TCL
180 ** Additional cruft needed by Tcl/Tk on the Mac.
181 ** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
184 /* ckfree() expects a char* */
185 #define FREECAST (char *)
187 #include <Events.h> /* For EventRecord */
189 typedef int (*TclMacConvertEventPtr
) (EventRecord
*eventPtr
);
190 void Tcl_MacSetEventProc (TclMacConvertEventPtr procPtr
);
191 int TkMacConvertEvent (EventRecord
*eventPtr
);
193 staticforward
int PyMacConvertEvent (EventRecord
*eventPtr
);
195 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
200 extern int SIOUXIsAppWindow(WindowPtr
);
202 #if defined(__CFM68K__) && !defined(__USING_STATIC_LIBS__)
205 #endif /* macintosh */
208 #define FREECAST (char *)
211 /**** Tkapp Object Declaration ****/
213 staticforward PyTypeObject Tkapp_Type
;
220 #define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
221 #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
222 #define Tkapp_Result(v) (((TkappObject *) (v))->interp->result)
224 #define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
225 (void *) v, ((PyObject *) v)->ob_refcnt))
229 /**** Error Handling ****/
231 static PyObject
*Tkinter_TclError
;
232 static int quitMainLoop
= 0;
233 static int errorInCmd
= 0;
234 static PyObject
*excInCmd
;
235 static PyObject
*valInCmd
;
236 static PyObject
*trbInCmd
;
241 Tkinter_Error(PyObject
*v
)
243 PyErr_SetString(Tkinter_TclError
, Tkapp_Result(v
));
254 /* Millisecond sleep() for Unix platforms. */
259 /* XXX Too bad if you don't have select(). */
261 t
.tv_sec
= milli
/1000;
262 t
.tv_usec
= (milli
%1000) * 1000;
263 select(0, (fd_set
*)0, (fd_set
*)0, (fd_set
*)0, &t
);
265 #endif /* MS_WINDOWS */
266 #endif /* WITH_THREAD */
270 AsString(PyObject
*value
, PyObject
*tmp
)
272 if (PyString_Check(value
))
273 return PyString_AsString(value
);
275 PyObject
*v
= PyObject_Str(value
);
276 PyList_Append(tmp
, v
);
278 return PyString_AsString(v
);
287 Merge(PyObject
*args
)
289 PyObject
*tmp
= NULL
;
290 char *argvStore
[ARGSZ
];
297 if (!(tmp
= PyList_New(0)))
306 else if (!PyTuple_Check(args
)) {
309 argv
[0] = AsString(args
, tmp
);
312 argc
= PyTuple_Size(args
);
315 argv
= (char **)ckalloc(argc
* sizeof(char *));
316 fv
= (int *)ckalloc(argc
* sizeof(int));
317 if (argv
== NULL
|| fv
== NULL
) {
323 for (i
= 0; i
< argc
; i
++) {
324 PyObject
*v
= PyTuple_GetItem(args
, i
);
325 if (PyTuple_Check(v
)) {
327 if (!(argv
[i
] = Merge(v
)))
330 else if (v
== Py_None
) {
336 argv
[i
] = AsString(v
, tmp
);
340 res
= Tcl_Merge(argc
, argv
);
343 for (i
= 0; i
< argc
; i
++)
347 if (argv
!= argvStore
)
348 ckfree(FREECAST argv
);
370 if (Tcl_SplitList((Tcl_Interp
*)NULL
, list
, &argc
, &argv
) != TCL_OK
) {
372 * Could be a quoted string containing funnies, e.g. {"}.
373 * Return the string itself.
375 return PyString_FromString(list
);
379 v
= PyString_FromString("");
381 v
= PyString_FromString(argv
[0]);
382 else if ((v
= PyTuple_New(argc
)) != NULL
) {
386 for (i
= 0; i
< argc
; i
++) {
387 if ((w
= Split(argv
[i
])) == NULL
) {
392 PyTuple_SetItem(v
, i
, w
);
395 Tcl_Free(FREECAST argv
);
401 /**** Tkapp Object ****/
405 Tcl_AppInit(Tcl_Interp
*interp
)
409 main
= Tk_MainWindow(interp
);
410 if (Tcl_Init(interp
) == TCL_ERROR
) {
411 PySys_WriteStderr("Tcl_Init error: %s\n", interp
->result
);
414 if (Tk_Init(interp
) == TCL_ERROR
) {
415 PySys_WriteStderr("Tk_Init error: %s\n", interp
->result
);
420 #endif /* !WITH_APPINIT */
425 /* Initialize the Tk application; see the `main' function in
429 static void EnableEventHook(void); /* Forward */
430 static void DisableEventHook(void); /* Forward */
433 Tkapp_New(char *screenName
, char *baseName
, char *className
, int interactive
)
438 v
= PyObject_New(TkappObject
, &Tkapp_Type
);
442 v
->interp
= Tcl_CreateInterp();
444 #if defined(macintosh)
445 /* This seems to be needed */
447 TkMacInitMenus(v
->interp
);
449 /* Delete the 'exit' command, which can screw things up */
450 Tcl_DeleteCommand(v
->interp
, "exit");
452 if (screenName
!= NULL
)
453 Tcl_SetVar2(v
->interp
, "env", "DISPLAY",
454 screenName
, TCL_GLOBAL_ONLY
);
457 Tcl_SetVar(v
->interp
, "tcl_interactive", "1", TCL_GLOBAL_ONLY
);
459 Tcl_SetVar(v
->interp
, "tcl_interactive", "0", TCL_GLOBAL_ONLY
);
461 /* This is used to get the application class for Tk 4.1 and up */
462 argv0
= (char*)ckalloc(strlen(className
) + 1);
469 strcpy(argv0
, className
);
470 if (isupper((int)(argv0
[0])))
471 argv0
[0] = tolower(argv0
[0]);
472 Tcl_SetVar(v
->interp
, "argv0", argv0
, TCL_GLOBAL_ONLY
);
475 if (Tcl_AppInit(v
->interp
) != TCL_OK
)
476 return (TkappObject
*)Tkinter_Error((PyObject
*)v
);
487 #if TKMAJORMINOR >= 8001
488 #define USING_OBJECTS
494 AsObj(PyObject
*value
)
498 if (PyString_Check(value
))
499 return Tcl_NewStringObj(PyString_AS_STRING(value
),
500 PyString_GET_SIZE(value
));
501 else if (PyInt_Check(value
))
502 return Tcl_NewLongObj(PyInt_AS_LONG(value
));
503 else if (PyFloat_Check(value
))
504 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value
));
505 else if (PyTuple_Check(value
)) {
506 Tcl_Obj
**argv
= (Tcl_Obj
**)
507 ckalloc(PyTuple_Size(value
)*sizeof(Tcl_Obj
*));
511 for(i
=0;i
<PyTuple_Size(value
);i
++)
512 argv
[i
] = AsObj(PyTuple_GetItem(value
,i
));
513 result
= Tcl_NewListObj(PyTuple_Size(value
), argv
);
514 ckfree(FREECAST argv
);
517 else if (PyUnicode_Check(value
)) {
518 #if TKMAJORMINOR <= 8001
519 /* In Tcl 8.1 we must use UTF-8 */
520 PyObject
* utf8
= PyUnicode_AsUTF8String (value
);
523 result
= Tcl_NewStringObj (PyString_AS_STRING (utf8
),
524 PyString_GET_SIZE (utf8
));
527 #else /* TKMAJORMINOR > 8001 */
528 /* In Tcl 8.2 and later, use Tcl_NewUnicodeObj() */
529 if (sizeof(Py_UNICODE
) != sizeof(Tcl_UniChar
)) {
530 /* XXX Should really test this at compile time */
531 PyErr_SetString(PyExc_SystemError
,
532 "Py_UNICODE and Tcl_UniChar differ in size");
535 return Tcl_NewUnicodeObj(PyUnicode_AS_UNICODE(value
),
536 PyUnicode_GET_SIZE(value
));
537 #endif /* TKMAJORMINOR > 8001 */
540 PyObject
*v
= PyObject_Str(value
);
550 Tkapp_Call(PyObject
*self
, PyObject
*args
)
552 Tcl_Obj
*objStore
[ARGSZ
];
553 Tcl_Obj
**objv
= NULL
;
555 PyObject
*res
= NULL
;
556 Tcl_Interp
*interp
= Tkapp_Interp(self
);
557 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
558 int flags
= TCL_EVAL_DIRECT
;
565 else if (!PyTuple_Check(args
)) {
567 objv
[0] = AsObj(args
);
570 Tcl_IncrRefCount(objv
[0]);
573 objc
= PyTuple_Size(args
);
576 objv
= (Tcl_Obj
**)ckalloc(objc
* sizeof(char *));
583 for (i
= 0; i
< objc
; i
++) {
584 PyObject
*v
= PyTuple_GetItem(args
, i
);
592 Tcl_IncrRefCount(objv
[i
]);
598 i
= Tcl_EvalObjv(interp
, objc
, objv
, flags
);
604 /* We could request the object result here, but doing
605 so would confuse applications that expect a string. */
606 char *s
= Tcl_GetStringResult(interp
);
608 /* If the result contains any bytes with the top bit set,
609 it's UTF-8 and we should decode it to Unicode */
616 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
618 /* Convert UTF-8 to Unicode string */
620 res
= PyUnicode_DecodeUTF8(s
, (int)(p
-s
), "strict");
623 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
631 for (i
= 0; i
< objc
; i
++)
632 Tcl_DecrRefCount(objv
[i
]);
633 if (objv
!= objStore
)
634 ckfree(FREECAST objv
);
638 #else /* !USING_OBJECTS */
641 Tkapp_Call(PyObject
*self
, PyObject
*args
)
643 /* This is copied from Merge() */
644 PyObject
*tmp
= NULL
;
645 char *argvStore
[ARGSZ
];
650 PyObject
*res
= NULL
; /* except this has a different type */
651 Tcl_CmdInfo info
; /* and this is added */
652 Tcl_Interp
*interp
= Tkapp_Interp(self
); /* and this too */
654 if (!(tmp
= PyList_New(0)))
663 else if (!PyTuple_Check(args
)) {
666 argv
[0] = AsString(args
, tmp
);
669 argc
= PyTuple_Size(args
);
672 argv
= (char **)ckalloc(argc
* sizeof(char *));
673 fv
= (int *)ckalloc(argc
* sizeof(int));
674 if (argv
== NULL
|| fv
== NULL
) {
680 for (i
= 0; i
< argc
; i
++) {
681 PyObject
*v
= PyTuple_GetItem(args
, i
);
682 if (PyTuple_Check(v
)) {
684 if (!(argv
[i
] = Merge(v
)))
687 else if (v
== Py_None
) {
693 argv
[i
] = AsString(v
, tmp
);
697 /* End code copied from Merge() */
699 /* All this to avoid a call to Tcl_Merge() and the corresponding call
700 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
701 if (Py_VerboseFlag
>= 2) {
702 for (i
= 0; i
< argc
; i
++)
703 PySys_WriteStderr("%s ", argv
[i
]);
708 !Tcl_GetCommandInfo(interp
, argv
[0], &info
) ||
712 cmd
= Tcl_Merge(argc
, argv
);
713 i
= Tcl_Eval(interp
, cmd
);
717 Tcl_ResetResult(interp
);
718 i
= (*info
.proc
)(info
.clientData
, interp
, argc
, argv
);
721 if (info
.proc
== NULL
&& Py_VerboseFlag
>= 2)
722 PySys_WriteStderr("... use TclEval ");
723 if (i
== TCL_ERROR
) {
724 if (Py_VerboseFlag
>= 2)
725 PySys_WriteStderr("... error: '%s'\n",
730 if (Py_VerboseFlag
>= 2)
731 PySys_WriteStderr("-> '%s'\n", interp
->result
);
732 res
= PyString_FromString(interp
->result
);
736 /* Copied from Merge() again */
738 for (i
= 0; i
< argc
; i
++)
742 if (argv
!= argvStore
)
743 ckfree(FREECAST argv
);
751 #endif /* !USING_OBJECTS */
754 Tkapp_GlobalCall(PyObject
*self
, PyObject
*args
)
756 /* Could do the same here as for Tkapp_Call(), but this is not used
757 much, so I can't be bothered. Unfortunately Tcl doesn't export a
758 way for the user to do what all its Global* variants do (save and
759 reset the scope pointer, call the local version, restore the saved
763 PyObject
*res
= NULL
;
767 PyErr_SetString(Tkinter_TclError
, "merge failed");
772 err
= Tcl_GlobalEval(Tkapp_Interp(self
), cmd
);
774 if (err
== TCL_ERROR
)
775 res
= Tkinter_Error(self
);
777 res
= PyString_FromString(Tkapp_Result(self
));
788 Tkapp_Eval(PyObject
*self
, PyObject
*args
)
791 PyObject
*res
= NULL
;
794 if (!PyArg_ParseTuple(args
, "s:eval", &script
))
798 err
= Tcl_Eval(Tkapp_Interp(self
), script
);
800 if (err
== TCL_ERROR
)
801 res
= Tkinter_Error(self
);
803 res
= PyString_FromString(Tkapp_Result(self
));
809 Tkapp_GlobalEval(PyObject
*self
, PyObject
*args
)
812 PyObject
*res
= NULL
;
815 if (!PyArg_ParseTuple(args
, "s:globaleval", &script
))
819 err
= Tcl_GlobalEval(Tkapp_Interp(self
), script
);
821 if (err
== TCL_ERROR
)
822 res
= Tkinter_Error(self
);
824 res
= PyString_FromString(Tkapp_Result(self
));
830 Tkapp_EvalFile(PyObject
*self
, PyObject
*args
)
833 PyObject
*res
= NULL
;
836 if (!PyArg_ParseTuple(args
, "s:evalfile", &fileName
))
840 err
= Tcl_EvalFile(Tkapp_Interp(self
), fileName
);
842 if (err
== TCL_ERROR
)
843 res
= Tkinter_Error(self
);
846 res
= PyString_FromString(Tkapp_Result(self
));
852 Tkapp_Record(PyObject
*self
, PyObject
*args
)
855 PyObject
*res
= NULL
;
858 if (!PyArg_ParseTuple(args
, "s", &script
))
862 err
= Tcl_RecordAndEval(Tkapp_Interp(self
), script
, TCL_NO_EVAL
);
864 if (err
== TCL_ERROR
)
865 res
= Tkinter_Error(self
);
867 res
= PyString_FromString(Tkapp_Result(self
));
873 Tkapp_AddErrorInfo(PyObject
*self
, PyObject
*args
)
877 if (!PyArg_ParseTuple(args
, "s:adderrorinfo", &msg
))
880 Tcl_AddErrorInfo(Tkapp_Interp(self
), msg
);
892 SetVar(PyObject
*self
, PyObject
*args
, int flags
)
894 char *name1
, *name2
, *ok
, *s
;
902 if (PyArg_ParseTuple(args
, "sO:setvar", &name1
, &newValue
)) {
904 s
= AsString(newValue
, tmp
);
906 ok
= Tcl_SetVar(Tkapp_Interp(self
), name1
, s
, flags
);
911 if (PyArg_ParseTuple(args
, "ssO:setvar", &name1
, &name2
, &newValue
)) {
912 s
= AsString (newValue
, tmp
);
914 ok
= Tcl_SetVar2(Tkapp_Interp(self
), name1
, name2
,
926 return Tkinter_Error(self
);
933 Tkapp_SetVar(PyObject
*self
, PyObject
*args
)
935 return SetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
939 Tkapp_GlobalSetVar(PyObject
*self
, PyObject
*args
)
941 return SetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
947 GetVar(PyObject
*self
, PyObject
*args
, int flags
)
949 char *name1
, *name2
=NULL
, *s
;
950 PyObject
*res
= NULL
;
952 if (!PyArg_ParseTuple(args
, "s|s:getvar", &name1
, &name2
))
956 s
= Tcl_GetVar(Tkapp_Interp(self
), name1
, flags
);
959 s
= Tcl_GetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
963 res
= Tkinter_Error(self
);
965 res
= PyString_FromString(s
);
971 Tkapp_GetVar(PyObject
*self
, PyObject
*args
)
973 return GetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
977 Tkapp_GlobalGetVar(PyObject
*self
, PyObject
*args
)
979 return GetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
985 UnsetVar(PyObject
*self
, PyObject
*args
, int flags
)
987 char *name1
, *name2
=NULL
;
988 PyObject
*res
= NULL
;
991 if (!PyArg_ParseTuple(args
, "s|s:unsetvar", &name1
, &name2
))
995 code
= Tcl_UnsetVar(Tkapp_Interp(self
), name1
, flags
);
998 code
= Tcl_UnsetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
1001 if (code
== TCL_ERROR
)
1002 res
= Tkinter_Error(self
);
1012 Tkapp_UnsetVar(PyObject
*self
, PyObject
*args
)
1014 return UnsetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
1018 Tkapp_GlobalUnsetVar(PyObject
*self
, PyObject
*args
)
1020 return UnsetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1025 /** Tcl to Python **/
1028 Tkapp_GetInt(PyObject
*self
, PyObject
*args
)
1033 if (!PyArg_ParseTuple(args
, "s:getint", &s
))
1035 if (Tcl_GetInt(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1036 return Tkinter_Error(self
);
1037 return Py_BuildValue("i", v
);
1041 Tkapp_GetDouble(PyObject
*self
, PyObject
*args
)
1046 if (!PyArg_ParseTuple(args
, "s:getdouble", &s
))
1048 if (Tcl_GetDouble(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1049 return Tkinter_Error(self
);
1050 return Py_BuildValue("d", v
);
1054 Tkapp_GetBoolean(PyObject
*self
, PyObject
*args
)
1059 if (!PyArg_ParseTuple(args
, "s:getboolean", &s
))
1061 if (Tcl_GetBoolean(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1062 return Tkinter_Error(self
);
1063 return Py_BuildValue("i", v
);
1067 Tkapp_ExprString(PyObject
*self
, PyObject
*args
)
1070 PyObject
*res
= NULL
;
1073 if (!PyArg_ParseTuple(args
, "s:exprstring", &s
))
1076 retval
= Tcl_ExprString(Tkapp_Interp(self
), s
);
1078 if (retval
== TCL_ERROR
)
1079 res
= Tkinter_Error(self
);
1081 res
= Py_BuildValue("s", Tkapp_Result(self
));
1087 Tkapp_ExprLong(PyObject
*self
, PyObject
*args
)
1090 PyObject
*res
= NULL
;
1094 if (!PyArg_ParseTuple(args
, "s:exprlong", &s
))
1097 retval
= Tcl_ExprLong(Tkapp_Interp(self
), s
, &v
);
1099 if (retval
== TCL_ERROR
)
1100 res
= Tkinter_Error(self
);
1102 res
= Py_BuildValue("l", v
);
1108 Tkapp_ExprDouble(PyObject
*self
, PyObject
*args
)
1111 PyObject
*res
= NULL
;
1115 if (!PyArg_ParseTuple(args
, "s:exprdouble", &s
))
1117 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1119 retval
= Tcl_ExprDouble(Tkapp_Interp(self
), s
, &v
);
1121 PyFPE_END_PROTECT(retval
)
1122 if (retval
== TCL_ERROR
)
1123 res
= Tkinter_Error(self
);
1125 res
= Py_BuildValue("d", v
);
1131 Tkapp_ExprBoolean(PyObject
*self
, PyObject
*args
)
1134 PyObject
*res
= NULL
;
1138 if (!PyArg_ParseTuple(args
, "s:exprboolean", &s
))
1141 retval
= Tcl_ExprBoolean(Tkapp_Interp(self
), s
, &v
);
1143 if (retval
== TCL_ERROR
)
1144 res
= Tkinter_Error(self
);
1146 res
= Py_BuildValue("i", v
);
1154 Tkapp_SplitList(PyObject
*self
, PyObject
*args
)
1162 if (!PyArg_ParseTuple(args
, "s:splitlist", &list
))
1165 if (Tcl_SplitList(Tkapp_Interp(self
), list
, &argc
, &argv
) == TCL_ERROR
)
1166 return Tkinter_Error(self
);
1168 if (!(v
= PyTuple_New(argc
)))
1171 for (i
= 0; i
< argc
; i
++) {
1172 PyObject
*s
= PyString_FromString(argv
[i
]);
1173 if (!s
|| PyTuple_SetItem(v
, i
, s
)) {
1181 ckfree(FREECAST argv
);
1186 Tkapp_Split(PyObject
*self
, PyObject
*args
)
1190 if (!PyArg_ParseTuple(args
, "s:split", &list
))
1196 Tkapp_Merge(PyObject
*self
, PyObject
*args
)
1198 char *s
= Merge(args
);
1199 PyObject
*res
= NULL
;
1202 res
= PyString_FromString(s
);
1206 PyErr_SetString(Tkinter_TclError
, "merge failed");
1215 /* Client data struct */
1219 } PythonCmd_ClientData
;
1222 PythonCmd_Error(Tcl_Interp
*interp
)
1225 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1230 /* This is the Tcl command that acts as a wrapper for Python
1231 * function or method.
1234 PythonCmd(ClientData clientData
, Tcl_Interp
*interp
, int argc
, char *argv
[])
1236 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1237 PyObject
*self
, *func
, *arg
, *res
, *tmp
;
1242 /* TBD: no error checking here since we know, via the
1243 * Tkapp_CreateCommand() that the client data is a two-tuple
1248 /* Create argument list (argv1, ..., argvN) */
1249 if (!(arg
= PyTuple_New(argc
- 1)))
1250 return PythonCmd_Error(interp
);
1252 for (i
= 0; i
< (argc
- 1); i
++) {
1253 PyObject
*s
= PyString_FromString(argv
[i
+ 1]);
1254 if (!s
|| PyTuple_SetItem(arg
, i
, s
)) {
1256 return PythonCmd_Error(interp
);
1259 res
= PyEval_CallObject(func
, arg
);
1263 return PythonCmd_Error(interp
);
1265 if (!(tmp
= PyList_New(0))) {
1267 return PythonCmd_Error(interp
);
1270 Tcl_SetResult(Tkapp_Interp(self
), AsString(res
, tmp
), TCL_VOLATILE
);
1280 PythonCmdDelete(ClientData clientData
)
1282 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1285 Py_XDECREF(data
->self
);
1286 Py_XDECREF(data
->func
);
1294 Tkapp_CreateCommand(PyObject
*self
, PyObject
*args
)
1296 PythonCmd_ClientData
*data
;
1301 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
1303 if (!PyCallable_Check(func
)) {
1304 PyErr_SetString(PyExc_TypeError
, "command not callable");
1308 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
1317 err
= Tcl_CreateCommand(Tkapp_Interp(self
), cmdName
, PythonCmd
,
1318 (ClientData
)data
, PythonCmdDelete
);
1321 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
1333 Tkapp_DeleteCommand(PyObject
*self
, PyObject
*args
)
1338 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
1341 err
= Tcl_DeleteCommand(Tkapp_Interp(self
), cmdName
);
1344 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
1353 #ifdef HAVE_CREATEFILEHANDLER
1354 /** File Handler **/
1356 typedef struct _fhcdata
{
1360 struct _fhcdata
*next
;
1361 } FileHandler_ClientData
;
1363 static FileHandler_ClientData
*HeadFHCD
;
1365 static FileHandler_ClientData
*
1366 NewFHCD(PyObject
*func
, PyObject
*file
, int id
)
1368 FileHandler_ClientData
*p
;
1369 p
= PyMem_NEW(FileHandler_ClientData
, 1);
1385 FileHandler_ClientData
*p
, **pp
;
1388 while ((p
= *pp
) != NULL
) {
1391 Py_XDECREF(p
->func
);
1392 Py_XDECREF(p
->file
);
1401 FileHandler(ClientData clientData
, int mask
)
1403 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
1404 PyObject
*func
, *file
, *arg
, *res
;
1410 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
1411 res
= PyEval_CallObject(func
, arg
);
1416 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1423 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
1424 /* args is (file, mask, func) */
1426 FileHandler_ClientData
*data
;
1427 PyObject
*file
, *func
;
1430 if (!PyArg_ParseTuple(args
, "OiO:createfilehandler", &file
, &mask
, &func
))
1432 tfile
= PyObject_AsFileDescriptor(file
);
1435 if (!PyCallable_Check(func
)) {
1436 PyErr_SetString(PyExc_TypeError
, "bad argument list");
1440 data
= NewFHCD(func
, file
, tfile
);
1444 /* Ought to check for null Tcl_File object... */
1446 Tcl_CreateFileHandler(tfile
, mask
, FileHandler
, (ClientData
) data
);
1453 Tkapp_DeleteFileHandler(PyObject
*self
, PyObject
*args
)
1458 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
1460 tfile
= PyObject_AsFileDescriptor(file
);
1466 /* Ought to check for null Tcl_File object... */
1468 Tcl_DeleteFileHandler(tfile
);
1473 #endif /* HAVE_CREATEFILEHANDLER */
1476 /**** Tktt Object (timer token) ****/
1478 staticforward PyTypeObject Tktt_Type
;
1482 Tcl_TimerToken token
;
1487 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
1489 TkttObject
*v
= (TkttObject
*)self
;
1490 PyObject
*func
= v
->func
;
1492 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
1494 if (v
->token
!= NULL
) {
1495 Tcl_DeleteTimerHandler(v
->token
);
1501 Py_DECREF(v
); /* See Tktt_New() */
1507 static PyMethodDef Tktt_methods
[] =
1509 {"deletetimerhandler", Tktt_DeleteTimerHandler
, 1},
1514 Tktt_New(PyObject
*func
)
1518 v
= PyObject_New(TkttObject
, &Tktt_Type
);
1526 /* Extra reference, deleted when called or when handler is deleted */
1532 Tktt_Dealloc(PyObject
*self
)
1534 TkttObject
*v
= (TkttObject
*)self
;
1535 PyObject
*func
= v
->func
;
1543 Tktt_Repr(PyObject
*self
)
1545 TkttObject
*v
= (TkttObject
*)self
;
1548 sprintf(buf
, "<tktimertoken at %p%s>", v
,
1549 v
->func
== NULL
? ", handler deleted" : "");
1550 return PyString_FromString(buf
);
1554 Tktt_GetAttr(PyObject
*self
, char *name
)
1556 return Py_FindMethod(Tktt_methods
, self
, name
);
1559 static PyTypeObject Tktt_Type
=
1561 PyObject_HEAD_INIT(NULL
)
1563 "tktimertoken", /*tp_name */
1564 sizeof(TkttObject
), /*tp_basicsize */
1566 Tktt_Dealloc
, /*tp_dealloc */
1568 Tktt_GetAttr
, /*tp_getattr */
1571 Tktt_Repr
, /*tp_repr */
1572 0, /*tp_as_number */
1573 0, /*tp_as_sequence */
1574 0, /*tp_as_mapping */
1580 /** Timer Handler **/
1583 TimerHandler(ClientData clientData
)
1585 TkttObject
*v
= (TkttObject
*)clientData
;
1586 PyObject
*func
= v
->func
;
1596 res
= PyEval_CallObject(func
, NULL
);
1598 Py_DECREF(v
); /* See Tktt_New() */
1602 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1611 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
1617 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler", &milliseconds
, &func
))
1619 if (!PyCallable_Check(func
)) {
1620 PyErr_SetString(PyExc_TypeError
, "bad argument list");
1624 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
1627 return (PyObject
*) v
;
1634 Tkapp_MainLoop(PyObject
*self
, PyObject
*args
)
1638 PyThreadState
*tstate
= PyThreadState_Get();
1641 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
1645 while (Tk_GetNumMainWindows() > threshold
&&
1652 Py_BEGIN_ALLOW_THREADS
1653 PyThread_acquire_lock(tcl_lock
, 1);
1654 tcl_tstate
= tstate
;
1655 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
1657 PyThread_release_lock(tcl_lock
);
1660 Py_END_ALLOW_THREADS
1662 result
= Tcl_DoOneEvent(0);
1665 if (PyErr_CheckSignals() != 0)
1674 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
1675 excInCmd
= valInCmd
= trbInCmd
= NULL
;
1683 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
1688 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
1692 rv
= Tcl_DoOneEvent(flags
);
1694 return Py_BuildValue("i", rv
);
1698 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
1701 if (!PyArg_ParseTuple(args
, ":quit"))
1710 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
1713 if (!PyArg_ParseTuple(args
, ":interpaddr"))
1716 return PyInt_FromLong((long)Tkapp_Interp(self
));
1721 /**** Tkapp Method List ****/
1723 static PyMethodDef Tkapp_methods
[] =
1725 {"call", Tkapp_Call
, 0},
1726 {"globalcall", Tkapp_GlobalCall
, 0},
1727 {"eval", Tkapp_Eval
, 1},
1728 {"globaleval", Tkapp_GlobalEval
, 1},
1729 {"evalfile", Tkapp_EvalFile
, 1},
1730 {"record", Tkapp_Record
, 1},
1731 {"adderrorinfo", Tkapp_AddErrorInfo
, 1},
1732 {"setvar", Tkapp_SetVar
, 1},
1733 {"globalsetvar", Tkapp_GlobalSetVar
, 1},
1734 {"getvar", Tkapp_GetVar
, 1},
1735 {"globalgetvar", Tkapp_GlobalGetVar
, 1},
1736 {"unsetvar", Tkapp_UnsetVar
, 1},
1737 {"globalunsetvar", Tkapp_GlobalUnsetVar
, 1},
1738 {"getint", Tkapp_GetInt
, 1},
1739 {"getdouble", Tkapp_GetDouble
, 1},
1740 {"getboolean", Tkapp_GetBoolean
, 1},
1741 {"exprstring", Tkapp_ExprString
, 1},
1742 {"exprlong", Tkapp_ExprLong
, 1},
1743 {"exprdouble", Tkapp_ExprDouble
, 1},
1744 {"exprboolean", Tkapp_ExprBoolean
, 1},
1745 {"splitlist", Tkapp_SplitList
, 1},
1746 {"split", Tkapp_Split
, 1},
1747 {"merge", Tkapp_Merge
, 0},
1748 {"createcommand", Tkapp_CreateCommand
, 1},
1749 {"deletecommand", Tkapp_DeleteCommand
, 1},
1750 #ifdef HAVE_CREATEFILEHANDLER
1751 {"createfilehandler", Tkapp_CreateFileHandler
, 1},
1752 {"deletefilehandler", Tkapp_DeleteFileHandler
, 1},
1754 {"createtimerhandler", Tkapp_CreateTimerHandler
, 1},
1755 {"mainloop", Tkapp_MainLoop
, 1},
1756 {"dooneevent", Tkapp_DoOneEvent
, 1},
1757 {"quit", Tkapp_Quit
, 1},
1758 {"interpaddr", Tkapp_InterpAddr
, 1},
1764 /**** Tkapp Type Methods ****/
1767 Tkapp_Dealloc(PyObject
*self
)
1770 Tcl_DeleteInterp(Tkapp_Interp(self
));
1777 Tkapp_GetAttr(PyObject
*self
, char *name
)
1779 return Py_FindMethod(Tkapp_methods
, self
, name
);
1782 static PyTypeObject Tkapp_Type
=
1784 PyObject_HEAD_INIT(NULL
)
1786 "tkapp", /*tp_name */
1787 sizeof(TkappObject
), /*tp_basicsize */
1789 Tkapp_Dealloc
, /*tp_dealloc */
1791 Tkapp_GetAttr
, /*tp_getattr */
1795 0, /*tp_as_number */
1796 0, /*tp_as_sequence */
1797 0, /*tp_as_mapping */
1803 /**** Tkinter Module ****/
1807 int size
; /* current size */
1808 int maxsize
; /* allocated size */
1812 _bump(FlattenContext
* context
, int size
)
1814 /* expand tuple to hold (at least) size new items. return true if
1815 successful, false if an exception was raised*/
1817 int maxsize
= context
->maxsize
* 2;
1819 if (maxsize
< context
->size
+ size
)
1820 maxsize
= context
->size
+ size
;
1822 context
->maxsize
= maxsize
;
1824 return _PyTuple_Resize(&context
->tuple
, maxsize
, 0) >= 0;
1828 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
1830 /* add tuple or list to argument tuple (recursively) */
1835 PyErr_SetString(PyExc_ValueError
,"nesting too deep in _flatten");
1837 } else if (PyList_Check(item
)) {
1838 size
= PyList_GET_SIZE(item
);
1839 /* preallocate (assume no nesting) */
1840 if (context
->size
+ size
> context
->maxsize
&& !_bump(context
, size
))
1842 /* copy items to output tuple */
1843 for (i
= 0; i
< size
; i
++) {
1844 PyObject
*o
= PyList_GET_ITEM(item
, i
);
1845 if (PyList_Check(o
) || PyTuple_Check(o
)) {
1846 if (!_flatten1(context
, o
, depth
+ 1))
1848 } else if (o
!= Py_None
) {
1849 if (context
->size
+ 1 > context
->maxsize
&& !_bump(context
, 1))
1852 PyTuple_SET_ITEM(context
->tuple
, context
->size
++, o
);
1855 } else if (PyTuple_Check(item
)) {
1856 /* same, for tuples */
1857 size
= PyTuple_GET_SIZE(item
);
1858 if (context
->size
+ size
> context
->maxsize
&& !_bump(context
, size
))
1860 for (i
= 0; i
< size
; i
++) {
1861 PyObject
*o
= PyTuple_GET_ITEM(item
, i
);
1862 if (PyList_Check(o
) || PyTuple_Check(o
)) {
1863 if (!_flatten1(context
, o
, depth
+ 1))
1865 } else if (o
!= Py_None
) {
1866 if (context
->size
+ 1 > context
->maxsize
&& !_bump(context
, 1))
1869 PyTuple_SET_ITEM(context
->tuple
, context
->size
++, o
);
1873 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
1880 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
1882 FlattenContext context
;
1885 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
1888 context
.maxsize
= PySequence_Size(item
);
1889 if (context
.maxsize
<= 0)
1890 return PyTuple_New(0);
1892 context
.tuple
= PyTuple_New(context
.maxsize
);
1898 if (!_flatten1(&context
, item
,0))
1901 if (_PyTuple_Resize(&context
.tuple
, context
.size
, 0))
1904 return context
.tuple
;
1908 Tkinter_Create(PyObject
*self
, PyObject
*args
)
1910 char *screenName
= NULL
;
1911 char *baseName
= NULL
;
1912 char *className
= NULL
;
1913 int interactive
= 0;
1915 baseName
= strrchr(Py_GetProgramName(), '/');
1916 if (baseName
!= NULL
)
1919 baseName
= Py_GetProgramName();
1922 if (!PyArg_ParseTuple(args
, "|zssi:create",
1923 &screenName
, &baseName
, &className
,
1927 return (PyObject
*) Tkapp_New(screenName
, baseName
, className
,
1931 static PyMethodDef moduleMethods
[] =
1933 {"_flatten", Tkinter_Flatten
, 1},
1934 {"create", Tkinter_Create
, 1},
1935 #ifdef HAVE_CREATEFILEHANDLER
1936 {"createfilehandler", Tkapp_CreateFileHandler
, 1},
1937 {"deletefilehandler", Tkapp_DeleteFileHandler
, 1},
1939 {"createtimerhandler", Tkapp_CreateTimerHandler
, 1},
1940 {"mainloop", Tkapp_MainLoop
, 1},
1941 {"dooneevent", Tkapp_DoOneEvent
, 1},
1942 {"quit", Tkapp_Quit
, 1},
1946 #ifdef WAIT_FOR_STDIN
1948 static int stdin_ready
= 0;
1952 MyFileProc(void *clientData
, int mask
)
1958 static PyThreadState
*event_tstate
= NULL
;
1967 PyEval_RestoreThread(event_tstate
);
1972 tfile
= fileno(stdin
);
1973 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
1975 while (!errorInCmd
&& !stdin_ready
) {
1983 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
1984 Py_BEGIN_ALLOW_THREADS
1985 PyThread_acquire_lock(tcl_lock
, 1);
1986 tcl_tstate
= event_tstate
;
1988 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
1991 PyThread_release_lock(tcl_lock
);
1994 Py_END_ALLOW_THREADS
1996 result
= Tcl_DoOneEvent(0);
2003 Tcl_DeleteFileHandler(tfile
);
2007 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2008 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2012 PyEval_SaveThread();
2020 EnableEventHook(void)
2022 #ifdef WAIT_FOR_STDIN
2023 if (PyOS_InputHook
== NULL
) {
2025 event_tstate
= PyThreadState_Get();
2027 PyOS_InputHook
= EventHook
;
2033 DisableEventHook(void)
2035 #ifdef WAIT_FOR_STDIN
2036 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
2037 PyOS_InputHook
= NULL
;
2043 /* all errors will be checked in one fell swoop in init_tkinter() */
2045 ins_long(PyObject
*d
, char *name
, long val
)
2047 PyObject
*v
= PyInt_FromLong(val
);
2049 PyDict_SetItemString(d
, name
, v
);
2054 ins_string(PyObject
*d
, char *name
, char *val
)
2056 PyObject
*v
= PyString_FromString(val
);
2058 PyDict_SetItemString(d
, name
, v
);
2069 Tkapp_Type
.ob_type
= &PyType_Type
;
2072 tcl_lock
= PyThread_allocate_lock();
2075 m
= Py_InitModule("_tkinter", moduleMethods
);
2077 d
= PyModule_GetDict(m
);
2078 Tkinter_TclError
= Py_BuildValue("s", "TclError");
2079 PyDict_SetItemString(d
, "TclError", Tkinter_TclError
);
2081 ins_long(d
, "READABLE", TCL_READABLE
);
2082 ins_long(d
, "WRITABLE", TCL_WRITABLE
);
2083 ins_long(d
, "EXCEPTION", TCL_EXCEPTION
);
2084 ins_long(d
, "WINDOW_EVENTS", TCL_WINDOW_EVENTS
);
2085 ins_long(d
, "FILE_EVENTS", TCL_FILE_EVENTS
);
2086 ins_long(d
, "TIMER_EVENTS", TCL_TIMER_EVENTS
);
2087 ins_long(d
, "IDLE_EVENTS", TCL_IDLE_EVENTS
);
2088 ins_long(d
, "ALL_EVENTS", TCL_ALL_EVENTS
);
2089 ins_long(d
, "DONT_WAIT", TCL_DONT_WAIT
);
2090 ins_string(d
, "TK_VERSION", TK_VERSION
);
2091 ins_string(d
, "TCL_VERSION", TCL_VERSION
);
2093 PyDict_SetItemString(d
, "TkappType", (PyObject
*)&Tkapp_Type
);
2095 Tktt_Type
.ob_type
= &PyType_Type
;
2096 PyDict_SetItemString(d
, "TkttType", (PyObject
*)&Tktt_Type
);
2098 /* This helps the dynamic loader; in Unicode aware Tcl versions
2099 it also helps Tcl find its encodings. */
2100 Tcl_FindExecutable(Py_GetProgramName());
2102 if (PyErr_Occurred())
2106 /* This was not a good idea; through <Destroy> bindings,
2107 Tcl_Finalize() may invoke Python code but at that point the
2108 interpreter and thread state have already been destroyed! */
2109 Py_AtExit(Tcl_Finalize
);
2114 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2115 ** Most of the initializations in that routine (toolbox init calls and
2116 ** such) have already been done for us, so we only need these.
2120 Tcl_MacSetEventProc(PyMacConvertEvent
);
2122 mac_addlibresources();
2123 #endif /* GENERATINGCFM */
2124 #endif /* macintosh */
2132 ** Anyone who embeds Tcl/Tk on the Mac must define panic().
2136 panic(char * format
, ...)
2140 va_start(varg
, format
);
2142 vfprintf(stderr
, format
, varg
);
2143 (void) fflush(stderr
);
2147 Py_FatalError("Tcl/Tk panic");
2151 ** Pass events to SIOUX before passing them to Tk.
2155 PyMacConvertEvent(EventRecord
*eventPtr
)
2159 ** Sioux eats too many events, so we don't pass it everything. We
2160 ** always pass update events to Sioux, and we only pass other events if
2161 ** the Sioux window is frontmost. This means that Tk menus don't work
2162 ** in that case, but at least we can scroll the sioux window.
2163 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2164 ** part of the external interface of Sioux...
2166 frontwin
= FrontWindow();
2167 if ( eventPtr
->what
== updateEvt
|| SIOUXIsAppWindow(frontwin
) ) {
2168 if (SIOUXHandleOneEvent(eventPtr
))
2169 return 0; /* Nothing happened to the Tcl event queue */
2171 return TkMacConvertEvent(eventPtr
);
2177 ** Additional Mac specific code for dealing with shared libraries.
2180 #include <Resources.h>
2181 #include <CodeFragments.h>
2183 static int loaded_from_shlib
= 0;
2184 static FSSpec library_fss
;
2187 ** If this module is dynamically loaded the following routine should
2188 ** be the init routine. It takes care of adding the shared library to
2189 ** the resource-file chain, so that the tk routines can find their
2193 init_tkinter_shlib(CFragInitBlockPtr data
)
2196 if ( data
== nil
) return noErr
;
2197 if ( data
->fragLocator
.where
== kDataForkCFragLocator
) {
2198 library_fss
= *data
->fragLocator
.u
.onDisk
.fileSpec
;
2199 loaded_from_shlib
= 1;
2200 } else if ( data
->fragLocator
.where
== kResourceCFragLocator
) {
2201 library_fss
= *data
->fragLocator
.u
.inSegs
.fileSpec
;
2202 loaded_from_shlib
= 1;
2208 ** Insert the library resources into the search path. Put them after
2209 ** the resources from the application. Again, we ignore errors.
2212 mac_addlibresources(void)
2214 if ( !loaded_from_shlib
)
2216 (void)FSpOpenResFile(&library_fss
, fsRdPerm
);
2219 #endif /* GENERATINGCFM */
2220 #endif /* macintosh */