blob: c71ffd016ad8814dccde09e6992f4ca01fcc8c35 [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,
Martin Panter4e6e5652016-06-20 07:52:50 +000055 making _tkinter correct for this API means breaking earlier
56 versions. USE_COMPAT_CONST allows making _tkinter work with both 8.4 and
Martin v. Löwis71e25a02002-10-01 18:08:06 +000057 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
Serhiy Storchaka656ffdb2015-04-21 21:17:33 +030083#if TK_HEX_VERSION < 0x08030201
Guilherme Poloc5eba1e2009-02-09 20:57:45 +000084#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
Serhiy Storchaka656ffdb2015-04-21 21:17:33 +030099#if TK_HEX_VERSION >= 0x08050208 && TK_HEX_VERSION < 0x08060000 || \
100 TK_HEX_VERSION >= 0x08060200
Serhiy Storchakac77c5b52015-04-02 18:46:30 +0300101#define HAVE_LIBTOMMAMTH
102#include <tclTomMath.h>
103#endif
104
Jack Janseneddc1442003-11-20 01:44:59 +0000105#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000106#define HAVE_CREATEFILEHANDLER
107#endif
108
Guido van Rossum00d93061998-05-28 23:06:38 +0000109#ifdef HAVE_CREATEFILEHANDLER
110
Neal Norwitzd948a432006-01-08 01:08:55 +0000111/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
112 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
113#ifndef TCL_UNIX_FD
114# ifdef TCL_WIN_SOCKET
115# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
116# else
117# define TCL_UNIX_FD 1
118# endif
119#endif
120
Guido van Rossum00d93061998-05-28 23:06:38 +0000121/* Tcl_CreateFileHandler() changed several times; these macros deal with the
122 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
123 Unix, only because Jack added it back); when available on Windows, it only
124 applies to sockets. */
125
Guido van Rossum7bf15641998-05-22 18:28:17 +0000126#ifdef MS_WINDOWS
127#define FHANDLETYPE TCL_WIN_SOCKET
128#else
129#define FHANDLETYPE TCL_UNIX_FD
130#endif
131
Guido van Rossum00d93061998-05-28 23:06:38 +0000132/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
133 which uses this to handle Tcl events while the user is typing commands. */
134
135#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000136#define WAIT_FOR_STDIN
137#endif
138
Guido van Rossum00d93061998-05-28 23:06:38 +0000139#endif /* HAVE_CREATEFILEHANDLER */
140
Guido van Rossumad4db171998-06-13 13:56:28 +0000141#ifdef MS_WINDOWS
142#include <conio.h>
143#define WAIT_FOR_STDIN
144#endif
145
Guido van Rossum00d93061998-05-28 23:06:38 +0000146#ifdef WITH_THREAD
147
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000148/* The threading situation is complicated. Tcl is not thread-safe, except
149 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000150 So we need to use a lock around all uses of Tcl. Previously, the Python
151 interpreter lock was used for this. However, this causes problems when
152 other Python threads need to run while Tcl is blocked waiting for events.
153
154 To solve this problem, a separate lock for Tcl is introduced. Holding it
155 is incompatible with holding Python's interpreter lock. The following four
156 macros manipulate both locks together.
157
158 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
159 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
160 that could call an event handler, or otherwise affect the state of a Tcl
161 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000162 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000163 released and the lock for Tcl has been acquired.
164
Guido van Rossum5e977831998-06-15 14:03:52 +0000165 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
166 (For example, when transferring data from the Tcl interpreter result to a
167 Python string object.) This can be done by using different macros to close
168 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
169 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
170 releases the Tcl lock.
171
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000172 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000173 handlers when the handler needs to use Python. Such event handlers are
174 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000175 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000176 the Python interpreter lock, restoring the appropriate thread state, and
177 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
178 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000179 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000180
181 These locks expand to several statements and brackets; they should not be
182 used in branches of if statements and the like.
183
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000184 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
185 only valid in the thread that created it, and all Tk activity must happen in this
186 thread, also. That means that the mainloop must be invoked in the thread that
187 created the interpreter. Invoking commands from other threads is possible;
188 _tkinter will queue an event for the interpreter thread, which will then
189 execute the command and pass back the result. If the main thread is not in the
190 mainloop, and invoking commands causes an exception; if the main loop is running
191 but not processing events, the command invocation will block.
192
193 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
194 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
195 threads. So we use the Tcl TLS API.
196
Guido van Rossum00d93061998-05-28 23:06:38 +0000197*/
198
Guido van Rossum65d5b571998-12-21 19:32:43 +0000199static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000200
201#ifdef TCL_THREADS
202static Tcl_ThreadDataKey state_key;
203typedef PyThreadState *ThreadSpecificData;
204#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
205#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000206static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000207#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000208
209#define ENTER_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000210 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
211 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000212
213#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000214 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000215
Guido van Rossum62320c91998-06-15 04:36:09 +0000216#define ENTER_OVERLAP \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000217 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000218
219#define LEAVE_OVERLAP_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000220 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000221
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000222#define ENTER_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000223 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
224 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000225
226#define LEAVE_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000227 { PyThreadState *tstate = PyEval_SaveThread(); \
228 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000229
230#define CHECK_TCL_APPARTMENT \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000231 if (((TkappObject *)self)->threaded && \
232 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
233 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
234 return 0; \
235 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000236
237#else
238
239#define ENTER_TCL
240#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000241#define ENTER_OVERLAP
242#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000243#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000244#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000245#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000246
247#endif
248
Guido van Rossum97867b21996-08-08 19:09:53 +0000249#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000250#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000251#endif
252
Guido van Rossum18468821994-06-20 07:49:28 +0000253/**** Tkapp Object Declaration ****/
254
Jeremy Hylton938ace62002-07-17 16:30:39 +0000255static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000256
Guido van Rossum00d93061998-05-28 23:06:38 +0000257typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000258 PyObject_HEAD
259 Tcl_Interp *interp;
260 int wantobjects;
261 int threaded; /* True if tcl_platform[threaded] */
262 Tcl_ThreadId thread_id;
263 int dispatching;
264 /* We cannot include tclInt.h, as this is internal.
265 So we cache interesting types here. */
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +0300266 const Tcl_ObjType *OldBooleanType;
267 const Tcl_ObjType *BooleanType;
268 const Tcl_ObjType *ByteArrayType;
269 const Tcl_ObjType *DoubleType;
270 const Tcl_ObjType *IntType;
Serhiy Storchakac77c5b52015-04-02 18:46:30 +0300271 const Tcl_ObjType *WideIntType;
272 const Tcl_ObjType *BignumType;
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +0300273 const Tcl_ObjType *ListType;
274 const Tcl_ObjType *ProcBodyType;
275 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000276} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000277
Christian Heimese93237d2007-12-19 02:37:44 +0000278#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000279#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000280#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000281
Guido van Rossum35d43371997-08-02 00:09:09 +0000282#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimese93237d2007-12-19 02:37:44 +0000283(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000284
Barry Warsawfa701a81997-01-16 00:15:11 +0000285
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000286
Guido van Rossum18468821994-06-20 07:49:28 +0000287/**** Error Handling ****/
288
289static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000290static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000291static int errorInCmd = 0;
292static PyObject *excInCmd;
293static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000294static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000295
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000296#ifdef TKINTER_PROTECT_LOADTK
297static int tk_load_failed;
298#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000299
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000300
Guido van Rossum18468821994-06-20 07:49:28 +0000301static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000302Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000303{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000304 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
305 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000306}
307
Barry Warsawfa701a81997-01-16 00:15:11 +0000308
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000309
Guido van Rossum18468821994-06-20 07:49:28 +0000310/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000311
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000312static int Tkinter_busywaitinterval = 20;
313
Guido van Rossum00d93061998-05-28 23:06:38 +0000314#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000315#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000316
Guido van Rossum00d93061998-05-28 23:06:38 +0000317/* Millisecond sleep() for Unix platforms. */
318
319static void
Fred Drake509d79a2000-07-08 04:04:38 +0000320Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000321{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000322 /* XXX Too bad if you don't have select(). */
323 struct timeval t;
324 t.tv_sec = milli/1000;
325 t.tv_usec = (milli%1000) * 1000;
326 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000327}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000328#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000329
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000330/* Wait up to 1s for the mainloop to come up. */
331
332static int
333WaitForMainloop(TkappObject* self)
334{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000335 int i;
336 for (i = 0; i < 10; i++) {
337 if (self->dispatching)
338 return 1;
339 Py_BEGIN_ALLOW_THREADS
340 Sleep(100);
341 Py_END_ALLOW_THREADS
342 }
343 if (self->dispatching)
344 return 1;
345 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
346 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000347}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000348#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000349
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000350
Guido van Rossum18468821994-06-20 07:49:28 +0000351static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000352AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000353{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000354 if (PyString_Check(value))
355 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000356#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000357 else if (PyUnicode_Check(value)) {
358 PyObject *v = PyUnicode_AsUTF8String(value);
359 if (v == NULL)
360 return NULL;
361 if (PyList_Append(tmp, v) != 0) {
362 Py_DECREF(v);
363 return NULL;
364 }
365 Py_DECREF(v);
366 return PyString_AsString(v);
367 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000368#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000369 else {
370 PyObject *v = PyObject_Str(value);
371 if (v == NULL)
372 return NULL;
373 if (PyList_Append(tmp, v) != 0) {
374 Py_DECREF(v);
375 return NULL;
376 }
377 Py_DECREF(v);
378 return PyString_AsString(v);
379 }
Guido van Rossum18468821994-06-20 07:49:28 +0000380}
381
Barry Warsawfa701a81997-01-16 00:15:11 +0000382
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000383
Guido van Rossum18468821994-06-20 07:49:28 +0000384#define ARGSZ 64
385
386static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000387Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000388{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000389 PyObject *tmp = NULL;
390 char *argvStore[ARGSZ];
391 char **argv = NULL;
392 int fvStore[ARGSZ];
393 int *fv = NULL;
Serhiy Storchaka42035702013-08-21 21:46:12 +0300394 Py_ssize_t argc = 0, fvc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000395 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000396
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000397 if (!(tmp = PyList_New(0)))
398 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000399
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000400 argv = argvStore;
401 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000402
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000403 if (args == NULL)
404 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000405
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000406 else if (!PyTuple_Check(args)) {
407 argc = 1;
408 fv[0] = 0;
409 if (!(argv[0] = AsString(args, tmp)))
410 goto finally;
411 }
412 else {
413 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000414
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000415 if (argc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +0300416 if (!CHECK_SIZE(argc, sizeof(char *))) {
417 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
418 goto finally;
419 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +0300420 argv = (char **)attemptckalloc((size_t)argc * sizeof(char *));
421 fv = (int *)attemptckalloc((size_t)argc * sizeof(int));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000422 if (argv == NULL || fv == NULL) {
423 PyErr_NoMemory();
424 goto finally;
425 }
426 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000427
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000428 for (i = 0; i < argc; i++) {
429 PyObject *v = PyTuple_GetItem(args, i);
430 if (PyTuple_Check(v)) {
431 fv[i] = 1;
432 if (!(argv[i] = Merge(v)))
433 goto finally;
434 fvc++;
435 }
436 else if (v == Py_None) {
437 argc = i;
438 break;
439 }
440 else {
441 fv[i] = 0;
442 if (!(argv[i] = AsString(v, tmp)))
443 goto finally;
444 fvc++;
445 }
446 }
447 }
448 res = Tcl_Merge(argc, argv);
449 if (res == NULL)
450 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000451
Barry Warsawfa701a81997-01-16 00:15:11 +0000452 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000453 for (i = 0; i < fvc; i++)
454 if (fv[i]) {
455 ckfree(argv[i]);
456 }
457 if (argv != argvStore)
458 ckfree(FREECAST argv);
459 if (fv != fvStore)
460 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000461
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000462 Py_DECREF(tmp);
463 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000464}
465
Barry Warsawfa701a81997-01-16 00:15:11 +0000466
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000467
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200468#ifdef Py_USING_UNICODE
469static PyObject *
470unicode_FromTclStringAndSize(const char *s, Py_ssize_t size)
471{
472 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
473 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
474 /* Tcl encodes null character as \xc0\x80 */
475 if (memchr(s, '\xc0', size)) {
476 char *buf, *q;
477 const char *e = s + size;
478 PyErr_Clear();
479 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchaka5d93f402014-07-14 12:20:01 +0300480 if (buf == NULL) {
481 PyErr_NoMemory();
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200482 return NULL;
Serhiy Storchaka5d93f402014-07-14 12:20:01 +0300483 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200484 while (s != e) {
485 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
486 *q++ = '\0';
487 s += 2;
488 }
489 else
490 *q++ = *s++;
491 }
492 s = buf;
493 size = q - s;
494 r = PyUnicode_DecodeUTF8(s, size, NULL);
495 PyMem_Free(buf);
496 }
497 }
498 return r;
499}
500#endif
501
502static PyObject *
503fromTclStringAndSize(const char *s, Py_ssize_t size)
504{
505 PyObject *r;
506#ifdef Py_USING_UNICODE
507 Py_ssize_t i;
508 /* If Tcl string contains any bytes with the top bit set,
509 it's UTF-8 and we should decode it to Unicode */
510 for (i = 0; i < size; i++)
511 if (s[i] & 0x80)
512 break;
513 if (i != size) {
514 /* It isn't an ASCII string. */
515 r = unicode_FromTclStringAndSize(s, size);
516 if (r)
517 return r;
518 PyErr_Clear();
519 }
520#endif
521 r = PyString_FromStringAndSize(s, size);
522 return r;
523}
524
525static PyObject *
526fromTclString(const char *s)
527{
528 return fromTclStringAndSize(s, strlen(s));
529}
530
531
Guido van Rossum18468821994-06-20 07:49:28 +0000532static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000533Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000534{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000535 int argc;
536 char **argv;
537 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000538
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000539 if (list == NULL) {
540 Py_INCREF(Py_None);
541 return Py_None;
542 }
Guido van Rossum18468821994-06-20 07:49:28 +0000543
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000544 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
545 /* Not a list.
546 * Could be a quoted string containing funnies, e.g. {"}.
547 * Return the string itself.
548 */
549 return PyString_FromString(list);
550 }
Guido van Rossum18468821994-06-20 07:49:28 +0000551
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000552 if (argc == 0)
553 v = PyString_FromString("");
554 else if (argc == 1)
555 v = PyString_FromString(argv[0]);
556 else if ((v = PyTuple_New(argc)) != NULL) {
557 int i;
558 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000559
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000560 for (i = 0; i < argc; i++) {
561 if ((w = Split(argv[i])) == NULL) {
562 Py_DECREF(v);
563 v = NULL;
564 break;
565 }
566 PyTuple_SetItem(v, i, w);
567 }
568 }
569 Tcl_Free(FREECAST argv);
570 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000571}
572
Martin v. Löwisffad6332002-11-26 09:28:05 +0000573/* In some cases, Tcl will still return strings that are supposed to be
574 lists. SplitObj walks through a nested tuple, finding string objects that
575 need to be split. */
576
Martin v. Löwis111c1802008-06-13 07:47:47 +0000577static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000578SplitObj(PyObject *arg)
579{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000580 if (PyTuple_Check(arg)) {
581 int i, size;
582 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000583
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000584 size = PyTuple_Size(arg);
585 result = NULL;
586 /* Recursively invoke SplitObj for all tuple items.
587 If this does not return a new object, no action is
588 needed. */
589 for(i = 0; i < size; i++) {
590 elem = PyTuple_GetItem(arg, i);
591 newelem = SplitObj(elem);
592 if (!newelem) {
593 Py_XDECREF(result);
594 return NULL;
595 }
596 if (!result) {
597 int k;
598 if (newelem == elem) {
599 Py_DECREF(newelem);
600 continue;
601 }
602 result = PyTuple_New(size);
603 if (!result)
604 return NULL;
605 for(k = 0; k < i; k++) {
606 elem = PyTuple_GetItem(arg, k);
607 Py_INCREF(elem);
608 PyTuple_SetItem(result, k, elem);
609 }
610 }
611 PyTuple_SetItem(result, i, newelem);
612 }
613 if (result)
614 return result;
615 /* Fall through, returning arg. */
616 }
617 else if (PyString_Check(arg)) {
618 int argc;
619 char **argv;
620 char *list = PyString_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000621
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000622 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
623 Py_INCREF(arg);
624 return arg;
625 }
626 Tcl_Free(FREECAST argv);
627 if (argc > 1)
628 return Split(PyString_AsString(arg));
629 /* Fall through, returning arg. */
630 }
Serhiy Storchakafab65422013-07-11 20:32:48 +0300631 else if (PyUnicode_Check(arg)) {
632 int argc;
633 char **argv;
634 char *list;
635 PyObject *s = PyUnicode_AsUTF8String(arg);
636
637 if (s == NULL) {
638 Py_INCREF(arg);
639 return arg;
640 }
641 list = PyString_AsString(s);
642
643 if (list == NULL ||
644 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
645 Py_DECREF(s);
646 Py_INCREF(arg);
647 return arg;
648 }
649 Tcl_Free(FREECAST argv);
650 if (argc > 1) {
651 PyObject *v = Split(list);
652 Py_DECREF(s);
653 return v;
654 }
655 Py_DECREF(s);
656 /* Fall through, returning arg. */
657 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000658 Py_INCREF(arg);
659 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000660}
Barry Warsawfa701a81997-01-16 00:15:11 +0000661
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000662
Guido van Rossum18468821994-06-20 07:49:28 +0000663/**** Tkapp Object ****/
664
665#ifndef WITH_APPINIT
666int
Fred Drake509d79a2000-07-08 04:04:38 +0000667Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000668{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000669 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000670
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000671 if (Tcl_Init(interp) == TCL_ERROR) {
672 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
673 return TCL_ERROR;
674 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000675
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000676 _tkinter_skip_tk_init = Tcl_GetVar(interp,
677 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
678 if (_tkinter_skip_tk_init != NULL &&
679 strcmp(_tkinter_skip_tk_init, "1") == 0) {
680 return TCL_OK;
681 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000682
683#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000684 if (tk_load_failed) {
685 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
686 return TCL_ERROR;
687 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000688#endif
689
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000690 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000691#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000692 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000693#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000694 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
695 return TCL_ERROR;
696 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000697
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000698 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000699}
700#endif /* !WITH_APPINIT */
701
Guido van Rossum18468821994-06-20 07:49:28 +0000702
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000703
Barry Warsawfa701a81997-01-16 00:15:11 +0000704
705/* Initialize the Tk application; see the `main' function in
706 * `tkMain.c'.
707 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000708
Thomas Wouters58d05102000-07-24 14:43:35 +0000709static void EnableEventHook(void); /* Forward */
710static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000711
Barry Warsawfa701a81997-01-16 00:15:11 +0000712static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000713Tkapp_New(char *screenName, char *baseName, char *className,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000714 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000715{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000716 TkappObject *v;
717 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000718
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000719 v = PyObject_New(TkappObject, &Tkapp_Type);
720 if (v == NULL)
721 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000722
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000723 v->interp = Tcl_CreateInterp();
724 v->wantobjects = wantobjects;
725 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
726 TCL_GLOBAL_ONLY) != NULL;
727 v->thread_id = Tcl_GetCurrentThread();
728 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000729
730#ifndef TCL_THREADS
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000731 if (v->threaded) {
732 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
733 Py_DECREF(v);
734 return 0;
735 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000736#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000737#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000738 if (v->threaded && tcl_lock) {
739 /* If Tcl is threaded, we don't need the lock. */
740 PyThread_free_lock(tcl_lock);
741 tcl_lock = NULL;
742 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000743#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000744
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +0300745 v->OldBooleanType = Tcl_GetObjType("boolean");
746 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000747 v->ByteArrayType = Tcl_GetObjType("bytearray");
748 v->DoubleType = Tcl_GetObjType("double");
749 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakac77c5b52015-04-02 18:46:30 +0300750 v->WideIntType = Tcl_GetObjType("wideInt");
751 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000752 v->ListType = Tcl_GetObjType("list");
753 v->ProcBodyType = Tcl_GetObjType("procbody");
754 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000755
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000756 /* Delete the 'exit' command, which can screw things up */
757 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000758
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000759 if (screenName != NULL)
760 Tcl_SetVar2(v->interp, "env", "DISPLAY",
761 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000762
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000763 if (interactive)
764 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
765 else
766 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000767
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000768 /* This is used to get the application class for Tk 4.1 and up */
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +0300769 argv0 = (char*)attemptckalloc(strlen(className) + 1);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000770 if (!argv0) {
771 PyErr_NoMemory();
772 Py_DECREF(v);
773 return NULL;
774 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000775
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000776 strcpy(argv0, className);
Antoine Pitrou44b3b542011-10-04 13:55:37 +0200777 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
778 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000779 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
780 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000781
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000782 if (! wantTk) {
783 Tcl_SetVar(v->interp,
784 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
785 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000786#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000787 else if (tk_load_failed) {
788 Tcl_SetVar(v->interp,
789 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
790 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000791#endif
David Aschere2b4b322004-02-18 05:59:53 +0000792
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000793 /* some initial arguments need to be in argv */
794 if (sync || use) {
795 char *args;
796 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000797
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000798 if (sync)
799 len += sizeof "-sync";
800 if (use)
801 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000802
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +0300803 args = (char*)attemptckalloc(len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000804 if (!args) {
805 PyErr_NoMemory();
806 Py_DECREF(v);
807 return NULL;
808 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000809
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000810 args[0] = '\0';
811 if (sync)
812 strcat(args, "-sync");
813 if (use) {
814 if (sync)
815 strcat(args, " ");
816 strcat(args, "-use ");
817 strcat(args, use);
818 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000819
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000820 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
821 ckfree(args);
822 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000823
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000824 if (Tcl_AppInit(v->interp) != TCL_OK) {
825 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000826#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000827 if (wantTk) {
828 const char *_tkinter_tk_failed;
829 _tkinter_tk_failed = Tcl_GetVar(v->interp,
830 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000831
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000832 if ( _tkinter_tk_failed != NULL &&
833 strcmp(_tkinter_tk_failed, "1") == 0) {
834 tk_load_failed = 1;
835 }
836 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000837#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000838 Py_DECREF((PyObject *)v);
839 return (TkappObject *)result;
840 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000841
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000842 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000843
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000844 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000845}
846
Barry Warsawfa701a81997-01-16 00:15:11 +0000847
Guilherme Polo1972d162009-03-27 21:43:08 +0000848#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000849static void
850Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000851 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000852{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000853 Py_BEGIN_ALLOW_THREADS;
854 Tcl_MutexLock(mutex);
855 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
856 Tcl_ThreadAlert(self->thread_id);
857 Tcl_ConditionWait(cond, mutex, NULL);
858 Tcl_MutexUnlock(mutex);
859 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000860}
Guilherme Polo1972d162009-03-27 21:43:08 +0000861#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000862
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000863
Guido van Rossum18468821994-06-20 07:49:28 +0000864/** Tcl Eval **/
865
Martin v. Löwisffad6332002-11-26 09:28:05 +0000866typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000867 PyObject_HEAD
868 Tcl_Obj *value;
869 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000870} PyTclObject;
871
872staticforward PyTypeObject PyTclObject_Type;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000873#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000874
875static PyObject *
876newPyTclObject(Tcl_Obj *arg)
877{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000878 PyTclObject *self;
879 self = PyObject_New(PyTclObject, &PyTclObject_Type);
880 if (self == NULL)
881 return NULL;
882 Tcl_IncrRefCount(arg);
883 self->value = arg;
884 self->string = NULL;
885 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000886}
887
888static void
889PyTclObject_dealloc(PyTclObject *self)
890{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000891 Tcl_DecrRefCount(self->value);
892 Py_XDECREF(self->string);
893 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000894}
895
896static PyObject *
897PyTclObject_str(PyTclObject *self)
898{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000899 if (self->string && PyString_Check(self->string)) {
900 Py_INCREF(self->string);
901 return self->string;
902 }
903 /* XXX Could cache value if it is an ASCII string. */
904 return PyString_FromString(Tcl_GetString(self->value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000905}
906
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000907static char*
908PyTclObject_TclString(PyObject *self)
909{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000910 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000911}
912
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000913/* Like _str, but create Unicode if necessary. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000914PyDoc_STRVAR(PyTclObject_string__doc__,
Martin v. Löwis39195712003-01-04 00:33:13 +0000915"the string representation of this object, either as string or Unicode");
916
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000917static PyObject *
918PyTclObject_string(PyTclObject *self, void *ignored)
919{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000920 if (!self->string) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200921 int len;
922 char *s = Tcl_GetStringFromObj(self->value, &len);
923 self->string = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000924 if (!self->string)
925 return NULL;
926 }
927 Py_INCREF(self->string);
928 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000929}
930
931#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000932PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
933
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000934static PyObject *
935PyTclObject_unicode(PyTclObject *self, void *ignored)
936{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000937 char *s;
938 int len;
939 if (self->string && PyUnicode_Check(self->string)) {
940 Py_INCREF(self->string);
941 return self->string;
942 }
943 /* XXX Could chache result if it is non-ASCII. */
944 s = Tcl_GetStringFromObj(self->value, &len);
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200945 return unicode_FromTclStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000946}
947#endif
948
Martin v. Löwisffad6332002-11-26 09:28:05 +0000949static PyObject *
950PyTclObject_repr(PyTclObject *self)
951{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000952 char buf[50];
953 PyOS_snprintf(buf, 50, "<%s object at %p>",
954 self->value->typePtr->name, self->value);
955 return PyString_FromString(buf);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000956}
957
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000958static int
959PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
960{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000961 int res;
962 res = strcmp(Tcl_GetString(self->value),
963 Tcl_GetString(other->value));
964 if (res < 0) return -1;
965 if (res > 0) return 1;
966 return 0;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000967}
968
Martin v. Löwis39195712003-01-04 00:33:13 +0000969PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
970
Martin v. Löwisffad6332002-11-26 09:28:05 +0000971static PyObject*
972get_typename(PyTclObject* obj, void* ignored)
973{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000974 return PyString_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000975}
976
Martin v. Löwis39195712003-01-04 00:33:13 +0000977
Martin v. Löwisffad6332002-11-26 09:28:05 +0000978static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000979 {"typename", (getter)get_typename, NULL, get_typename__doc__},
980 {"string", (getter)PyTclObject_string, NULL,
981 PyTclObject_string__doc__},
982 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000983};
984
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000985static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000986#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000987 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
988 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000989#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000990 {0}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000991};
992
Martin v. Löwisffad6332002-11-26 09:28:05 +0000993statichere PyTypeObject PyTclObject_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000994 PyObject_HEAD_INIT(NULL)
995 0, /*ob_size*/
996 "_tkinter.Tcl_Obj", /*tp_name*/
997 sizeof(PyTclObject), /*tp_basicsize*/
998 0, /*tp_itemsize*/
999 /* methods */
1000 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
1001 0, /*tp_print*/
1002 0, /*tp_getattr*/
1003 0, /*tp_setattr*/
1004 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
1005 (reprfunc)PyTclObject_repr, /*tp_repr*/
1006 0, /*tp_as_number*/
1007 0, /*tp_as_sequence*/
1008 0, /*tp_as_mapping*/
1009 0, /*tp_hash*/
1010 0, /*tp_call*/
1011 (reprfunc)PyTclObject_str, /*tp_str*/
1012 PyObject_GenericGetAttr,/*tp_getattro*/
1013 0, /*tp_setattro*/
1014 0, /*tp_as_buffer*/
1015 Py_TPFLAGS_DEFAULT, /*tp_flags*/
1016 0, /*tp_doc*/
1017 0, /*tp_traverse*/
1018 0, /*tp_clear*/
1019 0, /*tp_richcompare*/
1020 0, /*tp_weaklistoffset*/
1021 0, /*tp_iter*/
1022 0, /*tp_iternext*/
1023 PyTclObject_methods, /*tp_methods*/
1024 0, /*tp_members*/
1025 PyTclObject_getsetlist, /*tp_getset*/
1026 0, /*tp_base*/
1027 0, /*tp_dict*/
1028 0, /*tp_descr_get*/
1029 0, /*tp_descr_set*/
1030 0, /*tp_dictoffset*/
1031 0, /*tp_init*/
1032 0, /*tp_alloc*/
1033 0, /*tp_new*/
1034 0, /*tp_free*/
1035 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +00001036};
1037
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001038#if PY_SIZE_MAX > INT_MAX
1039#define CHECK_STRING_LENGTH(s) do { \
1040 if (s != NULL && strlen(s) >= INT_MAX) { \
1041 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
1042 return NULL; \
1043 } } while(0)
1044#else
1045#define CHECK_STRING_LENGTH(s)
1046#endif
1047
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001048#ifdef HAVE_LIBTOMMAMTH
1049static Tcl_Obj*
1050asBignumObj(PyObject *value)
1051{
1052 Tcl_Obj *result;
1053 int neg;
1054 PyObject *hexstr;
1055 char *hexchars;
1056 mp_int bigValue;
1057
1058 neg = Py_SIZE(value) < 0;
1059 hexstr = _PyLong_Format(value, 16, 0, 1);
1060 if (hexstr == NULL)
1061 return NULL;
1062 hexchars = PyString_AsString(hexstr);
1063 if (hexchars == NULL) {
1064 Py_DECREF(hexstr);
1065 return NULL;
1066 }
1067 hexchars += neg + 2; /* skip sign and "0x" */
1068 mp_init(&bigValue);
1069 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
1070 mp_clear(&bigValue);
1071 Py_DECREF(hexstr);
1072 PyErr_NoMemory();
1073 return NULL;
1074 }
1075 Py_DECREF(hexstr);
1076 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
1077 result = Tcl_NewBignumObj(&bigValue);
1078 mp_clear(&bigValue);
1079 if (result == NULL) {
1080 PyErr_NoMemory();
1081 return NULL;
1082 }
1083 return result;
1084}
1085#endif
1086
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001087static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001088AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001089{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001090 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001091
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001092 if (PyString_Check(value))
1093 return Tcl_NewStringObj(PyString_AS_STRING(value),
1094 PyString_GET_SIZE(value));
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001095
1096 if (PyBool_Check(value))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001097 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001098
1099 if (PyInt_Check(value))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001100 return Tcl_NewLongObj(PyInt_AS_LONG(value));
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001101
1102 if (PyLong_CheckExact(value)) {
1103 int overflow;
1104 long longValue;
1105#ifdef TCL_WIDE_INT_TYPE
1106 Tcl_WideInt wideValue;
1107#endif
1108 longValue = PyLong_AsLongAndOverflow(value, &overflow);
1109 if (!overflow) {
1110 return Tcl_NewLongObj(longValue);
1111 }
1112 /* If there is an overflow in the long conversion,
1113 fall through to wideInt handling. */
1114#ifdef TCL_WIDE_INT_TYPE
1115 if (_PyLong_AsByteArray((PyLongObject *)value,
1116 (unsigned char *)(void *)&wideValue,
1117 sizeof(wideValue),
1118#ifdef WORDS_BIGENDIAN
1119 0,
1120#else
1121 1,
1122#endif
1123 /* signed */ 1) == 0) {
1124 return Tcl_NewWideIntObj(wideValue);
1125 }
1126 PyErr_Clear();
1127#endif
1128 /* If there is an overflow in the wideInt conversion,
1129 fall through to bignum handling. */
1130#ifdef HAVE_LIBTOMMAMTH
1131 return asBignumObj(value);
1132#endif
1133 /* If there is no wideInt or bignum support,
1134 fall through to default object handling. */
1135 }
1136
1137 if (PyFloat_Check(value))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001138 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001139
1140 if (PyTuple_Check(value)) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001141 Tcl_Obj **argv;
1142 Py_ssize_t size, i;
1143
1144 size = PyTuple_Size(value);
Serhiy Storchaka17c01782014-09-11 10:56:59 +03001145 if (size == 0)
1146 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001147 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
1148 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1149 return NULL;
1150 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001151 argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001152 if(!argv)
1153 return 0;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001154 for (i = 0; i < size; i++)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001155 argv[i] = AsObj(PyTuple_GetItem(value,i));
1156 result = Tcl_NewListObj(PyTuple_Size(value), argv);
1157 ckfree(FREECAST argv);
1158 return result;
1159 }
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001160
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001161#ifdef Py_USING_UNICODE
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001162 if (PyUnicode_Check(value)) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001163 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
1164 Py_ssize_t size = PyUnicode_GET_SIZE(value);
1165 /* This #ifdef assumes that Tcl uses UCS-2.
1166 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001167#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001168 Tcl_UniChar *outbuf = NULL;
1169 Py_ssize_t i;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001170 size_t allocsize;
Serhiy Storchaka17c01782014-09-11 10:56:59 +03001171 if (size == 0)
1172 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001173 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1174 PyErr_SetString(PyExc_OverflowError, "string is too long");
1175 return NULL;
1176 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001177 if (sizeof(Py_UNICODE) == sizeof(Tcl_UniChar))
1178 return Tcl_NewUnicodeObj(inbuf, size);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001179 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001180 if (allocsize >= size)
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001181 outbuf = (Tcl_UniChar*)attemptckalloc(allocsize);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001182 /* Else overflow occurred, and we take the next exit */
1183 if (!outbuf) {
1184 PyErr_NoMemory();
1185 return NULL;
1186 }
1187 for (i = 0; i < size; i++) {
1188 if (inbuf[i] >= 0x10000) {
1189 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka46764482013-02-18 13:00:08 +02001190 PyErr_Format(Tkinter_TclError,
1191 "character U+%x is above the range "
1192 "(U+0000-U+FFFF) allowed by Tcl",
1193 (int)inbuf[i]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001194 ckfree(FREECAST outbuf);
1195 return NULL;
1196 }
1197 outbuf[i] = inbuf[i];
1198 }
1199 result = Tcl_NewUnicodeObj(outbuf, size);
1200 ckfree(FREECAST outbuf);
1201 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001202#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001203 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001204#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001205 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001206#endif
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001207
1208 if(PyTclObject_Check(value)) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001209 Tcl_Obj *v = ((PyTclObject*)value)->value;
1210 Tcl_IncrRefCount(v);
1211 return v;
1212 }
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001213
1214 {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001215 PyObject *v = PyObject_Str(value);
1216 if (!v)
1217 return 0;
1218 result = AsObj(v);
1219 Py_DECREF(v);
1220 return result;
1221 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001222}
1223
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001224static PyObject *
1225fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1226{
1227 int boolValue;
1228 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1229 return Tkinter_Error(tkapp);
1230 return PyBool_FromLong(boolValue);
1231}
1232
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001233#ifdef TCL_WIDE_INT_TYPE
1234static PyObject*
1235fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1236{
1237 Tcl_WideInt wideValue;
1238 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
1239#ifdef HAVE_LONG_LONG
1240 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1241 return PyLong_FromLongLong(wideValue);
1242#endif
1243 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1244 sizeof(wideValue),
1245#ifdef WORDS_BIGENDIAN
1246 0,
1247#else
1248 1,
1249#endif
1250 /* signed */ 1);
1251 }
1252 return NULL;
1253}
1254#endif
1255
1256#ifdef HAVE_LIBTOMMAMTH
1257static PyObject*
1258fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1259{
1260 mp_int bigValue;
1261 unsigned long numBytes;
1262 unsigned char *bytes;
1263 PyObject *res;
1264
1265 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1266 return Tkinter_Error(tkapp);
1267 numBytes = mp_unsigned_bin_size(&bigValue);
1268 bytes = PyMem_Malloc(numBytes);
1269 if (bytes == NULL) {
1270 mp_clear(&bigValue);
1271 return PyErr_NoMemory();
1272 }
1273 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1274 &numBytes) != MP_OKAY) {
1275 mp_clear(&bigValue);
1276 PyMem_Free(bytes);
1277 return PyErr_NoMemory();
1278 }
1279 res = _PyLong_FromByteArray(bytes, numBytes,
1280 /* big-endian */ 0,
1281 /* unsigned */ 0);
1282 PyMem_Free(bytes);
1283 if (res != NULL && bigValue.sign == MP_NEG) {
1284 PyObject *res2 = PyNumber_Negative(res);
1285 Py_DECREF(res);
1286 res = res2;
1287 }
1288 mp_clear(&bigValue);
1289 return res;
1290}
1291#endif
1292
Martin v. Löwisffad6332002-11-26 09:28:05 +00001293static PyObject*
1294FromObj(PyObject* tkapp, Tcl_Obj *value)
1295{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001296 PyObject *result = NULL;
1297 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001298 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001299
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001300 if (value->typePtr == NULL) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001301 result = fromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001302 return result;
1303 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001304
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001305 if (value->typePtr == app->BooleanType ||
1306 value->typePtr == app->OldBooleanType) {
1307 return fromBoolean(tkapp, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001308 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001309
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001310 if (value->typePtr == app->ByteArrayType) {
1311 int size;
1312 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1313 return PyString_FromStringAndSize(data, size);
1314 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001315
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001316 if (value->typePtr == app->DoubleType) {
1317 return PyFloat_FromDouble(value->internalRep.doubleValue);
1318 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001319
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001320 if (value->typePtr == app->IntType) {
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001321 long longValue;
1322 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1323 return PyInt_FromLong(longValue);
1324 /* If there is an error in the long conversion,
1325 fall through to wideInt handling. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001326 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001327
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001328#ifdef TCL_WIDE_INT_TYPE
1329 if (value->typePtr == app->IntType ||
1330 value->typePtr == app->WideIntType) {
1331 result = fromWideIntObj(tkapp, value);
1332 if (result != NULL || PyErr_Occurred())
1333 return result;
1334 Tcl_ResetResult(interp);
1335 /* If there is an error in the wideInt conversion,
1336 fall through to bignum handling. */
1337 }
1338#endif
1339
1340#ifdef HAVE_LIBTOMMAMTH
1341 if (value->typePtr == app->IntType ||
1342 value->typePtr == app->WideIntType ||
1343 value->typePtr == app->BignumType) {
1344 return fromBignumObj(tkapp, value);
1345 }
1346#endif
1347
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001348 if (value->typePtr == app->ListType) {
1349 int size;
1350 int i, status;
1351 PyObject *elem;
1352 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001353
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001354 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001355 if (status == TCL_ERROR)
1356 return Tkinter_Error(tkapp);
1357 result = PyTuple_New(size);
1358 if (!result)
1359 return NULL;
1360 for (i = 0; i < size; i++) {
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001361 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001362 if (status == TCL_ERROR) {
1363 Py_DECREF(result);
1364 return Tkinter_Error(tkapp);
1365 }
1366 elem = FromObj(tkapp, tcl_elem);
1367 if (!elem) {
1368 Py_DECREF(result);
1369 return NULL;
1370 }
1371 PyTuple_SetItem(result, i, elem);
1372 }
1373 return result;
1374 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001375
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001376 if (value->typePtr == app->ProcBodyType) {
1377 /* fall through: return tcl object. */
1378 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001379
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001380 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001381#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001382#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001383 PyObject *result;
1384 int size;
1385 Tcl_UniChar *input;
1386 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001387
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001388 size = Tcl_GetCharLength(value);
1389 result = PyUnicode_FromUnicode(NULL, size);
1390 if (!result)
1391 return NULL;
1392 input = Tcl_GetUnicode(value);
1393 output = PyUnicode_AS_UNICODE(result);
1394 while (size--)
1395 *output++ = *input++;
1396 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001397#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001398 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1399 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001400#endif
1401#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001402 int size;
1403 char *c;
1404 c = Tcl_GetStringFromObj(value, &size);
1405 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001406#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001407 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001408
Serhiy Storchaka656ffdb2015-04-21 21:17:33 +03001409#if TK_HEX_VERSION >= 0x08050000
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001410 if (app->BooleanType == NULL &&
1411 strcmp(value->typePtr->name, "booleanString") == 0) {
1412 /* booleanString type is not registered in Tcl */
1413 app->BooleanType = value->typePtr;
1414 return fromBoolean(tkapp, value);
1415 }
1416#endif
1417
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001418#ifdef HAVE_LIBTOMMAMTH
1419 if (app->BignumType == NULL &&
1420 strcmp(value->typePtr->name, "bignum") == 0) {
1421 /* bignum type is not registered in Tcl */
1422 app->BignumType = value->typePtr;
1423 return fromBignumObj(tkapp, value);
1424 }
1425#endif
1426
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001427 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001428}
1429
Guilherme Polo1972d162009-03-27 21:43:08 +00001430#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001431/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001432TCL_DECLARE_MUTEX(call_mutex)
1433
1434typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001435 Tcl_Event ev; /* Must be first */
1436 TkappObject *self;
1437 PyObject *args;
1438 int flags;
1439 PyObject **res;
1440 PyObject **exc_type, **exc_value, **exc_tb;
1441 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001442} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001443#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001444
1445void
1446Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001447{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001448 int i;
1449 for (i = 0; i < objc; i++)
1450 Tcl_DecrRefCount(objv[i]);
1451 if (objv != objStore)
1452 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001453}
Guido van Rossum18468821994-06-20 07:49:28 +00001454
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001455/* Convert Python objects to Tcl objects. This must happen in the
1456 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001457
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001458static Tcl_Obj**
1459Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1460{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001461 Tcl_Obj **objv = objStore;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001462 Py_ssize_t objc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001463 if (args == NULL)
1464 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001465
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001466 else if (!PyTuple_Check(args)) {
1467 objv[0] = AsObj(args);
1468 if (objv[0] == 0)
1469 goto finally;
1470 objc = 1;
1471 Tcl_IncrRefCount(objv[0]);
1472 }
1473 else {
1474 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001475
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001476 if (objc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001477 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1478 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1479 return NULL;
1480 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001481 objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001482 if (objv == NULL) {
1483 PyErr_NoMemory();
1484 objc = 0;
1485 goto finally;
1486 }
1487 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001488
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001489 for (i = 0; i < objc; i++) {
1490 PyObject *v = PyTuple_GetItem(args, i);
1491 if (v == Py_None) {
1492 objc = i;
1493 break;
1494 }
1495 objv[i] = AsObj(v);
1496 if (!objv[i]) {
1497 /* Reset objc, so it attempts to clear
1498 objects only up to i. */
1499 objc = i;
1500 goto finally;
1501 }
1502 Tcl_IncrRefCount(objv[i]);
1503 }
1504 }
1505 *pobjc = objc;
1506 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001507finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001508 Tkapp_CallDeallocArgs(objv, objStore, objc);
1509 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001510}
Guido van Rossum212643f1998-04-29 16:22:14 +00001511
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001512/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001513
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001514static PyObject*
1515Tkapp_CallResult(TkappObject *self)
1516{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001517 PyObject *res = NULL;
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001518 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001519 if(self->wantobjects) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001520 /* Not sure whether the IncrRef is necessary, but something
1521 may overwrite the interpreter result while we are
1522 converting it. */
1523 Tcl_IncrRefCount(value);
1524 res = FromObj((PyObject*)self, value);
1525 Tcl_DecrRefCount(value);
1526 } else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001527 int len;
1528 const char *s = Tcl_GetStringFromObj(value, &len);
1529 res = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001530 }
1531 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001532}
Guido van Rossum632de272000-03-29 00:19:50 +00001533
Guilherme Polo1972d162009-03-27 21:43:08 +00001534#ifdef WITH_THREAD
1535
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001536/* Tkapp_CallProc is the event procedure that is executed in the context of
1537 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1538 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001539
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001540static int
1541Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1542{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001543 Tcl_Obj *objStore[ARGSZ];
1544 Tcl_Obj **objv;
1545 int objc;
1546 int i;
1547 ENTER_PYTHON
1548 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1549 if (!objv) {
1550 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1551 *(e->res) = NULL;
1552 }
1553 LEAVE_PYTHON
1554 if (!objv)
1555 goto done;
1556 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1557 ENTER_PYTHON
1558 if (i == TCL_ERROR) {
1559 *(e->res) = NULL;
1560 *(e->exc_type) = NULL;
1561 *(e->exc_tb) = NULL;
1562 *(e->exc_value) = PyObject_CallFunction(
1563 Tkinter_TclError, "s",
1564 Tcl_GetStringResult(e->self->interp));
1565 }
1566 else {
1567 *(e->res) = Tkapp_CallResult(e->self);
1568 }
1569 LEAVE_PYTHON
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001570
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001571 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001572done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001573 /* Wake up calling thread. */
1574 Tcl_MutexLock(&call_mutex);
1575 Tcl_ConditionNotify(e->done);
1576 Tcl_MutexUnlock(&call_mutex);
1577 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001578}
1579
Guilherme Polo1972d162009-03-27 21:43:08 +00001580#endif
1581
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001582/* This is the main entry point for calling a Tcl command.
1583 It supports three cases, with regard to threading:
1584 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1585 the context of the calling thread.
1586 2. Tcl is threaded, caller of the command is in the interpreter thread:
1587 Execute the command in the calling thread. Since the Tcl lock will
1588 not be used, we can merge that with case 1.
1589 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1590 the interpreter thread. Allocation of Tcl objects needs to occur in the
1591 interpreter thread, so we ship the PyObject* args to the target thread,
1592 and perform processing there. */
1593
1594static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001595Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001596{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001597 Tcl_Obj *objStore[ARGSZ];
1598 Tcl_Obj **objv = NULL;
1599 int objc, i;
1600 PyObject *res = NULL;
1601 TkappObject *self = (TkappObject*)selfptr;
1602 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001603
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001604 /* If args is a single tuple, replace with contents of tuple */
1605 if (1 == PyTuple_Size(args)){
1606 PyObject* item = PyTuple_GetItem(args, 0);
1607 if (PyTuple_Check(item))
1608 args = item;
1609 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001610#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001611 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1612 /* We cannot call the command directly. Instead, we must
1613 marshal the parameters to the interpreter thread. */
1614 Tkapp_CallEvent *ev;
1615 Tcl_Condition cond = NULL;
1616 PyObject *exc_type, *exc_value, *exc_tb;
1617 if (!WaitForMainloop(self))
1618 return NULL;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001619 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1620 if (ev == NULL) {
1621 PyErr_NoMemory();
1622 return NULL;
1623 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001624 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1625 ev->self = self;
1626 ev->args = args;
1627 ev->res = &res;
1628 ev->exc_type = &exc_type;
1629 ev->exc_value = &exc_value;
1630 ev->exc_tb = &exc_tb;
1631 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001632
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001633 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001634
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001635 if (res == NULL) {
1636 if (exc_type)
1637 PyErr_Restore(exc_type, exc_value, exc_tb);
1638 else
1639 PyErr_SetObject(Tkinter_TclError, exc_value);
1640 }
1641 Tcl_ConditionFinalize(&cond);
1642 }
1643 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001644#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001645 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001646
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001647 objv = Tkapp_CallArgs(args, objStore, &objc);
1648 if (!objv)
1649 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001650
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001651 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001652
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001653 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001654
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001655 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001656
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001657 if (i == TCL_ERROR)
1658 Tkinter_Error(selfptr);
1659 else
1660 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001661
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001662 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001663
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001664 Tkapp_CallDeallocArgs(objv, objStore, objc);
1665 }
1666 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001667}
1668
1669
1670static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001671Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001672{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001673 /* Could do the same here as for Tkapp_Call(), but this is not used
1674 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1675 way for the user to do what all its Global* variants do (save and
1676 reset the scope pointer, call the local version, restore the saved
1677 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001678
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001679 char *cmd;
1680 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001681
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001682 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001683
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001684 cmd = Merge(args);
1685 if (cmd) {
1686 int err;
1687 ENTER_TCL
1688 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1689 ENTER_OVERLAP
1690 if (err == TCL_ERROR)
1691 res = Tkinter_Error(self);
1692 else
1693 res = PyString_FromString(Tkapp_Result(self));
1694 LEAVE_OVERLAP_TCL
1695 ckfree(cmd);
1696 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001697
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001698 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001699}
1700
1701static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001702Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001703{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001704 char *script;
1705 PyObject *res = NULL;
1706 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001707
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001708 if (!PyArg_ParseTuple(args, "s:eval", &script))
1709 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001710
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001711 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001712 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001713
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001714 ENTER_TCL
1715 err = Tcl_Eval(Tkapp_Interp(self), script);
1716 ENTER_OVERLAP
1717 if (err == TCL_ERROR)
1718 res = Tkinter_Error(self);
1719 else
1720 res = PyString_FromString(Tkapp_Result(self));
1721 LEAVE_OVERLAP_TCL
1722 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001723}
1724
1725static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001726Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001727{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001728 char *script;
1729 PyObject *res = NULL;
1730 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001731
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001732 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1733 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001734
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001735 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001736
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001737 ENTER_TCL
1738 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1739 ENTER_OVERLAP
1740 if (err == TCL_ERROR)
1741 res = Tkinter_Error(self);
1742 else
1743 res = PyString_FromString(Tkapp_Result(self));
1744 LEAVE_OVERLAP_TCL
1745 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001746}
1747
1748static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001749Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001750{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001751 char *fileName;
1752 PyObject *res = NULL;
1753 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001754
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001755 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1756 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001757
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001758 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001759 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001760
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001761 ENTER_TCL
1762 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1763 ENTER_OVERLAP
1764 if (err == TCL_ERROR)
1765 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001766
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001767 else
1768 res = PyString_FromString(Tkapp_Result(self));
1769 LEAVE_OVERLAP_TCL
1770 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001771}
1772
1773static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001774Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001775{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001776 char *script;
1777 PyObject *res = NULL;
1778 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001779
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001780 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001781 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001782
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001783 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001784 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001785
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001786 ENTER_TCL
1787 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1788 ENTER_OVERLAP
1789 if (err == TCL_ERROR)
1790 res = Tkinter_Error(self);
1791 else
1792 res = PyString_FromString(Tkapp_Result(self));
1793 LEAVE_OVERLAP_TCL
1794 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001795}
1796
1797static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001798Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001799{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001800 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001801
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001802 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1803 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001804 CHECK_STRING_LENGTH(msg);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001805 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001806
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001807 ENTER_TCL
1808 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1809 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001810
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001811 Py_INCREF(Py_None);
1812 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001813}
1814
Barry Warsawfa701a81997-01-16 00:15:11 +00001815
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001816
Guido van Rossum18468821994-06-20 07:49:28 +00001817/** Tcl Variable **/
1818
Guilherme Polo1972d162009-03-27 21:43:08 +00001819typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1820
1821#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001822TCL_DECLARE_MUTEX(var_mutex)
1823
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001824typedef struct VarEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001825 Tcl_Event ev; /* must be first */
1826 PyObject *self;
1827 PyObject *args;
1828 int flags;
1829 EventFunc func;
1830 PyObject **res;
1831 PyObject **exc_type;
1832 PyObject **exc_val;
1833 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001834} VarEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001835#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001836
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001837static int
1838varname_converter(PyObject *in, void *_out)
1839{
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001840 char *s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001841 char **out = (char**)_out;
1842 if (PyString_Check(in)) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001843 if (PyString_Size(in) > INT_MAX) {
1844 PyErr_SetString(PyExc_OverflowError, "string is too long");
1845 return 0;
1846 }
1847 s = PyString_AsString(in);
1848 if (strlen(s) != PyString_Size(in)) {
1849 PyErr_SetString(PyExc_ValueError, "null character in string");
1850 return 0;
1851 }
1852 *out = s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001853 return 1;
1854 }
1855 if (PyTclObject_Check(in)) {
1856 *out = PyTclObject_TclString(in);
1857 return 1;
1858 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001859 PyErr_Format(PyExc_TypeError,
1860 "must be str or Tcl_Obj, not %.50s",
1861 in->ob_type->tp_name);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001862 return 0;
1863}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001864
Guilherme Polo1972d162009-03-27 21:43:08 +00001865#ifdef WITH_THREAD
1866
Martin v. Löwis111c1802008-06-13 07:47:47 +00001867static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001868var_perform(VarEvent *ev)
1869{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001870 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1871 if (!*(ev->res)) {
1872 PyObject *exc, *val, *tb;
1873 PyErr_Fetch(&exc, &val, &tb);
1874 PyErr_NormalizeException(&exc, &val, &tb);
1875 *(ev->exc_type) = exc;
1876 *(ev->exc_val) = val;
Serhiy Storchaka4089b502016-10-28 12:14:34 +03001877 Py_XDECREF(tb);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001878 }
1879
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001880}
1881
1882static int
1883var_proc(VarEvent* ev, int flags)
1884{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001885 ENTER_PYTHON
1886 var_perform(ev);
1887 Tcl_MutexLock(&var_mutex);
1888 Tcl_ConditionNotify(ev->cond);
1889 Tcl_MutexUnlock(&var_mutex);
1890 LEAVE_PYTHON
1891 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001892}
1893
Guilherme Polo1972d162009-03-27 21:43:08 +00001894#endif
1895
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001896static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001897var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001898{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001899#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001900 TkappObject *self = (TkappObject*)selfptr;
1901 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1902 TkappObject *self = (TkappObject*)selfptr;
1903 VarEvent *ev;
1904 PyObject *res, *exc_type, *exc_val;
1905 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001906
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001907 /* The current thread is not the interpreter thread. Marshal
1908 the call to the interpreter thread, then wait for
1909 completion. */
1910 if (!WaitForMainloop(self))
1911 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001912
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001913 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1914 if (ev == NULL) {
1915 PyErr_NoMemory();
1916 return NULL;
1917 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001918 ev->self = selfptr;
1919 ev->args = args;
1920 ev->flags = flags;
1921 ev->func = func;
1922 ev->res = &res;
1923 ev->exc_type = &exc_type;
1924 ev->exc_val = &exc_val;
1925 ev->cond = &cond;
1926 ev->ev.proc = (Tcl_EventProc*)var_proc;
1927 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1928 Tcl_ConditionFinalize(&cond);
1929 if (!res) {
1930 PyErr_SetObject(exc_type, exc_val);
1931 Py_DECREF(exc_type);
1932 Py_DECREF(exc_val);
1933 return NULL;
1934 }
1935 return res;
1936 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001937#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001938 /* Tcl is not threaded, or this is the interpreter thread. */
1939 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001940}
1941
Guido van Rossum18468821994-06-20 07:49:28 +00001942static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001943SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001944{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001945 char *name1, *name2;
1946 PyObject *newValue;
1947 PyObject *res = NULL;
1948 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001949
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001950 switch (PyTuple_GET_SIZE(args)) {
1951 case 2:
1952 if (!PyArg_ParseTuple(args, "O&O:setvar",
1953 varname_converter, &name1, &newValue))
1954 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001955 /* XXX Acquire tcl lock??? */
1956 newval = AsObj(newValue);
1957 if (newval == NULL)
1958 return NULL;
1959 ENTER_TCL
1960 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1961 newval, flags);
1962 ENTER_OVERLAP
1963 if (!ok)
1964 Tkinter_Error(self);
1965 else {
1966 res = Py_None;
1967 Py_INCREF(res);
1968 }
1969 LEAVE_OVERLAP_TCL
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001970 break;
1971 case 3:
1972 if (!PyArg_ParseTuple(args, "ssO:setvar",
1973 &name1, &name2, &newValue))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001974 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001975 CHECK_STRING_LENGTH(name1);
1976 CHECK_STRING_LENGTH(name2);
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001977 /* XXX must hold tcl lock already??? */
1978 newval = AsObj(newValue);
1979 ENTER_TCL
1980 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1981 ENTER_OVERLAP
1982 if (!ok)
1983 Tkinter_Error(self);
1984 else {
1985 res = Py_None;
1986 Py_INCREF(res);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001987 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001988 LEAVE_OVERLAP_TCL
1989 break;
1990 default:
1991 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1992 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001993 }
1994 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001995}
1996
1997static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001998Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001999{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002000 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00002001}
2002
2003static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002004Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002005{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002006 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00002007}
2008
Barry Warsawfa701a81997-01-16 00:15:11 +00002009
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002010
Guido van Rossum18468821994-06-20 07:49:28 +00002011static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002012GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002013{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002014 char *name1, *name2=NULL;
2015 PyObject *res = NULL;
2016 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00002017
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002018 if (!PyArg_ParseTuple(args, "O&|s:getvar",
2019 varname_converter, &name1, &name2))
2020 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002021
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002022 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002023 ENTER_TCL
2024 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
2025 ENTER_OVERLAP
2026 if (tres == NULL) {
2027 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2028 } else {
2029 if (((TkappObject*)self)->wantobjects) {
2030 res = FromObj(self, tres);
2031 }
2032 else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002033 int len;
2034 char *s = Tcl_GetStringFromObj(tres, &len);
2035 res = PyString_FromStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002036 }
2037 }
2038 LEAVE_OVERLAP_TCL
2039 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002040}
2041
2042static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002043Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002044{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002045 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00002046}
2047
2048static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002049Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002050{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002051 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00002052}
2053
Barry Warsawfa701a81997-01-16 00:15:11 +00002054
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002055
Guido van Rossum18468821994-06-20 07:49:28 +00002056static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002057UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002058{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002059 char *name1, *name2=NULL;
2060 int code;
2061 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002062
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002063 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
2064 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00002065
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002066 CHECK_STRING_LENGTH(name1);
2067 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002068 ENTER_TCL
2069 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
2070 ENTER_OVERLAP
2071 if (code == TCL_ERROR)
2072 res = Tkinter_Error(self);
2073 else {
2074 Py_INCREF(Py_None);
2075 res = Py_None;
2076 }
2077 LEAVE_OVERLAP_TCL
2078 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002079}
2080
2081static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002082Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002083{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002084 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00002085}
2086
2087static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002088Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002089{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002090 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00002091}
2092
Barry Warsawfa701a81997-01-16 00:15:11 +00002093
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002094
Guido van Rossum18468821994-06-20 07:49:28 +00002095/** Tcl to Python **/
2096
2097static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002098Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002099{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002100 char *s;
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03002101#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH)
2102 Tcl_Obj *value;
2103 PyObject *result;
2104#else
2105 int intValue;
2106#endif
Guido van Rossum18468821994-06-20 07:49:28 +00002107
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002108 if (PyTuple_Size(args) == 1) {
2109 PyObject* o = PyTuple_GetItem(args, 0);
Serhiy Storchaka48c8bf22018-07-31 09:09:36 +03002110 if (_PyAnyInt_Check(o)) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002111 Py_INCREF(o);
2112 return o;
2113 }
2114 }
2115 if (!PyArg_ParseTuple(args, "s:getint", &s))
2116 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03002117 CHECK_STRING_LENGTH(s);
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03002118#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH)
2119 value = Tcl_NewStringObj(s, -1);
2120 if (value == NULL)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002121 return Tkinter_Error(self);
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03002122 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
2123 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
2124
2125 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
2126 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
2127 */
2128#ifdef HAVE_LIBTOMMAMTH
2129 result = fromBignumObj(self, value);
2130#else
2131 result = fromWideIntObj(self, value);
2132#endif
2133 Tcl_DecrRefCount(value);
Victor Stinnerbdd35672017-06-13 11:12:01 +02002134 if (result != NULL) {
2135 PyObject *resint = PyNumber_Int(result);
2136 Py_DECREF(result);
2137 return resint;
2138 }
2139
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03002140 if (PyErr_Occurred())
2141 return NULL;
2142#else
2143 if (Tcl_GetInt(Tkapp_Interp(self), s, &intValue) == TCL_OK)
2144 return PyInt_FromLong(intValue);
2145#endif
2146 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00002147}
2148
2149static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002150Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002151{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002152 char *s;
2153 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00002154
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002155 if (PyTuple_Size(args) == 1) {
2156 PyObject *o = PyTuple_GetItem(args, 0);
2157 if (PyFloat_Check(o)) {
2158 Py_INCREF(o);
2159 return o;
2160 }
2161 }
2162 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
2163 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03002164 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002165 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
2166 return Tkinter_Error(self);
2167 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00002168}
2169
2170static PyObject *
Serhiy Storchakaf29bc702015-04-04 12:42:25 +03002171Tkapp_GetBoolean(PyObject *self, PyObject *arg)
Guido van Rossum18468821994-06-20 07:49:28 +00002172{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002173 char *s;
2174 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002175
Serhiy Storchakaf29bc702015-04-04 12:42:25 +03002176 if (PyInt_Check(arg)) /* int or bool */
2177 return PyBool_FromLong(PyInt_AS_LONG(arg));
2178
2179 if (PyLong_Check(arg))
2180 return PyBool_FromLong(Py_SIZE(arg) != 0);
2181
2182 if (PyTclObject_Check(arg)) {
2183 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2184 ((PyTclObject*)arg)->value,
2185 &v) == TCL_ERROR)
2186 return Tkinter_Error(self);
2187 return PyBool_FromLong(v);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002188 }
Serhiy Storchakaf29bc702015-04-04 12:42:25 +03002189
2190 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002191 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03002192 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002193 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
2194 return Tkinter_Error(self);
2195 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002196}
2197
2198static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002199Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002200{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002201 char *s;
2202 PyObject *res = NULL;
2203 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002204
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002205 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
2206 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002207
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002208 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002209 CHECK_TCL_APPARTMENT;
2210
2211 ENTER_TCL
2212 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2213 ENTER_OVERLAP
2214 if (retval == TCL_ERROR)
2215 res = Tkinter_Error(self);
2216 else
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002217 res = PyString_FromString(Tkapp_Result(self));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002218 LEAVE_OVERLAP_TCL
2219 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002220}
2221
2222static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002223Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002224{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002225 char *s;
2226 PyObject *res = NULL;
2227 int retval;
2228 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002229
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002230 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
2231 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002232
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002233 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002234 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002235
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002236 ENTER_TCL
2237 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2238 ENTER_OVERLAP
2239 if (retval == TCL_ERROR)
2240 res = Tkinter_Error(self);
2241 else
2242 res = Py_BuildValue("l", v);
2243 LEAVE_OVERLAP_TCL
2244 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002245}
2246
2247static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002248Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002249{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002250 char *s;
2251 PyObject *res = NULL;
2252 double v;
2253 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002254
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002255 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2256 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002257 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002258 CHECK_TCL_APPARTMENT;
2259 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2260 ENTER_TCL
2261 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2262 ENTER_OVERLAP
2263 PyFPE_END_PROTECT(retval)
2264 if (retval == TCL_ERROR)
2265 res = Tkinter_Error(self);
2266 else
2267 res = Py_BuildValue("d", v);
2268 LEAVE_OVERLAP_TCL
2269 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002270}
2271
2272static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002273Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002274{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002275 char *s;
2276 PyObject *res = NULL;
2277 int retval;
2278 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002279
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002280 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2281 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002282 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002283 CHECK_TCL_APPARTMENT;
2284 ENTER_TCL
2285 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2286 ENTER_OVERLAP
2287 if (retval == TCL_ERROR)
2288 res = Tkinter_Error(self);
2289 else
2290 res = Py_BuildValue("i", v);
2291 LEAVE_OVERLAP_TCL
2292 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002293}
2294
Barry Warsawfa701a81997-01-16 00:15:11 +00002295
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002296
Guido van Rossum18468821994-06-20 07:49:28 +00002297static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002298Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002299{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002300 char *list;
2301 int argc;
2302 char **argv;
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002303 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002304 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002305
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002306 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2307 return NULL;
2308 if (PyTclObject_Check(arg)) {
2309 int objc;
2310 Tcl_Obj **objv;
2311 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2312 ((PyTclObject*)arg)->value,
2313 &objc, &objv) == TCL_ERROR) {
2314 return Tkinter_Error(self);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002315 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002316 if (!(v = PyTuple_New(objc)))
2317 return NULL;
2318 for (i = 0; i < objc; i++) {
2319 PyObject *s = FromObj(self, objv[i]);
2320 if (!s || PyTuple_SetItem(v, i, s)) {
2321 Py_DECREF(v);
2322 return NULL;
2323 }
2324 }
2325 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002326 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002327 if (PyTuple_Check(arg)) {
2328 Py_INCREF(arg);
2329 return arg;
2330 }
2331
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002332 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2333 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002334
Serhiy Storchaka328b5d02017-10-04 21:37:53 +03002335 if (strlen(list) >= INT_MAX) {
2336 PyErr_SetString(PyExc_OverflowError, "string is too long");
2337 PyMem_Free(list);
2338 return NULL;
2339 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002340 if (Tcl_SplitList(Tkapp_Interp(self), list,
2341 &argc, &argv) == TCL_ERROR) {
2342 PyMem_Free(list);
2343 return Tkinter_Error(self);
2344 }
Guido van Rossum18468821994-06-20 07:49:28 +00002345
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002346 if (!(v = PyTuple_New(argc)))
2347 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002348
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002349 for (i = 0; i < argc; i++) {
2350 PyObject *s = PyString_FromString(argv[i]);
2351 if (!s || PyTuple_SetItem(v, i, s)) {
2352 Py_DECREF(v);
2353 v = NULL;
2354 goto finally;
2355 }
2356 }
Guido van Rossum18468821994-06-20 07:49:28 +00002357
Barry Warsawfa701a81997-01-16 00:15:11 +00002358 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002359 ckfree(FREECAST argv);
2360 PyMem_Free(list);
2361 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002362}
2363
2364static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002365Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002366{
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002367 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002368 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002369
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002370 if (!PyArg_ParseTuple(args, "O:split", &arg))
2371 return NULL;
2372 if (PyTclObject_Check(arg)) {
2373 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2374 int objc;
2375 Tcl_Obj **objv;
2376 int i;
2377 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2378 &objc, &objv) == TCL_ERROR) {
2379 return FromObj(self, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002380 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002381 if (objc == 0)
2382 return PyString_FromString("");
2383 if (objc == 1)
2384 return FromObj(self, objv[0]);
2385 if (!(v = PyTuple_New(objc)))
2386 return NULL;
2387 for (i = 0; i < objc; i++) {
2388 PyObject *s = FromObj(self, objv[i]);
2389 if (!s || PyTuple_SetItem(v, i, s)) {
2390 Py_DECREF(v);
2391 return NULL;
2392 }
2393 }
2394 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002395 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002396 if (PyTuple_Check(arg))
2397 return SplitObj(arg);
2398
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002399 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2400 return NULL;
Serhiy Storchaka328b5d02017-10-04 21:37:53 +03002401 if (strlen(list) >= INT_MAX) {
2402 PyErr_SetString(PyExc_OverflowError, "string is too long");
2403 PyMem_Free(list);
2404 return NULL;
2405 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002406 v = Split(list);
2407 PyMem_Free(list);
2408 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002409}
2410
2411static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002412Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002413{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002414 char *s = Merge(args);
2415 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002416
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002417 if (s) {
2418 res = PyString_FromString(s);
2419 ckfree(s);
2420 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002421
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002422 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002423}
2424
Barry Warsawfa701a81997-01-16 00:15:11 +00002425
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002426
Guido van Rossum18468821994-06-20 07:49:28 +00002427/** Tcl Command **/
2428
Guido van Rossum00d93061998-05-28 23:06:38 +00002429/* Client data struct */
2430typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002431 PyObject *self;
2432 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002433} PythonCmd_ClientData;
2434
2435static int
Fred Drake509d79a2000-07-08 04:04:38 +00002436PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002437{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002438 errorInCmd = 1;
2439 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2440 LEAVE_PYTHON
2441 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002442}
2443
Guido van Rossum18468821994-06-20 07:49:28 +00002444/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002445 * function or method.
2446 */
Guido van Rossum18468821994-06-20 07:49:28 +00002447static int
Fred Drake509d79a2000-07-08 04:04:38 +00002448PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002449{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002450 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2451 PyObject *func, *arg, *res;
2452 int i, rv;
2453 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002454
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002455 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002456
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002457 /* TBD: no error checking here since we know, via the
2458 * Tkapp_CreateCommand() that the client data is a two-tuple
2459 */
2460 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002461
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002462 /* Create argument list (argv1, ..., argvN) */
2463 if (!(arg = PyTuple_New(argc - 1)))
2464 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002465
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002466 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002467 PyObject *s = fromTclString(argv[i + 1]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002468 if (!s || PyTuple_SetItem(arg, i, s)) {
2469 Py_DECREF(arg);
2470 return PythonCmd_Error(interp);
2471 }
2472 }
2473 res = PyEval_CallObject(func, arg);
2474 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002475
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002476 if (res == NULL)
2477 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002478
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002479 obj_res = AsObj(res);
2480 if (obj_res == NULL) {
2481 Py_DECREF(res);
2482 return PythonCmd_Error(interp);
2483 }
2484 else {
2485 Tcl_SetObjResult(interp, obj_res);
2486 rv = TCL_OK;
2487 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002488
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002489 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002490
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002491 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002492
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002493 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002494}
2495
2496static void
Fred Drake509d79a2000-07-08 04:04:38 +00002497PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002498{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002499 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002500
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002501 ENTER_PYTHON
2502 Py_XDECREF(data->self);
2503 Py_XDECREF(data->func);
2504 PyMem_DEL(data);
2505 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002506}
2507
Barry Warsawfa701a81997-01-16 00:15:11 +00002508
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002509
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002510
Guilherme Polo1972d162009-03-27 21:43:08 +00002511#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002512TCL_DECLARE_MUTEX(command_mutex)
2513
2514typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002515 Tcl_Event ev;
2516 Tcl_Interp* interp;
2517 char *name;
2518 int create;
2519 int *status;
2520 ClientData *data;
2521 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002522} CommandEvent;
2523
2524static int
2525Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002526{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002527 if (ev->create)
2528 *ev->status = Tcl_CreateCommand(
2529 ev->interp, ev->name, PythonCmd,
2530 ev->data, PythonCmdDelete) == NULL;
2531 else
2532 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2533 Tcl_MutexLock(&command_mutex);
2534 Tcl_ConditionNotify(ev->done);
2535 Tcl_MutexUnlock(&command_mutex);
2536 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002537}
Guilherme Polo1972d162009-03-27 21:43:08 +00002538#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002539
2540static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002541Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002542{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002543 TkappObject *self = (TkappObject*)selfptr;
2544 PythonCmd_ClientData *data;
2545 char *cmdName;
2546 PyObject *func;
2547 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002548
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002549 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2550 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002551 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002552 if (!PyCallable_Check(func)) {
2553 PyErr_SetString(PyExc_TypeError, "command not callable");
2554 return NULL;
2555 }
Guido van Rossum18468821994-06-20 07:49:28 +00002556
Martin v. Löwisa9656492003-03-30 08:44:58 +00002557#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002558 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2559 !WaitForMainloop(self))
2560 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002561#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002562
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002563 data = PyMem_NEW(PythonCmd_ClientData, 1);
2564 if (!data)
2565 return PyErr_NoMemory();
2566 Py_INCREF(self);
2567 Py_INCREF(func);
2568 data->self = selfptr;
2569 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002570
2571#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002572 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2573 Tcl_Condition cond = NULL;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03002574 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2575 if (ev == NULL) {
2576 PyErr_NoMemory();
2577 PyMem_DEL(data);
2578 return NULL;
2579 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002580 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2581 ev->interp = self->interp;
2582 ev->create = 1;
2583 ev->name = cmdName;
2584 ev->data = (ClientData)data;
2585 ev->status = &err;
2586 ev->done = &cond;
2587 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2588 Tcl_ConditionFinalize(&cond);
2589 }
2590 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002591#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002592 {
2593 ENTER_TCL
2594 err = Tcl_CreateCommand(
2595 Tkapp_Interp(self), cmdName, PythonCmd,
2596 (ClientData)data, PythonCmdDelete) == NULL;
2597 LEAVE_TCL
2598 }
2599 if (err) {
2600 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2601 PyMem_DEL(data);
2602 return NULL;
2603 }
Guido van Rossum18468821994-06-20 07:49:28 +00002604
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002605 Py_INCREF(Py_None);
2606 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002607}
2608
Barry Warsawfa701a81997-01-16 00:15:11 +00002609
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002610
Guido van Rossum18468821994-06-20 07:49:28 +00002611static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002612Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002613{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002614 TkappObject *self = (TkappObject*)selfptr;
2615 char *cmdName;
2616 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002617
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002618 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2619 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002620 CHECK_STRING_LENGTH(cmdName);
Guilherme Polo1972d162009-03-27 21:43:08 +00002621
2622#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002623 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2624 Tcl_Condition cond = NULL;
2625 CommandEvent *ev;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03002626 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2627 if (ev == NULL) {
2628 PyErr_NoMemory();
2629 return NULL;
2630 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002631 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2632 ev->interp = self->interp;
2633 ev->create = 0;
2634 ev->name = cmdName;
2635 ev->status = &err;
2636 ev->done = &cond;
2637 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2638 &command_mutex);
2639 Tcl_ConditionFinalize(&cond);
2640 }
2641 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002642#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002643 {
2644 ENTER_TCL
2645 err = Tcl_DeleteCommand(self->interp, cmdName);
2646 LEAVE_TCL
2647 }
2648 if (err == -1) {
2649 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2650 return NULL;
2651 }
2652 Py_INCREF(Py_None);
2653 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002654}
2655
Barry Warsawfa701a81997-01-16 00:15:11 +00002656
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002657
Guido van Rossum00d93061998-05-28 23:06:38 +00002658#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002659/** File Handler **/
2660
Guido van Rossum00d93061998-05-28 23:06:38 +00002661typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002662 PyObject *func;
2663 PyObject *file;
2664 int id;
2665 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002666} FileHandler_ClientData;
2667
2668static FileHandler_ClientData *HeadFHCD;
2669
2670static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002671NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002672{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002673 FileHandler_ClientData *p;
2674 p = PyMem_NEW(FileHandler_ClientData, 1);
2675 if (p != NULL) {
2676 Py_XINCREF(func);
2677 Py_XINCREF(file);
2678 p->func = func;
2679 p->file = file;
2680 p->id = id;
2681 p->next = HeadFHCD;
2682 HeadFHCD = p;
2683 }
2684 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002685}
2686
2687static void
Fred Drake509d79a2000-07-08 04:04:38 +00002688DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002689{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002690 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002691
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002692 pp = &HeadFHCD;
2693 while ((p = *pp) != NULL) {
2694 if (p->id == id) {
2695 *pp = p->next;
2696 Py_XDECREF(p->func);
2697 Py_XDECREF(p->file);
2698 PyMem_DEL(p);
2699 }
2700 else
2701 pp = &p->next;
2702 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002703}
2704
Guido van Rossuma597dde1995-01-10 20:56:29 +00002705static void
Fred Drake509d79a2000-07-08 04:04:38 +00002706FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002707{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002708 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2709 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002710
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002711 ENTER_PYTHON
2712 func = data->func;
2713 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002714
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002715 arg = Py_BuildValue("(Oi)", file, (long) mask);
2716 res = PyEval_CallObject(func, arg);
2717 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002718
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002719 if (res == NULL) {
2720 errorInCmd = 1;
2721 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2722 }
2723 Py_XDECREF(res);
2724 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002725}
2726
Guido van Rossum18468821994-06-20 07:49:28 +00002727static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002728Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2729 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002730{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002731 FileHandler_ClientData *data;
2732 PyObject *file, *func;
2733 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002734
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002735 if (!self && Py_Py3kWarningFlag) {
2736 if (PyErr_Warn(PyExc_DeprecationWarning,
2737 "_tkinter.createfilehandler 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, "OiO:createfilehandler",
2742 &file, &mask, &func))
2743 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002744
Martin v. Löwisa9656492003-03-30 08:44:58 +00002745#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002746 if (!self && !tcl_lock) {
2747 /* We don't have the Tcl lock since Tcl is threaded. */
2748 PyErr_SetString(PyExc_RuntimeError,
2749 "_tkinter.createfilehandler not supported "
2750 "for threaded Tcl");
2751 return NULL;
2752 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002753#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002754
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002755 if (self) {
2756 CHECK_TCL_APPARTMENT;
2757 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002758
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002759 tfile = PyObject_AsFileDescriptor(file);
2760 if (tfile < 0)
2761 return NULL;
2762 if (!PyCallable_Check(func)) {
2763 PyErr_SetString(PyExc_TypeError, "bad argument list");
2764 return NULL;
2765 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002766
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002767 data = NewFHCD(func, file, tfile);
2768 if (data == NULL)
2769 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002770
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002771 /* Ought to check for null Tcl_File object... */
2772 ENTER_TCL
2773 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2774 LEAVE_TCL
2775 Py_INCREF(Py_None);
2776 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002777}
2778
2779static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002780Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002781{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002782 PyObject *file;
2783 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002784
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002785 if (!self && Py_Py3kWarningFlag) {
2786 if (PyErr_Warn(PyExc_DeprecationWarning,
2787 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2788 return NULL;
2789 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002790
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002791 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2792 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002793
Martin v. Löwisa9656492003-03-30 08:44:58 +00002794#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002795 if (!self && !tcl_lock) {
2796 /* We don't have the Tcl lock since Tcl is threaded. */
2797 PyErr_SetString(PyExc_RuntimeError,
2798 "_tkinter.deletefilehandler not supported "
2799 "for threaded Tcl");
2800 return NULL;
2801 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002802#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002803
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002804 if (self) {
2805 CHECK_TCL_APPARTMENT;
2806 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002807
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002808 tfile = PyObject_AsFileDescriptor(file);
2809 if (tfile < 0)
2810 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002811
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002812 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002813
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002814 /* Ought to check for null Tcl_File object... */
2815 ENTER_TCL
2816 Tcl_DeleteFileHandler(tfile);
2817 LEAVE_TCL
2818 Py_INCREF(Py_None);
2819 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002820}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002821#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002822
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002823
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002824/**** Tktt Object (timer token) ****/
2825
Jeremy Hylton938ace62002-07-17 16:30:39 +00002826static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002827
Guido van Rossum00d93061998-05-28 23:06:38 +00002828typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002829 PyObject_HEAD
2830 Tcl_TimerToken token;
2831 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002832} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002833
2834static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002835Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002836{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002837 TkttObject *v = (TkttObject *)self;
2838 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002839
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002840 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2841 return NULL;
2842 if (v->token != NULL) {
2843 Tcl_DeleteTimerHandler(v->token);
2844 v->token = NULL;
2845 }
2846 if (func != NULL) {
2847 v->func = NULL;
2848 Py_DECREF(func);
2849 Py_DECREF(v); /* See Tktt_New() */
2850 }
2851 Py_INCREF(Py_None);
2852 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002853}
2854
2855static PyMethodDef Tktt_methods[] =
2856{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002857 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2858 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002859};
2860
2861static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002862Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002863{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002864 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002865
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002866 v = PyObject_New(TkttObject, &Tktt_Type);
2867 if (v == NULL)
2868 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002869
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002870 Py_INCREF(func);
2871 v->token = NULL;
2872 v->func = func;
2873
2874 /* Extra reference, deleted when called or when handler is deleted */
2875 Py_INCREF(v);
2876 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002877}
2878
2879static void
Fred Drake509d79a2000-07-08 04:04:38 +00002880Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002881{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002882 TkttObject *v = (TkttObject *)self;
2883 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002884
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002885 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002886
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002887 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002888}
2889
Guido van Rossum597ac201998-05-12 14:36:19 +00002890static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002891Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002892{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002893 TkttObject *v = (TkttObject *)self;
2894 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002895
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002896 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2897 v->func == NULL ? ", handler deleted" : "");
2898 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002899}
2900
2901static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002902Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002903{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002904 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002905}
2906
2907static PyTypeObject Tktt_Type =
2908{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002909 PyVarObject_HEAD_INIT(NULL, 0)
2910 "tktimertoken", /*tp_name */
2911 sizeof(TkttObject), /*tp_basicsize */
2912 0, /*tp_itemsize */
2913 Tktt_Dealloc, /*tp_dealloc */
2914 0, /*tp_print */
2915 Tktt_GetAttr, /*tp_getattr */
2916 0, /*tp_setattr */
2917 0, /*tp_compare */
2918 Tktt_Repr, /*tp_repr */
2919 0, /*tp_as_number */
2920 0, /*tp_as_sequence */
2921 0, /*tp_as_mapping */
2922 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002923};
2924
Barry Warsawfa701a81997-01-16 00:15:11 +00002925
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002926
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002927/** Timer Handler **/
2928
2929static void
Fred Drake509d79a2000-07-08 04:04:38 +00002930TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002931{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002932 TkttObject *v = (TkttObject *)clientData;
2933 PyObject *func = v->func;
2934 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002935
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002936 if (func == NULL)
2937 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002938
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002939 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002940
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002941 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002942
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002943 res = PyEval_CallObject(func, NULL);
2944 Py_DECREF(func);
2945 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002946
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002947 if (res == NULL) {
2948 errorInCmd = 1;
2949 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2950 }
2951 else
2952 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002953
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002954 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002955}
2956
2957static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002958Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002959{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002960 int milliseconds;
2961 PyObject *func;
2962 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002963
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002964 if (!self && Py_Py3kWarningFlag) {
2965 if (PyErr_Warn(PyExc_DeprecationWarning,
2966 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2967 return NULL;
2968 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002969
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002970 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2971 &milliseconds, &func))
2972 return NULL;
2973 if (!PyCallable_Check(func)) {
2974 PyErr_SetString(PyExc_TypeError, "bad argument list");
2975 return NULL;
2976 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002977
Martin v. Löwisa9656492003-03-30 08:44:58 +00002978#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002979 if (!self && !tcl_lock) {
2980 /* We don't have the Tcl lock since Tcl is threaded. */
2981 PyErr_SetString(PyExc_RuntimeError,
2982 "_tkinter.createtimerhandler not supported "
2983 "for threaded Tcl");
2984 return NULL;
2985 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002986#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002987
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002988 if (self) {
2989 CHECK_TCL_APPARTMENT;
2990 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002991
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002992 v = Tktt_New(func);
2993 if (v) {
2994 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2995 (ClientData)v);
2996 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002997
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002998 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002999}
3000
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003001
Guido van Rossum18468821994-06-20 07:49:28 +00003002/** Event Loop **/
3003
Guido van Rossum18468821994-06-20 07:49:28 +00003004static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00003005Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003006{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003007 int threshold = 0;
3008 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003009#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003010 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003011#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00003012
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003013 if (!self && Py_Py3kWarningFlag) {
3014 if (PyErr_Warn(PyExc_DeprecationWarning,
3015 "_tkinter.mainloop is gone in 3.x") < 0)
3016 return NULL;
3017 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00003018
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003019 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
3020 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003021
Martin v. Löwisa9656492003-03-30 08:44:58 +00003022#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003023 if (!self && !tcl_lock) {
3024 /* We don't have the Tcl lock since Tcl is threaded. */
3025 PyErr_SetString(PyExc_RuntimeError,
3026 "_tkinter.mainloop not supported "
3027 "for threaded Tcl");
3028 return NULL;
3029 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00003030#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00003031
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003032 if (self) {
3033 CHECK_TCL_APPARTMENT;
3034 self->dispatching = 1;
3035 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00003036
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003037 quitMainLoop = 0;
3038 while (Tk_GetNumMainWindows() > threshold &&
3039 !quitMainLoop &&
3040 !errorInCmd)
3041 {
3042 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00003043
3044#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003045 if (self && self->threaded) {
3046 /* Allow other Python threads to run. */
3047 ENTER_TCL
3048 result = Tcl_DoOneEvent(0);
3049 LEAVE_TCL
3050 }
3051 else {
3052 Py_BEGIN_ALLOW_THREADS
3053 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3054 tcl_tstate = tstate;
3055 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3056 tcl_tstate = NULL;
3057 if(tcl_lock)PyThread_release_lock(tcl_lock);
3058 if (result == 0)
3059 Sleep(Tkinter_busywaitinterval);
3060 Py_END_ALLOW_THREADS
3061 }
Guido van Rossum5b020781997-08-19 01:00:50 +00003062#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003063 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00003064#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003065
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003066 if (PyErr_CheckSignals() != 0) {
3067 if (self)
3068 self->dispatching = 0;
3069 return NULL;
3070 }
3071 if (result < 0)
3072 break;
3073 }
3074 if (self)
3075 self->dispatching = 0;
3076 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003077
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003078 if (errorInCmd) {
3079 errorInCmd = 0;
3080 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3081 excInCmd = valInCmd = trbInCmd = NULL;
3082 return NULL;
3083 }
3084 Py_INCREF(Py_None);
3085 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00003086}
3087
3088static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00003089Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00003090{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003091 int flags = 0;
3092 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00003093
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003094 if (!self && Py_Py3kWarningFlag) {
3095 if (PyErr_Warn(PyExc_DeprecationWarning,
3096 "_tkinter.dooneevent is gone in 3.x") < 0)
3097 return NULL;
3098 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00003099
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003100 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
3101 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00003102
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003103 ENTER_TCL
3104 rv = Tcl_DoOneEvent(flags);
3105 LEAVE_TCL
3106 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00003107}
3108
3109static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00003110Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003111{
3112
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003113 if (!self && Py_Py3kWarningFlag) {
3114 if (PyErr_Warn(PyExc_DeprecationWarning,
3115 "_tkinter.quit is gone in 3.x") < 0)
3116 return NULL;
3117 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00003118
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003119 if (!PyArg_ParseTuple(args, ":quit"))
3120 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00003121
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003122 quitMainLoop = 1;
3123 Py_INCREF(Py_None);
3124 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00003125}
3126
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003127static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00003128Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003129{
3130
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003131 if (!PyArg_ParseTuple(args, ":interpaddr"))
3132 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003133
Victor Stinner930c3c92013-09-05 00:26:15 +02003134 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003135}
3136
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003137static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00003138Tkapp_TkInit(PyObject *self, PyObject *args)
3139{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003140 Tcl_Interp *interp = Tkapp_Interp(self);
3141 const char * _tk_exists = NULL;
3142 int err;
David Aschere2b4b322004-02-18 05:59:53 +00003143
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00003144#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003145 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
3146 * first call failed.
3147 * To avoid the deadlock, we just refuse the second call through
3148 * a static variable.
3149 */
3150 if (tk_load_failed) {
3151 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
3152 return NULL;
3153 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00003154#endif
3155
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003156 /* We want to guard against calling Tk_Init() multiple times */
3157 CHECK_TCL_APPARTMENT;
3158 ENTER_TCL
3159 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
3160 ENTER_OVERLAP
3161 if (err == TCL_ERROR) {
3162 /* This sets an exception, but we cannot return right
3163 away because we need to exit the overlap first. */
3164 Tkinter_Error(self);
3165 } else {
3166 _tk_exists = Tkapp_Result(self);
3167 }
3168 LEAVE_OVERLAP_TCL
3169 if (err == TCL_ERROR) {
3170 return NULL;
3171 }
3172 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3173 if (Tk_Init(interp) == TCL_ERROR) {
3174 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00003175#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003176 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00003177#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003178 return NULL;
3179 }
3180 }
3181 Py_INCREF(Py_None);
3182 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00003183}
Barry Warsawfa701a81997-01-16 00:15:11 +00003184
Martin v. Löwisffad6332002-11-26 09:28:05 +00003185static PyObject *
3186Tkapp_WantObjects(PyObject *self, PyObject *args)
3187{
3188
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003189 int wantobjects = -1;
3190 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3191 return NULL;
3192 if (wantobjects == -1)
3193 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3194 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003195
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003196 Py_INCREF(Py_None);
3197 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003198}
3199
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003200static PyObject *
3201Tkapp_WillDispatch(PyObject *self, PyObject *args)
3202{
3203
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003204 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003205
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003206 Py_INCREF(Py_None);
3207 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003208}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003209
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03003210/* Convert Python string or any buffer compatible object to Tcl byte-array
3211 * object. Use it to pass binary data (e.g. image's data) to Tcl/Tk commands.
3212 */
3213static PyObject *
3214Tkapp_CreateByteArray(PyObject *self, PyObject *args)
3215{
3216 Py_buffer view;
3217 Tcl_Obj* obj;
3218 PyObject *res = NULL;
3219
3220 if (!PyArg_ParseTuple(args, "s*:_createbytearray", &view))
3221 return NULL;
3222
3223 if (view.len >= INT_MAX) {
3224 PyErr_SetString(PyExc_OverflowError, "string is too long");
3225 return NULL;
3226 }
3227 obj = Tcl_NewByteArrayObj(view.buf, (int)view.len);
3228 if (obj == NULL) {
3229 PyBuffer_Release(&view);
3230 return Tkinter_Error(self);
3231 }
3232 res = newPyTclObject(obj);
3233 PyBuffer_Release(&view);
3234 return res;
3235}
3236
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003237
Guido van Rossum18468821994-06-20 07:49:28 +00003238/**** Tkapp Method List ****/
3239
3240static PyMethodDef Tkapp_methods[] =
3241{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003242 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
3243 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3244 {"call", Tkapp_Call, METH_VARARGS},
3245 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
3246 {"eval", Tkapp_Eval, METH_VARARGS},
3247 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
3248 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
3249 {"record", Tkapp_Record, METH_VARARGS},
3250 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
3251 {"setvar", Tkapp_SetVar, METH_VARARGS},
3252 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3253 {"getvar", Tkapp_GetVar, METH_VARARGS},
3254 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3255 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3256 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3257 {"getint", Tkapp_GetInt, METH_VARARGS},
3258 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
Serhiy Storchakaf29bc702015-04-04 12:42:25 +03003259 {"getboolean", Tkapp_GetBoolean, METH_O},
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003260 {"exprstring", Tkapp_ExprString, METH_VARARGS},
3261 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
3262 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
3263 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
3264 {"splitlist", Tkapp_SplitList, METH_VARARGS},
3265 {"split", Tkapp_Split, METH_VARARGS},
3266 {"merge", Tkapp_Merge, METH_VARARGS},
3267 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
3268 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003269#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003270 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3271 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003272#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003273 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3274 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3275 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3276 {"quit", Tkapp_Quit, METH_VARARGS},
3277 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
3278 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03003279 {"_createbytearray", Tkapp_CreateByteArray, METH_VARARGS},
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003280 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003281};
3282
Barry Warsawfa701a81997-01-16 00:15:11 +00003283
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003284
Guido van Rossum18468821994-06-20 07:49:28 +00003285/**** Tkapp Type Methods ****/
3286
3287static void
Fred Drake509d79a2000-07-08 04:04:38 +00003288Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003289{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003290 /*CHECK_TCL_APPARTMENT;*/
3291 ENTER_TCL
3292 Tcl_DeleteInterp(Tkapp_Interp(self));
3293 LEAVE_TCL
3294 PyObject_Del(self);
3295 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003296}
3297
3298static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00003299Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00003300{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003301 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00003302}
3303
3304static PyTypeObject Tkapp_Type =
3305{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003306 PyVarObject_HEAD_INIT(NULL, 0)
3307 "tkapp", /*tp_name */
3308 sizeof(TkappObject), /*tp_basicsize */
3309 0, /*tp_itemsize */
3310 Tkapp_Dealloc, /*tp_dealloc */
3311 0, /*tp_print */
3312 Tkapp_GetAttr, /*tp_getattr */
3313 0, /*tp_setattr */
3314 0, /*tp_compare */
3315 0, /*tp_repr */
3316 0, /*tp_as_number */
3317 0, /*tp_as_sequence */
3318 0, /*tp_as_mapping */
3319 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00003320};
3321
Barry Warsawfa701a81997-01-16 00:15:11 +00003322
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003323
Guido van Rossum18468821994-06-20 07:49:28 +00003324/**** Tkinter Module ****/
3325
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003326typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003327 PyObject* tuple;
3328 int size; /* current size */
3329 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003330} FlattenContext;
3331
3332static int
3333_bump(FlattenContext* context, int size)
3334{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003335 /* expand tuple to hold (at least) size new items.
3336 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003337
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003338 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003339
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003340 if (maxsize < context->size + size)
3341 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003342
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003343 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003344
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003345 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003346}
3347
3348static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003349_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003350{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003351 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003352
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003353 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003354
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003355 if (depth > 1000) {
3356 PyErr_SetString(PyExc_ValueError,
3357 "nesting too deep in _flatten");
3358 return 0;
3359 } else if (PyList_Check(item)) {
3360 size = PyList_GET_SIZE(item);
3361 /* preallocate (assume no nesting) */
3362 if (context->size + size > context->maxsize &&
3363 !_bump(context, size))
3364 return 0;
3365 /* copy items to output tuple */
3366 for (i = 0; i < size; i++) {
3367 PyObject *o = PyList_GET_ITEM(item, i);
3368 if (PyList_Check(o) || PyTuple_Check(o)) {
3369 if (!_flatten1(context, o, depth + 1))
3370 return 0;
3371 } else if (o != Py_None) {
3372 if (context->size + 1 > context->maxsize &&
3373 !_bump(context, 1))
3374 return 0;
3375 Py_INCREF(o);
3376 PyTuple_SET_ITEM(context->tuple,
3377 context->size++, o);
3378 }
3379 }
3380 } else if (PyTuple_Check(item)) {
3381 /* same, for tuples */
3382 size = PyTuple_GET_SIZE(item);
3383 if (context->size + size > context->maxsize &&
3384 !_bump(context, size))
3385 return 0;
3386 for (i = 0; i < size; i++) {
3387 PyObject *o = PyTuple_GET_ITEM(item, i);
3388 if (PyList_Check(o) || PyTuple_Check(o)) {
3389 if (!_flatten1(context, o, depth + 1))
3390 return 0;
3391 } else if (o != Py_None) {
3392 if (context->size + 1 > context->maxsize &&
3393 !_bump(context, 1))
3394 return 0;
3395 Py_INCREF(o);
3396 PyTuple_SET_ITEM(context->tuple,
3397 context->size++, o);
3398 }
3399 }
3400 } else {
3401 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3402 return 0;
3403 }
3404 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003405}
3406
3407static PyObject *
3408Tkinter_Flatten(PyObject* self, PyObject* args)
3409{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003410 FlattenContext context;
3411 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003412
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003413 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3414 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003415
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003416 context.maxsize = PySequence_Size(item);
3417 if (context.maxsize < 0)
3418 return NULL;
3419 if (context.maxsize == 0)
3420 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003421
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003422 context.tuple = PyTuple_New(context.maxsize);
3423 if (!context.tuple)
3424 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003425
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003426 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003427
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003428 if (!_flatten1(&context, item,0))
3429 return NULL;
3430
3431 if (_PyTuple_Resize(&context.tuple, context.size))
3432 return NULL;
3433
3434 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003435}
3436
Guido van Rossum18468821994-06-20 07:49:28 +00003437static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003438Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003439{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003440 char *screenName = NULL;
3441 char *baseName = NULL;
3442 char *className = NULL;
3443 int interactive = 0;
3444 int wantobjects = 0;
3445 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3446 int sync = 0; /* pass -sync to wish */
3447 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003448
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003449 baseName = strrchr(Py_GetProgramName(), '/');
3450 if (baseName != NULL)
3451 baseName++;
3452 else
3453 baseName = Py_GetProgramName();
3454 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003455
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003456 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3457 &screenName, &baseName, &className,
3458 &interactive, &wantobjects, &wantTk,
3459 &sync, &use))
3460 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03003461 CHECK_STRING_LENGTH(screenName);
3462 CHECK_STRING_LENGTH(baseName);
3463 CHECK_STRING_LENGTH(className);
3464 CHECK_STRING_LENGTH(use);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003465
3466 return (PyObject *) Tkapp_New(screenName, baseName, className,
3467 interactive, wantobjects, wantTk,
3468 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003469}
3470
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003471static PyObject *
3472Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3473{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003474 int new_val;
3475 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3476 return NULL;
3477 if (new_val < 0) {
3478 PyErr_SetString(PyExc_ValueError,
3479 "busywaitinterval must be >= 0");
3480 return NULL;
3481 }
3482 Tkinter_busywaitinterval = new_val;
3483 Py_INCREF(Py_None);
3484 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003485}
3486
3487static char setbusywaitinterval_doc[] =
3488"setbusywaitinterval(n) -> None\n\
3489\n\
3490Set the busy-wait interval in milliseconds between successive\n\
3491calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3492It should be set to a divisor of the maximum time between\n\
3493frames in an animation.";
3494
3495static PyObject *
3496Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3497{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003498 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003499}
3500
3501static char getbusywaitinterval_doc[] =
3502"getbusywaitinterval() -> int\n\
3503\n\
3504Return the current busy-wait interval between successive\n\
3505calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3506
Guido van Rossum18468821994-06-20 07:49:28 +00003507static PyMethodDef moduleMethods[] =
3508{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003509 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3510 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003511#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003512 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3513 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003514#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003515 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3516 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3517 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3518 {"quit", Tkapp_Quit, METH_VARARGS},
3519 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3520 setbusywaitinterval_doc},
3521 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3522 METH_NOARGS, getbusywaitinterval_doc},
3523 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003524};
3525
Guido van Rossum7bf15641998-05-22 18:28:17 +00003526#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003527
3528static int stdin_ready = 0;
3529
Guido van Rossumad4db171998-06-13 13:56:28 +00003530#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003531static void
Fred Drake509d79a2000-07-08 04:04:38 +00003532MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003533{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003534 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003535}
Guido van Rossumad4db171998-06-13 13:56:28 +00003536#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003537
Martin v. Löwisa9656492003-03-30 08:44:58 +00003538#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003539static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003540#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003541
Guido van Rossum18468821994-06-20 07:49:28 +00003542static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003543EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003544{
Guido van Rossumad4db171998-06-13 13:56:28 +00003545#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003546 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003547#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003548#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003549 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003550#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003551 stdin_ready = 0;
3552 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003553#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003554 tfile = fileno(stdin);
3555 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003556#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003557 while (!errorInCmd && !stdin_ready) {
3558 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003559#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003560 if (_kbhit()) {
3561 stdin_ready = 1;
3562 break;
3563 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003564#endif
3565#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003566 Py_BEGIN_ALLOW_THREADS
3567 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3568 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003569
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003570 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003571
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003572 tcl_tstate = NULL;
3573 if(tcl_lock)PyThread_release_lock(tcl_lock);
3574 if (result == 0)
3575 Sleep(Tkinter_busywaitinterval);
3576 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003577#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003578 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003579#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003580
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003581 if (result < 0)
3582 break;
3583 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003584#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003585 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003586#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003587 if (errorInCmd) {
3588 errorInCmd = 0;
3589 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3590 excInCmd = valInCmd = trbInCmd = NULL;
3591 PyErr_Print();
3592 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003593#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003594 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003595#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003596 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003597}
Guido van Rossum18468821994-06-20 07:49:28 +00003598
Guido van Rossum00d93061998-05-28 23:06:38 +00003599#endif
3600
Guido van Rossum7bf15641998-05-22 18:28:17 +00003601static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003602EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003603{
Guido van Rossum00d93061998-05-28 23:06:38 +00003604#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003605 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003606#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003607 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003608#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003609 PyOS_InputHook = EventHook;
3610 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003611#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003612}
3613
3614static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003615DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003616{
Guido van Rossum00d93061998-05-28 23:06:38 +00003617#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003618 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3619 PyOS_InputHook = NULL;
3620 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003621#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003622}
3623
Barry Warsawfa701a81997-01-16 00:15:11 +00003624
3625/* all errors will be checked in one fell swoop in init_tkinter() */
3626static void
Fred Drake509d79a2000-07-08 04:04:38 +00003627ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003628{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003629 PyObject *v = PyInt_FromLong(val);
3630 if (v) {
3631 PyDict_SetItemString(d, name, v);
3632 Py_DECREF(v);
3633 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003634}
3635static void
Fred Drake509d79a2000-07-08 04:04:38 +00003636ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003637{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003638 PyObject *v = PyString_FromString(val);
3639 if (v) {
3640 PyDict_SetItemString(d, name, v);
3641 Py_DECREF(v);
3642 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003643}
3644
3645
Mark Hammond62b1ab12002-07-23 06:31:15 +00003646PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003647init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003648{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003649 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003650
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003651 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003652
3653#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003654 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003655#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003656
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003657 m = Py_InitModule("_tkinter", moduleMethods);
3658 if (m == NULL)
3659 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003660
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003661 d = PyModule_GetDict(m);
3662 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3663 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003664
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003665 ins_long(d, "READABLE", TCL_READABLE);
3666 ins_long(d, "WRITABLE", TCL_WRITABLE);
3667 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3668 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3669 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3670 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3671 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3672 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3673 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3674 ins_string(d, "TK_VERSION", TK_VERSION);
3675 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003676
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003677 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003678
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003679 Py_TYPE(&Tktt_Type) = &PyType_Type;
3680 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003681
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003682 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3683 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003684
3685#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003686 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3687 * start waking up. Note that Tcl_FindExecutable will do this, this
3688 * code must be above it! The original warning from
3689 * tkMacOSXAppInit.c is copied below.
3690 *
3691 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3692 * Tcl interpreter for now. It probably should work to do this
3693 * in the other order, but for now it doesn't seem to.
3694 *
3695 */
3696 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003697#endif
3698
3699
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003700 /* This helps the dynamic loader; in Unicode aware Tcl versions
3701 it also helps Tcl find its encodings. */
3702 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003703
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003704 if (PyErr_Occurred())
3705 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003706
Guido van Rossum43ff8681998-07-14 18:02:13 +00003707#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003708 /* This was not a good idea; through <Destroy> bindings,
3709 Tcl_Finalize() may invoke Python code but at that point the
3710 interpreter and thread state have already been destroyed! */
3711 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003712#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003713
Guido van Rossum18468821994-06-20 07:49:28 +00003714}