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
*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
2063 /* Create argument list (argv1, ..., argvN) */
2064 if (!(arg
= PyTuple_New(argc
- 1)))
2065 return PythonCmd_Error(interp
);
2067 for (i
= 0; i
< (argc
- 1); i
++) {
2068 PyObject
*s
= PyString_FromString(argv
[i
+ 1]);
2069 if (!s
|| PyTuple_SetItem(arg
, i
, s
)) {
2071 return PythonCmd_Error(interp
);
2074 res
= PyEval_CallObject(func
, arg
);
2078 return PythonCmd_Error(interp
);
2080 obj_res
= AsObj(res
);
2081 if (obj_res
== NULL
) {
2083 return PythonCmd_Error(interp
);
2086 Tcl_SetObjResult(interp
, obj_res
);
2098 PythonCmdDelete(ClientData clientData
)
2100 PythonCmd_ClientData
*data
= (PythonCmd_ClientData
*)clientData
;
2103 Py_XDECREF(data
->self
);
2104 Py_XDECREF(data
->func
);
2113 TCL_DECLARE_MUTEX(command_mutex
)
2115 typedef struct CommandEvent
{
2122 Tcl_Condition
*done
;
2126 Tkapp_CommandProc(CommandEvent
*ev
, int flags
)
2129 *ev
->status
= Tcl_CreateCommand(
2130 ev
->interp
, ev
->name
, PythonCmd
,
2131 ev
->data
, PythonCmdDelete
) == NULL
;
2133 *ev
->status
= Tcl_DeleteCommand(ev
->interp
, ev
->name
);
2134 Tcl_MutexLock(&command_mutex
);
2135 Tcl_ConditionNotify(ev
->done
);
2136 Tcl_MutexUnlock(&command_mutex
);
2142 Tkapp_CreateCommand(PyObject
*selfptr
, PyObject
*args
)
2144 TkappObject
*self
= (TkappObject
*)selfptr
;
2145 PythonCmd_ClientData
*data
;
2150 if (!PyArg_ParseTuple(args
, "sO:createcommand", &cmdName
, &func
))
2152 if (!PyCallable_Check(func
)) {
2153 PyErr_SetString(PyExc_TypeError
, "command not callable");
2158 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread() &&
2159 !WaitForMainloop(self
))
2163 data
= PyMem_NEW(PythonCmd_ClientData
, 1);
2165 return PyErr_NoMemory();
2168 data
->self
= selfptr
;
2172 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2173 Tcl_Condition cond
= NULL
;
2174 CommandEvent
*ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2175 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2176 ev
->interp
= self
->interp
;
2179 ev
->data
= (ClientData
)data
;
2182 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &cond
, &command_mutex
);
2183 Tcl_ConditionFinalize(&cond
);
2189 err
= Tcl_CreateCommand(
2190 Tkapp_Interp(self
), cmdName
, PythonCmd
,
2191 (ClientData
)data
, PythonCmdDelete
) == NULL
;
2195 PyErr_SetString(Tkinter_TclError
, "can't create Tcl command");
2207 Tkapp_DeleteCommand(PyObject
*selfptr
, PyObject
*args
)
2209 TkappObject
*self
= (TkappObject
*)selfptr
;
2213 if (!PyArg_ParseTuple(args
, "s:deletecommand", &cmdName
))
2217 if (self
->threaded
&& self
->thread_id
!= Tcl_GetCurrentThread()) {
2218 Tcl_Condition cond
= NULL
;
2220 ev
= (CommandEvent
*)ckalloc(sizeof(CommandEvent
));
2221 ev
->ev
.proc
= (Tcl_EventProc
*)Tkapp_CommandProc
;
2222 ev
->interp
= self
->interp
;
2227 Tkapp_ThreadSend(self
, (Tcl_Event
*)ev
, &cond
,
2229 Tcl_ConditionFinalize(&cond
);
2235 err
= Tcl_DeleteCommand(self
->interp
, cmdName
);
2239 PyErr_SetString(Tkinter_TclError
, "can't delete Tcl command");
2248 #ifdef HAVE_CREATEFILEHANDLER
2249 /** File Handler **/
2251 typedef struct _fhcdata
{
2255 struct _fhcdata
*next
;
2256 } FileHandler_ClientData
;
2258 static FileHandler_ClientData
*HeadFHCD
;
2260 static FileHandler_ClientData
*
2261 NewFHCD(PyObject
*func
, PyObject
*file
, int id
)
2263 FileHandler_ClientData
*p
;
2264 p
= PyMem_NEW(FileHandler_ClientData
, 1);
2280 FileHandler_ClientData
*p
, **pp
;
2283 while ((p
= *pp
) != NULL
) {
2286 Py_XDECREF(p
->func
);
2287 Py_XDECREF(p
->file
);
2296 FileHandler(ClientData clientData
, int mask
)
2298 FileHandler_ClientData
*data
= (FileHandler_ClientData
*)clientData
;
2299 PyObject
*func
, *file
, *arg
, *res
;
2305 arg
= Py_BuildValue("(Oi)", file
, (long) mask
);
2306 res
= PyEval_CallObject(func
, arg
);
2311 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2318 Tkapp_CreateFileHandler(PyObject
*self
, PyObject
*args
)
2319 /* args is (file, mask, func) */
2321 FileHandler_ClientData
*data
;
2322 PyObject
*file
, *func
;
2325 if (!self
&& Py_Py3kWarningFlag
) {
2326 if (PyErr_Warn(PyExc_DeprecationWarning
,
2327 "_tkinter.createfilehandler is gone in 3.x") < 0)
2331 if (!PyArg_ParseTuple(args
, "OiO:createfilehandler",
2332 &file
, &mask
, &func
))
2336 if (!self
&& !tcl_lock
) {
2337 /* We don't have the Tcl lock since Tcl is threaded. */
2338 PyErr_SetString(PyExc_RuntimeError
,
2339 "_tkinter.createfilehandler not supported "
2340 "for threaded Tcl");
2346 CHECK_TCL_APPARTMENT
;
2349 tfile
= PyObject_AsFileDescriptor(file
);
2352 if (!PyCallable_Check(func
)) {
2353 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2357 data
= NewFHCD(func
, file
, tfile
);
2361 /* Ought to check for null Tcl_File object... */
2363 Tcl_CreateFileHandler(tfile
, mask
, FileHandler
, (ClientData
) data
);
2370 Tkapp_DeleteFileHandler(PyObject
*self
, PyObject
*args
)
2375 if (!self
&& Py_Py3kWarningFlag
) {
2376 if (PyErr_Warn(PyExc_DeprecationWarning
,
2377 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2381 if (!PyArg_ParseTuple(args
, "O:deletefilehandler", &file
))
2385 if (!self
&& !tcl_lock
) {
2386 /* We don't have the Tcl lock since Tcl is threaded. */
2387 PyErr_SetString(PyExc_RuntimeError
,
2388 "_tkinter.deletefilehandler not supported "
2389 "for threaded Tcl");
2395 CHECK_TCL_APPARTMENT
;
2398 tfile
= PyObject_AsFileDescriptor(file
);
2404 /* Ought to check for null Tcl_File object... */
2406 Tcl_DeleteFileHandler(tfile
);
2411 #endif /* HAVE_CREATEFILEHANDLER */
2414 /**** Tktt Object (timer token) ****/
2416 static PyTypeObject Tktt_Type
;
2420 Tcl_TimerToken token
;
2425 Tktt_DeleteTimerHandler(PyObject
*self
, PyObject
*args
)
2427 TkttObject
*v
= (TkttObject
*)self
;
2428 PyObject
*func
= v
->func
;
2430 if (!PyArg_ParseTuple(args
, ":deletetimerhandler"))
2432 if (v
->token
!= NULL
) {
2433 Tcl_DeleteTimerHandler(v
->token
);
2439 Py_DECREF(v
); /* See Tktt_New() */
2445 static PyMethodDef Tktt_methods
[] =
2447 {"deletetimerhandler", Tktt_DeleteTimerHandler
, METH_VARARGS
},
2452 Tktt_New(PyObject
*func
)
2456 v
= PyObject_New(TkttObject
, &Tktt_Type
);
2464 /* Extra reference, deleted when called or when handler is deleted */
2470 Tktt_Dealloc(PyObject
*self
)
2472 TkttObject
*v
= (TkttObject
*)self
;
2473 PyObject
*func
= v
->func
;
2481 Tktt_Repr(PyObject
*self
)
2483 TkttObject
*v
= (TkttObject
*)self
;
2486 PyOS_snprintf(buf
, sizeof(buf
), "<tktimertoken at %p%s>", v
,
2487 v
->func
== NULL
? ", handler deleted" : "");
2488 return PyString_FromString(buf
);
2492 Tktt_GetAttr(PyObject
*self
, char *name
)
2494 return Py_FindMethod(Tktt_methods
, self
, name
);
2497 static PyTypeObject Tktt_Type
=
2499 PyVarObject_HEAD_INIT(NULL
, 0)
2500 "tktimertoken", /*tp_name */
2501 sizeof(TkttObject
), /*tp_basicsize */
2503 Tktt_Dealloc
, /*tp_dealloc */
2505 Tktt_GetAttr
, /*tp_getattr */
2508 Tktt_Repr
, /*tp_repr */
2509 0, /*tp_as_number */
2510 0, /*tp_as_sequence */
2511 0, /*tp_as_mapping */
2517 /** Timer Handler **/
2520 TimerHandler(ClientData clientData
)
2522 TkttObject
*v
= (TkttObject
*)clientData
;
2523 PyObject
*func
= v
->func
;
2533 res
= PyEval_CallObject(func
, NULL
);
2535 Py_DECREF(v
); /* See Tktt_New() */
2539 PyErr_Fetch(&excInCmd
, &valInCmd
, &trbInCmd
);
2548 Tkapp_CreateTimerHandler(PyObject
*self
, PyObject
*args
)
2554 if (!self
&& Py_Py3kWarningFlag
) {
2555 if (PyErr_Warn(PyExc_DeprecationWarning
,
2556 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2560 if (!PyArg_ParseTuple(args
, "iO:createtimerhandler",
2561 &milliseconds
, &func
))
2563 if (!PyCallable_Check(func
)) {
2564 PyErr_SetString(PyExc_TypeError
, "bad argument list");
2569 if (!self
&& !tcl_lock
) {
2570 /* We don't have the Tcl lock since Tcl is threaded. */
2571 PyErr_SetString(PyExc_RuntimeError
,
2572 "_tkinter.createtimerhandler not supported "
2573 "for threaded Tcl");
2579 CHECK_TCL_APPARTMENT
;
2584 v
->token
= Tcl_CreateTimerHandler(milliseconds
, TimerHandler
,
2588 return (PyObject
*) v
;
2595 Tkapp_MainLoop(PyObject
*selfptr
, PyObject
*args
)
2598 TkappObject
*self
= (TkappObject
*)selfptr
;
2600 PyThreadState
*tstate
= PyThreadState_Get();
2603 if (!self
&& Py_Py3kWarningFlag
) {
2604 if (PyErr_Warn(PyExc_DeprecationWarning
,
2605 "_tkinter.mainloop is gone in 3.x") < 0)
2609 if (!PyArg_ParseTuple(args
, "|i:mainloop", &threshold
))
2613 if (!self
&& !tcl_lock
) {
2614 /* We don't have the Tcl lock since Tcl is threaded. */
2615 PyErr_SetString(PyExc_RuntimeError
,
2616 "_tkinter.mainloop not supported "
2617 "for threaded Tcl");
2623 CHECK_TCL_APPARTMENT
;
2624 self
->dispatching
= 1;
2628 while (Tk_GetNumMainWindows() > threshold
&&
2635 if (self
&& self
->threaded
) {
2636 /* Allow other Python threads to run. */
2638 result
= Tcl_DoOneEvent(0);
2642 Py_BEGIN_ALLOW_THREADS
2643 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
2644 tcl_tstate
= tstate
;
2645 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
2647 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
2649 Sleep(Tkinter_busywaitinterval
);
2650 Py_END_ALLOW_THREADS
2653 result
= Tcl_DoOneEvent(0);
2656 if (PyErr_CheckSignals() != 0) {
2658 self
->dispatching
= 0;
2665 self
->dispatching
= 0;
2670 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
2671 excInCmd
= valInCmd
= trbInCmd
= NULL
;
2679 Tkapp_DoOneEvent(PyObject
*self
, PyObject
*args
)
2684 if (!self
&& Py_Py3kWarningFlag
) {
2685 if (PyErr_Warn(PyExc_DeprecationWarning
,
2686 "_tkinter.dooneevent is gone in 3.x") < 0)
2690 if (!PyArg_ParseTuple(args
, "|i:dooneevent", &flags
))
2694 rv
= Tcl_DoOneEvent(flags
);
2696 return Py_BuildValue("i", rv
);
2700 Tkapp_Quit(PyObject
*self
, PyObject
*args
)
2703 if (!self
&& Py_Py3kWarningFlag
) {
2704 if (PyErr_Warn(PyExc_DeprecationWarning
,
2705 "_tkinter.quit is gone in 3.x") < 0)
2709 if (!PyArg_ParseTuple(args
, ":quit"))
2718 Tkapp_InterpAddr(PyObject
*self
, PyObject
*args
)
2721 if (!PyArg_ParseTuple(args
, ":interpaddr"))
2724 return PyInt_FromLong((long)Tkapp_Interp(self
));
2728 Tkapp_TkInit(PyObject
*self
, PyObject
*args
)
2730 Tcl_Interp
*interp
= Tkapp_Interp(self
);
2731 const char * _tk_exists
= NULL
;
2734 #ifdef TKINTER_PROTECT_LOADTK
2735 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2736 * first call failed.
2737 * To avoid the deadlock, we just refuse the second call through
2738 * a static variable.
2740 if (tk_load_failed
) {
2741 PyErr_SetString(Tkinter_TclError
, TKINTER_LOADTK_ERRMSG
);
2746 /* We want to guard against calling Tk_Init() multiple times */
2747 CHECK_TCL_APPARTMENT
;
2749 err
= Tcl_Eval(Tkapp_Interp(self
), "info exists tk_version");
2751 if (err
== TCL_ERROR
) {
2752 /* This sets an exception, but we cannot return right
2753 away because we need to exit the overlap first. */
2754 Tkinter_Error(self
);
2756 _tk_exists
= Tkapp_Result(self
);
2759 if (err
== TCL_ERROR
) {
2762 if (_tk_exists
== NULL
|| strcmp(_tk_exists
, "1") != 0) {
2763 if (Tk_Init(interp
) == TCL_ERROR
) {
2764 PyErr_SetString(Tkinter_TclError
, Tcl_GetStringResult(Tkapp_Interp(self
)));
2765 #ifdef TKINTER_PROTECT_LOADTK
2776 Tkapp_WantObjects(PyObject
*self
, PyObject
*args
)
2779 int wantobjects
= -1;
2780 if (!PyArg_ParseTuple(args
, "|i:wantobjects", &wantobjects
))
2782 if (wantobjects
== -1)
2783 return PyBool_FromLong(((TkappObject
*)self
)->wantobjects
);
2784 ((TkappObject
*)self
)->wantobjects
= wantobjects
;
2791 Tkapp_WillDispatch(PyObject
*self
, PyObject
*args
)
2794 ((TkappObject
*)self
)->dispatching
= 1;
2801 /**** Tkapp Method List ****/
2803 static PyMethodDef Tkapp_methods
[] =
2805 {"willdispatch", Tkapp_WillDispatch
, METH_NOARGS
},
2806 {"wantobjects", Tkapp_WantObjects
, METH_VARARGS
},
2807 {"call", Tkapp_Call
, METH_VARARGS
},
2808 {"globalcall", Tkapp_GlobalCall
, METH_VARARGS
},
2809 {"eval", Tkapp_Eval
, METH_VARARGS
},
2810 {"globaleval", Tkapp_GlobalEval
, METH_VARARGS
},
2811 {"evalfile", Tkapp_EvalFile
, METH_VARARGS
},
2812 {"record", Tkapp_Record
, METH_VARARGS
},
2813 {"adderrorinfo", Tkapp_AddErrorInfo
, METH_VARARGS
},
2814 {"setvar", Tkapp_SetVar
, METH_VARARGS
},
2815 {"globalsetvar", Tkapp_GlobalSetVar
, METH_VARARGS
},
2816 {"getvar", Tkapp_GetVar
, METH_VARARGS
},
2817 {"globalgetvar", Tkapp_GlobalGetVar
, METH_VARARGS
},
2818 {"unsetvar", Tkapp_UnsetVar
, METH_VARARGS
},
2819 {"globalunsetvar", Tkapp_GlobalUnsetVar
, METH_VARARGS
},
2820 {"getint", Tkapp_GetInt
, METH_VARARGS
},
2821 {"getdouble", Tkapp_GetDouble
, METH_VARARGS
},
2822 {"getboolean", Tkapp_GetBoolean
, METH_VARARGS
},
2823 {"exprstring", Tkapp_ExprString
, METH_VARARGS
},
2824 {"exprlong", Tkapp_ExprLong
, METH_VARARGS
},
2825 {"exprdouble", Tkapp_ExprDouble
, METH_VARARGS
},
2826 {"exprboolean", Tkapp_ExprBoolean
, METH_VARARGS
},
2827 {"splitlist", Tkapp_SplitList
, METH_VARARGS
},
2828 {"split", Tkapp_Split
, METH_VARARGS
},
2829 {"merge", Tkapp_Merge
, METH_VARARGS
},
2830 {"createcommand", Tkapp_CreateCommand
, METH_VARARGS
},
2831 {"deletecommand", Tkapp_DeleteCommand
, METH_VARARGS
},
2832 #ifdef HAVE_CREATEFILEHANDLER
2833 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
2834 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
2836 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
2837 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
2838 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
2839 {"quit", Tkapp_Quit
, METH_VARARGS
},
2840 {"interpaddr", Tkapp_InterpAddr
, METH_VARARGS
},
2841 {"loadtk", Tkapp_TkInit
, METH_NOARGS
},
2847 /**** Tkapp Type Methods ****/
2850 Tkapp_Dealloc(PyObject
*self
)
2852 /*CHECK_TCL_APPARTMENT;*/
2854 Tcl_DeleteInterp(Tkapp_Interp(self
));
2861 Tkapp_GetAttr(PyObject
*self
, char *name
)
2863 return Py_FindMethod(Tkapp_methods
, self
, name
);
2866 static PyTypeObject Tkapp_Type
=
2868 PyVarObject_HEAD_INIT(NULL
, 0)
2869 "tkapp", /*tp_name */
2870 sizeof(TkappObject
), /*tp_basicsize */
2872 Tkapp_Dealloc
, /*tp_dealloc */
2874 Tkapp_GetAttr
, /*tp_getattr */
2878 0, /*tp_as_number */
2879 0, /*tp_as_sequence */
2880 0, /*tp_as_mapping */
2886 /**** Tkinter Module ****/
2890 int size
; /* current size */
2891 int maxsize
; /* allocated size */
2895 _bump(FlattenContext
* context
, int size
)
2897 /* expand tuple to hold (at least) size new items.
2898 return true if successful, false if an exception was raised */
2900 int maxsize
= context
->maxsize
* 2;
2902 if (maxsize
< context
->size
+ size
)
2903 maxsize
= context
->size
+ size
;
2905 context
->maxsize
= maxsize
;
2907 return _PyTuple_Resize(&context
->tuple
, maxsize
) >= 0;
2911 _flatten1(FlattenContext
* context
, PyObject
* item
, int depth
)
2913 /* add tuple or list to argument tuple (recursively) */
2918 PyErr_SetString(PyExc_ValueError
,
2919 "nesting too deep in _flatten");
2921 } else if (PyList_Check(item
)) {
2922 size
= PyList_GET_SIZE(item
);
2923 /* preallocate (assume no nesting) */
2924 if (context
->size
+ size
> context
->maxsize
&&
2925 !_bump(context
, size
))
2927 /* copy items to output tuple */
2928 for (i
= 0; i
< size
; i
++) {
2929 PyObject
*o
= PyList_GET_ITEM(item
, i
);
2930 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2931 if (!_flatten1(context
, o
, depth
+ 1))
2933 } else if (o
!= Py_None
) {
2934 if (context
->size
+ 1 > context
->maxsize
&&
2938 PyTuple_SET_ITEM(context
->tuple
,
2939 context
->size
++, o
);
2942 } else if (PyTuple_Check(item
)) {
2943 /* same, for tuples */
2944 size
= PyTuple_GET_SIZE(item
);
2945 if (context
->size
+ size
> context
->maxsize
&&
2946 !_bump(context
, size
))
2948 for (i
= 0; i
< size
; i
++) {
2949 PyObject
*o
= PyTuple_GET_ITEM(item
, i
);
2950 if (PyList_Check(o
) || PyTuple_Check(o
)) {
2951 if (!_flatten1(context
, o
, depth
+ 1))
2953 } else if (o
!= Py_None
) {
2954 if (context
->size
+ 1 > context
->maxsize
&&
2958 PyTuple_SET_ITEM(context
->tuple
,
2959 context
->size
++, o
);
2963 PyErr_SetString(PyExc_TypeError
, "argument must be sequence");
2970 Tkinter_Flatten(PyObject
* self
, PyObject
* args
)
2972 FlattenContext context
;
2975 if (!PyArg_ParseTuple(args
, "O:_flatten", &item
))
2978 context
.maxsize
= PySequence_Size(item
);
2979 if (context
.maxsize
< 0)
2981 if (context
.maxsize
== 0)
2982 return PyTuple_New(0);
2984 context
.tuple
= PyTuple_New(context
.maxsize
);
2990 if (!_flatten1(&context
, item
,0))
2993 if (_PyTuple_Resize(&context
.tuple
, context
.size
))
2996 return context
.tuple
;
3000 Tkinter_Create(PyObject
*self
, PyObject
*args
)
3002 char *screenName
= NULL
;
3003 char *baseName
= NULL
;
3004 char *className
= NULL
;
3005 int interactive
= 0;
3006 int wantobjects
= 0;
3007 int wantTk
= 1; /* If false, then Tk_Init() doesn't get called */
3008 int sync
= 0; /* pass -sync to wish */
3009 char *use
= NULL
; /* pass -use to wish */
3011 baseName
= strrchr(Py_GetProgramName(), '/');
3012 if (baseName
!= NULL
)
3015 baseName
= Py_GetProgramName();
3018 if (!PyArg_ParseTuple(args
, "|zssiiiiz:create",
3019 &screenName
, &baseName
, &className
,
3020 &interactive
, &wantobjects
, &wantTk
,
3024 return (PyObject
*) Tkapp_New(screenName
, baseName
, className
,
3025 interactive
, wantobjects
, wantTk
,
3030 Tkinter_setbusywaitinterval(PyObject
*self
, PyObject
*args
)
3033 if (!PyArg_ParseTuple(args
, "i:setbusywaitinterval", &new_val
))
3036 PyErr_SetString(PyExc_ValueError
,
3037 "busywaitinterval must be >= 0");
3040 Tkinter_busywaitinterval
= new_val
;
3045 static char setbusywaitinterval_doc
[] =
3046 "setbusywaitinterval(n) -> None\n\
3048 Set the busy-wait interval in milliseconds between successive\n\
3049 calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3050 It should be set to a divisor of the maximum time between\n\
3051 frames in an animation.";
3054 Tkinter_getbusywaitinterval(PyObject
*self
, PyObject
*args
)
3056 return PyInt_FromLong(Tkinter_busywaitinterval
);
3059 static char getbusywaitinterval_doc
[] =
3060 "getbusywaitinterval() -> int\n\
3062 Return the current busy-wait interval between successive\n\
3063 calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3065 static PyMethodDef moduleMethods
[] =
3067 {"_flatten", Tkinter_Flatten
, METH_VARARGS
},
3068 {"create", Tkinter_Create
, METH_VARARGS
},
3069 #ifdef HAVE_CREATEFILEHANDLER
3070 {"createfilehandler", Tkapp_CreateFileHandler
, METH_VARARGS
},
3071 {"deletefilehandler", Tkapp_DeleteFileHandler
, METH_VARARGS
},
3073 {"createtimerhandler", Tkapp_CreateTimerHandler
, METH_VARARGS
},
3074 {"mainloop", Tkapp_MainLoop
, METH_VARARGS
},
3075 {"dooneevent", Tkapp_DoOneEvent
, METH_VARARGS
},
3076 {"quit", Tkapp_Quit
, METH_VARARGS
},
3077 {"setbusywaitinterval",Tkinter_setbusywaitinterval
, METH_VARARGS
,
3078 setbusywaitinterval_doc
},
3079 {"getbusywaitinterval",(PyCFunction
)Tkinter_getbusywaitinterval
,
3080 METH_NOARGS
, getbusywaitinterval_doc
},
3084 #ifdef WAIT_FOR_STDIN
3086 static int stdin_ready
= 0;
3090 MyFileProc(void *clientData
, int mask
)
3097 static PyThreadState
*event_tstate
= NULL
;
3107 PyEval_RestoreThread(event_tstate
);
3112 tfile
= fileno(stdin
);
3113 Tcl_CreateFileHandler(tfile
, TCL_READABLE
, MyFileProc
, NULL
);
3115 while (!errorInCmd
&& !stdin_ready
) {
3123 #if defined(WITH_THREAD) || defined(MS_WINDOWS)
3124 Py_BEGIN_ALLOW_THREADS
3125 if(tcl_lock
)PyThread_acquire_lock(tcl_lock
, 1);
3126 tcl_tstate
= event_tstate
;
3128 result
= Tcl_DoOneEvent(TCL_DONT_WAIT
);
3131 if(tcl_lock
)PyThread_release_lock(tcl_lock
);
3133 Sleep(Tkinter_busywaitinterval
);
3134 Py_END_ALLOW_THREADS
3136 result
= Tcl_DoOneEvent(0);
3143 Tcl_DeleteFileHandler(tfile
);
3147 PyErr_Restore(excInCmd
, valInCmd
, trbInCmd
);
3148 excInCmd
= valInCmd
= trbInCmd
= NULL
;
3152 PyEval_SaveThread();
3160 EnableEventHook(void)
3162 #ifdef WAIT_FOR_STDIN
3163 if (PyOS_InputHook
== NULL
) {
3165 event_tstate
= PyThreadState_Get();
3167 PyOS_InputHook
= EventHook
;
3173 DisableEventHook(void)
3175 #ifdef WAIT_FOR_STDIN
3176 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook
== EventHook
) {
3177 PyOS_InputHook
= NULL
;
3183 /* all errors will be checked in one fell swoop in init_tkinter() */
3185 ins_long(PyObject
*d
, char *name
, long val
)
3187 PyObject
*v
= PyInt_FromLong(val
);
3189 PyDict_SetItemString(d
, name
, v
);
3194 ins_string(PyObject
*d
, char *name
, char *val
)
3196 PyObject
*v
= PyString_FromString(val
);
3198 PyDict_SetItemString(d
, name
, v
);
3209 Py_TYPE(&Tkapp_Type
) = &PyType_Type
;
3212 tcl_lock
= PyThread_allocate_lock();
3215 m
= Py_InitModule("_tkinter", moduleMethods
);
3219 d
= PyModule_GetDict(m
);
3220 Tkinter_TclError
= PyErr_NewException("_tkinter.TclError", NULL
, NULL
);
3221 PyDict_SetItemString(d
, "TclError", Tkinter_TclError
);
3223 ins_long(d
, "READABLE", TCL_READABLE
);
3224 ins_long(d
, "WRITABLE", TCL_WRITABLE
);
3225 ins_long(d
, "EXCEPTION", TCL_EXCEPTION
);
3226 ins_long(d
, "WINDOW_EVENTS", TCL_WINDOW_EVENTS
);
3227 ins_long(d
, "FILE_EVENTS", TCL_FILE_EVENTS
);
3228 ins_long(d
, "TIMER_EVENTS", TCL_TIMER_EVENTS
);
3229 ins_long(d
, "IDLE_EVENTS", TCL_IDLE_EVENTS
);
3230 ins_long(d
, "ALL_EVENTS", TCL_ALL_EVENTS
);
3231 ins_long(d
, "DONT_WAIT", TCL_DONT_WAIT
);
3232 ins_string(d
, "TK_VERSION", TK_VERSION
);
3233 ins_string(d
, "TCL_VERSION", TCL_VERSION
);
3235 PyDict_SetItemString(d
, "TkappType", (PyObject
*)&Tkapp_Type
);
3237 Py_TYPE(&Tktt_Type
) = &PyType_Type
;
3238 PyDict_SetItemString(d
, "TkttType", (PyObject
*)&Tktt_Type
);
3240 Py_TYPE(&PyTclObject_Type
) = &PyType_Type
;
3241 PyDict_SetItemString(d
, "Tcl_Obj", (PyObject
*)&PyTclObject_Type
);
3244 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3245 * start waking up. Note that Tcl_FindExecutable will do this, this
3246 * code must be above it! The original warning from
3247 * tkMacOSXAppInit.c is copied below.
3249 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3250 * Tcl interpreter for now. It probably should work to do this
3251 * in the other order, but for now it doesn't seem to.
3254 Tk_MacOSXSetupTkNotifier();
3258 /* This helps the dynamic loader; in Unicode aware Tcl versions
3259 it also helps Tcl find its encodings. */
3260 Tcl_FindExecutable(Py_GetProgramName());
3262 if (PyErr_Occurred())
3266 /* This was not a good idea; through <Destroy> bindings,
3267 Tcl_Finalize() may invoke Python code but at that point the
3268 interpreter and thread state have already been destroyed! */
3269 Py_AtExit(Tcl_Finalize
);