1 /***********************************************************
2 Copyright (C) 1994 Steen Lumholt.
6 ******************************************************************/
8 /* _tkinter.c -- Interface to libtk.a and libtcl.a. */
10 /* TCL/TK VERSION INFO:
12 Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
17 /* XXX Further speed-up ideas, involving Tcl 8.0 features:
19 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
36 /* Allow using this code in Python 2.[12] */
38 #define PyDoc_STRVAR(name,str) static char name[] = str
41 #ifndef PyMODINIT_FUNC
42 #define PyMODINIT_FUNC void
46 #define PyBool_Check(o) 0
47 #define PyBool_FromLong 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
72 /* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
73 #ifndef CONST84_RETURN
74 #define CONST84_RETURN
79 #if TK_VERSION_HEX < 0x08030102
80 #error "Tk older than 8.3.1 not supported"
83 /* Unicode conversion assumes that Tcl_UniChar is two bytes.
84 We cannot test this directly, so we test UTF-8 size instead,
85 expecting that TCL_UTF_MAX is changed if Tcl ever supports
86 either UTF-16 or UCS-4.
87 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
88 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
91 #if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
92 #error "unsupported Tcl configuration"
95 #if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
96 #define HAVE_CREATEFILEHANDLER
99 #ifdef HAVE_CREATEFILEHANDLER
101 /* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
102 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
104 # ifdef TCL_WIN_SOCKET
105 # define TCL_UNIX_FD (! TCL_WIN_SOCKET)
107 # define TCL_UNIX_FD 1
111 /* Tcl_CreateFileHandler() changed several times; these macros deal with the
112 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
113 Unix, only because Jack added it back); when available on Windows, it only
114 applies to sockets. */
117 #define FHANDLETYPE TCL_WIN_SOCKET
119 #define FHANDLETYPE TCL_UNIX_FD
122 /* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
123 which uses this to handle Tcl events while the user is typing commands. */
125 #if FHANDLETYPE == TCL_UNIX_FD
126 #define WAIT_FOR_STDIN
129 #endif /* HAVE_CREATEFILEHANDLER */
133 #define WAIT_FOR_STDIN
138 /* The threading situation is complicated. Tcl is not thread-safe, except
139 when configured with --enable-threads.
140 So we need to use a lock around all uses of Tcl. Previously, the Python
141 interpreter lock was used for this. However, this causes problems when
142 other Python threads need to run while Tcl is blocked waiting for events.
144 To solve this problem, a separate lock for Tcl is introduced. Holding it
145 is incompatible with holding Python's interpreter lock. The following four
146 macros manipulate both locks together.
148 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
149 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
150 that could call an event handler, or otherwise affect the state of a Tcl
151 interpreter. These assume that the surrounding code has the Python
152 interpreter lock; inside the brackets, the Python interpreter lock has been
153 released and the lock for Tcl has been acquired.
155 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
156 (For example, when transferring data from the Tcl interpreter result to a
157 Python string object.) This can be done by using different macros to close
158 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
159 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
160 releases the Tcl lock.
162 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
163 handlers when the handler needs to use Python. Such event handlers are
164 entered while the lock for Tcl is held; the event handler presumably needs
165 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
166 the Python interpreter lock, restoring the appropriate thread state, and
167 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
168 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
169 the code between ENTER_PYTHON and LEAVE_PYTHON.
171 These locks expand to several statements and brackets; they should not be
172 used in branches of if statements and the like.
174 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
175 only valid in the thread that created it, and all Tk activity must happen in this
176 thread, also. That means that the mainloop must be invoked in the thread that
177 created the interpreter. Invoking commands from other threads is possible;
178 _tkinter will queue an event for the interpreter thread, which will then
179 execute the command and pass back the result. If the main thread is not in the
180 mainloop, and invoking commands causes an exception; if the main loop is running
181 but not processing events, the command invocation will block.
183 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
184 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
185 threads. So we use the Tcl TLS API.
189 static PyThread_type_lock tcl_lock
= 0;
192 static Tcl_ThreadDataKey state_key
;
193 typedef PyThreadState
*ThreadSpecificData
;
194 #define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
196 static PyThreadState
*tcl_tstate
= NULL
;
200 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
201 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
204 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
206 #define ENTER_OVERLAP \
209 #define LEAVE_OVERLAP_TCL \
210 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
212 #define ENTER_PYTHON \
213 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
214 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
216 #define LEAVE_PYTHON \
217 { PyThreadState *tstate = PyEval_SaveThread(); \
218 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
220 #define CHECK_TCL_APPARTMENT \
221 if (((TkappObject *)self)->threaded && \
222 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
223 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
231 #define ENTER_OVERLAP
232 #define LEAVE_OVERLAP_TCL
235 #define CHECK_TCL_APPARTMENT
240 #define FREECAST (char *)
243 /**** Tkapp Object Declaration ****/
245 static PyTypeObject Tkapp_Type
;
251 int threaded
; /* True if tcl_platform[threaded] */
252 Tcl_ThreadId thread_id
;
254 /* We cannot include tclInt.h, as this is internal.
255 So we cache interesting types here. */
256 Tcl_ObjType
*BooleanType
;
257 Tcl_ObjType
*ByteArrayType
;
258 Tcl_ObjType
*DoubleType
;
259 Tcl_ObjType
*IntType
;
260 Tcl_ObjType
*ListType
;
261 Tcl_ObjType
*ProcBodyType
;
262 Tcl_ObjType
*StringType
;
265 #define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
266 #define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
267 #define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
269 #define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
270 (void *) v, Py_REFCNT(v)))
274 /**** Error Handling ****/
276 static PyObject
*Tkinter_TclError
;
277 static int quitMainLoop
= 0;
278 static int errorInCmd
= 0;
279 static PyObject
*excInCmd
;
280 static PyObject
*valInCmd
;
281 static PyObject
*trbInCmd
;
283 #ifdef TKINTER_PROTECT_LOADTK
284 static int tk_load_failed
;
289 Tkinter_Error(PyObject
*v
)
291 PyErr_SetString(Tkinter_TclError
, Tkapp_Result(v
));
299 static int Tkinter_busywaitinterval
= 20;
304 /* Millisecond sleep() for Unix platforms. */
309 /* XXX Too bad if you don't have select(). */
311 t
.tv_sec
= milli
/1000;
312 t
.tv_usec
= (milli
%1000) * 1000;
313 select(0, (fd_set
*)0, (fd_set
*)0, (fd_set
*)0, &t
);
315 #endif /* MS_WINDOWS */
317 /* Wait up to 1s for the mainloop to come up. */
320 WaitForMainloop(TkappObject
* self
)
323 for (i
= 0; i
< 10; i
++) {
324 if (self
->dispatching
)
326 Py_BEGIN_ALLOW_THREADS
330 if (self
->dispatching
)
332 PyErr_SetString(PyExc_RuntimeError
, "main thread is not in main loop");
335 #endif /* WITH_THREAD */
339 AsString(PyObject
*value
, PyObject
*tmp
)
341 if (PyString_Check(value
))
342 return PyString_AsString(value
);
343 #ifdef Py_USING_UNICODE
344 else if (PyUnicode_Check(value
)) {
345 PyObject
*v
= PyUnicode_AsUTF8String(value
);
348 if (PyList_Append(tmp
, v
) != 0) {
353 return PyString_AsString(v
);
357 PyObject
*v
= PyObject_Str(value
);
360 if (PyList_Append(tmp
, v
) != 0) {
365 return PyString_AsString(v
);
374 Merge(PyObject
*args
)
376 PyObject
*tmp
= NULL
;
377 char *argvStore
[ARGSZ
];
381 int argc
= 0, fvc
= 0, i
;
384 if (!(tmp
= PyList_New(0)))
393 else if (!PyTuple_Check(args
)) {
396 if (!(argv
[0] = AsString(args
, tmp
)))
400 argc
= PyTuple_Size(args
);
403 argv
= (char **)ckalloc(argc
* sizeof(char *));
404 fv
= (int *)ckalloc(argc
* sizeof(int));
405 if (argv
== NULL
|| fv
== NULL
) {
411 for (i
= 0; i
< argc
; i
++) {
412 PyObject
*v
= PyTuple_GetItem(args
, i
);
413 if (PyTuple_Check(v
)) {
415 if (!(argv
[i
] = Merge(v
)))
419 else if (v
== Py_None
) {
425 if (!(argv
[i
] = AsString(v
, tmp
)))
431 res
= Tcl_Merge(argc
, argv
);
433 PyErr_SetString(Tkinter_TclError
, "merge failed");
436 for (i
= 0; i
< fvc
; i
++)
440 if (argv
!= argvStore
)
441 ckfree(FREECAST argv
);
463 if (Tcl_SplitList((Tcl_Interp
*)NULL
, list
, &argc
, &argv
) != TCL_OK
) {
465 * Could be a quoted string containing funnies, e.g. {"}.
466 * Return the string itself.
468 return PyString_FromString(list
);
472 v
= PyString_FromString("");
474 v
= PyString_FromString(argv
[0]);
475 else if ((v
= PyTuple_New(argc
)) != NULL
) {
479 for (i
= 0; i
< argc
; i
++) {
480 if ((w
= Split(argv
[i
])) == NULL
) {
485 PyTuple_SetItem(v
, i
, w
);
488 Tcl_Free(FREECAST argv
);
492 /* In some cases, Tcl will still return strings that are supposed to be
493 lists. SplitObj walks through a nested tuple, finding string objects that
497 SplitObj(PyObject
*arg
)
499 if (PyTuple_Check(arg
)) {
501 PyObject
*elem
, *newelem
, *result
;
503 size
= PyTuple_Size(arg
);
505 /* Recursively invoke SplitObj for all tuple items.
506 If this does not return a new object, no action is
508 for(i
= 0; i
< size
; i
++) {
509 elem
= PyTuple_GetItem(arg
, i
);
510 newelem
= SplitObj(elem
);
517 if (newelem
== elem
) {
521 result
= PyTuple_New(size
);
524 for(k
= 0; k
< i
; k
++) {
525 elem
= PyTuple_GetItem(arg
, k
);
527 PyTuple_SetItem(result
, k
, elem
);
530 PyTuple_SetItem(result
, i
, newelem
);
534 /* Fall through, returning arg. */
536 else if (PyString_Check(arg
)) {
539 char *list
= PyString_AsString(arg
);
541 if (Tcl_SplitList((Tcl_Interp
*)NULL
, list
, &argc
, &argv
) != TCL_OK
) {
545 Tcl_Free(FREECAST argv
);
547 return Split(PyString_AsString(arg
));
548 /* Fall through, returning arg. */
555 /**** Tkapp Object ****/
559 Tcl_AppInit(Tcl_Interp
*interp
)
561 const char * _tkinter_skip_tk_init
;
563 if (Tcl_Init(interp
) == TCL_ERROR
) {
564 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp
));
568 _tkinter_skip_tk_init
= Tcl_GetVar(interp
,
569 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY
);
570 if (_tkinter_skip_tk_init
!= NULL
&&
571 strcmp(_tkinter_skip_tk_init
, "1") == 0) {
575 #ifdef TKINTER_PROTECT_LOADTK
576 if (tk_load_failed
) {
577 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG
);
582 if (Tk_Init(interp
) == TCL_ERROR
) {
583 #ifdef TKINTER_PROTECT_LOADTK
586 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp
));
592 #endif /* !WITH_APPINIT */
597 /* Initialize the Tk application; see the `main' function in
601 static void EnableEventHook(void); /* Forward */
602 static void DisableEventHook(void); /* Forward */
605 Tkapp_New(char *screenName
, char *baseName
, char *className
,
606 int interactive
, int wantobjects
, int wantTk
, int sync
, char *use
)
611 v
= PyObject_New(TkappObject
, &Tkapp_Type
);
615 v
->interp
= Tcl_CreateInterp();
616 v
->wantobjects
= wantobjects
;
617 v
->threaded
= Tcl_GetVar2Ex(v
->interp
, "tcl_platform", "threaded",
618 TCL_GLOBAL_ONLY
) != NULL
;
619 v
->thread_id
= Tcl_GetCurrentThread();
624 PyErr_SetString(PyExc_RuntimeError
, "Tcl is threaded but _tkinter is not");
630 if (v
->threaded
&& tcl_lock
) {
631 /* If Tcl is threaded, we don't need the lock. */
632 PyThread_free_lock(tcl_lock
);
637 v
->BooleanType
= Tcl_GetObjType("boolean");
638 v
->ByteArrayType
= Tcl_GetObjType("bytearray");
639 v
->DoubleType
= Tcl_GetObjType("double");
640 v
->IntType
= Tcl_GetObjType("int");
641 v
->ListType
= Tcl_GetObjType("list");
642 v
->ProcBodyType
= Tcl_GetObjType("procbody");
643 v
->StringType
= Tcl_GetObjType("string");
645 /* Delete the 'exit' command, which can screw things up */
646 Tcl_DeleteCommand(v
->interp
, "exit");
648 if (screenName
!= NULL
)
649 Tcl_SetVar2(v
->interp
, "env", "DISPLAY",
650 screenName
, TCL_GLOBAL_ONLY
);
653 Tcl_SetVar(v
->interp
, "tcl_interactive", "1", TCL_GLOBAL_ONLY
);
655 Tcl_SetVar(v
->interp
, "tcl_interactive", "0", TCL_GLOBAL_ONLY
);
657 /* This is used to get the application class for Tk 4.1 and up */
658 argv0
= (char*)ckalloc(strlen(className
) + 1);
665 strcpy(argv0
, className
);
666 if (isupper(Py_CHARMASK(argv0
[0])))
667 argv0
[0] = tolower(Py_CHARMASK(argv0
[0]));
668 Tcl_SetVar(v
->interp
, "argv0", argv0
, TCL_GLOBAL_ONLY
);
672 Tcl_SetVar(v
->interp
,
673 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY
);
675 #ifdef TKINTER_PROTECT_LOADTK
676 else if (tk_load_failed
) {
677 Tcl_SetVar(v
->interp
,
678 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY
);
682 /* some initial arguments need to be in argv */
688 len
+= sizeof "-sync";
690 len
+= strlen(use
) + sizeof "-use ";
692 args
= (char*)ckalloc(len
);
701 strcat(args
, "-sync");
705 strcat(args
, "-use ");
709 Tcl_SetVar(v
->interp
, "argv", args
, TCL_GLOBAL_ONLY
);
713 if (Tcl_AppInit(v
->interp
) != TCL_OK
) {
714 PyObject
*result
= Tkinter_Error((PyObject
*)v
);
715 #ifdef TKINTER_PROTECT_LOADTK
717 const char *_tkinter_tk_failed
;
718 _tkinter_tk_failed
= Tcl_GetVar(v
->interp
,
719 "_tkinter_tk_failed", TCL_GLOBAL_ONLY
);
721 if ( _tkinter_tk_failed
!= NULL
&&
722 strcmp(_tkinter_tk_failed
, "1") == 0) {
727 Py_DECREF((PyObject
*)v
);
728 return (TkappObject
*)result
;
739 Tkapp_ThreadSend(TkappObject
*self
, Tcl_Event
*ev
,
740 Tcl_Condition
*cond
, Tcl_Mutex
*mutex
)
742 Py_BEGIN_ALLOW_THREADS
;
743 Tcl_MutexLock(mutex
);
744 Tcl_ThreadQueueEvent(self
->thread_id
, ev
, TCL_QUEUE_TAIL
);
745 Tcl_ThreadAlert(self
->thread_id
);
746 Tcl_ConditionWait(cond
, mutex
, NULL
);
747 Tcl_MutexUnlock(mutex
);
758 PyObject
*string
; /* This cannot cause cycles. */
761 staticforward PyTypeObject PyTclObject_Type
;
762 #define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
765 newPyTclObject(Tcl_Obj
*arg
)
768 self
= PyObject_New(PyTclObject
, &PyTclObject_Type
);
771 Tcl_IncrRefCount(arg
);
774 return (PyObject
*)self
;
778 PyTclObject_dealloc(PyTclObject
*self
)
780 Tcl_DecrRefCount(self
->value
);
781 Py_XDECREF(self
->string
);
786 PyTclObject_str(PyTclObject
*self
)
788 if (self
->string
&& PyString_Check(self
->string
)) {
789 Py_INCREF(self
->string
);
792 /* XXX Could cache value if it is an ASCII string. */
793 return PyString_FromString(Tcl_GetString(self
->value
));
797 PyTclObject_TclString(PyObject
*self
)
799 return Tcl_GetString(((PyTclObject
*)self
)->value
);
802 /* Like _str, but create Unicode if necessary. */
803 PyDoc_STRVAR(PyTclObject_string__doc__
,
804 "the string representation of this object, either as string or Unicode");
807 PyTclObject_string(PyTclObject
*self
, void *ignored
)
812 s
= Tcl_GetStringFromObj(self
->value
, &len
);
813 for (i
= 0; i
< len
; i
++)
816 #ifdef Py_USING_UNICODE
818 /* It is an ASCII string. */
819 self
->string
= PyString_FromStringAndSize(s
, len
);
821 self
->string
= PyUnicode_DecodeUTF8(s
, len
, "strict");
824 self
->string
= PyString_FromStringAndSize(s
, len
);
828 self
->string
= PyString_FromStringAndSize(s
, len
);
833 Py_INCREF(self
->string
);
837 #ifdef Py_USING_UNICODE
838 PyDoc_STRVAR(PyTclObject_unicode__doc__
, "convert argument to unicode");
841 PyTclObject_unicode(PyTclObject
*self
, void *ignored
)
845 if (self
->string
&& PyUnicode_Check(self
->string
)) {
846 Py_INCREF(self
->string
);
849 /* XXX Could chache result if it is non-ASCII. */
850 s
= Tcl_GetStringFromObj(self
->value
, &len
);
851 return PyUnicode_DecodeUTF8(s
, len
, "strict");
856 PyTclObject_repr(PyTclObject
*self
)
859 PyOS_snprintf(buf
, 50, "<%s object at %p>",
860 self
->value
->typePtr
->name
, self
->value
);
861 return PyString_FromString(buf
);
865 PyTclObject_cmp(PyTclObject
*self
, PyTclObject
*other
)
868 res
= strcmp(Tcl_GetString(self
->value
),
869 Tcl_GetString(other
->value
));
870 if (res
< 0) return -1;
871 if (res
> 0) return 1;
875 PyDoc_STRVAR(get_typename__doc__
, "name of the Tcl type");
878 get_typename(PyTclObject
* obj
, void* ignored
)
880 return PyString_FromString(obj
->value
->typePtr
->name
);
884 static PyGetSetDef PyTclObject_getsetlist
[] = {
885 {"typename", (getter
)get_typename
, NULL
, get_typename__doc__
},
886 {"string", (getter
)PyTclObject_string
, NULL
,
887 PyTclObject_string__doc__
},
891 static PyMethodDef PyTclObject_methods
[] = {
892 #ifdef Py_USING_UNICODE
893 {"__unicode__", (PyCFunction
)PyTclObject_unicode
, METH_NOARGS
,
894 PyTclObject_unicode__doc__
},
899 statichere PyTypeObject PyTclObject_Type
= {
900 PyObject_HEAD_INIT(NULL
)
902 "_tkinter.Tcl_Obj", /*tp_name*/
903 sizeof(PyTclObject
), /*tp_basicsize*/
906 (destructor
)PyTclObject_dealloc
, /*tp_dealloc*/
910 (cmpfunc
)PyTclObject_cmp
, /*tp_compare*/
911 (reprfunc
)PyTclObject_repr
, /*tp_repr*/
913 0, /*tp_as_sequence*/
917 (reprfunc
)PyTclObject_str
, /*tp_str*/
918 PyObject_GenericGetAttr
,/*tp_getattro*/
921 Py_TPFLAGS_DEFAULT
, /*tp_flags*/
925 0, /*tp_richcompare*/
926 0, /*tp_weaklistoffset*/
929 PyTclObject_methods
, /*tp_methods*/
931 PyTclObject_getsetlist
, /*tp_getset*/
945 AsObj(PyObject
*value
)
949 if (PyString_Check(value
))
950 return Tcl_NewStringObj(PyString_AS_STRING(value
),
951 PyString_GET_SIZE(value
));
952 else if (PyBool_Check(value
))
953 return Tcl_NewBooleanObj(PyObject_IsTrue(value
));
954 else if (PyInt_Check(value
))
955 return Tcl_NewLongObj(PyInt_AS_LONG(value
));
956 else if (PyFloat_Check(value
))
957 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value
));
958 else if (PyTuple_Check(value
)) {
959 Tcl_Obj
**argv
= (Tcl_Obj
**)
960 ckalloc(PyTuple_Size(value
)*sizeof(Tcl_Obj
*));
964 for(i
=0;i
<PyTuple_Size(value
);i
++)
965 argv
[i
] = AsObj(PyTuple_GetItem(value
,i
));
966 result
= Tcl_NewListObj(PyTuple_Size(value
), argv
);
967 ckfree(FREECAST argv
);
970 #ifdef Py_USING_UNICODE
971 else if (PyUnicode_Check(value
)) {
972 Py_UNICODE
*inbuf
= PyUnicode_AS_UNICODE(value
);
973 Py_ssize_t size
= PyUnicode_GET_SIZE(value
);
974 /* This #ifdef assumes that Tcl uses UCS-2.
975 See TCL_UTF_MAX test above. */
976 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
977 Tcl_UniChar
*outbuf
= NULL
;
979 size_t allocsize
= ((size_t)size
) * sizeof(Tcl_UniChar
);
980 if (allocsize
>= size
)
981 outbuf
= (Tcl_UniChar
*)ckalloc(allocsize
);
982 /* Else overflow occurred, and we take the next exit */
987 for (i
= 0; i
< size
; i
++) {
988 if (inbuf
[i
] >= 0x10000) {
989 /* Tcl doesn't do UTF-16, yet. */
990 PyErr_SetString(PyExc_ValueError
,
991 "unsupported character");
992 ckfree(FREECAST outbuf
);
995 outbuf
[i
] = inbuf
[i
];
997 result
= Tcl_NewUnicodeObj(outbuf
, size
);
998 ckfree(FREECAST outbuf
);
1001 return Tcl_NewUnicodeObj(inbuf
, size
);
1006 else if(PyTclObject_Check(value
)) {
1007 Tcl_Obj
*v
= ((PyTclObject
*)value
)->value
;
1008 Tcl_IncrRefCount(v
);
1012 PyObject
*v
= PyObject_Str(value
);
1022 FromObj(PyObject
* tkapp
, Tcl_Obj
*value
)
1024 PyObject
*result
= NULL
;
1025 TkappObject
*app
= (TkappObject
*)tkapp
;
1027 if (value
->typePtr
== NULL
) {
1028 /* If the result contains any bytes with the top bit set,
1029 it's UTF-8 and we should decode it to Unicode */
1030 #ifdef Py_USING_UNICODE
1032 char *s
= value
->bytes
;
1033 int len
= value
->length
;
1034 for (i
= 0; i
< len
; i
++) {
1035 if (value
->bytes
[i
] & 0x80)
1039 if (i
== value
->length
)
1040 result
= PyString_FromStringAndSize(s
, len
);
1042 /* Convert UTF-8 to Unicode string */
1043 result
= PyUnicode_DecodeUTF8(s
, len
, "strict");
1044 if (result
== NULL
) {
1046 result
= PyString_FromStringAndSize(s
, len
);
1050 result
= PyString_FromStringAndSize(value
->bytes
, value
->length
);
1055 if (value
->typePtr
== app
->BooleanType
) {
1056 result
= value
->internalRep
.longValue
? Py_True
: Py_False
;
1061 if (value
->typePtr
== app
->ByteArrayType
) {
1063 char *data
= (char*)Tcl_GetByteArrayFromObj(value
, &size
);
1064 return PyString_FromStringAndSize(data
, size
);
1067 if (value
->typePtr
== app
->DoubleType
) {
1068 return PyFloat_FromDouble(value
->internalRep
.doubleValue
);
1071 if (value
->typePtr
== app
->IntType
) {
1072 return PyInt_FromLong(value
->internalRep
.longValue
);
1075 if (value
->typePtr
== app
->ListType
) {
1081 status
= Tcl_ListObjLength(Tkapp_Interp(tkapp
), value
, &size
);
1082 if (status
== TCL_ERROR
)
1083 return Tkinter_Error(tkapp
);
1084 result
= PyTuple_New(size
);
1087 for (i
= 0; i
< size
; i
++) {
1088 status
= Tcl_ListObjIndex(Tkapp_Interp(tkapp
),
1089 value
, i
, &tcl_elem
);
1090 if (status
== TCL_ERROR
) {
1092 return Tkinter_Error(tkapp
);
1094 elem
= FromObj(tkapp
, tcl_elem
);
1099 PyTuple_SetItem(result
, i
, elem
);
1104 if (value
->typePtr
== app
->ProcBodyType
) {
1105 /* fall through: return tcl object. */
1108 if (value
->typePtr
== app
->StringType
) {
1109 #ifdef Py_USING_UNICODE
1110 #if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
1116 size
= Tcl_GetCharLength(value
);
1117 result
= PyUnicode_FromUnicode(NULL
, size
);
1120 input
= Tcl_GetUnicode(value
);
1121 output
= PyUnicode_AS_UNICODE(result
);
1123 *output
++ = *input
++;
1126 return PyUnicode_FromUnicode(Tcl_GetUnicode(value
),
1127 Tcl_GetCharLength(value
));
1132 c
= Tcl_GetStringFromObj(value
, &size
);
1133 return PyString_FromStringAndSize(c
, size
);
1137 return newPyTclObject(value
);
1141 /* This mutex synchronizes inter-thread command calls. */
1142 TCL_DECLARE_MUTEX(call_mutex
)
1144 typedef struct Tkapp_CallEvent
{
1145 Tcl_Event ev
; /* Must be first */
1150 PyObject
**exc_type
, **exc_value
, **exc_tb
;
1151 Tcl_Condition
*done
;
1156 Tkapp_CallDeallocArgs(Tcl_Obj
** objv
, Tcl_Obj
** objStore
, int objc
)
1159 for (i
= 0; i
< objc
; i
++)
1160 Tcl_DecrRefCount(objv
[i
]);
1161 if (objv
!= objStore
)
1162 ckfree(FREECAST objv
);
1165 /* Convert Python objects to Tcl objects. This must happen in the
1166 interpreter thread, which may or may not be the calling thread. */
1169 Tkapp_CallArgs(PyObject
*args
, Tcl_Obj
** objStore
, int *pobjc
)
1171 Tcl_Obj
**objv
= objStore
;
1176 else if (!PyTuple_Check(args
)) {
1177 objv
[0] = AsObj(args
);
1181 Tcl_IncrRefCount(objv
[0]);
1184 objc
= PyTuple_Size(args
);
1187 objv
= (Tcl_Obj
**)ckalloc(objc
* sizeof(char *));
1195 for (i
= 0; i
< objc
; i
++) {
1196 PyObject
*v
= PyTuple_GetItem(args
, i
);
1203 /* Reset objc, so it attempts to clear
1204 objects only up to i. */
1208 Tcl_IncrRefCount(objv
[i
]);
1214 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1218 /* Convert the results of a command call into a Python objects. */
1221 Tkapp_CallResult(TkappObject
*self
)
1223 PyObject
*res
= NULL
;
1224 if(self
->wantobjects
) {
1225 Tcl_Obj
*value
= Tcl_GetObjResult(self
->interp
);
1226 /* Not sure whether the IncrRef is necessary, but something
1227 may overwrite the interpreter result while we are
1229 Tcl_IncrRefCount(value
);
1230 res
= FromObj((PyObject
*)self
, value
);
1231 Tcl_DecrRefCount(value
);
1233 const char *s
= Tcl_GetStringResult(self
->interp
);
1236 /* If the result contains any bytes with the top bit set,
1237 it's UTF-8 and we should decode it to Unicode */
1238 #ifdef Py_USING_UNICODE
1239 while (*p
!= '\0') {
1246 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
1248 /* Convert UTF-8 to Unicode string */
1249 p
= strchr(p
, '\0');
1250 res
= PyUnicode_DecodeUTF8(s
, (int)(p
-s
), "strict");
1253 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
1257 p
= strchr(p
, '\0');
1258 res
= PyString_FromStringAndSize(s
, (int)(p
-s
));
1266 /* Tkapp_CallProc is the event procedure that is executed in the context of
1267 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1268 hold the Python lock. */
1271 Tkapp_CallProc(Tkapp_CallEvent
*e
, int flags
)
1273 Tcl_Obj
*objStore
[ARGSZ
];
1278 objv
= Tkapp_CallArgs(e
->args
, objStore
, &objc
);
1280 PyErr_Fetch(e
->exc_type
, e
->exc_value
, e
->exc_tb
);
1286 i
= Tcl_EvalObjv(e
->self
->interp
, objc
, objv
, e
->flags
);
1288 if (i
== TCL_ERROR
) {
1290 *(e
->exc_type
) = NULL
;
1291 *(e
->exc_tb
) = NULL
;
1292 *(e
->exc_value
) = PyObject_CallFunction(
1293 Tkinter_TclError
, "s",
1294 Tcl_GetStringResult(e
->self
->interp
));
1297 *(e
->res
) = Tkapp_CallResult(e
->self
);
1301 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1303 /* Wake up calling thread. */
1304 Tcl_MutexLock(&call_mutex
);
1305 Tcl_ConditionNotify(e
->done
);
1306 Tcl_MutexUnlock(&call_mutex
);
1312 /* This is the main entry point for calling a Tcl command.
1313 It supports three cases, with regard to threading:
1314 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1315 the context of the calling thread.
1316 2. Tcl is threaded, caller of the command is in the interpreter thread:
1317 Execute the command in the calling thread. Since the Tcl lock will
1318 not be used, we can merge that with case 1.
1319 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1320 the interpreter thread. Allocation of Tcl objects needs to occur in the
1321 interpreter thread, so we ship the PyObject* args to the target thread,
1322 and perform processing there. */
1325 Tkapp_Call(PyObject
*selfptr
, PyObject
*args
)
1327 Tcl_Obj
*objStore
[ARGSZ
];
1328 Tcl_Obj
**objv
= NULL
;
1330 PyObject
*res
= NULL
;
1331 TkappObject
*self
= (TkappObject
*)selfptr
;
1332 int flags
= TCL_EVAL_DIRECT
| TCL_EVAL_GLOBAL
;
1334 /* If args is a single tuple, replace with contents of tuple */
1335 if (1 == PyTuple_Size(args
)){
1336 PyObject
* item
= PyTuple_GetItem(args
, 0);
1337 if (PyTuple_Check(item
))
1341 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1342 /* We cannot call the command directly. Instead, we must
1343 marshal the parameters to the interpreter thread. */
1344 Tkapp_CallEvent
*ev
;
1345 Tcl_Condition cond
= NULL
;
1346 PyObject
*exc_type
, *exc_value
, *exc_tb
;
1347 if (!WaitForMainloop(self
))
1349 ev
= (Tkapp_CallEvent
*)ckalloc(sizeof(Tkapp_CallEvent
));
1350 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CallProc
;
1354 ev
->exc_type
= &exc_type
;
1355 ev
->exc_value
= &exc_value
;
1356 ev
->exc_tb
= &exc_tb
;
1359 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &cond
, &call_mutex
);
1363 PyErr_Restore(exc_type
, exc_value
, exc_tb
);
1365 PyErr_SetObject(Tkinter_TclError
, exc_value
);
1367 Tcl_ConditionFinalize(&cond
);
1373 objv
= Tkapp_CallArgs(args
, objStore
, &objc
);
1379 i
= Tcl_EvalObjv(self
->interp
, objc
, objv
, flags
);
1384 Tkinter_Error(selfptr
);
1386 res
= Tkapp_CallResult(self
);
1390 Tkapp_CallDeallocArgs(objv
, objStore
, objc
);
1397 Tkapp_GlobalCall(PyObject
*self
, PyObject
*args
)
1399 /* Could do the same here as for Tkapp_Call(), but this is not used
1400 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1401 way for the user to do what all its Global* variants do (save and
1402 reset the scope pointer, call the local version, restore the saved
1406 PyObject
*res
= NULL
;
1408 CHECK_TCL_APPARTMENT
;
1414 err
= Tcl_GlobalEval(Tkapp_Interp(self
), cmd
);
1416 if (err
== TCL_ERROR
)
1417 res
= Tkinter_Error(self
);
1419 res
= PyString_FromString(Tkapp_Result(self
));
1428 Tkapp_Eval(PyObject
*self
, PyObject
*args
)
1431 PyObject
*res
= NULL
;
1434 if (!PyArg_ParseTuple(args
, "s:eval", &script
))
1437 CHECK_TCL_APPARTMENT
;
1440 err
= Tcl_Eval(Tkapp_Interp(self
), script
);
1442 if (err
== TCL_ERROR
)
1443 res
= Tkinter_Error(self
);
1445 res
= PyString_FromString(Tkapp_Result(self
));
1451 Tkapp_GlobalEval(PyObject
*self
, PyObject
*args
)
1454 PyObject
*res
= NULL
;
1457 if (!PyArg_ParseTuple(args
, "s:globaleval", &script
))
1460 CHECK_TCL_APPARTMENT
;
1463 err
= Tcl_GlobalEval(Tkapp_Interp(self
), script
);
1465 if (err
== TCL_ERROR
)
1466 res
= Tkinter_Error(self
);
1468 res
= PyString_FromString(Tkapp_Result(self
));
1474 Tkapp_EvalFile(PyObject
*self
, PyObject
*args
)
1477 PyObject
*res
= NULL
;
1480 if (!PyArg_ParseTuple(args
, "s:evalfile", &fileName
))
1483 CHECK_TCL_APPARTMENT
;
1486 err
= Tcl_EvalFile(Tkapp_Interp(self
), fileName
);
1488 if (err
== TCL_ERROR
)
1489 res
= Tkinter_Error(self
);
1492 res
= PyString_FromString(Tkapp_Result(self
));
1498 Tkapp_Record(PyObject
*self
, PyObject
*args
)
1501 PyObject
*res
= NULL
;
1504 if (!PyArg_ParseTuple(args
, "s", &script
))
1507 CHECK_TCL_APPARTMENT
;
1510 err
= Tcl_RecordAndEval(Tkapp_Interp(self
), script
, TCL_NO_EVAL
);
1512 if (err
== TCL_ERROR
)
1513 res
= Tkinter_Error(self
);
1515 res
= PyString_FromString(Tkapp_Result(self
));
1521 Tkapp_AddErrorInfo(PyObject
*self
, PyObject
*args
)
1525 if (!PyArg_ParseTuple(args
, "s:adderrorinfo", &msg
))
1527 CHECK_TCL_APPARTMENT
;
1530 Tcl_AddErrorInfo(Tkapp_Interp(self
), msg
);
1539 /** Tcl Variable **/
1541 typedef PyObject
* (*EventFunc
)(PyObject
*, PyObject
*args
, int flags
);
1544 TCL_DECLARE_MUTEX(var_mutex
)
1546 typedef struct VarEvent
{
1547 Tcl_Event ev
; /* must be first */
1553 PyObject
**exc_type
;
1555 Tcl_Condition
*cond
;
1560 varname_converter(PyObject
*in
, void *_out
)
1562 char **out
= (char**)_out
;
1563 if (PyString_Check(in
)) {
1564 *out
= PyString_AsString(in
);
1567 if (PyTclObject_Check(in
)) {
1568 *out
= PyTclObject_TclString(in
);
1571 /* XXX: Should give diagnostics. */
1578 var_perform(VarEvent
*ev
)
1580 *(ev
->res
) = ev
->func(ev
->self
, ev
->args
, ev
->flags
);
1582 PyObject
*exc
, *val
, *tb
;
1583 PyErr_Fetch(&exc
, &val
, &tb
);
1584 PyErr_NormalizeException(&exc
, &val
, &tb
);
1585 *(ev
->exc_type
) = exc
;
1586 *(ev
->exc_val
) = val
;
1593 var_proc(VarEvent
* ev
, int flags
)
1597 Tcl_MutexLock(&var_mutex
);
1598 Tcl_ConditionNotify(ev
->cond
);
1599 Tcl_MutexUnlock(&var_mutex
);
1607 var_invoke(EventFunc func
, PyObject
*selfptr
, PyObject
*args
, int flags
)
1610 TkappObject
*self
= (TkappObject
*)selfptr
;
1611 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
1612 TkappObject
*self
= (TkappObject
*)selfptr
;
1614 PyObject
*res
, *exc_type
, *exc_val
;
1615 Tcl_Condition cond
= NULL
;
1617 /* The current thread is not the interpreter thread. Marshal
1618 the call to the interpreter thread, then wait for
1620 if (!WaitForMainloop(self
))
1623 ev
= (VarEvent
*)ckalloc(sizeof(VarEvent
));
1630 ev
->exc_type
= &exc_type
;
1631 ev
->exc_val
= &exc_val
;
1633 ev
->ev
.proc
= (Tcl_EventProc
*)var_proc
;
1634 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &cond
, &var_mutex
);
1635 Tcl_ConditionFinalize(&cond
);
1637 PyErr_SetObject(exc_type
, exc_val
);
1638 Py_DECREF(exc_type
);
1645 /* Tcl is not threaded, or this is the interpreter thread. */
1646 return func(selfptr
, args
, flags
);
1650 SetVar(PyObject
*self
, PyObject
*args
, int flags
)
1652 char *name1
, *name2
;
1654 PyObject
*res
= NULL
;
1655 Tcl_Obj
*newval
, *ok
;
1657 if (PyArg_ParseTuple(args
, "O&O:setvar",
1658 varname_converter
, &name1
, &newValue
)) {
1659 /* XXX Acquire tcl lock??? */
1660 newval
= AsObj(newValue
);
1664 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, NULL
,
1668 Tkinter_Error(self
);
1677 if (PyArg_ParseTuple(args
, "ssO:setvar",
1678 &name1
, &name2
, &newValue
)) {
1679 /* XXX must hold tcl lock already??? */
1680 newval
= AsObj(newValue
);
1682 ok
= Tcl_SetVar2Ex(Tkapp_Interp(self
), name1
, name2
, newval
, flags
);
1685 Tkinter_Error(self
);
1700 Tkapp_SetVar(PyObject
*self
, PyObject
*args
)
1702 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1706 Tkapp_GlobalSetVar(PyObject
*self
, PyObject
*args
)
1708 return var_invoke(SetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1714 GetVar(PyObject
*self
, PyObject
*args
, int flags
)
1716 char *name1
, *name2
=NULL
;
1717 PyObject
*res
= NULL
;
1720 if (!PyArg_ParseTuple(args
, "O&|s:getvar",
1721 varname_converter
, &name1
, &name2
))
1725 tres
= Tcl_GetVar2Ex(Tkapp_Interp(self
), name1
, name2
, flags
);
1728 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
1730 if (((TkappObject
*)self
)->wantobjects
) {
1731 res
= FromObj(self
, tres
);
1734 res
= PyString_FromString(Tcl_GetString(tres
));
1742 Tkapp_GetVar(PyObject
*self
, PyObject
*args
)
1744 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1748 Tkapp_GlobalGetVar(PyObject
*self
, PyObject
*args
)
1750 return var_invoke(GetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1756 UnsetVar(PyObject
*self
, PyObject
*args
, int flags
)
1758 char *name1
, *name2
=NULL
;
1760 PyObject
*res
= NULL
;
1762 if (!PyArg_ParseTuple(args
, "s|s:unsetvar", &name1
, &name2
))
1766 code
= Tcl_UnsetVar2(Tkapp_Interp(self
), name1
, name2
, flags
);
1768 if (code
== TCL_ERROR
)
1769 res
= Tkinter_Error(self
);
1779 Tkapp_UnsetVar(PyObject
*self
, PyObject
*args
)
1781 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
);
1785 Tkapp_GlobalUnsetVar(PyObject
*self
, PyObject
*args
)
1787 return var_invoke(UnsetVar
, self
, args
, TCL_LEAVE_ERR_MSG
| TCL_GLOBAL_ONLY
);
1792 /** Tcl to Python **/
1795 Tkapp_GetInt(PyObject
*self
, PyObject
*args
)
1800 if (PyTuple_Size(args
) == 1) {
1801 PyObject
* o
= PyTuple_GetItem(args
, 0);
1802 if (PyInt_Check(o
)) {
1807 if (!PyArg_ParseTuple(args
, "s:getint", &s
))
1809 if (Tcl_GetInt(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1810 return Tkinter_Error(self
);
1811 return Py_BuildValue("i", v
);
1815 Tkapp_GetDouble(PyObject
*self
, PyObject
*args
)
1820 if (PyTuple_Size(args
) == 1) {
1821 PyObject
*o
= PyTuple_GetItem(args
, 0);
1822 if (PyFloat_Check(o
)) {
1827 if (!PyArg_ParseTuple(args
, "s:getdouble", &s
))
1829 if (Tcl_GetDouble(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1830 return Tkinter_Error(self
);
1831 return Py_BuildValue("d", v
);
1835 Tkapp_GetBoolean(PyObject
*self
, PyObject
*args
)
1840 if (PyTuple_Size(args
) == 1) {
1841 PyObject
*o
= PyTuple_GetItem(args
, 0);
1842 if (PyInt_Check(o
)) {
1847 if (!PyArg_ParseTuple(args
, "s:getboolean", &s
))
1849 if (Tcl_GetBoolean(Tkapp_Interp(self
), s
, &v
) == TCL_ERROR
)
1850 return Tkinter_Error(self
);
1851 return PyBool_FromLong(v
);
1855 Tkapp_ExprString(PyObject
*self
, PyObject
*args
)
1858 PyObject
*res
= NULL
;
1861 if (!PyArg_ParseTuple(args
, "s:exprstring", &s
))
1864 CHECK_TCL_APPARTMENT
;
1867 retval
= Tcl_ExprString(Tkapp_Interp(self
), s
);
1869 if (retval
== TCL_ERROR
)
1870 res
= Tkinter_Error(self
);
1872 res
= Py_BuildValue("s", Tkapp_Result(self
));
1878 Tkapp_ExprLong(PyObject
*self
, PyObject
*args
)
1881 PyObject
*res
= NULL
;
1885 if (!PyArg_ParseTuple(args
, "s:exprlong", &s
))
1888 CHECK_TCL_APPARTMENT
;
1891 retval
= Tcl_ExprLong(Tkapp_Interp(self
), s
, &v
);
1893 if (retval
== TCL_ERROR
)
1894 res
= Tkinter_Error(self
);
1896 res
= Py_BuildValue("l", v
);
1902 Tkapp_ExprDouble(PyObject
*self
, PyObject
*args
)
1905 PyObject
*res
= NULL
;
1909 if (!PyArg_ParseTuple(args
, "s:exprdouble", &s
))
1911 CHECK_TCL_APPARTMENT
;
1912 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1914 retval
= Tcl_ExprDouble(Tkapp_Interp(self
), s
, &v
);
1916 PyFPE_END_PROTECT(retval
)
1917 if (retval
== TCL_ERROR
)
1918 res
= Tkinter_Error(self
);
1920 res
= Py_BuildValue("d", v
);
1926 Tkapp_ExprBoolean(PyObject
*self
, PyObject
*args
)
1929 PyObject
*res
= NULL
;
1933 if (!PyArg_ParseTuple(args
, "s:exprboolean", &s
))
1935 CHECK_TCL_APPARTMENT
;
1937 retval
= Tcl_ExprBoolean(Tkapp_Interp(self
), s
, &v
);
1939 if (retval
== TCL_ERROR
)
1940 res
= Tkinter_Error(self
);
1942 res
= Py_BuildValue("i", v
);
1950 Tkapp_SplitList(PyObject
*self
, PyObject
*args
)
1958 if (PyTuple_Size(args
) == 1) {
1959 v
= PyTuple_GetItem(args
, 0);
1960 if (PyTuple_Check(v
)) {
1965 if (!PyArg_ParseTuple(args
, "et:splitlist", "utf-8", &list
))
1968 if (Tcl_SplitList(Tkapp_Interp(self
), list
,
1969 &argc
, &argv
) == TCL_ERROR
) {
1971 return Tkinter_Error(self
);
1974 if (!(v
= PyTuple_New(argc
)))
1977 for (i
= 0; i
< argc
; i
++) {
1978 PyObject
*s
= PyString_FromString(argv
[i
]);
1979 if (!s
|| PyTuple_SetItem(v
, i
, s
)) {
1987 ckfree(FREECAST argv
);
1993 Tkapp_Split(PyObject
*self
, PyObject
*args
)
1998 if (PyTuple_Size(args
) == 1) {
1999 PyObject
* o
= PyTuple_GetItem(args
, 0);
2000 if (PyTuple_Check(o
)) {
2005 if (!PyArg_ParseTuple(args
, "et:split", "utf-8", &list
))
2013 Tkapp_Merge(PyObject
*self
, PyObject
*args
)
2015 char *s
= Merge(args
);
2016 PyObject
*res
= NULL
;
2019 res
= PyString_FromString(s
);
2030 /* Client data struct */
2034 } PythonCmd_ClientData
;
2037 PythonCmd_Error(Tcl_Interp
*interp
)
2040 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2045 /* This is the Tcl command that acts as a wrapper for Python
2046 * function or method.
2049 PythonCmd(ClientData clientData
, Tcl_Interp
*interp
, int argc
, char *argv
[])
2051 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
2052 PyObject
*self
, *func
, *arg
, *res
;
2058 /* TBD: no error checking here since we know, via the
2059 * Tkapp_CreateCommand() that the client data is a two-tuple
2064 /* Create argument list (argv1, ..., argvN) */
2065 if (!(arg
= PyTuple_New(argc
- 1)))
2066 return PythonCmd_Error(interp
);
2068 for (i
= 0; i
< (argc
- 1); i
++) {
2069 PyObject
*s
= PyString_FromString(argv
[i
+ 1]);
2070 if (!s
|| PyTuple_SetItem(arg
, i
, s
)) {
2072 return PythonCmd_Error(interp
);
2075 res
= PyEval_CallObject(func
, arg
);
2079 return PythonCmd_Error(interp
);
2081 obj_res
= AsObj(res
);
2082 if (obj_res
== NULL
) {
2084 return PythonCmd_Error(interp
);
2087 Tcl_SetObjResult(interp
, obj_res
);
2099 PythonCmdDelete(ClientData clientData
)
2101 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
2104 Py_XDECREF(data
->self
);
2105 Py_XDECREF(data
->func
);
2114 TCL_DECLARE_MUTEX(command_mutex
)
2116 typedef struct CommandEvent
{
2123 Tcl_Condition
*done
;
2127 Tkapp_CommandProc(CommandEvent
*ev
, int flags
)
2130 *ev
->status
= Tcl_CreateCommand(
2131 ev
->interp
, ev
->name
, PythonCmd
,
2132 ev
->data
, PythonCmdDelete
) == NULL
;
2134 *ev
->status
= Tcl_DeleteCommand(ev
->interp
, ev
->name
);
2135 Tcl_MutexLock(&command_mutex
);
2136 Tcl_ConditionNotify(ev
->done
);
2137 Tcl_MutexUnlock(&command_mutex
);
2143 Tkapp_CreateCommand(PyObject
*selfptr
, PyObject
*args
)
2145 TkappObject
*self
= (TkappObject
*)selfptr
;
2146 PythonCmd_ClientData
*data
;
2151 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
2153 if (!PyCallable_Check(func
)) {
2154 PyErr_SetString(PyExc_TypeError
, "command not callable");
2159 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread() &&
2160 !WaitForMainloop(self
))
2164 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
2166 return PyErr_NoMemory();
2169 data
->self
= selfptr
;
2173 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2174 Tcl_Condition cond
= NULL
;
2175 CommandEvent
*ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2176 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2177 ev
->interp
= self
->interp
;
2180 ev
->data
= (ClientData
)data
;
2183 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &cond
, &command_mutex
);
2184 Tcl_ConditionFinalize(&cond
);
2190 err
= Tcl_CreateCommand(
2191 Tkapp_Interp(self
), cmdName
, PythonCmd
,
2192 (ClientData
)data
, PythonCmdDelete
) == NULL
;
2196 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
2208 Tkapp_DeleteCommand(PyObject
*selfptr
, PyObject
*args
)
2210 TkappObject
*self
= (TkappObject
*)selfptr
;
2214 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
2218 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2219 Tcl_Condition cond
= NULL
;
2221 ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2222 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2223 ev
->interp
= self
->interp
;
2228 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &cond
,
2230 Tcl_ConditionFinalize(&cond
);
2236 err
= Tcl_DeleteCommand(self
->interp
, cmdName
);
2240 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
2249 #ifdef HAVE_CREATEFILEHANDLER
2250 /** File Handler **/
2252 typedef struct _fhcdata
{
2256 struct _fhcdata
*next
;
2257 } FileHandler_ClientData
;
2259 static FileHandler_ClientData
*HeadFHCD
;
2261 static FileHandler_ClientData
*
2262 NewFHCD(PyObject
*func
, PyObject
*file
, int id
)
2264 FileHandler_ClientData
*p
;
2265 p
= PyMem_NEW(FileHandler_ClientData
, 1);
2281 FileHandler_ClientData
*p
, **pp
;
2284 while ((p
= *pp
) != NULL
) {
2287 Py_XDECREF(p
->func
);
2288 Py_XDECREF(p
->file
);
2297 FileHandler(ClientData clientData
, int mask
)
2299 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
2300 PyObject
*func
, *file
, *arg
, *res
;
2306 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
2307 res
= PyEval_CallObject(func
, arg
);
2312 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2319 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
2320 /* args is (file, mask, func) */
2322 FileHandler_ClientData
*data
;
2323 PyObject
*file
, *func
;
2326 if (!self
&& Py_Py3kWarningFlag
) {
2327 if (PyErr_Warn(PyExc_DeprecationWarning
,
2328 "_tkinter.createfilehandler is gone in 3.x") < 0)
2332 if (!PyArg_ParseTuple(args
, "OiO:createfilehandler",
2333 &file
, &mask
, &func
))
2337 if (!self
&& !tcl_lock
) {
2338 /* We don't have the Tcl lock since Tcl is threaded. */
2339 PyErr_SetString(PyExc_RuntimeError
,
2340 "_tkinter.createfilehandler not supported "
2341 "for threaded Tcl");
2347 CHECK_TCL_APPARTMENT
;
2350 tfile
= PyObject_AsFileDescriptor(file
);
2353 if (!PyCallable_Check(func
)) {
2354 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2358 data
= NewFHCD(func
, file
, tfile
);
2362 /* Ought to check for null Tcl_File object... */
2364 Tcl_CreateFileHandler(tfile
, mask
, FileHandler
, (ClientData
) data
);
2371 Tkapp_DeleteFileHandler(PyObject
*self
, PyObject
*args
)
2376 if (!self
&& Py_Py3kWarningFlag
) {
2377 if (PyErr_Warn(PyExc_DeprecationWarning
,
2378 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2382 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
2386 if (!self
&& !tcl_lock
) {
2387 /* We don't have the Tcl lock since Tcl is threaded. */
2388 PyErr_SetString(PyExc_RuntimeError
,
2389 "_tkinter.deletefilehandler not supported "
2390 "for threaded Tcl");
2396 CHECK_TCL_APPARTMENT
;
2399 tfile
= PyObject_AsFileDescriptor(file
);
2405 /* Ought to check for null Tcl_File object... */
2407 Tcl_DeleteFileHandler(tfile
);
2412 #endif /* HAVE_CREATEFILEHANDLER */
2415 /**** Tktt Object (timer token) ****/
2417 static PyTypeObject Tktt_Type
;
2421 Tcl_TimerToken token
;
2426 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
2428 TkttObject
*v
= (TkttObject
*)self
;
2429 PyObject
*func
= v
->func
;
2431 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
2433 if (v
->token
!= NULL
) {
2434 Tcl_DeleteTimerHandler(v
->token
);
2440 Py_DECREF(v
); /* See Tktt_New() */
2446 static PyMethodDef Tktt_methods
[] =
2448 {"deletetimerhandler", Tktt_DeleteTimerHandler
, METH_VARARGS
},
2453 Tktt_New(PyObject
*func
)
2457 v
= PyObject_New(TkttObject
, &Tktt_Type
);
2465 /* Extra reference, deleted when called or when handler is deleted */
2471 Tktt_Dealloc(PyObject
*self
)
2473 TkttObject
*v
= (TkttObject
*)self
;
2474 PyObject
*func
= v
->func
;
2482 Tktt_Repr(PyObject
*self
)
2484 TkttObject
*v
= (TkttObject
*)self
;
2487 PyOS_snprintf(buf
, sizeof(buf
), "<tktimertoken at %p%s>", v
,
2488 v
->func
== NULL
? ", handler deleted" : "");
2489 return PyString_FromString(buf
);
2493 Tktt_GetAttr(PyObject
*self
, char *name
)
2495 return Py_FindMethod(Tktt_methods
, self
, name
);
2498 static PyTypeObject Tktt_Type
=
2500 PyVarObject_HEAD_INIT(NULL
, 0)
2501 "tktimertoken", /*tp_name */
2502 sizeof(TkttObject
), /*tp_basicsize */
2504 Tktt_Dealloc
, /*tp_dealloc */
2506 Tktt_GetAttr
, /*tp_getattr */
2509 Tktt_Repr
, /*tp_repr */
2510 0, /*tp_as_number */
2511 0, /*tp_as_sequence */
2512 0, /*tp_as_mapping */
2518 /** Timer Handler **/
2521 TimerHandler(ClientData clientData
)
2523 TkttObject
*v
= (TkttObject
*)clientData
;
2524 PyObject
*func
= v
->func
;
2534 res
= PyEval_CallObject(func
, NULL
);
2536 Py_DECREF(v
); /* See Tktt_New() */
2540 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2549 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
2555 if (!self
&& Py_Py3kWarningFlag
) {
2556 if (PyErr_Warn(PyExc_DeprecationWarning
,
2557 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2561 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler",
2562 &milliseconds
, &func
))
2564 if (!PyCallable_Check(func
)) {
2565 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2570 if (!self
&& !tcl_lock
) {
2571 /* We don't have the Tcl lock since Tcl is threaded. */
2572 PyErr_SetString(PyExc_RuntimeError
,
2573 "_tkinter.createtimerhandler not supported "
2574 "for threaded Tcl");
2580 CHECK_TCL_APPARTMENT
;
2585 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
2589 return (PyObject
*) v
;
2596 Tkapp_MainLoop(PyObject
*selfptr
, PyObject
*args
)
2599 TkappObject
*self
= (TkappObject
*)selfptr
;
2601 PyThreadState
*tstate
= PyThreadState_Get();
2604 if (!self
&& Py_Py3kWarningFlag
) {
2605 if (PyErr_Warn(PyExc_DeprecationWarning
,
2606 "_tkinter.mainloop is gone in 3.x") < 0)
2610 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
2614 if (!self
&& !tcl_lock
) {
2615 /* We don't have the Tcl lock since Tcl is threaded. */
2616 PyErr_SetString(PyExc_RuntimeError
,
2617 "_tkinter.mainloop not supported "
2618 "for threaded Tcl");
2624 CHECK_TCL_APPARTMENT
;
2625 self
->dispatching
= 1;
2629 while (Tk_GetNumMainWindows() > threshold
&&
2636 if (self
&& self
->threaded
) {
2637 /* Allow other Python threads to run. */
2639 result
= Tcl_DoOneEvent(0);
2643 Py_BEGIN_ALLOW_THREADS
2644 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
2645 tcl_tstate
= tstate
;
2646 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
2648 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
2650 Sleep(Tkinter_busywaitinterval
);
2651 Py_END_ALLOW_THREADS
2654 result
= Tcl_DoOneEvent(0);
2657 if (PyErr_CheckSignals() != 0) {
2659 self
->dispatching
= 0;
2666 self
->dispatching
= 0;
2671 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2672 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2680 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
2685 if (!self
&& Py_Py3kWarningFlag
) {
2686 if (PyErr_Warn(PyExc_DeprecationWarning
,
2687 "_tkinter.dooneevent is gone in 3.x") < 0)
2691 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
2695 rv
= Tcl_DoOneEvent(flags
);
2697 return Py_BuildValue("i", rv
);
2701 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
2704 if (!self
&& Py_Py3kWarningFlag
) {
2705 if (PyErr_Warn(PyExc_DeprecationWarning
,
2706 "_tkinter.quit is gone in 3.x") < 0)
2710 if (!PyArg_ParseTuple(args
, ":quit"))
2719 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
2722 if (!PyArg_ParseTuple(args
, ":interpaddr"))
2725 return PyInt_FromLong((long)Tkapp_Interp(self
));
2729 Tkapp_TkInit(PyObject
*self
, PyObject
*args
)
2731 Tcl_Interp
*interp
= Tkapp_Interp(self
);
2732 const char * _tk_exists
= NULL
;
2735 #ifdef TKINTER_PROTECT_LOADTK
2736 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2737 * first call failed.
2738 * To avoid the deadlock, we just refuse the second call through
2739 * a static variable.
2741 if (tk_load_failed
) {
2742 PyErr_SetString(Tkinter_TclError
, TKINTER_LOADTK_ERRMSG
);
2747 /* We want to guard against calling Tk_Init() multiple times */
2748 CHECK_TCL_APPARTMENT
;
2750 err
= Tcl_Eval(Tkapp_Interp(self
), "info exists tk_version");
2752 if (err
== TCL_ERROR
) {
2753 /* This sets an exception, but we cannot return right
2754 away because we need to exit the overlap first. */
2755 Tkinter_Error(self
);
2757 _tk_exists
= Tkapp_Result(self
);
2760 if (err
== TCL_ERROR
) {
2763 if (_tk_exists
== NULL
|| strcmp(_tk_exists
, "1") != 0) {
2764 if (Tk_Init(interp
) == TCL_ERROR
) {
2765 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
2766 #ifdef TKINTER_PROTECT_LOADTK
2777 Tkapp_WantObjects(PyObject
*self
, PyObject
*args
)
2780 int wantobjects
= -1;
2781 if (!PyArg_ParseTuple(args
, "|i:wantobjects", &wantobjects
))
2783 if (wantobjects
== -1)
2784 return PyBool_FromLong(((TkappObject
*)self
)->wantobjects
);
2785 ((TkappObject
*)self
)->wantobjects
= wantobjects
;
2792 Tkapp_WillDispatch(PyObject
*self
, PyObject
*args
)
2795 ((TkappObject
*)self
)->dispatching
= 1;
2802 /**** Tkapp Method List ****/
2804 static PyMethodDef Tkapp_methods
[] =
2806 {"willdispatch", Tkapp_WillDispatch
, METH_NOARGS
},
2807 {"wantobjects", Tkapp_WantObjects
, METH_VARARGS
},
2808 {"call", Tkapp_Call
, METH_VARARGS
},
2809 {"globalcall", Tkapp_GlobalCall
, METH_VARARGS
},
2810 {"eval", Tkapp_Eval
, METH_VARARGS
},
2811 {"globaleval", Tkapp_GlobalEval
, METH_VARARGS
},
2812 {"evalfile", Tkapp_EvalFile
, METH_VARARGS
},
2813 {"record", Tkapp_Record
, METH_VARARGS
},
2814 {"adderrorinfo", Tkapp_AddErrorInfo
, METH_VARARGS
},
2815 {"setvar", Tkapp_SetVar
, METH_VARARGS
},
2816 {"globalsetvar", Tkapp_GlobalSetVar
, METH_VARARGS
},
2817 {"getvar", Tkapp_GetVar
, METH_VARARGS
},
2818 {"globalgetvar", Tkapp_GlobalGetVar
, METH_VARARGS
},
2819 {"unsetvar", Tkapp_UnsetVar
, METH_VARARGS
},
2820 {"globalunsetvar", Tkapp_GlobalUnsetVar
, METH_VARARGS
},
2821 {"getint", Tkapp_GetInt
, METH_VARARGS
},
2822 {"getdouble", Tkapp_GetDouble
, METH_VARARGS
},
2823 {"getboolean", Tkapp_GetBoolean
, METH_VARARGS
},
2824 {"exprstring", Tkapp_ExprString
, METH_VARARGS
},
2825 {"exprlong", Tkapp_ExprLong
, METH_VARARGS
},
2826 {"exprdouble", Tkapp_ExprDouble
, METH_VARARGS
},
2827 {"exprboolean", Tkapp_ExprBoolean
, METH_VARARGS
},
2828 {"splitlist", Tkapp_SplitList
, METH_VARARGS
},
2829 {"split", Tkapp_Split
, METH_VARARGS
},
2830 {"merge", Tkapp_Merge
, METH_VARARGS
},
2831 {"createcommand", Tkapp_CreateCommand
, METH_VARARGS
},
2832 {"deletecommand", Tkapp_DeleteCommand
, METH_VARARGS
},
2833 #ifdef HAVE_CREATEFILEHANDLER
2834 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
2835 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
2837 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
2838 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
2839 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
2840 {"quit", Tkapp_Quit
, METH_VARARGS
},
2841 {"interpaddr", Tkapp_InterpAddr
, METH_VARARGS
},
2842 {"loadtk", Tkapp_TkInit
, METH_NOARGS
},
2848 /**** Tkapp Type Methods ****/
2851 Tkapp_Dealloc(PyObject
*self
)
2853 /*CHECK_TCL_APPARTMENT;*/
2855 Tcl_DeleteInterp(Tkapp_Interp(self
));
2862 Tkapp_GetAttr(PyObject
*self
, char *name
)
2864 return Py_FindMethod(Tkapp_methods
, self
, name
);
2867 static PyTypeObject Tkapp_Type
=
2869 PyVarObject_HEAD_INIT(NULL
, 0)
2870 "tkapp", /*tp_name */
2871 sizeof(TkappObject
), /*tp_basicsize */
2873 Tkapp_Dealloc
, /*tp_dealloc */
2875 Tkapp_GetAttr
, /*tp_getattr */
2879 0, /*tp_as_number */
2880 0, /*tp_as_sequence */
2881 0, /*tp_as_mapping */
2887 /**** Tkinter Module ****/
2891 int size
; /* current size */
2892 int maxsize
; /* allocated size */
2896 _bump(FlattenContext
* context
, int size
)
2898 /* expand tuple to hold (at least) size new items.
2899 return true if successful, false if an exception was raised */
2901 int maxsize
= context
->maxsize
* 2;
2903 if (maxsize
< context
->size
+ size
)
2904 maxsize
= context
->size
+ size
;
2906 context
->maxsize
= maxsize
;
2908 return _PyTuple_Resize(&context
->tuple
, maxsize
) >= 0;
2912 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
2914 /* add tuple or list to argument tuple (recursively) */
2919 PyErr_SetString(PyExc_ValueError
,
2920 "nesting too deep in _flatten");
2922 } else if (PyList_Check(item
)) {
2923 size
= PyList_GET_SIZE(item
);
2924 /* preallocate (assume no nesting) */
2925 if (context
->size
+ size
> context
->maxsize
&&
2926 !_bump(context
, size
))
2928 /* copy items to output tuple */
2929 for (i
= 0; i
< size
; i
++) {
2930 PyObject
*o
= PyList_GET_ITEM(item
, i
);
2931 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2932 if (!_flatten1(context
, o
, depth
+ 1))
2934 } else if (o
!= Py_None
) {
2935 if (context
->size
+ 1 > context
->maxsize
&&
2939 PyTuple_SET_ITEM(context
->tuple
,
2940 context
->size
++, o
);
2943 } else if (PyTuple_Check(item
)) {
2944 /* same, for tuples */
2945 size
= PyTuple_GET_SIZE(item
);
2946 if (context
->size
+ size
> context
->maxsize
&&
2947 !_bump(context
, size
))
2949 for (i
= 0; i
< size
; i
++) {
2950 PyObject
*o
= PyTuple_GET_ITEM(item
, i
);
2951 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2952 if (!_flatten1(context
, o
, depth
+ 1))
2954 } else if (o
!= Py_None
) {
2955 if (context
->size
+ 1 > context
->maxsize
&&
2959 PyTuple_SET_ITEM(context
->tuple
,
2960 context
->size
++, o
);
2964 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
2971 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
2973 FlattenContext context
;
2976 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
2979 context
.maxsize
= PySequence_Size(item
);
2980 if (context
.maxsize
< 0)
2982 if (context
.maxsize
== 0)
2983 return PyTuple_New(0);
2985 context
.tuple
= PyTuple_New(context
.maxsize
);
2991 if (!_flatten1(&context
, item
,0))
2994 if (_PyTuple_Resize(&context
.tuple
, context
.size
))
2997 return context
.tuple
;
3001 Tkinter_Create(PyObject
*self
, PyObject
*args
)
3003 char *screenName
= NULL
;
3004 char *baseName
= NULL
;
3005 char *className
= NULL
;
3006 int interactive
= 0;
3007 int wantobjects
= 0;
3008 int wantTk
= 1; /* If false, then Tk_Init() doesn't get called */
3009 int sync
= 0; /* pass -sync to wish */
3010 char *use
= NULL
; /* pass -use to wish */
3012 baseName
= strrchr(Py_GetProgramName(), '/');
3013 if (baseName
!= NULL
)
3016 baseName
= Py_GetProgramName();
3019 if (!PyArg_ParseTuple(args
, "|zssiiiiz:create",
3020 &screenName
, &baseName
, &className
,
3021 &interactive
, &wantobjects
, &wantTk
,
3025 return (PyObject
*) Tkapp_New(screenName
, baseName
, className
,
3026 interactive
, wantobjects
, wantTk
,
3031 Tkinter_setbusywaitinterval(PyObject
*self
, PyObject
*args
)
3034 if (!PyArg_ParseTuple(args
, "i:setbusywaitinterval", &new_val
))
3037 PyErr_SetString(PyExc_ValueError
,
3038 "busywaitinterval must be >= 0");
3041 Tkinter_busywaitinterval
= new_val
;
3046 static char setbusywaitinterval_doc
[] =
3047 "setbusywaitinterval(n) -> None\n\
3049 Set the busy-wait interval in milliseconds between successive\n\
3050 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3051 It should be set to a divisor of the maximum time between\n\
3052 frames in an animation.";
3055 Tkinter_getbusywaitinterval(PyObject
*self
, PyObject
*args
)
3057 return PyInt_FromLong(Tkinter_busywaitinterval
);
3060 static char getbusywaitinterval_doc
[] =
3061 "getbusywaitinterval() -> int\n\
3063 Return the current busy-wait interval between successive\n\
3064 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3066 static PyMethodDef moduleMethods
[] =
3068 {"_flatten", Tkinter_Flatten
, METH_VARARGS
},
3069 {"create", Tkinter_Create
, METH_VARARGS
},
3070 #ifdef HAVE_CREATEFILEHANDLER
3071 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
3072 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
3074 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
3075 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
3076 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
3077 {"quit", Tkapp_Quit
, METH_VARARGS
},
3078 {"setbusywaitinterval",Tkinter_setbusywaitinterval
, METH_VARARGS
,
3079 setbusywaitinterval_doc
},
3080 {"getbusywaitinterval",(PyCFunction
)Tkinter_getbusywaitinterval
,
3081 METH_NOARGS
, getbusywaitinterval_doc
},
3085 #ifdef WAIT_FOR_STDIN
3087 static int stdin_ready
= 0;
3091 MyFileProc(void *clientData
, int mask
)
3098 static PyThreadState
*event_tstate
= NULL
;
3108 PyEval_RestoreThread(event_tstate
);
3113 tfile
= fileno(stdin
);
3114 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
3116 while (!errorInCmd
&& !stdin_ready
) {
3124 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3125 Py_BEGIN_ALLOW_THREADS
3126 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
3127 tcl_tstate
= event_tstate
;
3129 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
3132 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
3134 Sleep(Tkinter_busywaitinterval
);
3135 Py_END_ALLOW_THREADS
3137 result
= Tcl_DoOneEvent(0);
3144 Tcl_DeleteFileHandler(tfile
);
3148 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
3149 excInCmd
= valInCmd
= trbInCmd
= NULL
;
3153 PyEval_SaveThread();
3161 EnableEventHook(void)
3163 #ifdef WAIT_FOR_STDIN
3164 if (PyOS_InputHook
== NULL
) {
3166 event_tstate
= PyThreadState_Get();
3168 PyOS_InputHook
= EventHook
;
3174 DisableEventHook(void)
3176 #ifdef WAIT_FOR_STDIN
3177 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
3178 PyOS_InputHook
= NULL
;
3184 /* all errors will be checked in one fell swoop in init_tkinter() */
3186 ins_long(PyObject
*d
, char *name
, long val
)
3188 PyObject
*v
= PyInt_FromLong(val
);
3190 PyDict_SetItemString(d
, name
, v
);
3195 ins_string(PyObject
*d
, char *name
, char *val
)
3197 PyObject
*v
= PyString_FromString(val
);
3199 PyDict_SetItemString(d
, name
, v
);
3210 Py_TYPE(&Tkapp_Type
) = &PyType_Type
;
3213 tcl_lock
= PyThread_allocate_lock();
3216 m
= Py_InitModule("_tkinter", moduleMethods
);
3220 d
= PyModule_GetDict(m
);
3221 Tkinter_TclError
= PyErr_NewException("_tkinter.TclError", NULL
, NULL
);
3222 PyDict_SetItemString(d
, "TclError", Tkinter_TclError
);
3224 ins_long(d
, "READABLE", TCL_READABLE
);
3225 ins_long(d
, "WRITABLE", TCL_WRITABLE
);
3226 ins_long(d
, "EXCEPTION", TCL_EXCEPTION
);
3227 ins_long(d
, "WINDOW_EVENTS", TCL_WINDOW_EVENTS
);
3228 ins_long(d
, "FILE_EVENTS", TCL_FILE_EVENTS
);
3229 ins_long(d
, "TIMER_EVENTS", TCL_TIMER_EVENTS
);
3230 ins_long(d
, "IDLE_EVENTS", TCL_IDLE_EVENTS
);
3231 ins_long(d
, "ALL_EVENTS", TCL_ALL_EVENTS
);
3232 ins_long(d
, "DONT_WAIT", TCL_DONT_WAIT
);
3233 ins_string(d
, "TK_VERSION", TK_VERSION
);
3234 ins_string(d
, "TCL_VERSION", TCL_VERSION
);
3236 PyDict_SetItemString(d
, "TkappType", (PyObject
*)&Tkapp_Type
);
3238 Py_TYPE(&Tktt_Type
) = &PyType_Type
;
3239 PyDict_SetItemString(d
, "TkttType", (PyObject
*)&Tktt_Type
);
3241 Py_TYPE(&PyTclObject_Type
) = &PyType_Type
;
3242 PyDict_SetItemString(d
, "Tcl_Obj", (PyObject
*)&PyTclObject_Type
);
3245 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3246 * start waking up. Note that Tcl_FindExecutable will do this, this
3247 * code must be above it! The original warning from
3248 * tkMacOSXAppInit.c is copied below.
3250 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3251 * Tcl interpreter for now. It probably should work to do this
3252 * in the other order, but for now it doesn't seem to.
3255 Tk_MacOSXSetupTkNotifier();
3259 /* This helps the dynamic loader; in Unicode aware Tcl versions
3260 it also helps Tcl find its encodings. */
3261 Tcl_FindExecutable(Py_GetProgramName());
3263 if (PyErr_Occurred())
3267 /* This was not a good idea; through <Destroy> bindings,
3268 Tcl_Finalize() may invoke Python code but at that point the
3269 interpreter and thread state have already been destroyed! */
3270 Py_AtExit(Tcl_Finalize
);