blob: b4642b74f6e515a65ed3ad51838ccc87a5a400b0 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Antoine Pitrouc83ea132010-05-09 14:46:46 +000012 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
14 Tcl/Tk libraries.
Guido van Rossuma80649b2000-03-28 20:07:05 +000015*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Martin v. Löwis39195712003-01-04 00:33:13 +000036/* Allow using this code in Python 2.[12] */
37#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000038#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000039#endif
40
41#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000042#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000045#ifndef PyBool_Check
46#define PyBool_Check(o) 0
47#define PyBool_FromLong PyInt_FromLong
48#endif
49
Serhiy Storchaka42035702013-08-21 21:46:12 +030050#define CHECK_SIZE(size, elemsize) \
51 ((size_t)(size) <= (size_t)INT_MAX && \
52 (size_t)(size) <= UINT_MAX / (size_t)(elemsize))
53
Martin v. Löwis71e25a02002-10-01 18:08:06 +000054/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
55 making _tkinter correct for this API means to break earlier
56 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
57 earlier versions. Once Tcl releases before 8.4 don't need to be supported
58 anymore, this should go. */
59#define USE_COMPAT_CONST
60
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000061/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
62 it always; if Tcl is not threaded, the thread functions in
63 Tcl are empty. */
64#define TCL_THREADS
65
Jack Jansencb852442001-12-09 23:15:56 +000066#ifdef TK_FRAMEWORK
67#include <Tcl/tcl.h>
68#include <Tk/tk.h>
69#else
Guido van Rossum18468821994-06-20 07:49:28 +000070#include <tcl.h>
71#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000072#endif
Guido van Rossum18468821994-06-20 07:49:28 +000073
Guilherme Polo5d64c332009-04-05 02:11:19 +000074#include "tkinter.h"
75
Jason Tishlerbbe89612002-12-31 20:30:46 +000076/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000077#ifndef CONST84_RETURN
78#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000079#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000080#define CONST
81#endif
82
Guilherme Poloc5eba1e2009-02-09 20:57:45 +000083#if TK_VERSION_HEX < 0x08030102
84#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000085#endif
86
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000087/* Unicode conversion assumes that Tcl_UniChar is two bytes.
88 We cannot test this directly, so we test UTF-8 size instead,
89 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Antoine Pitrouc83ea132010-05-09 14:46:46 +000090 either UTF-16 or UCS-4.
91 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000092 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
93 as well.
94*/
95#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000096#error "unsupported Tcl configuration"
97#endif
98
Jack Janseneddc1442003-11-20 01:44:59 +000099#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000100#define HAVE_CREATEFILEHANDLER
101#endif
102
Guido van Rossum00d93061998-05-28 23:06:38 +0000103#ifdef HAVE_CREATEFILEHANDLER
104
Neal Norwitzd948a432006-01-08 01:08:55 +0000105/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
106 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
107#ifndef TCL_UNIX_FD
108# ifdef TCL_WIN_SOCKET
109# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
110# else
111# define TCL_UNIX_FD 1
112# endif
113#endif
114
Guido van Rossum00d93061998-05-28 23:06:38 +0000115/* Tcl_CreateFileHandler() changed several times; these macros deal with the
116 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
117 Unix, only because Jack added it back); when available on Windows, it only
118 applies to sockets. */
119
Guido van Rossum7bf15641998-05-22 18:28:17 +0000120#ifdef MS_WINDOWS
121#define FHANDLETYPE TCL_WIN_SOCKET
122#else
123#define FHANDLETYPE TCL_UNIX_FD
124#endif
125
Guido van Rossum00d93061998-05-28 23:06:38 +0000126/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
127 which uses this to handle Tcl events while the user is typing commands. */
128
129#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000130#define WAIT_FOR_STDIN
131#endif
132
Guido van Rossum00d93061998-05-28 23:06:38 +0000133#endif /* HAVE_CREATEFILEHANDLER */
134
Guido van Rossumad4db171998-06-13 13:56:28 +0000135#ifdef MS_WINDOWS
136#include <conio.h>
137#define WAIT_FOR_STDIN
138#endif
139
Guido van Rossum00d93061998-05-28 23:06:38 +0000140#ifdef WITH_THREAD
141
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000142/* The threading situation is complicated. Tcl is not thread-safe, except
143 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000144 So we need to use a lock around all uses of Tcl. Previously, the Python
145 interpreter lock was used for this. However, this causes problems when
146 other Python threads need to run while Tcl is blocked waiting for events.
147
148 To solve this problem, a separate lock for Tcl is introduced. Holding it
149 is incompatible with holding Python's interpreter lock. The following four
150 macros manipulate both locks together.
151
152 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
153 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
154 that could call an event handler, or otherwise affect the state of a Tcl
155 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000156 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000157 released and the lock for Tcl has been acquired.
158
Guido van Rossum5e977831998-06-15 14:03:52 +0000159 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
160 (For example, when transferring data from the Tcl interpreter result to a
161 Python string object.) This can be done by using different macros to close
162 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
163 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
164 releases the Tcl lock.
165
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000166 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000167 handlers when the handler needs to use Python. Such event handlers are
168 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000169 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000170 the Python interpreter lock, restoring the appropriate thread state, and
171 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
172 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000173 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000174
175 These locks expand to several statements and brackets; they should not be
176 used in branches of if statements and the like.
177
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000178 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
179 only valid in the thread that created it, and all Tk activity must happen in this
180 thread, also. That means that the mainloop must be invoked in the thread that
181 created the interpreter. Invoking commands from other threads is possible;
182 _tkinter will queue an event for the interpreter thread, which will then
183 execute the command and pass back the result. If the main thread is not in the
184 mainloop, and invoking commands causes an exception; if the main loop is running
185 but not processing events, the command invocation will block.
186
187 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
188 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
189 threads. So we use the Tcl TLS API.
190
Guido van Rossum00d93061998-05-28 23:06:38 +0000191*/
192
Guido van Rossum65d5b571998-12-21 19:32:43 +0000193static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000194
195#ifdef TCL_THREADS
196static Tcl_ThreadDataKey state_key;
197typedef PyThreadState *ThreadSpecificData;
198#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
199#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000200static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000201#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#define ENTER_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000204 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
205 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000206
207#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000208 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000209
Guido van Rossum62320c91998-06-15 04:36:09 +0000210#define ENTER_OVERLAP \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000211 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000212
213#define LEAVE_OVERLAP_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000214 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000215
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000216#define ENTER_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000217 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
218 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000219
220#define LEAVE_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000221 { PyThreadState *tstate = PyEval_SaveThread(); \
222 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000223
224#define CHECK_TCL_APPARTMENT \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000225 if (((TkappObject *)self)->threaded && \
226 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
227 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
228 return 0; \
229 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000230
231#else
232
233#define ENTER_TCL
234#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000235#define ENTER_OVERLAP
236#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000237#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000238#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000239#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000240
241#endif
242
Guido van Rossum97867b21996-08-08 19:09:53 +0000243#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000244#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000245#endif
246
Guido van Rossum18468821994-06-20 07:49:28 +0000247/**** Tkapp Object Declaration ****/
248
Jeremy Hylton938ace62002-07-17 16:30:39 +0000249static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000250
Guido van Rossum00d93061998-05-28 23:06:38 +0000251typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000252 PyObject_HEAD
253 Tcl_Interp *interp;
254 int wantobjects;
255 int threaded; /* True if tcl_platform[threaded] */
256 Tcl_ThreadId thread_id;
257 int dispatching;
258 /* We cannot include tclInt.h, as this is internal.
259 So we cache interesting types here. */
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +0300260 const Tcl_ObjType *OldBooleanType;
261 const Tcl_ObjType *BooleanType;
262 const Tcl_ObjType *ByteArrayType;
263 const Tcl_ObjType *DoubleType;
264 const Tcl_ObjType *IntType;
265 const Tcl_ObjType *ListType;
266 const Tcl_ObjType *ProcBodyType;
267 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000268} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000269
Christian Heimese93237d2007-12-19 02:37:44 +0000270#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000271#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000272#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000273
Guido van Rossum35d43371997-08-02 00:09:09 +0000274#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimese93237d2007-12-19 02:37:44 +0000275(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000276
Barry Warsawfa701a81997-01-16 00:15:11 +0000277
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000278
Guido van Rossum18468821994-06-20 07:49:28 +0000279/**** Error Handling ****/
280
281static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000282static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000283static int errorInCmd = 0;
284static PyObject *excInCmd;
285static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000286static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000287
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000288#ifdef TKINTER_PROTECT_LOADTK
289static int tk_load_failed;
290#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000291
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000292
Guido van Rossum18468821994-06-20 07:49:28 +0000293static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000294Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000295{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000296 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
297 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000298}
299
Barry Warsawfa701a81997-01-16 00:15:11 +0000300
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000301
Guido van Rossum18468821994-06-20 07:49:28 +0000302/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000303
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000304static int Tkinter_busywaitinterval = 20;
305
Guido van Rossum00d93061998-05-28 23:06:38 +0000306#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000307#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000308
Guido van Rossum00d93061998-05-28 23:06:38 +0000309/* Millisecond sleep() for Unix platforms. */
310
311static void
Fred Drake509d79a2000-07-08 04:04:38 +0000312Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000313{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000314 /* XXX Too bad if you don't have select(). */
315 struct timeval t;
316 t.tv_sec = milli/1000;
317 t.tv_usec = (milli%1000) * 1000;
318 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000319}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000320#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000321
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000322/* Wait up to 1s for the mainloop to come up. */
323
324static int
325WaitForMainloop(TkappObject* self)
326{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000327 int i;
328 for (i = 0; i < 10; i++) {
329 if (self->dispatching)
330 return 1;
331 Py_BEGIN_ALLOW_THREADS
332 Sleep(100);
333 Py_END_ALLOW_THREADS
334 }
335 if (self->dispatching)
336 return 1;
337 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
338 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000339}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000340#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000341
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000342
Guido van Rossum18468821994-06-20 07:49:28 +0000343static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000344AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000345{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000346 if (PyString_Check(value))
347 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000348#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000349 else if (PyUnicode_Check(value)) {
350 PyObject *v = PyUnicode_AsUTF8String(value);
351 if (v == NULL)
352 return NULL;
353 if (PyList_Append(tmp, v) != 0) {
354 Py_DECREF(v);
355 return NULL;
356 }
357 Py_DECREF(v);
358 return PyString_AsString(v);
359 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000360#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000361 else {
362 PyObject *v = PyObject_Str(value);
363 if (v == NULL)
364 return NULL;
365 if (PyList_Append(tmp, v) != 0) {
366 Py_DECREF(v);
367 return NULL;
368 }
369 Py_DECREF(v);
370 return PyString_AsString(v);
371 }
Guido van Rossum18468821994-06-20 07:49:28 +0000372}
373
Barry Warsawfa701a81997-01-16 00:15:11 +0000374
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000375
Guido van Rossum18468821994-06-20 07:49:28 +0000376#define ARGSZ 64
377
378static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000379Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000380{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000381 PyObject *tmp = NULL;
382 char *argvStore[ARGSZ];
383 char **argv = NULL;
384 int fvStore[ARGSZ];
385 int *fv = NULL;
Serhiy Storchaka42035702013-08-21 21:46:12 +0300386 Py_ssize_t argc = 0, fvc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000387 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000388
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000389 if (!(tmp = PyList_New(0)))
390 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000391
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000392 argv = argvStore;
393 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000394
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000395 if (args == NULL)
396 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000397
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000398 else if (!PyTuple_Check(args)) {
399 argc = 1;
400 fv[0] = 0;
401 if (!(argv[0] = AsString(args, tmp)))
402 goto finally;
403 }
404 else {
405 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000406
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000407 if (argc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +0300408 if (!CHECK_SIZE(argc, sizeof(char *))) {
409 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
410 goto finally;
411 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +0300412 argv = (char **)attemptckalloc((size_t)argc * sizeof(char *));
413 fv = (int *)attemptckalloc((size_t)argc * sizeof(int));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000414 if (argv == NULL || fv == NULL) {
415 PyErr_NoMemory();
416 goto finally;
417 }
418 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000419
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000420 for (i = 0; i < argc; i++) {
421 PyObject *v = PyTuple_GetItem(args, i);
422 if (PyTuple_Check(v)) {
423 fv[i] = 1;
424 if (!(argv[i] = Merge(v)))
425 goto finally;
426 fvc++;
427 }
428 else if (v == Py_None) {
429 argc = i;
430 break;
431 }
432 else {
433 fv[i] = 0;
434 if (!(argv[i] = AsString(v, tmp)))
435 goto finally;
436 fvc++;
437 }
438 }
439 }
440 res = Tcl_Merge(argc, argv);
441 if (res == NULL)
442 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000443
Barry Warsawfa701a81997-01-16 00:15:11 +0000444 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000445 for (i = 0; i < fvc; i++)
446 if (fv[i]) {
447 ckfree(argv[i]);
448 }
449 if (argv != argvStore)
450 ckfree(FREECAST argv);
451 if (fv != fvStore)
452 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000453
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000454 Py_DECREF(tmp);
455 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000456}
457
Barry Warsawfa701a81997-01-16 00:15:11 +0000458
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000459
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200460#ifdef Py_USING_UNICODE
461static PyObject *
462unicode_FromTclStringAndSize(const char *s, Py_ssize_t size)
463{
464 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
465 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
466 /* Tcl encodes null character as \xc0\x80 */
467 if (memchr(s, '\xc0', size)) {
468 char *buf, *q;
469 const char *e = s + size;
470 PyErr_Clear();
471 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchaka5d93f402014-07-14 12:20:01 +0300472 if (buf == NULL) {
473 PyErr_NoMemory();
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200474 return NULL;
Serhiy Storchaka5d93f402014-07-14 12:20:01 +0300475 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200476 while (s != e) {
477 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
478 *q++ = '\0';
479 s += 2;
480 }
481 else
482 *q++ = *s++;
483 }
484 s = buf;
485 size = q - s;
486 r = PyUnicode_DecodeUTF8(s, size, NULL);
487 PyMem_Free(buf);
488 }
489 }
490 return r;
491}
492#endif
493
494static PyObject *
495fromTclStringAndSize(const char *s, Py_ssize_t size)
496{
497 PyObject *r;
498#ifdef Py_USING_UNICODE
499 Py_ssize_t i;
500 /* If Tcl string contains any bytes with the top bit set,
501 it's UTF-8 and we should decode it to Unicode */
502 for (i = 0; i < size; i++)
503 if (s[i] & 0x80)
504 break;
505 if (i != size) {
506 /* It isn't an ASCII string. */
507 r = unicode_FromTclStringAndSize(s, size);
508 if (r)
509 return r;
510 PyErr_Clear();
511 }
512#endif
513 r = PyString_FromStringAndSize(s, size);
514 return r;
515}
516
517static PyObject *
518fromTclString(const char *s)
519{
520 return fromTclStringAndSize(s, strlen(s));
521}
522
523
Guido van Rossum18468821994-06-20 07:49:28 +0000524static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000525Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000526{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000527 int argc;
528 char **argv;
529 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000530
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000531 if (list == NULL) {
532 Py_INCREF(Py_None);
533 return Py_None;
534 }
Guido van Rossum18468821994-06-20 07:49:28 +0000535
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000536 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
537 /* Not a list.
538 * Could be a quoted string containing funnies, e.g. {"}.
539 * Return the string itself.
540 */
541 return PyString_FromString(list);
542 }
Guido van Rossum18468821994-06-20 07:49:28 +0000543
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000544 if (argc == 0)
545 v = PyString_FromString("");
546 else if (argc == 1)
547 v = PyString_FromString(argv[0]);
548 else if ((v = PyTuple_New(argc)) != NULL) {
549 int i;
550 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000551
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000552 for (i = 0; i < argc; i++) {
553 if ((w = Split(argv[i])) == NULL) {
554 Py_DECREF(v);
555 v = NULL;
556 break;
557 }
558 PyTuple_SetItem(v, i, w);
559 }
560 }
561 Tcl_Free(FREECAST argv);
562 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000563}
564
Martin v. Löwisffad6332002-11-26 09:28:05 +0000565/* In some cases, Tcl will still return strings that are supposed to be
566 lists. SplitObj walks through a nested tuple, finding string objects that
567 need to be split. */
568
Martin v. Löwis111c1802008-06-13 07:47:47 +0000569static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000570SplitObj(PyObject *arg)
571{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000572 if (PyTuple_Check(arg)) {
573 int i, size;
574 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000575
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000576 size = PyTuple_Size(arg);
577 result = NULL;
578 /* Recursively invoke SplitObj for all tuple items.
579 If this does not return a new object, no action is
580 needed. */
581 for(i = 0; i < size; i++) {
582 elem = PyTuple_GetItem(arg, i);
583 newelem = SplitObj(elem);
584 if (!newelem) {
585 Py_XDECREF(result);
586 return NULL;
587 }
588 if (!result) {
589 int k;
590 if (newelem == elem) {
591 Py_DECREF(newelem);
592 continue;
593 }
594 result = PyTuple_New(size);
595 if (!result)
596 return NULL;
597 for(k = 0; k < i; k++) {
598 elem = PyTuple_GetItem(arg, k);
599 Py_INCREF(elem);
600 PyTuple_SetItem(result, k, elem);
601 }
602 }
603 PyTuple_SetItem(result, i, newelem);
604 }
605 if (result)
606 return result;
607 /* Fall through, returning arg. */
608 }
609 else if (PyString_Check(arg)) {
610 int argc;
611 char **argv;
612 char *list = PyString_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000613
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000614 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
615 Py_INCREF(arg);
616 return arg;
617 }
618 Tcl_Free(FREECAST argv);
619 if (argc > 1)
620 return Split(PyString_AsString(arg));
621 /* Fall through, returning arg. */
622 }
Serhiy Storchakafab65422013-07-11 20:32:48 +0300623 else if (PyUnicode_Check(arg)) {
624 int argc;
625 char **argv;
626 char *list;
627 PyObject *s = PyUnicode_AsUTF8String(arg);
628
629 if (s == NULL) {
630 Py_INCREF(arg);
631 return arg;
632 }
633 list = PyString_AsString(s);
634
635 if (list == NULL ||
636 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
637 Py_DECREF(s);
638 Py_INCREF(arg);
639 return arg;
640 }
641 Tcl_Free(FREECAST argv);
642 if (argc > 1) {
643 PyObject *v = Split(list);
644 Py_DECREF(s);
645 return v;
646 }
647 Py_DECREF(s);
648 /* Fall through, returning arg. */
649 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000650 Py_INCREF(arg);
651 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000652}
Barry Warsawfa701a81997-01-16 00:15:11 +0000653
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000654
Guido van Rossum18468821994-06-20 07:49:28 +0000655/**** Tkapp Object ****/
656
657#ifndef WITH_APPINIT
658int
Fred Drake509d79a2000-07-08 04:04:38 +0000659Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000660{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000661 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000662
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000663 if (Tcl_Init(interp) == TCL_ERROR) {
664 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
665 return TCL_ERROR;
666 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000667
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000668 _tkinter_skip_tk_init = Tcl_GetVar(interp,
669 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
670 if (_tkinter_skip_tk_init != NULL &&
671 strcmp(_tkinter_skip_tk_init, "1") == 0) {
672 return TCL_OK;
673 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000674
675#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000676 if (tk_load_failed) {
677 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
678 return TCL_ERROR;
679 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000680#endif
681
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000682 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000683#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000684 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000685#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000686 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
687 return TCL_ERROR;
688 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000689
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000690 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000691}
692#endif /* !WITH_APPINIT */
693
Guido van Rossum18468821994-06-20 07:49:28 +0000694
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000695
Barry Warsawfa701a81997-01-16 00:15:11 +0000696
697/* Initialize the Tk application; see the `main' function in
698 * `tkMain.c'.
699 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000700
Thomas Wouters58d05102000-07-24 14:43:35 +0000701static void EnableEventHook(void); /* Forward */
702static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000703
Barry Warsawfa701a81997-01-16 00:15:11 +0000704static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000705Tkapp_New(char *screenName, char *baseName, char *className,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000706 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000707{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000708 TkappObject *v;
709 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000710
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000711 v = PyObject_New(TkappObject, &Tkapp_Type);
712 if (v == NULL)
713 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000714
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000715 v->interp = Tcl_CreateInterp();
716 v->wantobjects = wantobjects;
717 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
718 TCL_GLOBAL_ONLY) != NULL;
719 v->thread_id = Tcl_GetCurrentThread();
720 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000721
722#ifndef TCL_THREADS
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000723 if (v->threaded) {
724 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
725 Py_DECREF(v);
726 return 0;
727 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000728#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000729#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000730 if (v->threaded && tcl_lock) {
731 /* If Tcl is threaded, we don't need the lock. */
732 PyThread_free_lock(tcl_lock);
733 tcl_lock = NULL;
734 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000735#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000736
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +0300737 v->OldBooleanType = Tcl_GetObjType("boolean");
738 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000739 v->ByteArrayType = Tcl_GetObjType("bytearray");
740 v->DoubleType = Tcl_GetObjType("double");
741 v->IntType = Tcl_GetObjType("int");
742 v->ListType = Tcl_GetObjType("list");
743 v->ProcBodyType = Tcl_GetObjType("procbody");
744 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000745
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000746 /* Delete the 'exit' command, which can screw things up */
747 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000748
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000749 if (screenName != NULL)
750 Tcl_SetVar2(v->interp, "env", "DISPLAY",
751 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000752
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000753 if (interactive)
754 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
755 else
756 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000757
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000758 /* This is used to get the application class for Tk 4.1 and up */
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +0300759 argv0 = (char*)attemptckalloc(strlen(className) + 1);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000760 if (!argv0) {
761 PyErr_NoMemory();
762 Py_DECREF(v);
763 return NULL;
764 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000765
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000766 strcpy(argv0, className);
Antoine Pitrou44b3b542011-10-04 13:55:37 +0200767 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
768 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000769 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
770 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000771
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000772 if (! wantTk) {
773 Tcl_SetVar(v->interp,
774 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
775 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000776#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000777 else if (tk_load_failed) {
778 Tcl_SetVar(v->interp,
779 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
780 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000781#endif
David Aschere2b4b322004-02-18 05:59:53 +0000782
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000783 /* some initial arguments need to be in argv */
784 if (sync || use) {
785 char *args;
786 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000787
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000788 if (sync)
789 len += sizeof "-sync";
790 if (use)
791 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000792
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +0300793 args = (char*)attemptckalloc(len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000794 if (!args) {
795 PyErr_NoMemory();
796 Py_DECREF(v);
797 return NULL;
798 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000799
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000800 args[0] = '\0';
801 if (sync)
802 strcat(args, "-sync");
803 if (use) {
804 if (sync)
805 strcat(args, " ");
806 strcat(args, "-use ");
807 strcat(args, use);
808 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000809
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000810 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
811 ckfree(args);
812 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000813
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000814 if (Tcl_AppInit(v->interp) != TCL_OK) {
815 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000816#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000817 if (wantTk) {
818 const char *_tkinter_tk_failed;
819 _tkinter_tk_failed = Tcl_GetVar(v->interp,
820 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000821
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000822 if ( _tkinter_tk_failed != NULL &&
823 strcmp(_tkinter_tk_failed, "1") == 0) {
824 tk_load_failed = 1;
825 }
826 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000827#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000828 Py_DECREF((PyObject *)v);
829 return (TkappObject *)result;
830 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000831
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000832 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000833
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000834 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000835}
836
Barry Warsawfa701a81997-01-16 00:15:11 +0000837
Guilherme Polo1972d162009-03-27 21:43:08 +0000838#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000839static void
840Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000841 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000842{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000843 Py_BEGIN_ALLOW_THREADS;
844 Tcl_MutexLock(mutex);
845 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
846 Tcl_ThreadAlert(self->thread_id);
847 Tcl_ConditionWait(cond, mutex, NULL);
848 Tcl_MutexUnlock(mutex);
849 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000850}
Guilherme Polo1972d162009-03-27 21:43:08 +0000851#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000852
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000853
Guido van Rossum18468821994-06-20 07:49:28 +0000854/** Tcl Eval **/
855
Martin v. Löwisffad6332002-11-26 09:28:05 +0000856typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000857 PyObject_HEAD
858 Tcl_Obj *value;
859 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000860} PyTclObject;
861
862staticforward PyTypeObject PyTclObject_Type;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000863#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000864
865static PyObject *
866newPyTclObject(Tcl_Obj *arg)
867{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000868 PyTclObject *self;
869 self = PyObject_New(PyTclObject, &PyTclObject_Type);
870 if (self == NULL)
871 return NULL;
872 Tcl_IncrRefCount(arg);
873 self->value = arg;
874 self->string = NULL;
875 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000876}
877
878static void
879PyTclObject_dealloc(PyTclObject *self)
880{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000881 Tcl_DecrRefCount(self->value);
882 Py_XDECREF(self->string);
883 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000884}
885
886static PyObject *
887PyTclObject_str(PyTclObject *self)
888{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000889 if (self->string && PyString_Check(self->string)) {
890 Py_INCREF(self->string);
891 return self->string;
892 }
893 /* XXX Could cache value if it is an ASCII string. */
894 return PyString_FromString(Tcl_GetString(self->value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000895}
896
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000897static char*
898PyTclObject_TclString(PyObject *self)
899{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000900 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000901}
902
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000903/* Like _str, but create Unicode if necessary. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000904PyDoc_STRVAR(PyTclObject_string__doc__,
Martin v. Löwis39195712003-01-04 00:33:13 +0000905"the string representation of this object, either as string or Unicode");
906
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000907static PyObject *
908PyTclObject_string(PyTclObject *self, void *ignored)
909{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000910 if (!self->string) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200911 int len;
912 char *s = Tcl_GetStringFromObj(self->value, &len);
913 self->string = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000914 if (!self->string)
915 return NULL;
916 }
917 Py_INCREF(self->string);
918 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000919}
920
921#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000922PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
923
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000924static PyObject *
925PyTclObject_unicode(PyTclObject *self, void *ignored)
926{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000927 char *s;
928 int len;
929 if (self->string && PyUnicode_Check(self->string)) {
930 Py_INCREF(self->string);
931 return self->string;
932 }
933 /* XXX Could chache result if it is non-ASCII. */
934 s = Tcl_GetStringFromObj(self->value, &len);
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200935 return unicode_FromTclStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000936}
937#endif
938
Martin v. Löwisffad6332002-11-26 09:28:05 +0000939static PyObject *
940PyTclObject_repr(PyTclObject *self)
941{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000942 char buf[50];
943 PyOS_snprintf(buf, 50, "<%s object at %p>",
944 self->value->typePtr->name, self->value);
945 return PyString_FromString(buf);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000946}
947
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000948static int
949PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
950{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000951 int res;
952 res = strcmp(Tcl_GetString(self->value),
953 Tcl_GetString(other->value));
954 if (res < 0) return -1;
955 if (res > 0) return 1;
956 return 0;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000957}
958
Martin v. Löwis39195712003-01-04 00:33:13 +0000959PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
960
Martin v. Löwisffad6332002-11-26 09:28:05 +0000961static PyObject*
962get_typename(PyTclObject* obj, void* ignored)
963{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000964 return PyString_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000965}
966
Martin v. Löwis39195712003-01-04 00:33:13 +0000967
Martin v. Löwisffad6332002-11-26 09:28:05 +0000968static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000969 {"typename", (getter)get_typename, NULL, get_typename__doc__},
970 {"string", (getter)PyTclObject_string, NULL,
971 PyTclObject_string__doc__},
972 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000973};
974
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000975static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000976#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000977 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
978 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000979#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000980 {0}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000981};
982
Martin v. Löwisffad6332002-11-26 09:28:05 +0000983statichere PyTypeObject PyTclObject_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000984 PyObject_HEAD_INIT(NULL)
985 0, /*ob_size*/
986 "_tkinter.Tcl_Obj", /*tp_name*/
987 sizeof(PyTclObject), /*tp_basicsize*/
988 0, /*tp_itemsize*/
989 /* methods */
990 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
991 0, /*tp_print*/
992 0, /*tp_getattr*/
993 0, /*tp_setattr*/
994 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
995 (reprfunc)PyTclObject_repr, /*tp_repr*/
996 0, /*tp_as_number*/
997 0, /*tp_as_sequence*/
998 0, /*tp_as_mapping*/
999 0, /*tp_hash*/
1000 0, /*tp_call*/
1001 (reprfunc)PyTclObject_str, /*tp_str*/
1002 PyObject_GenericGetAttr,/*tp_getattro*/
1003 0, /*tp_setattro*/
1004 0, /*tp_as_buffer*/
1005 Py_TPFLAGS_DEFAULT, /*tp_flags*/
1006 0, /*tp_doc*/
1007 0, /*tp_traverse*/
1008 0, /*tp_clear*/
1009 0, /*tp_richcompare*/
1010 0, /*tp_weaklistoffset*/
1011 0, /*tp_iter*/
1012 0, /*tp_iternext*/
1013 PyTclObject_methods, /*tp_methods*/
1014 0, /*tp_members*/
1015 PyTclObject_getsetlist, /*tp_getset*/
1016 0, /*tp_base*/
1017 0, /*tp_dict*/
1018 0, /*tp_descr_get*/
1019 0, /*tp_descr_set*/
1020 0, /*tp_dictoffset*/
1021 0, /*tp_init*/
1022 0, /*tp_alloc*/
1023 0, /*tp_new*/
1024 0, /*tp_free*/
1025 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +00001026};
1027
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001028#if PY_SIZE_MAX > INT_MAX
1029#define CHECK_STRING_LENGTH(s) do { \
1030 if (s != NULL && strlen(s) >= INT_MAX) { \
1031 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
1032 return NULL; \
1033 } } while(0)
1034#else
1035#define CHECK_STRING_LENGTH(s)
1036#endif
1037
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001038static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001039AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001040{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001041 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001042
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001043 if (PyString_Check(value))
1044 return Tcl_NewStringObj(PyString_AS_STRING(value),
1045 PyString_GET_SIZE(value));
1046 else if (PyBool_Check(value))
1047 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
1048 else if (PyInt_Check(value))
1049 return Tcl_NewLongObj(PyInt_AS_LONG(value));
1050 else if (PyFloat_Check(value))
1051 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
1052 else if (PyTuple_Check(value)) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001053 Tcl_Obj **argv;
1054 Py_ssize_t size, i;
1055
1056 size = PyTuple_Size(value);
Serhiy Storchaka17c01782014-09-11 10:56:59 +03001057 if (size == 0)
1058 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001059 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
1060 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1061 return NULL;
1062 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001063 argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001064 if(!argv)
1065 return 0;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001066 for (i = 0; i < size; i++)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001067 argv[i] = AsObj(PyTuple_GetItem(value,i));
1068 result = Tcl_NewListObj(PyTuple_Size(value), argv);
1069 ckfree(FREECAST argv);
1070 return result;
1071 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001072#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001073 else if (PyUnicode_Check(value)) {
1074 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
1075 Py_ssize_t size = PyUnicode_GET_SIZE(value);
1076 /* This #ifdef assumes that Tcl uses UCS-2.
1077 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001078#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001079 Tcl_UniChar *outbuf = NULL;
1080 Py_ssize_t i;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001081 size_t allocsize;
Serhiy Storchaka17c01782014-09-11 10:56:59 +03001082 if (size == 0)
1083 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001084 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1085 PyErr_SetString(PyExc_OverflowError, "string is too long");
1086 return NULL;
1087 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001088 if (sizeof(Py_UNICODE) == sizeof(Tcl_UniChar))
1089 return Tcl_NewUnicodeObj(inbuf, size);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001090 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001091 if (allocsize >= size)
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001092 outbuf = (Tcl_UniChar*)attemptckalloc(allocsize);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001093 /* Else overflow occurred, and we take the next exit */
1094 if (!outbuf) {
1095 PyErr_NoMemory();
1096 return NULL;
1097 }
1098 for (i = 0; i < size; i++) {
1099 if (inbuf[i] >= 0x10000) {
1100 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka46764482013-02-18 13:00:08 +02001101 PyErr_Format(Tkinter_TclError,
1102 "character U+%x is above the range "
1103 "(U+0000-U+FFFF) allowed by Tcl",
1104 (int)inbuf[i]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001105 ckfree(FREECAST outbuf);
1106 return NULL;
1107 }
1108 outbuf[i] = inbuf[i];
1109 }
1110 result = Tcl_NewUnicodeObj(outbuf, size);
1111 ckfree(FREECAST outbuf);
1112 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001113#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001114 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001115#endif
1116
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001117 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001118#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001119 else if(PyTclObject_Check(value)) {
1120 Tcl_Obj *v = ((PyTclObject*)value)->value;
1121 Tcl_IncrRefCount(v);
1122 return v;
1123 }
1124 else {
1125 PyObject *v = PyObject_Str(value);
1126 if (!v)
1127 return 0;
1128 result = AsObj(v);
1129 Py_DECREF(v);
1130 return result;
1131 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001132}
1133
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001134static PyObject *
1135fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1136{
1137 int boolValue;
1138 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1139 return Tkinter_Error(tkapp);
1140 return PyBool_FromLong(boolValue);
1141}
1142
Martin v. Löwisffad6332002-11-26 09:28:05 +00001143static PyObject*
1144FromObj(PyObject* tkapp, Tcl_Obj *value)
1145{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001146 PyObject *result = NULL;
1147 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001148 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001149
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001150 if (value->typePtr == NULL) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001151 result = fromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001152 return result;
1153 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001154
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001155 if (value->typePtr == app->BooleanType ||
1156 value->typePtr == app->OldBooleanType) {
1157 return fromBoolean(tkapp, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001158 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001159
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001160 if (value->typePtr == app->ByteArrayType) {
1161 int size;
1162 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1163 return PyString_FromStringAndSize(data, size);
1164 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001165
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001166 if (value->typePtr == app->DoubleType) {
1167 return PyFloat_FromDouble(value->internalRep.doubleValue);
1168 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001169
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001170 if (value->typePtr == app->IntType) {
1171 return PyInt_FromLong(value->internalRep.longValue);
1172 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001173
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001174 if (value->typePtr == app->ListType) {
1175 int size;
1176 int i, status;
1177 PyObject *elem;
1178 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001179
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001180 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001181 if (status == TCL_ERROR)
1182 return Tkinter_Error(tkapp);
1183 result = PyTuple_New(size);
1184 if (!result)
1185 return NULL;
1186 for (i = 0; i < size; i++) {
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001187 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001188 if (status == TCL_ERROR) {
1189 Py_DECREF(result);
1190 return Tkinter_Error(tkapp);
1191 }
1192 elem = FromObj(tkapp, tcl_elem);
1193 if (!elem) {
1194 Py_DECREF(result);
1195 return NULL;
1196 }
1197 PyTuple_SetItem(result, i, elem);
1198 }
1199 return result;
1200 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001201
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001202 if (value->typePtr == app->ProcBodyType) {
1203 /* fall through: return tcl object. */
1204 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001205
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001206 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001207#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001208#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001209 PyObject *result;
1210 int size;
1211 Tcl_UniChar *input;
1212 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001213
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001214 size = Tcl_GetCharLength(value);
1215 result = PyUnicode_FromUnicode(NULL, size);
1216 if (!result)
1217 return NULL;
1218 input = Tcl_GetUnicode(value);
1219 output = PyUnicode_AS_UNICODE(result);
1220 while (size--)
1221 *output++ = *input++;
1222 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001223#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001224 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1225 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001226#endif
1227#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001228 int size;
1229 char *c;
1230 c = Tcl_GetStringFromObj(value, &size);
1231 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001232#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001233 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001234
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001235#if TK_VERSION_HEX >= 0x08050000
1236 if (app->BooleanType == NULL &&
1237 strcmp(value->typePtr->name, "booleanString") == 0) {
1238 /* booleanString type is not registered in Tcl */
1239 app->BooleanType = value->typePtr;
1240 return fromBoolean(tkapp, value);
1241 }
1242#endif
1243
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001244 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001245}
1246
Guilherme Polo1972d162009-03-27 21:43:08 +00001247#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001248/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001249TCL_DECLARE_MUTEX(call_mutex)
1250
1251typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001252 Tcl_Event ev; /* Must be first */
1253 TkappObject *self;
1254 PyObject *args;
1255 int flags;
1256 PyObject **res;
1257 PyObject **exc_type, **exc_value, **exc_tb;
1258 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001259} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001260#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001261
1262void
1263Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001264{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001265 int i;
1266 for (i = 0; i < objc; i++)
1267 Tcl_DecrRefCount(objv[i]);
1268 if (objv != objStore)
1269 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001270}
Guido van Rossum18468821994-06-20 07:49:28 +00001271
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001272/* Convert Python objects to Tcl objects. This must happen in the
1273 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001274
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001275static Tcl_Obj**
1276Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1277{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001278 Tcl_Obj **objv = objStore;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001279 Py_ssize_t objc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001280 if (args == NULL)
1281 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001282
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001283 else if (!PyTuple_Check(args)) {
1284 objv[0] = AsObj(args);
1285 if (objv[0] == 0)
1286 goto finally;
1287 objc = 1;
1288 Tcl_IncrRefCount(objv[0]);
1289 }
1290 else {
1291 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001292
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001293 if (objc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001294 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1295 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1296 return NULL;
1297 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001298 objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001299 if (objv == NULL) {
1300 PyErr_NoMemory();
1301 objc = 0;
1302 goto finally;
1303 }
1304 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001305
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001306 for (i = 0; i < objc; i++) {
1307 PyObject *v = PyTuple_GetItem(args, i);
1308 if (v == Py_None) {
1309 objc = i;
1310 break;
1311 }
1312 objv[i] = AsObj(v);
1313 if (!objv[i]) {
1314 /* Reset objc, so it attempts to clear
1315 objects only up to i. */
1316 objc = i;
1317 goto finally;
1318 }
1319 Tcl_IncrRefCount(objv[i]);
1320 }
1321 }
1322 *pobjc = objc;
1323 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001324finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001325 Tkapp_CallDeallocArgs(objv, objStore, objc);
1326 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001327}
Guido van Rossum212643f1998-04-29 16:22:14 +00001328
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001329/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001330
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001331static PyObject*
1332Tkapp_CallResult(TkappObject *self)
1333{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001334 PyObject *res = NULL;
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001335 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001336 if(self->wantobjects) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001337 /* Not sure whether the IncrRef is necessary, but something
1338 may overwrite the interpreter result while we are
1339 converting it. */
1340 Tcl_IncrRefCount(value);
1341 res = FromObj((PyObject*)self, value);
1342 Tcl_DecrRefCount(value);
1343 } else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001344 int len;
1345 const char *s = Tcl_GetStringFromObj(value, &len);
1346 res = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001347 }
1348 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001349}
Guido van Rossum632de272000-03-29 00:19:50 +00001350
Guilherme Polo1972d162009-03-27 21:43:08 +00001351#ifdef WITH_THREAD
1352
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001353/* Tkapp_CallProc is the event procedure that is executed in the context of
1354 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1355 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001356
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001357static int
1358Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1359{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001360 Tcl_Obj *objStore[ARGSZ];
1361 Tcl_Obj **objv;
1362 int objc;
1363 int i;
1364 ENTER_PYTHON
1365 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1366 if (!objv) {
1367 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1368 *(e->res) = NULL;
1369 }
1370 LEAVE_PYTHON
1371 if (!objv)
1372 goto done;
1373 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1374 ENTER_PYTHON
1375 if (i == TCL_ERROR) {
1376 *(e->res) = NULL;
1377 *(e->exc_type) = NULL;
1378 *(e->exc_tb) = NULL;
1379 *(e->exc_value) = PyObject_CallFunction(
1380 Tkinter_TclError, "s",
1381 Tcl_GetStringResult(e->self->interp));
1382 }
1383 else {
1384 *(e->res) = Tkapp_CallResult(e->self);
1385 }
1386 LEAVE_PYTHON
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001387
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001388 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001389done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001390 /* Wake up calling thread. */
1391 Tcl_MutexLock(&call_mutex);
1392 Tcl_ConditionNotify(e->done);
1393 Tcl_MutexUnlock(&call_mutex);
1394 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001395}
1396
Guilherme Polo1972d162009-03-27 21:43:08 +00001397#endif
1398
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001399/* This is the main entry point for calling a Tcl command.
1400 It supports three cases, with regard to threading:
1401 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1402 the context of the calling thread.
1403 2. Tcl is threaded, caller of the command is in the interpreter thread:
1404 Execute the command in the calling thread. Since the Tcl lock will
1405 not be used, we can merge that with case 1.
1406 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1407 the interpreter thread. Allocation of Tcl objects needs to occur in the
1408 interpreter thread, so we ship the PyObject* args to the target thread,
1409 and perform processing there. */
1410
1411static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001412Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001413{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001414 Tcl_Obj *objStore[ARGSZ];
1415 Tcl_Obj **objv = NULL;
1416 int objc, i;
1417 PyObject *res = NULL;
1418 TkappObject *self = (TkappObject*)selfptr;
1419 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001420
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001421 /* If args is a single tuple, replace with contents of tuple */
1422 if (1 == PyTuple_Size(args)){
1423 PyObject* item = PyTuple_GetItem(args, 0);
1424 if (PyTuple_Check(item))
1425 args = item;
1426 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001427#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001428 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1429 /* We cannot call the command directly. Instead, we must
1430 marshal the parameters to the interpreter thread. */
1431 Tkapp_CallEvent *ev;
1432 Tcl_Condition cond = NULL;
1433 PyObject *exc_type, *exc_value, *exc_tb;
1434 if (!WaitForMainloop(self))
1435 return NULL;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001436 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1437 if (ev == NULL) {
1438 PyErr_NoMemory();
1439 return NULL;
1440 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001441 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1442 ev->self = self;
1443 ev->args = args;
1444 ev->res = &res;
1445 ev->exc_type = &exc_type;
1446 ev->exc_value = &exc_value;
1447 ev->exc_tb = &exc_tb;
1448 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001449
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001450 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001451
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001452 if (res == NULL) {
1453 if (exc_type)
1454 PyErr_Restore(exc_type, exc_value, exc_tb);
1455 else
1456 PyErr_SetObject(Tkinter_TclError, exc_value);
1457 }
1458 Tcl_ConditionFinalize(&cond);
1459 }
1460 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001461#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001462 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001463
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001464 objv = Tkapp_CallArgs(args, objStore, &objc);
1465 if (!objv)
1466 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001467
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001468 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001469
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001470 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001471
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001472 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001473
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001474 if (i == TCL_ERROR)
1475 Tkinter_Error(selfptr);
1476 else
1477 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001478
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001479 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001480
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001481 Tkapp_CallDeallocArgs(objv, objStore, objc);
1482 }
1483 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001484}
1485
1486
1487static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001488Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001489{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001490 /* Could do the same here as for Tkapp_Call(), but this is not used
1491 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1492 way for the user to do what all its Global* variants do (save and
1493 reset the scope pointer, call the local version, restore the saved
1494 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001495
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001496 char *cmd;
1497 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001498
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001499 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001500
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001501 cmd = Merge(args);
1502 if (cmd) {
1503 int err;
1504 ENTER_TCL
1505 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1506 ENTER_OVERLAP
1507 if (err == TCL_ERROR)
1508 res = Tkinter_Error(self);
1509 else
1510 res = PyString_FromString(Tkapp_Result(self));
1511 LEAVE_OVERLAP_TCL
1512 ckfree(cmd);
1513 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001514
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001515 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001516}
1517
1518static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001519Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001520{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001521 char *script;
1522 PyObject *res = NULL;
1523 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001524
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001525 if (!PyArg_ParseTuple(args, "s:eval", &script))
1526 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001527
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001528 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001529 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001530
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001531 ENTER_TCL
1532 err = Tcl_Eval(Tkapp_Interp(self), script);
1533 ENTER_OVERLAP
1534 if (err == TCL_ERROR)
1535 res = Tkinter_Error(self);
1536 else
1537 res = PyString_FromString(Tkapp_Result(self));
1538 LEAVE_OVERLAP_TCL
1539 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001540}
1541
1542static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001543Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001544{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001545 char *script;
1546 PyObject *res = NULL;
1547 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001548
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001549 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1550 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001551
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001552 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001553
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001554 ENTER_TCL
1555 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1556 ENTER_OVERLAP
1557 if (err == TCL_ERROR)
1558 res = Tkinter_Error(self);
1559 else
1560 res = PyString_FromString(Tkapp_Result(self));
1561 LEAVE_OVERLAP_TCL
1562 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001563}
1564
1565static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001566Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001567{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001568 char *fileName;
1569 PyObject *res = NULL;
1570 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001571
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001572 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1573 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001574
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001575 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001576 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001577
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001578 ENTER_TCL
1579 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1580 ENTER_OVERLAP
1581 if (err == TCL_ERROR)
1582 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001583
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001584 else
1585 res = PyString_FromString(Tkapp_Result(self));
1586 LEAVE_OVERLAP_TCL
1587 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001588}
1589
1590static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001591Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001592{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001593 char *script;
1594 PyObject *res = NULL;
1595 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001596
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001597 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001598 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001599
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001600 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001601 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001602
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001603 ENTER_TCL
1604 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1605 ENTER_OVERLAP
1606 if (err == TCL_ERROR)
1607 res = Tkinter_Error(self);
1608 else
1609 res = PyString_FromString(Tkapp_Result(self));
1610 LEAVE_OVERLAP_TCL
1611 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001612}
1613
1614static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001615Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001616{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001617 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001618
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001619 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1620 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001621 CHECK_STRING_LENGTH(msg);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001622 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001623
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001624 ENTER_TCL
1625 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1626 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001627
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001628 Py_INCREF(Py_None);
1629 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001630}
1631
Barry Warsawfa701a81997-01-16 00:15:11 +00001632
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001633
Guido van Rossum18468821994-06-20 07:49:28 +00001634/** Tcl Variable **/
1635
Guilherme Polo1972d162009-03-27 21:43:08 +00001636typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1637
1638#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001639TCL_DECLARE_MUTEX(var_mutex)
1640
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001641typedef struct VarEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001642 Tcl_Event ev; /* must be first */
1643 PyObject *self;
1644 PyObject *args;
1645 int flags;
1646 EventFunc func;
1647 PyObject **res;
1648 PyObject **exc_type;
1649 PyObject **exc_val;
1650 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001651} VarEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001652#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001653
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001654static int
1655varname_converter(PyObject *in, void *_out)
1656{
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001657 char *s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001658 char **out = (char**)_out;
1659 if (PyString_Check(in)) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001660 if (PyString_Size(in) > INT_MAX) {
1661 PyErr_SetString(PyExc_OverflowError, "string is too long");
1662 return 0;
1663 }
1664 s = PyString_AsString(in);
1665 if (strlen(s) != PyString_Size(in)) {
1666 PyErr_SetString(PyExc_ValueError, "null character in string");
1667 return 0;
1668 }
1669 *out = s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001670 return 1;
1671 }
1672 if (PyTclObject_Check(in)) {
1673 *out = PyTclObject_TclString(in);
1674 return 1;
1675 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001676 PyErr_Format(PyExc_TypeError,
1677 "must be str or Tcl_Obj, not %.50s",
1678 in->ob_type->tp_name);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001679 return 0;
1680}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001681
Guilherme Polo1972d162009-03-27 21:43:08 +00001682#ifdef WITH_THREAD
1683
Martin v. Löwis111c1802008-06-13 07:47:47 +00001684static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001685var_perform(VarEvent *ev)
1686{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001687 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1688 if (!*(ev->res)) {
1689 PyObject *exc, *val, *tb;
1690 PyErr_Fetch(&exc, &val, &tb);
1691 PyErr_NormalizeException(&exc, &val, &tb);
1692 *(ev->exc_type) = exc;
1693 *(ev->exc_val) = val;
1694 Py_DECREF(tb);
1695 }
1696
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001697}
1698
1699static int
1700var_proc(VarEvent* ev, int flags)
1701{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001702 ENTER_PYTHON
1703 var_perform(ev);
1704 Tcl_MutexLock(&var_mutex);
1705 Tcl_ConditionNotify(ev->cond);
1706 Tcl_MutexUnlock(&var_mutex);
1707 LEAVE_PYTHON
1708 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001709}
1710
Guilherme Polo1972d162009-03-27 21:43:08 +00001711#endif
1712
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001713static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001714var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001715{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001716#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001717 TkappObject *self = (TkappObject*)selfptr;
1718 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1719 TkappObject *self = (TkappObject*)selfptr;
1720 VarEvent *ev;
1721 PyObject *res, *exc_type, *exc_val;
1722 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001723
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001724 /* The current thread is not the interpreter thread. Marshal
1725 the call to the interpreter thread, then wait for
1726 completion. */
1727 if (!WaitForMainloop(self))
1728 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001729
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001730 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1731 if (ev == NULL) {
1732 PyErr_NoMemory();
1733 return NULL;
1734 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001735 ev->self = selfptr;
1736 ev->args = args;
1737 ev->flags = flags;
1738 ev->func = func;
1739 ev->res = &res;
1740 ev->exc_type = &exc_type;
1741 ev->exc_val = &exc_val;
1742 ev->cond = &cond;
1743 ev->ev.proc = (Tcl_EventProc*)var_proc;
1744 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1745 Tcl_ConditionFinalize(&cond);
1746 if (!res) {
1747 PyErr_SetObject(exc_type, exc_val);
1748 Py_DECREF(exc_type);
1749 Py_DECREF(exc_val);
1750 return NULL;
1751 }
1752 return res;
1753 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001754#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001755 /* Tcl is not threaded, or this is the interpreter thread. */
1756 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001757}
1758
Guido van Rossum18468821994-06-20 07:49:28 +00001759static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001760SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001761{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001762 char *name1, *name2;
1763 PyObject *newValue;
1764 PyObject *res = NULL;
1765 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001766
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001767 switch (PyTuple_GET_SIZE(args)) {
1768 case 2:
1769 if (!PyArg_ParseTuple(args, "O&O:setvar",
1770 varname_converter, &name1, &newValue))
1771 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001772 /* XXX Acquire tcl lock??? */
1773 newval = AsObj(newValue);
1774 if (newval == NULL)
1775 return NULL;
1776 ENTER_TCL
1777 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1778 newval, flags);
1779 ENTER_OVERLAP
1780 if (!ok)
1781 Tkinter_Error(self);
1782 else {
1783 res = Py_None;
1784 Py_INCREF(res);
1785 }
1786 LEAVE_OVERLAP_TCL
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001787 break;
1788 case 3:
1789 if (!PyArg_ParseTuple(args, "ssO:setvar",
1790 &name1, &name2, &newValue))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001791 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001792 CHECK_STRING_LENGTH(name1);
1793 CHECK_STRING_LENGTH(name2);
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001794 /* XXX must hold tcl lock already??? */
1795 newval = AsObj(newValue);
1796 ENTER_TCL
1797 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1798 ENTER_OVERLAP
1799 if (!ok)
1800 Tkinter_Error(self);
1801 else {
1802 res = Py_None;
1803 Py_INCREF(res);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001804 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001805 LEAVE_OVERLAP_TCL
1806 break;
1807 default:
1808 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1809 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001810 }
1811 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001812}
1813
1814static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001815Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001816{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001817 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001818}
1819
1820static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001821Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001822{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001823 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001824}
1825
Barry Warsawfa701a81997-01-16 00:15:11 +00001826
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001827
Guido van Rossum18468821994-06-20 07:49:28 +00001828static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001829GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001830{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001831 char *name1, *name2=NULL;
1832 PyObject *res = NULL;
1833 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001834
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001835 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1836 varname_converter, &name1, &name2))
1837 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001838
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001839 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001840 ENTER_TCL
1841 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1842 ENTER_OVERLAP
1843 if (tres == NULL) {
1844 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1845 } else {
1846 if (((TkappObject*)self)->wantobjects) {
1847 res = FromObj(self, tres);
1848 }
1849 else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001850 int len;
1851 char *s = Tcl_GetStringFromObj(tres, &len);
1852 res = PyString_FromStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001853 }
1854 }
1855 LEAVE_OVERLAP_TCL
1856 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001857}
1858
1859static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001860Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001861{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001862 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001863}
1864
1865static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001866Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001867{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001868 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001869}
1870
Barry Warsawfa701a81997-01-16 00:15:11 +00001871
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001872
Guido van Rossum18468821994-06-20 07:49:28 +00001873static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001874UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001875{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001876 char *name1, *name2=NULL;
1877 int code;
1878 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001879
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001880 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1881 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001882
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001883 CHECK_STRING_LENGTH(name1);
1884 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001885 ENTER_TCL
1886 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1887 ENTER_OVERLAP
1888 if (code == TCL_ERROR)
1889 res = Tkinter_Error(self);
1890 else {
1891 Py_INCREF(Py_None);
1892 res = Py_None;
1893 }
1894 LEAVE_OVERLAP_TCL
1895 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001896}
1897
1898static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001899Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001900{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001901 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001902}
1903
1904static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001905Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001906{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001907 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001908}
1909
Barry Warsawfa701a81997-01-16 00:15:11 +00001910
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001911
Guido van Rossum18468821994-06-20 07:49:28 +00001912/** Tcl to Python **/
1913
1914static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001915Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001916{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001917 char *s;
1918 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001919
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001920 if (PyTuple_Size(args) == 1) {
1921 PyObject* o = PyTuple_GetItem(args, 0);
1922 if (PyInt_Check(o)) {
1923 Py_INCREF(o);
1924 return o;
1925 }
1926 }
1927 if (!PyArg_ParseTuple(args, "s:getint", &s))
1928 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001929 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001930 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1931 return Tkinter_Error(self);
1932 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001933}
1934
1935static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001936Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001937{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001938 char *s;
1939 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001940
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001941 if (PyTuple_Size(args) == 1) {
1942 PyObject *o = PyTuple_GetItem(args, 0);
1943 if (PyFloat_Check(o)) {
1944 Py_INCREF(o);
1945 return o;
1946 }
1947 }
1948 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1949 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001950 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001951 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1952 return Tkinter_Error(self);
1953 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001954}
1955
1956static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001957Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001958{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001959 char *s;
1960 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001961
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001962 if (PyTuple_Size(args) == 1) {
1963 PyObject *o = PyTuple_GetItem(args, 0);
1964 if (PyInt_Check(o)) {
1965 Py_INCREF(o);
1966 return o;
1967 }
1968 }
1969 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1970 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001971 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001972 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1973 return Tkinter_Error(self);
1974 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001975}
1976
1977static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001978Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001979{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001980 char *s;
1981 PyObject *res = NULL;
1982 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001983
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001984 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1985 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001986
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001987 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001988 CHECK_TCL_APPARTMENT;
1989
1990 ENTER_TCL
1991 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1992 ENTER_OVERLAP
1993 if (retval == TCL_ERROR)
1994 res = Tkinter_Error(self);
1995 else
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001996 res = PyString_FromString(Tkapp_Result(self));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001997 LEAVE_OVERLAP_TCL
1998 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001999}
2000
2001static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002002Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002003{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002004 char *s;
2005 PyObject *res = NULL;
2006 int retval;
2007 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002008
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002009 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
2010 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002011
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002012 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002013 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002014
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002015 ENTER_TCL
2016 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2017 ENTER_OVERLAP
2018 if (retval == TCL_ERROR)
2019 res = Tkinter_Error(self);
2020 else
2021 res = Py_BuildValue("l", v);
2022 LEAVE_OVERLAP_TCL
2023 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002024}
2025
2026static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002027Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002028{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002029 char *s;
2030 PyObject *res = NULL;
2031 double v;
2032 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002033
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002034 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2035 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002036 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002037 CHECK_TCL_APPARTMENT;
2038 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2039 ENTER_TCL
2040 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2041 ENTER_OVERLAP
2042 PyFPE_END_PROTECT(retval)
2043 if (retval == TCL_ERROR)
2044 res = Tkinter_Error(self);
2045 else
2046 res = Py_BuildValue("d", v);
2047 LEAVE_OVERLAP_TCL
2048 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002049}
2050
2051static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002052Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002053{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002054 char *s;
2055 PyObject *res = NULL;
2056 int retval;
2057 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002058
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002059 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2060 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002061 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002062 CHECK_TCL_APPARTMENT;
2063 ENTER_TCL
2064 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2065 ENTER_OVERLAP
2066 if (retval == TCL_ERROR)
2067 res = Tkinter_Error(self);
2068 else
2069 res = Py_BuildValue("i", v);
2070 LEAVE_OVERLAP_TCL
2071 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002072}
2073
Barry Warsawfa701a81997-01-16 00:15:11 +00002074
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002075
Guido van Rossum18468821994-06-20 07:49:28 +00002076static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002077Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002078{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002079 char *list;
2080 int argc;
2081 char **argv;
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002082 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002083 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002084
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002085 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2086 return NULL;
2087 if (PyTclObject_Check(arg)) {
2088 int objc;
2089 Tcl_Obj **objv;
2090 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2091 ((PyTclObject*)arg)->value,
2092 &objc, &objv) == TCL_ERROR) {
2093 return Tkinter_Error(self);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002094 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002095 if (!(v = PyTuple_New(objc)))
2096 return NULL;
2097 for (i = 0; i < objc; i++) {
2098 PyObject *s = FromObj(self, objv[i]);
2099 if (!s || PyTuple_SetItem(v, i, s)) {
2100 Py_DECREF(v);
2101 return NULL;
2102 }
2103 }
2104 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002105 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002106 if (PyTuple_Check(arg)) {
2107 Py_INCREF(arg);
2108 return arg;
2109 }
2110
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002111 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2112 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002113
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002114 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002115 if (Tcl_SplitList(Tkapp_Interp(self), list,
2116 &argc, &argv) == TCL_ERROR) {
2117 PyMem_Free(list);
2118 return Tkinter_Error(self);
2119 }
Guido van Rossum18468821994-06-20 07:49:28 +00002120
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002121 if (!(v = PyTuple_New(argc)))
2122 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002123
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002124 for (i = 0; i < argc; i++) {
2125 PyObject *s = PyString_FromString(argv[i]);
2126 if (!s || PyTuple_SetItem(v, i, s)) {
2127 Py_DECREF(v);
2128 v = NULL;
2129 goto finally;
2130 }
2131 }
Guido van Rossum18468821994-06-20 07:49:28 +00002132
Barry Warsawfa701a81997-01-16 00:15:11 +00002133 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002134 ckfree(FREECAST argv);
2135 PyMem_Free(list);
2136 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002137}
2138
2139static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002140Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002141{
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002142 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002143 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002144
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002145 if (!PyArg_ParseTuple(args, "O:split", &arg))
2146 return NULL;
2147 if (PyTclObject_Check(arg)) {
2148 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2149 int objc;
2150 Tcl_Obj **objv;
2151 int i;
2152 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2153 &objc, &objv) == TCL_ERROR) {
2154 return FromObj(self, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002155 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002156 if (objc == 0)
2157 return PyString_FromString("");
2158 if (objc == 1)
2159 return FromObj(self, objv[0]);
2160 if (!(v = PyTuple_New(objc)))
2161 return NULL;
2162 for (i = 0; i < objc; i++) {
2163 PyObject *s = FromObj(self, objv[i]);
2164 if (!s || PyTuple_SetItem(v, i, s)) {
2165 Py_DECREF(v);
2166 return NULL;
2167 }
2168 }
2169 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002170 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002171 if (PyTuple_Check(arg))
2172 return SplitObj(arg);
2173
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002174 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2175 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002176 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002177 v = Split(list);
2178 PyMem_Free(list);
2179 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002180}
2181
2182static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002183Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002184{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002185 char *s = Merge(args);
2186 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002187
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002188 if (s) {
2189 res = PyString_FromString(s);
2190 ckfree(s);
2191 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002192
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002193 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002194}
2195
Barry Warsawfa701a81997-01-16 00:15:11 +00002196
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002197
Guido van Rossum18468821994-06-20 07:49:28 +00002198/** Tcl Command **/
2199
Guido van Rossum00d93061998-05-28 23:06:38 +00002200/* Client data struct */
2201typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002202 PyObject *self;
2203 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002204} PythonCmd_ClientData;
2205
2206static int
Fred Drake509d79a2000-07-08 04:04:38 +00002207PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002208{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002209 errorInCmd = 1;
2210 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2211 LEAVE_PYTHON
2212 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002213}
2214
Guido van Rossum18468821994-06-20 07:49:28 +00002215/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002216 * function or method.
2217 */
Guido van Rossum18468821994-06-20 07:49:28 +00002218static int
Fred Drake509d79a2000-07-08 04:04:38 +00002219PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002220{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002221 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2222 PyObject *func, *arg, *res;
2223 int i, rv;
2224 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002225
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002226 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002227
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002228 /* TBD: no error checking here since we know, via the
2229 * Tkapp_CreateCommand() that the client data is a two-tuple
2230 */
2231 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002232
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002233 /* Create argument list (argv1, ..., argvN) */
2234 if (!(arg = PyTuple_New(argc - 1)))
2235 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002236
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002237 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002238 PyObject *s = fromTclString(argv[i + 1]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002239 if (!s || PyTuple_SetItem(arg, i, s)) {
2240 Py_DECREF(arg);
2241 return PythonCmd_Error(interp);
2242 }
2243 }
2244 res = PyEval_CallObject(func, arg);
2245 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002246
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002247 if (res == NULL)
2248 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002249
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002250 obj_res = AsObj(res);
2251 if (obj_res == NULL) {
2252 Py_DECREF(res);
2253 return PythonCmd_Error(interp);
2254 }
2255 else {
2256 Tcl_SetObjResult(interp, obj_res);
2257 rv = TCL_OK;
2258 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002259
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002260 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002261
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002262 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002263
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002264 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002265}
2266
2267static void
Fred Drake509d79a2000-07-08 04:04:38 +00002268PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002269{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002270 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002271
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002272 ENTER_PYTHON
2273 Py_XDECREF(data->self);
2274 Py_XDECREF(data->func);
2275 PyMem_DEL(data);
2276 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002277}
2278
Barry Warsawfa701a81997-01-16 00:15:11 +00002279
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002280
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002281
Guilherme Polo1972d162009-03-27 21:43:08 +00002282#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002283TCL_DECLARE_MUTEX(command_mutex)
2284
2285typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002286 Tcl_Event ev;
2287 Tcl_Interp* interp;
2288 char *name;
2289 int create;
2290 int *status;
2291 ClientData *data;
2292 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002293} CommandEvent;
2294
2295static int
2296Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002297{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002298 if (ev->create)
2299 *ev->status = Tcl_CreateCommand(
2300 ev->interp, ev->name, PythonCmd,
2301 ev->data, PythonCmdDelete) == NULL;
2302 else
2303 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2304 Tcl_MutexLock(&command_mutex);
2305 Tcl_ConditionNotify(ev->done);
2306 Tcl_MutexUnlock(&command_mutex);
2307 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002308}
Guilherme Polo1972d162009-03-27 21:43:08 +00002309#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002310
2311static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002312Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002313{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002314 TkappObject *self = (TkappObject*)selfptr;
2315 PythonCmd_ClientData *data;
2316 char *cmdName;
2317 PyObject *func;
2318 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002319
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002320 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2321 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002322 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002323 if (!PyCallable_Check(func)) {
2324 PyErr_SetString(PyExc_TypeError, "command not callable");
2325 return NULL;
2326 }
Guido van Rossum18468821994-06-20 07:49:28 +00002327
Martin v. Löwisa9656492003-03-30 08:44:58 +00002328#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002329 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2330 !WaitForMainloop(self))
2331 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002332#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002333
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002334 data = PyMem_NEW(PythonCmd_ClientData, 1);
2335 if (!data)
2336 return PyErr_NoMemory();
2337 Py_INCREF(self);
2338 Py_INCREF(func);
2339 data->self = selfptr;
2340 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002341
2342#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002343 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2344 Tcl_Condition cond = NULL;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03002345 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2346 if (ev == NULL) {
2347 PyErr_NoMemory();
2348 PyMem_DEL(data);
2349 return NULL;
2350 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002351 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2352 ev->interp = self->interp;
2353 ev->create = 1;
2354 ev->name = cmdName;
2355 ev->data = (ClientData)data;
2356 ev->status = &err;
2357 ev->done = &cond;
2358 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2359 Tcl_ConditionFinalize(&cond);
2360 }
2361 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002362#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002363 {
2364 ENTER_TCL
2365 err = Tcl_CreateCommand(
2366 Tkapp_Interp(self), cmdName, PythonCmd,
2367 (ClientData)data, PythonCmdDelete) == NULL;
2368 LEAVE_TCL
2369 }
2370 if (err) {
2371 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2372 PyMem_DEL(data);
2373 return NULL;
2374 }
Guido van Rossum18468821994-06-20 07:49:28 +00002375
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002376 Py_INCREF(Py_None);
2377 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002378}
2379
Barry Warsawfa701a81997-01-16 00:15:11 +00002380
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002381
Guido van Rossum18468821994-06-20 07:49:28 +00002382static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002383Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002384{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002385 TkappObject *self = (TkappObject*)selfptr;
2386 char *cmdName;
2387 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002388
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002389 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2390 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002391 CHECK_STRING_LENGTH(cmdName);
Guilherme Polo1972d162009-03-27 21:43:08 +00002392
2393#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002394 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2395 Tcl_Condition cond = NULL;
2396 CommandEvent *ev;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03002397 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2398 if (ev == NULL) {
2399 PyErr_NoMemory();
2400 return NULL;
2401 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002402 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2403 ev->interp = self->interp;
2404 ev->create = 0;
2405 ev->name = cmdName;
2406 ev->status = &err;
2407 ev->done = &cond;
2408 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2409 &command_mutex);
2410 Tcl_ConditionFinalize(&cond);
2411 }
2412 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002413#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002414 {
2415 ENTER_TCL
2416 err = Tcl_DeleteCommand(self->interp, cmdName);
2417 LEAVE_TCL
2418 }
2419 if (err == -1) {
2420 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2421 return NULL;
2422 }
2423 Py_INCREF(Py_None);
2424 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002425}
2426
Barry Warsawfa701a81997-01-16 00:15:11 +00002427
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002428
Guido van Rossum00d93061998-05-28 23:06:38 +00002429#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002430/** File Handler **/
2431
Guido van Rossum00d93061998-05-28 23:06:38 +00002432typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002433 PyObject *func;
2434 PyObject *file;
2435 int id;
2436 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002437} FileHandler_ClientData;
2438
2439static FileHandler_ClientData *HeadFHCD;
2440
2441static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002442NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002443{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002444 FileHandler_ClientData *p;
2445 p = PyMem_NEW(FileHandler_ClientData, 1);
2446 if (p != NULL) {
2447 Py_XINCREF(func);
2448 Py_XINCREF(file);
2449 p->func = func;
2450 p->file = file;
2451 p->id = id;
2452 p->next = HeadFHCD;
2453 HeadFHCD = p;
2454 }
2455 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002456}
2457
2458static void
Fred Drake509d79a2000-07-08 04:04:38 +00002459DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002460{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002461 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002462
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002463 pp = &HeadFHCD;
2464 while ((p = *pp) != NULL) {
2465 if (p->id == id) {
2466 *pp = p->next;
2467 Py_XDECREF(p->func);
2468 Py_XDECREF(p->file);
2469 PyMem_DEL(p);
2470 }
2471 else
2472 pp = &p->next;
2473 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002474}
2475
Guido van Rossuma597dde1995-01-10 20:56:29 +00002476static void
Fred Drake509d79a2000-07-08 04:04:38 +00002477FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002478{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002479 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2480 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002481
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002482 ENTER_PYTHON
2483 func = data->func;
2484 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002485
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002486 arg = Py_BuildValue("(Oi)", file, (long) mask);
2487 res = PyEval_CallObject(func, arg);
2488 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002489
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002490 if (res == NULL) {
2491 errorInCmd = 1;
2492 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2493 }
2494 Py_XDECREF(res);
2495 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002496}
2497
Guido van Rossum18468821994-06-20 07:49:28 +00002498static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002499Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2500 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002501{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002502 FileHandler_ClientData *data;
2503 PyObject *file, *func;
2504 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002505
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002506 if (!self && Py_Py3kWarningFlag) {
2507 if (PyErr_Warn(PyExc_DeprecationWarning,
2508 "_tkinter.createfilehandler is gone in 3.x") < 0)
2509 return NULL;
2510 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002511
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002512 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2513 &file, &mask, &func))
2514 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002515
Martin v. Löwisa9656492003-03-30 08:44:58 +00002516#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002517 if (!self && !tcl_lock) {
2518 /* We don't have the Tcl lock since Tcl is threaded. */
2519 PyErr_SetString(PyExc_RuntimeError,
2520 "_tkinter.createfilehandler not supported "
2521 "for threaded Tcl");
2522 return NULL;
2523 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002524#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002525
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002526 if (self) {
2527 CHECK_TCL_APPARTMENT;
2528 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002529
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002530 tfile = PyObject_AsFileDescriptor(file);
2531 if (tfile < 0)
2532 return NULL;
2533 if (!PyCallable_Check(func)) {
2534 PyErr_SetString(PyExc_TypeError, "bad argument list");
2535 return NULL;
2536 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002537
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002538 data = NewFHCD(func, file, tfile);
2539 if (data == NULL)
2540 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002541
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002542 /* Ought to check for null Tcl_File object... */
2543 ENTER_TCL
2544 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2545 LEAVE_TCL
2546 Py_INCREF(Py_None);
2547 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002548}
2549
2550static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002551Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002552{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002553 PyObject *file;
2554 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002555
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002556 if (!self && Py_Py3kWarningFlag) {
2557 if (PyErr_Warn(PyExc_DeprecationWarning,
2558 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2559 return NULL;
2560 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002561
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002562 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2563 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002564
Martin v. Löwisa9656492003-03-30 08:44:58 +00002565#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002566 if (!self && !tcl_lock) {
2567 /* We don't have the Tcl lock since Tcl is threaded. */
2568 PyErr_SetString(PyExc_RuntimeError,
2569 "_tkinter.deletefilehandler not supported "
2570 "for threaded Tcl");
2571 return NULL;
2572 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002573#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002574
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002575 if (self) {
2576 CHECK_TCL_APPARTMENT;
2577 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002578
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002579 tfile = PyObject_AsFileDescriptor(file);
2580 if (tfile < 0)
2581 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002582
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002583 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002584
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002585 /* Ought to check for null Tcl_File object... */
2586 ENTER_TCL
2587 Tcl_DeleteFileHandler(tfile);
2588 LEAVE_TCL
2589 Py_INCREF(Py_None);
2590 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002591}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002592#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002593
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002594
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002595/**** Tktt Object (timer token) ****/
2596
Jeremy Hylton938ace62002-07-17 16:30:39 +00002597static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002598
Guido van Rossum00d93061998-05-28 23:06:38 +00002599typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002600 PyObject_HEAD
2601 Tcl_TimerToken token;
2602 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002603} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002604
2605static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002606Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002607{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002608 TkttObject *v = (TkttObject *)self;
2609 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002610
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002611 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2612 return NULL;
2613 if (v->token != NULL) {
2614 Tcl_DeleteTimerHandler(v->token);
2615 v->token = NULL;
2616 }
2617 if (func != NULL) {
2618 v->func = NULL;
2619 Py_DECREF(func);
2620 Py_DECREF(v); /* See Tktt_New() */
2621 }
2622 Py_INCREF(Py_None);
2623 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002624}
2625
2626static PyMethodDef Tktt_methods[] =
2627{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002628 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2629 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002630};
2631
2632static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002633Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002634{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002635 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002636
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002637 v = PyObject_New(TkttObject, &Tktt_Type);
2638 if (v == NULL)
2639 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002640
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002641 Py_INCREF(func);
2642 v->token = NULL;
2643 v->func = func;
2644
2645 /* Extra reference, deleted when called or when handler is deleted */
2646 Py_INCREF(v);
2647 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002648}
2649
2650static void
Fred Drake509d79a2000-07-08 04:04:38 +00002651Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002652{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002653 TkttObject *v = (TkttObject *)self;
2654 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002655
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002656 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002657
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002658 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002659}
2660
Guido van Rossum597ac201998-05-12 14:36:19 +00002661static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002662Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002663{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002664 TkttObject *v = (TkttObject *)self;
2665 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002666
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002667 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2668 v->func == NULL ? ", handler deleted" : "");
2669 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002670}
2671
2672static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002673Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002674{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002675 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002676}
2677
2678static PyTypeObject Tktt_Type =
2679{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002680 PyVarObject_HEAD_INIT(NULL, 0)
2681 "tktimertoken", /*tp_name */
2682 sizeof(TkttObject), /*tp_basicsize */
2683 0, /*tp_itemsize */
2684 Tktt_Dealloc, /*tp_dealloc */
2685 0, /*tp_print */
2686 Tktt_GetAttr, /*tp_getattr */
2687 0, /*tp_setattr */
2688 0, /*tp_compare */
2689 Tktt_Repr, /*tp_repr */
2690 0, /*tp_as_number */
2691 0, /*tp_as_sequence */
2692 0, /*tp_as_mapping */
2693 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002694};
2695
Barry Warsawfa701a81997-01-16 00:15:11 +00002696
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002697
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002698/** Timer Handler **/
2699
2700static void
Fred Drake509d79a2000-07-08 04:04:38 +00002701TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002702{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002703 TkttObject *v = (TkttObject *)clientData;
2704 PyObject *func = v->func;
2705 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002706
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002707 if (func == NULL)
2708 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002709
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002710 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002711
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002712 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002713
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002714 res = PyEval_CallObject(func, NULL);
2715 Py_DECREF(func);
2716 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002717
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002718 if (res == NULL) {
2719 errorInCmd = 1;
2720 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2721 }
2722 else
2723 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002724
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002725 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002726}
2727
2728static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002729Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002730{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002731 int milliseconds;
2732 PyObject *func;
2733 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002734
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002735 if (!self && Py_Py3kWarningFlag) {
2736 if (PyErr_Warn(PyExc_DeprecationWarning,
2737 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2738 return NULL;
2739 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002740
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002741 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2742 &milliseconds, &func))
2743 return NULL;
2744 if (!PyCallable_Check(func)) {
2745 PyErr_SetString(PyExc_TypeError, "bad argument list");
2746 return NULL;
2747 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002748
Martin v. Löwisa9656492003-03-30 08:44:58 +00002749#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002750 if (!self && !tcl_lock) {
2751 /* We don't have the Tcl lock since Tcl is threaded. */
2752 PyErr_SetString(PyExc_RuntimeError,
2753 "_tkinter.createtimerhandler not supported "
2754 "for threaded Tcl");
2755 return NULL;
2756 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002757#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002758
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002759 if (self) {
2760 CHECK_TCL_APPARTMENT;
2761 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002762
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002763 v = Tktt_New(func);
2764 if (v) {
2765 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2766 (ClientData)v);
2767 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002768
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002769 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002770}
2771
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002772
Guido van Rossum18468821994-06-20 07:49:28 +00002773/** Event Loop **/
2774
Guido van Rossum18468821994-06-20 07:49:28 +00002775static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002776Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002777{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002778 int threshold = 0;
2779 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002780#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002781 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002782#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002783
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002784 if (!self && Py_Py3kWarningFlag) {
2785 if (PyErr_Warn(PyExc_DeprecationWarning,
2786 "_tkinter.mainloop is gone in 3.x") < 0)
2787 return NULL;
2788 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002789
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002790 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2791 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002792
Martin v. Löwisa9656492003-03-30 08:44:58 +00002793#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002794 if (!self && !tcl_lock) {
2795 /* We don't have the Tcl lock since Tcl is threaded. */
2796 PyErr_SetString(PyExc_RuntimeError,
2797 "_tkinter.mainloop not supported "
2798 "for threaded Tcl");
2799 return NULL;
2800 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002801#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002802
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002803 if (self) {
2804 CHECK_TCL_APPARTMENT;
2805 self->dispatching = 1;
2806 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002807
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002808 quitMainLoop = 0;
2809 while (Tk_GetNumMainWindows() > threshold &&
2810 !quitMainLoop &&
2811 !errorInCmd)
2812 {
2813 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002814
2815#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002816 if (self && self->threaded) {
2817 /* Allow other Python threads to run. */
2818 ENTER_TCL
2819 result = Tcl_DoOneEvent(0);
2820 LEAVE_TCL
2821 }
2822 else {
2823 Py_BEGIN_ALLOW_THREADS
2824 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2825 tcl_tstate = tstate;
2826 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2827 tcl_tstate = NULL;
2828 if(tcl_lock)PyThread_release_lock(tcl_lock);
2829 if (result == 0)
2830 Sleep(Tkinter_busywaitinterval);
2831 Py_END_ALLOW_THREADS
2832 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002833#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002834 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002835#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002836
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002837 if (PyErr_CheckSignals() != 0) {
2838 if (self)
2839 self->dispatching = 0;
2840 return NULL;
2841 }
2842 if (result < 0)
2843 break;
2844 }
2845 if (self)
2846 self->dispatching = 0;
2847 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002848
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002849 if (errorInCmd) {
2850 errorInCmd = 0;
2851 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2852 excInCmd = valInCmd = trbInCmd = NULL;
2853 return NULL;
2854 }
2855 Py_INCREF(Py_None);
2856 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002857}
2858
2859static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002860Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002861{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002862 int flags = 0;
2863 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002864
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002865 if (!self && Py_Py3kWarningFlag) {
2866 if (PyErr_Warn(PyExc_DeprecationWarning,
2867 "_tkinter.dooneevent is gone in 3.x") < 0)
2868 return NULL;
2869 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002870
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002871 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2872 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002873
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002874 ENTER_TCL
2875 rv = Tcl_DoOneEvent(flags);
2876 LEAVE_TCL
2877 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002878}
2879
2880static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002881Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002882{
2883
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002884 if (!self && Py_Py3kWarningFlag) {
2885 if (PyErr_Warn(PyExc_DeprecationWarning,
2886 "_tkinter.quit is gone in 3.x") < 0)
2887 return NULL;
2888 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002889
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002890 if (!PyArg_ParseTuple(args, ":quit"))
2891 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002892
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002893 quitMainLoop = 1;
2894 Py_INCREF(Py_None);
2895 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002896}
2897
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002898static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002899Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002900{
2901
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002902 if (!PyArg_ParseTuple(args, ":interpaddr"))
2903 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002904
Victor Stinner930c3c92013-09-05 00:26:15 +02002905 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002906}
2907
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002908static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002909Tkapp_TkInit(PyObject *self, PyObject *args)
2910{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002911 Tcl_Interp *interp = Tkapp_Interp(self);
2912 const char * _tk_exists = NULL;
2913 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002914
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002915#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002916 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2917 * first call failed.
2918 * To avoid the deadlock, we just refuse the second call through
2919 * a static variable.
2920 */
2921 if (tk_load_failed) {
2922 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2923 return NULL;
2924 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002925#endif
2926
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002927 /* We want to guard against calling Tk_Init() multiple times */
2928 CHECK_TCL_APPARTMENT;
2929 ENTER_TCL
2930 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2931 ENTER_OVERLAP
2932 if (err == TCL_ERROR) {
2933 /* This sets an exception, but we cannot return right
2934 away because we need to exit the overlap first. */
2935 Tkinter_Error(self);
2936 } else {
2937 _tk_exists = Tkapp_Result(self);
2938 }
2939 LEAVE_OVERLAP_TCL
2940 if (err == TCL_ERROR) {
2941 return NULL;
2942 }
2943 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2944 if (Tk_Init(interp) == TCL_ERROR) {
2945 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002946#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002947 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002948#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002949 return NULL;
2950 }
2951 }
2952 Py_INCREF(Py_None);
2953 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002954}
Barry Warsawfa701a81997-01-16 00:15:11 +00002955
Martin v. Löwisffad6332002-11-26 09:28:05 +00002956static PyObject *
2957Tkapp_WantObjects(PyObject *self, PyObject *args)
2958{
2959
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002960 int wantobjects = -1;
2961 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2962 return NULL;
2963 if (wantobjects == -1)
2964 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2965 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002966
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002967 Py_INCREF(Py_None);
2968 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002969}
2970
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002971static PyObject *
2972Tkapp_WillDispatch(PyObject *self, PyObject *args)
2973{
2974
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002975 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002976
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002977 Py_INCREF(Py_None);
2978 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002979}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002980
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03002981/* Convert Python string or any buffer compatible object to Tcl byte-array
2982 * object. Use it to pass binary data (e.g. image's data) to Tcl/Tk commands.
2983 */
2984static PyObject *
2985Tkapp_CreateByteArray(PyObject *self, PyObject *args)
2986{
2987 Py_buffer view;
2988 Tcl_Obj* obj;
2989 PyObject *res = NULL;
2990
2991 if (!PyArg_ParseTuple(args, "s*:_createbytearray", &view))
2992 return NULL;
2993
2994 if (view.len >= INT_MAX) {
2995 PyErr_SetString(PyExc_OverflowError, "string is too long");
2996 return NULL;
2997 }
2998 obj = Tcl_NewByteArrayObj(view.buf, (int)view.len);
2999 if (obj == NULL) {
3000 PyBuffer_Release(&view);
3001 return Tkinter_Error(self);
3002 }
3003 res = newPyTclObject(obj);
3004 PyBuffer_Release(&view);
3005 return res;
3006}
3007
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003008
Guido van Rossum18468821994-06-20 07:49:28 +00003009/**** Tkapp Method List ****/
3010
3011static PyMethodDef Tkapp_methods[] =
3012{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003013 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
3014 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3015 {"call", Tkapp_Call, METH_VARARGS},
3016 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
3017 {"eval", Tkapp_Eval, METH_VARARGS},
3018 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
3019 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
3020 {"record", Tkapp_Record, METH_VARARGS},
3021 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
3022 {"setvar", Tkapp_SetVar, METH_VARARGS},
3023 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3024 {"getvar", Tkapp_GetVar, METH_VARARGS},
3025 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3026 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3027 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3028 {"getint", Tkapp_GetInt, METH_VARARGS},
3029 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
3030 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
3031 {"exprstring", Tkapp_ExprString, METH_VARARGS},
3032 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
3033 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
3034 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
3035 {"splitlist", Tkapp_SplitList, METH_VARARGS},
3036 {"split", Tkapp_Split, METH_VARARGS},
3037 {"merge", Tkapp_Merge, METH_VARARGS},
3038 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
3039 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003040#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003041 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3042 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003043#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003044 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3045 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3046 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3047 {"quit", Tkapp_Quit, METH_VARARGS},
3048 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
3049 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03003050 {"_createbytearray", Tkapp_CreateByteArray, METH_VARARGS},
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003051 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003052};
3053
Barry Warsawfa701a81997-01-16 00:15:11 +00003054
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003055
Guido van Rossum18468821994-06-20 07:49:28 +00003056/**** Tkapp Type Methods ****/
3057
3058static void
Fred Drake509d79a2000-07-08 04:04:38 +00003059Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003060{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003061 /*CHECK_TCL_APPARTMENT;*/
3062 ENTER_TCL
3063 Tcl_DeleteInterp(Tkapp_Interp(self));
3064 LEAVE_TCL
3065 PyObject_Del(self);
3066 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003067}
3068
3069static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00003070Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00003071{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003072 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00003073}
3074
3075static PyTypeObject Tkapp_Type =
3076{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003077 PyVarObject_HEAD_INIT(NULL, 0)
3078 "tkapp", /*tp_name */
3079 sizeof(TkappObject), /*tp_basicsize */
3080 0, /*tp_itemsize */
3081 Tkapp_Dealloc, /*tp_dealloc */
3082 0, /*tp_print */
3083 Tkapp_GetAttr, /*tp_getattr */
3084 0, /*tp_setattr */
3085 0, /*tp_compare */
3086 0, /*tp_repr */
3087 0, /*tp_as_number */
3088 0, /*tp_as_sequence */
3089 0, /*tp_as_mapping */
3090 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00003091};
3092
Barry Warsawfa701a81997-01-16 00:15:11 +00003093
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003094
Guido van Rossum18468821994-06-20 07:49:28 +00003095/**** Tkinter Module ****/
3096
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003097typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003098 PyObject* tuple;
3099 int size; /* current size */
3100 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003101} FlattenContext;
3102
3103static int
3104_bump(FlattenContext* context, int size)
3105{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003106 /* expand tuple to hold (at least) size new items.
3107 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003108
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003109 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003110
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003111 if (maxsize < context->size + size)
3112 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003113
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003114 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003115
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003116 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003117}
3118
3119static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003120_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003121{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003122 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003123
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003124 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003125
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003126 if (depth > 1000) {
3127 PyErr_SetString(PyExc_ValueError,
3128 "nesting too deep in _flatten");
3129 return 0;
3130 } else if (PyList_Check(item)) {
3131 size = PyList_GET_SIZE(item);
3132 /* preallocate (assume no nesting) */
3133 if (context->size + size > context->maxsize &&
3134 !_bump(context, size))
3135 return 0;
3136 /* copy items to output tuple */
3137 for (i = 0; i < size; i++) {
3138 PyObject *o = PyList_GET_ITEM(item, i);
3139 if (PyList_Check(o) || PyTuple_Check(o)) {
3140 if (!_flatten1(context, o, depth + 1))
3141 return 0;
3142 } else if (o != Py_None) {
3143 if (context->size + 1 > context->maxsize &&
3144 !_bump(context, 1))
3145 return 0;
3146 Py_INCREF(o);
3147 PyTuple_SET_ITEM(context->tuple,
3148 context->size++, o);
3149 }
3150 }
3151 } else if (PyTuple_Check(item)) {
3152 /* same, for tuples */
3153 size = PyTuple_GET_SIZE(item);
3154 if (context->size + size > context->maxsize &&
3155 !_bump(context, size))
3156 return 0;
3157 for (i = 0; i < size; i++) {
3158 PyObject *o = PyTuple_GET_ITEM(item, i);
3159 if (PyList_Check(o) || PyTuple_Check(o)) {
3160 if (!_flatten1(context, o, depth + 1))
3161 return 0;
3162 } else if (o != Py_None) {
3163 if (context->size + 1 > context->maxsize &&
3164 !_bump(context, 1))
3165 return 0;
3166 Py_INCREF(o);
3167 PyTuple_SET_ITEM(context->tuple,
3168 context->size++, o);
3169 }
3170 }
3171 } else {
3172 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3173 return 0;
3174 }
3175 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003176}
3177
3178static PyObject *
3179Tkinter_Flatten(PyObject* self, PyObject* args)
3180{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003181 FlattenContext context;
3182 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003183
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003184 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3185 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003186
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003187 context.maxsize = PySequence_Size(item);
3188 if (context.maxsize < 0)
3189 return NULL;
3190 if (context.maxsize == 0)
3191 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003192
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003193 context.tuple = PyTuple_New(context.maxsize);
3194 if (!context.tuple)
3195 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003196
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003197 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003198
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003199 if (!_flatten1(&context, item,0))
3200 return NULL;
3201
3202 if (_PyTuple_Resize(&context.tuple, context.size))
3203 return NULL;
3204
3205 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003206}
3207
Guido van Rossum18468821994-06-20 07:49:28 +00003208static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003209Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003210{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003211 char *screenName = NULL;
3212 char *baseName = NULL;
3213 char *className = NULL;
3214 int interactive = 0;
3215 int wantobjects = 0;
3216 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3217 int sync = 0; /* pass -sync to wish */
3218 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003219
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003220 baseName = strrchr(Py_GetProgramName(), '/');
3221 if (baseName != NULL)
3222 baseName++;
3223 else
3224 baseName = Py_GetProgramName();
3225 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003226
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003227 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3228 &screenName, &baseName, &className,
3229 &interactive, &wantobjects, &wantTk,
3230 &sync, &use))
3231 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03003232 CHECK_STRING_LENGTH(screenName);
3233 CHECK_STRING_LENGTH(baseName);
3234 CHECK_STRING_LENGTH(className);
3235 CHECK_STRING_LENGTH(use);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003236
3237 return (PyObject *) Tkapp_New(screenName, baseName, className,
3238 interactive, wantobjects, wantTk,
3239 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003240}
3241
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003242static PyObject *
3243Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3244{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003245 int new_val;
3246 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3247 return NULL;
3248 if (new_val < 0) {
3249 PyErr_SetString(PyExc_ValueError,
3250 "busywaitinterval must be >= 0");
3251 return NULL;
3252 }
3253 Tkinter_busywaitinterval = new_val;
3254 Py_INCREF(Py_None);
3255 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003256}
3257
3258static char setbusywaitinterval_doc[] =
3259"setbusywaitinterval(n) -> None\n\
3260\n\
3261Set the busy-wait interval in milliseconds between successive\n\
3262calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3263It should be set to a divisor of the maximum time between\n\
3264frames in an animation.";
3265
3266static PyObject *
3267Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3268{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003269 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003270}
3271
3272static char getbusywaitinterval_doc[] =
3273"getbusywaitinterval() -> int\n\
3274\n\
3275Return the current busy-wait interval between successive\n\
3276calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3277
Guido van Rossum18468821994-06-20 07:49:28 +00003278static PyMethodDef moduleMethods[] =
3279{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003280 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3281 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003282#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003283 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3284 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003285#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003286 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3287 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3288 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3289 {"quit", Tkapp_Quit, METH_VARARGS},
3290 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3291 setbusywaitinterval_doc},
3292 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3293 METH_NOARGS, getbusywaitinterval_doc},
3294 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003295};
3296
Guido van Rossum7bf15641998-05-22 18:28:17 +00003297#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003298
3299static int stdin_ready = 0;
3300
Guido van Rossumad4db171998-06-13 13:56:28 +00003301#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003302static void
Fred Drake509d79a2000-07-08 04:04:38 +00003303MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003304{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003305 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003306}
Guido van Rossumad4db171998-06-13 13:56:28 +00003307#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003308
Martin v. Löwisa9656492003-03-30 08:44:58 +00003309#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003310static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003311#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003312
Guido van Rossum18468821994-06-20 07:49:28 +00003313static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003314EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003315{
Guido van Rossumad4db171998-06-13 13:56:28 +00003316#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003317 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003318#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003319#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003320 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003321#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003322 stdin_ready = 0;
3323 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003324#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003325 tfile = fileno(stdin);
3326 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003327#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003328 while (!errorInCmd && !stdin_ready) {
3329 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003330#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003331 if (_kbhit()) {
3332 stdin_ready = 1;
3333 break;
3334 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003335#endif
3336#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003337 Py_BEGIN_ALLOW_THREADS
3338 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3339 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003340
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003341 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003342
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003343 tcl_tstate = NULL;
3344 if(tcl_lock)PyThread_release_lock(tcl_lock);
3345 if (result == 0)
3346 Sleep(Tkinter_busywaitinterval);
3347 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003348#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003349 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003350#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003351
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003352 if (result < 0)
3353 break;
3354 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003355#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003356 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003357#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003358 if (errorInCmd) {
3359 errorInCmd = 0;
3360 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3361 excInCmd = valInCmd = trbInCmd = NULL;
3362 PyErr_Print();
3363 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003364#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003365 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003366#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003367 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003368}
Guido van Rossum18468821994-06-20 07:49:28 +00003369
Guido van Rossum00d93061998-05-28 23:06:38 +00003370#endif
3371
Guido van Rossum7bf15641998-05-22 18:28:17 +00003372static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003373EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003374{
Guido van Rossum00d93061998-05-28 23:06:38 +00003375#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003376 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003377#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003378 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003379#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003380 PyOS_InputHook = EventHook;
3381 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003382#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003383}
3384
3385static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003386DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003387{
Guido van Rossum00d93061998-05-28 23:06:38 +00003388#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003389 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3390 PyOS_InputHook = NULL;
3391 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003392#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003393}
3394
Barry Warsawfa701a81997-01-16 00:15:11 +00003395
3396/* all errors will be checked in one fell swoop in init_tkinter() */
3397static void
Fred Drake509d79a2000-07-08 04:04:38 +00003398ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003399{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003400 PyObject *v = PyInt_FromLong(val);
3401 if (v) {
3402 PyDict_SetItemString(d, name, v);
3403 Py_DECREF(v);
3404 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003405}
3406static void
Fred Drake509d79a2000-07-08 04:04:38 +00003407ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003408{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003409 PyObject *v = PyString_FromString(val);
3410 if (v) {
3411 PyDict_SetItemString(d, name, v);
3412 Py_DECREF(v);
3413 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003414}
3415
3416
Mark Hammond62b1ab12002-07-23 06:31:15 +00003417PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003418init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003419{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003420 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003421
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003422 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003423
3424#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003425 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003426#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003427
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003428 m = Py_InitModule("_tkinter", moduleMethods);
3429 if (m == NULL)
3430 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003431
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003432 d = PyModule_GetDict(m);
3433 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3434 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003435
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003436 ins_long(d, "READABLE", TCL_READABLE);
3437 ins_long(d, "WRITABLE", TCL_WRITABLE);
3438 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3439 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3440 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3441 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3442 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3443 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3444 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3445 ins_string(d, "TK_VERSION", TK_VERSION);
3446 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003447
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003448 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003449
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003450 Py_TYPE(&Tktt_Type) = &PyType_Type;
3451 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003452
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003453 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3454 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003455
3456#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003457 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3458 * start waking up. Note that Tcl_FindExecutable will do this, this
3459 * code must be above it! The original warning from
3460 * tkMacOSXAppInit.c is copied below.
3461 *
3462 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3463 * Tcl interpreter for now. It probably should work to do this
3464 * in the other order, but for now it doesn't seem to.
3465 *
3466 */
3467 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003468#endif
3469
3470
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003471 /* This helps the dynamic loader; in Unicode aware Tcl versions
3472 it also helps Tcl find its encodings. */
3473 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003474
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003475 if (PyErr_Occurred())
3476 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003477
Guido van Rossum43ff8681998-07-14 18:02:13 +00003478#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003479 /* This was not a good idea; through <Destroy> bindings,
3480 Tcl_Finalize() may invoke Python code but at that point the
3481 interpreter and thread state have already been destroyed! */
3482 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003483#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003484
Guido van Rossum18468821994-06-20 07:49:28 +00003485}