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.2 and later are supported. Older versions are not
13 supported. (Use Python 2.2 if you cannot upgrade your Tcl/Tk
17 /* XXX Further speed-up ideas, involving Tcl 8.0 features:
19 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
36 /* Allow using this code in Python 2.[12] */
38 #define PyDoc_STRVAR(name,str) static char name[] = str
41 #ifndef PyMODINIT_FUNC
42 #define PyMODINIT_FUNC void
46 #define PyBool_Check(o) 0
47 #define PyBool_FromLong PyLong_FromLong
50 /* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
51 making _tkinter correct for this API means to break earlier
52 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
53 earlier versions. Once Tcl releases before 8.4 don't need to be supported
54 anymore, this should go. */
55 #define USE_COMPAT_CONST
57 /* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
58 it always; if Tcl is not threaded, the thread functions in
70 /* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
71 #ifndef CONST84_RETURN
72 #define CONST84_RETURN
77 #define TKMAJORMINOR (TK_MAJOR_VERSION*1000 + TK_MINOR_VERSION)
79 #if TKMAJORMINOR < 8002
80 #error "Tk older than 8.2 not supported"
83 /* Unicode conversion assumes that Tcl_UniChar is two bytes.
84 We cannot test this directly, so we test UTF-8 size instead,
85 expecting that TCL_UTF_MAX is changed if Tcl ever supports
86 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
88 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
91 #if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
92 #error "unsupported Tcl configuration"
95 #if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
96 #define HAVE_CREATEFILEHANDLER
99 #ifdef HAVE_CREATEFILEHANDLER
101 /* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
102 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
104 # ifdef TCL_WIN_SOCKET
105 # define TCL_UNIX_FD (! TCL_WIN_SOCKET)
107 # define TCL_UNIX_FD 1
111 /* Tcl_CreateFileHandler() changed several times; these macros deal with the
112 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
113 Unix, only because Jack added it back); when available on Windows, it only
114 applies to sockets. */
117 #define FHANDLETYPE TCL_WIN_SOCKET
119 #define FHANDLETYPE TCL_UNIX_FD
122 /* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
123 which uses this to handle Tcl events while the user is typing commands. */
125 #if FHANDLETYPE == TCL_UNIX_FD
126 #define WAIT_FOR_STDIN
129 #endif /* HAVE_CREATEFILEHANDLER */
133 #define WAIT_FOR_STDIN
138 /* The threading situation is complicated. Tcl is not thread-safe, except
139 when configured with --enable-threads.
140 So we need to use a lock around all uses of Tcl. Previously, the Python
141 interpreter lock was used for this. However, this causes problems when
142 other Python threads need to run while Tcl is blocked waiting for events.
144 To solve this problem, a separate lock for Tcl is introduced. Holding it
145 is incompatible with holding Python's interpreter lock. The following four
146 macros manipulate both locks together.
148 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
149 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
150 that could call an event handler, or otherwise affect the state of a Tcl
151 interpreter. These assume that the surrounding code has the Python
152 interpreter lock; inside the brackets, the Python interpreter lock has been
153 released and the lock for Tcl has been acquired.
155 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
156 (For example, when transferring data from the Tcl interpreter result to a
157 Python string object.) This can be done by using different macros to close
158 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
159 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
160 releases the Tcl lock.
162 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
163 handlers when the handler needs to use Python. Such event handlers are
164 entered while the lock for Tcl is held; the event handler presumably needs
165 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
166 the Python interpreter lock, restoring the appropriate thread state, and
167 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
168 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
169 the code between ENTER_PYTHON and LEAVE_PYTHON.
171 These locks expand to several statements and brackets; they should not be
172 used in branches of if statements and the like.
174 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
175 only valid in the thread that created it, and all Tk activity must happen in this
176 thread, also. That means that the mainloop must be invoked in the thread that
177 created the interpreter. Invoking commands from other threads is possible;
178 _tkinter will queue an event for the interpreter thread, which will then
179 execute the command and pass back the result. If the main thread is not in the
180 mainloop, and invoking commands causes an exception; if the main loop is running
181 but not processing events, the command invocation will block.
183 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
184 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
185 threads. So we use the Tcl TLS API.
189 static PyThread_type_lock tcl_lock
= 0;
192 static Tcl_ThreadDataKey state_key
;
193 typedef PyThreadState
*ThreadSpecificData
;
194 #define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
196 static PyThreadState
*tcl_tstate
= NULL
;
200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
204 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
206 #define ENTER_OVERLAP \
209 #define LEAVE_OVERLAP_TCL \
210 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
212 #define ENTER_PYTHON \
213 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
214 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
216 #define LEAVE_PYTHON \
217 { PyThreadState *tstate = PyEval_SaveThread(); \
218 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
220 #define CHECK_TCL_APPARTMENT \
221 if (((TkappObject *)self)->threaded && \
222 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
223 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
231 #define ENTER_OVERLAP
232 #define LEAVE_OVERLAP_TCL
235 #define CHECK_TCL_APPARTMENT
240 #define FREECAST (char *)
243 /**** Tkapp Object Declaration ****/
245 static PyTypeObject Tkapp_Type
;
251 int threaded
; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id
;
254 /* We cannot include tclInt.h, as this is internal.
255 So we cache interesting types here. */
256 Tcl_ObjType
*BooleanType
;
257 Tcl_ObjType
*ByteArrayType
;
258 Tcl_ObjType
*DoubleType
;
259 Tcl_ObjType
*IntType
;
260 Tcl_ObjType
*ListType
;
261 Tcl_ObjType
*ProcBodyType
;
262 Tcl_ObjType
*StringType
;
265 #define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
266 #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
267 #define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
269 #define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
270 (void *) v, Py_REFCNT(v)))
274 /**** Error Handling ****/
276 static PyObject
*Tkinter_TclError
;
277 static int quitMainLoop
= 0;
278 static int errorInCmd
= 0;
279 static PyObject
*excInCmd
;
280 static PyObject
*valInCmd
;
281 static PyObject
*trbInCmd
;
286 Tkinter_Error(PyObject
*v
)
288 PyErr_SetString(Tkinter_TclError
, Tkapp_Result(v
));
296 static int Tkinter_busywaitinterval
= 20;
301 /* Millisecond sleep() for Unix platforms. */
306 /* XXX Too bad if you don't have select(). */
308 t
.tv_sec
= milli
/1000;
309 t
.tv_usec
= (milli
%1000) * 1000;
310 select(0, (fd_set
*)0, (fd_set
*)0, (fd_set
*)0, &t
);
312 #endif /* MS_WINDOWS */
314 /* Wait up to 1s for the mainloop to come up. */
317 WaitForMainloop(TkappObject
* self
)
320 for (i
= 0; i
< 10; i
++) {
321 if (self
->dispatching
)
323 Py_BEGIN_ALLOW_THREADS
327 if (self
->dispatching
)
329 PyErr_SetString(PyExc_RuntimeError
, "main thread is not in main loop");
332 #endif /* WITH_THREAD */
336 AsString(PyObject
*value
, PyObject
*tmp
)
338 if (PyString_Check(value
))
339 return PyString_AsString(value
);
340 else if (PyUnicode_Check(value
)) {
341 PyObject
*v
= PyUnicode_AsUTF8String(value
);
344 if (PyList_Append(tmp
, v
) != 0) {
349 return PyString_AsString(v
);
352 PyObject
*v
= PyObject_Str(value
);
355 if (PyList_Append(tmp
, v
) != 0) {
360 return PyString_AsString(v
);
369 Merge(PyObject
*args
)
371 PyObject
*tmp
= NULL
;
372 char *argvStore
[ARGSZ
];
376 int argc
= 0, fvc
= 0, i
;
379 if (!(tmp
= PyList_New(0)))
388 else if (!PyTuple_Check(args
)) {
391 if (!(argv
[0] = AsString(args
, tmp
)))
395 argc
= PyTuple_Size(args
);
398 argv
= (char **)ckalloc(argc
* sizeof(char *));
399 fv
= (int *)ckalloc(argc
* sizeof(int));
400 if (argv
== NULL
|| fv
== NULL
) {
406 for (i
= 0; i
< argc
; i
++) {
407 PyObject
*v
= PyTuple_GetItem(args
, i
);
408 if (PyTuple_Check(v
)) {
410 if (!(argv
[i
] = Merge(v
)))
414 else if (v
== Py_None
) {
420 if (!(argv
[i
] = AsString(v
, tmp
)))
426 res
= Tcl_Merge(argc
, argv
);
428 PyErr_SetString(Tkinter_TclError
, "merge failed");
431 for (i
= 0; i
< fvc
; i
++)
435 if (argv
!= argvStore
)
436 ckfree(FREECAST argv
);
458 if (Tcl_SplitList((Tcl_Interp
*)NULL
, list
, &argc
, &argv
) != TCL_OK
) {
460 * Could be a quoted string containing funnies, e.g. {"}.
461 * Return the string itself.
463 return PyUnicode_FromString(list
);
467 v
= PyUnicode_FromString("");
469 v
= PyUnicode_FromString(argv
[0]);
470 else if ((v
= PyTuple_New(argc
)) != NULL
) {
474 for (i
= 0; i
< argc
; i
++) {
475 if ((w
= Split(argv
[i
])) == NULL
) {
480 PyTuple_SetItem(v
, i
, w
);
483 Tcl_Free(FREECAST argv
);
487 /* In some cases, Tcl will still return strings that are supposed to be
488 lists. SplitObj walks through a nested tuple, finding string objects that
492 SplitObj(PyObject
*arg
)
494 if (PyTuple_Check(arg
)) {
496 PyObject
*elem
, *newelem
, *result
;
498 size
= PyTuple_Size(arg
);
500 /* Recursively invoke SplitObj for all tuple items.
501 If this does not return a new object, no action is
503 for(i
= 0; i
< size
; i
++) {
504 elem
= PyTuple_GetItem(arg
, i
);
505 newelem
= SplitObj(elem
);
512 if (newelem
== elem
) {
516 result
= PyTuple_New(size
);
519 for(k
= 0; k
< i
; k
++) {
520 elem
= PyTuple_GetItem(arg
, k
);
522 PyTuple_SetItem(result
, k
, elem
);
525 PyTuple_SetItem(result
, i
, newelem
);
529 /* Fall through, returning arg. */
531 else if (PyString_Check(arg
)) {
534 char *list
= PyString_AsString(arg
);
536 if (Tcl_SplitList((Tcl_Interp
*)NULL
, list
, &argc
, &argv
) != TCL_OK
) {
540 Tcl_Free(FREECAST argv
);
542 return Split(PyString_AsString(arg
));
543 /* Fall through, returning arg. */
550 /**** Tkapp Object ****/
554 Tcl_AppInit(Tcl_Interp
*interp
)
557 const char * _tkinter_skip_tk_init
;
559 if (Tcl_Init(interp
) == TCL_ERROR
) {
560 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp
));
563 _tkinter_skip_tk_init
= Tcl_GetVar(interp
, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY
);
564 if (_tkinter_skip_tk_init
== NULL
|| strcmp(_tkinter_skip_tk_init
, "1") != 0) {
565 main
= Tk_MainWindow(interp
);
566 if (Tk_Init(interp
) == TCL_ERROR
) {
567 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp
));
573 #endif /* !WITH_APPINIT */
578 /* Initialize the Tk application; see the `main' function in
582 static void EnableEventHook(void); /* Forward */
583 static void DisableEventHook(void); /* Forward */
586 Tkapp_New(char *screenName
, char *baseName
, char *className
,
587 int interactive
, int wantobjects
, int wantTk
, int sync
, char *use
)
592 v
= PyObject_New(TkappObject
, &Tkapp_Type
);
596 v
->interp
= Tcl_CreateInterp();
597 v
->wantobjects
= wantobjects
;
598 v
->threaded
= Tcl_GetVar2Ex(v
->interp
, "tcl_platform", "threaded",
599 TCL_GLOBAL_ONLY
) != NULL
;
600 v
->thread_id
= Tcl_GetCurrentThread();
605 PyErr_SetString(PyExc_RuntimeError
, "Tcl is threaded but _tkinter is not");
611 if (v
->threaded
&& tcl_lock
) {
612 /* If Tcl is threaded, we don't need the lock. */
613 PyThread_free_lock(tcl_lock
);
618 v
->BooleanType
= Tcl_GetObjType("boolean");
619 v
->ByteArrayType
= Tcl_GetObjType("bytearray");
620 v
->DoubleType
= Tcl_GetObjType("double");
621 v
->IntType
= Tcl_GetObjType("int");
622 v
->ListType
= Tcl_GetObjType("list");
623 v
->ProcBodyType
= Tcl_GetObjType("procbody");
624 v
->StringType
= Tcl_GetObjType("string");
626 /* Delete the 'exit' command, which can screw things up */
627 Tcl_DeleteCommand(v
->interp
, "exit");
629 if (screenName
!= NULL
)
630 Tcl_SetVar2(v
->interp
, "env", "DISPLAY",
631 screenName
, TCL_GLOBAL_ONLY
);
634 Tcl_SetVar(v
->interp
, "tcl_interactive", "1", TCL_GLOBAL_ONLY
);
636 Tcl_SetVar(v
->interp
, "tcl_interactive", "0", TCL_GLOBAL_ONLY
);
638 /* This is used to get the application class for Tk 4.1 and up */
639 argv0
= (char*)ckalloc(strlen(className
) + 1);
646 strcpy(argv0
, className
);
647 if (isupper(Py_CHARMASK(argv0
[0])))
648 argv0
[0] = tolower(Py_CHARMASK(argv0
[0]));
649 Tcl_SetVar(v
->interp
, "argv0", argv0
, TCL_GLOBAL_ONLY
);
653 Tcl_SetVar(v
->interp
, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY
);
656 /* some initial arguments need to be in argv */
662 len
+= sizeof "-sync";
664 len
+= strlen(use
) + sizeof "-use ";
666 args
= (char*)ckalloc(len
);
675 strcat(args
, "-sync");
679 strcat(args
, "-use ");
683 Tcl_SetVar(v
->interp
, "argv", args
, TCL_GLOBAL_ONLY
);
687 if (Tcl_AppInit(v
->interp
) != TCL_OK
) {
688 PyObject
*result
= Tkinter_Error((PyObject
*)v
);
689 Py_DECREF((PyObject
*)v
);
690 return (TkappObject
*)result
;
700 Tkapp_ThreadSend(TkappObject
*self
, Tcl_Event
*ev
,
701 Tcl_Condition
*cond
, Tcl_Mutex
*mutex
)
703 Py_BEGIN_ALLOW_THREADS
;
704 Tcl_MutexLock(mutex
);
705 Tcl_ThreadQueueEvent(self
->thread_id
, ev
, TCL_QUEUE_TAIL
);
706 Tcl_ThreadAlert(self
->thread_id
);
707 Tcl_ConditionWait(cond
, mutex
, NULL
);
708 Tcl_MutexUnlock(mutex
);
718 PyObject
*string
; /* This cannot cause cycles. */
721 static PyTypeObject PyTclObject_Type
;
722 #define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
725 newPyTclObject(Tcl_Obj
*arg
)
728 self
= PyObject_New(PyTclObject
, &PyTclObject_Type
);
731 Tcl_IncrRefCount(arg
);
734 return (PyObject
*)self
;
738 PyTclObject_dealloc(PyTclObject
*self
)
740 Tcl_DecrRefCount(self
->value
);
741 Py_XDECREF(self
->string
);
746 PyTclObject_TclString(PyObject
*self
)
748 return Tcl_GetString(((PyTclObject
*)self
)->value
);
751 /* Like _str, but create Unicode if necessary. */
752 PyDoc_STRVAR(PyTclObject_string__doc__
,
753 "the string representation of this object, either as str or bytes");
756 PyTclObject_string(PyTclObject
*self
, void *ignored
)
761 s
= Tcl_GetStringFromObj(self
->value
, &len
);
762 self
->string
= PyUnicode_FromStringAndSize(s
, len
);
766 Py_INCREF(self
->string
);
771 PyTclObject_str(PyTclObject
*self
, void *ignored
)
775 if (self
->string
&& PyUnicode_Check(self
->string
)) {
776 Py_INCREF(self
->string
);
779 /* XXX Could chache result if it is non-ASCII. */
780 s
= Tcl_GetStringFromObj(self
->value
, &len
);
781 return PyUnicode_DecodeUTF8(s
, len
, "strict");
785 PyTclObject_repr(PyTclObject
*self
)
787 return PyUnicode_FromFormat("<%s object at %p>",
788 self
->value
->typePtr
->name
, self
->value
);
792 PyTclObject_cmp(PyTclObject
*self
, PyTclObject
*other
)
795 res
= strcmp(Tcl_GetString(self
->value
),
796 Tcl_GetString(other
->value
));
797 if (res
< 0) return -1;
798 if (res
> 0) return 1;
802 PyDoc_STRVAR(get_typename__doc__
, "name of the Tcl type");
805 get_typename(PyTclObject
* obj
, void* ignored
)
807 return PyUnicode_FromString(obj
->value
->typePtr
->name
);
811 static PyGetSetDef PyTclObject_getsetlist
[] = {
812 {"typename", (getter
)get_typename
, NULL
, get_typename__doc__
},
813 {"string", (getter
)PyTclObject_string
, NULL
,
814 PyTclObject_string__doc__
},
818 static PyTypeObject PyTclObject_Type
= {
819 PyVarObject_HEAD_INIT(NULL
, 0)
820 "_tkinter.Tcl_Obj", /*tp_name*/
821 sizeof(PyTclObject
), /*tp_basicsize*/
824 (destructor
)PyTclObject_dealloc
, /*tp_dealloc*/
828 (cmpfunc
)PyTclObject_cmp
, /*tp_compare*/
829 (reprfunc
)PyTclObject_repr
, /*tp_repr*/
831 0, /*tp_as_sequence*/
835 (reprfunc
)PyTclObject_str
, /*tp_str*/
836 PyObject_GenericGetAttr
,/*tp_getattro*/
839 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
843 0, /*tp_richcompare*/
844 0, /*tp_weaklistoffset*/
849 PyTclObject_getsetlist
, /*tp_getset*/
863 AsObj(PyObject
*value
)
869 if (PyString_Check(value
))
870 return Tcl_NewStringObj(PyString_AS_STRING(value
),
871 PyString_GET_SIZE(value
));
872 else if (PyBool_Check(value
))
873 return Tcl_NewBooleanObj(PyObject_IsTrue(value
));
874 else if (PyLong_CheckExact(value
) &&
875 ((longVal
= PyLong_AsLongAndOverflow(value
, &overflow
)),
877 /* If there is an overflow in the long conversion,
878 fall through to default object handling. */
879 return Tcl_NewLongObj(longVal
);
881 else if (PyFloat_Check(value
))
882 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value
));
883 else if (PyTuple_Check(value
)) {
884 Tcl_Obj
**argv
= (Tcl_Obj
**)
885 ckalloc(PyTuple_Size(value
)*sizeof(Tcl_Obj
*));
889 for(i
=0;i
<PyTuple_Size(value
);i
++)
890 argv
[i
] = AsObj(PyTuple_GetItem(value
,i
));
891 result
= Tcl_NewListObj(PyTuple_Size(value
), argv
);
892 ckfree(FREECAST argv
);
895 else if (PyUnicode_Check(value
)) {
896 Py_UNICODE
*inbuf
= PyUnicode_AS_UNICODE(value
);
897 Py_ssize_t size
= PyUnicode_GET_SIZE(value
);
898 /* This #ifdef assumes that Tcl uses UCS-2.
899 See TCL_UTF_MAX test above. */
900 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
901 Tcl_UniChar
*outbuf
= NULL
;
903 size_t allocsize
= ((size_t)size
) * sizeof(Tcl_UniChar
);
904 if (allocsize
>= size
)
905 outbuf
= (Tcl_UniChar
*)ckalloc(allocsize
);
906 /* Else overflow occurred, and we take the next exit */
911 for (i
= 0; i
< size
; i
++) {
912 if (inbuf
[i
] >= 0x10000) {
913 /* Tcl doesn't do UTF-16, yet. */
914 PyErr_SetString(PyExc_ValueError
,
915 "unsupported character");
916 ckfree(FREECAST outbuf
);
919 outbuf
[i
] = inbuf
[i
];
921 result
= Tcl_NewUnicodeObj(outbuf
, size
);
922 ckfree(FREECAST outbuf
);
925 return Tcl_NewUnicodeObj(inbuf
, size
);
929 else if(PyTclObject_Check(value
)) {
930 Tcl_Obj
*v
= ((PyTclObject
*)value
)->value
;
935 PyObject
*v
= PyObject_Str(value
);
945 FromObj(PyObject
* tkapp
, Tcl_Obj
*value
)
947 PyObject
*result
= NULL
;
948 TkappObject
*app
= (TkappObject
*)tkapp
;
950 if (value
->typePtr
== NULL
) {
951 return PyUnicode_FromStringAndSize(value
->bytes
,
955 if (value
->typePtr
== app
->BooleanType
) {
956 result
= value
->internalRep
.longValue
? Py_True
: Py_False
;
961 if (value
->typePtr
== app
->ByteArrayType
) {
963 char *data
= (char*)Tcl_GetByteArrayFromObj(value
, &size
);
964 return PyString_FromStringAndSize(data
, size
);
967 if (value
->typePtr
== app
->DoubleType
) {
968 return PyFloat_FromDouble(value
->internalRep
.doubleValue
);
971 if (value
->typePtr
== app
->IntType
) {
972 return PyLong_FromLong(value
->internalRep
.longValue
);
975 if (value
->typePtr
== app
->ListType
) {
981 status
= Tcl_ListObjLength(Tkapp_Interp(tkapp
), value
, &size
);
982 if (status
== TCL_ERROR
)
983 return Tkinter_Error(tkapp
);
984 result
= PyTuple_New(size
);
987 for (i
= 0; i
< size
; i
++) {
988 status
= Tcl_ListObjIndex(Tkapp_Interp(tkapp
),
989 value
, i
, &tcl_elem
);
990 if (status
== TCL_ERROR
) {
992 return Tkinter_Error(tkapp
);
994 elem
= FromObj(tkapp
, tcl_elem
);
999 PyTuple_SetItem(result
, i
, elem
);
1004 if (value
->typePtr
== app
->ProcBodyType
) {
1005 /* fall through: return tcl object. */
1008 if (value
->typePtr
== app
->StringType
) {
1009 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1015 size
= Tcl_GetCharLength(value
);
1016 result
= PyUnicode_FromUnicode(NULL
, size
);
1019 input
= Tcl_GetUnicode(value
);
1020 output
= PyUnicode_AS_UNICODE(result
);
1022 *output
++ = *input
++;
1025 return PyUnicode_FromUnicode(Tcl_GetUnicode(value
),
1026 Tcl_GetCharLength(value
));
1030 return newPyTclObject(value
);
1033 /* This mutex synchronizes inter-thread command calls. */
1035 TCL_DECLARE_MUTEX(call_mutex
)
1037 typedef struct Tkapp_CallEvent
{
1038 Tcl_Event ev
; /* Must be first */
1043 PyObject
**exc_type
, **exc_value
, **exc_tb
;
1048 Tkapp_CallDeallocArgs(Tcl_Obj
** objv
, Tcl_Obj
** objStore
, int objc
)
1051 for (i
= 0; i
< objc
; i
++)
1052 Tcl_DecrRefCount(objv
[i
]);
1053 if (objv
!= objStore
)
1054 ckfree(FREECAST objv
);
1057 /* Convert Python objects to Tcl objects. This must happen in the
1058 interpreter thread, which may or may not be the calling thread. */
1061 Tkapp_CallArgs(PyObject
*args
, Tcl_Obj
** objStore
, int *pobjc
)
1063 Tcl_Obj
**objv
= objStore
;
1068 else if (!PyTuple_Check(args
)) {
1069 objv
[0] = AsObj(args
);
1073 Tcl_IncrRefCount(objv
[0]);
1076 objc
= PyTuple_Size(args
);
1079 objv
= (Tcl_Obj
**)ckalloc(objc
* sizeof(char *));
1087 for (i
= 0; i
< objc
; i
++) {
1088 PyObject
*v
= PyTuple_GetItem(args
, i
);
1095 /* Reset objc, so it attempts to clear
1096 objects only up to i. */
1100 Tcl_IncrRefCount(objv
[i
]);
1106 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1110 /* Convert the results of a command call into a Python objects. */
1113 Tkapp_CallResult(TkappObject
*self
)
1115 PyObject
*res
= NULL
;
1116 if(self
->wantobjects
) {
1117 Tcl_Obj
*value
= Tcl_GetObjResult(self
->interp
);
1118 /* Not sure whether the IncrRef is necessary, but something
1119 may overwrite the interpreter result while we are
1121 Tcl_IncrRefCount(value
);
1122 res
= FromObj((PyObject
*)self
, value
);
1123 Tcl_DecrRefCount(value
);
1125 const char *s
= Tcl_GetStringResult(self
->interp
);
1128 res
= PyUnicode_FromStringAndSize(s
, (int)(p
-s
));
1133 /* Tkapp_CallProc is the event procedure that is executed in the context of
1134 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1135 hold the Python lock. */
1138 Tkapp_CallProc(Tkapp_CallEvent
*e
, int flags
)
1140 Tcl_Obj
*objStore
[ARGSZ
];
1145 objv
= Tkapp_CallArgs(e
->args
, objStore
, &objc
);
1147 PyErr_Fetch(e
->exc_type
, e
->exc_value
, e
->exc_tb
);
1153 i
= Tcl_EvalObjv(e
->self
->interp
, objc
, objv
, e
->flags
);
1155 if (i
== TCL_ERROR
) {
1157 *(e
->exc_type
) = NULL
;
1158 *(e
->exc_tb
) = NULL
;
1159 *(e
->exc_value
) = PyObject_CallFunction(
1160 Tkinter_TclError
, "s",
1161 Tcl_GetStringResult(e
->self
->interp
));
1164 *(e
->res
) = Tkapp_CallResult(e
->self
);
1168 /* Wake up calling thread. */
1169 Tcl_MutexLock(&call_mutex
);
1170 Tcl_ConditionNotify(&e
->done
);
1171 Tcl_MutexUnlock(&call_mutex
);
1175 /* This is the main entry point for calling a Tcl command.
1176 It supports three cases, with regard to threading:
1177 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1178 the context of the calling thread.
1179 2. Tcl is threaded, caller of the command is in the interpreter thread:
1180 Execute the command in the calling thread. Since the Tcl lock will
1181 not be used, we can merge that with case 1.
1182 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1183 the interpreter thread. Allocation of Tcl objects needs to occur in the
1184 interpreter thread, so we ship the PyObject* args to the target thread,
1185 and perform processing there. */
1188 Tkapp_Call(PyObject
*selfptr
, PyObject
*args
)
1190 Tcl_Obj
*objStore
[ARGSZ
];
1191 Tcl_Obj
**objv
= NULL
;
1193 PyObject
*res
= NULL
;
1194 TkappObject
*self
= (TkappObject
*)selfptr
;
1195 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1196 int flags
= TCL_EVAL_DIRECT
;
1198 /* If args is a single tuple, replace with contents of tuple */
1199 if (1 == PyTuple_Size(args
)){
1200 PyObject
* item
= PyTuple_GetItem(args
, 0);
1201 if (PyTuple_Check(item
))
1205 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1206 /* We cannot call the command directly. Instead, we must
1207 marshal the parameters to the interpreter thread. */
1208 Tkapp_CallEvent
*ev
;
1209 PyObject
*exc_type
, *exc_value
, *exc_tb
;
1210 if (!WaitForMainloop(self
))
1212 ev
= (Tkapp_CallEvent
*)ckalloc(sizeof(Tkapp_CallEvent
));
1213 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CallProc
;
1217 ev
->exc_type
= &exc_type
;
1218 ev
->exc_value
= &exc_value
;
1219 ev
->exc_tb
= &exc_tb
;
1220 ev
->done
= (Tcl_Condition
)0;
1222 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
, &call_mutex
);
1226 PyErr_Restore(exc_type
, exc_value
, exc_tb
);
1228 PyErr_SetObject(Tkinter_TclError
, exc_value
);
1235 objv
= Tkapp_CallArgs(args
, objStore
, &objc
);
1241 i
= Tcl_EvalObjv(self
->interp
, objc
, objv
, flags
);
1246 Tkinter_Error(selfptr
);
1248 res
= Tkapp_CallResult(self
);
1252 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1259 Tkapp_GlobalCall(PyObject
*self
, PyObject
*args
)
1261 /* Could do the same here as for Tkapp_Call(), but this is not used
1262 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1263 way for the user to do what all its Global* variants do (save and
1264 reset the scope pointer, call the local version, restore the saved
1268 PyObject
*res
= NULL
;
1270 CHECK_TCL_APPARTMENT
;
1276 err
= Tcl_GlobalEval(Tkapp_Interp(self
), cmd
);
1278 if (err
== TCL_ERROR
)
1279 res
= Tkinter_Error(self
);
1281 res
= PyUnicode_FromString(Tkapp_Result(self
));
1290 Tkapp_Eval(PyObject
*self
, PyObject
*args
)
1293 PyObject
*res
= NULL
;
1296 if (!PyArg_ParseTuple(args
, "s:eval", &script
))
1299 CHECK_TCL_APPARTMENT
;
1302 err
= Tcl_Eval(Tkapp_Interp(self
), script
);
1304 if (err
== TCL_ERROR
)
1305 res
= Tkinter_Error(self
);
1307 res
= PyUnicode_FromString(Tkapp_Result(self
));
1313 Tkapp_GlobalEval(PyObject
*self
, PyObject
*args
)
1316 PyObject
*res
= NULL
;
1319 if (!PyArg_ParseTuple(args
, "s:globaleval", &script
))
1322 CHECK_TCL_APPARTMENT
;
1325 err
= Tcl_GlobalEval(Tkapp_Interp(self
), script
);
1327 if (err
== TCL_ERROR
)
1328 res
= Tkinter_Error(self
);
1330 res
= PyUnicode_FromString(Tkapp_Result(self
));
1336 Tkapp_EvalFile(PyObject
*self
, PyObject
*args
)
1339 PyObject
*res
= NULL
;
1342 if (!PyArg_ParseTuple(args
, "s:evalfile", &fileName
))
1345 CHECK_TCL_APPARTMENT
;
1348 err
= Tcl_EvalFile(Tkapp_Interp(self
), fileName
);
1350 if (err
== TCL_ERROR
)
1351 res
= Tkinter_Error(self
);
1354 res
= PyUnicode_FromString(Tkapp_Result(self
));
1360 Tkapp_Record(PyObject
*self
, PyObject
*args
)
1363 PyObject
*res
= NULL
;
1366 if (!PyArg_ParseTuple(args
, "s", &script
))
1369 CHECK_TCL_APPARTMENT
;
1372 err
= Tcl_RecordAndEval(Tkapp_Interp(self
), script
, TCL_NO_EVAL
);
1374 if (err
== TCL_ERROR
)
1375 res
= Tkinter_Error(self
);
1377 res
= PyUnicode_FromString(Tkapp_Result(self
));
1383 Tkapp_AddErrorInfo(PyObject
*self
, PyObject
*args
)
1387 if (!PyArg_ParseTuple(args
, "s:adderrorinfo", &msg
))
1389 CHECK_TCL_APPARTMENT
;
1392 Tcl_AddErrorInfo(Tkapp_Interp(self
), msg
);
1401 /** Tcl Variable **/
1403 TCL_DECLARE_MUTEX(var_mutex
)
1405 typedef PyObject
* (*EventFunc
)(PyObject
*, PyObject
*args
, int flags
);
1406 typedef struct VarEvent
{
1407 Tcl_Event ev
; /* must be first */
1413 PyObject
**exc_type
;
1419 varname_converter(PyObject
*in
, void *_out
)
1421 char **out
= (char**)_out
;
1422 if (PyString_Check(in
)) {
1423 *out
= PyString_AsString(in
);
1426 if (PyUnicode_Check(in
)) {
1427 *out
= PyUnicode_AsString(in
);
1430 if (PyTclObject_Check(in
)) {
1431 *out
= PyTclObject_TclString(in
);
1434 /* XXX: Should give diagnostics. */
1439 var_perform(VarEvent
*ev
)
1441 *(ev
->res
) = ev
->func(ev
->self
, ev
->args
, ev
->flags
);
1443 PyObject
*exc
, *val
, *tb
;
1444 PyErr_Fetch(&exc
, &val
, &tb
);
1445 PyErr_NormalizeException(&exc
, &val
, &tb
);
1446 *(ev
->exc_type
) = exc
;
1447 *(ev
->exc_val
) = val
;
1454 var_proc(VarEvent
* ev
, int flags
)
1458 Tcl_MutexLock(&var_mutex
);
1459 Tcl_ConditionNotify(&ev
->cond
);
1460 Tcl_MutexUnlock(&var_mutex
);
1466 var_invoke(EventFunc func
, PyObject
*selfptr
, PyObject
*args
, int flags
)
1468 TkappObject
*self
= (TkappObject
*)selfptr
;
1470 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1471 TkappObject
*self
= (TkappObject
*)selfptr
;
1473 PyObject
*res
, *exc_type
, *exc_val
;
1475 /* The current thread is not the interpreter thread. Marshal
1476 the call to the interpreter thread, then wait for
1478 if (!WaitForMainloop(self
))
1481 ev
= (VarEvent
*)ckalloc(sizeof(VarEvent
));
1488 ev
->exc_type
= &exc_type
;
1489 ev
->exc_val
= &exc_val
;
1491 ev
->ev
.proc
= (Tcl_EventProc
*)var_proc
;
1492 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->cond
, &var_mutex
);
1494 PyErr_SetObject(exc_type
, exc_val
);
1495 Py_DECREF(exc_type
);
1502 /* Tcl is not threaded, or this is the interpreter thread. */
1503 return func(selfptr
, args
, flags
);
1507 SetVar(PyObject
*self
, PyObject
*args
, int flags
)
1509 char *name1
, *name2
;
1511 PyObject
*res
= NULL
;
1512 Tcl_Obj
*newval
, *ok
;
1514 if (PyArg_ParseTuple(args
, "O&O:setvar",
1515 varname_converter
, &name1
, &newValue
)) {
1516 /* XXX Acquire tcl lock??? */
1517 newval
= AsObj(newValue
);
1521 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, NULL
,
1525 Tkinter_Error(self
);
1534 if (PyArg_ParseTuple(args
, "ssO:setvar",
1535 &name1
, &name2
, &newValue
)) {
1536 /* XXX must hold tcl lock already??? */
1537 newval
= AsObj(newValue
);
1539 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, name2
, newval
, flags
);
1542 Tkinter_Error(self
);
1557 Tkapp_SetVar(PyObject
*self
, PyObject
*args
)
1559 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1563 Tkapp_GlobalSetVar(PyObject
*self
, PyObject
*args
)
1565 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1571 GetVar(PyObject
*self
, PyObject
*args
, int flags
)
1573 char *name1
, *name2
=NULL
;
1574 PyObject
*res
= NULL
;
1577 if (!PyArg_ParseTuple(args
, "O&|s:getvar",
1578 varname_converter
, &name1
, &name2
))
1582 tres
= Tcl_GetVar2Ex(Tkapp_Interp(self
), name1
, name2
, flags
);
1585 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
1587 if (((TkappObject
*)self
)->wantobjects
) {
1588 res
= FromObj(self
, tres
);
1591 res
= PyUnicode_FromString(Tcl_GetString(tres
));
1599 Tkapp_GetVar(PyObject
*self
, PyObject
*args
)
1601 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1605 Tkapp_GlobalGetVar(PyObject
*self
, PyObject
*args
)
1607 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1613 UnsetVar(PyObject
*self
, PyObject
*args
, int flags
)
1615 char *name1
, *name2
=NULL
;
1617 PyObject
*res
= NULL
;
1619 if (!PyArg_ParseTuple(args
, "s|s:unsetvar", &name1
, &name2
))
1623 code
= Tcl_UnsetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
1625 if (code
== TCL_ERROR
)
1626 res
= Tkinter_Error(self
);
1636 Tkapp_UnsetVar(PyObject
*self
, PyObject
*args
)
1638 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1642 Tkapp_GlobalUnsetVar(PyObject
*self
, PyObject
*args
)
1644 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1649 /** Tcl to Python **/
1652 Tkapp_GetInt(PyObject
*self
, PyObject
*args
)
1657 if (PyTuple_Size(args
) == 1) {
1658 PyObject
* o
= PyTuple_GetItem(args
, 0);
1659 if (PyLong_Check(o
)) {
1664 if (!PyArg_ParseTuple(args
, "s:getint", &s
))
1666 if (Tcl_GetInt(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1667 return Tkinter_Error(self
);
1668 return Py_BuildValue("i", v
);
1672 Tkapp_GetDouble(PyObject
*self
, PyObject
*args
)
1677 if (PyTuple_Size(args
) == 1) {
1678 PyObject
*o
= PyTuple_GetItem(args
, 0);
1679 if (PyFloat_Check(o
)) {
1684 if (!PyArg_ParseTuple(args
, "s:getdouble", &s
))
1686 if (Tcl_GetDouble(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1687 return Tkinter_Error(self
);
1688 return Py_BuildValue("d", v
);
1692 Tkapp_GetBoolean(PyObject
*self
, PyObject
*args
)
1697 if (PyTuple_Size(args
) == 1) {
1698 PyObject
*o
= PyTuple_GetItem(args
, 0);
1699 if (PyLong_Check(o
)) {
1704 if (!PyArg_ParseTuple(args
, "s:getboolean", &s
))
1706 if (Tcl_GetBoolean(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1707 return Tkinter_Error(self
);
1708 return PyBool_FromLong(v
);
1712 Tkapp_ExprString(PyObject
*self
, PyObject
*args
)
1715 PyObject
*res
= NULL
;
1718 if (!PyArg_ParseTuple(args
, "s:exprstring", &s
))
1721 CHECK_TCL_APPARTMENT
;
1724 retval
= Tcl_ExprString(Tkapp_Interp(self
), s
);
1726 if (retval
== TCL_ERROR
)
1727 res
= Tkinter_Error(self
);
1729 res
= Py_BuildValue("s", Tkapp_Result(self
));
1735 Tkapp_ExprLong(PyObject
*self
, PyObject
*args
)
1738 PyObject
*res
= NULL
;
1742 if (!PyArg_ParseTuple(args
, "s:exprlong", &s
))
1745 CHECK_TCL_APPARTMENT
;
1748 retval
= Tcl_ExprLong(Tkapp_Interp(self
), s
, &v
);
1750 if (retval
== TCL_ERROR
)
1751 res
= Tkinter_Error(self
);
1753 res
= Py_BuildValue("l", v
);
1759 Tkapp_ExprDouble(PyObject
*self
, PyObject
*args
)
1762 PyObject
*res
= NULL
;
1766 if (!PyArg_ParseTuple(args
, "s:exprdouble", &s
))
1768 CHECK_TCL_APPARTMENT
;
1769 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1771 retval
= Tcl_ExprDouble(Tkapp_Interp(self
), s
, &v
);
1773 PyFPE_END_PROTECT(retval
)
1774 if (retval
== TCL_ERROR
)
1775 res
= Tkinter_Error(self
);
1777 res
= Py_BuildValue("d", v
);
1783 Tkapp_ExprBoolean(PyObject
*self
, PyObject
*args
)
1786 PyObject
*res
= NULL
;
1790 if (!PyArg_ParseTuple(args
, "s:exprboolean", &s
))
1792 CHECK_TCL_APPARTMENT
;
1794 retval
= Tcl_ExprBoolean(Tkapp_Interp(self
), s
, &v
);
1796 if (retval
== TCL_ERROR
)
1797 res
= Tkinter_Error(self
);
1799 res
= Py_BuildValue("i", v
);
1807 Tkapp_SplitList(PyObject
*self
, PyObject
*args
)
1815 if (PyTuple_Size(args
) == 1) {
1816 v
= PyTuple_GetItem(args
, 0);
1817 if (PyTuple_Check(v
)) {
1822 if (!PyArg_ParseTuple(args
, "et:splitlist", "utf-8", &list
))
1825 if (Tcl_SplitList(Tkapp_Interp(self
), list
,
1826 &argc
, &argv
) == TCL_ERROR
) {
1828 return Tkinter_Error(self
);
1831 if (!(v
= PyTuple_New(argc
)))
1834 for (i
= 0; i
< argc
; i
++) {
1835 PyObject
*s
= PyUnicode_FromString(argv
[i
]);
1836 if (!s
|| PyTuple_SetItem(v
, i
, s
)) {
1844 ckfree(FREECAST argv
);
1850 Tkapp_Split(PyObject
*self
, PyObject
*args
)
1855 if (PyTuple_Size(args
) == 1) {
1856 PyObject
* o
= PyTuple_GetItem(args
, 0);
1857 if (PyTuple_Check(o
)) {
1862 if (!PyArg_ParseTuple(args
, "et:split", "utf-8", &list
))
1870 Tkapp_Merge(PyObject
*self
, PyObject
*args
)
1872 char *s
= Merge(args
);
1873 PyObject
*res
= NULL
;
1876 res
= PyUnicode_FromString(s
);
1887 /* Client data struct */
1891 } PythonCmd_ClientData
;
1894 PythonCmd_Error(Tcl_Interp
*interp
)
1897 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1902 /* This is the Tcl command that acts as a wrapper for Python
1903 * function or method.
1906 PythonCmd(ClientData clientData
, Tcl_Interp
*interp
, int argc
, char *argv
[])
1908 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1909 PyObject
*self
, *func
, *arg
, *res
, *s
;
1915 /* TBD: no error checking here since we know, via the
1916 * Tkapp_CreateCommand() that the client data is a two-tuple
1921 /* Create argument list (argv1, ..., argvN) */
1922 if (!(arg
= PyTuple_New(argc
- 1)))
1923 return PythonCmd_Error(interp
);
1925 for (i
= 0; i
< (argc
- 1); i
++) {
1926 if (11 == (i
+ 1)) { /* the %A arg is the unicode char */
1927 char *a
= argv
[i
+ 1];
1928 s
= PyUnicode_FromUnicode((Py_UNICODE
*) a
, strlen(a
));
1931 s
= PyUnicode_FromString(argv
[i
+ 1]);
1933 if (!s
|| PyTuple_SetItem(arg
, i
, s
)) {
1935 return PythonCmd_Error(interp
);
1938 res
= PyEval_CallObject(func
, arg
);
1942 return PythonCmd_Error(interp
);
1944 obj_res
= AsObj(res
);
1945 if (obj_res
== NULL
) {
1947 return PythonCmd_Error(interp
);
1950 Tcl_SetObjResult(Tkapp_Interp(self
), obj_res
);
1962 PythonCmdDelete(ClientData clientData
)
1964 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1967 Py_XDECREF(data
->self
);
1968 Py_XDECREF(data
->func
);
1976 TCL_DECLARE_MUTEX(command_mutex
)
1978 typedef struct CommandEvent
{
1989 Tkapp_CommandProc(CommandEvent
*ev
, int flags
)
1992 *ev
->status
= Tcl_CreateCommand(
1993 ev
->interp
, ev
->name
, PythonCmd
,
1994 ev
->data
, PythonCmdDelete
) == NULL
;
1996 *ev
->status
= Tcl_DeleteCommand(ev
->interp
, ev
->name
);
1997 Tcl_MutexLock(&command_mutex
);
1998 Tcl_ConditionNotify(&ev
->done
);
1999 Tcl_MutexUnlock(&command_mutex
);
2004 Tkapp_CreateCommand(PyObject
*selfptr
, PyObject
*args
)
2006 TkappObject
*self
= (TkappObject
*)selfptr
;
2007 PythonCmd_ClientData
*data
;
2012 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
2014 if (!PyCallable_Check(func
)) {
2015 PyErr_SetString(PyExc_TypeError
, "command not callable");
2020 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread() &&
2021 !WaitForMainloop(self
))
2025 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
2027 return PyErr_NoMemory();
2030 data
->self
= selfptr
;
2033 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2034 CommandEvent
*ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2035 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2036 ev
->interp
= self
->interp
;
2039 ev
->data
= (ClientData
)data
;
2042 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
, &command_mutex
);
2046 err
= Tcl_CreateCommand(
2047 Tkapp_Interp(self
), cmdName
, PythonCmd
,
2048 (ClientData
)data
, PythonCmdDelete
) == NULL
;
2052 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
2064 Tkapp_DeleteCommand(PyObject
*selfptr
, PyObject
*args
)
2066 TkappObject
*self
= (TkappObject
*)selfptr
;
2070 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
2072 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2074 ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2075 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2076 ev
->interp
= self
->interp
;
2081 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
,
2086 err
= Tcl_DeleteCommand(self
->interp
, cmdName
);
2090 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
2099 #ifdef HAVE_CREATEFILEHANDLER
2100 /** File Handler **/
2102 typedef struct _fhcdata
{
2106 struct _fhcdata
*next
;
2107 } FileHandler_ClientData
;
2109 static FileHandler_ClientData
*HeadFHCD
;
2111 static FileHandler_ClientData
*
2112 NewFHCD(PyObject
*func
, PyObject
*file
, int id
)
2114 FileHandler_ClientData
*p
;
2115 p
= PyMem_NEW(FileHandler_ClientData
, 1);
2131 FileHandler_ClientData
*p
, **pp
;
2134 while ((p
= *pp
) != NULL
) {
2137 Py_XDECREF(p
->func
);
2138 Py_XDECREF(p
->file
);
2147 FileHandler(ClientData clientData
, int mask
)
2149 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
2150 PyObject
*func
, *file
, *arg
, *res
;
2156 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
2157 res
= PyEval_CallObject(func
, arg
);
2162 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2169 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
2170 /* args is (file, mask, func) */
2172 FileHandler_ClientData
*data
;
2173 PyObject
*file
, *func
;
2176 if (!PyArg_ParseTuple(args
, "OiO:createfilehandler",
2177 &file
, &mask
, &func
))
2181 if (!self
&& !tcl_lock
) {
2182 /* We don't have the Tcl lock since Tcl is threaded. */
2183 PyErr_SetString(PyExc_RuntimeError
,
2184 "_tkinter.createfilehandler not supported "
2185 "for threaded Tcl");
2191 CHECK_TCL_APPARTMENT
;
2194 tfile
= PyObject_AsFileDescriptor(file
);
2197 if (!PyCallable_Check(func
)) {
2198 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2202 data
= NewFHCD(func
, file
, tfile
);
2206 /* Ought to check for null Tcl_File object... */
2208 Tcl_CreateFileHandler(tfile
, mask
, FileHandler
, (ClientData
) data
);
2215 Tkapp_DeleteFileHandler(PyObject
*self
, PyObject
*args
)
2220 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
2224 if (!self
&& !tcl_lock
) {
2225 /* We don't have the Tcl lock since Tcl is threaded. */
2226 PyErr_SetString(PyExc_RuntimeError
,
2227 "_tkinter.deletefilehandler not supported "
2228 "for threaded Tcl");
2234 CHECK_TCL_APPARTMENT
;
2237 tfile
= PyObject_AsFileDescriptor(file
);
2243 /* Ought to check for null Tcl_File object... */
2245 Tcl_DeleteFileHandler(tfile
);
2250 #endif /* HAVE_CREATEFILEHANDLER */
2253 /**** Tktt Object (timer token) ****/
2255 static PyTypeObject Tktt_Type
;
2259 Tcl_TimerToken token
;
2264 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
2266 TkttObject
*v
= (TkttObject
*)self
;
2267 PyObject
*func
= v
->func
;
2269 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
2271 if (v
->token
!= NULL
) {
2272 Tcl_DeleteTimerHandler(v
->token
);
2278 Py_DECREF(v
); /* See Tktt_New() */
2284 static PyMethodDef Tktt_methods
[] =
2286 {"deletetimerhandler", Tktt_DeleteTimerHandler
, METH_VARARGS
},
2291 Tktt_New(PyObject
*func
)
2295 v
= PyObject_New(TkttObject
, &Tktt_Type
);
2303 /* Extra reference, deleted when called or when handler is deleted */
2309 Tktt_Dealloc(PyObject
*self
)
2311 TkttObject
*v
= (TkttObject
*)self
;
2312 PyObject
*func
= v
->func
;
2320 Tktt_Repr(PyObject
*self
)
2322 TkttObject
*v
= (TkttObject
*)self
;
2325 PyOS_snprintf(buf
, sizeof(buf
), "<tktimertoken at %p%s>", v
,
2326 v
->func
== NULL
? ", handler deleted" : "");
2327 return PyUnicode_FromString(buf
);
2331 Tktt_GetAttr(PyObject
*self
, char *name
)
2333 return Py_FindMethod(Tktt_methods
, self
, name
);
2336 static PyTypeObject Tktt_Type
=
2338 PyVarObject_HEAD_INIT(NULL
, 0)
2339 "tktimertoken", /*tp_name */
2340 sizeof(TkttObject
), /*tp_basicsize */
2342 Tktt_Dealloc
, /*tp_dealloc */
2344 Tktt_GetAttr
, /*tp_getattr */
2347 Tktt_Repr
, /*tp_repr */
2348 0, /*tp_as_number */
2349 0, /*tp_as_sequence */
2350 0, /*tp_as_mapping */
2356 /** Timer Handler **/
2359 TimerHandler(ClientData clientData
)
2361 TkttObject
*v
= (TkttObject
*)clientData
;
2362 PyObject
*func
= v
->func
;
2372 res
= PyEval_CallObject(func
, NULL
);
2374 Py_DECREF(v
); /* See Tktt_New() */
2378 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2387 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
2393 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler",
2394 &milliseconds
, &func
))
2396 if (!PyCallable_Check(func
)) {
2397 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2402 if (!self
&& !tcl_lock
) {
2403 /* We don't have the Tcl lock since Tcl is threaded. */
2404 PyErr_SetString(PyExc_RuntimeError
,
2405 "_tkinter.createtimerhandler not supported "
2406 "for threaded Tcl");
2412 CHECK_TCL_APPARTMENT
;
2417 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
2421 return (PyObject
*) v
;
2428 Tkapp_MainLoop(PyObject
*selfptr
, PyObject
*args
)
2431 TkappObject
*self
= (TkappObject
*)selfptr
;
2433 PyThreadState
*tstate
= PyThreadState_Get();
2436 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
2440 if (!self
&& !tcl_lock
) {
2441 /* We don't have the Tcl lock since Tcl is threaded. */
2442 PyErr_SetString(PyExc_RuntimeError
,
2443 "_tkinter.mainloop not supported "
2444 "for threaded Tcl");
2450 CHECK_TCL_APPARTMENT
;
2451 self
->dispatching
= 1;
2455 while (Tk_GetNumMainWindows() > threshold
&&
2462 if (self
&& self
->threaded
) {
2463 /* Allow other Python threads to run. */
2465 result
= Tcl_DoOneEvent(0);
2469 Py_BEGIN_ALLOW_THREADS
2470 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
2471 tcl_tstate
= tstate
;
2472 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
2474 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
2476 Sleep(Tkinter_busywaitinterval
);
2477 Py_END_ALLOW_THREADS
2480 result
= Tcl_DoOneEvent(0);
2483 if (PyErr_CheckSignals() != 0) {
2485 self
->dispatching
= 0;
2492 self
->dispatching
= 0;
2497 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2498 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2506 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
2511 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
2515 rv
= Tcl_DoOneEvent(flags
);
2517 return Py_BuildValue("i", rv
);
2521 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
2524 if (!PyArg_ParseTuple(args
, ":quit"))
2533 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
2536 if (!PyArg_ParseTuple(args
, ":interpaddr"))
2539 return PyLong_FromLong((long)Tkapp_Interp(self
));
2543 Tkapp_TkInit(PyObject
*self
, PyObject
*args
)
2545 static int has_failed
;
2546 Tcl_Interp
*interp
= Tkapp_Interp(self
);
2547 Tk_Window main_window
;
2548 const char * _tk_exists
= NULL
;
2550 main_window
= Tk_MainWindow(interp
);
2552 /* In all current versions of Tk (including 8.4.13), Tk_Init
2553 deadlocks on the second call when the first call failed.
2554 To avoid the deadlock, we just refuse the second call through
2555 a static variable. */
2557 PyErr_SetString(Tkinter_TclError
,
2558 "Calling Tk_Init again after a previous call failed might deadlock");
2562 /* We want to guard against calling Tk_Init() multiple times */
2563 CHECK_TCL_APPARTMENT
;
2565 err
= Tcl_Eval(Tkapp_Interp(self
), "info exists tk_version");
2567 if (err
== TCL_ERROR
) {
2568 /* This sets an exception, but we cannot return right
2569 away because we need to exit the overlap first. */
2570 Tkinter_Error(self
);
2572 _tk_exists
= Tkapp_Result(self
);
2575 if (err
== TCL_ERROR
) {
2578 if (_tk_exists
== NULL
|| strcmp(_tk_exists
, "1") != 0) {
2579 if (Tk_Init(interp
) == TCL_ERROR
) {
2580 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
2590 Tkapp_WantObjects(PyObject
*self
, PyObject
*args
)
2593 int wantobjects
= -1;
2594 if (!PyArg_ParseTuple(args
, "|i:wantobjects", &wantobjects
))
2596 if (wantobjects
== -1)
2597 return PyBool_FromLong(((TkappObject
*)self
)->wantobjects
);
2598 ((TkappObject
*)self
)->wantobjects
= wantobjects
;
2605 Tkapp_WillDispatch(PyObject
*self
, PyObject
*args
)
2608 ((TkappObject
*)self
)->dispatching
= 1;
2615 /**** Tkapp Method List ****/
2617 static PyMethodDef Tkapp_methods
[] =
2619 {"willdispatch", Tkapp_WillDispatch
, METH_NOARGS
},
2620 {"wantobjects", Tkapp_WantObjects
, METH_VARARGS
},
2621 {"call", Tkapp_Call
, METH_VARARGS
},
2622 {"globalcall", Tkapp_GlobalCall
, METH_VARARGS
},
2623 {"eval", Tkapp_Eval
, METH_VARARGS
},
2624 {"globaleval", Tkapp_GlobalEval
, METH_VARARGS
},
2625 {"evalfile", Tkapp_EvalFile
, METH_VARARGS
},
2626 {"record", Tkapp_Record
, METH_VARARGS
},
2627 {"adderrorinfo", Tkapp_AddErrorInfo
, METH_VARARGS
},
2628 {"setvar", Tkapp_SetVar
, METH_VARARGS
},
2629 {"globalsetvar", Tkapp_GlobalSetVar
, METH_VARARGS
},
2630 {"getvar", Tkapp_GetVar
, METH_VARARGS
},
2631 {"globalgetvar", Tkapp_GlobalGetVar
, METH_VARARGS
},
2632 {"unsetvar", Tkapp_UnsetVar
, METH_VARARGS
},
2633 {"globalunsetvar", Tkapp_GlobalUnsetVar
, METH_VARARGS
},
2634 {"getint", Tkapp_GetInt
, METH_VARARGS
},
2635 {"getdouble", Tkapp_GetDouble
, METH_VARARGS
},
2636 {"getboolean", Tkapp_GetBoolean
, METH_VARARGS
},
2637 {"exprstring", Tkapp_ExprString
, METH_VARARGS
},
2638 {"exprlong", Tkapp_ExprLong
, METH_VARARGS
},
2639 {"exprdouble", Tkapp_ExprDouble
, METH_VARARGS
},
2640 {"exprboolean", Tkapp_ExprBoolean
, METH_VARARGS
},
2641 {"splitlist", Tkapp_SplitList
, METH_VARARGS
},
2642 {"split", Tkapp_Split
, METH_VARARGS
},
2643 {"merge", Tkapp_Merge
, METH_VARARGS
},
2644 {"createcommand", Tkapp_CreateCommand
, METH_VARARGS
},
2645 {"deletecommand", Tkapp_DeleteCommand
, METH_VARARGS
},
2646 #ifdef HAVE_CREATEFILEHANDLER
2647 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
2648 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
2650 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
2651 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
2652 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
2653 {"quit", Tkapp_Quit
, METH_VARARGS
},
2654 {"interpaddr", Tkapp_InterpAddr
, METH_VARARGS
},
2655 {"loadtk", Tkapp_TkInit
, METH_NOARGS
},
2661 /**** Tkapp Type Methods ****/
2664 Tkapp_Dealloc(PyObject
*self
)
2666 /*CHECK_TCL_APPARTMENT;*/
2668 Tcl_DeleteInterp(Tkapp_Interp(self
));
2675 Tkapp_GetAttr(PyObject
*self
, char *name
)
2677 return Py_FindMethod(Tkapp_methods
, self
, name
);
2680 static PyTypeObject Tkapp_Type
=
2682 PyVarObject_HEAD_INIT(NULL
, 0)
2683 "tkapp", /*tp_name */
2684 sizeof(TkappObject
), /*tp_basicsize */
2686 Tkapp_Dealloc
, /*tp_dealloc */
2688 Tkapp_GetAttr
, /*tp_getattr */
2692 0, /*tp_as_number */
2693 0, /*tp_as_sequence */
2694 0, /*tp_as_mapping */
2700 /**** Tkinter Module ****/
2704 int size
; /* current size */
2705 int maxsize
; /* allocated size */
2709 _bump(FlattenContext
* context
, int size
)
2711 /* expand tuple to hold (at least) size new items.
2712 return true if successful, false if an exception was raised */
2714 int maxsize
= context
->maxsize
* 2;
2716 if (maxsize
< context
->size
+ size
)
2717 maxsize
= context
->size
+ size
;
2719 context
->maxsize
= maxsize
;
2721 return _PyTuple_Resize(&context
->tuple
, maxsize
) >= 0;
2725 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
2727 /* add tuple or list to argument tuple (recursively) */
2732 PyErr_SetString(PyExc_ValueError
,
2733 "nesting too deep in _flatten");
2735 } else if (PyList_Check(item
)) {
2736 size
= PyList_GET_SIZE(item
);
2737 /* preallocate (assume no nesting) */
2738 if (context
->size
+ size
> context
->maxsize
&&
2739 !_bump(context
, size
))
2741 /* copy items to output tuple */
2742 for (i
= 0; i
< size
; i
++) {
2743 PyObject
*o
= PyList_GET_ITEM(item
, i
);
2744 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2745 if (!_flatten1(context
, o
, depth
+ 1))
2747 } else if (o
!= Py_None
) {
2748 if (context
->size
+ 1 > context
->maxsize
&&
2752 PyTuple_SET_ITEM(context
->tuple
,
2753 context
->size
++, o
);
2756 } else if (PyTuple_Check(item
)) {
2757 /* same, for tuples */
2758 size
= PyTuple_GET_SIZE(item
);
2759 if (context
->size
+ size
> context
->maxsize
&&
2760 !_bump(context
, size
))
2762 for (i
= 0; i
< size
; i
++) {
2763 PyObject
*o
= PyTuple_GET_ITEM(item
, i
);
2764 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2765 if (!_flatten1(context
, o
, depth
+ 1))
2767 } else if (o
!= Py_None
) {
2768 if (context
->size
+ 1 > context
->maxsize
&&
2772 PyTuple_SET_ITEM(context
->tuple
,
2773 context
->size
++, o
);
2777 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
2784 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
2786 FlattenContext context
;
2789 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
2792 context
.maxsize
= PySequence_Size(item
);
2793 if (context
.maxsize
<= 0)
2794 return PyTuple_New(0);
2796 context
.tuple
= PyTuple_New(context
.maxsize
);
2802 if (!_flatten1(&context
, item
,0))
2805 if (_PyTuple_Resize(&context
.tuple
, context
.size
))
2808 return context
.tuple
;
2812 Tkinter_Create(PyObject
*self
, PyObject
*args
)
2814 char *screenName
= NULL
;
2815 char *baseName
= NULL
;
2816 char *className
= NULL
;
2817 int interactive
= 0;
2818 int wantobjects
= 0;
2819 int wantTk
= 1; /* If false, then Tk_Init() doesn't get called */
2820 int sync
= 0; /* pass -sync to wish */
2821 char *use
= NULL
; /* pass -use to wish */
2823 baseName
= strrchr(Py_GetProgramName(), '/');
2824 if (baseName
!= NULL
)
2827 baseName
= Py_GetProgramName();
2830 if (!PyArg_ParseTuple(args
, "|zssiiiiz:create",
2831 &screenName
, &baseName
, &className
,
2832 &interactive
, &wantobjects
, &wantTk
,
2836 return (PyObject
*) Tkapp_New(screenName
, baseName
, className
,
2837 interactive
, wantobjects
, wantTk
,
2842 Tkinter_setbusywaitinterval(PyObject
*self
, PyObject
*args
)
2845 if (!PyArg_ParseTuple(args
, "i:setbusywaitinterval", &new_val
))
2848 PyErr_SetString(PyExc_ValueError
,
2849 "busywaitinterval must be >= 0");
2852 Tkinter_busywaitinterval
= new_val
;
2857 static char setbusywaitinterval_doc
[] =
2858 "setbusywaitinterval(n) -> None\n\
2860 Set the busy-wait interval in milliseconds between successive\n\
2861 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2862 It should be set to a divisor of the maximum time between\n\
2863 frames in an animation.";
2866 Tkinter_getbusywaitinterval(PyObject
*self
, PyObject
*args
)
2868 return PyLong_FromLong(Tkinter_busywaitinterval
);
2871 static char getbusywaitinterval_doc
[] =
2872 "getbusywaitinterval() -> int\n\
2874 Return the current busy-wait interval between successive\n\
2875 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2877 static PyMethodDef moduleMethods
[] =
2879 {"_flatten", Tkinter_Flatten
, METH_VARARGS
},
2880 {"create", Tkinter_Create
, METH_VARARGS
},
2881 #ifdef HAVE_CREATEFILEHANDLER
2882 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
2883 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
2885 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
2886 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
2887 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
2888 {"quit", Tkapp_Quit
, METH_VARARGS
},
2889 {"setbusywaitinterval",Tkinter_setbusywaitinterval
, METH_VARARGS
,
2890 setbusywaitinterval_doc
},
2891 {"getbusywaitinterval",(PyCFunction
)Tkinter_getbusywaitinterval
,
2892 METH_NOARGS
, getbusywaitinterval_doc
},
2896 #ifdef WAIT_FOR_STDIN
2898 static int stdin_ready
= 0;
2902 MyFileProc(void *clientData
, int mask
)
2909 static PyThreadState
*event_tstate
= NULL
;
2919 PyEval_RestoreThread(event_tstate
);
2924 tfile
= fileno(stdin
);
2925 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
2927 while (!errorInCmd
&& !stdin_ready
) {
2935 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
2936 Py_BEGIN_ALLOW_THREADS
2937 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
2938 tcl_tstate
= event_tstate
;
2940 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
2943 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
2945 Sleep(Tkinter_busywaitinterval
);
2946 Py_END_ALLOW_THREADS
2948 result
= Tcl_DoOneEvent(0);
2955 Tcl_DeleteFileHandler(tfile
);
2959 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2960 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2964 PyEval_SaveThread();
2972 EnableEventHook(void)
2974 #ifdef WAIT_FOR_STDIN
2975 if (PyOS_InputHook
== NULL
) {
2977 event_tstate
= PyThreadState_Get();
2979 PyOS_InputHook
= EventHook
;
2985 DisableEventHook(void)
2987 #ifdef WAIT_FOR_STDIN
2988 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
2989 PyOS_InputHook
= NULL
;
2995 /* all errors will be checked in one fell swoop in init_tkinter() */
2997 ins_long(PyObject
*d
, char *name
, long val
)
2999 PyObject
*v
= PyLong_FromLong(val
);
3001 PyDict_SetItemString(d
, name
, v
);
3006 ins_string(PyObject
*d
, char *name
, char *val
)
3008 PyObject
*v
= PyUnicode_FromString(val
);
3010 PyDict_SetItemString(d
, name
, v
);
3021 Py_TYPE(&Tkapp_Type
) = &PyType_Type
;
3024 tcl_lock
= PyThread_allocate_lock();
3027 m
= Py_InitModule("_tkinter", moduleMethods
);
3031 d
= PyModule_GetDict(m
);
3032 Tkinter_TclError
= PyErr_NewException("_tkinter.TclError", NULL
, NULL
);
3033 PyDict_SetItemString(d
, "TclError", Tkinter_TclError
);
3035 ins_long(d
, "READABLE", TCL_READABLE
);
3036 ins_long(d
, "WRITABLE", TCL_WRITABLE
);
3037 ins_long(d
, "EXCEPTION", TCL_EXCEPTION
);
3038 ins_long(d
, "WINDOW_EVENTS", TCL_WINDOW_EVENTS
);
3039 ins_long(d
, "FILE_EVENTS", TCL_FILE_EVENTS
);
3040 ins_long(d
, "TIMER_EVENTS", TCL_TIMER_EVENTS
);
3041 ins_long(d
, "IDLE_EVENTS", TCL_IDLE_EVENTS
);
3042 ins_long(d
, "ALL_EVENTS", TCL_ALL_EVENTS
);
3043 ins_long(d
, "DONT_WAIT", TCL_DONT_WAIT
);
3044 ins_string(d
, "TK_VERSION", TK_VERSION
);
3045 ins_string(d
, "TCL_VERSION", TCL_VERSION
);
3047 PyDict_SetItemString(d
, "TkappType", (PyObject
*)&Tkapp_Type
);
3049 Py_TYPE(&Tktt_Type
) = &PyType_Type
;
3050 PyDict_SetItemString(d
, "TkttType", (PyObject
*)&Tktt_Type
);
3052 Py_TYPE(&PyTclObject_Type
) = &PyType_Type
;
3053 PyDict_SetItemString(d
, "Tcl_Obj", (PyObject
*)&PyTclObject_Type
);
3056 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3057 * start waking up. Note that Tcl_FindExecutable will do this, this
3058 * code must be above it! The original warning from
3059 * tkMacOSXAppInit.c is copied below.
3061 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3062 * Tcl interpreter for now. It probably should work to do this
3063 * in the other order, but for now it doesn't seem to.
3066 Tk_MacOSXSetupTkNotifier();
3070 /* This helps the dynamic loader; in Unicode aware Tcl versions
3071 it also helps Tcl find its encodings. */
3072 Tcl_FindExecutable(Py_GetProgramName());
3074 if (PyErr_Occurred())
3078 /* This was not a good idea; through <Destroy> bindings,
3079 Tcl_Finalize() may invoke Python code but at that point the
3080 interpreter and thread state have already been destroyed! */
3081 Py_AtExit(Tcl_Finalize
);