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 PyInt_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) ((v)->ob_type == &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, ((PyObject *) v)->ob_refcnt))
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 #ifdef Py_USING_UNICODE
341 else if (PyUnicode_Check(value
)) {
342 PyObject
*v
= PyUnicode_AsUTF8String(value
);
345 if (PyList_Append(tmp
, v
) != 0) {
350 return PyString_AsString(v
);
354 PyObject
*v
= PyObject_Str(value
);
357 if (PyList_Append(tmp
, v
) != 0) {
362 return PyString_AsString(v
);
371 Merge(PyObject
*args
)
373 PyObject
*tmp
= NULL
;
374 char *argvStore
[ARGSZ
];
378 int argc
= 0, fvc
= 0, i
;
381 if (!(tmp
= PyList_New(0)))
390 else if (!PyTuple_Check(args
)) {
393 if (!(argv
[0] = AsString(args
, tmp
)))
397 argc
= PyTuple_Size(args
);
400 argv
= (char **)ckalloc(argc
* sizeof(char *));
401 fv
= (int *)ckalloc(argc
* sizeof(int));
402 if (argv
== NULL
|| fv
== NULL
) {
408 for (i
= 0; i
< argc
; i
++) {
409 PyObject
*v
= PyTuple_GetItem(args
, i
);
410 if (PyTuple_Check(v
)) {
412 if (!(argv
[i
] = Merge(v
)))
416 else if (v
== Py_None
) {
422 if (!(argv
[i
] = AsString(v
, tmp
)))
428 res
= Tcl_Merge(argc
, argv
);
430 PyErr_SetString(Tkinter_TclError
, "merge failed");
433 for (i
= 0; i
< fvc
; i
++)
437 if (argv
!= argvStore
)
438 ckfree(FREECAST argv
);
460 if (Tcl_SplitList((Tcl_Interp
*)NULL
, list
, &argc
, &argv
) != TCL_OK
) {
462 * Could be a quoted string containing funnies, e.g. {"}.
463 * Return the string itself.
465 return PyString_FromString(list
);
469 v
= PyString_FromString("");
471 v
= PyString_FromString(argv
[0]);
472 else if ((v
= PyTuple_New(argc
)) != NULL
) {
476 for (i
= 0; i
< argc
; i
++) {
477 if ((w
= Split(argv
[i
])) == NULL
) {
482 PyTuple_SetItem(v
, i
, w
);
485 Tcl_Free(FREECAST argv
);
489 /* In some cases, Tcl will still return strings that are supposed to be
490 lists. SplitObj walks through a nested tuple, finding string objects that
494 SplitObj(PyObject
*arg
)
496 if (PyTuple_Check(arg
)) {
498 PyObject
*elem
, *newelem
, *result
;
500 size
= PyTuple_Size(arg
);
502 /* Recursively invoke SplitObj for all tuple items.
503 If this does not return a new object, no action is
505 for(i
= 0; i
< size
; i
++) {
506 elem
= PyTuple_GetItem(arg
, i
);
507 newelem
= SplitObj(elem
);
514 if (newelem
== elem
) {
518 result
= PyTuple_New(size
);
521 for(k
= 0; k
< i
; k
++) {
522 elem
= PyTuple_GetItem(arg
, k
);
524 PyTuple_SetItem(result
, k
, elem
);
527 PyTuple_SetItem(result
, i
, newelem
);
531 /* Fall through, returning arg. */
533 else if (PyString_Check(arg
)) {
536 char *list
= PyString_AsString(arg
);
538 if (Tcl_SplitList((Tcl_Interp
*)NULL
, list
, &argc
, &argv
) != TCL_OK
) {
542 Tcl_Free(FREECAST argv
);
544 return Split(PyString_AsString(arg
));
545 /* Fall through, returning arg. */
552 /**** Tkapp Object ****/
556 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
));
565 _tkinter_skip_tk_init
= Tcl_GetVar(interp
, "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY
);
566 if (_tkinter_skip_tk_init
== NULL
|| strcmp(_tkinter_skip_tk_init
, "1") != 0) {
567 main
= Tk_MainWindow(interp
);
568 if (Tk_Init(interp
) == TCL_ERROR
) {
569 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp
));
575 #endif /* !WITH_APPINIT */
580 /* Initialize the Tk application; see the `main' function in
584 static void EnableEventHook(void); /* Forward */
585 static void DisableEventHook(void); /* Forward */
588 Tkapp_New(char *screenName
, char *baseName
, char *className
,
589 int interactive
, int wantobjects
, int wantTk
, int sync
, char *use
)
594 v
= PyObject_New(TkappObject
, &Tkapp_Type
);
598 v
->interp
= Tcl_CreateInterp();
599 v
->wantobjects
= wantobjects
;
600 v
->threaded
= Tcl_GetVar2Ex(v
->interp
, "tcl_platform", "threaded",
601 TCL_GLOBAL_ONLY
) != NULL
;
602 v
->thread_id
= Tcl_GetCurrentThread();
607 PyErr_SetString(PyExc_RuntimeError
, "Tcl is threaded but _tkinter is not");
613 if (v
->threaded
&& tcl_lock
) {
614 /* If Tcl is threaded, we don't need the lock. */
615 PyThread_free_lock(tcl_lock
);
620 v
->BooleanType
= Tcl_GetObjType("boolean");
621 v
->ByteArrayType
= Tcl_GetObjType("bytearray");
622 v
->DoubleType
= Tcl_GetObjType("double");
623 v
->IntType
= Tcl_GetObjType("int");
624 v
->ListType
= Tcl_GetObjType("list");
625 v
->ProcBodyType
= Tcl_GetObjType("procbody");
626 v
->StringType
= Tcl_GetObjType("string");
628 /* Delete the 'exit' command, which can screw things up */
629 Tcl_DeleteCommand(v
->interp
, "exit");
631 if (screenName
!= NULL
)
632 Tcl_SetVar2(v
->interp
, "env", "DISPLAY",
633 screenName
, TCL_GLOBAL_ONLY
);
636 Tcl_SetVar(v
->interp
, "tcl_interactive", "1", TCL_GLOBAL_ONLY
);
638 Tcl_SetVar(v
->interp
, "tcl_interactive", "0", TCL_GLOBAL_ONLY
);
640 /* This is used to get the application class for Tk 4.1 and up */
641 argv0
= (char*)ckalloc(strlen(className
) + 1);
648 strcpy(argv0
, className
);
649 if (isupper(Py_CHARMASK(argv0
[0])))
650 argv0
[0] = tolower(argv0
[0]);
651 Tcl_SetVar(v
->interp
, "argv0", argv0
, TCL_GLOBAL_ONLY
);
655 Tcl_SetVar(v
->interp
, "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY
);
658 /* some initial arguments need to be in argv */
664 len
+= sizeof "-sync";
666 len
+= strlen(use
) + sizeof "-use ";
668 args
= (char*)ckalloc(len
);
677 strcat(args
, "-sync");
681 strcat(args
, "-use ");
685 Tcl_SetVar(v
->interp
, "argv", args
, TCL_GLOBAL_ONLY
);
689 if (Tcl_AppInit(v
->interp
) != TCL_OK
)
690 return (TkappObject
*)Tkinter_Error((PyObject
*)v
);
699 Tkapp_ThreadSend(TkappObject
*self
, Tcl_Event
*ev
,
700 Tcl_Condition
*cond
, Tcl_Mutex
*mutex
)
702 Py_BEGIN_ALLOW_THREADS
;
703 Tcl_MutexLock(mutex
);
704 Tcl_ThreadQueueEvent(self
->thread_id
, ev
, TCL_QUEUE_TAIL
);
705 Tcl_ThreadAlert(self
->thread_id
);
706 Tcl_ConditionWait(cond
, mutex
, NULL
);
707 Tcl_MutexUnlock(mutex
);
717 PyObject
*string
; /* This cannot cause cycles. */
720 staticforward PyTypeObject PyTclObject_Type
;
721 #define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
724 newPyTclObject(Tcl_Obj
*arg
)
727 self
= PyObject_New(PyTclObject
, &PyTclObject_Type
);
730 Tcl_IncrRefCount(arg
);
733 return (PyObject
*)self
;
737 PyTclObject_dealloc(PyTclObject
*self
)
739 Tcl_DecrRefCount(self
->value
);
740 Py_XDECREF(self
->string
);
745 PyTclObject_str(PyTclObject
*self
)
747 if (self
->string
&& PyString_Check(self
->string
)) {
748 Py_INCREF(self
->string
);
751 /* XXX Could cache value if it is an ASCII string. */
752 return PyString_FromString(Tcl_GetString(self
->value
));
756 PyTclObject_TclString(PyObject
*self
)
758 return Tcl_GetString(((PyTclObject
*)self
)->value
);
761 /* Like _str, but create Unicode if necessary. */
762 PyDoc_STRVAR(PyTclObject_string__doc__
,
763 "the string representation of this object, either as string or Unicode");
766 PyTclObject_string(PyTclObject
*self
, void *ignored
)
771 s
= Tcl_GetStringFromObj(self
->value
, &len
);
772 for (i
= 0; i
< len
; i
++)
775 #ifdef Py_USING_UNICODE
777 /* It is an ASCII string. */
778 self
->string
= PyString_FromStringAndSize(s
, len
);
780 self
->string
= PyUnicode_DecodeUTF8(s
, len
, "strict");
783 self
->string
= PyString_FromStringAndSize(s
, len
);
787 self
->string
= PyString_FromStringAndSize(s
, len
);
792 Py_INCREF(self
->string
);
796 #ifdef Py_USING_UNICODE
797 PyDoc_STRVAR(PyTclObject_unicode__doc__
, "convert argument to unicode");
800 PyTclObject_unicode(PyTclObject
*self
, void *ignored
)
804 if (self
->string
&& PyUnicode_Check(self
->string
)) {
805 Py_INCREF(self
->string
);
808 /* XXX Could chache result if it is non-ASCII. */
809 s
= Tcl_GetStringFromObj(self
->value
, &len
);
810 return PyUnicode_DecodeUTF8(s
, len
, "strict");
815 PyTclObject_repr(PyTclObject
*self
)
818 PyOS_snprintf(buf
, 50, "<%s object at %p>",
819 self
->value
->typePtr
->name
, self
->value
);
820 return PyString_FromString(buf
);
824 PyTclObject_cmp(PyTclObject
*self
, PyTclObject
*other
)
827 res
= strcmp(Tcl_GetString(self
->value
),
828 Tcl_GetString(other
->value
));
829 if (res
< 0) return -1;
830 if (res
> 0) return 1;
834 PyDoc_STRVAR(get_typename__doc__
, "name of the Tcl type");
837 get_typename(PyTclObject
* obj
, void* ignored
)
839 return PyString_FromString(obj
->value
->typePtr
->name
);
843 static PyGetSetDef PyTclObject_getsetlist
[] = {
844 {"typename", (getter
)get_typename
, NULL
, get_typename__doc__
},
845 {"string", (getter
)PyTclObject_string
, NULL
,
846 PyTclObject_string__doc__
},
850 static PyMethodDef PyTclObject_methods
[] = {
851 #ifdef Py_USING_UNICODE
852 {"__unicode__", (PyCFunction
)PyTclObject_unicode
, METH_NOARGS
,
853 PyTclObject_unicode__doc__
},
858 statichere PyTypeObject PyTclObject_Type
= {
859 PyObject_HEAD_INIT(NULL
)
861 "_tkinter.Tcl_Obj", /*tp_name*/
862 sizeof(PyTclObject
), /*tp_basicsize*/
865 (destructor
)PyTclObject_dealloc
, /*tp_dealloc*/
869 (cmpfunc
)PyTclObject_cmp
, /*tp_compare*/
870 (reprfunc
)PyTclObject_repr
, /*tp_repr*/
872 0, /*tp_as_sequence*/
876 (reprfunc
)PyTclObject_str
, /*tp_str*/
877 PyObject_GenericGetAttr
,/*tp_getattro*/
880 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
884 0, /*tp_richcompare*/
885 0, /*tp_weaklistoffset*/
888 PyTclObject_methods
, /*tp_methods*/
890 PyTclObject_getsetlist
, /*tp_getset*/
904 AsObj(PyObject
*value
)
908 if (PyString_Check(value
))
909 return Tcl_NewStringObj(PyString_AS_STRING(value
),
910 PyString_GET_SIZE(value
));
911 else if (PyBool_Check(value
))
912 return Tcl_NewBooleanObj(PyObject_IsTrue(value
));
913 else if (PyInt_Check(value
))
914 return Tcl_NewLongObj(PyInt_AS_LONG(value
));
915 else if (PyFloat_Check(value
))
916 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value
));
917 else if (PyTuple_Check(value
)) {
918 Tcl_Obj
**argv
= (Tcl_Obj
**)
919 ckalloc(PyTuple_Size(value
)*sizeof(Tcl_Obj
*));
923 for(i
=0;i
<PyTuple_Size(value
);i
++)
924 argv
[i
] = AsObj(PyTuple_GetItem(value
,i
));
925 result
= Tcl_NewListObj(PyTuple_Size(value
), argv
);
926 ckfree(FREECAST argv
);
929 #ifdef Py_USING_UNICODE
930 else if (PyUnicode_Check(value
)) {
931 Py_UNICODE
*inbuf
= PyUnicode_AS_UNICODE(value
);
932 int size
= PyUnicode_GET_SIZE(value
);
933 /* This #ifdef assumes that Tcl uses UCS-2.
934 See TCL_UTF_MAX test above. */
935 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
938 outbuf
= (Tcl_UniChar
*)ckalloc(size
* sizeof(Tcl_UniChar
));
943 for (i
= 0; i
< size
; i
++) {
944 if (inbuf
[i
] >= 0x10000) {
945 /* Tcl doesn't do UTF-16, yet. */
946 PyErr_SetString(PyExc_ValueError
,
947 "unsupported character");
948 ckfree(FREECAST outbuf
);
951 outbuf
[i
] = inbuf
[i
];
953 result
= Tcl_NewUnicodeObj(outbuf
, size
);
954 ckfree(FREECAST outbuf
);
957 return Tcl_NewUnicodeObj(inbuf
, size
);
962 else if(PyTclObject_Check(value
)) {
963 Tcl_Obj
*v
= ((PyTclObject
*)value
)->value
;
968 PyObject
*v
= PyObject_Str(value
);
978 FromObj(PyObject
* tkapp
, Tcl_Obj
*value
)
980 PyObject
*result
= NULL
;
981 TkappObject
*app
= (TkappObject
*)tkapp
;
983 if (value
->typePtr
== NULL
) {
984 /* If the result contains any bytes with the top bit set,
985 it's UTF-8 and we should decode it to Unicode */
986 #ifdef Py_USING_UNICODE
988 char *s
= value
->bytes
;
989 int len
= value
->length
;
990 for (i
= 0; i
< len
; i
++) {
991 if (value
->bytes
[i
] & 0x80)
995 if (i
== value
->length
)
996 result
= PyString_FromStringAndSize(s
, len
);
998 /* Convert UTF-8 to Unicode string */
999 result
= PyUnicode_DecodeUTF8(s
, len
, "strict");
1000 if (result
== NULL
) {
1002 result
= PyString_FromStringAndSize(s
, len
);
1006 result
= PyString_FromStringAndSize(value
->bytes
, value
->length
);
1011 if (value
->typePtr
== app
->BooleanType
) {
1012 result
= value
->internalRep
.longValue
? Py_True
: Py_False
;
1017 if (value
->typePtr
== app
->ByteArrayType
) {
1019 char *data
= (char*)Tcl_GetByteArrayFromObj(value
, &size
);
1020 return PyString_FromStringAndSize(data
, size
);
1023 if (value
->typePtr
== app
->DoubleType
) {
1024 return PyFloat_FromDouble(value
->internalRep
.doubleValue
);
1027 if (value
->typePtr
== app
->IntType
) {
1028 return PyInt_FromLong(value
->internalRep
.longValue
);
1031 if (value
->typePtr
== app
->ListType
) {
1037 status
= Tcl_ListObjLength(Tkapp_Interp(tkapp
), value
, &size
);
1038 if (status
== TCL_ERROR
)
1039 return Tkinter_Error(tkapp
);
1040 result
= PyTuple_New(size
);
1043 for (i
= 0; i
< size
; i
++) {
1044 status
= Tcl_ListObjIndex(Tkapp_Interp(tkapp
),
1045 value
, i
, &tcl_elem
);
1046 if (status
== TCL_ERROR
) {
1048 return Tkinter_Error(tkapp
);
1050 elem
= FromObj(tkapp
, tcl_elem
);
1055 PyTuple_SetItem(result
, i
, elem
);
1060 if (value
->typePtr
== app
->ProcBodyType
) {
1061 /* fall through: return tcl object. */
1064 if (value
->typePtr
== app
->StringType
) {
1065 #ifdef Py_USING_UNICODE
1066 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1072 size
= Tcl_GetCharLength(value
);
1073 result
= PyUnicode_FromUnicode(NULL
, size
);
1076 input
= Tcl_GetUnicode(value
);
1077 output
= PyUnicode_AS_UNICODE(result
);
1079 *output
++ = *input
++;
1082 return PyUnicode_FromUnicode(Tcl_GetUnicode(value
),
1083 Tcl_GetCharLength(value
));
1088 c
= Tcl_GetStringFromObj(value
, &size
);
1089 return PyString_FromStringAndSize(c
, size
);
1093 return newPyTclObject(value
);
1096 /* This mutex synchronizes inter-thread command calls. */
1098 TCL_DECLARE_MUTEX(call_mutex
)
1100 typedef struct Tkapp_CallEvent
{
1101 Tcl_Event ev
; /* Must be first */
1106 PyObject
**exc_type
, **exc_value
, **exc_tb
;
1111 Tkapp_CallDeallocArgs(Tcl_Obj
** objv
, Tcl_Obj
** objStore
, int objc
)
1114 for (i
= 0; i
< objc
; i
++)
1115 Tcl_DecrRefCount(objv
[i
]);
1116 if (objv
!= objStore
)
1117 ckfree(FREECAST objv
);
1120 /* Convert Python objects to Tcl objects. This must happen in the
1121 interpreter thread, which may or may not be the calling thread. */
1124 Tkapp_CallArgs(PyObject
*args
, Tcl_Obj
** objStore
, int *pobjc
)
1126 Tcl_Obj
**objv
= objStore
;
1131 else if (!PyTuple_Check(args
)) {
1132 objv
[0] = AsObj(args
);
1136 Tcl_IncrRefCount(objv
[0]);
1139 objc
= PyTuple_Size(args
);
1142 objv
= (Tcl_Obj
**)ckalloc(objc
* sizeof(char *));
1150 for (i
= 0; i
< objc
; i
++) {
1151 PyObject
*v
= PyTuple_GetItem(args
, i
);
1158 /* Reset objc, so it attempts to clear
1159 objects only up to i. */
1163 Tcl_IncrRefCount(objv
[i
]);
1169 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1173 /* Convert the results of a command call into a Python objects. */
1176 Tkapp_CallResult(TkappObject
*self
)
1178 PyObject
*res
= NULL
;
1179 if(self
->wantobjects
) {
1180 Tcl_Obj
*value
= Tcl_GetObjResult(self
->interp
);
1181 /* Not sure whether the IncrRef is necessary, but something
1182 may overwrite the interpreter result while we are
1184 Tcl_IncrRefCount(value
);
1185 res
= FromObj((PyObject
*)self
, value
);
1186 Tcl_DecrRefCount(value
);
1188 const char *s
= Tcl_GetStringResult(self
->interp
);
1191 /* If the result contains any bytes with the top bit set,
1192 it's UTF-8 and we should decode it to Unicode */
1193 #ifdef Py_USING_UNICODE
1194 while (*p
!= '\0') {
1201 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
1203 /* Convert UTF-8 to Unicode string */
1204 p
= strchr(p
, '\0');
1205 res
= PyUnicode_DecodeUTF8(s
, (int)(p
-s
), "strict");
1208 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
1212 p
= strchr(p
, '\0');
1213 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
1219 /* Tkapp_CallProc is the event procedure that is executed in the context of
1220 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1221 hold the Python lock. */
1224 Tkapp_CallProc(Tkapp_CallEvent
*e
, int flags
)
1226 Tcl_Obj
*objStore
[ARGSZ
];
1231 objv
= Tkapp_CallArgs(e
->args
, objStore
, &objc
);
1233 PyErr_Fetch(e
->exc_type
, e
->exc_value
, e
->exc_tb
);
1239 i
= Tcl_EvalObjv(e
->self
->interp
, objc
, objv
, e
->flags
);
1241 if (i
== TCL_ERROR
) {
1243 *(e
->exc_type
) = NULL
;
1244 *(e
->exc_tb
) = NULL
;
1245 *(e
->exc_value
) = PyObject_CallFunction(
1246 Tkinter_TclError
, "s",
1247 Tcl_GetStringResult(e
->self
->interp
));
1250 *(e
->res
) = Tkapp_CallResult(e
->self
);
1254 /* Wake up calling thread. */
1255 Tcl_MutexLock(&call_mutex
);
1256 Tcl_ConditionNotify(&e
->done
);
1257 Tcl_MutexUnlock(&call_mutex
);
1261 /* This is the main entry point for calling a Tcl command.
1262 It supports three cases, with regard to threading:
1263 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1264 the context of the calling thread.
1265 2. Tcl is threaded, caller of the command is in the interpreter thread:
1266 Execute the command in the calling thread. Since the Tcl lock will
1267 not be used, we can merge that with case 1.
1268 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1269 the interpreter thread. Allocation of Tcl objects needs to occur in the
1270 interpreter thread, so we ship the PyObject* args to the target thread,
1271 and perform processing there. */
1274 Tkapp_Call(PyObject
*_self
, PyObject
*args
)
1276 Tcl_Obj
*objStore
[ARGSZ
];
1277 Tcl_Obj
**objv
= NULL
;
1279 PyObject
*res
= NULL
;
1280 TkappObject
*self
= (TkappObject
*)_self
;
1281 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1282 int flags
= TCL_EVAL_DIRECT
;
1285 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1286 /* We cannot call the command directly. Instead, we must
1287 marshal the parameters to the interpreter thread. */
1288 Tkapp_CallEvent
*ev
;
1289 PyObject
*exc_type
, *exc_value
, *exc_tb
;
1290 if (!WaitForMainloop(self
))
1292 ev
= (Tkapp_CallEvent
*)ckalloc(sizeof(Tkapp_CallEvent
));
1293 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CallProc
;
1297 ev
->exc_type
= &exc_type
;
1298 ev
->exc_value
= &exc_value
;
1299 ev
->exc_tb
= &exc_tb
;
1300 ev
->done
= (Tcl_Condition
)0;
1302 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
, &call_mutex
);
1306 PyErr_Restore(exc_type
, exc_value
, exc_tb
);
1308 PyErr_SetObject(Tkinter_TclError
, exc_value
);
1315 objv
= Tkapp_CallArgs(args
, objStore
, &objc
);
1321 i
= Tcl_EvalObjv(self
->interp
, objc
, objv
, flags
);
1326 Tkinter_Error(_self
);
1328 res
= Tkapp_CallResult(self
);
1332 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1339 Tkapp_GlobalCall(PyObject
*self
, PyObject
*args
)
1341 /* Could do the same here as for Tkapp_Call(), but this is not used
1342 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1343 way for the user to do what all its Global* variants do (save and
1344 reset the scope pointer, call the local version, restore the saved
1348 PyObject
*res
= NULL
;
1350 CHECK_TCL_APPARTMENT
;
1356 err
= Tcl_GlobalEval(Tkapp_Interp(self
), cmd
);
1358 if (err
== TCL_ERROR
)
1359 res
= Tkinter_Error(self
);
1361 res
= PyString_FromString(Tkapp_Result(self
));
1370 Tkapp_Eval(PyObject
*self
, PyObject
*args
)
1373 PyObject
*res
= NULL
;
1376 if (!PyArg_ParseTuple(args
, "s:eval", &script
))
1379 CHECK_TCL_APPARTMENT
;
1382 err
= Tcl_Eval(Tkapp_Interp(self
), script
);
1384 if (err
== TCL_ERROR
)
1385 res
= Tkinter_Error(self
);
1387 res
= PyString_FromString(Tkapp_Result(self
));
1393 Tkapp_GlobalEval(PyObject
*self
, PyObject
*args
)
1396 PyObject
*res
= NULL
;
1399 if (!PyArg_ParseTuple(args
, "s:globaleval", &script
))
1402 CHECK_TCL_APPARTMENT
;
1405 err
= Tcl_GlobalEval(Tkapp_Interp(self
), script
);
1407 if (err
== TCL_ERROR
)
1408 res
= Tkinter_Error(self
);
1410 res
= PyString_FromString(Tkapp_Result(self
));
1416 Tkapp_EvalFile(PyObject
*self
, PyObject
*args
)
1419 PyObject
*res
= NULL
;
1422 if (!PyArg_ParseTuple(args
, "s:evalfile", &fileName
))
1425 CHECK_TCL_APPARTMENT
;
1428 err
= Tcl_EvalFile(Tkapp_Interp(self
), fileName
);
1430 if (err
== TCL_ERROR
)
1431 res
= Tkinter_Error(self
);
1434 res
= PyString_FromString(Tkapp_Result(self
));
1440 Tkapp_Record(PyObject
*self
, PyObject
*args
)
1443 PyObject
*res
= NULL
;
1446 if (!PyArg_ParseTuple(args
, "s", &script
))
1449 CHECK_TCL_APPARTMENT
;
1452 err
= Tcl_RecordAndEval(Tkapp_Interp(self
), script
, TCL_NO_EVAL
);
1454 if (err
== TCL_ERROR
)
1455 res
= Tkinter_Error(self
);
1457 res
= PyString_FromString(Tkapp_Result(self
));
1463 Tkapp_AddErrorInfo(PyObject
*self
, PyObject
*args
)
1467 if (!PyArg_ParseTuple(args
, "s:adderrorinfo", &msg
))
1469 CHECK_TCL_APPARTMENT
;
1472 Tcl_AddErrorInfo(Tkapp_Interp(self
), msg
);
1481 /** Tcl Variable **/
1483 TCL_DECLARE_MUTEX(var_mutex
)
1485 typedef PyObject
* (*EventFunc
)(PyObject
*, PyObject
*args
, int flags
);
1486 typedef struct VarEvent
{
1487 Tcl_Event ev
; /* must be first */
1493 PyObject
**exc_type
;
1499 varname_converter(PyObject
*in
, void *_out
)
1501 char **out
= (char**)_out
;
1502 if (PyString_Check(in
)) {
1503 *out
= PyString_AsString(in
);
1506 if (PyTclObject_Check(in
)) {
1507 *out
= PyTclObject_TclString(in
);
1510 /* XXX: Should give diagnostics. */
1515 var_perform(VarEvent
*ev
)
1517 *(ev
->res
) = ev
->func(ev
->self
, ev
->args
, ev
->flags
);
1519 PyObject
*exc
, *val
, *tb
;
1520 PyErr_Fetch(&exc
, &val
, &tb
);
1521 PyErr_NormalizeException(&exc
, &val
, &tb
);
1522 *(ev
->exc_type
) = exc
;
1523 *(ev
->exc_val
) = val
;
1530 var_proc(VarEvent
* ev
, int flags
)
1534 Tcl_MutexLock(&var_mutex
);
1535 Tcl_ConditionNotify(&ev
->cond
);
1536 Tcl_MutexUnlock(&var_mutex
);
1542 var_invoke(EventFunc func
, PyObject
*_self
, PyObject
*args
, int flags
)
1544 TkappObject
*self
= (TkappObject
*)_self
;
1546 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1547 TkappObject
*self
= (TkappObject
*)_self
;
1549 PyObject
*res
, *exc_type
, *exc_val
;
1551 /* The current thread is not the interpreter thread. Marshal
1552 the call to the interpreter thread, then wait for
1554 if (!WaitForMainloop(self
))
1557 ev
= (VarEvent
*)ckalloc(sizeof(VarEvent
));
1564 ev
->exc_type
= &exc_type
;
1565 ev
->exc_val
= &exc_val
;
1567 ev
->ev
.proc
= (Tcl_EventProc
*)var_proc
;
1568 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->cond
, &var_mutex
);
1570 PyErr_SetObject(exc_type
, exc_val
);
1571 Py_DECREF(exc_type
);
1578 /* Tcl is not threaded, or this is the interpreter thread. */
1579 return func(_self
, args
, flags
);
1583 SetVar(PyObject
*self
, PyObject
*args
, int flags
)
1585 char *name1
, *name2
;
1587 PyObject
*res
= NULL
;
1588 Tcl_Obj
*newval
, *ok
;
1590 if (PyArg_ParseTuple(args
, "O&O:setvar",
1591 varname_converter
, &name1
, &newValue
)) {
1592 /* XXX Acquire tcl lock??? */
1593 newval
= AsObj(newValue
);
1597 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, NULL
,
1601 Tkinter_Error(self
);
1610 if (PyArg_ParseTuple(args
, "ssO:setvar",
1611 &name1
, &name2
, &newValue
)) {
1612 /* XXX must hold tcl lock already??? */
1613 newval
= AsObj(newValue
);
1615 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, name2
, newval
, flags
);
1618 Tkinter_Error(self
);
1633 Tkapp_SetVar(PyObject
*self
, PyObject
*args
)
1635 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1639 Tkapp_GlobalSetVar(PyObject
*self
, PyObject
*args
)
1641 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1647 GetVar(PyObject
*self
, PyObject
*args
, int flags
)
1649 char *name1
, *name2
=NULL
;
1650 PyObject
*res
= NULL
;
1653 if (!PyArg_ParseTuple(args
, "O&|s:getvar",
1654 varname_converter
, &name1
, &name2
))
1658 tres
= Tcl_GetVar2Ex(Tkapp_Interp(self
), name1
, name2
, flags
);
1661 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
1663 if (((TkappObject
*)self
)->wantobjects
) {
1664 res
= FromObj(self
, tres
);
1667 res
= PyString_FromString(Tcl_GetString(tres
));
1675 Tkapp_GetVar(PyObject
*self
, PyObject
*args
)
1677 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1681 Tkapp_GlobalGetVar(PyObject
*self
, PyObject
*args
)
1683 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1689 UnsetVar(PyObject
*self
, PyObject
*args
, int flags
)
1691 char *name1
, *name2
=NULL
;
1693 PyObject
*res
= NULL
;
1695 if (!PyArg_ParseTuple(args
, "s|s:unsetvar", &name1
, &name2
))
1699 code
= Tcl_UnsetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
1701 if (code
== TCL_ERROR
)
1702 res
= Tkinter_Error(self
);
1712 Tkapp_UnsetVar(PyObject
*self
, PyObject
*args
)
1714 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1718 Tkapp_GlobalUnsetVar(PyObject
*self
, PyObject
*args
)
1720 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1725 /** Tcl to Python **/
1728 Tkapp_GetInt(PyObject
*self
, PyObject
*args
)
1733 if (PyTuple_Size(args
) == 1) {
1734 PyObject
* o
= PyTuple_GetItem(args
, 0);
1735 if (PyInt_Check(o
)) {
1740 if (!PyArg_ParseTuple(args
, "s:getint", &s
))
1742 if (Tcl_GetInt(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1743 return Tkinter_Error(self
);
1744 return Py_BuildValue("i", v
);
1748 Tkapp_GetDouble(PyObject
*self
, PyObject
*args
)
1753 if (PyTuple_Size(args
) == 1) {
1754 PyObject
*o
= PyTuple_GetItem(args
, 0);
1755 if (PyFloat_Check(o
)) {
1760 if (!PyArg_ParseTuple(args
, "s:getdouble", &s
))
1762 if (Tcl_GetDouble(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1763 return Tkinter_Error(self
);
1764 return Py_BuildValue("d", v
);
1768 Tkapp_GetBoolean(PyObject
*self
, PyObject
*args
)
1773 if (PyTuple_Size(args
) == 1) {
1774 PyObject
*o
= PyTuple_GetItem(args
, 0);
1775 if (PyInt_Check(o
)) {
1780 if (!PyArg_ParseTuple(args
, "s:getboolean", &s
))
1782 if (Tcl_GetBoolean(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1783 return Tkinter_Error(self
);
1784 return PyBool_FromLong(v
);
1788 Tkapp_ExprString(PyObject
*self
, PyObject
*args
)
1791 PyObject
*res
= NULL
;
1794 if (!PyArg_ParseTuple(args
, "s:exprstring", &s
))
1797 CHECK_TCL_APPARTMENT
;
1800 retval
= Tcl_ExprString(Tkapp_Interp(self
), s
);
1802 if (retval
== TCL_ERROR
)
1803 res
= Tkinter_Error(self
);
1805 res
= Py_BuildValue("s", Tkapp_Result(self
));
1811 Tkapp_ExprLong(PyObject
*self
, PyObject
*args
)
1814 PyObject
*res
= NULL
;
1818 if (!PyArg_ParseTuple(args
, "s:exprlong", &s
))
1821 CHECK_TCL_APPARTMENT
;
1824 retval
= Tcl_ExprLong(Tkapp_Interp(self
), s
, &v
);
1826 if (retval
== TCL_ERROR
)
1827 res
= Tkinter_Error(self
);
1829 res
= Py_BuildValue("l", v
);
1835 Tkapp_ExprDouble(PyObject
*self
, PyObject
*args
)
1838 PyObject
*res
= NULL
;
1842 if (!PyArg_ParseTuple(args
, "s:exprdouble", &s
))
1844 CHECK_TCL_APPARTMENT
;
1845 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1847 retval
= Tcl_ExprDouble(Tkapp_Interp(self
), s
, &v
);
1849 PyFPE_END_PROTECT(retval
)
1850 if (retval
== TCL_ERROR
)
1851 res
= Tkinter_Error(self
);
1853 res
= Py_BuildValue("d", v
);
1859 Tkapp_ExprBoolean(PyObject
*self
, PyObject
*args
)
1862 PyObject
*res
= NULL
;
1866 if (!PyArg_ParseTuple(args
, "s:exprboolean", &s
))
1868 CHECK_TCL_APPARTMENT
;
1870 retval
= Tcl_ExprBoolean(Tkapp_Interp(self
), s
, &v
);
1872 if (retval
== TCL_ERROR
)
1873 res
= Tkinter_Error(self
);
1875 res
= Py_BuildValue("i", v
);
1883 Tkapp_SplitList(PyObject
*self
, PyObject
*args
)
1891 if (PyTuple_Size(args
) == 1) {
1892 v
= PyTuple_GetItem(args
, 0);
1893 if (PyTuple_Check(v
)) {
1898 if (!PyArg_ParseTuple(args
, "et:splitlist", "utf-8", &list
))
1901 if (Tcl_SplitList(Tkapp_Interp(self
), list
,
1902 &argc
, &argv
) == TCL_ERROR
) {
1904 return Tkinter_Error(self
);
1907 if (!(v
= PyTuple_New(argc
)))
1910 for (i
= 0; i
< argc
; i
++) {
1911 PyObject
*s
= PyString_FromString(argv
[i
]);
1912 if (!s
|| PyTuple_SetItem(v
, i
, s
)) {
1920 ckfree(FREECAST argv
);
1926 Tkapp_Split(PyObject
*self
, PyObject
*args
)
1931 if (PyTuple_Size(args
) == 1) {
1932 PyObject
* o
= PyTuple_GetItem(args
, 0);
1933 if (PyTuple_Check(o
)) {
1938 if (!PyArg_ParseTuple(args
, "et:split", "utf-8", &list
))
1946 Tkapp_Merge(PyObject
*self
, PyObject
*args
)
1948 char *s
= Merge(args
);
1949 PyObject
*res
= NULL
;
1952 res
= PyString_FromString(s
);
1963 /* Client data struct */
1967 } PythonCmd_ClientData
;
1970 PythonCmd_Error(Tcl_Interp
*interp
)
1973 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1978 /* This is the Tcl command that acts as a wrapper for Python
1979 * function or method.
1982 PythonCmd(ClientData clientData
, Tcl_Interp
*interp
, int argc
, char *argv
[])
1984 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1985 PyObject
*self
, *func
, *arg
, *res
, *tmp
;
1991 /* TBD: no error checking here since we know, via the
1992 * Tkapp_CreateCommand() that the client data is a two-tuple
1997 /* Create argument list (argv1, ..., argvN) */
1998 if (!(arg
= PyTuple_New(argc
- 1)))
1999 return PythonCmd_Error(interp
);
2001 for (i
= 0; i
< (argc
- 1); i
++) {
2002 PyObject
*s
= PyString_FromString(argv
[i
+ 1]);
2003 if (!s
|| PyTuple_SetItem(arg
, i
, s
)) {
2005 return PythonCmd_Error(interp
);
2008 res
= PyEval_CallObject(func
, arg
);
2012 return PythonCmd_Error(interp
);
2014 if (!(tmp
= PyList_New(0))) {
2016 return PythonCmd_Error(interp
);
2019 s
= AsString(res
, tmp
);
2021 rv
= PythonCmd_Error(interp
);
2024 Tcl_SetResult(Tkapp_Interp(self
), s
, TCL_VOLATILE
);
2037 PythonCmdDelete(ClientData clientData
)
2039 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
2042 Py_XDECREF(data
->self
);
2043 Py_XDECREF(data
->func
);
2051 TCL_DECLARE_MUTEX(command_mutex
)
2053 typedef struct CommandEvent
{
2064 Tkapp_CommandProc(CommandEvent
*ev
, int flags
)
2067 *ev
->status
= Tcl_CreateCommand(
2068 ev
->interp
, ev
->name
, PythonCmd
,
2069 ev
->data
, PythonCmdDelete
) == NULL
;
2071 *ev
->status
= Tcl_DeleteCommand(ev
->interp
, ev
->name
);
2072 Tcl_MutexLock(&command_mutex
);
2073 Tcl_ConditionNotify(&ev
->done
);
2074 Tcl_MutexUnlock(&command_mutex
);
2079 Tkapp_CreateCommand(PyObject
*_self
, PyObject
*args
)
2081 TkappObject
*self
= (TkappObject
*)_self
;
2082 PythonCmd_ClientData
*data
;
2087 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
2089 if (!PyCallable_Check(func
)) {
2090 PyErr_SetString(PyExc_TypeError
, "command not callable");
2095 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread() &&
2096 !WaitForMainloop(self
))
2100 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
2102 return PyErr_NoMemory();
2108 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2109 CommandEvent
*ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2110 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2111 ev
->interp
= self
->interp
;
2114 ev
->data
= (ClientData
)data
;
2117 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
, &command_mutex
);
2121 err
= Tcl_CreateCommand(
2122 Tkapp_Interp(self
), cmdName
, PythonCmd
,
2123 (ClientData
)data
, PythonCmdDelete
) == NULL
;
2127 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
2139 Tkapp_DeleteCommand(PyObject
*_self
, PyObject
*args
)
2141 TkappObject
*self
= (TkappObject
*)_self
;
2145 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
2147 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2149 ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2150 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2151 ev
->interp
= self
->interp
;
2156 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
,
2161 err
= Tcl_DeleteCommand(self
->interp
, cmdName
);
2165 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
2174 #ifdef HAVE_CREATEFILEHANDLER
2175 /** File Handler **/
2177 typedef struct _fhcdata
{
2181 struct _fhcdata
*next
;
2182 } FileHandler_ClientData
;
2184 static FileHandler_ClientData
*HeadFHCD
;
2186 static FileHandler_ClientData
*
2187 NewFHCD(PyObject
*func
, PyObject
*file
, int id
)
2189 FileHandler_ClientData
*p
;
2190 p
= PyMem_NEW(FileHandler_ClientData
, 1);
2206 FileHandler_ClientData
*p
, **pp
;
2209 while ((p
= *pp
) != NULL
) {
2212 Py_XDECREF(p
->func
);
2213 Py_XDECREF(p
->file
);
2222 FileHandler(ClientData clientData
, int mask
)
2224 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
2225 PyObject
*func
, *file
, *arg
, *res
;
2231 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
2232 res
= PyEval_CallObject(func
, arg
);
2237 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2244 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
2245 /* args is (file, mask, func) */
2247 FileHandler_ClientData
*data
;
2248 PyObject
*file
, *func
;
2251 if (!PyArg_ParseTuple(args
, "OiO:createfilehandler",
2252 &file
, &mask
, &func
))
2256 if (!self
&& !tcl_lock
) {
2257 /* We don't have the Tcl lock since Tcl is threaded. */
2258 PyErr_SetString(PyExc_RuntimeError
,
2259 "_tkinter.createfilehandler not supported "
2260 "for threaded Tcl");
2266 CHECK_TCL_APPARTMENT
;
2269 tfile
= PyObject_AsFileDescriptor(file
);
2272 if (!PyCallable_Check(func
)) {
2273 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2277 data
= NewFHCD(func
, file
, tfile
);
2281 /* Ought to check for null Tcl_File object... */
2283 Tcl_CreateFileHandler(tfile
, mask
, FileHandler
, (ClientData
) data
);
2290 Tkapp_DeleteFileHandler(PyObject
*self
, PyObject
*args
)
2295 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
2299 if (!self
&& !tcl_lock
) {
2300 /* We don't have the Tcl lock since Tcl is threaded. */
2301 PyErr_SetString(PyExc_RuntimeError
,
2302 "_tkinter.deletefilehandler not supported "
2303 "for threaded Tcl");
2309 CHECK_TCL_APPARTMENT
;
2312 tfile
= PyObject_AsFileDescriptor(file
);
2318 /* Ought to check for null Tcl_File object... */
2320 Tcl_DeleteFileHandler(tfile
);
2325 #endif /* HAVE_CREATEFILEHANDLER */
2328 /**** Tktt Object (timer token) ****/
2330 static PyTypeObject Tktt_Type
;
2334 Tcl_TimerToken token
;
2339 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
2341 TkttObject
*v
= (TkttObject
*)self
;
2342 PyObject
*func
= v
->func
;
2344 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
2346 if (v
->token
!= NULL
) {
2347 Tcl_DeleteTimerHandler(v
->token
);
2353 Py_DECREF(v
); /* See Tktt_New() */
2359 static PyMethodDef Tktt_methods
[] =
2361 {"deletetimerhandler", Tktt_DeleteTimerHandler
, METH_VARARGS
},
2366 Tktt_New(PyObject
*func
)
2370 v
= PyObject_New(TkttObject
, &Tktt_Type
);
2378 /* Extra reference, deleted when called or when handler is deleted */
2384 Tktt_Dealloc(PyObject
*self
)
2386 TkttObject
*v
= (TkttObject
*)self
;
2387 PyObject
*func
= v
->func
;
2395 Tktt_Repr(PyObject
*self
)
2397 TkttObject
*v
= (TkttObject
*)self
;
2400 PyOS_snprintf(buf
, sizeof(buf
), "<tktimertoken at %p%s>", v
,
2401 v
->func
== NULL
? ", handler deleted" : "");
2402 return PyString_FromString(buf
);
2406 Tktt_GetAttr(PyObject
*self
, const char *name
)
2408 return Py_FindMethod(Tktt_methods
, self
, name
);
2411 static PyTypeObject Tktt_Type
=
2413 PyObject_HEAD_INIT(NULL
)
2415 "tktimertoken", /*tp_name */
2416 sizeof(TkttObject
), /*tp_basicsize */
2418 Tktt_Dealloc
, /*tp_dealloc */
2420 Tktt_GetAttr
, /*tp_getattr */
2423 Tktt_Repr
, /*tp_repr */
2424 0, /*tp_as_number */
2425 0, /*tp_as_sequence */
2426 0, /*tp_as_mapping */
2432 /** Timer Handler **/
2435 TimerHandler(ClientData clientData
)
2437 TkttObject
*v
= (TkttObject
*)clientData
;
2438 PyObject
*func
= v
->func
;
2448 res
= PyEval_CallObject(func
, NULL
);
2450 Py_DECREF(v
); /* See Tktt_New() */
2454 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2463 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
2469 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler",
2470 &milliseconds
, &func
))
2472 if (!PyCallable_Check(func
)) {
2473 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2478 if (!self
&& !tcl_lock
) {
2479 /* We don't have the Tcl lock since Tcl is threaded. */
2480 PyErr_SetString(PyExc_RuntimeError
,
2481 "_tkinter.createtimerhandler not supported "
2482 "for threaded Tcl");
2488 CHECK_TCL_APPARTMENT
;
2492 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
2495 return (PyObject
*) v
;
2502 Tkapp_MainLoop(PyObject
*_self
, PyObject
*args
)
2505 TkappObject
*self
= (TkappObject
*)_self
;
2507 PyThreadState
*tstate
= PyThreadState_Get();
2510 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
2514 if (!self
&& !tcl_lock
) {
2515 /* We don't have the Tcl lock since Tcl is threaded. */
2516 PyErr_SetString(PyExc_RuntimeError
,
2517 "_tkinter.mainloop not supported "
2518 "for threaded Tcl");
2524 CHECK_TCL_APPARTMENT
;
2525 self
->dispatching
= 1;
2529 while (Tk_GetNumMainWindows() > threshold
&&
2536 if (self
&& self
->threaded
) {
2537 /* Allow other Python threads to run. */
2539 result
= Tcl_DoOneEvent(0);
2543 Py_BEGIN_ALLOW_THREADS
2544 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
2545 tcl_tstate
= tstate
;
2546 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
2548 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
2550 Sleep(Tkinter_busywaitinterval
);
2551 Py_END_ALLOW_THREADS
2554 result
= Tcl_DoOneEvent(0);
2557 if (PyErr_CheckSignals() != 0) {
2559 self
->dispatching
= 0;
2566 self
->dispatching
= 0;
2571 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2572 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2580 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
2585 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
2589 rv
= Tcl_DoOneEvent(flags
);
2591 return Py_BuildValue("i", rv
);
2595 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
2598 if (!PyArg_ParseTuple(args
, ":quit"))
2607 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
2610 if (!PyArg_ParseTuple(args
, ":interpaddr"))
2613 return PyInt_FromLong((long)Tkapp_Interp(self
));
2617 Tkapp_TkInit(PyObject
*self
, PyObject
*args
)
2619 Tcl_Interp
*interp
= Tkapp_Interp(self
);
2620 Tk_Window main_window
;
2621 const char * _tk_exists
= NULL
;
2622 PyObject
*res
= NULL
;
2624 main_window
= Tk_MainWindow(interp
);
2626 /* We want to guard against calling Tk_Init() multiple times */
2627 CHECK_TCL_APPARTMENT
;
2629 err
= Tcl_Eval(Tkapp_Interp(self
), "info exists tk_version");
2631 if (err
== TCL_ERROR
) {
2632 /* XXX: shouldn't we do something with res? */
2633 res
= Tkinter_Error(self
);
2635 _tk_exists
= Tkapp_Result(self
);
2638 if (err
== TCL_ERROR
) {
2641 if (_tk_exists
== NULL
|| strcmp(_tk_exists
, "1") != 0) {
2642 if (Tk_Init(interp
) == TCL_ERROR
) {
2643 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
2652 Tkapp_WantObjects(PyObject
*self
, PyObject
*args
)
2655 int wantobjects
= -1;
2656 if (!PyArg_ParseTuple(args
, "|i:wantobjects", &wantobjects
))
2658 if (wantobjects
== -1)
2659 return PyBool_FromLong(((TkappObject
*)self
)->wantobjects
);
2660 ((TkappObject
*)self
)->wantobjects
= wantobjects
;
2667 Tkapp_WillDispatch(PyObject
*self
, PyObject
*args
)
2670 ((TkappObject
*)self
)->dispatching
= 1;
2677 /**** Tkapp Method List ****/
2679 static PyMethodDef Tkapp_methods
[] =
2681 {"willdispatch", Tkapp_WillDispatch
, METH_NOARGS
},
2682 {"wantobjects", Tkapp_WantObjects
, METH_VARARGS
},
2683 {"call", Tkapp_Call
, METH_OLDARGS
},
2684 {"globalcall", Tkapp_GlobalCall
, METH_OLDARGS
},
2685 {"eval", Tkapp_Eval
, METH_VARARGS
},
2686 {"globaleval", Tkapp_GlobalEval
, METH_VARARGS
},
2687 {"evalfile", Tkapp_EvalFile
, METH_VARARGS
},
2688 {"record", Tkapp_Record
, METH_VARARGS
},
2689 {"adderrorinfo", Tkapp_AddErrorInfo
, METH_VARARGS
},
2690 {"setvar", Tkapp_SetVar
, METH_VARARGS
},
2691 {"globalsetvar", Tkapp_GlobalSetVar
, METH_VARARGS
},
2692 {"getvar", Tkapp_GetVar
, METH_VARARGS
},
2693 {"globalgetvar", Tkapp_GlobalGetVar
, METH_VARARGS
},
2694 {"unsetvar", Tkapp_UnsetVar
, METH_VARARGS
},
2695 {"globalunsetvar", Tkapp_GlobalUnsetVar
, METH_VARARGS
},
2696 {"getint", Tkapp_GetInt
, METH_VARARGS
},
2697 {"getdouble", Tkapp_GetDouble
, METH_VARARGS
},
2698 {"getboolean", Tkapp_GetBoolean
, METH_VARARGS
},
2699 {"exprstring", Tkapp_ExprString
, METH_VARARGS
},
2700 {"exprlong", Tkapp_ExprLong
, METH_VARARGS
},
2701 {"exprdouble", Tkapp_ExprDouble
, METH_VARARGS
},
2702 {"exprboolean", Tkapp_ExprBoolean
, METH_VARARGS
},
2703 {"splitlist", Tkapp_SplitList
, METH_VARARGS
},
2704 {"split", Tkapp_Split
, METH_VARARGS
},
2705 {"merge", Tkapp_Merge
, METH_OLDARGS
},
2706 {"createcommand", Tkapp_CreateCommand
, METH_VARARGS
},
2707 {"deletecommand", Tkapp_DeleteCommand
, METH_VARARGS
},
2708 #ifdef HAVE_CREATEFILEHANDLER
2709 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
2710 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
2712 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
2713 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
2714 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
2715 {"quit", Tkapp_Quit
, METH_VARARGS
},
2716 {"interpaddr", Tkapp_InterpAddr
, METH_VARARGS
},
2717 {"loadtk", Tkapp_TkInit
, METH_NOARGS
},
2723 /**** Tkapp Type Methods ****/
2726 Tkapp_Dealloc(PyObject
*self
)
2728 /*CHECK_TCL_APPARTMENT;*/
2730 Tcl_DeleteInterp(Tkapp_Interp(self
));
2737 Tkapp_GetAttr(PyObject
*self
, const char *name
)
2739 return Py_FindMethod(Tkapp_methods
, self
, name
);
2742 static PyTypeObject Tkapp_Type
=
2744 PyObject_HEAD_INIT(NULL
)
2746 "tkapp", /*tp_name */
2747 sizeof(TkappObject
), /*tp_basicsize */
2749 Tkapp_Dealloc
, /*tp_dealloc */
2751 Tkapp_GetAttr
, /*tp_getattr */
2755 0, /*tp_as_number */
2756 0, /*tp_as_sequence */
2757 0, /*tp_as_mapping */
2763 /**** Tkinter Module ****/
2767 int size
; /* current size */
2768 int maxsize
; /* allocated size */
2772 _bump(FlattenContext
* context
, int size
)
2774 /* expand tuple to hold (at least) size new items.
2775 return true if successful, false if an exception was raised */
2777 int maxsize
= context
->maxsize
* 2;
2779 if (maxsize
< context
->size
+ size
)
2780 maxsize
= context
->size
+ size
;
2782 context
->maxsize
= maxsize
;
2784 return _PyTuple_Resize(&context
->tuple
, maxsize
) >= 0;
2788 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
2790 /* add tuple or list to argument tuple (recursively) */
2795 PyErr_SetString(PyExc_ValueError
,
2796 "nesting too deep in _flatten");
2798 } else if (PyList_Check(item
)) {
2799 size
= PyList_GET_SIZE(item
);
2800 /* preallocate (assume no nesting) */
2801 if (context
->size
+ size
> context
->maxsize
&&
2802 !_bump(context
, size
))
2804 /* copy items to output tuple */
2805 for (i
= 0; i
< size
; i
++) {
2806 PyObject
*o
= PyList_GET_ITEM(item
, i
);
2807 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2808 if (!_flatten1(context
, o
, depth
+ 1))
2810 } else if (o
!= Py_None
) {
2811 if (context
->size
+ 1 > context
->maxsize
&&
2815 PyTuple_SET_ITEM(context
->tuple
,
2816 context
->size
++, o
);
2819 } else if (PyTuple_Check(item
)) {
2820 /* same, for tuples */
2821 size
= PyTuple_GET_SIZE(item
);
2822 if (context
->size
+ size
> context
->maxsize
&&
2823 !_bump(context
, size
))
2825 for (i
= 0; i
< size
; i
++) {
2826 PyObject
*o
= PyTuple_GET_ITEM(item
, i
);
2827 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2828 if (!_flatten1(context
, o
, depth
+ 1))
2830 } else if (o
!= Py_None
) {
2831 if (context
->size
+ 1 > context
->maxsize
&&
2835 PyTuple_SET_ITEM(context
->tuple
,
2836 context
->size
++, o
);
2840 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
2847 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
2849 FlattenContext context
;
2852 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
2855 context
.maxsize
= PySequence_Size(item
);
2856 if (context
.maxsize
<= 0)
2857 return PyTuple_New(0);
2859 context
.tuple
= PyTuple_New(context
.maxsize
);
2865 if (!_flatten1(&context
, item
,0))
2868 if (_PyTuple_Resize(&context
.tuple
, context
.size
))
2871 return context
.tuple
;
2875 Tkinter_Create(PyObject
*self
, PyObject
*args
)
2877 char *screenName
= NULL
;
2878 char *baseName
= NULL
;
2879 char *className
= NULL
;
2880 int interactive
= 0;
2881 int wantobjects
= 0;
2882 int wantTk
= 1; /* If false, then Tk_Init() doesn't get called */
2883 int sync
= 0; /* pass -sync to wish */
2884 char *use
= NULL
; /* pass -use to wish */
2886 baseName
= strrchr(Py_GetProgramName(), '/');
2887 if (baseName
!= NULL
)
2890 baseName
= Py_GetProgramName();
2893 if (!PyArg_ParseTuple(args
, "|zssiiiiz:create",
2894 &screenName
, &baseName
, &className
,
2895 &interactive
, &wantobjects
, &wantTk
,
2899 return (PyObject
*) Tkapp_New(screenName
, baseName
, className
,
2900 interactive
, wantobjects
, wantTk
,
2905 Tkinter_setbusywaitinterval(PyObject
*self
, PyObject
*args
)
2908 if (!PyArg_ParseTuple(args
, "i:setbusywaitinterval", &new_val
))
2911 PyErr_SetString(PyExc_ValueError
,
2912 "busywaitinterval must be >= 0");
2915 Tkinter_busywaitinterval
= new_val
;
2920 static char setbusywaitinterval_doc
[] =
2921 "setbusywaitinterval(n) -> None\n\
2923 Set the busy-wait interval in milliseconds between successive\n\
2924 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2925 It should be set to a divisor of the maximum time between\n\
2926 frames in an animation.";
2929 Tkinter_getbusywaitinterval(PyObject
*self
, PyObject
*args
)
2931 return PyInt_FromLong(Tkinter_busywaitinterval
);
2934 static char getbusywaitinterval_doc
[] =
2935 "getbusywaitinterval() -> int\n\
2937 Return the current busy-wait interval between successive\n\
2938 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2940 static PyMethodDef moduleMethods
[] =
2942 {"_flatten", Tkinter_Flatten
, METH_VARARGS
},
2943 {"create", Tkinter_Create
, METH_VARARGS
},
2944 #ifdef HAVE_CREATEFILEHANDLER
2945 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
2946 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
2948 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
2949 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
2950 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
2951 {"quit", Tkapp_Quit
, METH_VARARGS
},
2952 {"setbusywaitinterval",Tkinter_setbusywaitinterval
, METH_VARARGS
,
2953 setbusywaitinterval_doc
},
2954 {"getbusywaitinterval",(PyCFunction
)Tkinter_getbusywaitinterval
,
2955 METH_NOARGS
, getbusywaitinterval_doc
},
2959 #ifdef WAIT_FOR_STDIN
2961 static int stdin_ready
= 0;
2965 MyFileProc(void *clientData
, int mask
)
2972 static PyThreadState
*event_tstate
= NULL
;
2982 PyEval_RestoreThread(event_tstate
);
2987 tfile
= fileno(stdin
);
2988 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
2990 while (!errorInCmd
&& !stdin_ready
) {
2998 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
2999 Py_BEGIN_ALLOW_THREADS
3000 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
3001 tcl_tstate
= event_tstate
;
3003 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
3006 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
3008 Sleep(Tkinter_busywaitinterval
);
3009 Py_END_ALLOW_THREADS
3011 result
= Tcl_DoOneEvent(0);
3018 Tcl_DeleteFileHandler(tfile
);
3022 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
3023 excInCmd
= valInCmd
= trbInCmd
= NULL
;
3027 PyEval_SaveThread();
3035 EnableEventHook(void)
3037 #ifdef WAIT_FOR_STDIN
3038 if (PyOS_InputHook
== NULL
) {
3040 event_tstate
= PyThreadState_Get();
3042 PyOS_InputHook
= EventHook
;
3048 DisableEventHook(void)
3050 #ifdef WAIT_FOR_STDIN
3051 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
3052 PyOS_InputHook
= NULL
;
3058 /* all errors will be checked in one fell swoop in init_tkinter() */
3060 ins_long(PyObject
*d
, char *name
, long val
)
3062 PyObject
*v
= PyInt_FromLong(val
);
3064 PyDict_SetItemString(d
, name
, v
);
3069 ins_string(PyObject
*d
, char *name
, char *val
)
3071 PyObject
*v
= PyString_FromString(val
);
3073 PyDict_SetItemString(d
, name
, v
);
3084 Tkapp_Type
.ob_type
= &PyType_Type
;
3087 tcl_lock
= PyThread_allocate_lock();
3090 m
= Py_InitModule("_tkinter", moduleMethods
);
3092 d
= PyModule_GetDict(m
);
3093 Tkinter_TclError
= PyErr_NewException("_tkinter.TclError", NULL
, NULL
);
3094 PyDict_SetItemString(d
, "TclError", Tkinter_TclError
);
3096 ins_long(d
, "READABLE", TCL_READABLE
);
3097 ins_long(d
, "WRITABLE", TCL_WRITABLE
);
3098 ins_long(d
, "EXCEPTION", TCL_EXCEPTION
);
3099 ins_long(d
, "WINDOW_EVENTS", TCL_WINDOW_EVENTS
);
3100 ins_long(d
, "FILE_EVENTS", TCL_FILE_EVENTS
);
3101 ins_long(d
, "TIMER_EVENTS", TCL_TIMER_EVENTS
);
3102 ins_long(d
, "IDLE_EVENTS", TCL_IDLE_EVENTS
);
3103 ins_long(d
, "ALL_EVENTS", TCL_ALL_EVENTS
);
3104 ins_long(d
, "DONT_WAIT", TCL_DONT_WAIT
);
3105 ins_string(d
, "TK_VERSION", TK_VERSION
);
3106 ins_string(d
, "TCL_VERSION", TCL_VERSION
);
3108 PyDict_SetItemString(d
, "TkappType", (PyObject
*)&Tkapp_Type
);
3110 Tktt_Type
.ob_type
= &PyType_Type
;
3111 PyDict_SetItemString(d
, "TkttType", (PyObject
*)&Tktt_Type
);
3113 PyTclObject_Type
.ob_type
= &PyType_Type
;
3114 PyDict_SetItemString(d
, "Tcl_Obj", (PyObject
*)&PyTclObject_Type
);
3117 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3118 * start waking up. Note that Tcl_FindExecutable will do this, this
3119 * code must be above it! The original warning from
3120 * tkMacOSXAppInit.c is copied below.
3122 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3123 * Tcl interpreter for now. It probably should work to do this
3124 * in the other order, but for now it doesn't seem to.
3127 Tk_MacOSXSetupTkNotifier();
3131 /* This helps the dynamic loader; in Unicode aware Tcl versions
3132 it also helps Tcl find its encodings. */
3133 Tcl_FindExecutable(Py_GetProgramName());
3135 if (PyErr_Occurred())
3139 /* This was not a good idea; through <Destroy> bindings,
3140 Tcl_Finalize() may invoke Python code but at that point the
3141 interpreter and thread state have already been destroyed! */
3142 Py_AtExit(Tcl_Finalize
);