blob: 4d9cc0df87170134707457733c3b723557948dd9 [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Antoine Pitrouc83ea132010-05-09 14:46:46 +000012 Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
14 Tcl/Tk libraries.
Guido van Rossuma80649b2000-03-28 20:07:05 +000015*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Martin v. Löwis39195712003-01-04 00:33:13 +000036/* Allow using this code in Python 2.[12] */
37#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000038#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000039#endif
40
41#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000042#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000045#ifndef PyBool_Check
46#define PyBool_Check(o) 0
47#define PyBool_FromLong PyInt_FromLong
48#endif
49
Serhiy Storchaka42035702013-08-21 21:46:12 +030050#define CHECK_SIZE(size, elemsize) \
51 ((size_t)(size) <= (size_t)INT_MAX && \
52 (size_t)(size) <= UINT_MAX / (size_t)(elemsize))
53
Martin v. Löwis71e25a02002-10-01 18:08:06 +000054/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
55 making _tkinter correct for this API means to break earlier
56 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
57 earlier versions. Once Tcl releases before 8.4 don't need to be supported
58 anymore, this should go. */
59#define USE_COMPAT_CONST
60
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000061/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
62 it always; if Tcl is not threaded, the thread functions in
63 Tcl are empty. */
64#define TCL_THREADS
65
Jack Jansencb852442001-12-09 23:15:56 +000066#ifdef TK_FRAMEWORK
67#include <Tcl/tcl.h>
68#include <Tk/tk.h>
69#else
Guido van Rossum18468821994-06-20 07:49:28 +000070#include <tcl.h>
71#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000072#endif
Guido van Rossum18468821994-06-20 07:49:28 +000073
Guilherme Polo5d64c332009-04-05 02:11:19 +000074#include "tkinter.h"
75
Jason Tishlerbbe89612002-12-31 20:30:46 +000076/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000077#ifndef CONST84_RETURN
78#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000079#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000080#define CONST
81#endif
82
Guilherme Poloc5eba1e2009-02-09 20:57:45 +000083#if TK_VERSION_HEX < 0x08030102
84#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000085#endif
86
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000087/* Unicode conversion assumes that Tcl_UniChar is two bytes.
88 We cannot test this directly, so we test UTF-8 size instead,
89 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Antoine Pitrouc83ea132010-05-09 14:46:46 +000090 either UTF-16 or UCS-4.
91 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000092 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
93 as well.
94*/
95#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000096#error "unsupported Tcl configuration"
97#endif
98
Serhiy Storchaka02d02982015-04-20 14:05:37 +030099#if TK_VERSION_HEX >= 0x08050002
Serhiy Storchakac77c5b52015-04-02 18:46:30 +0300100#define HAVE_LIBTOMMAMTH
101#include <tclTomMath.h>
102#endif
103
Jack Janseneddc1442003-11-20 01:44:59 +0000104#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000105#define HAVE_CREATEFILEHANDLER
106#endif
107
Guido van Rossum00d93061998-05-28 23:06:38 +0000108#ifdef HAVE_CREATEFILEHANDLER
109
Neal Norwitzd948a432006-01-08 01:08:55 +0000110/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
111 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
112#ifndef TCL_UNIX_FD
113# ifdef TCL_WIN_SOCKET
114# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
115# else
116# define TCL_UNIX_FD 1
117# endif
118#endif
119
Guido van Rossum00d93061998-05-28 23:06:38 +0000120/* Tcl_CreateFileHandler() changed several times; these macros deal with the
121 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
122 Unix, only because Jack added it back); when available on Windows, it only
123 applies to sockets. */
124
Guido van Rossum7bf15641998-05-22 18:28:17 +0000125#ifdef MS_WINDOWS
126#define FHANDLETYPE TCL_WIN_SOCKET
127#else
128#define FHANDLETYPE TCL_UNIX_FD
129#endif
130
Guido van Rossum00d93061998-05-28 23:06:38 +0000131/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
132 which uses this to handle Tcl events while the user is typing commands. */
133
134#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000135#define WAIT_FOR_STDIN
136#endif
137
Guido van Rossum00d93061998-05-28 23:06:38 +0000138#endif /* HAVE_CREATEFILEHANDLER */
139
Guido van Rossumad4db171998-06-13 13:56:28 +0000140#ifdef MS_WINDOWS
141#include <conio.h>
142#define WAIT_FOR_STDIN
143#endif
144
Guido van Rossum00d93061998-05-28 23:06:38 +0000145#ifdef WITH_THREAD
146
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000147/* The threading situation is complicated. Tcl is not thread-safe, except
148 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000149 So we need to use a lock around all uses of Tcl. Previously, the Python
150 interpreter lock was used for this. However, this causes problems when
151 other Python threads need to run while Tcl is blocked waiting for events.
152
153 To solve this problem, a separate lock for Tcl is introduced. Holding it
154 is incompatible with holding Python's interpreter lock. The following four
155 macros manipulate both locks together.
156
157 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
158 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
159 that could call an event handler, or otherwise affect the state of a Tcl
160 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000161 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000162 released and the lock for Tcl has been acquired.
163
Guido van Rossum5e977831998-06-15 14:03:52 +0000164 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
165 (For example, when transferring data from the Tcl interpreter result to a
166 Python string object.) This can be done by using different macros to close
167 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
168 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
169 releases the Tcl lock.
170
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000171 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000172 handlers when the handler needs to use Python. Such event handlers are
173 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000174 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000175 the Python interpreter lock, restoring the appropriate thread state, and
176 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
177 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000178 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000179
180 These locks expand to several statements and brackets; they should not be
181 used in branches of if statements and the like.
182
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000183 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
184 only valid in the thread that created it, and all Tk activity must happen in this
185 thread, also. That means that the mainloop must be invoked in the thread that
186 created the interpreter. Invoking commands from other threads is possible;
187 _tkinter will queue an event for the interpreter thread, which will then
188 execute the command and pass back the result. If the main thread is not in the
189 mainloop, and invoking commands causes an exception; if the main loop is running
190 but not processing events, the command invocation will block.
191
192 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
193 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
194 threads. So we use the Tcl TLS API.
195
Guido van Rossum00d93061998-05-28 23:06:38 +0000196*/
197
Guido van Rossum65d5b571998-12-21 19:32:43 +0000198static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000199
200#ifdef TCL_THREADS
201static Tcl_ThreadDataKey state_key;
202typedef PyThreadState *ThreadSpecificData;
203#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
204#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000205static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000206#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000207
208#define ENTER_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000209 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
210 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000211
212#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000213 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000214
Guido van Rossum62320c91998-06-15 04:36:09 +0000215#define ENTER_OVERLAP \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000216 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000217
218#define LEAVE_OVERLAP_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000219 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000220
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000221#define ENTER_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000222 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
223 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000224
225#define LEAVE_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000226 { PyThreadState *tstate = PyEval_SaveThread(); \
227 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000228
229#define CHECK_TCL_APPARTMENT \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000230 if (((TkappObject *)self)->threaded && \
231 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
232 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
233 return 0; \
234 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000235
236#else
237
238#define ENTER_TCL
239#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000240#define ENTER_OVERLAP
241#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000242#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000243#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000244#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000245
246#endif
247
Guido van Rossum97867b21996-08-08 19:09:53 +0000248#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000249#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000250#endif
251
Guido van Rossum18468821994-06-20 07:49:28 +0000252/**** Tkapp Object Declaration ****/
253
Jeremy Hylton938ace62002-07-17 16:30:39 +0000254static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000255
Guido van Rossum00d93061998-05-28 23:06:38 +0000256typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000257 PyObject_HEAD
258 Tcl_Interp *interp;
259 int wantobjects;
260 int threaded; /* True if tcl_platform[threaded] */
261 Tcl_ThreadId thread_id;
262 int dispatching;
263 /* We cannot include tclInt.h, as this is internal.
264 So we cache interesting types here. */
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +0300265 const Tcl_ObjType *OldBooleanType;
266 const Tcl_ObjType *BooleanType;
267 const Tcl_ObjType *ByteArrayType;
268 const Tcl_ObjType *DoubleType;
269 const Tcl_ObjType *IntType;
Serhiy Storchakac77c5b52015-04-02 18:46:30 +0300270 const Tcl_ObjType *WideIntType;
271 const Tcl_ObjType *BignumType;
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +0300272 const Tcl_ObjType *ListType;
273 const Tcl_ObjType *ProcBodyType;
274 const Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000275} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000276
Christian Heimese93237d2007-12-19 02:37:44 +0000277#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000278#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000279#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000280
Guido van Rossum35d43371997-08-02 00:09:09 +0000281#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimese93237d2007-12-19 02:37:44 +0000282(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000283
Barry Warsawfa701a81997-01-16 00:15:11 +0000284
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000285
Guido van Rossum18468821994-06-20 07:49:28 +0000286/**** Error Handling ****/
287
288static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000289static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000290static int errorInCmd = 0;
291static PyObject *excInCmd;
292static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000293static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000294
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000295#ifdef TKINTER_PROTECT_LOADTK
296static int tk_load_failed;
297#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000298
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000299
Guido van Rossum18468821994-06-20 07:49:28 +0000300static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000301Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000302{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000303 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
304 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000305}
306
Barry Warsawfa701a81997-01-16 00:15:11 +0000307
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000308
Guido van Rossum18468821994-06-20 07:49:28 +0000309/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000310
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000311static int Tkinter_busywaitinterval = 20;
312
Guido van Rossum00d93061998-05-28 23:06:38 +0000313#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000314#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000315
Guido van Rossum00d93061998-05-28 23:06:38 +0000316/* Millisecond sleep() for Unix platforms. */
317
318static void
Fred Drake509d79a2000-07-08 04:04:38 +0000319Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000320{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000321 /* XXX Too bad if you don't have select(). */
322 struct timeval t;
323 t.tv_sec = milli/1000;
324 t.tv_usec = (milli%1000) * 1000;
325 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000326}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000327#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000328
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000329/* Wait up to 1s for the mainloop to come up. */
330
331static int
332WaitForMainloop(TkappObject* self)
333{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000334 int i;
335 for (i = 0; i < 10; i++) {
336 if (self->dispatching)
337 return 1;
338 Py_BEGIN_ALLOW_THREADS
339 Sleep(100);
340 Py_END_ALLOW_THREADS
341 }
342 if (self->dispatching)
343 return 1;
344 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
345 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000346}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000347#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000348
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000349
Guido van Rossum18468821994-06-20 07:49:28 +0000350static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000351AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000352{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000353 if (PyString_Check(value))
354 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000355#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000356 else if (PyUnicode_Check(value)) {
357 PyObject *v = PyUnicode_AsUTF8String(value);
358 if (v == NULL)
359 return NULL;
360 if (PyList_Append(tmp, v) != 0) {
361 Py_DECREF(v);
362 return NULL;
363 }
364 Py_DECREF(v);
365 return PyString_AsString(v);
366 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000367#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000368 else {
369 PyObject *v = PyObject_Str(value);
370 if (v == NULL)
371 return NULL;
372 if (PyList_Append(tmp, v) != 0) {
373 Py_DECREF(v);
374 return NULL;
375 }
376 Py_DECREF(v);
377 return PyString_AsString(v);
378 }
Guido van Rossum18468821994-06-20 07:49:28 +0000379}
380
Barry Warsawfa701a81997-01-16 00:15:11 +0000381
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000382
Guido van Rossum18468821994-06-20 07:49:28 +0000383#define ARGSZ 64
384
385static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000386Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000387{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000388 PyObject *tmp = NULL;
389 char *argvStore[ARGSZ];
390 char **argv = NULL;
391 int fvStore[ARGSZ];
392 int *fv = NULL;
Serhiy Storchaka42035702013-08-21 21:46:12 +0300393 Py_ssize_t argc = 0, fvc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000394 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000395
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000396 if (!(tmp = PyList_New(0)))
397 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000398
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000399 argv = argvStore;
400 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000401
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000402 if (args == NULL)
403 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000404
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000405 else if (!PyTuple_Check(args)) {
406 argc = 1;
407 fv[0] = 0;
408 if (!(argv[0] = AsString(args, tmp)))
409 goto finally;
410 }
411 else {
412 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000413
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000414 if (argc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +0300415 if (!CHECK_SIZE(argc, sizeof(char *))) {
416 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
417 goto finally;
418 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +0300419 argv = (char **)attemptckalloc((size_t)argc * sizeof(char *));
420 fv = (int *)attemptckalloc((size_t)argc * sizeof(int));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000421 if (argv == NULL || fv == NULL) {
422 PyErr_NoMemory();
423 goto finally;
424 }
425 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000426
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000427 for (i = 0; i < argc; i++) {
428 PyObject *v = PyTuple_GetItem(args, i);
429 if (PyTuple_Check(v)) {
430 fv[i] = 1;
431 if (!(argv[i] = Merge(v)))
432 goto finally;
433 fvc++;
434 }
435 else if (v == Py_None) {
436 argc = i;
437 break;
438 }
439 else {
440 fv[i] = 0;
441 if (!(argv[i] = AsString(v, tmp)))
442 goto finally;
443 fvc++;
444 }
445 }
446 }
447 res = Tcl_Merge(argc, argv);
448 if (res == NULL)
449 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000450
Barry Warsawfa701a81997-01-16 00:15:11 +0000451 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000452 for (i = 0; i < fvc; i++)
453 if (fv[i]) {
454 ckfree(argv[i]);
455 }
456 if (argv != argvStore)
457 ckfree(FREECAST argv);
458 if (fv != fvStore)
459 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000460
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000461 Py_DECREF(tmp);
462 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000463}
464
Barry Warsawfa701a81997-01-16 00:15:11 +0000465
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000466
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200467#ifdef Py_USING_UNICODE
468static PyObject *
469unicode_FromTclStringAndSize(const char *s, Py_ssize_t size)
470{
471 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
472 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
473 /* Tcl encodes null character as \xc0\x80 */
474 if (memchr(s, '\xc0', size)) {
475 char *buf, *q;
476 const char *e = s + size;
477 PyErr_Clear();
478 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchaka5d93f402014-07-14 12:20:01 +0300479 if (buf == NULL) {
480 PyErr_NoMemory();
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200481 return NULL;
Serhiy Storchaka5d93f402014-07-14 12:20:01 +0300482 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200483 while (s != e) {
484 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
485 *q++ = '\0';
486 s += 2;
487 }
488 else
489 *q++ = *s++;
490 }
491 s = buf;
492 size = q - s;
493 r = PyUnicode_DecodeUTF8(s, size, NULL);
494 PyMem_Free(buf);
495 }
496 }
497 return r;
498}
499#endif
500
501static PyObject *
502fromTclStringAndSize(const char *s, Py_ssize_t size)
503{
504 PyObject *r;
505#ifdef Py_USING_UNICODE
506 Py_ssize_t i;
507 /* If Tcl string contains any bytes with the top bit set,
508 it's UTF-8 and we should decode it to Unicode */
509 for (i = 0; i < size; i++)
510 if (s[i] & 0x80)
511 break;
512 if (i != size) {
513 /* It isn't an ASCII string. */
514 r = unicode_FromTclStringAndSize(s, size);
515 if (r)
516 return r;
517 PyErr_Clear();
518 }
519#endif
520 r = PyString_FromStringAndSize(s, size);
521 return r;
522}
523
524static PyObject *
525fromTclString(const char *s)
526{
527 return fromTclStringAndSize(s, strlen(s));
528}
529
530
Guido van Rossum18468821994-06-20 07:49:28 +0000531static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000532Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000533{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000534 int argc;
535 char **argv;
536 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000537
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000538 if (list == NULL) {
539 Py_INCREF(Py_None);
540 return Py_None;
541 }
Guido van Rossum18468821994-06-20 07:49:28 +0000542
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000543 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
544 /* Not a list.
545 * Could be a quoted string containing funnies, e.g. {"}.
546 * Return the string itself.
547 */
548 return PyString_FromString(list);
549 }
Guido van Rossum18468821994-06-20 07:49:28 +0000550
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000551 if (argc == 0)
552 v = PyString_FromString("");
553 else if (argc == 1)
554 v = PyString_FromString(argv[0]);
555 else if ((v = PyTuple_New(argc)) != NULL) {
556 int i;
557 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000558
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000559 for (i = 0; i < argc; i++) {
560 if ((w = Split(argv[i])) == NULL) {
561 Py_DECREF(v);
562 v = NULL;
563 break;
564 }
565 PyTuple_SetItem(v, i, w);
566 }
567 }
568 Tcl_Free(FREECAST argv);
569 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000570}
571
Martin v. Löwisffad6332002-11-26 09:28:05 +0000572/* In some cases, Tcl will still return strings that are supposed to be
573 lists. SplitObj walks through a nested tuple, finding string objects that
574 need to be split. */
575
Martin v. Löwis111c1802008-06-13 07:47:47 +0000576static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000577SplitObj(PyObject *arg)
578{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000579 if (PyTuple_Check(arg)) {
580 int i, size;
581 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000582
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000583 size = PyTuple_Size(arg);
584 result = NULL;
585 /* Recursively invoke SplitObj for all tuple items.
586 If this does not return a new object, no action is
587 needed. */
588 for(i = 0; i < size; i++) {
589 elem = PyTuple_GetItem(arg, i);
590 newelem = SplitObj(elem);
591 if (!newelem) {
592 Py_XDECREF(result);
593 return NULL;
594 }
595 if (!result) {
596 int k;
597 if (newelem == elem) {
598 Py_DECREF(newelem);
599 continue;
600 }
601 result = PyTuple_New(size);
602 if (!result)
603 return NULL;
604 for(k = 0; k < i; k++) {
605 elem = PyTuple_GetItem(arg, k);
606 Py_INCREF(elem);
607 PyTuple_SetItem(result, k, elem);
608 }
609 }
610 PyTuple_SetItem(result, i, newelem);
611 }
612 if (result)
613 return result;
614 /* Fall through, returning arg. */
615 }
616 else if (PyString_Check(arg)) {
617 int argc;
618 char **argv;
619 char *list = PyString_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000620
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000621 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
622 Py_INCREF(arg);
623 return arg;
624 }
625 Tcl_Free(FREECAST argv);
626 if (argc > 1)
627 return Split(PyString_AsString(arg));
628 /* Fall through, returning arg. */
629 }
Serhiy Storchakafab65422013-07-11 20:32:48 +0300630 else if (PyUnicode_Check(arg)) {
631 int argc;
632 char **argv;
633 char *list;
634 PyObject *s = PyUnicode_AsUTF8String(arg);
635
636 if (s == NULL) {
637 Py_INCREF(arg);
638 return arg;
639 }
640 list = PyString_AsString(s);
641
642 if (list == NULL ||
643 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
644 Py_DECREF(s);
645 Py_INCREF(arg);
646 return arg;
647 }
648 Tcl_Free(FREECAST argv);
649 if (argc > 1) {
650 PyObject *v = Split(list);
651 Py_DECREF(s);
652 return v;
653 }
654 Py_DECREF(s);
655 /* Fall through, returning arg. */
656 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000657 Py_INCREF(arg);
658 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000659}
Barry Warsawfa701a81997-01-16 00:15:11 +0000660
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000661
Guido van Rossum18468821994-06-20 07:49:28 +0000662/**** Tkapp Object ****/
663
664#ifndef WITH_APPINIT
665int
Fred Drake509d79a2000-07-08 04:04:38 +0000666Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000667{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000668 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000669
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000670 if (Tcl_Init(interp) == TCL_ERROR) {
671 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
672 return TCL_ERROR;
673 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000674
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000675 _tkinter_skip_tk_init = Tcl_GetVar(interp,
676 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
677 if (_tkinter_skip_tk_init != NULL &&
678 strcmp(_tkinter_skip_tk_init, "1") == 0) {
679 return TCL_OK;
680 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000681
682#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000683 if (tk_load_failed) {
684 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
685 return TCL_ERROR;
686 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000687#endif
688
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000689 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000690#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000691 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000692#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000693 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
694 return TCL_ERROR;
695 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000696
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000697 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000698}
699#endif /* !WITH_APPINIT */
700
Guido van Rossum18468821994-06-20 07:49:28 +0000701
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000702
Barry Warsawfa701a81997-01-16 00:15:11 +0000703
704/* Initialize the Tk application; see the `main' function in
705 * `tkMain.c'.
706 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000707
Thomas Wouters58d05102000-07-24 14:43:35 +0000708static void EnableEventHook(void); /* Forward */
709static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000710
Barry Warsawfa701a81997-01-16 00:15:11 +0000711static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000712Tkapp_New(char *screenName, char *baseName, char *className,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000713 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000714{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000715 TkappObject *v;
716 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000717
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000718 v = PyObject_New(TkappObject, &Tkapp_Type);
719 if (v == NULL)
720 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000721
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000722 v->interp = Tcl_CreateInterp();
723 v->wantobjects = wantobjects;
724 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
725 TCL_GLOBAL_ONLY) != NULL;
726 v->thread_id = Tcl_GetCurrentThread();
727 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000728
729#ifndef TCL_THREADS
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000730 if (v->threaded) {
731 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
732 Py_DECREF(v);
733 return 0;
734 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000735#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000736#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000737 if (v->threaded && tcl_lock) {
738 /* If Tcl is threaded, we don't need the lock. */
739 PyThread_free_lock(tcl_lock);
740 tcl_lock = NULL;
741 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000742#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000743
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +0300744 v->OldBooleanType = Tcl_GetObjType("boolean");
745 v->BooleanType = Tcl_GetObjType("booleanString");
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000746 v->ByteArrayType = Tcl_GetObjType("bytearray");
747 v->DoubleType = Tcl_GetObjType("double");
748 v->IntType = Tcl_GetObjType("int");
Serhiy Storchakac77c5b52015-04-02 18:46:30 +0300749 v->WideIntType = Tcl_GetObjType("wideInt");
750 v->BignumType = Tcl_GetObjType("bignum");
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000751 v->ListType = Tcl_GetObjType("list");
752 v->ProcBodyType = Tcl_GetObjType("procbody");
753 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000754
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000755 /* Delete the 'exit' command, which can screw things up */
756 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000757
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000758 if (screenName != NULL)
759 Tcl_SetVar2(v->interp, "env", "DISPLAY",
760 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000761
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000762 if (interactive)
763 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
764 else
765 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000766
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000767 /* This is used to get the application class for Tk 4.1 and up */
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +0300768 argv0 = (char*)attemptckalloc(strlen(className) + 1);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000769 if (!argv0) {
770 PyErr_NoMemory();
771 Py_DECREF(v);
772 return NULL;
773 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000774
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000775 strcpy(argv0, className);
Antoine Pitrou44b3b542011-10-04 13:55:37 +0200776 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
777 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000778 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
779 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000780
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000781 if (! wantTk) {
782 Tcl_SetVar(v->interp,
783 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
784 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000785#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000786 else if (tk_load_failed) {
787 Tcl_SetVar(v->interp,
788 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
789 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000790#endif
David Aschere2b4b322004-02-18 05:59:53 +0000791
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000792 /* some initial arguments need to be in argv */
793 if (sync || use) {
794 char *args;
795 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000796
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000797 if (sync)
798 len += sizeof "-sync";
799 if (use)
800 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000801
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +0300802 args = (char*)attemptckalloc(len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000803 if (!args) {
804 PyErr_NoMemory();
805 Py_DECREF(v);
806 return NULL;
807 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000808
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000809 args[0] = '\0';
810 if (sync)
811 strcat(args, "-sync");
812 if (use) {
813 if (sync)
814 strcat(args, " ");
815 strcat(args, "-use ");
816 strcat(args, use);
817 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000818
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000819 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
820 ckfree(args);
821 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000822
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000823 if (Tcl_AppInit(v->interp) != TCL_OK) {
824 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000825#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000826 if (wantTk) {
827 const char *_tkinter_tk_failed;
828 _tkinter_tk_failed = Tcl_GetVar(v->interp,
829 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000830
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000831 if ( _tkinter_tk_failed != NULL &&
832 strcmp(_tkinter_tk_failed, "1") == 0) {
833 tk_load_failed = 1;
834 }
835 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000836#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000837 Py_DECREF((PyObject *)v);
838 return (TkappObject *)result;
839 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000840
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000841 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000842
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000843 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000844}
845
Barry Warsawfa701a81997-01-16 00:15:11 +0000846
Guilherme Polo1972d162009-03-27 21:43:08 +0000847#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000848static void
849Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000850 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000851{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000852 Py_BEGIN_ALLOW_THREADS;
853 Tcl_MutexLock(mutex);
854 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
855 Tcl_ThreadAlert(self->thread_id);
856 Tcl_ConditionWait(cond, mutex, NULL);
857 Tcl_MutexUnlock(mutex);
858 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000859}
Guilherme Polo1972d162009-03-27 21:43:08 +0000860#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000861
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000862
Guido van Rossum18468821994-06-20 07:49:28 +0000863/** Tcl Eval **/
864
Martin v. Löwisffad6332002-11-26 09:28:05 +0000865typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000866 PyObject_HEAD
867 Tcl_Obj *value;
868 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000869} PyTclObject;
870
871staticforward PyTypeObject PyTclObject_Type;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000872#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000873
874static PyObject *
875newPyTclObject(Tcl_Obj *arg)
876{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000877 PyTclObject *self;
878 self = PyObject_New(PyTclObject, &PyTclObject_Type);
879 if (self == NULL)
880 return NULL;
881 Tcl_IncrRefCount(arg);
882 self->value = arg;
883 self->string = NULL;
884 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000885}
886
887static void
888PyTclObject_dealloc(PyTclObject *self)
889{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000890 Tcl_DecrRefCount(self->value);
891 Py_XDECREF(self->string);
892 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000893}
894
895static PyObject *
896PyTclObject_str(PyTclObject *self)
897{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000898 if (self->string && PyString_Check(self->string)) {
899 Py_INCREF(self->string);
900 return self->string;
901 }
902 /* XXX Could cache value if it is an ASCII string. */
903 return PyString_FromString(Tcl_GetString(self->value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000904}
905
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000906static char*
907PyTclObject_TclString(PyObject *self)
908{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000909 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000910}
911
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000912/* Like _str, but create Unicode if necessary. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000913PyDoc_STRVAR(PyTclObject_string__doc__,
Martin v. Löwis39195712003-01-04 00:33:13 +0000914"the string representation of this object, either as string or Unicode");
915
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000916static PyObject *
917PyTclObject_string(PyTclObject *self, void *ignored)
918{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000919 if (!self->string) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200920 int len;
921 char *s = Tcl_GetStringFromObj(self->value, &len);
922 self->string = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000923 if (!self->string)
924 return NULL;
925 }
926 Py_INCREF(self->string);
927 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000928}
929
930#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000931PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
932
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000933static PyObject *
934PyTclObject_unicode(PyTclObject *self, void *ignored)
935{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000936 char *s;
937 int len;
938 if (self->string && PyUnicode_Check(self->string)) {
939 Py_INCREF(self->string);
940 return self->string;
941 }
942 /* XXX Could chache result if it is non-ASCII. */
943 s = Tcl_GetStringFromObj(self->value, &len);
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200944 return unicode_FromTclStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000945}
946#endif
947
Martin v. Löwisffad6332002-11-26 09:28:05 +0000948static PyObject *
949PyTclObject_repr(PyTclObject *self)
950{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000951 char buf[50];
952 PyOS_snprintf(buf, 50, "<%s object at %p>",
953 self->value->typePtr->name, self->value);
954 return PyString_FromString(buf);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000955}
956
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000957static int
958PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
959{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000960 int res;
961 res = strcmp(Tcl_GetString(self->value),
962 Tcl_GetString(other->value));
963 if (res < 0) return -1;
964 if (res > 0) return 1;
965 return 0;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000966}
967
Martin v. Löwis39195712003-01-04 00:33:13 +0000968PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
969
Martin v. Löwisffad6332002-11-26 09:28:05 +0000970static PyObject*
971get_typename(PyTclObject* obj, void* ignored)
972{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000973 return PyString_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000974}
975
Martin v. Löwis39195712003-01-04 00:33:13 +0000976
Martin v. Löwisffad6332002-11-26 09:28:05 +0000977static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000978 {"typename", (getter)get_typename, NULL, get_typename__doc__},
979 {"string", (getter)PyTclObject_string, NULL,
980 PyTclObject_string__doc__},
981 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000982};
983
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000984static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000985#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000986 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
987 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000988#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000989 {0}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000990};
991
Martin v. Löwisffad6332002-11-26 09:28:05 +0000992statichere PyTypeObject PyTclObject_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000993 PyObject_HEAD_INIT(NULL)
994 0, /*ob_size*/
995 "_tkinter.Tcl_Obj", /*tp_name*/
996 sizeof(PyTclObject), /*tp_basicsize*/
997 0, /*tp_itemsize*/
998 /* methods */
999 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
1000 0, /*tp_print*/
1001 0, /*tp_getattr*/
1002 0, /*tp_setattr*/
1003 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
1004 (reprfunc)PyTclObject_repr, /*tp_repr*/
1005 0, /*tp_as_number*/
1006 0, /*tp_as_sequence*/
1007 0, /*tp_as_mapping*/
1008 0, /*tp_hash*/
1009 0, /*tp_call*/
1010 (reprfunc)PyTclObject_str, /*tp_str*/
1011 PyObject_GenericGetAttr,/*tp_getattro*/
1012 0, /*tp_setattro*/
1013 0, /*tp_as_buffer*/
1014 Py_TPFLAGS_DEFAULT, /*tp_flags*/
1015 0, /*tp_doc*/
1016 0, /*tp_traverse*/
1017 0, /*tp_clear*/
1018 0, /*tp_richcompare*/
1019 0, /*tp_weaklistoffset*/
1020 0, /*tp_iter*/
1021 0, /*tp_iternext*/
1022 PyTclObject_methods, /*tp_methods*/
1023 0, /*tp_members*/
1024 PyTclObject_getsetlist, /*tp_getset*/
1025 0, /*tp_base*/
1026 0, /*tp_dict*/
1027 0, /*tp_descr_get*/
1028 0, /*tp_descr_set*/
1029 0, /*tp_dictoffset*/
1030 0, /*tp_init*/
1031 0, /*tp_alloc*/
1032 0, /*tp_new*/
1033 0, /*tp_free*/
1034 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +00001035};
1036
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001037#if PY_SIZE_MAX > INT_MAX
1038#define CHECK_STRING_LENGTH(s) do { \
1039 if (s != NULL && strlen(s) >= INT_MAX) { \
1040 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
1041 return NULL; \
1042 } } while(0)
1043#else
1044#define CHECK_STRING_LENGTH(s)
1045#endif
1046
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001047#ifdef HAVE_LIBTOMMAMTH
1048static Tcl_Obj*
1049asBignumObj(PyObject *value)
1050{
1051 Tcl_Obj *result;
1052 int neg;
1053 PyObject *hexstr;
1054 char *hexchars;
1055 mp_int bigValue;
1056
1057 neg = Py_SIZE(value) < 0;
1058 hexstr = _PyLong_Format(value, 16, 0, 1);
1059 if (hexstr == NULL)
1060 return NULL;
1061 hexchars = PyString_AsString(hexstr);
1062 if (hexchars == NULL) {
1063 Py_DECREF(hexstr);
1064 return NULL;
1065 }
1066 hexchars += neg + 2; /* skip sign and "0x" */
1067 mp_init(&bigValue);
1068 if (mp_read_radix(&bigValue, hexchars, 16) != MP_OKAY) {
1069 mp_clear(&bigValue);
1070 Py_DECREF(hexstr);
1071 PyErr_NoMemory();
1072 return NULL;
1073 }
1074 Py_DECREF(hexstr);
1075 bigValue.sign = neg ? MP_NEG : MP_ZPOS;
1076 result = Tcl_NewBignumObj(&bigValue);
1077 mp_clear(&bigValue);
1078 if (result == NULL) {
1079 PyErr_NoMemory();
1080 return NULL;
1081 }
1082 return result;
1083}
1084#endif
1085
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001086static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001087AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001088{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001089 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001090
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001091 if (PyString_Check(value))
1092 return Tcl_NewStringObj(PyString_AS_STRING(value),
1093 PyString_GET_SIZE(value));
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001094
1095 if (PyBool_Check(value))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001096 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001097
1098 if (PyInt_Check(value))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001099 return Tcl_NewLongObj(PyInt_AS_LONG(value));
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001100
1101 if (PyLong_CheckExact(value)) {
1102 int overflow;
1103 long longValue;
1104#ifdef TCL_WIDE_INT_TYPE
1105 Tcl_WideInt wideValue;
1106#endif
1107 longValue = PyLong_AsLongAndOverflow(value, &overflow);
1108 if (!overflow) {
1109 return Tcl_NewLongObj(longValue);
1110 }
1111 /* If there is an overflow in the long conversion,
1112 fall through to wideInt handling. */
1113#ifdef TCL_WIDE_INT_TYPE
1114 if (_PyLong_AsByteArray((PyLongObject *)value,
1115 (unsigned char *)(void *)&wideValue,
1116 sizeof(wideValue),
1117#ifdef WORDS_BIGENDIAN
1118 0,
1119#else
1120 1,
1121#endif
1122 /* signed */ 1) == 0) {
1123 return Tcl_NewWideIntObj(wideValue);
1124 }
1125 PyErr_Clear();
1126#endif
1127 /* If there is an overflow in the wideInt conversion,
1128 fall through to bignum handling. */
1129#ifdef HAVE_LIBTOMMAMTH
1130 return asBignumObj(value);
1131#endif
1132 /* If there is no wideInt or bignum support,
1133 fall through to default object handling. */
1134 }
1135
1136 if (PyFloat_Check(value))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001137 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001138
1139 if (PyTuple_Check(value)) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001140 Tcl_Obj **argv;
1141 Py_ssize_t size, i;
1142
1143 size = PyTuple_Size(value);
Serhiy Storchaka17c01782014-09-11 10:56:59 +03001144 if (size == 0)
1145 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001146 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
1147 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1148 return NULL;
1149 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001150 argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001151 if(!argv)
1152 return 0;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001153 for (i = 0; i < size; i++)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001154 argv[i] = AsObj(PyTuple_GetItem(value,i));
1155 result = Tcl_NewListObj(PyTuple_Size(value), argv);
1156 ckfree(FREECAST argv);
1157 return result;
1158 }
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001159
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001160#ifdef Py_USING_UNICODE
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001161 if (PyUnicode_Check(value)) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001162 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
1163 Py_ssize_t size = PyUnicode_GET_SIZE(value);
1164 /* This #ifdef assumes that Tcl uses UCS-2.
1165 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001166#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001167 Tcl_UniChar *outbuf = NULL;
1168 Py_ssize_t i;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001169 size_t allocsize;
Serhiy Storchaka17c01782014-09-11 10:56:59 +03001170 if (size == 0)
1171 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001172 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1173 PyErr_SetString(PyExc_OverflowError, "string is too long");
1174 return NULL;
1175 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001176 if (sizeof(Py_UNICODE) == sizeof(Tcl_UniChar))
1177 return Tcl_NewUnicodeObj(inbuf, size);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001178 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001179 if (allocsize >= size)
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001180 outbuf = (Tcl_UniChar*)attemptckalloc(allocsize);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001181 /* Else overflow occurred, and we take the next exit */
1182 if (!outbuf) {
1183 PyErr_NoMemory();
1184 return NULL;
1185 }
1186 for (i = 0; i < size; i++) {
1187 if (inbuf[i] >= 0x10000) {
1188 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka46764482013-02-18 13:00:08 +02001189 PyErr_Format(Tkinter_TclError,
1190 "character U+%x is above the range "
1191 "(U+0000-U+FFFF) allowed by Tcl",
1192 (int)inbuf[i]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001193 ckfree(FREECAST outbuf);
1194 return NULL;
1195 }
1196 outbuf[i] = inbuf[i];
1197 }
1198 result = Tcl_NewUnicodeObj(outbuf, size);
1199 ckfree(FREECAST outbuf);
1200 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001201#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001202 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001203#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001204 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001205#endif
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001206
1207 if(PyTclObject_Check(value)) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001208 Tcl_Obj *v = ((PyTclObject*)value)->value;
1209 Tcl_IncrRefCount(v);
1210 return v;
1211 }
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001212
1213 {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001214 PyObject *v = PyObject_Str(value);
1215 if (!v)
1216 return 0;
1217 result = AsObj(v);
1218 Py_DECREF(v);
1219 return result;
1220 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001221}
1222
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001223static PyObject *
1224fromBoolean(PyObject* tkapp, Tcl_Obj *value)
1225{
1226 int boolValue;
1227 if (Tcl_GetBooleanFromObj(Tkapp_Interp(tkapp), value, &boolValue) == TCL_ERROR)
1228 return Tkinter_Error(tkapp);
1229 return PyBool_FromLong(boolValue);
1230}
1231
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001232#ifdef TCL_WIDE_INT_TYPE
1233static PyObject*
1234fromWideIntObj(PyObject* tkapp, Tcl_Obj *value)
1235{
1236 Tcl_WideInt wideValue;
1237 if (Tcl_GetWideIntFromObj(Tkapp_Interp(tkapp), value, &wideValue) == TCL_OK) {
1238#ifdef HAVE_LONG_LONG
1239 if (sizeof(wideValue) <= SIZEOF_LONG_LONG)
1240 return PyLong_FromLongLong(wideValue);
1241#endif
1242 return _PyLong_FromByteArray((unsigned char *)(void *)&wideValue,
1243 sizeof(wideValue),
1244#ifdef WORDS_BIGENDIAN
1245 0,
1246#else
1247 1,
1248#endif
1249 /* signed */ 1);
1250 }
1251 return NULL;
1252}
1253#endif
1254
1255#ifdef HAVE_LIBTOMMAMTH
1256static PyObject*
1257fromBignumObj(PyObject* tkapp, Tcl_Obj *value)
1258{
1259 mp_int bigValue;
1260 unsigned long numBytes;
1261 unsigned char *bytes;
1262 PyObject *res;
1263
1264 if (Tcl_GetBignumFromObj(Tkapp_Interp(tkapp), value, &bigValue) != TCL_OK)
1265 return Tkinter_Error(tkapp);
1266 numBytes = mp_unsigned_bin_size(&bigValue);
1267 bytes = PyMem_Malloc(numBytes);
1268 if (bytes == NULL) {
1269 mp_clear(&bigValue);
1270 return PyErr_NoMemory();
1271 }
1272 if (mp_to_unsigned_bin_n(&bigValue, bytes,
1273 &numBytes) != MP_OKAY) {
1274 mp_clear(&bigValue);
1275 PyMem_Free(bytes);
1276 return PyErr_NoMemory();
1277 }
1278 res = _PyLong_FromByteArray(bytes, numBytes,
1279 /* big-endian */ 0,
1280 /* unsigned */ 0);
1281 PyMem_Free(bytes);
1282 if (res != NULL && bigValue.sign == MP_NEG) {
1283 PyObject *res2 = PyNumber_Negative(res);
1284 Py_DECREF(res);
1285 res = res2;
1286 }
1287 mp_clear(&bigValue);
1288 return res;
1289}
1290#endif
1291
Martin v. Löwisffad6332002-11-26 09:28:05 +00001292static PyObject*
1293FromObj(PyObject* tkapp, Tcl_Obj *value)
1294{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001295 PyObject *result = NULL;
1296 TkappObject *app = (TkappObject*)tkapp;
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001297 Tcl_Interp *interp = Tkapp_Interp(tkapp);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001298
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001299 if (value->typePtr == NULL) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001300 result = fromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001301 return result;
1302 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001303
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001304 if (value->typePtr == app->BooleanType ||
1305 value->typePtr == app->OldBooleanType) {
1306 return fromBoolean(tkapp, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001307 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001308
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001309 if (value->typePtr == app->ByteArrayType) {
1310 int size;
1311 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1312 return PyString_FromStringAndSize(data, size);
1313 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001314
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001315 if (value->typePtr == app->DoubleType) {
1316 return PyFloat_FromDouble(value->internalRep.doubleValue);
1317 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001318
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001319 if (value->typePtr == app->IntType) {
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001320 long longValue;
1321 if (Tcl_GetLongFromObj(interp, value, &longValue) == TCL_OK)
1322 return PyInt_FromLong(longValue);
1323 /* If there is an error in the long conversion,
1324 fall through to wideInt handling. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001325 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001326
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001327#ifdef TCL_WIDE_INT_TYPE
1328 if (value->typePtr == app->IntType ||
1329 value->typePtr == app->WideIntType) {
1330 result = fromWideIntObj(tkapp, value);
1331 if (result != NULL || PyErr_Occurred())
1332 return result;
1333 Tcl_ResetResult(interp);
1334 /* If there is an error in the wideInt conversion,
1335 fall through to bignum handling. */
1336 }
1337#endif
1338
1339#ifdef HAVE_LIBTOMMAMTH
1340 if (value->typePtr == app->IntType ||
1341 value->typePtr == app->WideIntType ||
1342 value->typePtr == app->BignumType) {
1343 return fromBignumObj(tkapp, value);
1344 }
1345#endif
1346
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001347 if (value->typePtr == app->ListType) {
1348 int size;
1349 int i, status;
1350 PyObject *elem;
1351 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001352
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001353 status = Tcl_ListObjLength(interp, value, &size);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001354 if (status == TCL_ERROR)
1355 return Tkinter_Error(tkapp);
1356 result = PyTuple_New(size);
1357 if (!result)
1358 return NULL;
1359 for (i = 0; i < size; i++) {
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001360 status = Tcl_ListObjIndex(interp, value, i, &tcl_elem);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001361 if (status == TCL_ERROR) {
1362 Py_DECREF(result);
1363 return Tkinter_Error(tkapp);
1364 }
1365 elem = FromObj(tkapp, tcl_elem);
1366 if (!elem) {
1367 Py_DECREF(result);
1368 return NULL;
1369 }
1370 PyTuple_SetItem(result, i, elem);
1371 }
1372 return result;
1373 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001374
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001375 if (value->typePtr == app->ProcBodyType) {
1376 /* fall through: return tcl object. */
1377 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001378
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001379 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001380#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001381#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001382 PyObject *result;
1383 int size;
1384 Tcl_UniChar *input;
1385 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001386
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001387 size = Tcl_GetCharLength(value);
1388 result = PyUnicode_FromUnicode(NULL, size);
1389 if (!result)
1390 return NULL;
1391 input = Tcl_GetUnicode(value);
1392 output = PyUnicode_AS_UNICODE(result);
1393 while (size--)
1394 *output++ = *input++;
1395 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001396#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001397 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1398 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001399#endif
1400#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001401 int size;
1402 char *c;
1403 c = Tcl_GetStringFromObj(value, &size);
1404 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001405#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001406 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001407
Serhiy Storchakacba6b5d2015-04-02 10:35:57 +03001408#if TK_VERSION_HEX >= 0x08050000
1409 if (app->BooleanType == NULL &&
1410 strcmp(value->typePtr->name, "booleanString") == 0) {
1411 /* booleanString type is not registered in Tcl */
1412 app->BooleanType = value->typePtr;
1413 return fromBoolean(tkapp, value);
1414 }
1415#endif
1416
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03001417#ifdef HAVE_LIBTOMMAMTH
1418 if (app->BignumType == NULL &&
1419 strcmp(value->typePtr->name, "bignum") == 0) {
1420 /* bignum type is not registered in Tcl */
1421 app->BignumType = value->typePtr;
1422 return fromBignumObj(tkapp, value);
1423 }
1424#endif
1425
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001426 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001427}
1428
Guilherme Polo1972d162009-03-27 21:43:08 +00001429#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001430/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001431TCL_DECLARE_MUTEX(call_mutex)
1432
1433typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001434 Tcl_Event ev; /* Must be first */
1435 TkappObject *self;
1436 PyObject *args;
1437 int flags;
1438 PyObject **res;
1439 PyObject **exc_type, **exc_value, **exc_tb;
1440 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001441} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001442#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001443
1444void
1445Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001446{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001447 int i;
1448 for (i = 0; i < objc; i++)
1449 Tcl_DecrRefCount(objv[i]);
1450 if (objv != objStore)
1451 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001452}
Guido van Rossum18468821994-06-20 07:49:28 +00001453
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001454/* Convert Python objects to Tcl objects. This must happen in the
1455 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001456
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001457static Tcl_Obj**
1458Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1459{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001460 Tcl_Obj **objv = objStore;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001461 Py_ssize_t objc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001462 if (args == NULL)
1463 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001464
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001465 else if (!PyTuple_Check(args)) {
1466 objv[0] = AsObj(args);
1467 if (objv[0] == 0)
1468 goto finally;
1469 objc = 1;
1470 Tcl_IncrRefCount(objv[0]);
1471 }
1472 else {
1473 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001474
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001475 if (objc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001476 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1477 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1478 return NULL;
1479 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001480 objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001481 if (objv == NULL) {
1482 PyErr_NoMemory();
1483 objc = 0;
1484 goto finally;
1485 }
1486 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001487
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001488 for (i = 0; i < objc; i++) {
1489 PyObject *v = PyTuple_GetItem(args, i);
1490 if (v == Py_None) {
1491 objc = i;
1492 break;
1493 }
1494 objv[i] = AsObj(v);
1495 if (!objv[i]) {
1496 /* Reset objc, so it attempts to clear
1497 objects only up to i. */
1498 objc = i;
1499 goto finally;
1500 }
1501 Tcl_IncrRefCount(objv[i]);
1502 }
1503 }
1504 *pobjc = objc;
1505 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001506finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001507 Tkapp_CallDeallocArgs(objv, objStore, objc);
1508 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001509}
Guido van Rossum212643f1998-04-29 16:22:14 +00001510
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001511/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001512
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001513static PyObject*
1514Tkapp_CallResult(TkappObject *self)
1515{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001516 PyObject *res = NULL;
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001517 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001518 if(self->wantobjects) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001519 /* Not sure whether the IncrRef is necessary, but something
1520 may overwrite the interpreter result while we are
1521 converting it. */
1522 Tcl_IncrRefCount(value);
1523 res = FromObj((PyObject*)self, value);
1524 Tcl_DecrRefCount(value);
1525 } else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001526 int len;
1527 const char *s = Tcl_GetStringFromObj(value, &len);
1528 res = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001529 }
1530 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001531}
Guido van Rossum632de272000-03-29 00:19:50 +00001532
Guilherme Polo1972d162009-03-27 21:43:08 +00001533#ifdef WITH_THREAD
1534
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001535/* Tkapp_CallProc is the event procedure that is executed in the context of
1536 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1537 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001538
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001539static int
1540Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1541{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001542 Tcl_Obj *objStore[ARGSZ];
1543 Tcl_Obj **objv;
1544 int objc;
1545 int i;
1546 ENTER_PYTHON
1547 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1548 if (!objv) {
1549 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1550 *(e->res) = NULL;
1551 }
1552 LEAVE_PYTHON
1553 if (!objv)
1554 goto done;
1555 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1556 ENTER_PYTHON
1557 if (i == TCL_ERROR) {
1558 *(e->res) = NULL;
1559 *(e->exc_type) = NULL;
1560 *(e->exc_tb) = NULL;
1561 *(e->exc_value) = PyObject_CallFunction(
1562 Tkinter_TclError, "s",
1563 Tcl_GetStringResult(e->self->interp));
1564 }
1565 else {
1566 *(e->res) = Tkapp_CallResult(e->self);
1567 }
1568 LEAVE_PYTHON
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001569
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001570 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001571done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001572 /* Wake up calling thread. */
1573 Tcl_MutexLock(&call_mutex);
1574 Tcl_ConditionNotify(e->done);
1575 Tcl_MutexUnlock(&call_mutex);
1576 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001577}
1578
Guilherme Polo1972d162009-03-27 21:43:08 +00001579#endif
1580
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001581/* This is the main entry point for calling a Tcl command.
1582 It supports three cases, with regard to threading:
1583 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1584 the context of the calling thread.
1585 2. Tcl is threaded, caller of the command is in the interpreter thread:
1586 Execute the command in the calling thread. Since the Tcl lock will
1587 not be used, we can merge that with case 1.
1588 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1589 the interpreter thread. Allocation of Tcl objects needs to occur in the
1590 interpreter thread, so we ship the PyObject* args to the target thread,
1591 and perform processing there. */
1592
1593static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001594Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001595{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001596 Tcl_Obj *objStore[ARGSZ];
1597 Tcl_Obj **objv = NULL;
1598 int objc, i;
1599 PyObject *res = NULL;
1600 TkappObject *self = (TkappObject*)selfptr;
1601 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001602
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001603 /* If args is a single tuple, replace with contents of tuple */
1604 if (1 == PyTuple_Size(args)){
1605 PyObject* item = PyTuple_GetItem(args, 0);
1606 if (PyTuple_Check(item))
1607 args = item;
1608 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001609#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001610 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1611 /* We cannot call the command directly. Instead, we must
1612 marshal the parameters to the interpreter thread. */
1613 Tkapp_CallEvent *ev;
1614 Tcl_Condition cond = NULL;
1615 PyObject *exc_type, *exc_value, *exc_tb;
1616 if (!WaitForMainloop(self))
1617 return NULL;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001618 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1619 if (ev == NULL) {
1620 PyErr_NoMemory();
1621 return NULL;
1622 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001623 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1624 ev->self = self;
1625 ev->args = args;
1626 ev->res = &res;
1627 ev->exc_type = &exc_type;
1628 ev->exc_value = &exc_value;
1629 ev->exc_tb = &exc_tb;
1630 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001631
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001632 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001633
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001634 if (res == NULL) {
1635 if (exc_type)
1636 PyErr_Restore(exc_type, exc_value, exc_tb);
1637 else
1638 PyErr_SetObject(Tkinter_TclError, exc_value);
1639 }
1640 Tcl_ConditionFinalize(&cond);
1641 }
1642 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001643#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001644 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001645
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001646 objv = Tkapp_CallArgs(args, objStore, &objc);
1647 if (!objv)
1648 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001649
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001650 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001651
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001652 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001653
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001654 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001655
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001656 if (i == TCL_ERROR)
1657 Tkinter_Error(selfptr);
1658 else
1659 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001660
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001661 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001662
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001663 Tkapp_CallDeallocArgs(objv, objStore, objc);
1664 }
1665 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001666}
1667
1668
1669static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001670Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001671{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001672 /* Could do the same here as for Tkapp_Call(), but this is not used
1673 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1674 way for the user to do what all its Global* variants do (save and
1675 reset the scope pointer, call the local version, restore the saved
1676 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001677
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001678 char *cmd;
1679 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001680
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001681 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001682
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001683 cmd = Merge(args);
1684 if (cmd) {
1685 int err;
1686 ENTER_TCL
1687 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1688 ENTER_OVERLAP
1689 if (err == TCL_ERROR)
1690 res = Tkinter_Error(self);
1691 else
1692 res = PyString_FromString(Tkapp_Result(self));
1693 LEAVE_OVERLAP_TCL
1694 ckfree(cmd);
1695 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001696
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001697 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001698}
1699
1700static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001701Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001702{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001703 char *script;
1704 PyObject *res = NULL;
1705 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001706
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001707 if (!PyArg_ParseTuple(args, "s:eval", &script))
1708 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001709
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001710 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001711 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001712
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001713 ENTER_TCL
1714 err = Tcl_Eval(Tkapp_Interp(self), script);
1715 ENTER_OVERLAP
1716 if (err == TCL_ERROR)
1717 res = Tkinter_Error(self);
1718 else
1719 res = PyString_FromString(Tkapp_Result(self));
1720 LEAVE_OVERLAP_TCL
1721 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001722}
1723
1724static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001725Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001726{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001727 char *script;
1728 PyObject *res = NULL;
1729 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001730
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001731 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1732 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001733
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001734 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001735
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001736 ENTER_TCL
1737 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1738 ENTER_OVERLAP
1739 if (err == TCL_ERROR)
1740 res = Tkinter_Error(self);
1741 else
1742 res = PyString_FromString(Tkapp_Result(self));
1743 LEAVE_OVERLAP_TCL
1744 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001745}
1746
1747static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001748Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001749{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001750 char *fileName;
1751 PyObject *res = NULL;
1752 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001753
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001754 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1755 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001756
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001757 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001758 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001759
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001760 ENTER_TCL
1761 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1762 ENTER_OVERLAP
1763 if (err == TCL_ERROR)
1764 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001765
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001766 else
1767 res = PyString_FromString(Tkapp_Result(self));
1768 LEAVE_OVERLAP_TCL
1769 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001770}
1771
1772static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001773Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001774{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001775 char *script;
1776 PyObject *res = NULL;
1777 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001778
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001779 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001780 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001781
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001782 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001783 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001784
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001785 ENTER_TCL
1786 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1787 ENTER_OVERLAP
1788 if (err == TCL_ERROR)
1789 res = Tkinter_Error(self);
1790 else
1791 res = PyString_FromString(Tkapp_Result(self));
1792 LEAVE_OVERLAP_TCL
1793 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001794}
1795
1796static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001797Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001798{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001799 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001800
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001801 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1802 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001803 CHECK_STRING_LENGTH(msg);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001804 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001805
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001806 ENTER_TCL
1807 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1808 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001809
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001810 Py_INCREF(Py_None);
1811 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001812}
1813
Barry Warsawfa701a81997-01-16 00:15:11 +00001814
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001815
Guido van Rossum18468821994-06-20 07:49:28 +00001816/** Tcl Variable **/
1817
Guilherme Polo1972d162009-03-27 21:43:08 +00001818typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1819
1820#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001821TCL_DECLARE_MUTEX(var_mutex)
1822
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001823typedef struct VarEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001824 Tcl_Event ev; /* must be first */
1825 PyObject *self;
1826 PyObject *args;
1827 int flags;
1828 EventFunc func;
1829 PyObject **res;
1830 PyObject **exc_type;
1831 PyObject **exc_val;
1832 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001833} VarEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001834#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001835
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001836static int
1837varname_converter(PyObject *in, void *_out)
1838{
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001839 char *s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001840 char **out = (char**)_out;
1841 if (PyString_Check(in)) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001842 if (PyString_Size(in) > INT_MAX) {
1843 PyErr_SetString(PyExc_OverflowError, "string is too long");
1844 return 0;
1845 }
1846 s = PyString_AsString(in);
1847 if (strlen(s) != PyString_Size(in)) {
1848 PyErr_SetString(PyExc_ValueError, "null character in string");
1849 return 0;
1850 }
1851 *out = s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001852 return 1;
1853 }
1854 if (PyTclObject_Check(in)) {
1855 *out = PyTclObject_TclString(in);
1856 return 1;
1857 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001858 PyErr_Format(PyExc_TypeError,
1859 "must be str or Tcl_Obj, not %.50s",
1860 in->ob_type->tp_name);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001861 return 0;
1862}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001863
Guilherme Polo1972d162009-03-27 21:43:08 +00001864#ifdef WITH_THREAD
1865
Martin v. Löwis111c1802008-06-13 07:47:47 +00001866static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001867var_perform(VarEvent *ev)
1868{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001869 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1870 if (!*(ev->res)) {
1871 PyObject *exc, *val, *tb;
1872 PyErr_Fetch(&exc, &val, &tb);
1873 PyErr_NormalizeException(&exc, &val, &tb);
1874 *(ev->exc_type) = exc;
1875 *(ev->exc_val) = val;
1876 Py_DECREF(tb);
1877 }
1878
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001879}
1880
1881static int
1882var_proc(VarEvent* ev, int flags)
1883{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001884 ENTER_PYTHON
1885 var_perform(ev);
1886 Tcl_MutexLock(&var_mutex);
1887 Tcl_ConditionNotify(ev->cond);
1888 Tcl_MutexUnlock(&var_mutex);
1889 LEAVE_PYTHON
1890 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001891}
1892
Guilherme Polo1972d162009-03-27 21:43:08 +00001893#endif
1894
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001895static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001896var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001897{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001898#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001899 TkappObject *self = (TkappObject*)selfptr;
1900 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1901 TkappObject *self = (TkappObject*)selfptr;
1902 VarEvent *ev;
1903 PyObject *res, *exc_type, *exc_val;
1904 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001905
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001906 /* The current thread is not the interpreter thread. Marshal
1907 the call to the interpreter thread, then wait for
1908 completion. */
1909 if (!WaitForMainloop(self))
1910 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001911
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001912 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1913 if (ev == NULL) {
1914 PyErr_NoMemory();
1915 return NULL;
1916 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001917 ev->self = selfptr;
1918 ev->args = args;
1919 ev->flags = flags;
1920 ev->func = func;
1921 ev->res = &res;
1922 ev->exc_type = &exc_type;
1923 ev->exc_val = &exc_val;
1924 ev->cond = &cond;
1925 ev->ev.proc = (Tcl_EventProc*)var_proc;
1926 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1927 Tcl_ConditionFinalize(&cond);
1928 if (!res) {
1929 PyErr_SetObject(exc_type, exc_val);
1930 Py_DECREF(exc_type);
1931 Py_DECREF(exc_val);
1932 return NULL;
1933 }
1934 return res;
1935 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001936#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001937 /* Tcl is not threaded, or this is the interpreter thread. */
1938 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001939}
1940
Guido van Rossum18468821994-06-20 07:49:28 +00001941static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001942SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001943{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001944 char *name1, *name2;
1945 PyObject *newValue;
1946 PyObject *res = NULL;
1947 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001948
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001949 switch (PyTuple_GET_SIZE(args)) {
1950 case 2:
1951 if (!PyArg_ParseTuple(args, "O&O:setvar",
1952 varname_converter, &name1, &newValue))
1953 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001954 /* XXX Acquire tcl lock??? */
1955 newval = AsObj(newValue);
1956 if (newval == NULL)
1957 return NULL;
1958 ENTER_TCL
1959 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1960 newval, flags);
1961 ENTER_OVERLAP
1962 if (!ok)
1963 Tkinter_Error(self);
1964 else {
1965 res = Py_None;
1966 Py_INCREF(res);
1967 }
1968 LEAVE_OVERLAP_TCL
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001969 break;
1970 case 3:
1971 if (!PyArg_ParseTuple(args, "ssO:setvar",
1972 &name1, &name2, &newValue))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001973 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001974 CHECK_STRING_LENGTH(name1);
1975 CHECK_STRING_LENGTH(name2);
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001976 /* XXX must hold tcl lock already??? */
1977 newval = AsObj(newValue);
1978 ENTER_TCL
1979 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1980 ENTER_OVERLAP
1981 if (!ok)
1982 Tkinter_Error(self);
1983 else {
1984 res = Py_None;
1985 Py_INCREF(res);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001986 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001987 LEAVE_OVERLAP_TCL
1988 break;
1989 default:
1990 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1991 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001992 }
1993 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001994}
1995
1996static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001997Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001998{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001999 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00002000}
2001
2002static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002003Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002004{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002005 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00002006}
2007
Barry Warsawfa701a81997-01-16 00:15:11 +00002008
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002009
Guido van Rossum18468821994-06-20 07:49:28 +00002010static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002011GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002012{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002013 char *name1, *name2=NULL;
2014 PyObject *res = NULL;
2015 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00002016
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002017 if (!PyArg_ParseTuple(args, "O&|s:getvar",
2018 varname_converter, &name1, &name2))
2019 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002020
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002021 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002022 ENTER_TCL
2023 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
2024 ENTER_OVERLAP
2025 if (tres == NULL) {
2026 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
2027 } else {
2028 if (((TkappObject*)self)->wantobjects) {
2029 res = FromObj(self, tres);
2030 }
2031 else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002032 int len;
2033 char *s = Tcl_GetStringFromObj(tres, &len);
2034 res = PyString_FromStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002035 }
2036 }
2037 LEAVE_OVERLAP_TCL
2038 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002039}
2040
2041static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002042Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002043{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002044 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00002045}
2046
2047static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002048Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002049{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002050 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00002051}
2052
Barry Warsawfa701a81997-01-16 00:15:11 +00002053
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002054
Guido van Rossum18468821994-06-20 07:49:28 +00002055static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002056UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002057{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002058 char *name1, *name2=NULL;
2059 int code;
2060 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002061
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002062 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
2063 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00002064
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002065 CHECK_STRING_LENGTH(name1);
2066 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002067 ENTER_TCL
2068 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
2069 ENTER_OVERLAP
2070 if (code == TCL_ERROR)
2071 res = Tkinter_Error(self);
2072 else {
2073 Py_INCREF(Py_None);
2074 res = Py_None;
2075 }
2076 LEAVE_OVERLAP_TCL
2077 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002078}
2079
2080static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002081Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002082{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002083 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00002084}
2085
2086static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002087Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002088{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002089 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00002090}
2091
Barry Warsawfa701a81997-01-16 00:15:11 +00002092
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002093
Guido van Rossum18468821994-06-20 07:49:28 +00002094/** Tcl to Python **/
2095
2096static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002097Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002098{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002099 char *s;
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03002100#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH)
2101 Tcl_Obj *value;
2102 PyObject *result;
2103#else
2104 int intValue;
2105#endif
Guido van Rossum18468821994-06-20 07:49:28 +00002106
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002107 if (PyTuple_Size(args) == 1) {
2108 PyObject* o = PyTuple_GetItem(args, 0);
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03002109 if (PyInt_Check(o) || PyLong_Check(o)) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002110 Py_INCREF(o);
2111 return o;
2112 }
2113 }
2114 if (!PyArg_ParseTuple(args, "s:getint", &s))
2115 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03002116 CHECK_STRING_LENGTH(s);
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03002117#if defined(TCL_WIDE_INT_TYPE) || defined(HAVE_LIBTOMMAMTH)
2118 value = Tcl_NewStringObj(s, -1);
2119 if (value == NULL)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002120 return Tkinter_Error(self);
Serhiy Storchakac77c5b52015-04-02 18:46:30 +03002121 /* Don't use Tcl_GetInt() because it returns ambiguous result for value
2122 in ranges -2**32..-2**31-1 and 2**31..2**32-1 (on 32-bit platform).
2123
2124 Prefer bignum because Tcl_GetWideIntFromObj returns ambiguous result for
2125 value in ranges -2**64..-2**63-1 and 2**63..2**64-1 (on 32-bit platform).
2126 */
2127#ifdef HAVE_LIBTOMMAMTH
2128 result = fromBignumObj(self, value);
2129#else
2130 result = fromWideIntObj(self, value);
2131#endif
2132 Tcl_DecrRefCount(value);
2133 if (result != NULL)
2134 return PyNumber_Int(result);
2135 if (PyErr_Occurred())
2136 return NULL;
2137#else
2138 if (Tcl_GetInt(Tkapp_Interp(self), s, &intValue) == TCL_OK)
2139 return PyInt_FromLong(intValue);
2140#endif
2141 return Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00002142}
2143
2144static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002145Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002146{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002147 char *s;
2148 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00002149
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002150 if (PyTuple_Size(args) == 1) {
2151 PyObject *o = PyTuple_GetItem(args, 0);
2152 if (PyFloat_Check(o)) {
2153 Py_INCREF(o);
2154 return o;
2155 }
2156 }
2157 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
2158 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03002159 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002160 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
2161 return Tkinter_Error(self);
2162 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00002163}
2164
2165static PyObject *
Serhiy Storchakaf29bc702015-04-04 12:42:25 +03002166Tkapp_GetBoolean(PyObject *self, PyObject *arg)
Guido van Rossum18468821994-06-20 07:49:28 +00002167{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002168 char *s;
2169 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002170
Serhiy Storchakaf29bc702015-04-04 12:42:25 +03002171 if (PyInt_Check(arg)) /* int or bool */
2172 return PyBool_FromLong(PyInt_AS_LONG(arg));
2173
2174 if (PyLong_Check(arg))
2175 return PyBool_FromLong(Py_SIZE(arg) != 0);
2176
2177 if (PyTclObject_Check(arg)) {
2178 if (Tcl_GetBooleanFromObj(Tkapp_Interp(self),
2179 ((PyTclObject*)arg)->value,
2180 &v) == TCL_ERROR)
2181 return Tkinter_Error(self);
2182 return PyBool_FromLong(v);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002183 }
Serhiy Storchakaf29bc702015-04-04 12:42:25 +03002184
2185 if (!PyArg_Parse(arg, "s:getboolean", &s))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002186 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03002187 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002188 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
2189 return Tkinter_Error(self);
2190 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002191}
2192
2193static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002194Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002195{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002196 char *s;
2197 PyObject *res = NULL;
2198 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002199
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002200 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
2201 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002202
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002203 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002204 CHECK_TCL_APPARTMENT;
2205
2206 ENTER_TCL
2207 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2208 ENTER_OVERLAP
2209 if (retval == TCL_ERROR)
2210 res = Tkinter_Error(self);
2211 else
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002212 res = PyString_FromString(Tkapp_Result(self));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002213 LEAVE_OVERLAP_TCL
2214 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002215}
2216
2217static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002218Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002219{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002220 char *s;
2221 PyObject *res = NULL;
2222 int retval;
2223 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002224
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002225 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
2226 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002227
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002228 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002229 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002230
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002231 ENTER_TCL
2232 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2233 ENTER_OVERLAP
2234 if (retval == TCL_ERROR)
2235 res = Tkinter_Error(self);
2236 else
2237 res = Py_BuildValue("l", v);
2238 LEAVE_OVERLAP_TCL
2239 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002240}
2241
2242static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002243Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002244{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002245 char *s;
2246 PyObject *res = NULL;
2247 double v;
2248 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002249
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002250 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2251 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002252 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002253 CHECK_TCL_APPARTMENT;
2254 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2255 ENTER_TCL
2256 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2257 ENTER_OVERLAP
2258 PyFPE_END_PROTECT(retval)
2259 if (retval == TCL_ERROR)
2260 res = Tkinter_Error(self);
2261 else
2262 res = Py_BuildValue("d", v);
2263 LEAVE_OVERLAP_TCL
2264 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002265}
2266
2267static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002268Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002269{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002270 char *s;
2271 PyObject *res = NULL;
2272 int retval;
2273 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002274
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002275 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2276 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002277 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002278 CHECK_TCL_APPARTMENT;
2279 ENTER_TCL
2280 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2281 ENTER_OVERLAP
2282 if (retval == TCL_ERROR)
2283 res = Tkinter_Error(self);
2284 else
2285 res = Py_BuildValue("i", v);
2286 LEAVE_OVERLAP_TCL
2287 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002288}
2289
Barry Warsawfa701a81997-01-16 00:15:11 +00002290
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002291
Guido van Rossum18468821994-06-20 07:49:28 +00002292static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002293Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002294{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002295 char *list;
2296 int argc;
2297 char **argv;
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002298 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002299 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002300
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002301 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2302 return NULL;
2303 if (PyTclObject_Check(arg)) {
2304 int objc;
2305 Tcl_Obj **objv;
2306 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2307 ((PyTclObject*)arg)->value,
2308 &objc, &objv) == TCL_ERROR) {
2309 return Tkinter_Error(self);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002310 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002311 if (!(v = PyTuple_New(objc)))
2312 return NULL;
2313 for (i = 0; i < objc; i++) {
2314 PyObject *s = FromObj(self, objv[i]);
2315 if (!s || PyTuple_SetItem(v, i, s)) {
2316 Py_DECREF(v);
2317 return NULL;
2318 }
2319 }
2320 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002321 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002322 if (PyTuple_Check(arg)) {
2323 Py_INCREF(arg);
2324 return arg;
2325 }
2326
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002327 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2328 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002329
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002330 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002331 if (Tcl_SplitList(Tkapp_Interp(self), list,
2332 &argc, &argv) == TCL_ERROR) {
2333 PyMem_Free(list);
2334 return Tkinter_Error(self);
2335 }
Guido van Rossum18468821994-06-20 07:49:28 +00002336
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002337 if (!(v = PyTuple_New(argc)))
2338 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002339
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002340 for (i = 0; i < argc; i++) {
2341 PyObject *s = PyString_FromString(argv[i]);
2342 if (!s || PyTuple_SetItem(v, i, s)) {
2343 Py_DECREF(v);
2344 v = NULL;
2345 goto finally;
2346 }
2347 }
Guido van Rossum18468821994-06-20 07:49:28 +00002348
Barry Warsawfa701a81997-01-16 00:15:11 +00002349 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002350 ckfree(FREECAST argv);
2351 PyMem_Free(list);
2352 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002353}
2354
2355static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002356Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002357{
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002358 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002359 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002360
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002361 if (!PyArg_ParseTuple(args, "O:split", &arg))
2362 return NULL;
2363 if (PyTclObject_Check(arg)) {
2364 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2365 int objc;
2366 Tcl_Obj **objv;
2367 int i;
2368 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2369 &objc, &objv) == TCL_ERROR) {
2370 return FromObj(self, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002371 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002372 if (objc == 0)
2373 return PyString_FromString("");
2374 if (objc == 1)
2375 return FromObj(self, objv[0]);
2376 if (!(v = PyTuple_New(objc)))
2377 return NULL;
2378 for (i = 0; i < objc; i++) {
2379 PyObject *s = FromObj(self, objv[i]);
2380 if (!s || PyTuple_SetItem(v, i, s)) {
2381 Py_DECREF(v);
2382 return NULL;
2383 }
2384 }
2385 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002386 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002387 if (PyTuple_Check(arg))
2388 return SplitObj(arg);
2389
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002390 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2391 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002392 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002393 v = Split(list);
2394 PyMem_Free(list);
2395 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002396}
2397
2398static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002399Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002400{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002401 char *s = Merge(args);
2402 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002403
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002404 if (s) {
2405 res = PyString_FromString(s);
2406 ckfree(s);
2407 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002408
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002409 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002410}
2411
Barry Warsawfa701a81997-01-16 00:15:11 +00002412
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002413
Guido van Rossum18468821994-06-20 07:49:28 +00002414/** Tcl Command **/
2415
Guido van Rossum00d93061998-05-28 23:06:38 +00002416/* Client data struct */
2417typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002418 PyObject *self;
2419 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002420} PythonCmd_ClientData;
2421
2422static int
Fred Drake509d79a2000-07-08 04:04:38 +00002423PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002424{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002425 errorInCmd = 1;
2426 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2427 LEAVE_PYTHON
2428 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002429}
2430
Guido van Rossum18468821994-06-20 07:49:28 +00002431/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002432 * function or method.
2433 */
Guido van Rossum18468821994-06-20 07:49:28 +00002434static int
Fred Drake509d79a2000-07-08 04:04:38 +00002435PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002436{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002437 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2438 PyObject *func, *arg, *res;
2439 int i, rv;
2440 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002441
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002442 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002443
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002444 /* TBD: no error checking here since we know, via the
2445 * Tkapp_CreateCommand() that the client data is a two-tuple
2446 */
2447 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002448
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002449 /* Create argument list (argv1, ..., argvN) */
2450 if (!(arg = PyTuple_New(argc - 1)))
2451 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002452
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002453 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002454 PyObject *s = fromTclString(argv[i + 1]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002455 if (!s || PyTuple_SetItem(arg, i, s)) {
2456 Py_DECREF(arg);
2457 return PythonCmd_Error(interp);
2458 }
2459 }
2460 res = PyEval_CallObject(func, arg);
2461 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002462
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002463 if (res == NULL)
2464 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002465
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002466 obj_res = AsObj(res);
2467 if (obj_res == NULL) {
2468 Py_DECREF(res);
2469 return PythonCmd_Error(interp);
2470 }
2471 else {
2472 Tcl_SetObjResult(interp, obj_res);
2473 rv = TCL_OK;
2474 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002475
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002476 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002477
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002478 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002479
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002480 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002481}
2482
2483static void
Fred Drake509d79a2000-07-08 04:04:38 +00002484PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002485{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002486 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002487
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002488 ENTER_PYTHON
2489 Py_XDECREF(data->self);
2490 Py_XDECREF(data->func);
2491 PyMem_DEL(data);
2492 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002493}
2494
Barry Warsawfa701a81997-01-16 00:15:11 +00002495
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002496
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002497
Guilherme Polo1972d162009-03-27 21:43:08 +00002498#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002499TCL_DECLARE_MUTEX(command_mutex)
2500
2501typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002502 Tcl_Event ev;
2503 Tcl_Interp* interp;
2504 char *name;
2505 int create;
2506 int *status;
2507 ClientData *data;
2508 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002509} CommandEvent;
2510
2511static int
2512Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002513{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002514 if (ev->create)
2515 *ev->status = Tcl_CreateCommand(
2516 ev->interp, ev->name, PythonCmd,
2517 ev->data, PythonCmdDelete) == NULL;
2518 else
2519 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2520 Tcl_MutexLock(&command_mutex);
2521 Tcl_ConditionNotify(ev->done);
2522 Tcl_MutexUnlock(&command_mutex);
2523 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002524}
Guilherme Polo1972d162009-03-27 21:43:08 +00002525#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002526
2527static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002528Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002529{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002530 TkappObject *self = (TkappObject*)selfptr;
2531 PythonCmd_ClientData *data;
2532 char *cmdName;
2533 PyObject *func;
2534 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002535
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002536 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2537 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002538 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002539 if (!PyCallable_Check(func)) {
2540 PyErr_SetString(PyExc_TypeError, "command not callable");
2541 return NULL;
2542 }
Guido van Rossum18468821994-06-20 07:49:28 +00002543
Martin v. Löwisa9656492003-03-30 08:44:58 +00002544#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002545 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2546 !WaitForMainloop(self))
2547 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002548#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002549
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002550 data = PyMem_NEW(PythonCmd_ClientData, 1);
2551 if (!data)
2552 return PyErr_NoMemory();
2553 Py_INCREF(self);
2554 Py_INCREF(func);
2555 data->self = selfptr;
2556 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002557
2558#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002559 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2560 Tcl_Condition cond = NULL;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03002561 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2562 if (ev == NULL) {
2563 PyErr_NoMemory();
2564 PyMem_DEL(data);
2565 return NULL;
2566 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002567 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2568 ev->interp = self->interp;
2569 ev->create = 1;
2570 ev->name = cmdName;
2571 ev->data = (ClientData)data;
2572 ev->status = &err;
2573 ev->done = &cond;
2574 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2575 Tcl_ConditionFinalize(&cond);
2576 }
2577 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002578#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002579 {
2580 ENTER_TCL
2581 err = Tcl_CreateCommand(
2582 Tkapp_Interp(self), cmdName, PythonCmd,
2583 (ClientData)data, PythonCmdDelete) == NULL;
2584 LEAVE_TCL
2585 }
2586 if (err) {
2587 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2588 PyMem_DEL(data);
2589 return NULL;
2590 }
Guido van Rossum18468821994-06-20 07:49:28 +00002591
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002592 Py_INCREF(Py_None);
2593 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002594}
2595
Barry Warsawfa701a81997-01-16 00:15:11 +00002596
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002597
Guido van Rossum18468821994-06-20 07:49:28 +00002598static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002599Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002600{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002601 TkappObject *self = (TkappObject*)selfptr;
2602 char *cmdName;
2603 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002604
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002605 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2606 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002607 CHECK_STRING_LENGTH(cmdName);
Guilherme Polo1972d162009-03-27 21:43:08 +00002608
2609#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002610 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2611 Tcl_Condition cond = NULL;
2612 CommandEvent *ev;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03002613 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2614 if (ev == NULL) {
2615 PyErr_NoMemory();
2616 return NULL;
2617 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002618 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2619 ev->interp = self->interp;
2620 ev->create = 0;
2621 ev->name = cmdName;
2622 ev->status = &err;
2623 ev->done = &cond;
2624 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2625 &command_mutex);
2626 Tcl_ConditionFinalize(&cond);
2627 }
2628 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002629#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002630 {
2631 ENTER_TCL
2632 err = Tcl_DeleteCommand(self->interp, cmdName);
2633 LEAVE_TCL
2634 }
2635 if (err == -1) {
2636 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2637 return NULL;
2638 }
2639 Py_INCREF(Py_None);
2640 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002641}
2642
Barry Warsawfa701a81997-01-16 00:15:11 +00002643
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002644
Guido van Rossum00d93061998-05-28 23:06:38 +00002645#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002646/** File Handler **/
2647
Guido van Rossum00d93061998-05-28 23:06:38 +00002648typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002649 PyObject *func;
2650 PyObject *file;
2651 int id;
2652 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002653} FileHandler_ClientData;
2654
2655static FileHandler_ClientData *HeadFHCD;
2656
2657static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002658NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002659{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002660 FileHandler_ClientData *p;
2661 p = PyMem_NEW(FileHandler_ClientData, 1);
2662 if (p != NULL) {
2663 Py_XINCREF(func);
2664 Py_XINCREF(file);
2665 p->func = func;
2666 p->file = file;
2667 p->id = id;
2668 p->next = HeadFHCD;
2669 HeadFHCD = p;
2670 }
2671 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002672}
2673
2674static void
Fred Drake509d79a2000-07-08 04:04:38 +00002675DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002676{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002677 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002678
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002679 pp = &HeadFHCD;
2680 while ((p = *pp) != NULL) {
2681 if (p->id == id) {
2682 *pp = p->next;
2683 Py_XDECREF(p->func);
2684 Py_XDECREF(p->file);
2685 PyMem_DEL(p);
2686 }
2687 else
2688 pp = &p->next;
2689 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002690}
2691
Guido van Rossuma597dde1995-01-10 20:56:29 +00002692static void
Fred Drake509d79a2000-07-08 04:04:38 +00002693FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002694{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002695 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2696 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002697
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002698 ENTER_PYTHON
2699 func = data->func;
2700 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002701
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002702 arg = Py_BuildValue("(Oi)", file, (long) mask);
2703 res = PyEval_CallObject(func, arg);
2704 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002705
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002706 if (res == NULL) {
2707 errorInCmd = 1;
2708 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2709 }
2710 Py_XDECREF(res);
2711 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002712}
2713
Guido van Rossum18468821994-06-20 07:49:28 +00002714static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002715Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2716 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002717{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002718 FileHandler_ClientData *data;
2719 PyObject *file, *func;
2720 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002721
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002722 if (!self && Py_Py3kWarningFlag) {
2723 if (PyErr_Warn(PyExc_DeprecationWarning,
2724 "_tkinter.createfilehandler is gone in 3.x") < 0)
2725 return NULL;
2726 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002727
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002728 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2729 &file, &mask, &func))
2730 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002731
Martin v. Löwisa9656492003-03-30 08:44:58 +00002732#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002733 if (!self && !tcl_lock) {
2734 /* We don't have the Tcl lock since Tcl is threaded. */
2735 PyErr_SetString(PyExc_RuntimeError,
2736 "_tkinter.createfilehandler not supported "
2737 "for threaded Tcl");
2738 return NULL;
2739 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002740#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002741
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002742 if (self) {
2743 CHECK_TCL_APPARTMENT;
2744 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002745
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002746 tfile = PyObject_AsFileDescriptor(file);
2747 if (tfile < 0)
2748 return NULL;
2749 if (!PyCallable_Check(func)) {
2750 PyErr_SetString(PyExc_TypeError, "bad argument list");
2751 return NULL;
2752 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002753
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002754 data = NewFHCD(func, file, tfile);
2755 if (data == NULL)
2756 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002757
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002758 /* Ought to check for null Tcl_File object... */
2759 ENTER_TCL
2760 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2761 LEAVE_TCL
2762 Py_INCREF(Py_None);
2763 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002764}
2765
2766static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002767Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002768{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002769 PyObject *file;
2770 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002771
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002772 if (!self && Py_Py3kWarningFlag) {
2773 if (PyErr_Warn(PyExc_DeprecationWarning,
2774 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2775 return NULL;
2776 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002777
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002778 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2779 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002780
Martin v. Löwisa9656492003-03-30 08:44:58 +00002781#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002782 if (!self && !tcl_lock) {
2783 /* We don't have the Tcl lock since Tcl is threaded. */
2784 PyErr_SetString(PyExc_RuntimeError,
2785 "_tkinter.deletefilehandler not supported "
2786 "for threaded Tcl");
2787 return NULL;
2788 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002789#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002790
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002791 if (self) {
2792 CHECK_TCL_APPARTMENT;
2793 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002794
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002795 tfile = PyObject_AsFileDescriptor(file);
2796 if (tfile < 0)
2797 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002798
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002799 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002800
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002801 /* Ought to check for null Tcl_File object... */
2802 ENTER_TCL
2803 Tcl_DeleteFileHandler(tfile);
2804 LEAVE_TCL
2805 Py_INCREF(Py_None);
2806 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002807}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002808#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002809
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002810
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002811/**** Tktt Object (timer token) ****/
2812
Jeremy Hylton938ace62002-07-17 16:30:39 +00002813static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002814
Guido van Rossum00d93061998-05-28 23:06:38 +00002815typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002816 PyObject_HEAD
2817 Tcl_TimerToken token;
2818 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002819} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002820
2821static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002822Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002823{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002824 TkttObject *v = (TkttObject *)self;
2825 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002826
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002827 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2828 return NULL;
2829 if (v->token != NULL) {
2830 Tcl_DeleteTimerHandler(v->token);
2831 v->token = NULL;
2832 }
2833 if (func != NULL) {
2834 v->func = NULL;
2835 Py_DECREF(func);
2836 Py_DECREF(v); /* See Tktt_New() */
2837 }
2838 Py_INCREF(Py_None);
2839 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002840}
2841
2842static PyMethodDef Tktt_methods[] =
2843{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002844 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2845 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002846};
2847
2848static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002849Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002850{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002851 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002852
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002853 v = PyObject_New(TkttObject, &Tktt_Type);
2854 if (v == NULL)
2855 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002856
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002857 Py_INCREF(func);
2858 v->token = NULL;
2859 v->func = func;
2860
2861 /* Extra reference, deleted when called or when handler is deleted */
2862 Py_INCREF(v);
2863 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002864}
2865
2866static void
Fred Drake509d79a2000-07-08 04:04:38 +00002867Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002868{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002869 TkttObject *v = (TkttObject *)self;
2870 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002871
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002872 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002873
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002874 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002875}
2876
Guido van Rossum597ac201998-05-12 14:36:19 +00002877static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002878Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002879{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002880 TkttObject *v = (TkttObject *)self;
2881 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002882
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002883 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2884 v->func == NULL ? ", handler deleted" : "");
2885 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002886}
2887
2888static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002889Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002890{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002891 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002892}
2893
2894static PyTypeObject Tktt_Type =
2895{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002896 PyVarObject_HEAD_INIT(NULL, 0)
2897 "tktimertoken", /*tp_name */
2898 sizeof(TkttObject), /*tp_basicsize */
2899 0, /*tp_itemsize */
2900 Tktt_Dealloc, /*tp_dealloc */
2901 0, /*tp_print */
2902 Tktt_GetAttr, /*tp_getattr */
2903 0, /*tp_setattr */
2904 0, /*tp_compare */
2905 Tktt_Repr, /*tp_repr */
2906 0, /*tp_as_number */
2907 0, /*tp_as_sequence */
2908 0, /*tp_as_mapping */
2909 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002910};
2911
Barry Warsawfa701a81997-01-16 00:15:11 +00002912
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002913
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002914/** Timer Handler **/
2915
2916static void
Fred Drake509d79a2000-07-08 04:04:38 +00002917TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002918{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002919 TkttObject *v = (TkttObject *)clientData;
2920 PyObject *func = v->func;
2921 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002922
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002923 if (func == NULL)
2924 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002925
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002926 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002927
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002928 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002929
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002930 res = PyEval_CallObject(func, NULL);
2931 Py_DECREF(func);
2932 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002933
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002934 if (res == NULL) {
2935 errorInCmd = 1;
2936 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2937 }
2938 else
2939 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002940
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002941 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002942}
2943
2944static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002945Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002946{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002947 int milliseconds;
2948 PyObject *func;
2949 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002950
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002951 if (!self && Py_Py3kWarningFlag) {
2952 if (PyErr_Warn(PyExc_DeprecationWarning,
2953 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2954 return NULL;
2955 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002956
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002957 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2958 &milliseconds, &func))
2959 return NULL;
2960 if (!PyCallable_Check(func)) {
2961 PyErr_SetString(PyExc_TypeError, "bad argument list");
2962 return NULL;
2963 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002964
Martin v. Löwisa9656492003-03-30 08:44:58 +00002965#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002966 if (!self && !tcl_lock) {
2967 /* We don't have the Tcl lock since Tcl is threaded. */
2968 PyErr_SetString(PyExc_RuntimeError,
2969 "_tkinter.createtimerhandler not supported "
2970 "for threaded Tcl");
2971 return NULL;
2972 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002973#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002974
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002975 if (self) {
2976 CHECK_TCL_APPARTMENT;
2977 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002978
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002979 v = Tktt_New(func);
2980 if (v) {
2981 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2982 (ClientData)v);
2983 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002984
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002985 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002986}
2987
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002988
Guido van Rossum18468821994-06-20 07:49:28 +00002989/** Event Loop **/
2990
Guido van Rossum18468821994-06-20 07:49:28 +00002991static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002992Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002993{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002994 int threshold = 0;
2995 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002996#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002997 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002998#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002999
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003000 if (!self && Py_Py3kWarningFlag) {
3001 if (PyErr_Warn(PyExc_DeprecationWarning,
3002 "_tkinter.mainloop is gone in 3.x") < 0)
3003 return NULL;
3004 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00003005
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003006 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
3007 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003008
Martin v. Löwisa9656492003-03-30 08:44:58 +00003009#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003010 if (!self && !tcl_lock) {
3011 /* We don't have the Tcl lock since Tcl is threaded. */
3012 PyErr_SetString(PyExc_RuntimeError,
3013 "_tkinter.mainloop not supported "
3014 "for threaded Tcl");
3015 return NULL;
3016 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00003017#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00003018
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003019 if (self) {
3020 CHECK_TCL_APPARTMENT;
3021 self->dispatching = 1;
3022 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00003023
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003024 quitMainLoop = 0;
3025 while (Tk_GetNumMainWindows() > threshold &&
3026 !quitMainLoop &&
3027 !errorInCmd)
3028 {
3029 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00003030
3031#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003032 if (self && self->threaded) {
3033 /* Allow other Python threads to run. */
3034 ENTER_TCL
3035 result = Tcl_DoOneEvent(0);
3036 LEAVE_TCL
3037 }
3038 else {
3039 Py_BEGIN_ALLOW_THREADS
3040 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3041 tcl_tstate = tstate;
3042 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3043 tcl_tstate = NULL;
3044 if(tcl_lock)PyThread_release_lock(tcl_lock);
3045 if (result == 0)
3046 Sleep(Tkinter_busywaitinterval);
3047 Py_END_ALLOW_THREADS
3048 }
Guido van Rossum5b020781997-08-19 01:00:50 +00003049#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003050 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00003051#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003052
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003053 if (PyErr_CheckSignals() != 0) {
3054 if (self)
3055 self->dispatching = 0;
3056 return NULL;
3057 }
3058 if (result < 0)
3059 break;
3060 }
3061 if (self)
3062 self->dispatching = 0;
3063 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003064
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003065 if (errorInCmd) {
3066 errorInCmd = 0;
3067 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3068 excInCmd = valInCmd = trbInCmd = NULL;
3069 return NULL;
3070 }
3071 Py_INCREF(Py_None);
3072 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00003073}
3074
3075static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00003076Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00003077{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003078 int flags = 0;
3079 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00003080
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003081 if (!self && Py_Py3kWarningFlag) {
3082 if (PyErr_Warn(PyExc_DeprecationWarning,
3083 "_tkinter.dooneevent is gone in 3.x") < 0)
3084 return NULL;
3085 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00003086
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003087 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
3088 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00003089
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003090 ENTER_TCL
3091 rv = Tcl_DoOneEvent(flags);
3092 LEAVE_TCL
3093 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00003094}
3095
3096static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00003097Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003098{
3099
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003100 if (!self && Py_Py3kWarningFlag) {
3101 if (PyErr_Warn(PyExc_DeprecationWarning,
3102 "_tkinter.quit is gone in 3.x") < 0)
3103 return NULL;
3104 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00003105
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003106 if (!PyArg_ParseTuple(args, ":quit"))
3107 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00003108
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003109 quitMainLoop = 1;
3110 Py_INCREF(Py_None);
3111 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00003112}
3113
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003114static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00003115Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003116{
3117
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003118 if (!PyArg_ParseTuple(args, ":interpaddr"))
3119 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003120
Victor Stinner930c3c92013-09-05 00:26:15 +02003121 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003122}
3123
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003124static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00003125Tkapp_TkInit(PyObject *self, PyObject *args)
3126{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003127 Tcl_Interp *interp = Tkapp_Interp(self);
3128 const char * _tk_exists = NULL;
3129 int err;
David Aschere2b4b322004-02-18 05:59:53 +00003130
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00003131#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003132 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
3133 * first call failed.
3134 * To avoid the deadlock, we just refuse the second call through
3135 * a static variable.
3136 */
3137 if (tk_load_failed) {
3138 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
3139 return NULL;
3140 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00003141#endif
3142
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003143 /* We want to guard against calling Tk_Init() multiple times */
3144 CHECK_TCL_APPARTMENT;
3145 ENTER_TCL
3146 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
3147 ENTER_OVERLAP
3148 if (err == TCL_ERROR) {
3149 /* This sets an exception, but we cannot return right
3150 away because we need to exit the overlap first. */
3151 Tkinter_Error(self);
3152 } else {
3153 _tk_exists = Tkapp_Result(self);
3154 }
3155 LEAVE_OVERLAP_TCL
3156 if (err == TCL_ERROR) {
3157 return NULL;
3158 }
3159 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3160 if (Tk_Init(interp) == TCL_ERROR) {
3161 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00003162#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003163 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00003164#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003165 return NULL;
3166 }
3167 }
3168 Py_INCREF(Py_None);
3169 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00003170}
Barry Warsawfa701a81997-01-16 00:15:11 +00003171
Martin v. Löwisffad6332002-11-26 09:28:05 +00003172static PyObject *
3173Tkapp_WantObjects(PyObject *self, PyObject *args)
3174{
3175
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003176 int wantobjects = -1;
3177 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3178 return NULL;
3179 if (wantobjects == -1)
3180 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3181 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003182
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003183 Py_INCREF(Py_None);
3184 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003185}
3186
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003187static PyObject *
3188Tkapp_WillDispatch(PyObject *self, PyObject *args)
3189{
3190
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003191 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003192
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003193 Py_INCREF(Py_None);
3194 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003195}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003196
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03003197/* Convert Python string or any buffer compatible object to Tcl byte-array
3198 * object. Use it to pass binary data (e.g. image's data) to Tcl/Tk commands.
3199 */
3200static PyObject *
3201Tkapp_CreateByteArray(PyObject *self, PyObject *args)
3202{
3203 Py_buffer view;
3204 Tcl_Obj* obj;
3205 PyObject *res = NULL;
3206
3207 if (!PyArg_ParseTuple(args, "s*:_createbytearray", &view))
3208 return NULL;
3209
3210 if (view.len >= INT_MAX) {
3211 PyErr_SetString(PyExc_OverflowError, "string is too long");
3212 return NULL;
3213 }
3214 obj = Tcl_NewByteArrayObj(view.buf, (int)view.len);
3215 if (obj == NULL) {
3216 PyBuffer_Release(&view);
3217 return Tkinter_Error(self);
3218 }
3219 res = newPyTclObject(obj);
3220 PyBuffer_Release(&view);
3221 return res;
3222}
3223
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003224
Guido van Rossum18468821994-06-20 07:49:28 +00003225/**** Tkapp Method List ****/
3226
3227static PyMethodDef Tkapp_methods[] =
3228{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003229 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
3230 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3231 {"call", Tkapp_Call, METH_VARARGS},
3232 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
3233 {"eval", Tkapp_Eval, METH_VARARGS},
3234 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
3235 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
3236 {"record", Tkapp_Record, METH_VARARGS},
3237 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
3238 {"setvar", Tkapp_SetVar, METH_VARARGS},
3239 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3240 {"getvar", Tkapp_GetVar, METH_VARARGS},
3241 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3242 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3243 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3244 {"getint", Tkapp_GetInt, METH_VARARGS},
3245 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
Serhiy Storchakaf29bc702015-04-04 12:42:25 +03003246 {"getboolean", Tkapp_GetBoolean, METH_O},
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003247 {"exprstring", Tkapp_ExprString, METH_VARARGS},
3248 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
3249 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
3250 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
3251 {"splitlist", Tkapp_SplitList, METH_VARARGS},
3252 {"split", Tkapp_Split, METH_VARARGS},
3253 {"merge", Tkapp_Merge, METH_VARARGS},
3254 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
3255 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003256#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003257 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3258 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003259#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003260 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3261 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3262 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3263 {"quit", Tkapp_Quit, METH_VARARGS},
3264 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
3265 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03003266 {"_createbytearray", Tkapp_CreateByteArray, METH_VARARGS},
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003267 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003268};
3269
Barry Warsawfa701a81997-01-16 00:15:11 +00003270
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003271
Guido van Rossum18468821994-06-20 07:49:28 +00003272/**** Tkapp Type Methods ****/
3273
3274static void
Fred Drake509d79a2000-07-08 04:04:38 +00003275Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003276{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003277 /*CHECK_TCL_APPARTMENT;*/
3278 ENTER_TCL
3279 Tcl_DeleteInterp(Tkapp_Interp(self));
3280 LEAVE_TCL
3281 PyObject_Del(self);
3282 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003283}
3284
3285static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00003286Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00003287{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003288 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00003289}
3290
3291static PyTypeObject Tkapp_Type =
3292{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003293 PyVarObject_HEAD_INIT(NULL, 0)
3294 "tkapp", /*tp_name */
3295 sizeof(TkappObject), /*tp_basicsize */
3296 0, /*tp_itemsize */
3297 Tkapp_Dealloc, /*tp_dealloc */
3298 0, /*tp_print */
3299 Tkapp_GetAttr, /*tp_getattr */
3300 0, /*tp_setattr */
3301 0, /*tp_compare */
3302 0, /*tp_repr */
3303 0, /*tp_as_number */
3304 0, /*tp_as_sequence */
3305 0, /*tp_as_mapping */
3306 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00003307};
3308
Barry Warsawfa701a81997-01-16 00:15:11 +00003309
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003310
Guido van Rossum18468821994-06-20 07:49:28 +00003311/**** Tkinter Module ****/
3312
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003313typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003314 PyObject* tuple;
3315 int size; /* current size */
3316 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003317} FlattenContext;
3318
3319static int
3320_bump(FlattenContext* context, int size)
3321{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003322 /* expand tuple to hold (at least) size new items.
3323 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003324
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003325 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003326
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003327 if (maxsize < context->size + size)
3328 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003329
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003330 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003331
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003332 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003333}
3334
3335static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003336_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003337{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003338 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003339
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003340 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003341
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003342 if (depth > 1000) {
3343 PyErr_SetString(PyExc_ValueError,
3344 "nesting too deep in _flatten");
3345 return 0;
3346 } else if (PyList_Check(item)) {
3347 size = PyList_GET_SIZE(item);
3348 /* preallocate (assume no nesting) */
3349 if (context->size + size > context->maxsize &&
3350 !_bump(context, size))
3351 return 0;
3352 /* copy items to output tuple */
3353 for (i = 0; i < size; i++) {
3354 PyObject *o = PyList_GET_ITEM(item, i);
3355 if (PyList_Check(o) || PyTuple_Check(o)) {
3356 if (!_flatten1(context, o, depth + 1))
3357 return 0;
3358 } else if (o != Py_None) {
3359 if (context->size + 1 > context->maxsize &&
3360 !_bump(context, 1))
3361 return 0;
3362 Py_INCREF(o);
3363 PyTuple_SET_ITEM(context->tuple,
3364 context->size++, o);
3365 }
3366 }
3367 } else if (PyTuple_Check(item)) {
3368 /* same, for tuples */
3369 size = PyTuple_GET_SIZE(item);
3370 if (context->size + size > context->maxsize &&
3371 !_bump(context, size))
3372 return 0;
3373 for (i = 0; i < size; i++) {
3374 PyObject *o = PyTuple_GET_ITEM(item, i);
3375 if (PyList_Check(o) || PyTuple_Check(o)) {
3376 if (!_flatten1(context, o, depth + 1))
3377 return 0;
3378 } else if (o != Py_None) {
3379 if (context->size + 1 > context->maxsize &&
3380 !_bump(context, 1))
3381 return 0;
3382 Py_INCREF(o);
3383 PyTuple_SET_ITEM(context->tuple,
3384 context->size++, o);
3385 }
3386 }
3387 } else {
3388 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3389 return 0;
3390 }
3391 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003392}
3393
3394static PyObject *
3395Tkinter_Flatten(PyObject* self, PyObject* args)
3396{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003397 FlattenContext context;
3398 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003399
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003400 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3401 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003402
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003403 context.maxsize = PySequence_Size(item);
3404 if (context.maxsize < 0)
3405 return NULL;
3406 if (context.maxsize == 0)
3407 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003408
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003409 context.tuple = PyTuple_New(context.maxsize);
3410 if (!context.tuple)
3411 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003412
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003413 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003414
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003415 if (!_flatten1(&context, item,0))
3416 return NULL;
3417
3418 if (_PyTuple_Resize(&context.tuple, context.size))
3419 return NULL;
3420
3421 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003422}
3423
Guido van Rossum18468821994-06-20 07:49:28 +00003424static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003425Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003426{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003427 char *screenName = NULL;
3428 char *baseName = NULL;
3429 char *className = NULL;
3430 int interactive = 0;
3431 int wantobjects = 0;
3432 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3433 int sync = 0; /* pass -sync to wish */
3434 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003435
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003436 baseName = strrchr(Py_GetProgramName(), '/');
3437 if (baseName != NULL)
3438 baseName++;
3439 else
3440 baseName = Py_GetProgramName();
3441 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003442
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003443 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3444 &screenName, &baseName, &className,
3445 &interactive, &wantobjects, &wantTk,
3446 &sync, &use))
3447 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03003448 CHECK_STRING_LENGTH(screenName);
3449 CHECK_STRING_LENGTH(baseName);
3450 CHECK_STRING_LENGTH(className);
3451 CHECK_STRING_LENGTH(use);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003452
3453 return (PyObject *) Tkapp_New(screenName, baseName, className,
3454 interactive, wantobjects, wantTk,
3455 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003456}
3457
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003458static PyObject *
3459Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3460{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003461 int new_val;
3462 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3463 return NULL;
3464 if (new_val < 0) {
3465 PyErr_SetString(PyExc_ValueError,
3466 "busywaitinterval must be >= 0");
3467 return NULL;
3468 }
3469 Tkinter_busywaitinterval = new_val;
3470 Py_INCREF(Py_None);
3471 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003472}
3473
3474static char setbusywaitinterval_doc[] =
3475"setbusywaitinterval(n) -> None\n\
3476\n\
3477Set the busy-wait interval in milliseconds between successive\n\
3478calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3479It should be set to a divisor of the maximum time between\n\
3480frames in an animation.";
3481
3482static PyObject *
3483Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3484{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003485 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003486}
3487
3488static char getbusywaitinterval_doc[] =
3489"getbusywaitinterval() -> int\n\
3490\n\
3491Return the current busy-wait interval between successive\n\
3492calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3493
Guido van Rossum18468821994-06-20 07:49:28 +00003494static PyMethodDef moduleMethods[] =
3495{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003496 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3497 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003498#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003499 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3500 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003501#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003502 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3503 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3504 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3505 {"quit", Tkapp_Quit, METH_VARARGS},
3506 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3507 setbusywaitinterval_doc},
3508 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3509 METH_NOARGS, getbusywaitinterval_doc},
3510 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003511};
3512
Guido van Rossum7bf15641998-05-22 18:28:17 +00003513#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003514
3515static int stdin_ready = 0;
3516
Guido van Rossumad4db171998-06-13 13:56:28 +00003517#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003518static void
Fred Drake509d79a2000-07-08 04:04:38 +00003519MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003520{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003521 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003522}
Guido van Rossumad4db171998-06-13 13:56:28 +00003523#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003524
Martin v. Löwisa9656492003-03-30 08:44:58 +00003525#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003526static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003527#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003528
Guido van Rossum18468821994-06-20 07:49:28 +00003529static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003530EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003531{
Guido van Rossumad4db171998-06-13 13:56:28 +00003532#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003533 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003534#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003535#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003536 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003537#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003538 stdin_ready = 0;
3539 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003540#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003541 tfile = fileno(stdin);
3542 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003543#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003544 while (!errorInCmd && !stdin_ready) {
3545 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003546#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003547 if (_kbhit()) {
3548 stdin_ready = 1;
3549 break;
3550 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003551#endif
3552#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003553 Py_BEGIN_ALLOW_THREADS
3554 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3555 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003556
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003557 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003558
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003559 tcl_tstate = NULL;
3560 if(tcl_lock)PyThread_release_lock(tcl_lock);
3561 if (result == 0)
3562 Sleep(Tkinter_busywaitinterval);
3563 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003564#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003565 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003566#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003567
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003568 if (result < 0)
3569 break;
3570 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003571#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003572 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003573#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003574 if (errorInCmd) {
3575 errorInCmd = 0;
3576 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3577 excInCmd = valInCmd = trbInCmd = NULL;
3578 PyErr_Print();
3579 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003580#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003581 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003582#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003583 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003584}
Guido van Rossum18468821994-06-20 07:49:28 +00003585
Guido van Rossum00d93061998-05-28 23:06:38 +00003586#endif
3587
Guido van Rossum7bf15641998-05-22 18:28:17 +00003588static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003589EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003590{
Guido van Rossum00d93061998-05-28 23:06:38 +00003591#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003592 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003593#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003594 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003595#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003596 PyOS_InputHook = EventHook;
3597 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003598#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003599}
3600
3601static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003602DisableEventHook(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 (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3606 PyOS_InputHook = NULL;
3607 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003608#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003609}
3610
Barry Warsawfa701a81997-01-16 00:15:11 +00003611
3612/* all errors will be checked in one fell swoop in init_tkinter() */
3613static void
Fred Drake509d79a2000-07-08 04:04:38 +00003614ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003615{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003616 PyObject *v = PyInt_FromLong(val);
3617 if (v) {
3618 PyDict_SetItemString(d, name, v);
3619 Py_DECREF(v);
3620 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003621}
3622static void
Fred Drake509d79a2000-07-08 04:04:38 +00003623ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003624{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003625 PyObject *v = PyString_FromString(val);
3626 if (v) {
3627 PyDict_SetItemString(d, name, v);
3628 Py_DECREF(v);
3629 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003630}
3631
3632
Mark Hammond62b1ab12002-07-23 06:31:15 +00003633PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003634init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003635{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003636 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003637
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003638 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003639
3640#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003641 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003642#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003643
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003644 m = Py_InitModule("_tkinter", moduleMethods);
3645 if (m == NULL)
3646 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003647
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003648 d = PyModule_GetDict(m);
3649 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3650 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003651
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003652 ins_long(d, "READABLE", TCL_READABLE);
3653 ins_long(d, "WRITABLE", TCL_WRITABLE);
3654 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3655 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3656 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3657 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3658 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3659 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3660 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3661 ins_string(d, "TK_VERSION", TK_VERSION);
3662 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003663
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003664 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003665
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003666 Py_TYPE(&Tktt_Type) = &PyType_Type;
3667 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003668
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003669 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3670 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003671
3672#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003673 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3674 * start waking up. Note that Tcl_FindExecutable will do this, this
3675 * code must be above it! The original warning from
3676 * tkMacOSXAppInit.c is copied below.
3677 *
3678 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3679 * Tcl interpreter for now. It probably should work to do this
3680 * in the other order, but for now it doesn't seem to.
3681 *
3682 */
3683 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003684#endif
3685
3686
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003687 /* This helps the dynamic loader; in Unicode aware Tcl versions
3688 it also helps Tcl find its encodings. */
3689 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003690
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003691 if (PyErr_Occurred())
3692 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003693
Guido van Rossum43ff8681998-07-14 18:02:13 +00003694#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003695 /* This was not a good idea; through <Destroy> bindings,
3696 Tcl_Finalize() may invoke Python code but at that point the
3697 interpreter and thread state have already been destroyed! */
3698 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003699#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003700
Guido van Rossum18468821994-06-20 07:49:28 +00003701}