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.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
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
72 /* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
73 #ifndef CONST84_RETURN
74 #define CONST84_RETURN
79 #if TK_VERSION_HEX < 0x08030102
80 #error "Tk older than 8.3.1 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
;
283 #ifdef TKINTER_PROTECT_LOADTK
284 static int tk_load_failed
= 0;
289 Tkinter_Error(PyObject
*v
)
291 PyErr_SetString(Tkinter_TclError
, Tkapp_Result(v
));
299 static int Tkinter_busywaitinterval
= 20;
304 /* Millisecond sleep() for Unix platforms. */
309 /* XXX Too bad if you don't have select(). */
311 t
.tv_sec
= milli
/1000;
312 t
.tv_usec
= (milli
%1000) * 1000;
313 select(0, (fd_set
*)0, (fd_set
*)0, (fd_set
*)0, &t
);
315 #endif /* MS_WINDOWS */
317 /* Wait up to 1s for the mainloop to come up. */
320 WaitForMainloop(TkappObject
* self
)
323 for (i
= 0; i
< 10; i
++) {
324 if (self
->dispatching
)
326 Py_BEGIN_ALLOW_THREADS
330 if (self
->dispatching
)
332 PyErr_SetString(PyExc_RuntimeError
, "main thread is not in main loop");
335 #endif /* WITH_THREAD */
339 AsString(PyObject
*value
, PyObject
*tmp
)
341 if (PyBytes_Check(value
))
342 return PyBytes_AsString(value
);
343 else if (PyUnicode_Check(value
)) {
344 PyObject
*v
= PyUnicode_AsUTF8String(value
);
347 if (PyList_Append(tmp
, v
) != 0) {
352 return PyBytes_AsString(v
);
355 PyObject
*v
= PyObject_Str(value
);
358 if (PyList_Append(tmp
, v
) != 0) {
363 return PyBytes_AsString(v
);
372 Merge(PyObject
*args
)
374 PyObject
*tmp
= NULL
;
375 char *argvStore
[ARGSZ
];
379 int argc
= 0, fvc
= 0, i
;
382 if (!(tmp
= PyList_New(0)))
391 else if (!PyTuple_Check(args
)) {
394 if (!(argv
[0] = AsString(args
, tmp
)))
398 argc
= PyTuple_Size(args
);
401 argv
= (char **)ckalloc(argc
* sizeof(char *));
402 fv
= (int *)ckalloc(argc
* sizeof(int));
403 if (argv
== NULL
|| fv
== NULL
) {
409 for (i
= 0; i
< argc
; i
++) {
410 PyObject
*v
= PyTuple_GetItem(args
, i
);
411 if (PyTuple_Check(v
)) {
413 if (!(argv
[i
] = Merge(v
)))
417 else if (v
== Py_None
) {
423 if (!(argv
[i
] = AsString(v
, tmp
)))
429 res
= Tcl_Merge(argc
, argv
);
431 PyErr_SetString(Tkinter_TclError
, "merge failed");
434 for (i
= 0; i
< fvc
; i
++)
438 if (argv
!= argvStore
)
439 ckfree(FREECAST argv
);
461 if (Tcl_SplitList((Tcl_Interp
*)NULL
, list
, &argc
, &argv
) != TCL_OK
) {
463 * Could be a quoted string containing funnies, e.g. {"}.
464 * Return the string itself.
466 return PyUnicode_FromString(list
);
470 v
= PyUnicode_FromString("");
472 v
= PyUnicode_FromString(argv
[0]);
473 else if ((v
= PyTuple_New(argc
)) != NULL
) {
477 for (i
= 0; i
< argc
; i
++) {
478 if ((w
= Split(argv
[i
])) == NULL
) {
483 PyTuple_SetItem(v
, i
, w
);
486 Tcl_Free(FREECAST argv
);
490 /* In some cases, Tcl will still return strings that are supposed to be
491 lists. SplitObj walks through a nested tuple, finding string objects that
495 SplitObj(PyObject
*arg
)
497 if (PyTuple_Check(arg
)) {
499 PyObject
*elem
, *newelem
, *result
;
501 size
= PyTuple_Size(arg
);
503 /* Recursively invoke SplitObj for all tuple items.
504 If this does not return a new object, no action is
506 for(i
= 0; i
< size
; i
++) {
507 elem
= PyTuple_GetItem(arg
, i
);
508 newelem
= SplitObj(elem
);
515 if (newelem
== elem
) {
519 result
= PyTuple_New(size
);
522 for(k
= 0; k
< i
; k
++) {
523 elem
= PyTuple_GetItem(arg
, k
);
525 PyTuple_SetItem(result
, k
, elem
);
528 PyTuple_SetItem(result
, i
, newelem
);
532 /* Fall through, returning arg. */
534 else if (PyBytes_Check(arg
)) {
537 char *list
= PyBytes_AsString(arg
);
539 if (Tcl_SplitList((Tcl_Interp
*)NULL
, list
, &argc
, &argv
) != TCL_OK
) {
543 Tcl_Free(FREECAST argv
);
545 return Split(PyBytes_AsString(arg
));
546 /* Fall through, returning arg. */
553 /**** Tkapp Object ****/
557 Tcl_AppInit(Tcl_Interp
*interp
)
559 const char * _tkinter_skip_tk_init
;
561 if (Tcl_Init(interp
) == TCL_ERROR
) {
562 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp
));
566 _tkinter_skip_tk_init
= Tcl_GetVar(interp
,
567 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY
);
568 if (_tkinter_skip_tk_init
!= NULL
&&
569 strcmp(_tkinter_skip_tk_init
, "1") == 0) {
573 #ifdef TKINTER_PROTECT_LOADTK
574 if (tk_load_failed
) {
575 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG
);
580 if (Tk_Init(interp
) == TCL_ERROR
) {
581 #ifdef TKINTER_PROTECT_LOADTK
584 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp
));
590 #endif /* !WITH_APPINIT */
595 /* Initialize the Tk application; see the `main' function in
599 static void EnableEventHook(void); /* Forward */
600 static void DisableEventHook(void); /* Forward */
603 Tkapp_New(char *screenName
, char *className
,
604 int interactive
, int wantobjects
, int wantTk
, int sync
, char *use
)
609 v
= PyObject_New(TkappObject
, &Tkapp_Type
);
613 v
->interp
= Tcl_CreateInterp();
614 v
->wantobjects
= wantobjects
;
615 v
->threaded
= Tcl_GetVar2Ex(v
->interp
, "tcl_platform", "threaded",
616 TCL_GLOBAL_ONLY
) != NULL
;
617 v
->thread_id
= Tcl_GetCurrentThread();
622 PyErr_SetString(PyExc_RuntimeError
, "Tcl is threaded but _tkinter is not");
628 if (v
->threaded
&& tcl_lock
) {
629 /* If Tcl is threaded, we don't need the lock. */
630 PyThread_free_lock(tcl_lock
);
635 v
->BooleanType
= Tcl_GetObjType("boolean");
636 v
->ByteArrayType
= Tcl_GetObjType("bytearray");
637 v
->DoubleType
= Tcl_GetObjType("double");
638 v
->IntType
= Tcl_GetObjType("int");
639 v
->ListType
= Tcl_GetObjType("list");
640 v
->ProcBodyType
= Tcl_GetObjType("procbody");
641 v
->StringType
= Tcl_GetObjType("string");
643 /* Delete the 'exit' command, which can screw things up */
644 Tcl_DeleteCommand(v
->interp
, "exit");
646 if (screenName
!= NULL
)
647 Tcl_SetVar2(v
->interp
, "env", "DISPLAY",
648 screenName
, TCL_GLOBAL_ONLY
);
651 Tcl_SetVar(v
->interp
, "tcl_interactive", "1", TCL_GLOBAL_ONLY
);
653 Tcl_SetVar(v
->interp
, "tcl_interactive", "0", TCL_GLOBAL_ONLY
);
655 /* This is used to get the application class for Tk 4.1 and up */
656 argv0
= (char*)ckalloc(strlen(className
) + 1);
663 strcpy(argv0
, className
);
664 if (isupper(Py_CHARMASK(argv0
[0])))
665 argv0
[0] = tolower(Py_CHARMASK(argv0
[0]));
666 Tcl_SetVar(v
->interp
, "argv0", argv0
, TCL_GLOBAL_ONLY
);
670 Tcl_SetVar(v
->interp
,
671 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY
);
673 #ifdef TKINTER_PROTECT_LOADTK
674 else if (tk_load_failed
) {
675 Tcl_SetVar(v
->interp
,
676 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY
);
680 /* some initial arguments need to be in argv */
686 len
+= sizeof "-sync";
688 len
+= strlen(use
) + sizeof "-use ";
690 args
= (char*)ckalloc(len
);
699 strcat(args
, "-sync");
703 strcat(args
, "-use ");
707 Tcl_SetVar(v
->interp
, "argv", args
, TCL_GLOBAL_ONLY
);
711 if (Tcl_AppInit(v
->interp
) != TCL_OK
) {
712 PyObject
*result
= Tkinter_Error((PyObject
*)v
);
713 #ifdef TKINTER_PROTECT_LOADTK
715 const char *_tkinter_tk_failed
;
716 _tkinter_tk_failed
= Tcl_GetVar(v
->interp
,
717 "_tkinter_tk_failed", TCL_GLOBAL_ONLY
);
719 if ( _tkinter_tk_failed
!= NULL
&&
720 strcmp(_tkinter_tk_failed
, "1") == 0) {
725 Py_DECREF((PyObject
*)v
);
726 return (TkappObject
*)result
;
737 Tkapp_ThreadSend(TkappObject
*self
, Tcl_Event
*ev
,
738 Tcl_Condition
*cond
, Tcl_Mutex
*mutex
)
740 Py_BEGIN_ALLOW_THREADS
;
741 Tcl_MutexLock(mutex
);
742 Tcl_ThreadQueueEvent(self
->thread_id
, ev
, TCL_QUEUE_TAIL
);
743 Tcl_ThreadAlert(self
->thread_id
);
744 Tcl_ConditionWait(cond
, mutex
, NULL
);
745 Tcl_MutexUnlock(mutex
);
756 PyObject
*string
; /* This cannot cause cycles. */
759 static PyTypeObject PyTclObject_Type
;
760 #define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
763 newPyTclObject(Tcl_Obj
*arg
)
766 self
= PyObject_New(PyTclObject
, &PyTclObject_Type
);
769 Tcl_IncrRefCount(arg
);
772 return (PyObject
*)self
;
776 PyTclObject_dealloc(PyTclObject
*self
)
778 Tcl_DecrRefCount(self
->value
);
779 Py_XDECREF(self
->string
);
784 PyTclObject_TclString(PyObject
*self
)
786 return Tcl_GetString(((PyTclObject
*)self
)->value
);
789 /* Like _str, but create Unicode if necessary. */
790 PyDoc_STRVAR(PyTclObject_string__doc__
,
791 "the string representation of this object, either as str or bytes");
794 PyTclObject_string(PyTclObject
*self
, void *ignored
)
799 s
= Tcl_GetStringFromObj(self
->value
, &len
);
800 self
->string
= PyUnicode_FromStringAndSize(s
, len
);
804 Py_INCREF(self
->string
);
809 PyTclObject_str(PyTclObject
*self
, void *ignored
)
813 if (self
->string
&& PyUnicode_Check(self
->string
)) {
814 Py_INCREF(self
->string
);
817 /* XXX Could chache result if it is non-ASCII. */
818 s
= Tcl_GetStringFromObj(self
->value
, &len
);
819 return PyUnicode_DecodeUTF8(s
, len
, "strict");
823 PyTclObject_repr(PyTclObject
*self
)
825 return PyUnicode_FromFormat("<%s object at %p>",
826 self
->value
->typePtr
->name
, self
->value
);
829 #define TEST_COND(cond) ((cond) ? Py_True : Py_False)
832 PyTclObject_richcompare(PyObject
*self
, PyObject
*other
, int op
)
837 /* neither argument should be NULL, unless something's gone wrong */
838 if (self
== NULL
|| other
== NULL
) {
839 PyErr_BadInternalCall();
843 /* both arguments should be instances of PyTclObject */
844 if (!PyTclObject_Check(self
) || !PyTclObject_Check(other
)) {
845 v
= Py_NotImplemented
;
850 /* fast path when self and other are identical */
853 result
= strcmp(Tcl_GetString(((PyTclObject
*)self
)->value
),
854 Tcl_GetString(((PyTclObject
*)other
)->value
));
855 /* Convert return value to a Boolean */
858 v
= TEST_COND(result
== 0);
861 v
= TEST_COND(result
!= 0);
864 v
= TEST_COND(result
<= 0);
867 v
= TEST_COND(result
>= 0);
870 v
= TEST_COND(result
< 0);
873 v
= TEST_COND(result
> 0);
884 PyDoc_STRVAR(get_typename__doc__
, "name of the Tcl type");
887 get_typename(PyTclObject
* obj
, void* ignored
)
889 return PyUnicode_FromString(obj
->value
->typePtr
->name
);
893 static PyGetSetDef PyTclObject_getsetlist
[] = {
894 {"typename", (getter
)get_typename
, NULL
, get_typename__doc__
},
895 {"string", (getter
)PyTclObject_string
, NULL
,
896 PyTclObject_string__doc__
},
900 static PyTypeObject PyTclObject_Type
= {
901 PyVarObject_HEAD_INIT(NULL
, 0)
902 "_tkinter.Tcl_Obj", /*tp_name*/
903 sizeof(PyTclObject
), /*tp_basicsize*/
906 (destructor
)PyTclObject_dealloc
,/*tp_dealloc*/
911 (reprfunc
)PyTclObject_repr
, /*tp_repr*/
913 0, /*tp_as_sequence*/
917 (reprfunc
)PyTclObject_str
, /*tp_str*/
918 PyObject_GenericGetAttr
, /*tp_getattro*/
921 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
925 PyTclObject_richcompare
, /*tp_richcompare*/
926 0, /*tp_weaklistoffset*/
931 PyTclObject_getsetlist
, /*tp_getset*/
945 AsObj(PyObject
*value
)
951 if (PyBytes_Check(value
))
952 return Tcl_NewStringObj(PyBytes_AS_STRING(value
),
953 PyBytes_GET_SIZE(value
));
954 else if (PyBool_Check(value
))
955 return Tcl_NewBooleanObj(PyObject_IsTrue(value
));
956 else if (PyLong_CheckExact(value
) &&
957 ((longVal
= PyLong_AsLongAndOverflow(value
, &overflow
)),
959 /* If there is an overflow in the long conversion,
960 fall through to default object handling. */
961 return Tcl_NewLongObj(longVal
);
963 else if (PyFloat_Check(value
))
964 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value
));
965 else if (PyTuple_Check(value
)) {
966 Tcl_Obj
**argv
= (Tcl_Obj
**)
967 ckalloc(PyTuple_Size(value
)*sizeof(Tcl_Obj
*));
971 for(i
=0;i
<PyTuple_Size(value
);i
++)
972 argv
[i
] = AsObj(PyTuple_GetItem(value
,i
));
973 result
= Tcl_NewListObj(PyTuple_Size(value
), argv
);
974 ckfree(FREECAST argv
);
977 else if (PyUnicode_Check(value
)) {
978 Py_UNICODE
*inbuf
= PyUnicode_AS_UNICODE(value
);
979 Py_ssize_t size
= PyUnicode_GET_SIZE(value
);
980 /* This #ifdef assumes that Tcl uses UCS-2.
981 See TCL_UTF_MAX test above. */
982 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
983 Tcl_UniChar
*outbuf
= NULL
;
985 size_t allocsize
= ((size_t)size
) * sizeof(Tcl_UniChar
);
986 if (allocsize
>= size
)
987 outbuf
= (Tcl_UniChar
*)ckalloc(allocsize
);
988 /* Else overflow occurred, and we take the next exit */
993 for (i
= 0; i
< size
; i
++) {
994 if (inbuf
[i
] >= 0x10000) {
995 /* Tcl doesn't do UTF-16, yet. */
996 PyErr_SetString(PyExc_ValueError
,
997 "unsupported character");
998 ckfree(FREECAST outbuf
);
1001 outbuf
[i
] = inbuf
[i
];
1003 result
= Tcl_NewUnicodeObj(outbuf
, size
);
1004 ckfree(FREECAST outbuf
);
1007 return Tcl_NewUnicodeObj(inbuf
, size
);
1011 else if(PyTclObject_Check(value
)) {
1012 Tcl_Obj
*v
= ((PyTclObject
*)value
)->value
;
1013 Tcl_IncrRefCount(v
);
1017 PyObject
*v
= PyObject_Str(value
);
1027 FromObj(PyObject
* tkapp
, Tcl_Obj
*value
)
1029 PyObject
*result
= NULL
;
1030 TkappObject
*app
= (TkappObject
*)tkapp
;
1032 if (value
->typePtr
== NULL
) {
1033 return PyUnicode_FromStringAndSize(value
->bytes
,
1037 if (value
->typePtr
== app
->BooleanType
) {
1038 result
= value
->internalRep
.longValue
? Py_True
: Py_False
;
1043 if (value
->typePtr
== app
->ByteArrayType
) {
1045 char *data
= (char*)Tcl_GetByteArrayFromObj(value
, &size
);
1046 return PyBytes_FromStringAndSize(data
, size
);
1049 if (value
->typePtr
== app
->DoubleType
) {
1050 return PyFloat_FromDouble(value
->internalRep
.doubleValue
);
1053 if (value
->typePtr
== app
->IntType
) {
1054 return PyLong_FromLong(value
->internalRep
.longValue
);
1057 if (value
->typePtr
== app
->ListType
) {
1063 status
= Tcl_ListObjLength(Tkapp_Interp(tkapp
), value
, &size
);
1064 if (status
== TCL_ERROR
)
1065 return Tkinter_Error(tkapp
);
1066 result
= PyTuple_New(size
);
1069 for (i
= 0; i
< size
; i
++) {
1070 status
= Tcl_ListObjIndex(Tkapp_Interp(tkapp
),
1071 value
, i
, &tcl_elem
);
1072 if (status
== TCL_ERROR
) {
1074 return Tkinter_Error(tkapp
);
1076 elem
= FromObj(tkapp
, tcl_elem
);
1081 PyTuple_SetItem(result
, i
, elem
);
1086 if (value
->typePtr
== app
->ProcBodyType
) {
1087 /* fall through: return tcl object. */
1090 if (value
->typePtr
== app
->StringType
) {
1091 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1097 size
= Tcl_GetCharLength(value
);
1098 result
= PyUnicode_FromUnicode(NULL
, size
);
1101 input
= Tcl_GetUnicode(value
);
1102 output
= PyUnicode_AS_UNICODE(result
);
1104 *output
++ = *input
++;
1107 return PyUnicode_FromUnicode(Tcl_GetUnicode(value
),
1108 Tcl_GetCharLength(value
));
1112 return newPyTclObject(value
);
1116 /* This mutex synchronizes inter-thread command calls. */
1117 TCL_DECLARE_MUTEX(call_mutex
)
1119 typedef struct Tkapp_CallEvent
{
1120 Tcl_Event ev
; /* Must be first */
1125 PyObject
**exc_type
, **exc_value
, **exc_tb
;
1126 Tcl_Condition
*done
;
1131 Tkapp_CallDeallocArgs(Tcl_Obj
** objv
, Tcl_Obj
** objStore
, int objc
)
1134 for (i
= 0; i
< objc
; i
++)
1135 Tcl_DecrRefCount(objv
[i
]);
1136 if (objv
!= objStore
)
1137 ckfree(FREECAST objv
);
1140 /* Convert Python objects to Tcl objects. This must happen in the
1141 interpreter thread, which may or may not be the calling thread. */
1144 Tkapp_CallArgs(PyObject
*args
, Tcl_Obj
** objStore
, int *pobjc
)
1146 Tcl_Obj
**objv
= objStore
;
1151 else if (!PyTuple_Check(args
)) {
1152 objv
[0] = AsObj(args
);
1156 Tcl_IncrRefCount(objv
[0]);
1159 objc
= PyTuple_Size(args
);
1162 objv
= (Tcl_Obj
**)ckalloc(objc
* sizeof(char *));
1170 for (i
= 0; i
< objc
; i
++) {
1171 PyObject
*v
= PyTuple_GetItem(args
, i
);
1178 /* Reset objc, so it attempts to clear
1179 objects only up to i. */
1183 Tcl_IncrRefCount(objv
[i
]);
1189 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1193 /* Convert the results of a command call into a Python objects. */
1196 Tkapp_CallResult(TkappObject
*self
)
1198 PyObject
*res
= NULL
;
1199 if(self
->wantobjects
) {
1200 Tcl_Obj
*value
= Tcl_GetObjResult(self
->interp
);
1201 /* Not sure whether the IncrRef is necessary, but something
1202 may overwrite the interpreter result while we are
1204 Tcl_IncrRefCount(value
);
1205 res
= FromObj((PyObject
*)self
, value
);
1206 Tcl_DecrRefCount(value
);
1208 const char *s
= Tcl_GetStringResult(self
->interp
);
1211 res
= PyUnicode_FromStringAndSize(s
, (int)(p
-s
));
1218 /* Tkapp_CallProc is the event procedure that is executed in the context of
1219 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1220 hold the Python lock. */
1223 Tkapp_CallProc(Tkapp_CallEvent
*e
, int flags
)
1225 Tcl_Obj
*objStore
[ARGSZ
];
1230 objv
= Tkapp_CallArgs(e
->args
, objStore
, &objc
);
1232 PyErr_Fetch(e
->exc_type
, e
->exc_value
, e
->exc_tb
);
1238 i
= Tcl_EvalObjv(e
->self
->interp
, objc
, objv
, e
->flags
);
1240 if (i
== TCL_ERROR
) {
1242 *(e
->exc_type
) = NULL
;
1243 *(e
->exc_tb
) = NULL
;
1244 *(e
->exc_value
) = PyObject_CallFunction(
1245 Tkinter_TclError
, "s",
1246 Tcl_GetStringResult(e
->self
->interp
));
1249 *(e
->res
) = Tkapp_CallResult(e
->self
);
1253 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1255 /* Wake up calling thread. */
1256 Tcl_MutexLock(&call_mutex
);
1257 Tcl_ConditionNotify(e
->done
);
1258 Tcl_MutexUnlock(&call_mutex
);
1264 /* This is the main entry point for calling a Tcl command.
1265 It supports three cases, with regard to threading:
1266 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1267 the context of the calling thread.
1268 2. Tcl is threaded, caller of the command is in the interpreter thread:
1269 Execute the command in the calling thread. Since the Tcl lock will
1270 not be used, we can merge that with case 1.
1271 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1272 the interpreter thread. Allocation of Tcl objects needs to occur in the
1273 interpreter thread, so we ship the PyObject* args to the target thread,
1274 and perform processing there. */
1277 Tkapp_Call(PyObject
*selfptr
, PyObject
*args
)
1279 Tcl_Obj
*objStore
[ARGSZ
];
1280 Tcl_Obj
**objv
= NULL
;
1282 PyObject
*res
= NULL
;
1283 TkappObject
*self
= (TkappObject
*)selfptr
;
1284 int flags
= TCL_EVAL_DIRECT
| TCL_EVAL_GLOBAL
;
1286 /* If args is a single tuple, replace with contents of tuple */
1287 if (1 == PyTuple_Size(args
)){
1288 PyObject
* item
= PyTuple_GetItem(args
, 0);
1289 if (PyTuple_Check(item
))
1293 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1294 /* We cannot call the command directly. Instead, we must
1295 marshal the parameters to the interpreter thread. */
1296 Tkapp_CallEvent
*ev
;
1297 Tcl_Condition cond
= NULL
;
1298 PyObject
*exc_type
, *exc_value
, *exc_tb
;
1299 if (!WaitForMainloop(self
))
1301 ev
= (Tkapp_CallEvent
*)ckalloc(sizeof(Tkapp_CallEvent
));
1302 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CallProc
;
1306 ev
->exc_type
= &exc_type
;
1307 ev
->exc_value
= &exc_value
;
1308 ev
->exc_tb
= &exc_tb
;
1311 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &cond
, &call_mutex
);
1315 PyErr_Restore(exc_type
, exc_value
, exc_tb
);
1317 PyErr_SetObject(Tkinter_TclError
, exc_value
);
1319 Tcl_ConditionFinalize(&cond
);
1325 objv
= Tkapp_CallArgs(args
, objStore
, &objc
);
1331 i
= Tcl_EvalObjv(self
->interp
, objc
, objv
, flags
);
1336 Tkinter_Error(selfptr
);
1338 res
= Tkapp_CallResult(self
);
1342 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1349 Tkapp_GlobalCall(PyObject
*self
, PyObject
*args
)
1351 /* Could do the same here as for Tkapp_Call(), but this is not used
1352 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1353 way for the user to do what all its Global* variants do (save and
1354 reset the scope pointer, call the local version, restore the saved
1358 PyObject
*res
= NULL
;
1360 CHECK_TCL_APPARTMENT
;
1366 err
= Tcl_GlobalEval(Tkapp_Interp(self
), cmd
);
1368 if (err
== TCL_ERROR
)
1369 res
= Tkinter_Error(self
);
1371 res
= PyUnicode_FromString(Tkapp_Result(self
));
1380 Tkapp_Eval(PyObject
*self
, PyObject
*args
)
1383 PyObject
*res
= NULL
;
1386 if (!PyArg_ParseTuple(args
, "s:eval", &script
))
1389 CHECK_TCL_APPARTMENT
;
1392 err
= Tcl_Eval(Tkapp_Interp(self
), script
);
1394 if (err
== TCL_ERROR
)
1395 res
= Tkinter_Error(self
);
1397 res
= PyUnicode_FromString(Tkapp_Result(self
));
1403 Tkapp_GlobalEval(PyObject
*self
, PyObject
*args
)
1406 PyObject
*res
= NULL
;
1409 if (!PyArg_ParseTuple(args
, "s:globaleval", &script
))
1412 CHECK_TCL_APPARTMENT
;
1415 err
= Tcl_GlobalEval(Tkapp_Interp(self
), script
);
1417 if (err
== TCL_ERROR
)
1418 res
= Tkinter_Error(self
);
1420 res
= PyUnicode_FromString(Tkapp_Result(self
));
1426 Tkapp_EvalFile(PyObject
*self
, PyObject
*args
)
1429 PyObject
*res
= NULL
;
1432 if (!PyArg_ParseTuple(args
, "s:evalfile", &fileName
))
1435 CHECK_TCL_APPARTMENT
;
1438 err
= Tcl_EvalFile(Tkapp_Interp(self
), fileName
);
1440 if (err
== TCL_ERROR
)
1441 res
= Tkinter_Error(self
);
1444 res
= PyUnicode_FromString(Tkapp_Result(self
));
1450 Tkapp_Record(PyObject
*self
, PyObject
*args
)
1453 PyObject
*res
= NULL
;
1456 if (!PyArg_ParseTuple(args
, "s", &script
))
1459 CHECK_TCL_APPARTMENT
;
1462 err
= Tcl_RecordAndEval(Tkapp_Interp(self
), script
, TCL_NO_EVAL
);
1464 if (err
== TCL_ERROR
)
1465 res
= Tkinter_Error(self
);
1467 res
= PyUnicode_FromString(Tkapp_Result(self
));
1473 Tkapp_AddErrorInfo(PyObject
*self
, PyObject
*args
)
1477 if (!PyArg_ParseTuple(args
, "s:adderrorinfo", &msg
))
1479 CHECK_TCL_APPARTMENT
;
1482 Tcl_AddErrorInfo(Tkapp_Interp(self
), msg
);
1491 /** Tcl Variable **/
1493 typedef PyObject
* (*EventFunc
)(PyObject
*, PyObject
*args
, int flags
);
1496 TCL_DECLARE_MUTEX(var_mutex
)
1498 typedef struct VarEvent
{
1499 Tcl_Event ev
; /* must be first */
1505 PyObject
**exc_type
;
1507 Tcl_Condition
*cond
;
1512 varname_converter(PyObject
*in
, void *_out
)
1514 char **out
= (char**)_out
;
1515 if (PyBytes_Check(in
)) {
1516 *out
= PyBytes_AsString(in
);
1519 if (PyUnicode_Check(in
)) {
1520 *out
= _PyUnicode_AsString(in
);
1523 if (PyTclObject_Check(in
)) {
1524 *out
= PyTclObject_TclString(in
);
1527 /* XXX: Should give diagnostics. */
1534 var_perform(VarEvent
*ev
)
1536 *(ev
->res
) = ev
->func(ev
->self
, ev
->args
, ev
->flags
);
1538 PyObject
*exc
, *val
, *tb
;
1539 PyErr_Fetch(&exc
, &val
, &tb
);
1540 PyErr_NormalizeException(&exc
, &val
, &tb
);
1541 *(ev
->exc_type
) = exc
;
1542 *(ev
->exc_val
) = val
;
1549 var_proc(VarEvent
* ev
, int flags
)
1553 Tcl_MutexLock(&var_mutex
);
1554 Tcl_ConditionNotify(ev
->cond
);
1555 Tcl_MutexUnlock(&var_mutex
);
1563 var_invoke(EventFunc func
, PyObject
*selfptr
, PyObject
*args
, int flags
)
1566 TkappObject
*self
= (TkappObject
*)selfptr
;
1567 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1568 TkappObject
*self
= (TkappObject
*)selfptr
;
1570 PyObject
*res
, *exc_type
, *exc_val
;
1571 Tcl_Condition cond
= NULL
;
1573 /* The current thread is not the interpreter thread. Marshal
1574 the call to the interpreter thread, then wait for
1576 if (!WaitForMainloop(self
))
1579 ev
= (VarEvent
*)ckalloc(sizeof(VarEvent
));
1586 ev
->exc_type
= &exc_type
;
1587 ev
->exc_val
= &exc_val
;
1589 ev
->ev
.proc
= (Tcl_EventProc
*)var_proc
;
1590 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &cond
, &var_mutex
);
1591 Tcl_ConditionFinalize(&cond
);
1593 PyErr_SetObject(exc_type
, exc_val
);
1594 Py_DECREF(exc_type
);
1601 /* Tcl is not threaded, or this is the interpreter thread. */
1602 return func(selfptr
, args
, flags
);
1606 SetVar(PyObject
*self
, PyObject
*args
, int flags
)
1608 char *name1
, *name2
;
1610 PyObject
*res
= NULL
;
1611 Tcl_Obj
*newval
, *ok
;
1613 if (PyArg_ParseTuple(args
, "O&O:setvar",
1614 varname_converter
, &name1
, &newValue
)) {
1615 /* XXX Acquire tcl lock??? */
1616 newval
= AsObj(newValue
);
1620 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, NULL
,
1624 Tkinter_Error(self
);
1633 if (PyArg_ParseTuple(args
, "ssO:setvar",
1634 &name1
, &name2
, &newValue
)) {
1635 /* XXX must hold tcl lock already??? */
1636 newval
= AsObj(newValue
);
1638 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, name2
, newval
, flags
);
1641 Tkinter_Error(self
);
1656 Tkapp_SetVar(PyObject
*self
, PyObject
*args
)
1658 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1662 Tkapp_GlobalSetVar(PyObject
*self
, PyObject
*args
)
1664 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1670 GetVar(PyObject
*self
, PyObject
*args
, int flags
)
1672 char *name1
, *name2
=NULL
;
1673 PyObject
*res
= NULL
;
1676 if (!PyArg_ParseTuple(args
, "O&|s:getvar",
1677 varname_converter
, &name1
, &name2
))
1681 tres
= Tcl_GetVar2Ex(Tkapp_Interp(self
), name1
, name2
, flags
);
1684 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
1686 if (((TkappObject
*)self
)->wantobjects
) {
1687 res
= FromObj(self
, tres
);
1690 res
= PyUnicode_FromString(Tcl_GetString(tres
));
1698 Tkapp_GetVar(PyObject
*self
, PyObject
*args
)
1700 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1704 Tkapp_GlobalGetVar(PyObject
*self
, PyObject
*args
)
1706 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1712 UnsetVar(PyObject
*self
, PyObject
*args
, int flags
)
1714 char *name1
, *name2
=NULL
;
1716 PyObject
*res
= NULL
;
1718 if (!PyArg_ParseTuple(args
, "s|s:unsetvar", &name1
, &name2
))
1722 code
= Tcl_UnsetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
1724 if (code
== TCL_ERROR
)
1725 res
= Tkinter_Error(self
);
1735 Tkapp_UnsetVar(PyObject
*self
, PyObject
*args
)
1737 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1741 Tkapp_GlobalUnsetVar(PyObject
*self
, PyObject
*args
)
1743 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1748 /** Tcl to Python **/
1751 Tkapp_GetInt(PyObject
*self
, PyObject
*args
)
1756 if (PyTuple_Size(args
) == 1) {
1757 PyObject
* o
= PyTuple_GetItem(args
, 0);
1758 if (PyLong_Check(o
)) {
1763 if (!PyArg_ParseTuple(args
, "s:getint", &s
))
1765 if (Tcl_GetInt(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1766 return Tkinter_Error(self
);
1767 return Py_BuildValue("i", v
);
1771 Tkapp_GetDouble(PyObject
*self
, PyObject
*args
)
1776 if (PyTuple_Size(args
) == 1) {
1777 PyObject
*o
= PyTuple_GetItem(args
, 0);
1778 if (PyFloat_Check(o
)) {
1783 if (!PyArg_ParseTuple(args
, "s:getdouble", &s
))
1785 if (Tcl_GetDouble(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1786 return Tkinter_Error(self
);
1787 return Py_BuildValue("d", v
);
1791 Tkapp_GetBoolean(PyObject
*self
, PyObject
*args
)
1796 if (PyTuple_Size(args
) == 1) {
1797 PyObject
*o
= PyTuple_GetItem(args
, 0);
1798 if (PyLong_Check(o
)) {
1803 if (!PyArg_ParseTuple(args
, "s:getboolean", &s
))
1805 if (Tcl_GetBoolean(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1806 return Tkinter_Error(self
);
1807 return PyBool_FromLong(v
);
1811 Tkapp_ExprString(PyObject
*self
, PyObject
*args
)
1814 PyObject
*res
= NULL
;
1817 if (!PyArg_ParseTuple(args
, "s:exprstring", &s
))
1820 CHECK_TCL_APPARTMENT
;
1823 retval
= Tcl_ExprString(Tkapp_Interp(self
), s
);
1825 if (retval
== TCL_ERROR
)
1826 res
= Tkinter_Error(self
);
1828 res
= Py_BuildValue("s", Tkapp_Result(self
));
1834 Tkapp_ExprLong(PyObject
*self
, PyObject
*args
)
1837 PyObject
*res
= NULL
;
1841 if (!PyArg_ParseTuple(args
, "s:exprlong", &s
))
1844 CHECK_TCL_APPARTMENT
;
1847 retval
= Tcl_ExprLong(Tkapp_Interp(self
), s
, &v
);
1849 if (retval
== TCL_ERROR
)
1850 res
= Tkinter_Error(self
);
1852 res
= Py_BuildValue("l", v
);
1858 Tkapp_ExprDouble(PyObject
*self
, PyObject
*args
)
1861 PyObject
*res
= NULL
;
1865 if (!PyArg_ParseTuple(args
, "s:exprdouble", &s
))
1867 CHECK_TCL_APPARTMENT
;
1868 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1870 retval
= Tcl_ExprDouble(Tkapp_Interp(self
), s
, &v
);
1872 PyFPE_END_PROTECT(retval
)
1873 if (retval
== TCL_ERROR
)
1874 res
= Tkinter_Error(self
);
1876 res
= Py_BuildValue("d", v
);
1882 Tkapp_ExprBoolean(PyObject
*self
, PyObject
*args
)
1885 PyObject
*res
= NULL
;
1889 if (!PyArg_ParseTuple(args
, "s:exprboolean", &s
))
1891 CHECK_TCL_APPARTMENT
;
1893 retval
= Tcl_ExprBoolean(Tkapp_Interp(self
), s
, &v
);
1895 if (retval
== TCL_ERROR
)
1896 res
= Tkinter_Error(self
);
1898 res
= Py_BuildValue("i", v
);
1906 Tkapp_SplitList(PyObject
*self
, PyObject
*args
)
1914 if (PyTuple_Size(args
) == 1) {
1915 v
= PyTuple_GetItem(args
, 0);
1916 if (PyTuple_Check(v
)) {
1921 if (!PyArg_ParseTuple(args
, "et:splitlist", "utf-8", &list
))
1924 if (Tcl_SplitList(Tkapp_Interp(self
), list
,
1925 &argc
, &argv
) == TCL_ERROR
) {
1927 return Tkinter_Error(self
);
1930 if (!(v
= PyTuple_New(argc
)))
1933 for (i
= 0; i
< argc
; i
++) {
1934 PyObject
*s
= PyUnicode_FromString(argv
[i
]);
1935 if (!s
|| PyTuple_SetItem(v
, i
, s
)) {
1943 ckfree(FREECAST argv
);
1949 Tkapp_Split(PyObject
*self
, PyObject
*args
)
1954 if (PyTuple_Size(args
) == 1) {
1955 PyObject
* o
= PyTuple_GetItem(args
, 0);
1956 if (PyTuple_Check(o
)) {
1961 if (!PyArg_ParseTuple(args
, "et:split", "utf-8", &list
))
1969 Tkapp_Merge(PyObject
*self
, PyObject
*args
)
1971 char *s
= Merge(args
);
1972 PyObject
*res
= NULL
;
1975 res
= PyUnicode_FromString(s
);
1986 /* Client data struct */
1990 } PythonCmd_ClientData
;
1993 PythonCmd_Error(Tcl_Interp
*interp
)
1996 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2001 /* This is the Tcl command that acts as a wrapper for Python
2002 * function or method.
2005 PythonCmd(ClientData clientData
, Tcl_Interp
*interp
, int argc
, char *argv
[])
2007 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
2008 PyObject
*self
, *func
, *arg
, *res
;
2014 /* TBD: no error checking here since we know, via the
2015 * Tkapp_CreateCommand() that the client data is a two-tuple
2020 /* Create argument list (argv1, ..., argvN) */
2021 if (!(arg
= PyTuple_New(argc
- 1)))
2022 return PythonCmd_Error(interp
);
2024 for (i
= 0; i
< (argc
- 1); i
++) {
2025 PyObject
*s
= PyUnicode_FromString(argv
[i
+ 1]);
2026 if (!s
|| PyTuple_SetItem(arg
, i
, s
)) {
2028 return PythonCmd_Error(interp
);
2031 res
= PyEval_CallObject(func
, arg
);
2035 return PythonCmd_Error(interp
);
2037 obj_res
= AsObj(res
);
2038 if (obj_res
== NULL
) {
2040 return PythonCmd_Error(interp
);
2043 Tcl_SetObjResult(interp
, obj_res
);
2055 PythonCmdDelete(ClientData clientData
)
2057 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
2060 Py_XDECREF(data
->self
);
2061 Py_XDECREF(data
->func
);
2070 TCL_DECLARE_MUTEX(command_mutex
)
2072 typedef struct CommandEvent
{
2079 Tcl_Condition
*done
;
2083 Tkapp_CommandProc(CommandEvent
*ev
, int flags
)
2086 *ev
->status
= Tcl_CreateCommand(
2087 ev
->interp
, ev
->name
, PythonCmd
,
2088 ev
->data
, PythonCmdDelete
) == NULL
;
2090 *ev
->status
= Tcl_DeleteCommand(ev
->interp
, ev
->name
);
2091 Tcl_MutexLock(&command_mutex
);
2092 Tcl_ConditionNotify(ev
->done
);
2093 Tcl_MutexUnlock(&command_mutex
);
2099 Tkapp_CreateCommand(PyObject
*selfptr
, PyObject
*args
)
2101 TkappObject
*self
= (TkappObject
*)selfptr
;
2102 PythonCmd_ClientData
*data
;
2107 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
2109 if (!PyCallable_Check(func
)) {
2110 PyErr_SetString(PyExc_TypeError
, "command not callable");
2115 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread() &&
2116 !WaitForMainloop(self
))
2120 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
2122 return PyErr_NoMemory();
2125 data
->self
= selfptr
;
2128 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2129 Tcl_Condition cond
= NULL
;
2130 CommandEvent
*ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2131 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2132 ev
->interp
= self
->interp
;
2135 ev
->data
= (ClientData
)data
;
2138 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &cond
, &command_mutex
);
2139 Tcl_ConditionFinalize(&cond
);
2145 err
= Tcl_CreateCommand(
2146 Tkapp_Interp(self
), cmdName
, PythonCmd
,
2147 (ClientData
)data
, PythonCmdDelete
) == NULL
;
2151 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
2163 Tkapp_DeleteCommand(PyObject
*selfptr
, PyObject
*args
)
2165 TkappObject
*self
= (TkappObject
*)selfptr
;
2169 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
2173 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2174 Tcl_Condition cond
= NULL
;
2176 ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2177 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2178 ev
->interp
= self
->interp
;
2183 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &cond
,
2185 Tcl_ConditionFinalize(&cond
);
2191 err
= Tcl_DeleteCommand(self
->interp
, cmdName
);
2195 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
2204 #ifdef HAVE_CREATEFILEHANDLER
2205 /** File Handler **/
2207 typedef struct _fhcdata
{
2211 struct _fhcdata
*next
;
2212 } FileHandler_ClientData
;
2214 static FileHandler_ClientData
*HeadFHCD
;
2216 static FileHandler_ClientData
*
2217 NewFHCD(PyObject
*func
, PyObject
*file
, int id
)
2219 FileHandler_ClientData
*p
;
2220 p
= PyMem_NEW(FileHandler_ClientData
, 1);
2236 FileHandler_ClientData
*p
, **pp
;
2239 while ((p
= *pp
) != NULL
) {
2242 Py_XDECREF(p
->func
);
2243 Py_XDECREF(p
->file
);
2252 FileHandler(ClientData clientData
, int mask
)
2254 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
2255 PyObject
*func
, *file
, *arg
, *res
;
2261 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
2262 res
= PyEval_CallObject(func
, arg
);
2267 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2274 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
2275 /* args is (file, mask, func) */
2277 FileHandler_ClientData
*data
;
2278 PyObject
*file
, *func
;
2281 if (!PyArg_ParseTuple(args
, "OiO:createfilehandler",
2282 &file
, &mask
, &func
))
2285 CHECK_TCL_APPARTMENT
;
2287 tfile
= PyObject_AsFileDescriptor(file
);
2290 if (!PyCallable_Check(func
)) {
2291 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2295 data
= NewFHCD(func
, file
, tfile
);
2299 /* Ought to check for null Tcl_File object... */
2301 Tcl_CreateFileHandler(tfile
, mask
, FileHandler
, (ClientData
) data
);
2308 Tkapp_DeleteFileHandler(PyObject
*self
, PyObject
*args
)
2313 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
2316 CHECK_TCL_APPARTMENT
;
2318 tfile
= PyObject_AsFileDescriptor(file
);
2324 /* Ought to check for null Tcl_File object... */
2326 Tcl_DeleteFileHandler(tfile
);
2331 #endif /* HAVE_CREATEFILEHANDLER */
2334 /**** Tktt Object (timer token) ****/
2336 static PyTypeObject Tktt_Type
;
2340 Tcl_TimerToken token
;
2345 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
2347 TkttObject
*v
= (TkttObject
*)self
;
2348 PyObject
*func
= v
->func
;
2350 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
2352 if (v
->token
!= NULL
) {
2353 Tcl_DeleteTimerHandler(v
->token
);
2359 Py_DECREF(v
); /* See Tktt_New() */
2365 static PyMethodDef Tktt_methods
[] =
2367 {"deletetimerhandler", Tktt_DeleteTimerHandler
, METH_VARARGS
},
2372 Tktt_New(PyObject
*func
)
2376 v
= PyObject_New(TkttObject
, &Tktt_Type
);
2384 /* Extra reference, deleted when called or when handler is deleted */
2390 Tktt_Dealloc(PyObject
*self
)
2392 TkttObject
*v
= (TkttObject
*)self
;
2393 PyObject
*func
= v
->func
;
2401 Tktt_Repr(PyObject
*self
)
2403 TkttObject
*v
= (TkttObject
*)self
;
2406 PyOS_snprintf(buf
, sizeof(buf
), "<tktimertoken at %p%s>", v
,
2407 v
->func
== NULL
? ", handler deleted" : "");
2408 return PyUnicode_FromString(buf
);
2411 static PyTypeObject Tktt_Type
=
2413 PyVarObject_HEAD_INIT(NULL
, 0)
2414 "tktimertoken", /*tp_name */
2415 sizeof(TkttObject
), /*tp_basicsize */
2417 Tktt_Dealloc
, /*tp_dealloc */
2422 Tktt_Repr
, /*tp_repr */
2423 0, /*tp_as_number */
2424 0, /*tp_as_sequence */
2425 0, /*tp_as_mapping */
2432 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
2436 0, /*tp_richcompare*/
2437 0, /*tp_weaklistoffset*/
2440 Tktt_methods
, /*tp_methods*/
2445 /** Timer Handler **/
2448 TimerHandler(ClientData clientData
)
2450 TkttObject
*v
= (TkttObject
*)clientData
;
2451 PyObject
*func
= v
->func
;
2461 res
= PyEval_CallObject(func
, NULL
);
2463 Py_DECREF(v
); /* See Tktt_New() */
2467 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2476 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
2482 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler",
2483 &milliseconds
, &func
))
2485 if (!PyCallable_Check(func
)) {
2486 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2490 CHECK_TCL_APPARTMENT
;
2494 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
2498 return (PyObject
*) v
;
2505 Tkapp_MainLoop(PyObject
*selfptr
, PyObject
*args
)
2508 TkappObject
*self
= (TkappObject
*)selfptr
;
2510 PyThreadState
*tstate
= PyThreadState_Get();
2513 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
2516 CHECK_TCL_APPARTMENT
;
2517 self
->dispatching
= 1;
2520 while (Tk_GetNumMainWindows() > threshold
&&
2527 if (self
->threaded
) {
2528 /* Allow other Python threads to run. */
2530 result
= Tcl_DoOneEvent(0);
2534 Py_BEGIN_ALLOW_THREADS
2535 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
2536 tcl_tstate
= tstate
;
2537 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
2539 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
2541 Sleep(Tkinter_busywaitinterval
);
2542 Py_END_ALLOW_THREADS
2545 result
= Tcl_DoOneEvent(0);
2548 if (PyErr_CheckSignals() != 0) {
2549 self
->dispatching
= 0;
2555 self
->dispatching
= 0;
2560 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2561 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2569 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
2574 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
2578 rv
= Tcl_DoOneEvent(flags
);
2580 return Py_BuildValue("i", rv
);
2584 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
2587 if (!PyArg_ParseTuple(args
, ":quit"))
2596 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
2599 if (!PyArg_ParseTuple(args
, ":interpaddr"))
2602 return PyLong_FromLong((long)Tkapp_Interp(self
));
2606 Tkapp_TkInit(PyObject
*self
, PyObject
*args
)
2608 Tcl_Interp
*interp
= Tkapp_Interp(self
);
2609 const char * _tk_exists
= NULL
;
2612 #ifdef TKINTER_PROTECT_LOADTK
2613 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2614 * first call failed.
2615 * To avoid the deadlock, we just refuse the second call through
2616 * a static variable.
2618 if (tk_load_failed
) {
2619 PyErr_SetString(Tkinter_TclError
, TKINTER_LOADTK_ERRMSG
);
2624 /* We want to guard against calling Tk_Init() multiple times */
2625 CHECK_TCL_APPARTMENT
;
2627 err
= Tcl_Eval(Tkapp_Interp(self
), "info exists tk_version");
2629 if (err
== TCL_ERROR
) {
2630 /* This sets an exception, but we cannot return right
2631 away because we need to exit the overlap first. */
2632 Tkinter_Error(self
);
2634 _tk_exists
= Tkapp_Result(self
);
2637 if (err
== TCL_ERROR
) {
2640 if (_tk_exists
== NULL
|| strcmp(_tk_exists
, "1") != 0) {
2641 if (Tk_Init(interp
) == TCL_ERROR
) {
2642 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
2643 #ifdef TKINTER_PROTECT_LOADTK
2654 Tkapp_WantObjects(PyObject
*self
, PyObject
*args
)
2657 int wantobjects
= -1;
2658 if (!PyArg_ParseTuple(args
, "|i:wantobjects", &wantobjects
))
2660 if (wantobjects
== -1)
2661 return PyBool_FromLong(((TkappObject
*)self
)->wantobjects
);
2662 ((TkappObject
*)self
)->wantobjects
= wantobjects
;
2669 Tkapp_WillDispatch(PyObject
*self
, PyObject
*args
)
2672 ((TkappObject
*)self
)->dispatching
= 1;
2679 /**** Tkapp Method List ****/
2681 static PyMethodDef Tkapp_methods
[] =
2683 {"willdispatch", Tkapp_WillDispatch
, METH_NOARGS
},
2684 {"wantobjects", Tkapp_WantObjects
, METH_VARARGS
},
2685 {"call", Tkapp_Call
, METH_VARARGS
},
2686 {"globalcall", Tkapp_GlobalCall
, METH_VARARGS
},
2687 {"eval", Tkapp_Eval
, METH_VARARGS
},
2688 {"globaleval", Tkapp_GlobalEval
, METH_VARARGS
},
2689 {"evalfile", Tkapp_EvalFile
, METH_VARARGS
},
2690 {"record", Tkapp_Record
, METH_VARARGS
},
2691 {"adderrorinfo", Tkapp_AddErrorInfo
, METH_VARARGS
},
2692 {"setvar", Tkapp_SetVar
, METH_VARARGS
},
2693 {"globalsetvar", Tkapp_GlobalSetVar
, METH_VARARGS
},
2694 {"getvar", Tkapp_GetVar
, METH_VARARGS
},
2695 {"globalgetvar", Tkapp_GlobalGetVar
, METH_VARARGS
},
2696 {"unsetvar", Tkapp_UnsetVar
, METH_VARARGS
},
2697 {"globalunsetvar", Tkapp_GlobalUnsetVar
, METH_VARARGS
},
2698 {"getint", Tkapp_GetInt
, METH_VARARGS
},
2699 {"getdouble", Tkapp_GetDouble
, METH_VARARGS
},
2700 {"getboolean", Tkapp_GetBoolean
, METH_VARARGS
},
2701 {"exprstring", Tkapp_ExprString
, METH_VARARGS
},
2702 {"exprlong", Tkapp_ExprLong
, METH_VARARGS
},
2703 {"exprdouble", Tkapp_ExprDouble
, METH_VARARGS
},
2704 {"exprboolean", Tkapp_ExprBoolean
, METH_VARARGS
},
2705 {"splitlist", Tkapp_SplitList
, METH_VARARGS
},
2706 {"split", Tkapp_Split
, METH_VARARGS
},
2707 {"merge", Tkapp_Merge
, METH_VARARGS
},
2708 {"createcommand", Tkapp_CreateCommand
, METH_VARARGS
},
2709 {"deletecommand", Tkapp_DeleteCommand
, METH_VARARGS
},
2710 #ifdef HAVE_CREATEFILEHANDLER
2711 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
2712 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
2714 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
2715 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
2716 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
2717 {"quit", Tkapp_Quit
, METH_VARARGS
},
2718 {"interpaddr", Tkapp_InterpAddr
, METH_VARARGS
},
2719 {"loadtk", Tkapp_TkInit
, METH_NOARGS
},
2725 /**** Tkapp Type Methods ****/
2728 Tkapp_Dealloc(PyObject
*self
)
2730 /*CHECK_TCL_APPARTMENT;*/
2732 Tcl_DeleteInterp(Tkapp_Interp(self
));
2738 static PyTypeObject Tkapp_Type
=
2740 PyVarObject_HEAD_INIT(NULL
, 0)
2741 "tkapp", /*tp_name */
2742 sizeof(TkappObject
), /*tp_basicsize */
2744 Tkapp_Dealloc
, /*tp_dealloc */
2750 0, /*tp_as_number */
2751 0, /*tp_as_sequence */
2752 0, /*tp_as_mapping */
2759 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
2763 0, /*tp_richcompare*/
2764 0, /*tp_weaklistoffset*/
2767 Tkapp_methods
, /*tp_methods*/
2772 /**** Tkinter Module ****/
2776 int size
; /* current size */
2777 int maxsize
; /* allocated size */
2781 _bump(FlattenContext
* context
, int size
)
2783 /* expand tuple to hold (at least) size new items.
2784 return true if successful, false if an exception was raised */
2786 int maxsize
= context
->maxsize
* 2;
2788 if (maxsize
< context
->size
+ size
)
2789 maxsize
= context
->size
+ size
;
2791 context
->maxsize
= maxsize
;
2793 return _PyTuple_Resize(&context
->tuple
, maxsize
) >= 0;
2797 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
2799 /* add tuple or list to argument tuple (recursively) */
2804 PyErr_SetString(PyExc_ValueError
,
2805 "nesting too deep in _flatten");
2807 } else if (PyList_Check(item
)) {
2808 size
= PyList_GET_SIZE(item
);
2809 /* preallocate (assume no nesting) */
2810 if (context
->size
+ size
> context
->maxsize
&&
2811 !_bump(context
, size
))
2813 /* copy items to output tuple */
2814 for (i
= 0; i
< size
; i
++) {
2815 PyObject
*o
= PyList_GET_ITEM(item
, i
);
2816 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2817 if (!_flatten1(context
, o
, depth
+ 1))
2819 } else if (o
!= Py_None
) {
2820 if (context
->size
+ 1 > context
->maxsize
&&
2824 PyTuple_SET_ITEM(context
->tuple
,
2825 context
->size
++, o
);
2828 } else if (PyTuple_Check(item
)) {
2829 /* same, for tuples */
2830 size
= PyTuple_GET_SIZE(item
);
2831 if (context
->size
+ size
> context
->maxsize
&&
2832 !_bump(context
, size
))
2834 for (i
= 0; i
< size
; i
++) {
2835 PyObject
*o
= PyTuple_GET_ITEM(item
, i
);
2836 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2837 if (!_flatten1(context
, o
, depth
+ 1))
2839 } else if (o
!= Py_None
) {
2840 if (context
->size
+ 1 > context
->maxsize
&&
2844 PyTuple_SET_ITEM(context
->tuple
,
2845 context
->size
++, o
);
2849 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
2856 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
2858 FlattenContext context
;
2861 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
2864 context
.maxsize
= PySequence_Size(item
);
2865 if (context
.maxsize
< 0)
2867 if (context
.maxsize
== 0)
2868 return PyTuple_New(0);
2870 context
.tuple
= PyTuple_New(context
.maxsize
);
2876 if (!_flatten1(&context
, item
,0))
2879 if (_PyTuple_Resize(&context
.tuple
, context
.size
))
2882 return context
.tuple
;
2886 Tkinter_Create(PyObject
*self
, PyObject
*args
)
2888 char *screenName
= NULL
;
2889 char *baseName
= NULL
; /* XXX this is not used anymore;
2890 try getting rid of it. */
2891 char *className
= NULL
;
2892 int interactive
= 0;
2893 int wantobjects
= 0;
2894 int wantTk
= 1; /* If false, then Tk_Init() doesn't get called */
2895 int sync
= 0; /* pass -sync to wish */
2896 char *use
= NULL
; /* pass -use to wish */
2900 if (!PyArg_ParseTuple(args
, "|zssiiiiz:create",
2901 &screenName
, &baseName
, &className
,
2902 &interactive
, &wantobjects
, &wantTk
,
2906 return (PyObject
*) Tkapp_New(screenName
, className
,
2907 interactive
, wantobjects
, wantTk
,
2912 Tkinter_setbusywaitinterval(PyObject
*self
, PyObject
*args
)
2915 if (!PyArg_ParseTuple(args
, "i:setbusywaitinterval", &new_val
))
2918 PyErr_SetString(PyExc_ValueError
,
2919 "busywaitinterval must be >= 0");
2922 Tkinter_busywaitinterval
= new_val
;
2927 static char setbusywaitinterval_doc
[] =
2928 "setbusywaitinterval(n) -> None\n\
2930 Set the busy-wait interval in milliseconds between successive\n\
2931 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2932 It should be set to a divisor of the maximum time between\n\
2933 frames in an animation.";
2936 Tkinter_getbusywaitinterval(PyObject
*self
, PyObject
*args
)
2938 return PyLong_FromLong(Tkinter_busywaitinterval
);
2941 static char getbusywaitinterval_doc
[] =
2942 "getbusywaitinterval() -> int\n\
2944 Return the current busy-wait interval between successive\n\
2945 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2947 static PyMethodDef moduleMethods
[] =
2949 {"_flatten", Tkinter_Flatten
, METH_VARARGS
},
2950 {"create", Tkinter_Create
, METH_VARARGS
},
2951 {"setbusywaitinterval",Tkinter_setbusywaitinterval
, METH_VARARGS
,
2952 setbusywaitinterval_doc
},
2953 {"getbusywaitinterval",(PyCFunction
)Tkinter_getbusywaitinterval
,
2954 METH_NOARGS
, getbusywaitinterval_doc
},
2958 #ifdef WAIT_FOR_STDIN
2960 static int stdin_ready
= 0;
2964 MyFileProc(void *clientData
, int mask
)
2971 static PyThreadState
*event_tstate
= NULL
;
2981 PyEval_RestoreThread(event_tstate
);
2986 tfile
= fileno(stdin
);
2987 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
2989 while (!errorInCmd
&& !stdin_ready
) {
2997 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
2998 Py_BEGIN_ALLOW_THREADS
2999 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
3000 tcl_tstate
= event_tstate
;
3002 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
3005 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
3007 Sleep(Tkinter_busywaitinterval
);
3008 Py_END_ALLOW_THREADS
3010 result
= Tcl_DoOneEvent(0);
3017 Tcl_DeleteFileHandler(tfile
);
3021 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
3022 excInCmd
= valInCmd
= trbInCmd
= NULL
;
3026 PyEval_SaveThread();
3034 EnableEventHook(void)
3036 #ifdef WAIT_FOR_STDIN
3037 if (PyOS_InputHook
== NULL
) {
3039 event_tstate
= PyThreadState_Get();
3041 PyOS_InputHook
= EventHook
;
3047 DisableEventHook(void)
3049 #ifdef WAIT_FOR_STDIN
3050 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
3051 PyOS_InputHook
= NULL
;
3057 /* all errors will be checked in one fell swoop in init_tkinter() */
3059 ins_long(PyObject
*d
, char *name
, long val
)
3061 PyObject
*v
= PyLong_FromLong(val
);
3063 PyDict_SetItemString(d
, name
, v
);
3068 ins_string(PyObject
*d
, char *name
, char *val
)
3070 PyObject
*v
= PyUnicode_FromString(val
);
3072 PyDict_SetItemString(d
, name
, v
);
3078 static struct PyModuleDef _tkintermodule
= {
3079 PyModuleDef_HEAD_INIT
,
3091 PyInit__tkinter(void)
3093 PyObject
*m
, *d
, *uexe
, *cexe
;
3095 if (PyType_Ready(&Tkapp_Type
) < 0)
3099 tcl_lock
= PyThread_allocate_lock();
3102 m
= PyModule_Create(&_tkintermodule
);
3106 d
= PyModule_GetDict(m
);
3107 Tkinter_TclError
= PyErr_NewException("_tkinter.TclError", NULL
, NULL
);
3108 PyDict_SetItemString(d
, "TclError", Tkinter_TclError
);
3110 ins_long(d
, "READABLE", TCL_READABLE
);
3111 ins_long(d
, "WRITABLE", TCL_WRITABLE
);
3112 ins_long(d
, "EXCEPTION", TCL_EXCEPTION
);
3113 ins_long(d
, "WINDOW_EVENTS", TCL_WINDOW_EVENTS
);
3114 ins_long(d
, "FILE_EVENTS", TCL_FILE_EVENTS
);
3115 ins_long(d
, "TIMER_EVENTS", TCL_TIMER_EVENTS
);
3116 ins_long(d
, "IDLE_EVENTS", TCL_IDLE_EVENTS
);
3117 ins_long(d
, "ALL_EVENTS", TCL_ALL_EVENTS
);
3118 ins_long(d
, "DONT_WAIT", TCL_DONT_WAIT
);
3119 ins_string(d
, "TK_VERSION", TK_VERSION
);
3120 ins_string(d
, "TCL_VERSION", TCL_VERSION
);
3122 PyDict_SetItemString(d
, "TkappType", (PyObject
*)&Tkapp_Type
);
3124 if (PyType_Ready(&Tktt_Type
) < 0)
3126 PyDict_SetItemString(d
, "TkttType", (PyObject
*)&Tktt_Type
);
3128 Py_TYPE(&PyTclObject_Type
) = &PyType_Type
;
3129 PyDict_SetItemString(d
, "Tcl_Obj", (PyObject
*)&PyTclObject_Type
);
3132 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3133 * start waking up. Note that Tcl_FindExecutable will do this, this
3134 * code must be above it! The original warning from
3135 * tkMacOSXAppInit.c is copied below.
3137 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3138 * Tcl interpreter for now. It probably should work to do this
3139 * in the other order, but for now it doesn't seem to.
3142 Tk_MacOSXSetupTkNotifier();
3146 /* This helps the dynamic loader; in Unicode aware Tcl versions
3147 it also helps Tcl find its encodings. */
3148 uexe
= PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3150 cexe
= PyUnicode_AsEncodedString(uexe
,
3151 Py_FileSystemDefaultEncoding
,
3154 Tcl_FindExecutable(PyBytes_AsString(cexe
));
3159 if (PyErr_Occurred()) {
3165 /* This was not a good idea; through <Destroy> bindings,
3166 Tcl_Finalize() may invoke Python code but at that point the
3167 interpreter and thread state have already been destroyed! */
3168 Py_AtExit(Tcl_Finalize
);