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(Py_CHARMASK(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 PyObject
*result
= Tkinter_Error((PyObject
*)v
);
691 Py_DECREF((PyObject
*)v
);
692 return (TkappObject
*)result
;
702 Tkapp_ThreadSend(TkappObject
*self
, Tcl_Event
*ev
,
703 Tcl_Condition
*cond
, Tcl_Mutex
*mutex
)
705 Py_BEGIN_ALLOW_THREADS
;
706 Tcl_MutexLock(mutex
);
707 Tcl_ThreadQueueEvent(self
->thread_id
, ev
, TCL_QUEUE_TAIL
);
708 Tcl_ThreadAlert(self
->thread_id
);
709 Tcl_ConditionWait(cond
, mutex
, NULL
);
710 Tcl_MutexUnlock(mutex
);
720 PyObject
*string
; /* This cannot cause cycles. */
723 staticforward PyTypeObject PyTclObject_Type
;
724 #define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
727 newPyTclObject(Tcl_Obj
*arg
)
730 self
= PyObject_New(PyTclObject
, &PyTclObject_Type
);
733 Tcl_IncrRefCount(arg
);
736 return (PyObject
*)self
;
740 PyTclObject_dealloc(PyTclObject
*self
)
742 Tcl_DecrRefCount(self
->value
);
743 Py_XDECREF(self
->string
);
748 PyTclObject_str(PyTclObject
*self
)
750 if (self
->string
&& PyString_Check(self
->string
)) {
751 Py_INCREF(self
->string
);
754 /* XXX Could cache value if it is an ASCII string. */
755 return PyString_FromString(Tcl_GetString(self
->value
));
759 PyTclObject_TclString(PyObject
*self
)
761 return Tcl_GetString(((PyTclObject
*)self
)->value
);
764 /* Like _str, but create Unicode if necessary. */
765 PyDoc_STRVAR(PyTclObject_string__doc__
,
766 "the string representation of this object, either as string or Unicode");
769 PyTclObject_string(PyTclObject
*self
, void *ignored
)
774 s
= Tcl_GetStringFromObj(self
->value
, &len
);
775 for (i
= 0; i
< len
; i
++)
778 #ifdef Py_USING_UNICODE
780 /* It is an ASCII string. */
781 self
->string
= PyString_FromStringAndSize(s
, len
);
783 self
->string
= PyUnicode_DecodeUTF8(s
, len
, "strict");
786 self
->string
= PyString_FromStringAndSize(s
, len
);
790 self
->string
= PyString_FromStringAndSize(s
, len
);
795 Py_INCREF(self
->string
);
799 #ifdef Py_USING_UNICODE
800 PyDoc_STRVAR(PyTclObject_unicode__doc__
, "convert argument to unicode");
803 PyTclObject_unicode(PyTclObject
*self
, void *ignored
)
807 if (self
->string
&& PyUnicode_Check(self
->string
)) {
808 Py_INCREF(self
->string
);
811 /* XXX Could chache result if it is non-ASCII. */
812 s
= Tcl_GetStringFromObj(self
->value
, &len
);
813 return PyUnicode_DecodeUTF8(s
, len
, "strict");
818 PyTclObject_repr(PyTclObject
*self
)
821 PyOS_snprintf(buf
, 50, "<%s object at %p>",
822 self
->value
->typePtr
->name
, self
->value
);
823 return PyString_FromString(buf
);
827 PyTclObject_cmp(PyTclObject
*self
, PyTclObject
*other
)
830 res
= strcmp(Tcl_GetString(self
->value
),
831 Tcl_GetString(other
->value
));
832 if (res
< 0) return -1;
833 if (res
> 0) return 1;
837 PyDoc_STRVAR(get_typename__doc__
, "name of the Tcl type");
840 get_typename(PyTclObject
* obj
, void* ignored
)
842 return PyString_FromString(obj
->value
->typePtr
->name
);
846 static PyGetSetDef PyTclObject_getsetlist
[] = {
847 {"typename", (getter
)get_typename
, NULL
, get_typename__doc__
},
848 {"string", (getter
)PyTclObject_string
, NULL
,
849 PyTclObject_string__doc__
},
853 static PyMethodDef PyTclObject_methods
[] = {
854 #ifdef Py_USING_UNICODE
855 {"__unicode__", (PyCFunction
)PyTclObject_unicode
, METH_NOARGS
,
856 PyTclObject_unicode__doc__
},
861 statichere PyTypeObject PyTclObject_Type
= {
862 PyObject_HEAD_INIT(NULL
)
864 "_tkinter.Tcl_Obj", /*tp_name*/
865 sizeof(PyTclObject
), /*tp_basicsize*/
868 (destructor
)PyTclObject_dealloc
, /*tp_dealloc*/
872 (cmpfunc
)PyTclObject_cmp
, /*tp_compare*/
873 (reprfunc
)PyTclObject_repr
, /*tp_repr*/
875 0, /*tp_as_sequence*/
879 (reprfunc
)PyTclObject_str
, /*tp_str*/
880 PyObject_GenericGetAttr
,/*tp_getattro*/
883 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
887 0, /*tp_richcompare*/
888 0, /*tp_weaklistoffset*/
891 PyTclObject_methods
, /*tp_methods*/
893 PyTclObject_getsetlist
, /*tp_getset*/
907 AsObj(PyObject
*value
)
911 if (PyString_Check(value
))
912 return Tcl_NewStringObj(PyString_AS_STRING(value
),
913 PyString_GET_SIZE(value
));
914 else if (PyBool_Check(value
))
915 return Tcl_NewBooleanObj(PyObject_IsTrue(value
));
916 else if (PyInt_Check(value
))
917 return Tcl_NewLongObj(PyInt_AS_LONG(value
));
918 else if (PyFloat_Check(value
))
919 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value
));
920 else if (PyTuple_Check(value
)) {
921 Tcl_Obj
**argv
= (Tcl_Obj
**)
922 ckalloc(PyTuple_Size(value
)*sizeof(Tcl_Obj
*));
926 for(i
=0;i
<PyTuple_Size(value
);i
++)
927 argv
[i
] = AsObj(PyTuple_GetItem(value
,i
));
928 result
= Tcl_NewListObj(PyTuple_Size(value
), argv
);
929 ckfree(FREECAST argv
);
932 #ifdef Py_USING_UNICODE
933 else if (PyUnicode_Check(value
)) {
934 Py_UNICODE
*inbuf
= PyUnicode_AS_UNICODE(value
);
935 Py_ssize_t size
= PyUnicode_GET_SIZE(value
);
936 /* This #ifdef assumes that Tcl uses UCS-2.
937 See TCL_UTF_MAX test above. */
938 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
941 assert(size
< size
* sizeof(Tcl_UniChar
));
942 outbuf
= (Tcl_UniChar
*)ckalloc(size
* sizeof(Tcl_UniChar
));
947 for (i
= 0; i
< size
; i
++) {
948 if (inbuf
[i
] >= 0x10000) {
949 /* Tcl doesn't do UTF-16, yet. */
950 PyErr_SetString(PyExc_ValueError
,
951 "unsupported character");
952 ckfree(FREECAST outbuf
);
955 outbuf
[i
] = inbuf
[i
];
957 result
= Tcl_NewUnicodeObj(outbuf
, size
);
958 ckfree(FREECAST outbuf
);
961 return Tcl_NewUnicodeObj(inbuf
, size
);
966 else if(PyTclObject_Check(value
)) {
967 Tcl_Obj
*v
= ((PyTclObject
*)value
)->value
;
972 PyObject
*v
= PyObject_Str(value
);
982 FromObj(PyObject
* tkapp
, Tcl_Obj
*value
)
984 PyObject
*result
= NULL
;
985 TkappObject
*app
= (TkappObject
*)tkapp
;
987 if (value
->typePtr
== NULL
) {
988 /* If the result contains any bytes with the top bit set,
989 it's UTF-8 and we should decode it to Unicode */
990 #ifdef Py_USING_UNICODE
992 char *s
= value
->bytes
;
993 int len
= value
->length
;
994 for (i
= 0; i
< len
; i
++) {
995 if (value
->bytes
[i
] & 0x80)
999 if (i
== value
->length
)
1000 result
= PyString_FromStringAndSize(s
, len
);
1002 /* Convert UTF-8 to Unicode string */
1003 result
= PyUnicode_DecodeUTF8(s
, len
, "strict");
1004 if (result
== NULL
) {
1006 result
= PyString_FromStringAndSize(s
, len
);
1010 result
= PyString_FromStringAndSize(value
->bytes
, value
->length
);
1015 if (value
->typePtr
== app
->BooleanType
) {
1016 result
= value
->internalRep
.longValue
? Py_True
: Py_False
;
1021 if (value
->typePtr
== app
->ByteArrayType
) {
1023 char *data
= (char*)Tcl_GetByteArrayFromObj(value
, &size
);
1024 return PyString_FromStringAndSize(data
, size
);
1027 if (value
->typePtr
== app
->DoubleType
) {
1028 return PyFloat_FromDouble(value
->internalRep
.doubleValue
);
1031 if (value
->typePtr
== app
->IntType
) {
1032 return PyInt_FromLong(value
->internalRep
.longValue
);
1035 if (value
->typePtr
== app
->ListType
) {
1041 status
= Tcl_ListObjLength(Tkapp_Interp(tkapp
), value
, &size
);
1042 if (status
== TCL_ERROR
)
1043 return Tkinter_Error(tkapp
);
1044 result
= PyTuple_New(size
);
1047 for (i
= 0; i
< size
; i
++) {
1048 status
= Tcl_ListObjIndex(Tkapp_Interp(tkapp
),
1049 value
, i
, &tcl_elem
);
1050 if (status
== TCL_ERROR
) {
1052 return Tkinter_Error(tkapp
);
1054 elem
= FromObj(tkapp
, tcl_elem
);
1059 PyTuple_SetItem(result
, i
, elem
);
1064 if (value
->typePtr
== app
->ProcBodyType
) {
1065 /* fall through: return tcl object. */
1068 if (value
->typePtr
== app
->StringType
) {
1069 #ifdef Py_USING_UNICODE
1070 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1076 size
= Tcl_GetCharLength(value
);
1077 result
= PyUnicode_FromUnicode(NULL
, size
);
1080 input
= Tcl_GetUnicode(value
);
1081 output
= PyUnicode_AS_UNICODE(result
);
1083 *output
++ = *input
++;
1086 return PyUnicode_FromUnicode(Tcl_GetUnicode(value
),
1087 Tcl_GetCharLength(value
));
1092 c
= Tcl_GetStringFromObj(value
, &size
);
1093 return PyString_FromStringAndSize(c
, size
);
1097 return newPyTclObject(value
);
1100 /* This mutex synchronizes inter-thread command calls. */
1102 TCL_DECLARE_MUTEX(call_mutex
)
1104 typedef struct Tkapp_CallEvent
{
1105 Tcl_Event ev
; /* Must be first */
1110 PyObject
**exc_type
, **exc_value
, **exc_tb
;
1115 Tkapp_CallDeallocArgs(Tcl_Obj
** objv
, Tcl_Obj
** objStore
, int objc
)
1118 for (i
= 0; i
< objc
; i
++)
1119 Tcl_DecrRefCount(objv
[i
]);
1120 if (objv
!= objStore
)
1121 ckfree(FREECAST objv
);
1124 /* Convert Python objects to Tcl objects. This must happen in the
1125 interpreter thread, which may or may not be the calling thread. */
1128 Tkapp_CallArgs(PyObject
*args
, Tcl_Obj
** objStore
, int *pobjc
)
1130 Tcl_Obj
**objv
= objStore
;
1135 else if (!PyTuple_Check(args
)) {
1136 objv
[0] = AsObj(args
);
1140 Tcl_IncrRefCount(objv
[0]);
1143 objc
= PyTuple_Size(args
);
1146 objv
= (Tcl_Obj
**)ckalloc(objc
* sizeof(char *));
1154 for (i
= 0; i
< objc
; i
++) {
1155 PyObject
*v
= PyTuple_GetItem(args
, i
);
1162 /* Reset objc, so it attempts to clear
1163 objects only up to i. */
1167 Tcl_IncrRefCount(objv
[i
]);
1173 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1177 /* Convert the results of a command call into a Python objects. */
1180 Tkapp_CallResult(TkappObject
*self
)
1182 PyObject
*res
= NULL
;
1183 if(self
->wantobjects
) {
1184 Tcl_Obj
*value
= Tcl_GetObjResult(self
->interp
);
1185 /* Not sure whether the IncrRef is necessary, but something
1186 may overwrite the interpreter result while we are
1188 Tcl_IncrRefCount(value
);
1189 res
= FromObj((PyObject
*)self
, value
);
1190 Tcl_DecrRefCount(value
);
1192 const char *s
= Tcl_GetStringResult(self
->interp
);
1195 /* If the result contains any bytes with the top bit set,
1196 it's UTF-8 and we should decode it to Unicode */
1197 #ifdef Py_USING_UNICODE
1198 while (*p
!= '\0') {
1205 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
1207 /* Convert UTF-8 to Unicode string */
1208 p
= strchr(p
, '\0');
1209 res
= PyUnicode_DecodeUTF8(s
, (int)(p
-s
), "strict");
1212 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
1216 p
= strchr(p
, '\0');
1217 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
1223 /* Tkapp_CallProc is the event procedure that is executed in the context of
1224 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1225 hold the Python lock. */
1228 Tkapp_CallProc(Tkapp_CallEvent
*e
, int flags
)
1230 Tcl_Obj
*objStore
[ARGSZ
];
1235 objv
= Tkapp_CallArgs(e
->args
, objStore
, &objc
);
1237 PyErr_Fetch(e
->exc_type
, e
->exc_value
, e
->exc_tb
);
1243 i
= Tcl_EvalObjv(e
->self
->interp
, objc
, objv
, e
->flags
);
1245 if (i
== TCL_ERROR
) {
1247 *(e
->exc_type
) = NULL
;
1248 *(e
->exc_tb
) = NULL
;
1249 *(e
->exc_value
) = PyObject_CallFunction(
1250 Tkinter_TclError
, "s",
1251 Tcl_GetStringResult(e
->self
->interp
));
1254 *(e
->res
) = Tkapp_CallResult(e
->self
);
1258 /* Wake up calling thread. */
1259 Tcl_MutexLock(&call_mutex
);
1260 Tcl_ConditionNotify(&e
->done
);
1261 Tcl_MutexUnlock(&call_mutex
);
1265 /* This is the main entry point for calling a Tcl command.
1266 It supports three cases, with regard to threading:
1267 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1268 the context of the calling thread.
1269 2. Tcl is threaded, caller of the command is in the interpreter thread:
1270 Execute the command in the calling thread. Since the Tcl lock will
1271 not be used, we can merge that with case 1.
1272 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1273 the interpreter thread. Allocation of Tcl objects needs to occur in the
1274 interpreter thread, so we ship the PyObject* args to the target thread,
1275 and perform processing there. */
1278 Tkapp_Call(PyObject
*selfptr
, PyObject
*args
)
1280 Tcl_Obj
*objStore
[ARGSZ
];
1281 Tcl_Obj
**objv
= NULL
;
1283 PyObject
*res
= NULL
;
1284 TkappObject
*self
= (TkappObject
*)selfptr
;
1285 /* Could add TCL_EVAL_GLOBAL if wrapped by GlobalCall... */
1286 int flags
= TCL_EVAL_DIRECT
;
1289 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1290 /* We cannot call the command directly. Instead, we must
1291 marshal the parameters to the interpreter thread. */
1292 Tkapp_CallEvent
*ev
;
1293 PyObject
*exc_type
, *exc_value
, *exc_tb
;
1294 if (!WaitForMainloop(self
))
1296 ev
= (Tkapp_CallEvent
*)ckalloc(sizeof(Tkapp_CallEvent
));
1297 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CallProc
;
1301 ev
->exc_type
= &exc_type
;
1302 ev
->exc_value
= &exc_value
;
1303 ev
->exc_tb
= &exc_tb
;
1304 ev
->done
= (Tcl_Condition
)0;
1306 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
, &call_mutex
);
1310 PyErr_Restore(exc_type
, exc_value
, exc_tb
);
1312 PyErr_SetObject(Tkinter_TclError
, exc_value
);
1319 objv
= Tkapp_CallArgs(args
, objStore
, &objc
);
1325 i
= Tcl_EvalObjv(self
->interp
, objc
, objv
, flags
);
1330 Tkinter_Error(selfptr
);
1332 res
= Tkapp_CallResult(self
);
1336 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1343 Tkapp_GlobalCall(PyObject
*self
, PyObject
*args
)
1345 /* Could do the same here as for Tkapp_Call(), but this is not used
1346 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1347 way for the user to do what all its Global* variants do (save and
1348 reset the scope pointer, call the local version, restore the saved
1352 PyObject
*res
= NULL
;
1354 CHECK_TCL_APPARTMENT
;
1360 err
= Tcl_GlobalEval(Tkapp_Interp(self
), cmd
);
1362 if (err
== TCL_ERROR
)
1363 res
= Tkinter_Error(self
);
1365 res
= PyString_FromString(Tkapp_Result(self
));
1374 Tkapp_Eval(PyObject
*self
, PyObject
*args
)
1377 PyObject
*res
= NULL
;
1380 if (!PyArg_ParseTuple(args
, "s:eval", &script
))
1383 CHECK_TCL_APPARTMENT
;
1386 err
= Tcl_Eval(Tkapp_Interp(self
), script
);
1388 if (err
== TCL_ERROR
)
1389 res
= Tkinter_Error(self
);
1391 res
= PyString_FromString(Tkapp_Result(self
));
1397 Tkapp_GlobalEval(PyObject
*self
, PyObject
*args
)
1400 PyObject
*res
= NULL
;
1403 if (!PyArg_ParseTuple(args
, "s:globaleval", &script
))
1406 CHECK_TCL_APPARTMENT
;
1409 err
= Tcl_GlobalEval(Tkapp_Interp(self
), script
);
1411 if (err
== TCL_ERROR
)
1412 res
= Tkinter_Error(self
);
1414 res
= PyString_FromString(Tkapp_Result(self
));
1420 Tkapp_EvalFile(PyObject
*self
, PyObject
*args
)
1423 PyObject
*res
= NULL
;
1426 if (!PyArg_ParseTuple(args
, "s:evalfile", &fileName
))
1429 CHECK_TCL_APPARTMENT
;
1432 err
= Tcl_EvalFile(Tkapp_Interp(self
), fileName
);
1434 if (err
== TCL_ERROR
)
1435 res
= Tkinter_Error(self
);
1438 res
= PyString_FromString(Tkapp_Result(self
));
1444 Tkapp_Record(PyObject
*self
, PyObject
*args
)
1447 PyObject
*res
= NULL
;
1450 if (!PyArg_ParseTuple(args
, "s", &script
))
1453 CHECK_TCL_APPARTMENT
;
1456 err
= Tcl_RecordAndEval(Tkapp_Interp(self
), script
, TCL_NO_EVAL
);
1458 if (err
== TCL_ERROR
)
1459 res
= Tkinter_Error(self
);
1461 res
= PyString_FromString(Tkapp_Result(self
));
1467 Tkapp_AddErrorInfo(PyObject
*self
, PyObject
*args
)
1471 if (!PyArg_ParseTuple(args
, "s:adderrorinfo", &msg
))
1473 CHECK_TCL_APPARTMENT
;
1476 Tcl_AddErrorInfo(Tkapp_Interp(self
), msg
);
1485 /** Tcl Variable **/
1487 TCL_DECLARE_MUTEX(var_mutex
)
1489 typedef PyObject
* (*EventFunc
)(PyObject
*, PyObject
*args
, int flags
);
1490 typedef struct VarEvent
{
1491 Tcl_Event ev
; /* must be first */
1497 PyObject
**exc_type
;
1503 varname_converter(PyObject
*in
, void *_out
)
1505 char **out
= (char**)_out
;
1506 if (PyString_Check(in
)) {
1507 *out
= PyString_AsString(in
);
1510 if (PyTclObject_Check(in
)) {
1511 *out
= PyTclObject_TclString(in
);
1514 /* XXX: Should give diagnostics. */
1519 var_perform(VarEvent
*ev
)
1521 *(ev
->res
) = ev
->func(ev
->self
, ev
->args
, ev
->flags
);
1523 PyObject
*exc
, *val
, *tb
;
1524 PyErr_Fetch(&exc
, &val
, &tb
);
1525 PyErr_NormalizeException(&exc
, &val
, &tb
);
1526 *(ev
->exc_type
) = exc
;
1527 *(ev
->exc_val
) = val
;
1534 var_proc(VarEvent
* ev
, int flags
)
1538 Tcl_MutexLock(&var_mutex
);
1539 Tcl_ConditionNotify(&ev
->cond
);
1540 Tcl_MutexUnlock(&var_mutex
);
1546 var_invoke(EventFunc func
, PyObject
*selfptr
, PyObject
*args
, int flags
)
1548 TkappObject
*self
= (TkappObject
*)selfptr
;
1550 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1551 TkappObject
*self
= (TkappObject
*)selfptr
;
1553 PyObject
*res
, *exc_type
, *exc_val
;
1555 /* The current thread is not the interpreter thread. Marshal
1556 the call to the interpreter thread, then wait for
1558 if (!WaitForMainloop(self
))
1561 ev
= (VarEvent
*)ckalloc(sizeof(VarEvent
));
1568 ev
->exc_type
= &exc_type
;
1569 ev
->exc_val
= &exc_val
;
1571 ev
->ev
.proc
= (Tcl_EventProc
*)var_proc
;
1572 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->cond
, &var_mutex
);
1574 PyErr_SetObject(exc_type
, exc_val
);
1575 Py_DECREF(exc_type
);
1582 /* Tcl is not threaded, or this is the interpreter thread. */
1583 return func(selfptr
, args
, flags
);
1587 SetVar(PyObject
*self
, PyObject
*args
, int flags
)
1589 char *name1
, *name2
;
1591 PyObject
*res
= NULL
;
1592 Tcl_Obj
*newval
, *ok
;
1594 if (PyArg_ParseTuple(args
, "O&O:setvar",
1595 varname_converter
, &name1
, &newValue
)) {
1596 /* XXX Acquire tcl lock??? */
1597 newval
= AsObj(newValue
);
1601 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, NULL
,
1605 Tkinter_Error(self
);
1614 if (PyArg_ParseTuple(args
, "ssO:setvar",
1615 &name1
, &name2
, &newValue
)) {
1616 /* XXX must hold tcl lock already??? */
1617 newval
= AsObj(newValue
);
1619 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, name2
, newval
, flags
);
1622 Tkinter_Error(self
);
1637 Tkapp_SetVar(PyObject
*self
, PyObject
*args
)
1639 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1643 Tkapp_GlobalSetVar(PyObject
*self
, PyObject
*args
)
1645 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1651 GetVar(PyObject
*self
, PyObject
*args
, int flags
)
1653 char *name1
, *name2
=NULL
;
1654 PyObject
*res
= NULL
;
1657 if (!PyArg_ParseTuple(args
, "O&|s:getvar",
1658 varname_converter
, &name1
, &name2
))
1662 tres
= Tcl_GetVar2Ex(Tkapp_Interp(self
), name1
, name2
, flags
);
1665 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
1667 if (((TkappObject
*)self
)->wantobjects
) {
1668 res
= FromObj(self
, tres
);
1671 res
= PyString_FromString(Tcl_GetString(tres
));
1679 Tkapp_GetVar(PyObject
*self
, PyObject
*args
)
1681 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1685 Tkapp_GlobalGetVar(PyObject
*self
, PyObject
*args
)
1687 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1693 UnsetVar(PyObject
*self
, PyObject
*args
, int flags
)
1695 char *name1
, *name2
=NULL
;
1697 PyObject
*res
= NULL
;
1699 if (!PyArg_ParseTuple(args
, "s|s:unsetvar", &name1
, &name2
))
1703 code
= Tcl_UnsetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
1705 if (code
== TCL_ERROR
)
1706 res
= Tkinter_Error(self
);
1716 Tkapp_UnsetVar(PyObject
*self
, PyObject
*args
)
1718 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1722 Tkapp_GlobalUnsetVar(PyObject
*self
, PyObject
*args
)
1724 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1729 /** Tcl to Python **/
1732 Tkapp_GetInt(PyObject
*self
, PyObject
*args
)
1737 if (PyTuple_Size(args
) == 1) {
1738 PyObject
* o
= PyTuple_GetItem(args
, 0);
1739 if (PyInt_Check(o
)) {
1744 if (!PyArg_ParseTuple(args
, "s:getint", &s
))
1746 if (Tcl_GetInt(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1747 return Tkinter_Error(self
);
1748 return Py_BuildValue("i", v
);
1752 Tkapp_GetDouble(PyObject
*self
, PyObject
*args
)
1757 if (PyTuple_Size(args
) == 1) {
1758 PyObject
*o
= PyTuple_GetItem(args
, 0);
1759 if (PyFloat_Check(o
)) {
1764 if (!PyArg_ParseTuple(args
, "s:getdouble", &s
))
1766 if (Tcl_GetDouble(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1767 return Tkinter_Error(self
);
1768 return Py_BuildValue("d", v
);
1772 Tkapp_GetBoolean(PyObject
*self
, PyObject
*args
)
1777 if (PyTuple_Size(args
) == 1) {
1778 PyObject
*o
= PyTuple_GetItem(args
, 0);
1779 if (PyInt_Check(o
)) {
1784 if (!PyArg_ParseTuple(args
, "s:getboolean", &s
))
1786 if (Tcl_GetBoolean(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1787 return Tkinter_Error(self
);
1788 return PyBool_FromLong(v
);
1792 Tkapp_ExprString(PyObject
*self
, PyObject
*args
)
1795 PyObject
*res
= NULL
;
1798 if (!PyArg_ParseTuple(args
, "s:exprstring", &s
))
1801 CHECK_TCL_APPARTMENT
;
1804 retval
= Tcl_ExprString(Tkapp_Interp(self
), s
);
1806 if (retval
== TCL_ERROR
)
1807 res
= Tkinter_Error(self
);
1809 res
= Py_BuildValue("s", Tkapp_Result(self
));
1815 Tkapp_ExprLong(PyObject
*self
, PyObject
*args
)
1818 PyObject
*res
= NULL
;
1822 if (!PyArg_ParseTuple(args
, "s:exprlong", &s
))
1825 CHECK_TCL_APPARTMENT
;
1828 retval
= Tcl_ExprLong(Tkapp_Interp(self
), s
, &v
);
1830 if (retval
== TCL_ERROR
)
1831 res
= Tkinter_Error(self
);
1833 res
= Py_BuildValue("l", v
);
1839 Tkapp_ExprDouble(PyObject
*self
, PyObject
*args
)
1842 PyObject
*res
= NULL
;
1846 if (!PyArg_ParseTuple(args
, "s:exprdouble", &s
))
1848 CHECK_TCL_APPARTMENT
;
1849 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1851 retval
= Tcl_ExprDouble(Tkapp_Interp(self
), s
, &v
);
1853 PyFPE_END_PROTECT(retval
)
1854 if (retval
== TCL_ERROR
)
1855 res
= Tkinter_Error(self
);
1857 res
= Py_BuildValue("d", v
);
1863 Tkapp_ExprBoolean(PyObject
*self
, PyObject
*args
)
1866 PyObject
*res
= NULL
;
1870 if (!PyArg_ParseTuple(args
, "s:exprboolean", &s
))
1872 CHECK_TCL_APPARTMENT
;
1874 retval
= Tcl_ExprBoolean(Tkapp_Interp(self
), s
, &v
);
1876 if (retval
== TCL_ERROR
)
1877 res
= Tkinter_Error(self
);
1879 res
= Py_BuildValue("i", v
);
1887 Tkapp_SplitList(PyObject
*self
, PyObject
*args
)
1895 if (PyTuple_Size(args
) == 1) {
1896 v
= PyTuple_GetItem(args
, 0);
1897 if (PyTuple_Check(v
)) {
1902 if (!PyArg_ParseTuple(args
, "et:splitlist", "utf-8", &list
))
1905 if (Tcl_SplitList(Tkapp_Interp(self
), list
,
1906 &argc
, &argv
) == TCL_ERROR
) {
1908 return Tkinter_Error(self
);
1911 if (!(v
= PyTuple_New(argc
)))
1914 for (i
= 0; i
< argc
; i
++) {
1915 PyObject
*s
= PyString_FromString(argv
[i
]);
1916 if (!s
|| PyTuple_SetItem(v
, i
, s
)) {
1924 ckfree(FREECAST argv
);
1930 Tkapp_Split(PyObject
*self
, PyObject
*args
)
1935 if (PyTuple_Size(args
) == 1) {
1936 PyObject
* o
= PyTuple_GetItem(args
, 0);
1937 if (PyTuple_Check(o
)) {
1942 if (!PyArg_ParseTuple(args
, "et:split", "utf-8", &list
))
1950 Tkapp_Merge(PyObject
*self
, PyObject
*args
)
1952 char *s
= Merge(args
);
1953 PyObject
*res
= NULL
;
1956 res
= PyString_FromString(s
);
1967 /* Client data struct */
1971 } PythonCmd_ClientData
;
1974 PythonCmd_Error(Tcl_Interp
*interp
)
1977 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1982 /* This is the Tcl command that acts as a wrapper for Python
1983 * function or method.
1986 PythonCmd(ClientData clientData
, Tcl_Interp
*interp
, int argc
, char *argv
[])
1988 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1989 PyObject
*self
, *func
, *arg
, *res
, *tmp
;
1995 /* TBD: no error checking here since we know, via the
1996 * Tkapp_CreateCommand() that the client data is a two-tuple
2001 /* Create argument list (argv1, ..., argvN) */
2002 if (!(arg
= PyTuple_New(argc
- 1)))
2003 return PythonCmd_Error(interp
);
2005 for (i
= 0; i
< (argc
- 1); i
++) {
2006 PyObject
*s
= PyString_FromString(argv
[i
+ 1]);
2007 if (!s
|| PyTuple_SetItem(arg
, i
, s
)) {
2009 return PythonCmd_Error(interp
);
2012 res
= PyEval_CallObject(func
, arg
);
2016 return PythonCmd_Error(interp
);
2018 if (!(tmp
= PyList_New(0))) {
2020 return PythonCmd_Error(interp
);
2023 s
= AsString(res
, tmp
);
2025 rv
= PythonCmd_Error(interp
);
2028 Tcl_SetResult(Tkapp_Interp(self
), s
, TCL_VOLATILE
);
2041 PythonCmdDelete(ClientData clientData
)
2043 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
2046 Py_XDECREF(data
->self
);
2047 Py_XDECREF(data
->func
);
2055 TCL_DECLARE_MUTEX(command_mutex
)
2057 typedef struct CommandEvent
{
2068 Tkapp_CommandProc(CommandEvent
*ev
, int flags
)
2071 *ev
->status
= Tcl_CreateCommand(
2072 ev
->interp
, ev
->name
, PythonCmd
,
2073 ev
->data
, PythonCmdDelete
) == NULL
;
2075 *ev
->status
= Tcl_DeleteCommand(ev
->interp
, ev
->name
);
2076 Tcl_MutexLock(&command_mutex
);
2077 Tcl_ConditionNotify(&ev
->done
);
2078 Tcl_MutexUnlock(&command_mutex
);
2083 Tkapp_CreateCommand(PyObject
*selfptr
, PyObject
*args
)
2085 TkappObject
*self
= (TkappObject
*)selfptr
;
2086 PythonCmd_ClientData
*data
;
2091 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
2093 if (!PyCallable_Check(func
)) {
2094 PyErr_SetString(PyExc_TypeError
, "command not callable");
2099 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread() &&
2100 !WaitForMainloop(self
))
2104 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
2106 return PyErr_NoMemory();
2109 data
->self
= selfptr
;
2112 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2113 CommandEvent
*ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2114 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2115 ev
->interp
= self
->interp
;
2118 ev
->data
= (ClientData
)data
;
2121 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
, &command_mutex
);
2125 err
= Tcl_CreateCommand(
2126 Tkapp_Interp(self
), cmdName
, PythonCmd
,
2127 (ClientData
)data
, PythonCmdDelete
) == NULL
;
2131 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
2143 Tkapp_DeleteCommand(PyObject
*selfptr
, PyObject
*args
)
2145 TkappObject
*self
= (TkappObject
*)selfptr
;
2149 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
2151 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2153 ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2154 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2155 ev
->interp
= self
->interp
;
2160 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
,
2165 err
= Tcl_DeleteCommand(self
->interp
, cmdName
);
2169 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
2178 #ifdef HAVE_CREATEFILEHANDLER
2179 /** File Handler **/
2181 typedef struct _fhcdata
{
2185 struct _fhcdata
*next
;
2186 } FileHandler_ClientData
;
2188 static FileHandler_ClientData
*HeadFHCD
;
2190 static FileHandler_ClientData
*
2191 NewFHCD(PyObject
*func
, PyObject
*file
, int id
)
2193 FileHandler_ClientData
*p
;
2194 p
= PyMem_NEW(FileHandler_ClientData
, 1);
2210 FileHandler_ClientData
*p
, **pp
;
2213 while ((p
= *pp
) != NULL
) {
2216 Py_XDECREF(p
->func
);
2217 Py_XDECREF(p
->file
);
2226 FileHandler(ClientData clientData
, int mask
)
2228 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
2229 PyObject
*func
, *file
, *arg
, *res
;
2235 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
2236 res
= PyEval_CallObject(func
, arg
);
2241 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2248 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
2249 /* args is (file, mask, func) */
2251 FileHandler_ClientData
*data
;
2252 PyObject
*file
, *func
;
2255 if (!PyArg_ParseTuple(args
, "OiO:createfilehandler",
2256 &file
, &mask
, &func
))
2260 if (!self
&& !tcl_lock
) {
2261 /* We don't have the Tcl lock since Tcl is threaded. */
2262 PyErr_SetString(PyExc_RuntimeError
,
2263 "_tkinter.createfilehandler not supported "
2264 "for threaded Tcl");
2270 CHECK_TCL_APPARTMENT
;
2273 tfile
= PyObject_AsFileDescriptor(file
);
2276 if (!PyCallable_Check(func
)) {
2277 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2281 data
= NewFHCD(func
, file
, tfile
);
2285 /* Ought to check for null Tcl_File object... */
2287 Tcl_CreateFileHandler(tfile
, mask
, FileHandler
, (ClientData
) data
);
2294 Tkapp_DeleteFileHandler(PyObject
*self
, PyObject
*args
)
2299 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
2303 if (!self
&& !tcl_lock
) {
2304 /* We don't have the Tcl lock since Tcl is threaded. */
2305 PyErr_SetString(PyExc_RuntimeError
,
2306 "_tkinter.deletefilehandler not supported "
2307 "for threaded Tcl");
2313 CHECK_TCL_APPARTMENT
;
2316 tfile
= PyObject_AsFileDescriptor(file
);
2322 /* Ought to check for null Tcl_File object... */
2324 Tcl_DeleteFileHandler(tfile
);
2329 #endif /* HAVE_CREATEFILEHANDLER */
2332 /**** Tktt Object (timer token) ****/
2334 static PyTypeObject Tktt_Type
;
2338 Tcl_TimerToken token
;
2343 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
2345 TkttObject
*v
= (TkttObject
*)self
;
2346 PyObject
*func
= v
->func
;
2348 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
2350 if (v
->token
!= NULL
) {
2351 Tcl_DeleteTimerHandler(v
->token
);
2357 Py_DECREF(v
); /* See Tktt_New() */
2363 static PyMethodDef Tktt_methods
[] =
2365 {"deletetimerhandler", Tktt_DeleteTimerHandler
, METH_VARARGS
},
2370 Tktt_New(PyObject
*func
)
2374 v
= PyObject_New(TkttObject
, &Tktt_Type
);
2382 /* Extra reference, deleted when called or when handler is deleted */
2388 Tktt_Dealloc(PyObject
*self
)
2390 TkttObject
*v
= (TkttObject
*)self
;
2391 PyObject
*func
= v
->func
;
2399 Tktt_Repr(PyObject
*self
)
2401 TkttObject
*v
= (TkttObject
*)self
;
2404 PyOS_snprintf(buf
, sizeof(buf
), "<tktimertoken at %p%s>", v
,
2405 v
->func
== NULL
? ", handler deleted" : "");
2406 return PyString_FromString(buf
);
2410 Tktt_GetAttr(PyObject
*self
, char *name
)
2412 return Py_FindMethod(Tktt_methods
, self
, name
);
2415 static PyTypeObject Tktt_Type
=
2417 PyObject_HEAD_INIT(NULL
)
2419 "tktimertoken", /*tp_name */
2420 sizeof(TkttObject
), /*tp_basicsize */
2422 Tktt_Dealloc
, /*tp_dealloc */
2424 Tktt_GetAttr
, /*tp_getattr */
2427 Tktt_Repr
, /*tp_repr */
2428 0, /*tp_as_number */
2429 0, /*tp_as_sequence */
2430 0, /*tp_as_mapping */
2436 /** Timer Handler **/
2439 TimerHandler(ClientData clientData
)
2441 TkttObject
*v
= (TkttObject
*)clientData
;
2442 PyObject
*func
= v
->func
;
2452 res
= PyEval_CallObject(func
, NULL
);
2454 Py_DECREF(v
); /* See Tktt_New() */
2458 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2467 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
2473 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler",
2474 &milliseconds
, &func
))
2476 if (!PyCallable_Check(func
)) {
2477 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2482 if (!self
&& !tcl_lock
) {
2483 /* We don't have the Tcl lock since Tcl is threaded. */
2484 PyErr_SetString(PyExc_RuntimeError
,
2485 "_tkinter.createtimerhandler not supported "
2486 "for threaded Tcl");
2492 CHECK_TCL_APPARTMENT
;
2496 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
2499 return (PyObject
*) v
;
2506 Tkapp_MainLoop(PyObject
*selfptr
, PyObject
*args
)
2509 TkappObject
*self
= (TkappObject
*)selfptr
;
2511 PyThreadState
*tstate
= PyThreadState_Get();
2514 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
2518 if (!self
&& !tcl_lock
) {
2519 /* We don't have the Tcl lock since Tcl is threaded. */
2520 PyErr_SetString(PyExc_RuntimeError
,
2521 "_tkinter.mainloop not supported "
2522 "for threaded Tcl");
2528 CHECK_TCL_APPARTMENT
;
2529 self
->dispatching
= 1;
2533 while (Tk_GetNumMainWindows() > threshold
&&
2540 if (self
&& self
->threaded
) {
2541 /* Allow other Python threads to run. */
2543 result
= Tcl_DoOneEvent(0);
2547 Py_BEGIN_ALLOW_THREADS
2548 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
2549 tcl_tstate
= tstate
;
2550 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
2552 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
2554 Sleep(Tkinter_busywaitinterval
);
2555 Py_END_ALLOW_THREADS
2558 result
= Tcl_DoOneEvent(0);
2561 if (PyErr_CheckSignals() != 0) {
2563 self
->dispatching
= 0;
2570 self
->dispatching
= 0;
2575 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2576 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2584 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
2589 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
2593 rv
= Tcl_DoOneEvent(flags
);
2595 return Py_BuildValue("i", rv
);
2599 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
2602 if (!PyArg_ParseTuple(args
, ":quit"))
2611 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
2614 if (!PyArg_ParseTuple(args
, ":interpaddr"))
2617 return PyInt_FromLong((long)Tkapp_Interp(self
));
2621 Tkapp_TkInit(PyObject
*self
, PyObject
*args
)
2623 static int has_failed
;
2624 Tcl_Interp
*interp
= Tkapp_Interp(self
);
2625 Tk_Window main_window
;
2626 const char * _tk_exists
= NULL
;
2628 main_window
= Tk_MainWindow(interp
);
2630 /* In all current versions of Tk (including 8.4.13), Tk_Init
2631 deadlocks on the second call when the first call failed.
2632 To avoid the deadlock, we just refuse the second call through
2633 a static variable. */
2635 PyErr_SetString(Tkinter_TclError
,
2636 "Calling Tk_Init again after a previous call failed might deadlock");
2640 /* We want to guard against calling Tk_Init() multiple times */
2641 CHECK_TCL_APPARTMENT
;
2643 err
= Tcl_Eval(Tkapp_Interp(self
), "info exists tk_version");
2645 if (err
== TCL_ERROR
) {
2646 /* This sets an exception, but we cannot return right
2647 away because we need to exit the overlap first. */
2648 Tkinter_Error(self
);
2650 _tk_exists
= Tkapp_Result(self
);
2653 if (err
== TCL_ERROR
) {
2656 if (_tk_exists
== NULL
|| strcmp(_tk_exists
, "1") != 0) {
2657 if (Tk_Init(interp
) == TCL_ERROR
) {
2658 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
2668 Tkapp_WantObjects(PyObject
*self
, PyObject
*args
)
2671 int wantobjects
= -1;
2672 if (!PyArg_ParseTuple(args
, "|i:wantobjects", &wantobjects
))
2674 if (wantobjects
== -1)
2675 return PyBool_FromLong(((TkappObject
*)self
)->wantobjects
);
2676 ((TkappObject
*)self
)->wantobjects
= wantobjects
;
2683 Tkapp_WillDispatch(PyObject
*self
, PyObject
*args
)
2686 ((TkappObject
*)self
)->dispatching
= 1;
2693 /**** Tkapp Method List ****/
2695 static PyMethodDef Tkapp_methods
[] =
2697 {"willdispatch", Tkapp_WillDispatch
, METH_NOARGS
},
2698 {"wantobjects", Tkapp_WantObjects
, METH_VARARGS
},
2699 {"call", Tkapp_Call
, METH_OLDARGS
},
2700 {"globalcall", Tkapp_GlobalCall
, METH_OLDARGS
},
2701 {"eval", Tkapp_Eval
, METH_VARARGS
},
2702 {"globaleval", Tkapp_GlobalEval
, METH_VARARGS
},
2703 {"evalfile", Tkapp_EvalFile
, METH_VARARGS
},
2704 {"record", Tkapp_Record
, METH_VARARGS
},
2705 {"adderrorinfo", Tkapp_AddErrorInfo
, METH_VARARGS
},
2706 {"setvar", Tkapp_SetVar
, METH_VARARGS
},
2707 {"globalsetvar", Tkapp_GlobalSetVar
, METH_VARARGS
},
2708 {"getvar", Tkapp_GetVar
, METH_VARARGS
},
2709 {"globalgetvar", Tkapp_GlobalGetVar
, METH_VARARGS
},
2710 {"unsetvar", Tkapp_UnsetVar
, METH_VARARGS
},
2711 {"globalunsetvar", Tkapp_GlobalUnsetVar
, METH_VARARGS
},
2712 {"getint", Tkapp_GetInt
, METH_VARARGS
},
2713 {"getdouble", Tkapp_GetDouble
, METH_VARARGS
},
2714 {"getboolean", Tkapp_GetBoolean
, METH_VARARGS
},
2715 {"exprstring", Tkapp_ExprString
, METH_VARARGS
},
2716 {"exprlong", Tkapp_ExprLong
, METH_VARARGS
},
2717 {"exprdouble", Tkapp_ExprDouble
, METH_VARARGS
},
2718 {"exprboolean", Tkapp_ExprBoolean
, METH_VARARGS
},
2719 {"splitlist", Tkapp_SplitList
, METH_VARARGS
},
2720 {"split", Tkapp_Split
, METH_VARARGS
},
2721 {"merge", Tkapp_Merge
, METH_OLDARGS
},
2722 {"createcommand", Tkapp_CreateCommand
, METH_VARARGS
},
2723 {"deletecommand", Tkapp_DeleteCommand
, METH_VARARGS
},
2724 #ifdef HAVE_CREATEFILEHANDLER
2725 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
2726 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
2728 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
2729 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
2730 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
2731 {"quit", Tkapp_Quit
, METH_VARARGS
},
2732 {"interpaddr", Tkapp_InterpAddr
, METH_VARARGS
},
2733 {"loadtk", Tkapp_TkInit
, METH_NOARGS
},
2739 /**** Tkapp Type Methods ****/
2742 Tkapp_Dealloc(PyObject
*self
)
2744 /*CHECK_TCL_APPARTMENT;*/
2746 Tcl_DeleteInterp(Tkapp_Interp(self
));
2753 Tkapp_GetAttr(PyObject
*self
, char *name
)
2755 return Py_FindMethod(Tkapp_methods
, self
, name
);
2758 static PyTypeObject Tkapp_Type
=
2760 PyObject_HEAD_INIT(NULL
)
2762 "tkapp", /*tp_name */
2763 sizeof(TkappObject
), /*tp_basicsize */
2765 Tkapp_Dealloc
, /*tp_dealloc */
2767 Tkapp_GetAttr
, /*tp_getattr */
2771 0, /*tp_as_number */
2772 0, /*tp_as_sequence */
2773 0, /*tp_as_mapping */
2779 /**** Tkinter Module ****/
2783 int size
; /* current size */
2784 int maxsize
; /* allocated size */
2788 _bump(FlattenContext
* context
, int size
)
2790 /* expand tuple to hold (at least) size new items.
2791 return true if successful, false if an exception was raised */
2793 int maxsize
= context
->maxsize
* 2;
2795 if (maxsize
< context
->size
+ size
)
2796 maxsize
= context
->size
+ size
;
2798 context
->maxsize
= maxsize
;
2800 return _PyTuple_Resize(&context
->tuple
, maxsize
) >= 0;
2804 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
2806 /* add tuple or list to argument tuple (recursively) */
2811 PyErr_SetString(PyExc_ValueError
,
2812 "nesting too deep in _flatten");
2814 } else if (PyList_Check(item
)) {
2815 size
= PyList_GET_SIZE(item
);
2816 /* preallocate (assume no nesting) */
2817 if (context
->size
+ size
> context
->maxsize
&&
2818 !_bump(context
, size
))
2820 /* copy items to output tuple */
2821 for (i
= 0; i
< size
; i
++) {
2822 PyObject
*o
= PyList_GET_ITEM(item
, i
);
2823 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2824 if (!_flatten1(context
, o
, depth
+ 1))
2826 } else if (o
!= Py_None
) {
2827 if (context
->size
+ 1 > context
->maxsize
&&
2831 PyTuple_SET_ITEM(context
->tuple
,
2832 context
->size
++, o
);
2835 } else if (PyTuple_Check(item
)) {
2836 /* same, for tuples */
2837 size
= PyTuple_GET_SIZE(item
);
2838 if (context
->size
+ size
> context
->maxsize
&&
2839 !_bump(context
, size
))
2841 for (i
= 0; i
< size
; i
++) {
2842 PyObject
*o
= PyTuple_GET_ITEM(item
, i
);
2843 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2844 if (!_flatten1(context
, o
, depth
+ 1))
2846 } else if (o
!= Py_None
) {
2847 if (context
->size
+ 1 > context
->maxsize
&&
2851 PyTuple_SET_ITEM(context
->tuple
,
2852 context
->size
++, o
);
2856 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
2863 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
2865 FlattenContext context
;
2868 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
2871 context
.maxsize
= PySequence_Size(item
);
2872 if (context
.maxsize
<= 0)
2873 return PyTuple_New(0);
2875 context
.tuple
= PyTuple_New(context
.maxsize
);
2881 if (!_flatten1(&context
, item
,0))
2884 if (_PyTuple_Resize(&context
.tuple
, context
.size
))
2887 return context
.tuple
;
2891 Tkinter_Create(PyObject
*self
, PyObject
*args
)
2893 char *screenName
= NULL
;
2894 char *baseName
= NULL
;
2895 char *className
= NULL
;
2896 int interactive
= 0;
2897 int wantobjects
= 0;
2898 int wantTk
= 1; /* If false, then Tk_Init() doesn't get called */
2899 int sync
= 0; /* pass -sync to wish */
2900 char *use
= NULL
; /* pass -use to wish */
2902 baseName
= strrchr(Py_GetProgramName(), '/');
2903 if (baseName
!= NULL
)
2906 baseName
= Py_GetProgramName();
2909 if (!PyArg_ParseTuple(args
, "|zssiiiiz:create",
2910 &screenName
, &baseName
, &className
,
2911 &interactive
, &wantobjects
, &wantTk
,
2915 return (PyObject
*) Tkapp_New(screenName
, baseName
, className
,
2916 interactive
, wantobjects
, wantTk
,
2921 Tkinter_setbusywaitinterval(PyObject
*self
, PyObject
*args
)
2924 if (!PyArg_ParseTuple(args
, "i:setbusywaitinterval", &new_val
))
2927 PyErr_SetString(PyExc_ValueError
,
2928 "busywaitinterval must be >= 0");
2931 Tkinter_busywaitinterval
= new_val
;
2936 static char setbusywaitinterval_doc
[] =
2937 "setbusywaitinterval(n) -> None\n\
2939 Set the busy-wait interval in milliseconds between successive\n\
2940 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2941 It should be set to a divisor of the maximum time between\n\
2942 frames in an animation.";
2945 Tkinter_getbusywaitinterval(PyObject
*self
, PyObject
*args
)
2947 return PyInt_FromLong(Tkinter_busywaitinterval
);
2950 static char getbusywaitinterval_doc
[] =
2951 "getbusywaitinterval() -> int\n\
2953 Return the current busy-wait interval between successive\n\
2954 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2956 static PyMethodDef moduleMethods
[] =
2958 {"_flatten", Tkinter_Flatten
, METH_VARARGS
},
2959 {"create", Tkinter_Create
, METH_VARARGS
},
2960 #ifdef HAVE_CREATEFILEHANDLER
2961 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
2962 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
2964 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
2965 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
2966 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
2967 {"quit", Tkapp_Quit
, METH_VARARGS
},
2968 {"setbusywaitinterval",Tkinter_setbusywaitinterval
, METH_VARARGS
,
2969 setbusywaitinterval_doc
},
2970 {"getbusywaitinterval",(PyCFunction
)Tkinter_getbusywaitinterval
,
2971 METH_NOARGS
, getbusywaitinterval_doc
},
2975 #ifdef WAIT_FOR_STDIN
2977 static int stdin_ready
= 0;
2981 MyFileProc(void *clientData
, int mask
)
2988 static PyThreadState
*event_tstate
= NULL
;
2998 PyEval_RestoreThread(event_tstate
);
3003 tfile
= fileno(stdin
);
3004 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
3006 while (!errorInCmd
&& !stdin_ready
) {
3014 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3015 Py_BEGIN_ALLOW_THREADS
3016 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
3017 tcl_tstate
= event_tstate
;
3019 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
3022 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
3024 Sleep(Tkinter_busywaitinterval
);
3025 Py_END_ALLOW_THREADS
3027 result
= Tcl_DoOneEvent(0);
3034 Tcl_DeleteFileHandler(tfile
);
3038 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
3039 excInCmd
= valInCmd
= trbInCmd
= NULL
;
3043 PyEval_SaveThread();
3051 EnableEventHook(void)
3053 #ifdef WAIT_FOR_STDIN
3054 if (PyOS_InputHook
== NULL
) {
3056 event_tstate
= PyThreadState_Get();
3058 PyOS_InputHook
= EventHook
;
3064 DisableEventHook(void)
3066 #ifdef WAIT_FOR_STDIN
3067 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
3068 PyOS_InputHook
= NULL
;
3074 /* all errors will be checked in one fell swoop in init_tkinter() */
3076 ins_long(PyObject
*d
, char *name
, long val
)
3078 PyObject
*v
= PyInt_FromLong(val
);
3080 PyDict_SetItemString(d
, name
, v
);
3085 ins_string(PyObject
*d
, char *name
, char *val
)
3087 PyObject
*v
= PyString_FromString(val
);
3089 PyDict_SetItemString(d
, name
, v
);
3100 Tkapp_Type
.ob_type
= &PyType_Type
;
3103 tcl_lock
= PyThread_allocate_lock();
3106 m
= Py_InitModule("_tkinter", moduleMethods
);
3110 d
= PyModule_GetDict(m
);
3111 Tkinter_TclError
= PyErr_NewException("_tkinter.TclError", NULL
, NULL
);
3112 PyDict_SetItemString(d
, "TclError", Tkinter_TclError
);
3114 ins_long(d
, "READABLE", TCL_READABLE
);
3115 ins_long(d
, "WRITABLE", TCL_WRITABLE
);
3116 ins_long(d
, "EXCEPTION", TCL_EXCEPTION
);
3117 ins_long(d
, "WINDOW_EVENTS", TCL_WINDOW_EVENTS
);
3118 ins_long(d
, "FILE_EVENTS", TCL_FILE_EVENTS
);
3119 ins_long(d
, "TIMER_EVENTS", TCL_TIMER_EVENTS
);
3120 ins_long(d
, "IDLE_EVENTS", TCL_IDLE_EVENTS
);
3121 ins_long(d
, "ALL_EVENTS", TCL_ALL_EVENTS
);
3122 ins_long(d
, "DONT_WAIT", TCL_DONT_WAIT
);
3123 ins_string(d
, "TK_VERSION", TK_VERSION
);
3124 ins_string(d
, "TCL_VERSION", TCL_VERSION
);
3126 PyDict_SetItemString(d
, "TkappType", (PyObject
*)&Tkapp_Type
);
3128 Tktt_Type
.ob_type
= &PyType_Type
;
3129 PyDict_SetItemString(d
, "TkttType", (PyObject
*)&Tktt_Type
);
3131 PyTclObject_Type
.ob_type
= &PyType_Type
;
3132 PyDict_SetItemString(d
, "Tcl_Obj", (PyObject
*)&PyTclObject_Type
);
3135 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3136 * start waking up. Note that Tcl_FindExecutable will do this, this
3137 * code must be above it! The original warning from
3138 * tkMacOSXAppInit.c is copied below.
3140 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3141 * Tcl interpreter for now. It probably should work to do this
3142 * in the other order, but for now it doesn't seem to.
3145 Tk_MacOSXSetupTkNotifier();
3149 /* This helps the dynamic loader; in Unicode aware Tcl versions
3150 it also helps Tcl find its encodings. */
3151 Tcl_FindExecutable(Py_GetProgramName());
3153 if (PyErr_Occurred())
3157 /* This was not a good idea; through <Destroy> bindings,
3158 Tcl_Finalize() may invoke Python code but at that point the
3159 interpreter and thread state have already been destroyed! */
3160 Py_AtExit(Tcl_Finalize
);