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) (Py_Type(v) == &Tkapp_Type)
266 #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
267 #define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
269 #define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
270 (void *) v, Py_Refcnt(v)))
274 /**** Error Handling ****/
276 static PyObject
*Tkinter_TclError
;
277 static int quitMainLoop
= 0;
278 static int errorInCmd
= 0;
279 static PyObject
*excInCmd
;
280 static PyObject
*valInCmd
;
281 static PyObject
*trbInCmd
;
286 Tkinter_Error(PyObject
*v
)
288 PyErr_SetString(Tkinter_TclError
, Tkapp_Result(v
));
296 static int Tkinter_busywaitinterval
= 20;
301 /* Millisecond sleep() for Unix platforms. */
306 /* XXX Too bad if you don't have select(). */
308 t
.tv_sec
= milli
/1000;
309 t
.tv_usec
= (milli
%1000) * 1000;
310 select(0, (fd_set
*)0, (fd_set
*)0, (fd_set
*)0, &t
);
312 #endif /* MS_WINDOWS */
314 /* Wait up to 1s for the mainloop to come up. */
317 WaitForMainloop(TkappObject
* self
)
320 for (i
= 0; i
< 10; i
++) {
321 if (self
->dispatching
)
323 Py_BEGIN_ALLOW_THREADS
327 if (self
->dispatching
)
329 PyErr_SetString(PyExc_RuntimeError
, "main thread is not in main loop");
332 #endif /* WITH_THREAD */
336 AsString(PyObject
*value
, PyObject
*tmp
)
338 if (PyString_Check(value
))
339 return PyString_AsString(value
);
340 #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
;
1288 /* If args is a single tuple, replace with contents of tuple */
1289 if (1 == PyTuple_Size(args
)){
1290 PyObject
* item
= PyTuple_GetItem(args
, 0);
1291 if (PyTuple_Check(item
))
1295 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1296 /* We cannot call the command directly. Instead, we must
1297 marshal the parameters to the interpreter thread. */
1298 Tkapp_CallEvent
*ev
;
1299 PyObject
*exc_type
, *exc_value
, *exc_tb
;
1300 if (!WaitForMainloop(self
))
1302 ev
= (Tkapp_CallEvent
*)ckalloc(sizeof(Tkapp_CallEvent
));
1303 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CallProc
;
1307 ev
->exc_type
= &exc_type
;
1308 ev
->exc_value
= &exc_value
;
1309 ev
->exc_tb
= &exc_tb
;
1310 ev
->done
= (Tcl_Condition
)0;
1312 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
, &call_mutex
);
1316 PyErr_Restore(exc_type
, exc_value
, exc_tb
);
1318 PyErr_SetObject(Tkinter_TclError
, exc_value
);
1325 objv
= Tkapp_CallArgs(args
, objStore
, &objc
);
1331 i
= Tcl_EvalObjv(self
->interp
, objc
, objv
, flags
);
1336 Tkinter_Error(selfptr
);
1338 res
= Tkapp_CallResult(self
);
1342 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1349 Tkapp_GlobalCall(PyObject
*self
, PyObject
*args
)
1351 /* Could do the same here as for Tkapp_Call(), but this is not used
1352 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1353 way for the user to do what all its Global* variants do (save and
1354 reset the scope pointer, call the local version, restore the saved
1358 PyObject
*res
= NULL
;
1360 CHECK_TCL_APPARTMENT
;
1366 err
= Tcl_GlobalEval(Tkapp_Interp(self
), cmd
);
1368 if (err
== TCL_ERROR
)
1369 res
= Tkinter_Error(self
);
1371 res
= PyString_FromString(Tkapp_Result(self
));
1380 Tkapp_Eval(PyObject
*self
, PyObject
*args
)
1383 PyObject
*res
= NULL
;
1386 if (!PyArg_ParseTuple(args
, "s:eval", &script
))
1389 CHECK_TCL_APPARTMENT
;
1392 err
= Tcl_Eval(Tkapp_Interp(self
), script
);
1394 if (err
== TCL_ERROR
)
1395 res
= Tkinter_Error(self
);
1397 res
= PyString_FromString(Tkapp_Result(self
));
1403 Tkapp_GlobalEval(PyObject
*self
, PyObject
*args
)
1406 PyObject
*res
= NULL
;
1409 if (!PyArg_ParseTuple(args
, "s:globaleval", &script
))
1412 CHECK_TCL_APPARTMENT
;
1415 err
= Tcl_GlobalEval(Tkapp_Interp(self
), script
);
1417 if (err
== TCL_ERROR
)
1418 res
= Tkinter_Error(self
);
1420 res
= PyString_FromString(Tkapp_Result(self
));
1426 Tkapp_EvalFile(PyObject
*self
, PyObject
*args
)
1429 PyObject
*res
= NULL
;
1432 if (!PyArg_ParseTuple(args
, "s:evalfile", &fileName
))
1435 CHECK_TCL_APPARTMENT
;
1438 err
= Tcl_EvalFile(Tkapp_Interp(self
), fileName
);
1440 if (err
== TCL_ERROR
)
1441 res
= Tkinter_Error(self
);
1444 res
= PyString_FromString(Tkapp_Result(self
));
1450 Tkapp_Record(PyObject
*self
, PyObject
*args
)
1453 PyObject
*res
= NULL
;
1456 if (!PyArg_ParseTuple(args
, "s", &script
))
1459 CHECK_TCL_APPARTMENT
;
1462 err
= Tcl_RecordAndEval(Tkapp_Interp(self
), script
, TCL_NO_EVAL
);
1464 if (err
== TCL_ERROR
)
1465 res
= Tkinter_Error(self
);
1467 res
= PyString_FromString(Tkapp_Result(self
));
1473 Tkapp_AddErrorInfo(PyObject
*self
, PyObject
*args
)
1477 if (!PyArg_ParseTuple(args
, "s:adderrorinfo", &msg
))
1479 CHECK_TCL_APPARTMENT
;
1482 Tcl_AddErrorInfo(Tkapp_Interp(self
), msg
);
1491 /** Tcl Variable **/
1493 TCL_DECLARE_MUTEX(var_mutex
)
1495 typedef PyObject
* (*EventFunc
)(PyObject
*, PyObject
*args
, int flags
);
1496 typedef struct VarEvent
{
1497 Tcl_Event ev
; /* must be first */
1503 PyObject
**exc_type
;
1509 varname_converter(PyObject
*in
, void *_out
)
1511 char **out
= (char**)_out
;
1512 if (PyString_Check(in
)) {
1513 *out
= PyString_AsString(in
);
1516 if (PyTclObject_Check(in
)) {
1517 *out
= PyTclObject_TclString(in
);
1520 /* XXX: Should give diagnostics. */
1525 var_perform(VarEvent
*ev
)
1527 *(ev
->res
) = ev
->func(ev
->self
, ev
->args
, ev
->flags
);
1529 PyObject
*exc
, *val
, *tb
;
1530 PyErr_Fetch(&exc
, &val
, &tb
);
1531 PyErr_NormalizeException(&exc
, &val
, &tb
);
1532 *(ev
->exc_type
) = exc
;
1533 *(ev
->exc_val
) = val
;
1540 var_proc(VarEvent
* ev
, int flags
)
1544 Tcl_MutexLock(&var_mutex
);
1545 Tcl_ConditionNotify(&ev
->cond
);
1546 Tcl_MutexUnlock(&var_mutex
);
1552 var_invoke(EventFunc func
, PyObject
*selfptr
, PyObject
*args
, int flags
)
1554 TkappObject
*self
= (TkappObject
*)selfptr
;
1556 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1557 TkappObject
*self
= (TkappObject
*)selfptr
;
1559 PyObject
*res
, *exc_type
, *exc_val
;
1561 /* The current thread is not the interpreter thread. Marshal
1562 the call to the interpreter thread, then wait for
1564 if (!WaitForMainloop(self
))
1567 ev
= (VarEvent
*)ckalloc(sizeof(VarEvent
));
1574 ev
->exc_type
= &exc_type
;
1575 ev
->exc_val
= &exc_val
;
1577 ev
->ev
.proc
= (Tcl_EventProc
*)var_proc
;
1578 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->cond
, &var_mutex
);
1580 PyErr_SetObject(exc_type
, exc_val
);
1581 Py_DECREF(exc_type
);
1588 /* Tcl is not threaded, or this is the interpreter thread. */
1589 return func(selfptr
, args
, flags
);
1593 SetVar(PyObject
*self
, PyObject
*args
, int flags
)
1595 char *name1
, *name2
;
1597 PyObject
*res
= NULL
;
1598 Tcl_Obj
*newval
, *ok
;
1600 if (PyArg_ParseTuple(args
, "O&O:setvar",
1601 varname_converter
, &name1
, &newValue
)) {
1602 /* XXX Acquire tcl lock??? */
1603 newval
= AsObj(newValue
);
1607 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, NULL
,
1611 Tkinter_Error(self
);
1620 if (PyArg_ParseTuple(args
, "ssO:setvar",
1621 &name1
, &name2
, &newValue
)) {
1622 /* XXX must hold tcl lock already??? */
1623 newval
= AsObj(newValue
);
1625 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, name2
, newval
, flags
);
1628 Tkinter_Error(self
);
1643 Tkapp_SetVar(PyObject
*self
, PyObject
*args
)
1645 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1649 Tkapp_GlobalSetVar(PyObject
*self
, PyObject
*args
)
1651 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1657 GetVar(PyObject
*self
, PyObject
*args
, int flags
)
1659 char *name1
, *name2
=NULL
;
1660 PyObject
*res
= NULL
;
1663 if (!PyArg_ParseTuple(args
, "O&|s:getvar",
1664 varname_converter
, &name1
, &name2
))
1668 tres
= Tcl_GetVar2Ex(Tkapp_Interp(self
), name1
, name2
, flags
);
1671 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
1673 if (((TkappObject
*)self
)->wantobjects
) {
1674 res
= FromObj(self
, tres
);
1677 res
= PyString_FromString(Tcl_GetString(tres
));
1685 Tkapp_GetVar(PyObject
*self
, PyObject
*args
)
1687 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1691 Tkapp_GlobalGetVar(PyObject
*self
, PyObject
*args
)
1693 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1699 UnsetVar(PyObject
*self
, PyObject
*args
, int flags
)
1701 char *name1
, *name2
=NULL
;
1703 PyObject
*res
= NULL
;
1705 if (!PyArg_ParseTuple(args
, "s|s:unsetvar", &name1
, &name2
))
1709 code
= Tcl_UnsetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
1711 if (code
== TCL_ERROR
)
1712 res
= Tkinter_Error(self
);
1722 Tkapp_UnsetVar(PyObject
*self
, PyObject
*args
)
1724 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1728 Tkapp_GlobalUnsetVar(PyObject
*self
, PyObject
*args
)
1730 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1735 /** Tcl to Python **/
1738 Tkapp_GetInt(PyObject
*self
, PyObject
*args
)
1743 if (PyTuple_Size(args
) == 1) {
1744 PyObject
* o
= PyTuple_GetItem(args
, 0);
1745 if (PyInt_Check(o
)) {
1750 if (!PyArg_ParseTuple(args
, "s:getint", &s
))
1752 if (Tcl_GetInt(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1753 return Tkinter_Error(self
);
1754 return Py_BuildValue("i", v
);
1758 Tkapp_GetDouble(PyObject
*self
, PyObject
*args
)
1763 if (PyTuple_Size(args
) == 1) {
1764 PyObject
*o
= PyTuple_GetItem(args
, 0);
1765 if (PyFloat_Check(o
)) {
1770 if (!PyArg_ParseTuple(args
, "s:getdouble", &s
))
1772 if (Tcl_GetDouble(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1773 return Tkinter_Error(self
);
1774 return Py_BuildValue("d", v
);
1778 Tkapp_GetBoolean(PyObject
*self
, PyObject
*args
)
1783 if (PyTuple_Size(args
) == 1) {
1784 PyObject
*o
= PyTuple_GetItem(args
, 0);
1785 if (PyInt_Check(o
)) {
1790 if (!PyArg_ParseTuple(args
, "s:getboolean", &s
))
1792 if (Tcl_GetBoolean(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1793 return Tkinter_Error(self
);
1794 return PyBool_FromLong(v
);
1798 Tkapp_ExprString(PyObject
*self
, PyObject
*args
)
1801 PyObject
*res
= NULL
;
1804 if (!PyArg_ParseTuple(args
, "s:exprstring", &s
))
1807 CHECK_TCL_APPARTMENT
;
1810 retval
= Tcl_ExprString(Tkapp_Interp(self
), s
);
1812 if (retval
== TCL_ERROR
)
1813 res
= Tkinter_Error(self
);
1815 res
= Py_BuildValue("s", Tkapp_Result(self
));
1821 Tkapp_ExprLong(PyObject
*self
, PyObject
*args
)
1824 PyObject
*res
= NULL
;
1828 if (!PyArg_ParseTuple(args
, "s:exprlong", &s
))
1831 CHECK_TCL_APPARTMENT
;
1834 retval
= Tcl_ExprLong(Tkapp_Interp(self
), s
, &v
);
1836 if (retval
== TCL_ERROR
)
1837 res
= Tkinter_Error(self
);
1839 res
= Py_BuildValue("l", v
);
1845 Tkapp_ExprDouble(PyObject
*self
, PyObject
*args
)
1848 PyObject
*res
= NULL
;
1852 if (!PyArg_ParseTuple(args
, "s:exprdouble", &s
))
1854 CHECK_TCL_APPARTMENT
;
1855 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1857 retval
= Tcl_ExprDouble(Tkapp_Interp(self
), s
, &v
);
1859 PyFPE_END_PROTECT(retval
)
1860 if (retval
== TCL_ERROR
)
1861 res
= Tkinter_Error(self
);
1863 res
= Py_BuildValue("d", v
);
1869 Tkapp_ExprBoolean(PyObject
*self
, PyObject
*args
)
1872 PyObject
*res
= NULL
;
1876 if (!PyArg_ParseTuple(args
, "s:exprboolean", &s
))
1878 CHECK_TCL_APPARTMENT
;
1880 retval
= Tcl_ExprBoolean(Tkapp_Interp(self
), s
, &v
);
1882 if (retval
== TCL_ERROR
)
1883 res
= Tkinter_Error(self
);
1885 res
= Py_BuildValue("i", v
);
1893 Tkapp_SplitList(PyObject
*self
, PyObject
*args
)
1901 if (PyTuple_Size(args
) == 1) {
1902 v
= PyTuple_GetItem(args
, 0);
1903 if (PyTuple_Check(v
)) {
1908 if (!PyArg_ParseTuple(args
, "et:splitlist", "utf-8", &list
))
1911 if (Tcl_SplitList(Tkapp_Interp(self
), list
,
1912 &argc
, &argv
) == TCL_ERROR
) {
1914 return Tkinter_Error(self
);
1917 if (!(v
= PyTuple_New(argc
)))
1920 for (i
= 0; i
< argc
; i
++) {
1921 PyObject
*s
= PyString_FromString(argv
[i
]);
1922 if (!s
|| PyTuple_SetItem(v
, i
, s
)) {
1930 ckfree(FREECAST argv
);
1936 Tkapp_Split(PyObject
*self
, PyObject
*args
)
1941 if (PyTuple_Size(args
) == 1) {
1942 PyObject
* o
= PyTuple_GetItem(args
, 0);
1943 if (PyTuple_Check(o
)) {
1948 if (!PyArg_ParseTuple(args
, "et:split", "utf-8", &list
))
1956 Tkapp_Merge(PyObject
*self
, PyObject
*args
)
1958 char *s
= Merge(args
);
1959 PyObject
*res
= NULL
;
1962 res
= PyString_FromString(s
);
1973 /* Client data struct */
1977 } PythonCmd_ClientData
;
1980 PythonCmd_Error(Tcl_Interp
*interp
)
1983 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1988 /* This is the Tcl command that acts as a wrapper for Python
1989 * function or method.
1992 PythonCmd(ClientData clientData
, Tcl_Interp
*interp
, int argc
, char *argv
[])
1994 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1995 PyObject
*self
, *func
, *arg
, *res
, *tmp
;
2001 /* TBD: no error checking here since we know, via the
2002 * Tkapp_CreateCommand() that the client data is a two-tuple
2007 /* Create argument list (argv1, ..., argvN) */
2008 if (!(arg
= PyTuple_New(argc
- 1)))
2009 return PythonCmd_Error(interp
);
2011 for (i
= 0; i
< (argc
- 1); i
++) {
2012 PyObject
*s
= PyString_FromString(argv
[i
+ 1]);
2013 if (!s
|| PyTuple_SetItem(arg
, i
, s
)) {
2015 return PythonCmd_Error(interp
);
2018 res
= PyEval_CallObject(func
, arg
);
2022 return PythonCmd_Error(interp
);
2024 if (!(tmp
= PyList_New(0))) {
2026 return PythonCmd_Error(interp
);
2029 s
= AsString(res
, tmp
);
2033 return PythonCmd_Error(interp
);
2036 Tcl_SetResult(Tkapp_Interp(self
), s
, TCL_VOLATILE
);
2049 PythonCmdDelete(ClientData clientData
)
2051 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
2054 Py_XDECREF(data
->self
);
2055 Py_XDECREF(data
->func
);
2063 TCL_DECLARE_MUTEX(command_mutex
)
2065 typedef struct CommandEvent
{
2076 Tkapp_CommandProc(CommandEvent
*ev
, int flags
)
2079 *ev
->status
= Tcl_CreateCommand(
2080 ev
->interp
, ev
->name
, PythonCmd
,
2081 ev
->data
, PythonCmdDelete
) == NULL
;
2083 *ev
->status
= Tcl_DeleteCommand(ev
->interp
, ev
->name
);
2084 Tcl_MutexLock(&command_mutex
);
2085 Tcl_ConditionNotify(&ev
->done
);
2086 Tcl_MutexUnlock(&command_mutex
);
2091 Tkapp_CreateCommand(PyObject
*selfptr
, PyObject
*args
)
2093 TkappObject
*self
= (TkappObject
*)selfptr
;
2094 PythonCmd_ClientData
*data
;
2099 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
2101 if (!PyCallable_Check(func
)) {
2102 PyErr_SetString(PyExc_TypeError
, "command not callable");
2107 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread() &&
2108 !WaitForMainloop(self
))
2112 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
2114 return PyErr_NoMemory();
2117 data
->self
= selfptr
;
2120 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2121 CommandEvent
*ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2122 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2123 ev
->interp
= self
->interp
;
2126 ev
->data
= (ClientData
)data
;
2129 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
, &command_mutex
);
2133 err
= Tcl_CreateCommand(
2134 Tkapp_Interp(self
), cmdName
, PythonCmd
,
2135 (ClientData
)data
, PythonCmdDelete
) == NULL
;
2139 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
2151 Tkapp_DeleteCommand(PyObject
*selfptr
, PyObject
*args
)
2153 TkappObject
*self
= (TkappObject
*)selfptr
;
2157 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
2159 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2161 ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2162 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2163 ev
->interp
= self
->interp
;
2168 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
,
2173 err
= Tcl_DeleteCommand(self
->interp
, cmdName
);
2177 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
2186 #ifdef HAVE_CREATEFILEHANDLER
2187 /** File Handler **/
2189 typedef struct _fhcdata
{
2193 struct _fhcdata
*next
;
2194 } FileHandler_ClientData
;
2196 static FileHandler_ClientData
*HeadFHCD
;
2198 static FileHandler_ClientData
*
2199 NewFHCD(PyObject
*func
, PyObject
*file
, int id
)
2201 FileHandler_ClientData
*p
;
2202 p
= PyMem_NEW(FileHandler_ClientData
, 1);
2218 FileHandler_ClientData
*p
, **pp
;
2221 while ((p
= *pp
) != NULL
) {
2224 Py_XDECREF(p
->func
);
2225 Py_XDECREF(p
->file
);
2234 FileHandler(ClientData clientData
, int mask
)
2236 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
2237 PyObject
*func
, *file
, *arg
, *res
;
2243 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
2244 res
= PyEval_CallObject(func
, arg
);
2249 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2256 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
2257 /* args is (file, mask, func) */
2259 FileHandler_ClientData
*data
;
2260 PyObject
*file
, *func
;
2263 if (!PyArg_ParseTuple(args
, "OiO:createfilehandler",
2264 &file
, &mask
, &func
))
2268 if (!self
&& !tcl_lock
) {
2269 /* We don't have the Tcl lock since Tcl is threaded. */
2270 PyErr_SetString(PyExc_RuntimeError
,
2271 "_tkinter.createfilehandler not supported "
2272 "for threaded Tcl");
2278 CHECK_TCL_APPARTMENT
;
2281 tfile
= PyObject_AsFileDescriptor(file
);
2284 if (!PyCallable_Check(func
)) {
2285 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2289 data
= NewFHCD(func
, file
, tfile
);
2293 /* Ought to check for null Tcl_File object... */
2295 Tcl_CreateFileHandler(tfile
, mask
, FileHandler
, (ClientData
) data
);
2302 Tkapp_DeleteFileHandler(PyObject
*self
, PyObject
*args
)
2307 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
2311 if (!self
&& !tcl_lock
) {
2312 /* We don't have the Tcl lock since Tcl is threaded. */
2313 PyErr_SetString(PyExc_RuntimeError
,
2314 "_tkinter.deletefilehandler not supported "
2315 "for threaded Tcl");
2321 CHECK_TCL_APPARTMENT
;
2324 tfile
= PyObject_AsFileDescriptor(file
);
2330 /* Ought to check for null Tcl_File object... */
2332 Tcl_DeleteFileHandler(tfile
);
2337 #endif /* HAVE_CREATEFILEHANDLER */
2340 /**** Tktt Object (timer token) ****/
2342 static PyTypeObject Tktt_Type
;
2346 Tcl_TimerToken token
;
2351 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
2353 TkttObject
*v
= (TkttObject
*)self
;
2354 PyObject
*func
= v
->func
;
2356 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
2358 if (v
->token
!= NULL
) {
2359 Tcl_DeleteTimerHandler(v
->token
);
2365 Py_DECREF(v
); /* See Tktt_New() */
2371 static PyMethodDef Tktt_methods
[] =
2373 {"deletetimerhandler", Tktt_DeleteTimerHandler
, METH_VARARGS
},
2378 Tktt_New(PyObject
*func
)
2382 v
= PyObject_New(TkttObject
, &Tktt_Type
);
2390 /* Extra reference, deleted when called or when handler is deleted */
2396 Tktt_Dealloc(PyObject
*self
)
2398 TkttObject
*v
= (TkttObject
*)self
;
2399 PyObject
*func
= v
->func
;
2407 Tktt_Repr(PyObject
*self
)
2409 TkttObject
*v
= (TkttObject
*)self
;
2412 PyOS_snprintf(buf
, sizeof(buf
), "<tktimertoken at %p%s>", v
,
2413 v
->func
== NULL
? ", handler deleted" : "");
2414 return PyString_FromString(buf
);
2418 Tktt_GetAttr(PyObject
*self
, char *name
)
2420 return Py_FindMethod(Tktt_methods
, self
, name
);
2423 static PyTypeObject Tktt_Type
=
2425 PyVarObject_HEAD_INIT(NULL
, 0)
2426 "tktimertoken", /*tp_name */
2427 sizeof(TkttObject
), /*tp_basicsize */
2429 Tktt_Dealloc
, /*tp_dealloc */
2431 Tktt_GetAttr
, /*tp_getattr */
2434 Tktt_Repr
, /*tp_repr */
2435 0, /*tp_as_number */
2436 0, /*tp_as_sequence */
2437 0, /*tp_as_mapping */
2443 /** Timer Handler **/
2446 TimerHandler(ClientData clientData
)
2448 TkttObject
*v
= (TkttObject
*)clientData
;
2449 PyObject
*func
= v
->func
;
2459 res
= PyEval_CallObject(func
, NULL
);
2461 Py_DECREF(v
); /* See Tktt_New() */
2465 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2474 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
2480 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler",
2481 &milliseconds
, &func
))
2483 if (!PyCallable_Check(func
)) {
2484 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2489 if (!self
&& !tcl_lock
) {
2490 /* We don't have the Tcl lock since Tcl is threaded. */
2491 PyErr_SetString(PyExc_RuntimeError
,
2492 "_tkinter.createtimerhandler not supported "
2493 "for threaded Tcl");
2499 CHECK_TCL_APPARTMENT
;
2504 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
2508 return (PyObject
*) v
;
2515 Tkapp_MainLoop(PyObject
*selfptr
, PyObject
*args
)
2518 TkappObject
*self
= (TkappObject
*)selfptr
;
2520 PyThreadState
*tstate
= PyThreadState_Get();
2523 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
2527 if (!self
&& !tcl_lock
) {
2528 /* We don't have the Tcl lock since Tcl is threaded. */
2529 PyErr_SetString(PyExc_RuntimeError
,
2530 "_tkinter.mainloop not supported "
2531 "for threaded Tcl");
2537 CHECK_TCL_APPARTMENT
;
2538 self
->dispatching
= 1;
2542 while (Tk_GetNumMainWindows() > threshold
&&
2549 if (self
&& self
->threaded
) {
2550 /* Allow other Python threads to run. */
2552 result
= Tcl_DoOneEvent(0);
2556 Py_BEGIN_ALLOW_THREADS
2557 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
2558 tcl_tstate
= tstate
;
2559 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
2561 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
2563 Sleep(Tkinter_busywaitinterval
);
2564 Py_END_ALLOW_THREADS
2567 result
= Tcl_DoOneEvent(0);
2570 if (PyErr_CheckSignals() != 0) {
2572 self
->dispatching
= 0;
2579 self
->dispatching
= 0;
2584 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2585 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2593 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
2598 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
2602 rv
= Tcl_DoOneEvent(flags
);
2604 return Py_BuildValue("i", rv
);
2608 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
2611 if (!PyArg_ParseTuple(args
, ":quit"))
2620 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
2623 if (!PyArg_ParseTuple(args
, ":interpaddr"))
2626 return PyInt_FromLong((long)Tkapp_Interp(self
));
2630 Tkapp_TkInit(PyObject
*self
, PyObject
*args
)
2632 static int has_failed
;
2633 Tcl_Interp
*interp
= Tkapp_Interp(self
);
2634 Tk_Window main_window
;
2635 const char * _tk_exists
= NULL
;
2637 main_window
= Tk_MainWindow(interp
);
2639 /* In all current versions of Tk (including 8.4.13), Tk_Init
2640 deadlocks on the second call when the first call failed.
2641 To avoid the deadlock, we just refuse the second call through
2642 a static variable. */
2644 PyErr_SetString(Tkinter_TclError
,
2645 "Calling Tk_Init again after a previous call failed might deadlock");
2649 /* We want to guard against calling Tk_Init() multiple times */
2650 CHECK_TCL_APPARTMENT
;
2652 err
= Tcl_Eval(Tkapp_Interp(self
), "info exists tk_version");
2654 if (err
== TCL_ERROR
) {
2655 /* This sets an exception, but we cannot return right
2656 away because we need to exit the overlap first. */
2657 Tkinter_Error(self
);
2659 _tk_exists
= Tkapp_Result(self
);
2662 if (err
== TCL_ERROR
) {
2665 if (_tk_exists
== NULL
|| strcmp(_tk_exists
, "1") != 0) {
2666 if (Tk_Init(interp
) == TCL_ERROR
) {
2667 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
2677 Tkapp_WantObjects(PyObject
*self
, PyObject
*args
)
2680 int wantobjects
= -1;
2681 if (!PyArg_ParseTuple(args
, "|i:wantobjects", &wantobjects
))
2683 if (wantobjects
== -1)
2684 return PyBool_FromLong(((TkappObject
*)self
)->wantobjects
);
2685 ((TkappObject
*)self
)->wantobjects
= wantobjects
;
2692 Tkapp_WillDispatch(PyObject
*self
, PyObject
*args
)
2695 ((TkappObject
*)self
)->dispatching
= 1;
2702 /**** Tkapp Method List ****/
2704 static PyMethodDef Tkapp_methods
[] =
2706 {"willdispatch", Tkapp_WillDispatch
, METH_NOARGS
},
2707 {"wantobjects", Tkapp_WantObjects
, METH_VARARGS
},
2708 {"call", Tkapp_Call
, METH_VARARGS
},
2709 {"globalcall", Tkapp_GlobalCall
, METH_VARARGS
},
2710 {"eval", Tkapp_Eval
, METH_VARARGS
},
2711 {"globaleval", Tkapp_GlobalEval
, METH_VARARGS
},
2712 {"evalfile", Tkapp_EvalFile
, METH_VARARGS
},
2713 {"record", Tkapp_Record
, METH_VARARGS
},
2714 {"adderrorinfo", Tkapp_AddErrorInfo
, METH_VARARGS
},
2715 {"setvar", Tkapp_SetVar
, METH_VARARGS
},
2716 {"globalsetvar", Tkapp_GlobalSetVar
, METH_VARARGS
},
2717 {"getvar", Tkapp_GetVar
, METH_VARARGS
},
2718 {"globalgetvar", Tkapp_GlobalGetVar
, METH_VARARGS
},
2719 {"unsetvar", Tkapp_UnsetVar
, METH_VARARGS
},
2720 {"globalunsetvar", Tkapp_GlobalUnsetVar
, METH_VARARGS
},
2721 {"getint", Tkapp_GetInt
, METH_VARARGS
},
2722 {"getdouble", Tkapp_GetDouble
, METH_VARARGS
},
2723 {"getboolean", Tkapp_GetBoolean
, METH_VARARGS
},
2724 {"exprstring", Tkapp_ExprString
, METH_VARARGS
},
2725 {"exprlong", Tkapp_ExprLong
, METH_VARARGS
},
2726 {"exprdouble", Tkapp_ExprDouble
, METH_VARARGS
},
2727 {"exprboolean", Tkapp_ExprBoolean
, METH_VARARGS
},
2728 {"splitlist", Tkapp_SplitList
, METH_VARARGS
},
2729 {"split", Tkapp_Split
, METH_VARARGS
},
2730 {"merge", Tkapp_Merge
, METH_VARARGS
},
2731 {"createcommand", Tkapp_CreateCommand
, METH_VARARGS
},
2732 {"deletecommand", Tkapp_DeleteCommand
, METH_VARARGS
},
2733 #ifdef HAVE_CREATEFILEHANDLER
2734 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
2735 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
2737 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
2738 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
2739 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
2740 {"quit", Tkapp_Quit
, METH_VARARGS
},
2741 {"interpaddr", Tkapp_InterpAddr
, METH_VARARGS
},
2742 {"loadtk", Tkapp_TkInit
, METH_NOARGS
},
2748 /**** Tkapp Type Methods ****/
2751 Tkapp_Dealloc(PyObject
*self
)
2753 /*CHECK_TCL_APPARTMENT;*/
2755 Tcl_DeleteInterp(Tkapp_Interp(self
));
2762 Tkapp_GetAttr(PyObject
*self
, char *name
)
2764 return Py_FindMethod(Tkapp_methods
, self
, name
);
2767 static PyTypeObject Tkapp_Type
=
2769 PyVarObject_HEAD_INIT(NULL
, 0)
2770 "tkapp", /*tp_name */
2771 sizeof(TkappObject
), /*tp_basicsize */
2773 Tkapp_Dealloc
, /*tp_dealloc */
2775 Tkapp_GetAttr
, /*tp_getattr */
2779 0, /*tp_as_number */
2780 0, /*tp_as_sequence */
2781 0, /*tp_as_mapping */
2787 /**** Tkinter Module ****/
2791 int size
; /* current size */
2792 int maxsize
; /* allocated size */
2796 _bump(FlattenContext
* context
, int size
)
2798 /* expand tuple to hold (at least) size new items.
2799 return true if successful, false if an exception was raised */
2801 int maxsize
= context
->maxsize
* 2;
2803 if (maxsize
< context
->size
+ size
)
2804 maxsize
= context
->size
+ size
;
2806 context
->maxsize
= maxsize
;
2808 return _PyTuple_Resize(&context
->tuple
, maxsize
) >= 0;
2812 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
2814 /* add tuple or list to argument tuple (recursively) */
2819 PyErr_SetString(PyExc_ValueError
,
2820 "nesting too deep in _flatten");
2822 } else if (PyList_Check(item
)) {
2823 size
= PyList_GET_SIZE(item
);
2824 /* preallocate (assume no nesting) */
2825 if (context
->size
+ size
> context
->maxsize
&&
2826 !_bump(context
, size
))
2828 /* copy items to output tuple */
2829 for (i
= 0; i
< size
; i
++) {
2830 PyObject
*o
= PyList_GET_ITEM(item
, i
);
2831 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2832 if (!_flatten1(context
, o
, depth
+ 1))
2834 } else if (o
!= Py_None
) {
2835 if (context
->size
+ 1 > context
->maxsize
&&
2839 PyTuple_SET_ITEM(context
->tuple
,
2840 context
->size
++, o
);
2843 } else if (PyTuple_Check(item
)) {
2844 /* same, for tuples */
2845 size
= PyTuple_GET_SIZE(item
);
2846 if (context
->size
+ size
> context
->maxsize
&&
2847 !_bump(context
, size
))
2849 for (i
= 0; i
< size
; i
++) {
2850 PyObject
*o
= PyTuple_GET_ITEM(item
, i
);
2851 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2852 if (!_flatten1(context
, o
, depth
+ 1))
2854 } else if (o
!= Py_None
) {
2855 if (context
->size
+ 1 > context
->maxsize
&&
2859 PyTuple_SET_ITEM(context
->tuple
,
2860 context
->size
++, o
);
2864 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
2871 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
2873 FlattenContext context
;
2876 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
2879 context
.maxsize
= PySequence_Size(item
);
2880 if (context
.maxsize
<= 0)
2881 return PyTuple_New(0);
2883 context
.tuple
= PyTuple_New(context
.maxsize
);
2889 if (!_flatten1(&context
, item
,0))
2892 if (_PyTuple_Resize(&context
.tuple
, context
.size
))
2895 return context
.tuple
;
2899 Tkinter_Create(PyObject
*self
, PyObject
*args
)
2901 char *screenName
= NULL
;
2902 char *baseName
= NULL
;
2903 char *className
= NULL
;
2904 int interactive
= 0;
2905 int wantobjects
= 0;
2906 int wantTk
= 1; /* If false, then Tk_Init() doesn't get called */
2907 int sync
= 0; /* pass -sync to wish */
2908 char *use
= NULL
; /* pass -use to wish */
2910 baseName
= strrchr(Py_GetProgramName(), '/');
2911 if (baseName
!= NULL
)
2914 baseName
= Py_GetProgramName();
2917 if (!PyArg_ParseTuple(args
, "|zssiiiiz:create",
2918 &screenName
, &baseName
, &className
,
2919 &interactive
, &wantobjects
, &wantTk
,
2923 return (PyObject
*) Tkapp_New(screenName
, baseName
, className
,
2924 interactive
, wantobjects
, wantTk
,
2929 Tkinter_setbusywaitinterval(PyObject
*self
, PyObject
*args
)
2932 if (!PyArg_ParseTuple(args
, "i:setbusywaitinterval", &new_val
))
2935 PyErr_SetString(PyExc_ValueError
,
2936 "busywaitinterval must be >= 0");
2939 Tkinter_busywaitinterval
= new_val
;
2944 static char setbusywaitinterval_doc
[] =
2945 "setbusywaitinterval(n) -> None\n\
2947 Set the busy-wait interval in milliseconds between successive\n\
2948 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2949 It should be set to a divisor of the maximum time between\n\
2950 frames in an animation.";
2953 Tkinter_getbusywaitinterval(PyObject
*self
, PyObject
*args
)
2955 return PyInt_FromLong(Tkinter_busywaitinterval
);
2958 static char getbusywaitinterval_doc
[] =
2959 "getbusywaitinterval() -> int\n\
2961 Return the current busy-wait interval between successive\n\
2962 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2964 static PyMethodDef moduleMethods
[] =
2966 {"_flatten", Tkinter_Flatten
, METH_VARARGS
},
2967 {"create", Tkinter_Create
, METH_VARARGS
},
2968 #ifdef HAVE_CREATEFILEHANDLER
2969 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
2970 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
2972 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
2973 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
2974 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
2975 {"quit", Tkapp_Quit
, METH_VARARGS
},
2976 {"setbusywaitinterval",Tkinter_setbusywaitinterval
, METH_VARARGS
,
2977 setbusywaitinterval_doc
},
2978 {"getbusywaitinterval",(PyCFunction
)Tkinter_getbusywaitinterval
,
2979 METH_NOARGS
, getbusywaitinterval_doc
},
2983 #ifdef WAIT_FOR_STDIN
2985 static int stdin_ready
= 0;
2989 MyFileProc(void *clientData
, int mask
)
2996 static PyThreadState
*event_tstate
= NULL
;
3006 PyEval_RestoreThread(event_tstate
);
3011 tfile
= fileno(stdin
);
3012 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
3014 while (!errorInCmd
&& !stdin_ready
) {
3022 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3023 Py_BEGIN_ALLOW_THREADS
3024 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
3025 tcl_tstate
= event_tstate
;
3027 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
3030 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
3032 Sleep(Tkinter_busywaitinterval
);
3033 Py_END_ALLOW_THREADS
3035 result
= Tcl_DoOneEvent(0);
3042 Tcl_DeleteFileHandler(tfile
);
3046 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
3047 excInCmd
= valInCmd
= trbInCmd
= NULL
;
3051 PyEval_SaveThread();
3059 EnableEventHook(void)
3061 #ifdef WAIT_FOR_STDIN
3062 if (PyOS_InputHook
== NULL
) {
3064 event_tstate
= PyThreadState_Get();
3066 PyOS_InputHook
= EventHook
;
3072 DisableEventHook(void)
3074 #ifdef WAIT_FOR_STDIN
3075 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
3076 PyOS_InputHook
= NULL
;
3082 /* all errors will be checked in one fell swoop in init_tkinter() */
3084 ins_long(PyObject
*d
, char *name
, long val
)
3086 PyObject
*v
= PyInt_FromLong(val
);
3088 PyDict_SetItemString(d
, name
, v
);
3093 ins_string(PyObject
*d
, char *name
, char *val
)
3095 PyObject
*v
= PyString_FromString(val
);
3097 PyDict_SetItemString(d
, name
, v
);
3108 Py_Type(&Tkapp_Type
) = &PyType_Type
;
3111 tcl_lock
= PyThread_allocate_lock();
3114 m
= Py_InitModule("_tkinter", moduleMethods
);
3118 d
= PyModule_GetDict(m
);
3119 Tkinter_TclError
= PyErr_NewException("_tkinter.TclError", NULL
, NULL
);
3120 PyDict_SetItemString(d
, "TclError", Tkinter_TclError
);
3122 ins_long(d
, "READABLE", TCL_READABLE
);
3123 ins_long(d
, "WRITABLE", TCL_WRITABLE
);
3124 ins_long(d
, "EXCEPTION", TCL_EXCEPTION
);
3125 ins_long(d
, "WINDOW_EVENTS", TCL_WINDOW_EVENTS
);
3126 ins_long(d
, "FILE_EVENTS", TCL_FILE_EVENTS
);
3127 ins_long(d
, "TIMER_EVENTS", TCL_TIMER_EVENTS
);
3128 ins_long(d
, "IDLE_EVENTS", TCL_IDLE_EVENTS
);
3129 ins_long(d
, "ALL_EVENTS", TCL_ALL_EVENTS
);
3130 ins_long(d
, "DONT_WAIT", TCL_DONT_WAIT
);
3131 ins_string(d
, "TK_VERSION", TK_VERSION
);
3132 ins_string(d
, "TCL_VERSION", TCL_VERSION
);
3134 PyDict_SetItemString(d
, "TkappType", (PyObject
*)&Tkapp_Type
);
3136 Py_Type(&Tktt_Type
) = &PyType_Type
;
3137 PyDict_SetItemString(d
, "TkttType", (PyObject
*)&Tktt_Type
);
3139 Py_Type(&PyTclObject_Type
) = &PyType_Type
;
3140 PyDict_SetItemString(d
, "Tcl_Obj", (PyObject
*)&PyTclObject_Type
);
3143 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3144 * start waking up. Note that Tcl_FindExecutable will do this, this
3145 * code must be above it! The original warning from
3146 * tkMacOSXAppInit.c is copied below.
3148 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3149 * Tcl interpreter for now. It probably should work to do this
3150 * in the other order, but for now it doesn't seem to.
3153 Tk_MacOSXSetupTkNotifier();
3157 /* This helps the dynamic loader; in Unicode aware Tcl versions
3158 it also helps Tcl find its encodings. */
3159 Tcl_FindExecutable(Py_GetProgramName());
3161 if (PyErr_Occurred())
3165 /* This was not a good idea; through <Destroy> bindings,
3166 Tcl_Finalize() may invoke Python code but at that point the
3167 interpreter and thread state have already been destroyed! */
3168 Py_AtExit(Tcl_Finalize
);