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).
52 #define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
54 #if TKMAJORMINOR < 8000
55 #error "Tk older than 8.0 not supported"
58 #if defined(macintosh)
59 /* Sigh, we have to include this to get at the tcl qd pointer */
61 /* And this one we need to clear the menu bar */
65 #if !(defined(MS_WINDOWS) || defined(__CYGWIN__) || defined(macintosh))
66 /* Mac has it, but it doesn't really work:-( */
67 #define HAVE_CREATEFILEHANDLER
70 #ifdef HAVE_CREATEFILEHANDLER
72 /* Tcl_CreateFileHandler() changed several times; these macros deal with the
73 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
74 Unix, only because Jack added it back); when available on Windows, it only
75 applies to sockets. */
78 #define FHANDLETYPE TCL_WIN_SOCKET
80 #define FHANDLETYPE TCL_UNIX_FD
83 /* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
84 which uses this to handle Tcl events while the user is typing commands. */
86 #if FHANDLETYPE == TCL_UNIX_FD
87 #define WAIT_FOR_STDIN
90 #endif /* HAVE_CREATEFILEHANDLER */
94 #define WAIT_FOR_STDIN
99 /* The threading situation is complicated. Tcl is not thread-safe, except for
100 Tcl 8.1, which will probably remain in alpha status for another 6 months
101 (and the README says that Tk will probably remain thread-unsafe forever).
102 So we need to use a lock around all uses of Tcl. Previously, the Python
103 interpreter lock was used for this. However, this causes problems when
104 other Python threads need to run while Tcl is blocked waiting for events.
106 To solve this problem, a separate lock for Tcl is introduced. Holding it
107 is incompatible with holding Python's interpreter lock. The following four
108 macros manipulate both locks together.
110 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
111 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
112 that could call an event handler, or otherwise affect the state of a Tcl
113 interpreter. These assume that the surrounding code has the Python
114 interpreter lock; inside the brackets, the Python interpreter lock has been
115 released and the lock for Tcl has been acquired.
117 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
118 (For example, when transferring data from the Tcl interpreter result to a
119 Python string object.) This can be done by using different macros to close
120 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
121 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
122 releases the Tcl lock.
124 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
125 handlers when the handler needs to use Python. Such event handlers are
126 entered while the lock for Tcl is held; the event handler presumably needs
127 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
128 the Python interpreter lock, restoring the appropriate thread state, and
129 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
130 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
131 the code between ENTER_PYTHON and LEAVE_PYTHON.
133 These locks expand to several statements and brackets; they should not be
134 used in branches of if statements and the like.
138 static PyThread_type_lock tcl_lock
= 0;
139 static PyThreadState
*tcl_tstate
= NULL
;
142 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
143 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
146 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
148 #define ENTER_OVERLAP \
151 #define LEAVE_OVERLAP_TCL \
152 tcl_tstate = NULL; PyThread_release_lock(tcl_lock); }
154 #define ENTER_PYTHON \
155 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
156 PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
158 #define LEAVE_PYTHON \
159 { PyThreadState *tstate = PyEval_SaveThread(); \
160 PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
166 #define ENTER_OVERLAP
167 #define LEAVE_OVERLAP_TCL
176 ** Additional cruft needed by Tcl/Tk on the Mac.
177 ** This is for Tcl 7.5 and Tk 4.1 (patch release 1).
180 /* ckfree() expects a char* */
181 #define FREECAST (char *)
183 #include <Events.h> /* For EventRecord */
185 typedef int (*TclMacConvertEventPtr
) (EventRecord
*eventPtr
);
186 void Tcl_MacSetEventProc(TclMacConvertEventPtr procPtr
);
187 int TkMacConvertEvent(EventRecord
*eventPtr
);
189 staticforward
int PyMacConvertEvent(EventRecord
*eventPtr
);
192 extern int SIOUXIsAppWindow(WindowPtr
);
194 #endif /* macintosh */
197 #define FREECAST (char *)
200 /**** Tkapp Object Declaration ****/
202 staticforward PyTypeObject Tkapp_Type
;
209 #define Tkapp_Check(v) ((v)->ob_type == &Tkapp_Type)
210 #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
211 #define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
213 #define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
214 (void *) v, ((PyObject *) v)->ob_refcnt))
218 /**** Error Handling ****/
220 static PyObject
*Tkinter_TclError
;
221 static int quitMainLoop
= 0;
222 static int errorInCmd
= 0;
223 static PyObject
*excInCmd
;
224 static PyObject
*valInCmd
;
225 static PyObject
*trbInCmd
;
230 Tkinter_Error(PyObject
*v
)
232 PyErr_SetString(Tkinter_TclError
, Tkapp_Result(v
));
243 /* Millisecond sleep() for Unix platforms. */
248 /* XXX Too bad if you don't have select(). */
250 t
.tv_sec
= milli
/1000;
251 t
.tv_usec
= (milli
%1000) * 1000;
252 select(0, (fd_set
*)0, (fd_set
*)0, (fd_set
*)0, &t
);
254 #endif /* MS_WINDOWS */
255 #endif /* WITH_THREAD */
259 AsString(PyObject
*value
, PyObject
*tmp
)
261 if (PyString_Check(value
))
262 return PyString_AsString(value
);
263 #ifdef Py_USING_UNICODE
264 else if (PyUnicode_Check(value
)) {
265 PyObject
*v
= PyUnicode_AsUTF8String(value
);
268 if (PyList_Append(tmp
, v
) != 0) {
273 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
);
463 /* Delete the 'exit' command, which can screw things up */
464 Tcl_DeleteCommand(v
->interp
, "exit");
466 if (screenName
!= NULL
)
467 Tcl_SetVar2(v
->interp
, "env", "DISPLAY",
468 screenName
, TCL_GLOBAL_ONLY
);
471 Tcl_SetVar(v
->interp
, "tcl_interactive", "1", TCL_GLOBAL_ONLY
);
473 Tcl_SetVar(v
->interp
, "tcl_interactive", "0", TCL_GLOBAL_ONLY
);
475 /* This is used to get the application class for Tk 4.1 and up */
476 argv0
= (char*)ckalloc(strlen(className
) + 1);
483 strcpy(argv0
, className
);
484 if (isupper((int)(argv0
[0])))
485 argv0
[0] = tolower(argv0
[0]);
486 Tcl_SetVar(v
->interp
, "argv0", argv0
, TCL_GLOBAL_ONLY
);
489 if (Tcl_AppInit(v
->interp
) != TCL_OK
)
490 return (TkappObject
*)Tkinter_Error((PyObject
*)v
);
501 #if TKMAJORMINOR >= 8001
502 #define USING_OBJECTS
508 AsObj(PyObject
*value
)
512 if (PyString_Check(value
))
513 return Tcl_NewStringObj(PyString_AS_STRING(value
),
514 PyString_GET_SIZE(value
));
515 else if (PyInt_Check(value
))
516 return Tcl_NewLongObj(PyInt_AS_LONG(value
));
517 else if (PyFloat_Check(value
))
518 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value
));
519 else if (PyTuple_Check(value
)) {
520 Tcl_Obj
**argv
= (Tcl_Obj
**)
521 ckalloc(PyTuple_Size(value
)*sizeof(Tcl_Obj
*));
525 for(i
=0;i
<PyTuple_Size(value
);i
++)
526 argv
[i
] = AsObj(PyTuple_GetItem(value
,i
));
527 result
= Tcl_NewListObj(PyTuple_Size(value
), argv
);
528 ckfree(FREECAST argv
);
531 #ifdef Py_USING_UNICODE
532 else if (PyUnicode_Check(value
)) {
533 #if TKMAJORMINOR <= 8001
534 /* In Tcl 8.1 we must use UTF-8 */
535 PyObject
* utf8
= PyUnicode_AsUTF8String(value
);
538 result
= Tcl_NewStringObj(PyString_AS_STRING(utf8
),
539 PyString_GET_SIZE(utf8
));
542 #else /* TKMAJORMINOR > 8001 */
543 /* In Tcl 8.2 and later, use Tcl_NewUnicodeObj() */
544 if (sizeof(Py_UNICODE
) != sizeof(Tcl_UniChar
)) {
545 /* XXX Should really test this at compile time */
546 PyErr_SetString(PyExc_SystemError
,
547 "Py_UNICODE and Tcl_UniChar differ in size");
550 return Tcl_NewUnicodeObj(PyUnicode_AS_UNICODE(value
),
551 PyUnicode_GET_SIZE(value
));
552 #endif /* TKMAJORMINOR > 8001 */
556 PyObject
*v
= PyObject_Str(value
);
566 Tkapp_Call(PyObject
*self
, PyObject
*args
)
568 Tcl_Obj
*objStore
[ARGSZ
];
569 Tcl_Obj
**objv
= NULL
;
571 PyObject
*res
= NULL
;
572 Tcl_Interp
*interp
= Tkapp_Interp(self
);
573 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
574 int flags
= TCL_EVAL_DIRECT
;
581 else if (!PyTuple_Check(args
)) {
582 objv
[0] = AsObj(args
);
586 Tcl_IncrRefCount(objv
[0]);
589 objc
= PyTuple_Size(args
);
592 objv
= (Tcl_Obj
**)ckalloc(objc
* sizeof(char *));
600 for (i
= 0; i
< objc
; i
++) {
601 PyObject
*v
= PyTuple_GetItem(args
, i
);
608 /* Reset objc, so it attempts to clear
609 objects only up to i. */
613 Tcl_IncrRefCount(objv
[i
]);
619 i
= Tcl_EvalObjv(interp
, objc
, objv
, flags
);
625 /* We could request the object result here, but doing
626 so would confuse applications that expect a string. */
627 char *s
= Tcl_GetStringResult(interp
);
630 /* If the result contains any bytes with the top bit set,
631 it's UTF-8 and we should decode it to Unicode */
632 #ifdef Py_USING_UNICODE
640 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
642 /* Convert UTF-8 to Unicode string */
644 res
= PyUnicode_DecodeUTF8(s
, (int)(p
-s
), "strict");
647 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
652 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
659 for (i
= 0; i
< objc
; i
++)
660 Tcl_DecrRefCount(objv
[i
]);
661 if (objv
!= objStore
)
662 ckfree(FREECAST objv
);
666 #else /* !USING_OBJECTS */
669 Tkapp_Call(PyObject
*self
, PyObject
*args
)
671 /* This is copied from Merge() */
672 PyObject
*tmp
= NULL
;
673 char *argvStore
[ARGSZ
];
677 int argc
= 0, fvc
= 0, i
;
678 PyObject
*res
= NULL
; /* except this has a different type */
679 Tcl_CmdInfo info
; /* and this is added */
680 Tcl_Interp
*interp
= Tkapp_Interp(self
); /* and this too */
682 if (!(tmp
= PyList_New(0)))
691 else if (!PyTuple_Check(args
)) {
694 if (!(argv
[0] = AsString(args
, tmp
)))
698 argc
= PyTuple_Size(args
);
701 argv
= (char **)ckalloc(argc
* sizeof(char *));
702 fv
= (int *)ckalloc(argc
* sizeof(int));
703 if (argv
== NULL
|| fv
== NULL
) {
709 for (i
= 0; i
< argc
; i
++) {
710 PyObject
*v
= PyTuple_GetItem(args
, i
);
711 if (PyTuple_Check(v
)) {
713 if (!(argv
[i
] = Merge(v
)))
717 else if (v
== Py_None
) {
723 if (!(argv
[i
] = AsString(v
, tmp
)))
729 /* End code copied from Merge() */
731 /* All this to avoid a call to Tcl_Merge() and the corresponding call
732 to Tcl_SplitList() inside Tcl_Eval()... It can save a bundle! */
733 if (Py_VerboseFlag
>= 2) {
734 for (i
= 0; i
< argc
; i
++)
735 PySys_WriteStderr("%s ", argv
[i
]);
740 !Tcl_GetCommandInfo(interp
, argv
[0], &info
) ||
744 cmd
= Tcl_Merge(argc
, argv
);
745 i
= Tcl_Eval(interp
, cmd
);
749 Tcl_ResetResult(interp
);
750 i
= (*info
.proc
)(info
.clientData
, interp
, argc
, argv
);
753 if (info
.proc
== NULL
&& Py_VerboseFlag
>= 2)
754 PySys_WriteStderr("... use TclEval ");
755 if (i
== TCL_ERROR
) {
756 if (Py_VerboseFlag
>= 2)
757 PySys_WriteStderr("... error: '%s'\n",
758 Tcl_GetStringResult(interp
));
762 if (Py_VerboseFlag
>= 2)
763 PySys_WriteStderr("-> '%s'\n", Tcl_GetStringResult(interp
));
764 res
= PyString_FromString(Tcl_GetStringResult(interp
));
768 /* Copied from Merge() again */
770 for (i
= 0; i
< fvc
; i
++)
774 if (argv
!= argvStore
)
775 ckfree(FREECAST argv
);
783 #endif /* !USING_OBJECTS */
786 Tkapp_GlobalCall(PyObject
*self
, PyObject
*args
)
788 /* Could do the same here as for Tkapp_Call(), but this is not used
789 much, so I can't be bothered. Unfortunately Tcl doesn't export a
790 way for the user to do what all its Global* variants do (save and
791 reset the scope pointer, call the local version, restore the saved
795 PyObject
*res
= NULL
;
801 err
= Tcl_GlobalEval(Tkapp_Interp(self
), cmd
);
803 if (err
== TCL_ERROR
)
804 res
= Tkinter_Error(self
);
806 res
= PyString_FromString(Tkapp_Result(self
));
815 Tkapp_Eval(PyObject
*self
, PyObject
*args
)
818 PyObject
*res
= NULL
;
821 if (!PyArg_ParseTuple(args
, "s:eval", &script
))
825 err
= Tcl_Eval(Tkapp_Interp(self
), script
);
827 if (err
== TCL_ERROR
)
828 res
= Tkinter_Error(self
);
830 res
= PyString_FromString(Tkapp_Result(self
));
836 Tkapp_GlobalEval(PyObject
*self
, PyObject
*args
)
839 PyObject
*res
= NULL
;
842 if (!PyArg_ParseTuple(args
, "s:globaleval", &script
))
846 err
= Tcl_GlobalEval(Tkapp_Interp(self
), script
);
848 if (err
== TCL_ERROR
)
849 res
= Tkinter_Error(self
);
851 res
= PyString_FromString(Tkapp_Result(self
));
857 Tkapp_EvalFile(PyObject
*self
, PyObject
*args
)
860 PyObject
*res
= NULL
;
863 if (!PyArg_ParseTuple(args
, "s:evalfile", &fileName
))
867 err
= Tcl_EvalFile(Tkapp_Interp(self
), fileName
);
869 if (err
== TCL_ERROR
)
870 res
= Tkinter_Error(self
);
873 res
= PyString_FromString(Tkapp_Result(self
));
879 Tkapp_Record(PyObject
*self
, PyObject
*args
)
882 PyObject
*res
= NULL
;
885 if (!PyArg_ParseTuple(args
, "s", &script
))
889 err
= Tcl_RecordAndEval(Tkapp_Interp(self
), script
, TCL_NO_EVAL
);
891 if (err
== TCL_ERROR
)
892 res
= Tkinter_Error(self
);
894 res
= PyString_FromString(Tkapp_Result(self
));
900 Tkapp_AddErrorInfo(PyObject
*self
, PyObject
*args
)
904 if (!PyArg_ParseTuple(args
, "s:adderrorinfo", &msg
))
907 Tcl_AddErrorInfo(Tkapp_Interp(self
), msg
);
919 SetVar(PyObject
*self
, PyObject
*args
, int flags
)
921 char *name1
, *name2
, *ok
, *s
;
929 if (PyArg_ParseTuple(args
, "sO:setvar", &name1
, &newValue
)) {
931 s
= AsString(newValue
, tmp
);
935 ok
= Tcl_SetVar(Tkapp_Interp(self
), name1
, s
, flags
);
940 if (PyArg_ParseTuple(args
, "ssO:setvar",
941 &name1
, &name2
, &newValue
)) {
942 s
= AsString(newValue
, tmp
);
946 ok
= Tcl_SetVar2(Tkapp_Interp(self
), name1
, name2
,
958 return Tkinter_Error(self
);
965 Tkapp_SetVar(PyObject
*self
, PyObject
*args
)
967 return SetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
971 Tkapp_GlobalSetVar(PyObject
*self
, PyObject
*args
)
973 return SetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
979 GetVar(PyObject
*self
, PyObject
*args
, int flags
)
981 char *name1
, *name2
=NULL
, *s
;
982 PyObject
*res
= NULL
;
984 if (!PyArg_ParseTuple(args
, "s|s:getvar", &name1
, &name2
))
988 s
= Tcl_GetVar(Tkapp_Interp(self
), name1
, flags
);
991 s
= Tcl_GetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
995 res
= Tkinter_Error(self
);
997 res
= PyString_FromString(s
);
1003 Tkapp_GetVar(PyObject
*self
, PyObject
*args
)
1005 return GetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
1009 Tkapp_GlobalGetVar(PyObject
*self
, PyObject
*args
)
1011 return GetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1017 UnsetVar(PyObject
*self
, PyObject
*args
, int flags
)
1019 char *name1
, *name2
=NULL
;
1020 PyObject
*res
= NULL
;
1023 if (!PyArg_ParseTuple(args
, "s|s:unsetvar", &name1
, &name2
))
1027 code
= Tcl_UnsetVar(Tkapp_Interp(self
), name1
, flags
);
1030 code
= Tcl_UnsetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
1033 if (code
== TCL_ERROR
)
1034 res
= Tkinter_Error(self
);
1044 Tkapp_UnsetVar(PyObject
*self
, PyObject
*args
)
1046 return UnsetVar(self
, args
, TCL_LEAVE_ERR_MSG
);
1050 Tkapp_GlobalUnsetVar(PyObject
*self
, PyObject
*args
)
1052 return UnsetVar(self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1057 /** Tcl to Python **/
1060 Tkapp_GetInt(PyObject
*self
, PyObject
*args
)
1065 if (!PyArg_ParseTuple(args
, "s:getint", &s
))
1067 if (Tcl_GetInt(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1068 return Tkinter_Error(self
);
1069 return Py_BuildValue("i", v
);
1073 Tkapp_GetDouble(PyObject
*self
, PyObject
*args
)
1078 if (!PyArg_ParseTuple(args
, "s:getdouble", &s
))
1080 if (Tcl_GetDouble(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1081 return Tkinter_Error(self
);
1082 return Py_BuildValue("d", v
);
1086 Tkapp_GetBoolean(PyObject
*self
, PyObject
*args
)
1091 if (!PyArg_ParseTuple(args
, "s:getboolean", &s
))
1093 if (Tcl_GetBoolean(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1094 return Tkinter_Error(self
);
1095 return Py_BuildValue("i", v
);
1099 Tkapp_ExprString(PyObject
*self
, PyObject
*args
)
1102 PyObject
*res
= NULL
;
1105 if (!PyArg_ParseTuple(args
, "s:exprstring", &s
))
1108 retval
= Tcl_ExprString(Tkapp_Interp(self
), s
);
1110 if (retval
== TCL_ERROR
)
1111 res
= Tkinter_Error(self
);
1113 res
= Py_BuildValue("s", Tkapp_Result(self
));
1119 Tkapp_ExprLong(PyObject
*self
, PyObject
*args
)
1122 PyObject
*res
= NULL
;
1126 if (!PyArg_ParseTuple(args
, "s:exprlong", &s
))
1129 retval
= Tcl_ExprLong(Tkapp_Interp(self
), s
, &v
);
1131 if (retval
== TCL_ERROR
)
1132 res
= Tkinter_Error(self
);
1134 res
= Py_BuildValue("l", v
);
1140 Tkapp_ExprDouble(PyObject
*self
, PyObject
*args
)
1143 PyObject
*res
= NULL
;
1147 if (!PyArg_ParseTuple(args
, "s:exprdouble", &s
))
1149 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1151 retval
= Tcl_ExprDouble(Tkapp_Interp(self
), s
, &v
);
1153 PyFPE_END_PROTECT(retval
)
1154 if (retval
== TCL_ERROR
)
1155 res
= Tkinter_Error(self
);
1157 res
= Py_BuildValue("d", v
);
1163 Tkapp_ExprBoolean(PyObject
*self
, PyObject
*args
)
1166 PyObject
*res
= NULL
;
1170 if (!PyArg_ParseTuple(args
, "s:exprboolean", &s
))
1173 retval
= Tcl_ExprBoolean(Tkapp_Interp(self
), s
, &v
);
1175 if (retval
== TCL_ERROR
)
1176 res
= Tkinter_Error(self
);
1178 res
= Py_BuildValue("i", v
);
1186 Tkapp_SplitList(PyObject
*self
, PyObject
*args
)
1194 if (!PyArg_ParseTuple(args
, "et:splitlist", "utf-8", &list
))
1197 if (Tcl_SplitList(Tkapp_Interp(self
), list
, &argc
, &argv
) == TCL_ERROR
)
1198 return Tkinter_Error(self
);
1200 if (!(v
= PyTuple_New(argc
)))
1203 for (i
= 0; i
< argc
; i
++) {
1204 PyObject
*s
= PyString_FromString(argv
[i
]);
1205 if (!s
|| PyTuple_SetItem(v
, i
, s
)) {
1213 ckfree(FREECAST argv
);
1218 Tkapp_Split(PyObject
*self
, PyObject
*args
)
1222 if (!PyArg_ParseTuple(args
, "et:split", "utf-8", &list
))
1228 Tkapp_Merge(PyObject
*self
, PyObject
*args
)
1230 char *s
= Merge(args
);
1231 PyObject
*res
= NULL
;
1234 res
= PyString_FromString(s
);
1245 /* Client data struct */
1249 } PythonCmd_ClientData
;
1252 PythonCmd_Error(Tcl_Interp
*interp
)
1255 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1260 /* This is the Tcl command that acts as a wrapper for Python
1261 * function or method.
1264 PythonCmd(ClientData clientData
, Tcl_Interp
*interp
, int argc
, char *argv
[])
1266 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1267 PyObject
*self
, *func
, *arg
, *res
, *tmp
;
1273 /* TBD: no error checking here since we know, via the
1274 * Tkapp_CreateCommand() that the client data is a two-tuple
1279 /* Create argument list (argv1, ..., argvN) */
1280 if (!(arg
= PyTuple_New(argc
- 1)))
1281 return PythonCmd_Error(interp
);
1283 for (i
= 0; i
< (argc
- 1); i
++) {
1284 PyObject
*s
= PyString_FromString(argv
[i
+ 1]);
1285 if (!s
|| PyTuple_SetItem(arg
, i
, s
)) {
1287 return PythonCmd_Error(interp
);
1290 res
= PyEval_CallObject(func
, arg
);
1294 return PythonCmd_Error(interp
);
1296 if (!(tmp
= PyList_New(0))) {
1298 return PythonCmd_Error(interp
);
1301 s
= AsString(res
, tmp
);
1303 rv
= PythonCmd_Error(interp
);
1306 Tcl_SetResult(Tkapp_Interp(self
), s
, TCL_VOLATILE
);
1319 PythonCmdDelete(ClientData clientData
)
1321 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1324 Py_XDECREF(data
->self
);
1325 Py_XDECREF(data
->func
);
1333 Tkapp_CreateCommand(PyObject
*self
, PyObject
*args
)
1335 PythonCmd_ClientData
*data
;
1340 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
1342 if (!PyCallable_Check(func
)) {
1343 PyErr_SetString(PyExc_TypeError
, "command not callable");
1347 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
1356 err
= Tcl_CreateCommand(Tkapp_Interp(self
), cmdName
, PythonCmd
,
1357 (ClientData
)data
, PythonCmdDelete
);
1360 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
1372 Tkapp_DeleteCommand(PyObject
*self
, PyObject
*args
)
1377 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
1380 err
= Tcl_DeleteCommand(Tkapp_Interp(self
), cmdName
);
1383 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
1392 #ifdef HAVE_CREATEFILEHANDLER
1393 /** File Handler **/
1395 typedef struct _fhcdata
{
1399 struct _fhcdata
*next
;
1400 } FileHandler_ClientData
;
1402 static FileHandler_ClientData
*HeadFHCD
;
1404 static FileHandler_ClientData
*
1405 NewFHCD(PyObject
*func
, PyObject
*file
, int id
)
1407 FileHandler_ClientData
*p
;
1408 p
= PyMem_NEW(FileHandler_ClientData
, 1);
1424 FileHandler_ClientData
*p
, **pp
;
1427 while ((p
= *pp
) != NULL
) {
1430 Py_XDECREF(p
->func
);
1431 Py_XDECREF(p
->file
);
1440 FileHandler(ClientData clientData
, int mask
)
1442 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
1443 PyObject
*func
, *file
, *arg
, *res
;
1449 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
1450 res
= PyEval_CallObject(func
, arg
);
1455 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1462 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
1463 /* args is (file, mask, func) */
1465 FileHandler_ClientData
*data
;
1466 PyObject
*file
, *func
;
1469 if (!PyArg_ParseTuple(args
, "OiO:createfilehandler",
1470 &file
, &mask
, &func
))
1472 tfile
= PyObject_AsFileDescriptor(file
);
1475 if (!PyCallable_Check(func
)) {
1476 PyErr_SetString(PyExc_TypeError
, "bad argument list");
1480 data
= NewFHCD(func
, file
, tfile
);
1484 /* Ought to check for null Tcl_File object... */
1486 Tcl_CreateFileHandler(tfile
, mask
, FileHandler
, (ClientData
) data
);
1493 Tkapp_DeleteFileHandler(PyObject
*self
, PyObject
*args
)
1498 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
1500 tfile
= PyObject_AsFileDescriptor(file
);
1506 /* Ought to check for null Tcl_File object... */
1508 Tcl_DeleteFileHandler(tfile
);
1513 #endif /* HAVE_CREATEFILEHANDLER */
1516 /**** Tktt Object (timer token) ****/
1518 staticforward PyTypeObject Tktt_Type
;
1522 Tcl_TimerToken token
;
1527 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
1529 TkttObject
*v
= (TkttObject
*)self
;
1530 PyObject
*func
= v
->func
;
1532 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
1534 if (v
->token
!= NULL
) {
1535 Tcl_DeleteTimerHandler(v
->token
);
1541 Py_DECREF(v
); /* See Tktt_New() */
1547 static PyMethodDef Tktt_methods
[] =
1549 {"deletetimerhandler", Tktt_DeleteTimerHandler
, 1},
1554 Tktt_New(PyObject
*func
)
1558 v
= PyObject_New(TkttObject
, &Tktt_Type
);
1566 /* Extra reference, deleted when called or when handler is deleted */
1572 Tktt_Dealloc(PyObject
*self
)
1574 TkttObject
*v
= (TkttObject
*)self
;
1575 PyObject
*func
= v
->func
;
1583 Tktt_Repr(PyObject
*self
)
1585 TkttObject
*v
= (TkttObject
*)self
;
1588 PyOS_snprintf(buf
, sizeof(buf
), "<tktimertoken at %p%s>", v
,
1589 v
->func
== NULL
? ", handler deleted" : "");
1590 return PyString_FromString(buf
);
1594 Tktt_GetAttr(PyObject
*self
, char *name
)
1596 return Py_FindMethod(Tktt_methods
, self
, name
);
1599 static PyTypeObject Tktt_Type
=
1601 PyObject_HEAD_INIT(NULL
)
1603 "tktimertoken", /*tp_name */
1604 sizeof(TkttObject
), /*tp_basicsize */
1606 Tktt_Dealloc
, /*tp_dealloc */
1608 Tktt_GetAttr
, /*tp_getattr */
1611 Tktt_Repr
, /*tp_repr */
1612 0, /*tp_as_number */
1613 0, /*tp_as_sequence */
1614 0, /*tp_as_mapping */
1620 /** Timer Handler **/
1623 TimerHandler(ClientData clientData
)
1625 TkttObject
*v
= (TkttObject
*)clientData
;
1626 PyObject
*func
= v
->func
;
1636 res
= PyEval_CallObject(func
, NULL
);
1638 Py_DECREF(v
); /* See Tktt_New() */
1642 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1651 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
1657 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler",
1658 &milliseconds
, &func
))
1660 if (!PyCallable_Check(func
)) {
1661 PyErr_SetString(PyExc_TypeError
, "bad argument list");
1665 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
1668 return (PyObject
*) v
;
1675 Tkapp_MainLoop(PyObject
*self
, PyObject
*args
)
1679 PyThreadState
*tstate
= PyThreadState_Get();
1682 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
1686 while (Tk_GetNumMainWindows() > threshold
&&
1693 Py_BEGIN_ALLOW_THREADS
1694 PyThread_acquire_lock(tcl_lock
, 1);
1695 tcl_tstate
= tstate
;
1696 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
1698 PyThread_release_lock(tcl_lock
);
1701 Py_END_ALLOW_THREADS
1703 result
= Tcl_DoOneEvent(0);
1706 if (PyErr_CheckSignals() != 0)
1715 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
1716 excInCmd
= valInCmd
= trbInCmd
= NULL
;
1724 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
1729 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
1733 rv
= Tcl_DoOneEvent(flags
);
1735 return Py_BuildValue("i", rv
);
1739 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
1742 if (!PyArg_ParseTuple(args
, ":quit"))
1751 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
1754 if (!PyArg_ParseTuple(args
, ":interpaddr"))
1757 return PyInt_FromLong((long)Tkapp_Interp(self
));
1762 /**** Tkapp Method List ****/
1764 static PyMethodDef Tkapp_methods
[] =
1766 {"call", Tkapp_Call
, 0},
1767 {"globalcall", Tkapp_GlobalCall
, 0},
1768 {"eval", Tkapp_Eval
, 1},
1769 {"globaleval", Tkapp_GlobalEval
, 1},
1770 {"evalfile", Tkapp_EvalFile
, 1},
1771 {"record", Tkapp_Record
, 1},
1772 {"adderrorinfo", Tkapp_AddErrorInfo
, 1},
1773 {"setvar", Tkapp_SetVar
, 1},
1774 {"globalsetvar", Tkapp_GlobalSetVar
, 1},
1775 {"getvar", Tkapp_GetVar
, 1},
1776 {"globalgetvar", Tkapp_GlobalGetVar
, 1},
1777 {"unsetvar", Tkapp_UnsetVar
, 1},
1778 {"globalunsetvar", Tkapp_GlobalUnsetVar
, 1},
1779 {"getint", Tkapp_GetInt
, 1},
1780 {"getdouble", Tkapp_GetDouble
, 1},
1781 {"getboolean", Tkapp_GetBoolean
, 1},
1782 {"exprstring", Tkapp_ExprString
, 1},
1783 {"exprlong", Tkapp_ExprLong
, 1},
1784 {"exprdouble", Tkapp_ExprDouble
, 1},
1785 {"exprboolean", Tkapp_ExprBoolean
, 1},
1786 {"splitlist", Tkapp_SplitList
, 1},
1787 {"split", Tkapp_Split
, 1},
1788 {"merge", Tkapp_Merge
, 0},
1789 {"createcommand", Tkapp_CreateCommand
, 1},
1790 {"deletecommand", Tkapp_DeleteCommand
, 1},
1791 #ifdef HAVE_CREATEFILEHANDLER
1792 {"createfilehandler", Tkapp_CreateFileHandler
, 1},
1793 {"deletefilehandler", Tkapp_DeleteFileHandler
, 1},
1795 {"createtimerhandler", Tkapp_CreateTimerHandler
, 1},
1796 {"mainloop", Tkapp_MainLoop
, 1},
1797 {"dooneevent", Tkapp_DoOneEvent
, 1},
1798 {"quit", Tkapp_Quit
, 1},
1799 {"interpaddr", Tkapp_InterpAddr
, 1},
1805 /**** Tkapp Type Methods ****/
1808 Tkapp_Dealloc(PyObject
*self
)
1811 Tcl_DeleteInterp(Tkapp_Interp(self
));
1818 Tkapp_GetAttr(PyObject
*self
, char *name
)
1820 return Py_FindMethod(Tkapp_methods
, self
, name
);
1823 static PyTypeObject Tkapp_Type
=
1825 PyObject_HEAD_INIT(NULL
)
1827 "tkapp", /*tp_name */
1828 sizeof(TkappObject
), /*tp_basicsize */
1830 Tkapp_Dealloc
, /*tp_dealloc */
1832 Tkapp_GetAttr
, /*tp_getattr */
1836 0, /*tp_as_number */
1837 0, /*tp_as_sequence */
1838 0, /*tp_as_mapping */
1844 /**** Tkinter Module ****/
1848 int size
; /* current size */
1849 int maxsize
; /* allocated size */
1853 _bump(FlattenContext
* context
, int size
)
1855 /* expand tuple to hold (at least) size new items.
1856 return true if successful, false if an exception was raised */
1858 int maxsize
= context
->maxsize
* 2;
1860 if (maxsize
< context
->size
+ size
)
1861 maxsize
= context
->size
+ size
;
1863 context
->maxsize
= maxsize
;
1865 return _PyTuple_Resize(&context
->tuple
, maxsize
) >= 0;
1869 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
1871 /* add tuple or list to argument tuple (recursively) */
1876 PyErr_SetString(PyExc_ValueError
,
1877 "nesting too deep in _flatten");
1879 } else if (PyList_Check(item
)) {
1880 size
= PyList_GET_SIZE(item
);
1881 /* preallocate (assume no nesting) */
1882 if (context
->size
+ size
> context
->maxsize
&&
1883 !_bump(context
, size
))
1885 /* copy items to output tuple */
1886 for (i
= 0; i
< size
; i
++) {
1887 PyObject
*o
= PyList_GET_ITEM(item
, i
);
1888 if (PyList_Check(o
) || PyTuple_Check(o
)) {
1889 if (!_flatten1(context
, o
, depth
+ 1))
1891 } else if (o
!= Py_None
) {
1892 if (context
->size
+ 1 > context
->maxsize
&&
1896 PyTuple_SET_ITEM(context
->tuple
,
1897 context
->size
++, o
);
1900 } else if (PyTuple_Check(item
)) {
1901 /* same, for tuples */
1902 size
= PyTuple_GET_SIZE(item
);
1903 if (context
->size
+ size
> context
->maxsize
&&
1904 !_bump(context
, size
))
1906 for (i
= 0; i
< size
; i
++) {
1907 PyObject
*o
= PyTuple_GET_ITEM(item
, i
);
1908 if (PyList_Check(o
) || PyTuple_Check(o
)) {
1909 if (!_flatten1(context
, o
, depth
+ 1))
1911 } else if (o
!= Py_None
) {
1912 if (context
->size
+ 1 > context
->maxsize
&&
1916 PyTuple_SET_ITEM(context
->tuple
,
1917 context
->size
++, o
);
1921 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
1928 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
1930 FlattenContext context
;
1933 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
1936 context
.maxsize
= PySequence_Size(item
);
1937 if (context
.maxsize
<= 0)
1938 return PyTuple_New(0);
1940 context
.tuple
= PyTuple_New(context
.maxsize
);
1946 if (!_flatten1(&context
, item
,0))
1949 if (_PyTuple_Resize(&context
.tuple
, context
.size
))
1952 return context
.tuple
;
1956 Tkinter_Create(PyObject
*self
, PyObject
*args
)
1958 char *screenName
= NULL
;
1959 char *baseName
= NULL
;
1960 char *className
= NULL
;
1961 int interactive
= 0;
1963 baseName
= strrchr(Py_GetProgramName(), '/');
1964 if (baseName
!= NULL
)
1967 baseName
= Py_GetProgramName();
1970 if (!PyArg_ParseTuple(args
, "|zssi:create",
1971 &screenName
, &baseName
, &className
,
1975 return (PyObject
*) Tkapp_New(screenName
, baseName
, className
,
1979 static PyMethodDef moduleMethods
[] =
1981 {"_flatten", Tkinter_Flatten
, 1},
1982 {"create", Tkinter_Create
, 1},
1983 #ifdef HAVE_CREATEFILEHANDLER
1984 {"createfilehandler", Tkapp_CreateFileHandler
, 1},
1985 {"deletefilehandler", Tkapp_DeleteFileHandler
, 1},
1987 {"createtimerhandler", Tkapp_CreateTimerHandler
, 1},
1988 {"mainloop", Tkapp_MainLoop
, 1},
1989 {"dooneevent", Tkapp_DoOneEvent
, 1},
1990 {"quit", Tkapp_Quit
, 1},
1994 #ifdef WAIT_FOR_STDIN
1996 static int stdin_ready
= 0;
2000 MyFileProc(void *clientData
, int mask
)
2006 static PyThreadState
*event_tstate
= NULL
;
2015 PyEval_RestoreThread(event_tstate
);
2020 tfile
= fileno(stdin
);
2021 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
2023 while (!errorInCmd
&& !stdin_ready
) {
2031 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
2032 Py_BEGIN_ALLOW_THREADS
2033 PyThread_acquire_lock(tcl_lock
, 1);
2034 tcl_tstate
= event_tstate
;
2036 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
2039 PyThread_release_lock(tcl_lock
);
2042 Py_END_ALLOW_THREADS
2044 result
= Tcl_DoOneEvent(0);
2051 Tcl_DeleteFileHandler(tfile
);
2055 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2056 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2060 PyEval_SaveThread();
2068 EnableEventHook(void)
2070 #ifdef WAIT_FOR_STDIN
2071 if (PyOS_InputHook
== NULL
) {
2073 event_tstate
= PyThreadState_Get();
2075 PyOS_InputHook
= EventHook
;
2081 DisableEventHook(void)
2083 #ifdef WAIT_FOR_STDIN
2084 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
2085 PyOS_InputHook
= NULL
;
2091 /* all errors will be checked in one fell swoop in init_tkinter() */
2093 ins_long(PyObject
*d
, char *name
, long val
)
2095 PyObject
*v
= PyInt_FromLong(val
);
2097 PyDict_SetItemString(d
, name
, v
);
2102 ins_string(PyObject
*d
, char *name
, char *val
)
2104 PyObject
*v
= PyString_FromString(val
);
2106 PyDict_SetItemString(d
, name
, v
);
2117 Tkapp_Type
.ob_type
= &PyType_Type
;
2120 tcl_lock
= PyThread_allocate_lock();
2123 m
= Py_InitModule("_tkinter", moduleMethods
);
2125 d
= PyModule_GetDict(m
);
2126 Tkinter_TclError
= Py_BuildValue("s", "TclError");
2127 PyDict_SetItemString(d
, "TclError", Tkinter_TclError
);
2129 ins_long(d
, "READABLE", TCL_READABLE
);
2130 ins_long(d
, "WRITABLE", TCL_WRITABLE
);
2131 ins_long(d
, "EXCEPTION", TCL_EXCEPTION
);
2132 ins_long(d
, "WINDOW_EVENTS", TCL_WINDOW_EVENTS
);
2133 ins_long(d
, "FILE_EVENTS", TCL_FILE_EVENTS
);
2134 ins_long(d
, "TIMER_EVENTS", TCL_TIMER_EVENTS
);
2135 ins_long(d
, "IDLE_EVENTS", TCL_IDLE_EVENTS
);
2136 ins_long(d
, "ALL_EVENTS", TCL_ALL_EVENTS
);
2137 ins_long(d
, "DONT_WAIT", TCL_DONT_WAIT
);
2138 ins_string(d
, "TK_VERSION", TK_VERSION
);
2139 ins_string(d
, "TCL_VERSION", TCL_VERSION
);
2141 PyDict_SetItemString(d
, "TkappType", (PyObject
*)&Tkapp_Type
);
2143 Tktt_Type
.ob_type
= &PyType_Type
;
2144 PyDict_SetItemString(d
, "TkttType", (PyObject
*)&Tktt_Type
);
2148 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
2149 * start waking up. Note that Tcl_FindExecutable will do this, this
2150 * code must be above it! The original warning from
2151 * tkMacOSXAppInit.c is copied below.
2153 * NB - You have to swap in the Tk Notifier BEFORE you start up the
2154 * Tcl interpreter for now. It probably should work to do this
2155 * in the other order, but for now it doesn't seem to.
2158 Tk_MacOSXSetupTkNotifier();
2162 /* This helps the dynamic loader; in Unicode aware Tcl versions
2163 it also helps Tcl find its encodings. */
2164 Tcl_FindExecutable(Py_GetProgramName());
2166 if (PyErr_Occurred())
2170 /* This was not a good idea; through <Destroy> bindings,
2171 Tcl_Finalize() may invoke Python code but at that point the
2172 interpreter and thread state have already been destroyed! */
2173 Py_AtExit(Tcl_Finalize
);
2178 ** Part of this code is stolen from MacintoshInit in tkMacAppInit.
2179 ** Most of the initializations in that routine (toolbox init calls and
2180 ** such) have already been done for us, so we only need these.
2184 Tcl_MacSetEventProc(PyMacConvertEvent
);
2186 mac_addlibresources();
2187 #endif /* GENERATINGCFM */
2188 #endif /* macintosh */
2196 ** Anyone who embeds Tcl/Tk on the Mac must define panic().
2200 panic(char * format
, ...)
2204 va_start(varg
, format
);
2206 vfprintf(stderr
, format
, varg
);
2207 (void) fflush(stderr
);
2211 Py_FatalError("Tcl/Tk panic");
2215 ** Pass events to SIOUX before passing them to Tk.
2219 PyMacConvertEvent(EventRecord
*eventPtr
)
2223 ** Sioux eats too many events, so we don't pass it everything. We
2224 ** always pass update events to Sioux, and we only pass other events if
2225 ** the Sioux window is frontmost. This means that Tk menus don't work
2226 ** in that case, but at least we can scroll the sioux window.
2227 ** Note that the SIOUXIsAppWindow() routine we use here is not really
2228 ** part of the external interface of Sioux...
2230 frontwin
= FrontWindow();
2231 if ( eventPtr
->what
== updateEvt
|| SIOUXIsAppWindow(frontwin
) ) {
2232 if (SIOUXHandleOneEvent(eventPtr
))
2233 return 0; /* Nothing happened to the Tcl event queue */
2235 return TkMacConvertEvent(eventPtr
);
2241 ** Additional Mac specific code for dealing with shared libraries.
2244 #include <Resources.h>
2245 #include <CodeFragments.h>
2247 static int loaded_from_shlib
= 0;
2248 static FSSpec library_fss
;
2251 ** If this module is dynamically loaded the following routine should
2252 ** be the init routine. It takes care of adding the shared library to
2253 ** the resource-file chain, so that the tk routines can find their
2257 init_tkinter_shlib(CFragInitBlockPtr data
)
2260 if ( data
== nil
) return noErr
;
2261 if ( data
->fragLocator
.where
== kDataForkCFragLocator
) {
2262 library_fss
= *data
->fragLocator
.u
.onDisk
.fileSpec
;
2263 loaded_from_shlib
= 1;
2264 } else if ( data
->fragLocator
.where
== kResourceCFragLocator
) {
2265 library_fss
= *data
->fragLocator
.u
.inSegs
.fileSpec
;
2266 loaded_from_shlib
= 1;
2272 ** Insert the library resources into the search path. Put them after
2273 ** the resources from the application. Again, we ignore errors.
2276 mac_addlibresources(void)
2278 if ( !loaded_from_shlib
)
2280 (void)FSpOpenResFile(&library_fss
, fsRdPerm
);
2283 #endif /* GENERATINGCFM */
2284 #endif /* macintosh */