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
939 Tcl_UniChar
*outbuf
= NULL
;
941 size_t allocsize
= ((size_t)size
) * sizeof(Tcl_UniChar
);
942 if (allocsize
>= size
)
943 outbuf
= (Tcl_UniChar
*)ckalloc(allocsize
);
944 /* Else overflow occurred, and we take the next exit */
949 for (i
= 0; i
< size
; i
++) {
950 if (inbuf
[i
] >= 0x10000) {
951 /* Tcl doesn't do UTF-16, yet. */
952 PyErr_SetString(PyExc_ValueError
,
953 "unsupported character");
954 ckfree(FREECAST outbuf
);
957 outbuf
[i
] = inbuf
[i
];
959 result
= Tcl_NewUnicodeObj(outbuf
, size
);
960 ckfree(FREECAST outbuf
);
963 return Tcl_NewUnicodeObj(inbuf
, size
);
968 else if(PyTclObject_Check(value
)) {
969 Tcl_Obj
*v
= ((PyTclObject
*)value
)->value
;
974 PyObject
*v
= PyObject_Str(value
);
984 FromObj(PyObject
* tkapp
, Tcl_Obj
*value
)
986 PyObject
*result
= NULL
;
987 TkappObject
*app
= (TkappObject
*)tkapp
;
989 if (value
->typePtr
== NULL
) {
990 /* If the result contains any bytes with the top bit set,
991 it's UTF-8 and we should decode it to Unicode */
992 #ifdef Py_USING_UNICODE
994 char *s
= value
->bytes
;
995 int len
= value
->length
;
996 for (i
= 0; i
< len
; i
++) {
997 if (value
->bytes
[i
] & 0x80)
1001 if (i
== value
->length
)
1002 result
= PyString_FromStringAndSize(s
, len
);
1004 /* Convert UTF-8 to Unicode string */
1005 result
= PyUnicode_DecodeUTF8(s
, len
, "strict");
1006 if (result
== NULL
) {
1008 result
= PyString_FromStringAndSize(s
, len
);
1012 result
= PyString_FromStringAndSize(value
->bytes
, value
->length
);
1017 if (value
->typePtr
== app
->BooleanType
) {
1018 result
= value
->internalRep
.longValue
? Py_True
: Py_False
;
1023 if (value
->typePtr
== app
->ByteArrayType
) {
1025 char *data
= (char*)Tcl_GetByteArrayFromObj(value
, &size
);
1026 return PyString_FromStringAndSize(data
, size
);
1029 if (value
->typePtr
== app
->DoubleType
) {
1030 return PyFloat_FromDouble(value
->internalRep
.doubleValue
);
1033 if (value
->typePtr
== app
->IntType
) {
1034 return PyInt_FromLong(value
->internalRep
.longValue
);
1037 if (value
->typePtr
== app
->ListType
) {
1043 status
= Tcl_ListObjLength(Tkapp_Interp(tkapp
), value
, &size
);
1044 if (status
== TCL_ERROR
)
1045 return Tkinter_Error(tkapp
);
1046 result
= PyTuple_New(size
);
1049 for (i
= 0; i
< size
; i
++) {
1050 status
= Tcl_ListObjIndex(Tkapp_Interp(tkapp
),
1051 value
, i
, &tcl_elem
);
1052 if (status
== TCL_ERROR
) {
1054 return Tkinter_Error(tkapp
);
1056 elem
= FromObj(tkapp
, tcl_elem
);
1061 PyTuple_SetItem(result
, i
, elem
);
1066 if (value
->typePtr
== app
->ProcBodyType
) {
1067 /* fall through: return tcl object. */
1070 if (value
->typePtr
== app
->StringType
) {
1071 #ifdef Py_USING_UNICODE
1072 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1078 size
= Tcl_GetCharLength(value
);
1079 result
= PyUnicode_FromUnicode(NULL
, size
);
1082 input
= Tcl_GetUnicode(value
);
1083 output
= PyUnicode_AS_UNICODE(result
);
1085 *output
++ = *input
++;
1088 return PyUnicode_FromUnicode(Tcl_GetUnicode(value
),
1089 Tcl_GetCharLength(value
));
1094 c
= Tcl_GetStringFromObj(value
, &size
);
1095 return PyString_FromStringAndSize(c
, size
);
1099 return newPyTclObject(value
);
1102 /* This mutex synchronizes inter-thread command calls. */
1104 TCL_DECLARE_MUTEX(call_mutex
)
1106 typedef struct Tkapp_CallEvent
{
1107 Tcl_Event ev
; /* Must be first */
1112 PyObject
**exc_type
, **exc_value
, **exc_tb
;
1117 Tkapp_CallDeallocArgs(Tcl_Obj
** objv
, Tcl_Obj
** objStore
, int objc
)
1120 for (i
= 0; i
< objc
; i
++)
1121 Tcl_DecrRefCount(objv
[i
]);
1122 if (objv
!= objStore
)
1123 ckfree(FREECAST objv
);
1126 /* Convert Python objects to Tcl objects. This must happen in the
1127 interpreter thread, which may or may not be the calling thread. */
1130 Tkapp_CallArgs(PyObject
*args
, Tcl_Obj
** objStore
, int *pobjc
)
1132 Tcl_Obj
**objv
= objStore
;
1137 else if (!PyTuple_Check(args
)) {
1138 objv
[0] = AsObj(args
);
1142 Tcl_IncrRefCount(objv
[0]);
1145 objc
= PyTuple_Size(args
);
1148 objv
= (Tcl_Obj
**)ckalloc(objc
* sizeof(char *));
1156 for (i
= 0; i
< objc
; i
++) {
1157 PyObject
*v
= PyTuple_GetItem(args
, i
);
1164 /* Reset objc, so it attempts to clear
1165 objects only up to i. */
1169 Tcl_IncrRefCount(objv
[i
]);
1175 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1179 /* Convert the results of a command call into a Python objects. */
1182 Tkapp_CallResult(TkappObject
*self
)
1184 PyObject
*res
= NULL
;
1185 if(self
->wantobjects
) {
1186 Tcl_Obj
*value
= Tcl_GetObjResult(self
->interp
);
1187 /* Not sure whether the IncrRef is necessary, but something
1188 may overwrite the interpreter result while we are
1190 Tcl_IncrRefCount(value
);
1191 res
= FromObj((PyObject
*)self
, value
);
1192 Tcl_DecrRefCount(value
);
1194 const char *s
= Tcl_GetStringResult(self
->interp
);
1197 /* If the result contains any bytes with the top bit set,
1198 it's UTF-8 and we should decode it to Unicode */
1199 #ifdef Py_USING_UNICODE
1200 while (*p
!= '\0') {
1207 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
1209 /* Convert UTF-8 to Unicode string */
1210 p
= strchr(p
, '\0');
1211 res
= PyUnicode_DecodeUTF8(s
, (int)(p
-s
), "strict");
1214 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
1218 p
= strchr(p
, '\0');
1219 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
1225 /* Tkapp_CallProc is the event procedure that is executed in the context of
1226 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1227 hold the Python lock. */
1230 Tkapp_CallProc(Tkapp_CallEvent
*e
, int flags
)
1232 Tcl_Obj
*objStore
[ARGSZ
];
1237 objv
= Tkapp_CallArgs(e
->args
, objStore
, &objc
);
1239 PyErr_Fetch(e
->exc_type
, e
->exc_value
, e
->exc_tb
);
1245 i
= Tcl_EvalObjv(e
->self
->interp
, objc
, objv
, e
->flags
);
1247 if (i
== TCL_ERROR
) {
1249 *(e
->exc_type
) = NULL
;
1250 *(e
->exc_tb
) = NULL
;
1251 *(e
->exc_value
) = PyObject_CallFunction(
1252 Tkinter_TclError
, "s",
1253 Tcl_GetStringResult(e
->self
->interp
));
1256 *(e
->res
) = Tkapp_CallResult(e
->self
);
1260 /* Wake up calling thread. */
1261 Tcl_MutexLock(&call_mutex
);
1262 Tcl_ConditionNotify(&e
->done
);
1263 Tcl_MutexUnlock(&call_mutex
);
1267 /* This is the main entry point for calling a Tcl command.
1268 It supports three cases, with regard to threading:
1269 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1270 the context of the calling thread.
1271 2. Tcl is threaded, caller of the command is in the interpreter thread:
1272 Execute the command in the calling thread. Since the Tcl lock will
1273 not be used, we can merge that with case 1.
1274 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1275 the interpreter thread. Allocation of Tcl objects needs to occur in the
1276 interpreter thread, so we ship the PyObject* args to the target thread,
1277 and perform processing there. */
1280 Tkapp_Call(PyObject
*selfptr
, PyObject
*args
)
1282 Tcl_Obj
*objStore
[ARGSZ
];
1283 Tcl_Obj
**objv
= NULL
;
1285 PyObject
*res
= NULL
;
1286 TkappObject
*self
= (TkappObject
*)selfptr
;
1287 int flags
= TCL_EVAL_DIRECT
| TCL_EVAL_GLOBAL
;
1289 /* If args is a single tuple, replace with contents of tuple */
1290 if (1 == PyTuple_Size(args
)){
1291 PyObject
* item
= PyTuple_GetItem(args
, 0);
1292 if (PyTuple_Check(item
))
1296 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1297 /* We cannot call the command directly. Instead, we must
1298 marshal the parameters to the interpreter thread. */
1299 Tkapp_CallEvent
*ev
;
1300 PyObject
*exc_type
, *exc_value
, *exc_tb
;
1301 if (!WaitForMainloop(self
))
1303 ev
= (Tkapp_CallEvent
*)ckalloc(sizeof(Tkapp_CallEvent
));
1304 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CallProc
;
1308 ev
->exc_type
= &exc_type
;
1309 ev
->exc_value
= &exc_value
;
1310 ev
->exc_tb
= &exc_tb
;
1311 ev
->done
= (Tcl_Condition
)0;
1313 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
, &call_mutex
);
1317 PyErr_Restore(exc_type
, exc_value
, exc_tb
);
1319 PyErr_SetObject(Tkinter_TclError
, exc_value
);
1326 objv
= Tkapp_CallArgs(args
, objStore
, &objc
);
1332 i
= Tcl_EvalObjv(self
->interp
, objc
, objv
, flags
);
1337 Tkinter_Error(selfptr
);
1339 res
= Tkapp_CallResult(self
);
1343 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1350 Tkapp_GlobalCall(PyObject
*self
, PyObject
*args
)
1352 /* Could do the same here as for Tkapp_Call(), but this is not used
1353 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1354 way for the user to do what all its Global* variants do (save and
1355 reset the scope pointer, call the local version, restore the saved
1359 PyObject
*res
= NULL
;
1361 CHECK_TCL_APPARTMENT
;
1367 err
= Tcl_GlobalEval(Tkapp_Interp(self
), cmd
);
1369 if (err
== TCL_ERROR
)
1370 res
= Tkinter_Error(self
);
1372 res
= PyString_FromString(Tkapp_Result(self
));
1381 Tkapp_Eval(PyObject
*self
, PyObject
*args
)
1384 PyObject
*res
= NULL
;
1387 if (!PyArg_ParseTuple(args
, "s:eval", &script
))
1390 CHECK_TCL_APPARTMENT
;
1393 err
= Tcl_Eval(Tkapp_Interp(self
), script
);
1395 if (err
== TCL_ERROR
)
1396 res
= Tkinter_Error(self
);
1398 res
= PyString_FromString(Tkapp_Result(self
));
1404 Tkapp_GlobalEval(PyObject
*self
, PyObject
*args
)
1407 PyObject
*res
= NULL
;
1410 if (!PyArg_ParseTuple(args
, "s:globaleval", &script
))
1413 CHECK_TCL_APPARTMENT
;
1416 err
= Tcl_GlobalEval(Tkapp_Interp(self
), script
);
1418 if (err
== TCL_ERROR
)
1419 res
= Tkinter_Error(self
);
1421 res
= PyString_FromString(Tkapp_Result(self
));
1427 Tkapp_EvalFile(PyObject
*self
, PyObject
*args
)
1430 PyObject
*res
= NULL
;
1433 if (!PyArg_ParseTuple(args
, "s:evalfile", &fileName
))
1436 CHECK_TCL_APPARTMENT
;
1439 err
= Tcl_EvalFile(Tkapp_Interp(self
), fileName
);
1441 if (err
== TCL_ERROR
)
1442 res
= Tkinter_Error(self
);
1445 res
= PyString_FromString(Tkapp_Result(self
));
1451 Tkapp_Record(PyObject
*self
, PyObject
*args
)
1454 PyObject
*res
= NULL
;
1457 if (!PyArg_ParseTuple(args
, "s", &script
))
1460 CHECK_TCL_APPARTMENT
;
1463 err
= Tcl_RecordAndEval(Tkapp_Interp(self
), script
, TCL_NO_EVAL
);
1465 if (err
== TCL_ERROR
)
1466 res
= Tkinter_Error(self
);
1468 res
= PyString_FromString(Tkapp_Result(self
));
1474 Tkapp_AddErrorInfo(PyObject
*self
, PyObject
*args
)
1478 if (!PyArg_ParseTuple(args
, "s:adderrorinfo", &msg
))
1480 CHECK_TCL_APPARTMENT
;
1483 Tcl_AddErrorInfo(Tkapp_Interp(self
), msg
);
1492 /** Tcl Variable **/
1494 TCL_DECLARE_MUTEX(var_mutex
)
1496 typedef PyObject
* (*EventFunc
)(PyObject
*, PyObject
*args
, int flags
);
1497 typedef struct VarEvent
{
1498 Tcl_Event ev
; /* must be first */
1504 PyObject
**exc_type
;
1510 varname_converter(PyObject
*in
, void *_out
)
1512 char **out
= (char**)_out
;
1513 if (PyString_Check(in
)) {
1514 *out
= PyString_AsString(in
);
1517 if (PyTclObject_Check(in
)) {
1518 *out
= PyTclObject_TclString(in
);
1521 /* XXX: Should give diagnostics. */
1526 var_perform(VarEvent
*ev
)
1528 *(ev
->res
) = ev
->func(ev
->self
, ev
->args
, ev
->flags
);
1530 PyObject
*exc
, *val
, *tb
;
1531 PyErr_Fetch(&exc
, &val
, &tb
);
1532 PyErr_NormalizeException(&exc
, &val
, &tb
);
1533 *(ev
->exc_type
) = exc
;
1534 *(ev
->exc_val
) = val
;
1541 var_proc(VarEvent
* ev
, int flags
)
1545 Tcl_MutexLock(&var_mutex
);
1546 Tcl_ConditionNotify(&ev
->cond
);
1547 Tcl_MutexUnlock(&var_mutex
);
1553 var_invoke(EventFunc func
, PyObject
*selfptr
, PyObject
*args
, int flags
)
1555 TkappObject
*self
= (TkappObject
*)selfptr
;
1557 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1558 TkappObject
*self
= (TkappObject
*)selfptr
;
1560 PyObject
*res
, *exc_type
, *exc_val
;
1562 /* The current thread is not the interpreter thread. Marshal
1563 the call to the interpreter thread, then wait for
1565 if (!WaitForMainloop(self
))
1568 ev
= (VarEvent
*)ckalloc(sizeof(VarEvent
));
1575 ev
->exc_type
= &exc_type
;
1576 ev
->exc_val
= &exc_val
;
1578 ev
->ev
.proc
= (Tcl_EventProc
*)var_proc
;
1579 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->cond
, &var_mutex
);
1581 PyErr_SetObject(exc_type
, exc_val
);
1582 Py_DECREF(exc_type
);
1589 /* Tcl is not threaded, or this is the interpreter thread. */
1590 return func(selfptr
, args
, flags
);
1594 SetVar(PyObject
*self
, PyObject
*args
, int flags
)
1596 char *name1
, *name2
;
1598 PyObject
*res
= NULL
;
1599 Tcl_Obj
*newval
, *ok
;
1601 if (PyArg_ParseTuple(args
, "O&O:setvar",
1602 varname_converter
, &name1
, &newValue
)) {
1603 /* XXX Acquire tcl lock??? */
1604 newval
= AsObj(newValue
);
1608 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, NULL
,
1612 Tkinter_Error(self
);
1621 if (PyArg_ParseTuple(args
, "ssO:setvar",
1622 &name1
, &name2
, &newValue
)) {
1623 /* XXX must hold tcl lock already??? */
1624 newval
= AsObj(newValue
);
1626 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, name2
, newval
, flags
);
1629 Tkinter_Error(self
);
1644 Tkapp_SetVar(PyObject
*self
, PyObject
*args
)
1646 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1650 Tkapp_GlobalSetVar(PyObject
*self
, PyObject
*args
)
1652 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1658 GetVar(PyObject
*self
, PyObject
*args
, int flags
)
1660 char *name1
, *name2
=NULL
;
1661 PyObject
*res
= NULL
;
1664 if (!PyArg_ParseTuple(args
, "O&|s:getvar",
1665 varname_converter
, &name1
, &name2
))
1669 tres
= Tcl_GetVar2Ex(Tkapp_Interp(self
), name1
, name2
, flags
);
1672 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
1674 if (((TkappObject
*)self
)->wantobjects
) {
1675 res
= FromObj(self
, tres
);
1678 res
= PyString_FromString(Tcl_GetString(tres
));
1686 Tkapp_GetVar(PyObject
*self
, PyObject
*args
)
1688 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1692 Tkapp_GlobalGetVar(PyObject
*self
, PyObject
*args
)
1694 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1700 UnsetVar(PyObject
*self
, PyObject
*args
, int flags
)
1702 char *name1
, *name2
=NULL
;
1704 PyObject
*res
= NULL
;
1706 if (!PyArg_ParseTuple(args
, "s|s:unsetvar", &name1
, &name2
))
1710 code
= Tcl_UnsetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
1712 if (code
== TCL_ERROR
)
1713 res
= Tkinter_Error(self
);
1723 Tkapp_UnsetVar(PyObject
*self
, PyObject
*args
)
1725 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1729 Tkapp_GlobalUnsetVar(PyObject
*self
, PyObject
*args
)
1731 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1736 /** Tcl to Python **/
1739 Tkapp_GetInt(PyObject
*self
, PyObject
*args
)
1744 if (PyTuple_Size(args
) == 1) {
1745 PyObject
* o
= PyTuple_GetItem(args
, 0);
1746 if (PyInt_Check(o
)) {
1751 if (!PyArg_ParseTuple(args
, "s:getint", &s
))
1753 if (Tcl_GetInt(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1754 return Tkinter_Error(self
);
1755 return Py_BuildValue("i", v
);
1759 Tkapp_GetDouble(PyObject
*self
, PyObject
*args
)
1764 if (PyTuple_Size(args
) == 1) {
1765 PyObject
*o
= PyTuple_GetItem(args
, 0);
1766 if (PyFloat_Check(o
)) {
1771 if (!PyArg_ParseTuple(args
, "s:getdouble", &s
))
1773 if (Tcl_GetDouble(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1774 return Tkinter_Error(self
);
1775 return Py_BuildValue("d", v
);
1779 Tkapp_GetBoolean(PyObject
*self
, PyObject
*args
)
1784 if (PyTuple_Size(args
) == 1) {
1785 PyObject
*o
= PyTuple_GetItem(args
, 0);
1786 if (PyInt_Check(o
)) {
1791 if (!PyArg_ParseTuple(args
, "s:getboolean", &s
))
1793 if (Tcl_GetBoolean(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1794 return Tkinter_Error(self
);
1795 return PyBool_FromLong(v
);
1799 Tkapp_ExprString(PyObject
*self
, PyObject
*args
)
1802 PyObject
*res
= NULL
;
1805 if (!PyArg_ParseTuple(args
, "s:exprstring", &s
))
1808 CHECK_TCL_APPARTMENT
;
1811 retval
= Tcl_ExprString(Tkapp_Interp(self
), s
);
1813 if (retval
== TCL_ERROR
)
1814 res
= Tkinter_Error(self
);
1816 res
= Py_BuildValue("s", Tkapp_Result(self
));
1822 Tkapp_ExprLong(PyObject
*self
, PyObject
*args
)
1825 PyObject
*res
= NULL
;
1829 if (!PyArg_ParseTuple(args
, "s:exprlong", &s
))
1832 CHECK_TCL_APPARTMENT
;
1835 retval
= Tcl_ExprLong(Tkapp_Interp(self
), s
, &v
);
1837 if (retval
== TCL_ERROR
)
1838 res
= Tkinter_Error(self
);
1840 res
= Py_BuildValue("l", v
);
1846 Tkapp_ExprDouble(PyObject
*self
, PyObject
*args
)
1849 PyObject
*res
= NULL
;
1853 if (!PyArg_ParseTuple(args
, "s:exprdouble", &s
))
1855 CHECK_TCL_APPARTMENT
;
1856 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1858 retval
= Tcl_ExprDouble(Tkapp_Interp(self
), s
, &v
);
1860 PyFPE_END_PROTECT(retval
)
1861 if (retval
== TCL_ERROR
)
1862 res
= Tkinter_Error(self
);
1864 res
= Py_BuildValue("d", v
);
1870 Tkapp_ExprBoolean(PyObject
*self
, PyObject
*args
)
1873 PyObject
*res
= NULL
;
1877 if (!PyArg_ParseTuple(args
, "s:exprboolean", &s
))
1879 CHECK_TCL_APPARTMENT
;
1881 retval
= Tcl_ExprBoolean(Tkapp_Interp(self
), s
, &v
);
1883 if (retval
== TCL_ERROR
)
1884 res
= Tkinter_Error(self
);
1886 res
= Py_BuildValue("i", v
);
1894 Tkapp_SplitList(PyObject
*self
, PyObject
*args
)
1902 if (PyTuple_Size(args
) == 1) {
1903 v
= PyTuple_GetItem(args
, 0);
1904 if (PyTuple_Check(v
)) {
1909 if (!PyArg_ParseTuple(args
, "et:splitlist", "utf-8", &list
))
1912 if (Tcl_SplitList(Tkapp_Interp(self
), list
,
1913 &argc
, &argv
) == TCL_ERROR
) {
1915 return Tkinter_Error(self
);
1918 if (!(v
= PyTuple_New(argc
)))
1921 for (i
= 0; i
< argc
; i
++) {
1922 PyObject
*s
= PyString_FromString(argv
[i
]);
1923 if (!s
|| PyTuple_SetItem(v
, i
, s
)) {
1931 ckfree(FREECAST argv
);
1937 Tkapp_Split(PyObject
*self
, PyObject
*args
)
1942 if (PyTuple_Size(args
) == 1) {
1943 PyObject
* o
= PyTuple_GetItem(args
, 0);
1944 if (PyTuple_Check(o
)) {
1949 if (!PyArg_ParseTuple(args
, "et:split", "utf-8", &list
))
1957 Tkapp_Merge(PyObject
*self
, PyObject
*args
)
1959 char *s
= Merge(args
);
1960 PyObject
*res
= NULL
;
1963 res
= PyString_FromString(s
);
1974 /* Client data struct */
1978 } PythonCmd_ClientData
;
1981 PythonCmd_Error(Tcl_Interp
*interp
)
1984 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
1989 /* This is the Tcl command that acts as a wrapper for Python
1990 * function or method.
1993 PythonCmd(ClientData clientData
, Tcl_Interp
*interp
, int argc
, char *argv
[])
1995 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
1996 PyObject
*self
, *func
, *arg
, *res
;
2002 /* TBD: no error checking here since we know, via the
2003 * Tkapp_CreateCommand() that the client data is a two-tuple
2008 /* Create argument list (argv1, ..., argvN) */
2009 if (!(arg
= PyTuple_New(argc
- 1)))
2010 return PythonCmd_Error(interp
);
2012 for (i
= 0; i
< (argc
- 1); i
++) {
2013 PyObject
*s
= PyString_FromString(argv
[i
+ 1]);
2014 if (!s
|| PyTuple_SetItem(arg
, i
, s
)) {
2016 return PythonCmd_Error(interp
);
2019 res
= PyEval_CallObject(func
, arg
);
2023 return PythonCmd_Error(interp
);
2025 obj_res
= AsObj(res
);
2026 if (obj_res
== NULL
) {
2028 return PythonCmd_Error(interp
);
2031 Tcl_SetObjResult(Tkapp_Interp(self
), obj_res
);
2043 PythonCmdDelete(ClientData clientData
)
2045 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
2048 Py_XDECREF(data
->self
);
2049 Py_XDECREF(data
->func
);
2057 TCL_DECLARE_MUTEX(command_mutex
)
2059 typedef struct CommandEvent
{
2070 Tkapp_CommandProc(CommandEvent
*ev
, int flags
)
2073 *ev
->status
= Tcl_CreateCommand(
2074 ev
->interp
, ev
->name
, PythonCmd
,
2075 ev
->data
, PythonCmdDelete
) == NULL
;
2077 *ev
->status
= Tcl_DeleteCommand(ev
->interp
, ev
->name
);
2078 Tcl_MutexLock(&command_mutex
);
2079 Tcl_ConditionNotify(&ev
->done
);
2080 Tcl_MutexUnlock(&command_mutex
);
2085 Tkapp_CreateCommand(PyObject
*selfptr
, PyObject
*args
)
2087 TkappObject
*self
= (TkappObject
*)selfptr
;
2088 PythonCmd_ClientData
*data
;
2093 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
2095 if (!PyCallable_Check(func
)) {
2096 PyErr_SetString(PyExc_TypeError
, "command not callable");
2101 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread() &&
2102 !WaitForMainloop(self
))
2106 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
2108 return PyErr_NoMemory();
2111 data
->self
= selfptr
;
2114 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2115 CommandEvent
*ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2116 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2117 ev
->interp
= self
->interp
;
2120 ev
->data
= (ClientData
)data
;
2123 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
, &command_mutex
);
2127 err
= Tcl_CreateCommand(
2128 Tkapp_Interp(self
), cmdName
, PythonCmd
,
2129 (ClientData
)data
, PythonCmdDelete
) == NULL
;
2133 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
2145 Tkapp_DeleteCommand(PyObject
*selfptr
, PyObject
*args
)
2147 TkappObject
*self
= (TkappObject
*)selfptr
;
2151 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
2153 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2155 ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2156 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2157 ev
->interp
= self
->interp
;
2162 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &ev
->done
,
2167 err
= Tcl_DeleteCommand(self
->interp
, cmdName
);
2171 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
2180 #ifdef HAVE_CREATEFILEHANDLER
2181 /** File Handler **/
2183 typedef struct _fhcdata
{
2187 struct _fhcdata
*next
;
2188 } FileHandler_ClientData
;
2190 static FileHandler_ClientData
*HeadFHCD
;
2192 static FileHandler_ClientData
*
2193 NewFHCD(PyObject
*func
, PyObject
*file
, int id
)
2195 FileHandler_ClientData
*p
;
2196 p
= PyMem_NEW(FileHandler_ClientData
, 1);
2212 FileHandler_ClientData
*p
, **pp
;
2215 while ((p
= *pp
) != NULL
) {
2218 Py_XDECREF(p
->func
);
2219 Py_XDECREF(p
->file
);
2228 FileHandler(ClientData clientData
, int mask
)
2230 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
2231 PyObject
*func
, *file
, *arg
, *res
;
2237 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
2238 res
= PyEval_CallObject(func
, arg
);
2243 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2250 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
2251 /* args is (file, mask, func) */
2253 FileHandler_ClientData
*data
;
2254 PyObject
*file
, *func
;
2257 if (!self
&& Py_Py3kWarningFlag
) {
2258 if (PyErr_Warn(PyExc_DeprecationWarning
,
2259 "_tkinter.createfilehandler is gone in 3.x") < 0)
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 (!self
&& Py_Py3kWarningFlag
) {
2308 if (PyErr_Warn(PyExc_DeprecationWarning
,
2309 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2313 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
2317 if (!self
&& !tcl_lock
) {
2318 /* We don't have the Tcl lock since Tcl is threaded. */
2319 PyErr_SetString(PyExc_RuntimeError
,
2320 "_tkinter.deletefilehandler not supported "
2321 "for threaded Tcl");
2327 CHECK_TCL_APPARTMENT
;
2330 tfile
= PyObject_AsFileDescriptor(file
);
2336 /* Ought to check for null Tcl_File object... */
2338 Tcl_DeleteFileHandler(tfile
);
2343 #endif /* HAVE_CREATEFILEHANDLER */
2346 /**** Tktt Object (timer token) ****/
2348 static PyTypeObject Tktt_Type
;
2352 Tcl_TimerToken token
;
2357 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
2359 TkttObject
*v
= (TkttObject
*)self
;
2360 PyObject
*func
= v
->func
;
2362 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
2364 if (v
->token
!= NULL
) {
2365 Tcl_DeleteTimerHandler(v
->token
);
2371 Py_DECREF(v
); /* See Tktt_New() */
2377 static PyMethodDef Tktt_methods
[] =
2379 {"deletetimerhandler", Tktt_DeleteTimerHandler
, METH_VARARGS
},
2384 Tktt_New(PyObject
*func
)
2388 v
= PyObject_New(TkttObject
, &Tktt_Type
);
2396 /* Extra reference, deleted when called or when handler is deleted */
2402 Tktt_Dealloc(PyObject
*self
)
2404 TkttObject
*v
= (TkttObject
*)self
;
2405 PyObject
*func
= v
->func
;
2413 Tktt_Repr(PyObject
*self
)
2415 TkttObject
*v
= (TkttObject
*)self
;
2418 PyOS_snprintf(buf
, sizeof(buf
), "<tktimertoken at %p%s>", v
,
2419 v
->func
== NULL
? ", handler deleted" : "");
2420 return PyString_FromString(buf
);
2424 Tktt_GetAttr(PyObject
*self
, char *name
)
2426 return Py_FindMethod(Tktt_methods
, self
, name
);
2429 static PyTypeObject Tktt_Type
=
2431 PyVarObject_HEAD_INIT(NULL
, 0)
2432 "tktimertoken", /*tp_name */
2433 sizeof(TkttObject
), /*tp_basicsize */
2435 Tktt_Dealloc
, /*tp_dealloc */
2437 Tktt_GetAttr
, /*tp_getattr */
2440 Tktt_Repr
, /*tp_repr */
2441 0, /*tp_as_number */
2442 0, /*tp_as_sequence */
2443 0, /*tp_as_mapping */
2449 /** Timer Handler **/
2452 TimerHandler(ClientData clientData
)
2454 TkttObject
*v
= (TkttObject
*)clientData
;
2455 PyObject
*func
= v
->func
;
2465 res
= PyEval_CallObject(func
, NULL
);
2467 Py_DECREF(v
); /* See Tktt_New() */
2471 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2480 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
2486 if (!self
&& Py_Py3kWarningFlag
) {
2487 if (PyErr_Warn(PyExc_DeprecationWarning
,
2488 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2492 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler",
2493 &milliseconds
, &func
))
2495 if (!PyCallable_Check(func
)) {
2496 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2501 if (!self
&& !tcl_lock
) {
2502 /* We don't have the Tcl lock since Tcl is threaded. */
2503 PyErr_SetString(PyExc_RuntimeError
,
2504 "_tkinter.createtimerhandler not supported "
2505 "for threaded Tcl");
2511 CHECK_TCL_APPARTMENT
;
2516 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
2520 return (PyObject
*) v
;
2527 Tkapp_MainLoop(PyObject
*selfptr
, PyObject
*args
)
2530 TkappObject
*self
= (TkappObject
*)selfptr
;
2532 PyThreadState
*tstate
= PyThreadState_Get();
2535 if (!self
&& Py_Py3kWarningFlag
) {
2536 if (PyErr_Warn(PyExc_DeprecationWarning
,
2537 "_tkinter.mainloop is gone in 3.x") < 0)
2541 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
2545 if (!self
&& !tcl_lock
) {
2546 /* We don't have the Tcl lock since Tcl is threaded. */
2547 PyErr_SetString(PyExc_RuntimeError
,
2548 "_tkinter.mainloop not supported "
2549 "for threaded Tcl");
2555 CHECK_TCL_APPARTMENT
;
2556 self
->dispatching
= 1;
2560 while (Tk_GetNumMainWindows() > threshold
&&
2567 if (self
&& self
->threaded
) {
2568 /* Allow other Python threads to run. */
2570 result
= Tcl_DoOneEvent(0);
2574 Py_BEGIN_ALLOW_THREADS
2575 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
2576 tcl_tstate
= tstate
;
2577 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
2579 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
2581 Sleep(Tkinter_busywaitinterval
);
2582 Py_END_ALLOW_THREADS
2585 result
= Tcl_DoOneEvent(0);
2588 if (PyErr_CheckSignals() != 0) {
2590 self
->dispatching
= 0;
2597 self
->dispatching
= 0;
2602 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2603 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2611 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
2616 if (!self
&& Py_Py3kWarningFlag
) {
2617 if (PyErr_Warn(PyExc_DeprecationWarning
,
2618 "_tkinter.dooneevent is gone in 3.x") < 0)
2622 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
2626 rv
= Tcl_DoOneEvent(flags
);
2628 return Py_BuildValue("i", rv
);
2632 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
2635 if (!self
&& Py_Py3kWarningFlag
) {
2636 if (PyErr_Warn(PyExc_DeprecationWarning
,
2637 "_tkinter.createfilehandler is gone in 3.x") < 0)
2641 if (!PyArg_ParseTuple(args
, ":quit"))
2650 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
2653 if (!PyArg_ParseTuple(args
, ":interpaddr"))
2656 return PyInt_FromLong((long)Tkapp_Interp(self
));
2660 Tkapp_TkInit(PyObject
*self
, PyObject
*args
)
2662 static int has_failed
;
2663 Tcl_Interp
*interp
= Tkapp_Interp(self
);
2664 Tk_Window main_window
;
2665 const char * _tk_exists
= NULL
;
2667 main_window
= Tk_MainWindow(interp
);
2669 /* In all current versions of Tk (including 8.4.13), Tk_Init
2670 deadlocks on the second call when the first call failed.
2671 To avoid the deadlock, we just refuse the second call through
2672 a static variable. */
2674 PyErr_SetString(Tkinter_TclError
,
2675 "Calling Tk_Init again after a previous call failed might deadlock");
2679 /* We want to guard against calling Tk_Init() multiple times */
2680 CHECK_TCL_APPARTMENT
;
2682 err
= Tcl_Eval(Tkapp_Interp(self
), "info exists tk_version");
2684 if (err
== TCL_ERROR
) {
2685 /* This sets an exception, but we cannot return right
2686 away because we need to exit the overlap first. */
2687 Tkinter_Error(self
);
2689 _tk_exists
= Tkapp_Result(self
);
2692 if (err
== TCL_ERROR
) {
2695 if (_tk_exists
== NULL
|| strcmp(_tk_exists
, "1") != 0) {
2696 if (Tk_Init(interp
) == TCL_ERROR
) {
2697 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
2707 Tkapp_WantObjects(PyObject
*self
, PyObject
*args
)
2710 int wantobjects
= -1;
2711 if (!PyArg_ParseTuple(args
, "|i:wantobjects", &wantobjects
))
2713 if (wantobjects
== -1)
2714 return PyBool_FromLong(((TkappObject
*)self
)->wantobjects
);
2715 ((TkappObject
*)self
)->wantobjects
= wantobjects
;
2722 Tkapp_WillDispatch(PyObject
*self
, PyObject
*args
)
2725 ((TkappObject
*)self
)->dispatching
= 1;
2732 /**** Tkapp Method List ****/
2734 static PyMethodDef Tkapp_methods
[] =
2736 {"willdispatch", Tkapp_WillDispatch
, METH_NOARGS
},
2737 {"wantobjects", Tkapp_WantObjects
, METH_VARARGS
},
2738 {"call", Tkapp_Call
, METH_VARARGS
},
2739 {"globalcall", Tkapp_GlobalCall
, METH_VARARGS
},
2740 {"eval", Tkapp_Eval
, METH_VARARGS
},
2741 {"globaleval", Tkapp_GlobalEval
, METH_VARARGS
},
2742 {"evalfile", Tkapp_EvalFile
, METH_VARARGS
},
2743 {"record", Tkapp_Record
, METH_VARARGS
},
2744 {"adderrorinfo", Tkapp_AddErrorInfo
, METH_VARARGS
},
2745 {"setvar", Tkapp_SetVar
, METH_VARARGS
},
2746 {"globalsetvar", Tkapp_GlobalSetVar
, METH_VARARGS
},
2747 {"getvar", Tkapp_GetVar
, METH_VARARGS
},
2748 {"globalgetvar", Tkapp_GlobalGetVar
, METH_VARARGS
},
2749 {"unsetvar", Tkapp_UnsetVar
, METH_VARARGS
},
2750 {"globalunsetvar", Tkapp_GlobalUnsetVar
, METH_VARARGS
},
2751 {"getint", Tkapp_GetInt
, METH_VARARGS
},
2752 {"getdouble", Tkapp_GetDouble
, METH_VARARGS
},
2753 {"getboolean", Tkapp_GetBoolean
, METH_VARARGS
},
2754 {"exprstring", Tkapp_ExprString
, METH_VARARGS
},
2755 {"exprlong", Tkapp_ExprLong
, METH_VARARGS
},
2756 {"exprdouble", Tkapp_ExprDouble
, METH_VARARGS
},
2757 {"exprboolean", Tkapp_ExprBoolean
, METH_VARARGS
},
2758 {"splitlist", Tkapp_SplitList
, METH_VARARGS
},
2759 {"split", Tkapp_Split
, METH_VARARGS
},
2760 {"merge", Tkapp_Merge
, METH_VARARGS
},
2761 {"createcommand", Tkapp_CreateCommand
, METH_VARARGS
},
2762 {"deletecommand", Tkapp_DeleteCommand
, METH_VARARGS
},
2763 #ifdef HAVE_CREATEFILEHANDLER
2764 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
2765 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
2767 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
2768 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
2769 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
2770 {"quit", Tkapp_Quit
, METH_VARARGS
},
2771 {"interpaddr", Tkapp_InterpAddr
, METH_VARARGS
},
2772 {"loadtk", Tkapp_TkInit
, METH_NOARGS
},
2778 /**** Tkapp Type Methods ****/
2781 Tkapp_Dealloc(PyObject
*self
)
2783 /*CHECK_TCL_APPARTMENT;*/
2785 Tcl_DeleteInterp(Tkapp_Interp(self
));
2792 Tkapp_GetAttr(PyObject
*self
, char *name
)
2794 return Py_FindMethod(Tkapp_methods
, self
, name
);
2797 static PyTypeObject Tkapp_Type
=
2799 PyVarObject_HEAD_INIT(NULL
, 0)
2800 "tkapp", /*tp_name */
2801 sizeof(TkappObject
), /*tp_basicsize */
2803 Tkapp_Dealloc
, /*tp_dealloc */
2805 Tkapp_GetAttr
, /*tp_getattr */
2809 0, /*tp_as_number */
2810 0, /*tp_as_sequence */
2811 0, /*tp_as_mapping */
2817 /**** Tkinter Module ****/
2821 int size
; /* current size */
2822 int maxsize
; /* allocated size */
2826 _bump(FlattenContext
* context
, int size
)
2828 /* expand tuple to hold (at least) size new items.
2829 return true if successful, false if an exception was raised */
2831 int maxsize
= context
->maxsize
* 2;
2833 if (maxsize
< context
->size
+ size
)
2834 maxsize
= context
->size
+ size
;
2836 context
->maxsize
= maxsize
;
2838 return _PyTuple_Resize(&context
->tuple
, maxsize
) >= 0;
2842 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
2844 /* add tuple or list to argument tuple (recursively) */
2849 PyErr_SetString(PyExc_ValueError
,
2850 "nesting too deep in _flatten");
2852 } else if (PyList_Check(item
)) {
2853 size
= PyList_GET_SIZE(item
);
2854 /* preallocate (assume no nesting) */
2855 if (context
->size
+ size
> context
->maxsize
&&
2856 !_bump(context
, size
))
2858 /* copy items to output tuple */
2859 for (i
= 0; i
< size
; i
++) {
2860 PyObject
*o
= PyList_GET_ITEM(item
, i
);
2861 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2862 if (!_flatten1(context
, o
, depth
+ 1))
2864 } else if (o
!= Py_None
) {
2865 if (context
->size
+ 1 > context
->maxsize
&&
2869 PyTuple_SET_ITEM(context
->tuple
,
2870 context
->size
++, o
);
2873 } else if (PyTuple_Check(item
)) {
2874 /* same, for tuples */
2875 size
= PyTuple_GET_SIZE(item
);
2876 if (context
->size
+ size
> context
->maxsize
&&
2877 !_bump(context
, size
))
2879 for (i
= 0; i
< size
; i
++) {
2880 PyObject
*o
= PyTuple_GET_ITEM(item
, i
);
2881 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2882 if (!_flatten1(context
, o
, depth
+ 1))
2884 } else if (o
!= Py_None
) {
2885 if (context
->size
+ 1 > context
->maxsize
&&
2889 PyTuple_SET_ITEM(context
->tuple
,
2890 context
->size
++, o
);
2894 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
2901 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
2903 FlattenContext context
;
2906 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
2909 context
.maxsize
= PySequence_Size(item
);
2910 if (context
.maxsize
< 0)
2912 if (context
.maxsize
== 0)
2913 return PyTuple_New(0);
2915 context
.tuple
= PyTuple_New(context
.maxsize
);
2921 if (!_flatten1(&context
, item
,0))
2924 if (_PyTuple_Resize(&context
.tuple
, context
.size
))
2927 return context
.tuple
;
2931 Tkinter_Create(PyObject
*self
, PyObject
*args
)
2933 char *screenName
= NULL
;
2934 char *baseName
= NULL
;
2935 char *className
= NULL
;
2936 int interactive
= 0;
2937 int wantobjects
= 0;
2938 int wantTk
= 1; /* If false, then Tk_Init() doesn't get called */
2939 int sync
= 0; /* pass -sync to wish */
2940 char *use
= NULL
; /* pass -use to wish */
2942 baseName
= strrchr(Py_GetProgramName(), '/');
2943 if (baseName
!= NULL
)
2946 baseName
= Py_GetProgramName();
2949 if (!PyArg_ParseTuple(args
, "|zssiiiiz:create",
2950 &screenName
, &baseName
, &className
,
2951 &interactive
, &wantobjects
, &wantTk
,
2955 return (PyObject
*) Tkapp_New(screenName
, baseName
, className
,
2956 interactive
, wantobjects
, wantTk
,
2961 Tkinter_setbusywaitinterval(PyObject
*self
, PyObject
*args
)
2964 if (!PyArg_ParseTuple(args
, "i:setbusywaitinterval", &new_val
))
2967 PyErr_SetString(PyExc_ValueError
,
2968 "busywaitinterval must be >= 0");
2971 Tkinter_busywaitinterval
= new_val
;
2976 static char setbusywaitinterval_doc
[] =
2977 "setbusywaitinterval(n) -> None\n\
2979 Set the busy-wait interval in milliseconds between successive\n\
2980 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2981 It should be set to a divisor of the maximum time between\n\
2982 frames in an animation.";
2985 Tkinter_getbusywaitinterval(PyObject
*self
, PyObject
*args
)
2987 return PyInt_FromLong(Tkinter_busywaitinterval
);
2990 static char getbusywaitinterval_doc
[] =
2991 "getbusywaitinterval() -> int\n\
2993 Return the current busy-wait interval between successive\n\
2994 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
2996 static PyMethodDef moduleMethods
[] =
2998 {"_flatten", Tkinter_Flatten
, METH_VARARGS
},
2999 {"create", Tkinter_Create
, METH_VARARGS
},
3000 #ifdef HAVE_CREATEFILEHANDLER
3001 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
3002 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
3004 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
3005 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
3006 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
3007 {"quit", Tkapp_Quit
, METH_VARARGS
},
3008 {"setbusywaitinterval",Tkinter_setbusywaitinterval
, METH_VARARGS
,
3009 setbusywaitinterval_doc
},
3010 {"getbusywaitinterval",(PyCFunction
)Tkinter_getbusywaitinterval
,
3011 METH_NOARGS
, getbusywaitinterval_doc
},
3015 #ifdef WAIT_FOR_STDIN
3017 static int stdin_ready
= 0;
3021 MyFileProc(void *clientData
, int mask
)
3028 static PyThreadState
*event_tstate
= NULL
;
3038 PyEval_RestoreThread(event_tstate
);
3043 tfile
= fileno(stdin
);
3044 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
3046 while (!errorInCmd
&& !stdin_ready
) {
3054 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3055 Py_BEGIN_ALLOW_THREADS
3056 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
3057 tcl_tstate
= event_tstate
;
3059 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
3062 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
3064 Sleep(Tkinter_busywaitinterval
);
3065 Py_END_ALLOW_THREADS
3067 result
= Tcl_DoOneEvent(0);
3074 Tcl_DeleteFileHandler(tfile
);
3078 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
3079 excInCmd
= valInCmd
= trbInCmd
= NULL
;
3083 PyEval_SaveThread();
3091 EnableEventHook(void)
3093 #ifdef WAIT_FOR_STDIN
3094 if (PyOS_InputHook
== NULL
) {
3096 event_tstate
= PyThreadState_Get();
3098 PyOS_InputHook
= EventHook
;
3104 DisableEventHook(void)
3106 #ifdef WAIT_FOR_STDIN
3107 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
3108 PyOS_InputHook
= NULL
;
3114 /* all errors will be checked in one fell swoop in init_tkinter() */
3116 ins_long(PyObject
*d
, char *name
, long val
)
3118 PyObject
*v
= PyInt_FromLong(val
);
3120 PyDict_SetItemString(d
, name
, v
);
3125 ins_string(PyObject
*d
, char *name
, char *val
)
3127 PyObject
*v
= PyString_FromString(val
);
3129 PyDict_SetItemString(d
, name
, v
);
3140 Py_TYPE(&Tkapp_Type
) = &PyType_Type
;
3143 tcl_lock
= PyThread_allocate_lock();
3146 m
= Py_InitModule("_tkinter", moduleMethods
);
3150 d
= PyModule_GetDict(m
);
3151 Tkinter_TclError
= PyErr_NewException("_tkinter.TclError", NULL
, NULL
);
3152 PyDict_SetItemString(d
, "TclError", Tkinter_TclError
);
3154 ins_long(d
, "READABLE", TCL_READABLE
);
3155 ins_long(d
, "WRITABLE", TCL_WRITABLE
);
3156 ins_long(d
, "EXCEPTION", TCL_EXCEPTION
);
3157 ins_long(d
, "WINDOW_EVENTS", TCL_WINDOW_EVENTS
);
3158 ins_long(d
, "FILE_EVENTS", TCL_FILE_EVENTS
);
3159 ins_long(d
, "TIMER_EVENTS", TCL_TIMER_EVENTS
);
3160 ins_long(d
, "IDLE_EVENTS", TCL_IDLE_EVENTS
);
3161 ins_long(d
, "ALL_EVENTS", TCL_ALL_EVENTS
);
3162 ins_long(d
, "DONT_WAIT", TCL_DONT_WAIT
);
3163 ins_string(d
, "TK_VERSION", TK_VERSION
);
3164 ins_string(d
, "TCL_VERSION", TCL_VERSION
);
3166 PyDict_SetItemString(d
, "TkappType", (PyObject
*)&Tkapp_Type
);
3168 Py_TYPE(&Tktt_Type
) = &PyType_Type
;
3169 PyDict_SetItemString(d
, "TkttType", (PyObject
*)&Tktt_Type
);
3171 Py_TYPE(&PyTclObject_Type
) = &PyType_Type
;
3172 PyDict_SetItemString(d
, "Tcl_Obj", (PyObject
*)&PyTclObject_Type
);
3175 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3176 * start waking up. Note that Tcl_FindExecutable will do this, this
3177 * code must be above it! The original warning from
3178 * tkMacOSXAppInit.c is copied below.
3180 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3181 * Tcl interpreter for now. It probably should work to do this
3182 * in the other order, but for now it doesn't seem to.
3185 Tk_MacOSXSetupTkNotifier();
3189 /* This helps the dynamic loader; in Unicode aware Tcl versions
3190 it also helps Tcl find its encodings. */
3191 Tcl_FindExecutable(Py_GetProgramName());
3193 if (PyErr_Occurred())
3197 /* This was not a good idea; through <Destroy> bindings,
3198 Tcl_Finalize() may invoke Python code but at that point the
3199 interpreter and thread state have already been destroyed! */
3200 Py_AtExit(Tcl_Finalize
);