blob: 840b9dbdab32a8e8afe7cea8a220f9a520edf652 [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 Storchakac77c5b52015-04-02 18:46:30 +030099#if TK_VERSION_HEX >= 0x08050000
100#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 *
Fred Drake509d79a2000-07-08 04:04:38 +00002166Tkapp_GetBoolean(PyObject *self, PyObject *args)
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
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002171 if (PyTuple_Size(args) == 1) {
2172 PyObject *o = PyTuple_GetItem(args, 0);
2173 if (PyInt_Check(o)) {
2174 Py_INCREF(o);
2175 return o;
2176 }
2177 }
2178 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
2179 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03002180 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002181 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
2182 return Tkinter_Error(self);
2183 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00002184}
2185
2186static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002187Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002188{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002189 char *s;
2190 PyObject *res = NULL;
2191 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002192
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002193 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
2194 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002195
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002196 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002197 CHECK_TCL_APPARTMENT;
2198
2199 ENTER_TCL
2200 retval = Tcl_ExprString(Tkapp_Interp(self), s);
2201 ENTER_OVERLAP
2202 if (retval == TCL_ERROR)
2203 res = Tkinter_Error(self);
2204 else
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002205 res = PyString_FromString(Tkapp_Result(self));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002206 LEAVE_OVERLAP_TCL
2207 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002208}
2209
2210static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002211Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002212{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002213 char *s;
2214 PyObject *res = NULL;
2215 int retval;
2216 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00002217
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002218 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
2219 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002220
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002221 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002222 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002223
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002224 ENTER_TCL
2225 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
2226 ENTER_OVERLAP
2227 if (retval == TCL_ERROR)
2228 res = Tkinter_Error(self);
2229 else
2230 res = Py_BuildValue("l", v);
2231 LEAVE_OVERLAP_TCL
2232 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002233}
2234
2235static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002236Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002237{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002238 char *s;
2239 PyObject *res = NULL;
2240 double v;
2241 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002242
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002243 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2244 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002245 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002246 CHECK_TCL_APPARTMENT;
2247 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2248 ENTER_TCL
2249 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2250 ENTER_OVERLAP
2251 PyFPE_END_PROTECT(retval)
2252 if (retval == TCL_ERROR)
2253 res = Tkinter_Error(self);
2254 else
2255 res = Py_BuildValue("d", v);
2256 LEAVE_OVERLAP_TCL
2257 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002258}
2259
2260static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002261Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002262{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002263 char *s;
2264 PyObject *res = NULL;
2265 int retval;
2266 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002267
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002268 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2269 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002270 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002271 CHECK_TCL_APPARTMENT;
2272 ENTER_TCL
2273 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2274 ENTER_OVERLAP
2275 if (retval == TCL_ERROR)
2276 res = Tkinter_Error(self);
2277 else
2278 res = Py_BuildValue("i", v);
2279 LEAVE_OVERLAP_TCL
2280 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002281}
2282
Barry Warsawfa701a81997-01-16 00:15:11 +00002283
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002284
Guido van Rossum18468821994-06-20 07:49:28 +00002285static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002286Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002287{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002288 char *list;
2289 int argc;
2290 char **argv;
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002291 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002292 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002293
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002294 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2295 return NULL;
2296 if (PyTclObject_Check(arg)) {
2297 int objc;
2298 Tcl_Obj **objv;
2299 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2300 ((PyTclObject*)arg)->value,
2301 &objc, &objv) == TCL_ERROR) {
2302 return Tkinter_Error(self);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002303 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002304 if (!(v = PyTuple_New(objc)))
2305 return NULL;
2306 for (i = 0; i < objc; i++) {
2307 PyObject *s = FromObj(self, objv[i]);
2308 if (!s || PyTuple_SetItem(v, i, s)) {
2309 Py_DECREF(v);
2310 return NULL;
2311 }
2312 }
2313 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002314 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002315 if (PyTuple_Check(arg)) {
2316 Py_INCREF(arg);
2317 return arg;
2318 }
2319
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002320 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2321 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002322
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002323 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002324 if (Tcl_SplitList(Tkapp_Interp(self), list,
2325 &argc, &argv) == TCL_ERROR) {
2326 PyMem_Free(list);
2327 return Tkinter_Error(self);
2328 }
Guido van Rossum18468821994-06-20 07:49:28 +00002329
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002330 if (!(v = PyTuple_New(argc)))
2331 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002332
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002333 for (i = 0; i < argc; i++) {
2334 PyObject *s = PyString_FromString(argv[i]);
2335 if (!s || PyTuple_SetItem(v, i, s)) {
2336 Py_DECREF(v);
2337 v = NULL;
2338 goto finally;
2339 }
2340 }
Guido van Rossum18468821994-06-20 07:49:28 +00002341
Barry Warsawfa701a81997-01-16 00:15:11 +00002342 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002343 ckfree(FREECAST argv);
2344 PyMem_Free(list);
2345 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002346}
2347
2348static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002349Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002350{
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002351 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002352 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002353
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002354 if (!PyArg_ParseTuple(args, "O:split", &arg))
2355 return NULL;
2356 if (PyTclObject_Check(arg)) {
2357 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2358 int objc;
2359 Tcl_Obj **objv;
2360 int i;
2361 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2362 &objc, &objv) == TCL_ERROR) {
2363 return FromObj(self, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002364 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002365 if (objc == 0)
2366 return PyString_FromString("");
2367 if (objc == 1)
2368 return FromObj(self, objv[0]);
2369 if (!(v = PyTuple_New(objc)))
2370 return NULL;
2371 for (i = 0; i < objc; i++) {
2372 PyObject *s = FromObj(self, objv[i]);
2373 if (!s || PyTuple_SetItem(v, i, s)) {
2374 Py_DECREF(v);
2375 return NULL;
2376 }
2377 }
2378 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002379 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002380 if (PyTuple_Check(arg))
2381 return SplitObj(arg);
2382
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002383 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2384 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002385 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002386 v = Split(list);
2387 PyMem_Free(list);
2388 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002389}
2390
2391static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002392Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002393{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002394 char *s = Merge(args);
2395 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002396
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002397 if (s) {
2398 res = PyString_FromString(s);
2399 ckfree(s);
2400 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002401
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002402 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002403}
2404
Barry Warsawfa701a81997-01-16 00:15:11 +00002405
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002406
Guido van Rossum18468821994-06-20 07:49:28 +00002407/** Tcl Command **/
2408
Guido van Rossum00d93061998-05-28 23:06:38 +00002409/* Client data struct */
2410typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002411 PyObject *self;
2412 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002413} PythonCmd_ClientData;
2414
2415static int
Fred Drake509d79a2000-07-08 04:04:38 +00002416PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002417{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002418 errorInCmd = 1;
2419 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2420 LEAVE_PYTHON
2421 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002422}
2423
Guido van Rossum18468821994-06-20 07:49:28 +00002424/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002425 * function or method.
2426 */
Guido van Rossum18468821994-06-20 07:49:28 +00002427static int
Fred Drake509d79a2000-07-08 04:04:38 +00002428PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002429{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002430 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2431 PyObject *func, *arg, *res;
2432 int i, rv;
2433 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002434
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002435 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002436
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002437 /* TBD: no error checking here since we know, via the
2438 * Tkapp_CreateCommand() that the client data is a two-tuple
2439 */
2440 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002441
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002442 /* Create argument list (argv1, ..., argvN) */
2443 if (!(arg = PyTuple_New(argc - 1)))
2444 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002445
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002446 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002447 PyObject *s = fromTclString(argv[i + 1]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002448 if (!s || PyTuple_SetItem(arg, i, s)) {
2449 Py_DECREF(arg);
2450 return PythonCmd_Error(interp);
2451 }
2452 }
2453 res = PyEval_CallObject(func, arg);
2454 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002455
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002456 if (res == NULL)
2457 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002458
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002459 obj_res = AsObj(res);
2460 if (obj_res == NULL) {
2461 Py_DECREF(res);
2462 return PythonCmd_Error(interp);
2463 }
2464 else {
2465 Tcl_SetObjResult(interp, obj_res);
2466 rv = TCL_OK;
2467 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002468
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002469 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002470
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002471 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002472
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002473 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002474}
2475
2476static void
Fred Drake509d79a2000-07-08 04:04:38 +00002477PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002478{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002479 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002480
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002481 ENTER_PYTHON
2482 Py_XDECREF(data->self);
2483 Py_XDECREF(data->func);
2484 PyMem_DEL(data);
2485 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002486}
2487
Barry Warsawfa701a81997-01-16 00:15:11 +00002488
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002489
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002490
Guilherme Polo1972d162009-03-27 21:43:08 +00002491#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002492TCL_DECLARE_MUTEX(command_mutex)
2493
2494typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002495 Tcl_Event ev;
2496 Tcl_Interp* interp;
2497 char *name;
2498 int create;
2499 int *status;
2500 ClientData *data;
2501 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002502} CommandEvent;
2503
2504static int
2505Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002506{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002507 if (ev->create)
2508 *ev->status = Tcl_CreateCommand(
2509 ev->interp, ev->name, PythonCmd,
2510 ev->data, PythonCmdDelete) == NULL;
2511 else
2512 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2513 Tcl_MutexLock(&command_mutex);
2514 Tcl_ConditionNotify(ev->done);
2515 Tcl_MutexUnlock(&command_mutex);
2516 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002517}
Guilherme Polo1972d162009-03-27 21:43:08 +00002518#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002519
2520static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002521Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002522{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002523 TkappObject *self = (TkappObject*)selfptr;
2524 PythonCmd_ClientData *data;
2525 char *cmdName;
2526 PyObject *func;
2527 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002528
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002529 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2530 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002531 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002532 if (!PyCallable_Check(func)) {
2533 PyErr_SetString(PyExc_TypeError, "command not callable");
2534 return NULL;
2535 }
Guido van Rossum18468821994-06-20 07:49:28 +00002536
Martin v. Löwisa9656492003-03-30 08:44:58 +00002537#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002538 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2539 !WaitForMainloop(self))
2540 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002541#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002542
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002543 data = PyMem_NEW(PythonCmd_ClientData, 1);
2544 if (!data)
2545 return PyErr_NoMemory();
2546 Py_INCREF(self);
2547 Py_INCREF(func);
2548 data->self = selfptr;
2549 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002550
2551#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002552 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2553 Tcl_Condition cond = NULL;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03002554 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2555 if (ev == NULL) {
2556 PyErr_NoMemory();
2557 PyMem_DEL(data);
2558 return NULL;
2559 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002560 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2561 ev->interp = self->interp;
2562 ev->create = 1;
2563 ev->name = cmdName;
2564 ev->data = (ClientData)data;
2565 ev->status = &err;
2566 ev->done = &cond;
2567 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2568 Tcl_ConditionFinalize(&cond);
2569 }
2570 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002571#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002572 {
2573 ENTER_TCL
2574 err = Tcl_CreateCommand(
2575 Tkapp_Interp(self), cmdName, PythonCmd,
2576 (ClientData)data, PythonCmdDelete) == NULL;
2577 LEAVE_TCL
2578 }
2579 if (err) {
2580 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2581 PyMem_DEL(data);
2582 return NULL;
2583 }
Guido van Rossum18468821994-06-20 07:49:28 +00002584
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002585 Py_INCREF(Py_None);
2586 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002587}
2588
Barry Warsawfa701a81997-01-16 00:15:11 +00002589
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002590
Guido van Rossum18468821994-06-20 07:49:28 +00002591static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002592Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002593{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002594 TkappObject *self = (TkappObject*)selfptr;
2595 char *cmdName;
2596 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002597
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002598 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2599 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002600 CHECK_STRING_LENGTH(cmdName);
Guilherme Polo1972d162009-03-27 21:43:08 +00002601
2602#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002603 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2604 Tcl_Condition cond = NULL;
2605 CommandEvent *ev;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03002606 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2607 if (ev == NULL) {
2608 PyErr_NoMemory();
2609 return NULL;
2610 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002611 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2612 ev->interp = self->interp;
2613 ev->create = 0;
2614 ev->name = cmdName;
2615 ev->status = &err;
2616 ev->done = &cond;
2617 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2618 &command_mutex);
2619 Tcl_ConditionFinalize(&cond);
2620 }
2621 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002622#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002623 {
2624 ENTER_TCL
2625 err = Tcl_DeleteCommand(self->interp, cmdName);
2626 LEAVE_TCL
2627 }
2628 if (err == -1) {
2629 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2630 return NULL;
2631 }
2632 Py_INCREF(Py_None);
2633 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002634}
2635
Barry Warsawfa701a81997-01-16 00:15:11 +00002636
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002637
Guido van Rossum00d93061998-05-28 23:06:38 +00002638#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002639/** File Handler **/
2640
Guido van Rossum00d93061998-05-28 23:06:38 +00002641typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002642 PyObject *func;
2643 PyObject *file;
2644 int id;
2645 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002646} FileHandler_ClientData;
2647
2648static FileHandler_ClientData *HeadFHCD;
2649
2650static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002651NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002652{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002653 FileHandler_ClientData *p;
2654 p = PyMem_NEW(FileHandler_ClientData, 1);
2655 if (p != NULL) {
2656 Py_XINCREF(func);
2657 Py_XINCREF(file);
2658 p->func = func;
2659 p->file = file;
2660 p->id = id;
2661 p->next = HeadFHCD;
2662 HeadFHCD = p;
2663 }
2664 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002665}
2666
2667static void
Fred Drake509d79a2000-07-08 04:04:38 +00002668DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002669{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002670 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002671
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002672 pp = &HeadFHCD;
2673 while ((p = *pp) != NULL) {
2674 if (p->id == id) {
2675 *pp = p->next;
2676 Py_XDECREF(p->func);
2677 Py_XDECREF(p->file);
2678 PyMem_DEL(p);
2679 }
2680 else
2681 pp = &p->next;
2682 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002683}
2684
Guido van Rossuma597dde1995-01-10 20:56:29 +00002685static void
Fred Drake509d79a2000-07-08 04:04:38 +00002686FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002687{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002688 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2689 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002690
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002691 ENTER_PYTHON
2692 func = data->func;
2693 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002694
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002695 arg = Py_BuildValue("(Oi)", file, (long) mask);
2696 res = PyEval_CallObject(func, arg);
2697 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002698
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002699 if (res == NULL) {
2700 errorInCmd = 1;
2701 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2702 }
2703 Py_XDECREF(res);
2704 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002705}
2706
Guido van Rossum18468821994-06-20 07:49:28 +00002707static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002708Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2709 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002710{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002711 FileHandler_ClientData *data;
2712 PyObject *file, *func;
2713 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002714
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002715 if (!self && Py_Py3kWarningFlag) {
2716 if (PyErr_Warn(PyExc_DeprecationWarning,
2717 "_tkinter.createfilehandler is gone in 3.x") < 0)
2718 return NULL;
2719 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002720
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002721 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2722 &file, &mask, &func))
2723 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002724
Martin v. Löwisa9656492003-03-30 08:44:58 +00002725#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002726 if (!self && !tcl_lock) {
2727 /* We don't have the Tcl lock since Tcl is threaded. */
2728 PyErr_SetString(PyExc_RuntimeError,
2729 "_tkinter.createfilehandler not supported "
2730 "for threaded Tcl");
2731 return NULL;
2732 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002733#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002734
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002735 if (self) {
2736 CHECK_TCL_APPARTMENT;
2737 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002738
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002739 tfile = PyObject_AsFileDescriptor(file);
2740 if (tfile < 0)
2741 return NULL;
2742 if (!PyCallable_Check(func)) {
2743 PyErr_SetString(PyExc_TypeError, "bad argument list");
2744 return NULL;
2745 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002746
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002747 data = NewFHCD(func, file, tfile);
2748 if (data == NULL)
2749 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002750
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002751 /* Ought to check for null Tcl_File object... */
2752 ENTER_TCL
2753 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2754 LEAVE_TCL
2755 Py_INCREF(Py_None);
2756 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002757}
2758
2759static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002760Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002761{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002762 PyObject *file;
2763 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002764
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002765 if (!self && Py_Py3kWarningFlag) {
2766 if (PyErr_Warn(PyExc_DeprecationWarning,
2767 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2768 return NULL;
2769 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002770
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002771 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2772 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002773
Martin v. Löwisa9656492003-03-30 08:44:58 +00002774#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002775 if (!self && !tcl_lock) {
2776 /* We don't have the Tcl lock since Tcl is threaded. */
2777 PyErr_SetString(PyExc_RuntimeError,
2778 "_tkinter.deletefilehandler not supported "
2779 "for threaded Tcl");
2780 return NULL;
2781 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002782#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002783
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002784 if (self) {
2785 CHECK_TCL_APPARTMENT;
2786 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002787
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002788 tfile = PyObject_AsFileDescriptor(file);
2789 if (tfile < 0)
2790 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002791
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002792 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002793
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002794 /* Ought to check for null Tcl_File object... */
2795 ENTER_TCL
2796 Tcl_DeleteFileHandler(tfile);
2797 LEAVE_TCL
2798 Py_INCREF(Py_None);
2799 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002800}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002801#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002802
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002803
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002804/**** Tktt Object (timer token) ****/
2805
Jeremy Hylton938ace62002-07-17 16:30:39 +00002806static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002807
Guido van Rossum00d93061998-05-28 23:06:38 +00002808typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002809 PyObject_HEAD
2810 Tcl_TimerToken token;
2811 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002812} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002813
2814static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002815Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002816{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002817 TkttObject *v = (TkttObject *)self;
2818 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002819
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002820 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2821 return NULL;
2822 if (v->token != NULL) {
2823 Tcl_DeleteTimerHandler(v->token);
2824 v->token = NULL;
2825 }
2826 if (func != NULL) {
2827 v->func = NULL;
2828 Py_DECREF(func);
2829 Py_DECREF(v); /* See Tktt_New() */
2830 }
2831 Py_INCREF(Py_None);
2832 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002833}
2834
2835static PyMethodDef Tktt_methods[] =
2836{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002837 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2838 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002839};
2840
2841static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002842Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002843{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002844 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002845
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002846 v = PyObject_New(TkttObject, &Tktt_Type);
2847 if (v == NULL)
2848 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002849
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002850 Py_INCREF(func);
2851 v->token = NULL;
2852 v->func = func;
2853
2854 /* Extra reference, deleted when called or when handler is deleted */
2855 Py_INCREF(v);
2856 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002857}
2858
2859static void
Fred Drake509d79a2000-07-08 04:04:38 +00002860Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002861{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002862 TkttObject *v = (TkttObject *)self;
2863 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002864
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002865 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002866
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002867 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002868}
2869
Guido van Rossum597ac201998-05-12 14:36:19 +00002870static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002871Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002872{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002873 TkttObject *v = (TkttObject *)self;
2874 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002875
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002876 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2877 v->func == NULL ? ", handler deleted" : "");
2878 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002879}
2880
2881static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002882Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002883{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002884 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002885}
2886
2887static PyTypeObject Tktt_Type =
2888{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002889 PyVarObject_HEAD_INIT(NULL, 0)
2890 "tktimertoken", /*tp_name */
2891 sizeof(TkttObject), /*tp_basicsize */
2892 0, /*tp_itemsize */
2893 Tktt_Dealloc, /*tp_dealloc */
2894 0, /*tp_print */
2895 Tktt_GetAttr, /*tp_getattr */
2896 0, /*tp_setattr */
2897 0, /*tp_compare */
2898 Tktt_Repr, /*tp_repr */
2899 0, /*tp_as_number */
2900 0, /*tp_as_sequence */
2901 0, /*tp_as_mapping */
2902 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002903};
2904
Barry Warsawfa701a81997-01-16 00:15:11 +00002905
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002906
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002907/** Timer Handler **/
2908
2909static void
Fred Drake509d79a2000-07-08 04:04:38 +00002910TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002911{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002912 TkttObject *v = (TkttObject *)clientData;
2913 PyObject *func = v->func;
2914 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002915
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002916 if (func == NULL)
2917 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002918
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002919 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002920
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002921 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002922
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002923 res = PyEval_CallObject(func, NULL);
2924 Py_DECREF(func);
2925 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002926
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002927 if (res == NULL) {
2928 errorInCmd = 1;
2929 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2930 }
2931 else
2932 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002933
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002934 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002935}
2936
2937static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002938Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002939{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002940 int milliseconds;
2941 PyObject *func;
2942 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002943
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002944 if (!self && Py_Py3kWarningFlag) {
2945 if (PyErr_Warn(PyExc_DeprecationWarning,
2946 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2947 return NULL;
2948 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002949
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002950 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2951 &milliseconds, &func))
2952 return NULL;
2953 if (!PyCallable_Check(func)) {
2954 PyErr_SetString(PyExc_TypeError, "bad argument list");
2955 return NULL;
2956 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002957
Martin v. Löwisa9656492003-03-30 08:44:58 +00002958#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002959 if (!self && !tcl_lock) {
2960 /* We don't have the Tcl lock since Tcl is threaded. */
2961 PyErr_SetString(PyExc_RuntimeError,
2962 "_tkinter.createtimerhandler not supported "
2963 "for threaded Tcl");
2964 return NULL;
2965 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002966#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002967
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002968 if (self) {
2969 CHECK_TCL_APPARTMENT;
2970 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002971
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002972 v = Tktt_New(func);
2973 if (v) {
2974 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2975 (ClientData)v);
2976 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002977
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002978 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002979}
2980
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002981
Guido van Rossum18468821994-06-20 07:49:28 +00002982/** Event Loop **/
2983
Guido van Rossum18468821994-06-20 07:49:28 +00002984static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002985Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002986{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002987 int threshold = 0;
2988 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002989#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002990 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002991#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002992
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002993 if (!self && Py_Py3kWarningFlag) {
2994 if (PyErr_Warn(PyExc_DeprecationWarning,
2995 "_tkinter.mainloop is gone in 3.x") < 0)
2996 return NULL;
2997 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002998
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002999 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
3000 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003001
Martin v. Löwisa9656492003-03-30 08:44:58 +00003002#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003003 if (!self && !tcl_lock) {
3004 /* We don't have the Tcl lock since Tcl is threaded. */
3005 PyErr_SetString(PyExc_RuntimeError,
3006 "_tkinter.mainloop not supported "
3007 "for threaded Tcl");
3008 return NULL;
3009 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00003010#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00003011
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003012 if (self) {
3013 CHECK_TCL_APPARTMENT;
3014 self->dispatching = 1;
3015 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00003016
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003017 quitMainLoop = 0;
3018 while (Tk_GetNumMainWindows() > threshold &&
3019 !quitMainLoop &&
3020 !errorInCmd)
3021 {
3022 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00003023
3024#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003025 if (self && self->threaded) {
3026 /* Allow other Python threads to run. */
3027 ENTER_TCL
3028 result = Tcl_DoOneEvent(0);
3029 LEAVE_TCL
3030 }
3031 else {
3032 Py_BEGIN_ALLOW_THREADS
3033 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3034 tcl_tstate = tstate;
3035 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
3036 tcl_tstate = NULL;
3037 if(tcl_lock)PyThread_release_lock(tcl_lock);
3038 if (result == 0)
3039 Sleep(Tkinter_busywaitinterval);
3040 Py_END_ALLOW_THREADS
3041 }
Guido van Rossum5b020781997-08-19 01:00:50 +00003042#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003043 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00003044#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003045
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003046 if (PyErr_CheckSignals() != 0) {
3047 if (self)
3048 self->dispatching = 0;
3049 return NULL;
3050 }
3051 if (result < 0)
3052 break;
3053 }
3054 if (self)
3055 self->dispatching = 0;
3056 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003057
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003058 if (errorInCmd) {
3059 errorInCmd = 0;
3060 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3061 excInCmd = valInCmd = trbInCmd = NULL;
3062 return NULL;
3063 }
3064 Py_INCREF(Py_None);
3065 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00003066}
3067
3068static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00003069Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00003070{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003071 int flags = 0;
3072 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00003073
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003074 if (!self && Py_Py3kWarningFlag) {
3075 if (PyErr_Warn(PyExc_DeprecationWarning,
3076 "_tkinter.dooneevent is gone in 3.x") < 0)
3077 return NULL;
3078 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00003079
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003080 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
3081 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00003082
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003083 ENTER_TCL
3084 rv = Tcl_DoOneEvent(flags);
3085 LEAVE_TCL
3086 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00003087}
3088
3089static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00003090Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003091{
3092
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003093 if (!self && Py_Py3kWarningFlag) {
3094 if (PyErr_Warn(PyExc_DeprecationWarning,
3095 "_tkinter.quit is gone in 3.x") < 0)
3096 return NULL;
3097 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00003098
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003099 if (!PyArg_ParseTuple(args, ":quit"))
3100 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00003101
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003102 quitMainLoop = 1;
3103 Py_INCREF(Py_None);
3104 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00003105}
3106
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003107static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00003108Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003109{
3110
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003111 if (!PyArg_ParseTuple(args, ":interpaddr"))
3112 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003113
Victor Stinner930c3c92013-09-05 00:26:15 +02003114 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00003115}
3116
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003117static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00003118Tkapp_TkInit(PyObject *self, PyObject *args)
3119{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003120 Tcl_Interp *interp = Tkapp_Interp(self);
3121 const char * _tk_exists = NULL;
3122 int err;
David Aschere2b4b322004-02-18 05:59:53 +00003123
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00003124#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003125 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
3126 * first call failed.
3127 * To avoid the deadlock, we just refuse the second call through
3128 * a static variable.
3129 */
3130 if (tk_load_failed) {
3131 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
3132 return NULL;
3133 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00003134#endif
3135
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003136 /* We want to guard against calling Tk_Init() multiple times */
3137 CHECK_TCL_APPARTMENT;
3138 ENTER_TCL
3139 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
3140 ENTER_OVERLAP
3141 if (err == TCL_ERROR) {
3142 /* This sets an exception, but we cannot return right
3143 away because we need to exit the overlap first. */
3144 Tkinter_Error(self);
3145 } else {
3146 _tk_exists = Tkapp_Result(self);
3147 }
3148 LEAVE_OVERLAP_TCL
3149 if (err == TCL_ERROR) {
3150 return NULL;
3151 }
3152 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
3153 if (Tk_Init(interp) == TCL_ERROR) {
3154 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00003155#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003156 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00003157#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003158 return NULL;
3159 }
3160 }
3161 Py_INCREF(Py_None);
3162 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00003163}
Barry Warsawfa701a81997-01-16 00:15:11 +00003164
Martin v. Löwisffad6332002-11-26 09:28:05 +00003165static PyObject *
3166Tkapp_WantObjects(PyObject *self, PyObject *args)
3167{
3168
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003169 int wantobjects = -1;
3170 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
3171 return NULL;
3172 if (wantobjects == -1)
3173 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
3174 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003175
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003176 Py_INCREF(Py_None);
3177 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00003178}
3179
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003180static PyObject *
3181Tkapp_WillDispatch(PyObject *self, PyObject *args)
3182{
3183
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003184 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003185
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003186 Py_INCREF(Py_None);
3187 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00003188}
Martin v. Löwisffad6332002-11-26 09:28:05 +00003189
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03003190/* Convert Python string or any buffer compatible object to Tcl byte-array
3191 * object. Use it to pass binary data (e.g. image's data) to Tcl/Tk commands.
3192 */
3193static PyObject *
3194Tkapp_CreateByteArray(PyObject *self, PyObject *args)
3195{
3196 Py_buffer view;
3197 Tcl_Obj* obj;
3198 PyObject *res = NULL;
3199
3200 if (!PyArg_ParseTuple(args, "s*:_createbytearray", &view))
3201 return NULL;
3202
3203 if (view.len >= INT_MAX) {
3204 PyErr_SetString(PyExc_OverflowError, "string is too long");
3205 return NULL;
3206 }
3207 obj = Tcl_NewByteArrayObj(view.buf, (int)view.len);
3208 if (obj == NULL) {
3209 PyBuffer_Release(&view);
3210 return Tkinter_Error(self);
3211 }
3212 res = newPyTclObject(obj);
3213 PyBuffer_Release(&view);
3214 return res;
3215}
3216
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003217
Guido van Rossum18468821994-06-20 07:49:28 +00003218/**** Tkapp Method List ****/
3219
3220static PyMethodDef Tkapp_methods[] =
3221{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003222 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
3223 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
3224 {"call", Tkapp_Call, METH_VARARGS},
3225 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
3226 {"eval", Tkapp_Eval, METH_VARARGS},
3227 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
3228 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
3229 {"record", Tkapp_Record, METH_VARARGS},
3230 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
3231 {"setvar", Tkapp_SetVar, METH_VARARGS},
3232 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3233 {"getvar", Tkapp_GetVar, METH_VARARGS},
3234 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3235 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3236 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3237 {"getint", Tkapp_GetInt, METH_VARARGS},
3238 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
3239 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
3240 {"exprstring", Tkapp_ExprString, METH_VARARGS},
3241 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
3242 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
3243 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
3244 {"splitlist", Tkapp_SplitList, METH_VARARGS},
3245 {"split", Tkapp_Split, METH_VARARGS},
3246 {"merge", Tkapp_Merge, METH_VARARGS},
3247 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
3248 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003249#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003250 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3251 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003252#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003253 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3254 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3255 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3256 {"quit", Tkapp_Quit, METH_VARARGS},
3257 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
3258 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03003259 {"_createbytearray", Tkapp_CreateByteArray, METH_VARARGS},
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003260 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003261};
3262
Barry Warsawfa701a81997-01-16 00:15:11 +00003263
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003264
Guido van Rossum18468821994-06-20 07:49:28 +00003265/**** Tkapp Type Methods ****/
3266
3267static void
Fred Drake509d79a2000-07-08 04:04:38 +00003268Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003269{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003270 /*CHECK_TCL_APPARTMENT;*/
3271 ENTER_TCL
3272 Tcl_DeleteInterp(Tkapp_Interp(self));
3273 LEAVE_TCL
3274 PyObject_Del(self);
3275 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003276}
3277
3278static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00003279Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00003280{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003281 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00003282}
3283
3284static PyTypeObject Tkapp_Type =
3285{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003286 PyVarObject_HEAD_INIT(NULL, 0)
3287 "tkapp", /*tp_name */
3288 sizeof(TkappObject), /*tp_basicsize */
3289 0, /*tp_itemsize */
3290 Tkapp_Dealloc, /*tp_dealloc */
3291 0, /*tp_print */
3292 Tkapp_GetAttr, /*tp_getattr */
3293 0, /*tp_setattr */
3294 0, /*tp_compare */
3295 0, /*tp_repr */
3296 0, /*tp_as_number */
3297 0, /*tp_as_sequence */
3298 0, /*tp_as_mapping */
3299 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00003300};
3301
Barry Warsawfa701a81997-01-16 00:15:11 +00003302
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003303
Guido van Rossum18468821994-06-20 07:49:28 +00003304/**** Tkinter Module ****/
3305
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003306typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003307 PyObject* tuple;
3308 int size; /* current size */
3309 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003310} FlattenContext;
3311
3312static int
3313_bump(FlattenContext* context, int size)
3314{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003315 /* expand tuple to hold (at least) size new items.
3316 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003317
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003318 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003319
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003320 if (maxsize < context->size + size)
3321 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003322
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003323 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003324
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003325 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003326}
3327
3328static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003329_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003330{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003331 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003332
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003333 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003334
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003335 if (depth > 1000) {
3336 PyErr_SetString(PyExc_ValueError,
3337 "nesting too deep in _flatten");
3338 return 0;
3339 } else if (PyList_Check(item)) {
3340 size = PyList_GET_SIZE(item);
3341 /* preallocate (assume no nesting) */
3342 if (context->size + size > context->maxsize &&
3343 !_bump(context, size))
3344 return 0;
3345 /* copy items to output tuple */
3346 for (i = 0; i < size; i++) {
3347 PyObject *o = PyList_GET_ITEM(item, i);
3348 if (PyList_Check(o) || PyTuple_Check(o)) {
3349 if (!_flatten1(context, o, depth + 1))
3350 return 0;
3351 } else if (o != Py_None) {
3352 if (context->size + 1 > context->maxsize &&
3353 !_bump(context, 1))
3354 return 0;
3355 Py_INCREF(o);
3356 PyTuple_SET_ITEM(context->tuple,
3357 context->size++, o);
3358 }
3359 }
3360 } else if (PyTuple_Check(item)) {
3361 /* same, for tuples */
3362 size = PyTuple_GET_SIZE(item);
3363 if (context->size + size > context->maxsize &&
3364 !_bump(context, size))
3365 return 0;
3366 for (i = 0; i < size; i++) {
3367 PyObject *o = PyTuple_GET_ITEM(item, i);
3368 if (PyList_Check(o) || PyTuple_Check(o)) {
3369 if (!_flatten1(context, o, depth + 1))
3370 return 0;
3371 } else if (o != Py_None) {
3372 if (context->size + 1 > context->maxsize &&
3373 !_bump(context, 1))
3374 return 0;
3375 Py_INCREF(o);
3376 PyTuple_SET_ITEM(context->tuple,
3377 context->size++, o);
3378 }
3379 }
3380 } else {
3381 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3382 return 0;
3383 }
3384 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003385}
3386
3387static PyObject *
3388Tkinter_Flatten(PyObject* self, PyObject* args)
3389{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003390 FlattenContext context;
3391 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003392
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003393 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3394 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003395
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003396 context.maxsize = PySequence_Size(item);
3397 if (context.maxsize < 0)
3398 return NULL;
3399 if (context.maxsize == 0)
3400 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003401
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003402 context.tuple = PyTuple_New(context.maxsize);
3403 if (!context.tuple)
3404 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003405
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003406 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003407
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003408 if (!_flatten1(&context, item,0))
3409 return NULL;
3410
3411 if (_PyTuple_Resize(&context.tuple, context.size))
3412 return NULL;
3413
3414 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003415}
3416
Guido van Rossum18468821994-06-20 07:49:28 +00003417static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003418Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003419{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003420 char *screenName = NULL;
3421 char *baseName = NULL;
3422 char *className = NULL;
3423 int interactive = 0;
3424 int wantobjects = 0;
3425 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3426 int sync = 0; /* pass -sync to wish */
3427 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003428
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003429 baseName = strrchr(Py_GetProgramName(), '/');
3430 if (baseName != NULL)
3431 baseName++;
3432 else
3433 baseName = Py_GetProgramName();
3434 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003435
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003436 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3437 &screenName, &baseName, &className,
3438 &interactive, &wantobjects, &wantTk,
3439 &sync, &use))
3440 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03003441 CHECK_STRING_LENGTH(screenName);
3442 CHECK_STRING_LENGTH(baseName);
3443 CHECK_STRING_LENGTH(className);
3444 CHECK_STRING_LENGTH(use);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003445
3446 return (PyObject *) Tkapp_New(screenName, baseName, className,
3447 interactive, wantobjects, wantTk,
3448 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003449}
3450
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003451static PyObject *
3452Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3453{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003454 int new_val;
3455 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3456 return NULL;
3457 if (new_val < 0) {
3458 PyErr_SetString(PyExc_ValueError,
3459 "busywaitinterval must be >= 0");
3460 return NULL;
3461 }
3462 Tkinter_busywaitinterval = new_val;
3463 Py_INCREF(Py_None);
3464 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003465}
3466
3467static char setbusywaitinterval_doc[] =
3468"setbusywaitinterval(n) -> None\n\
3469\n\
3470Set the busy-wait interval in milliseconds between successive\n\
3471calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3472It should be set to a divisor of the maximum time between\n\
3473frames in an animation.";
3474
3475static PyObject *
3476Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3477{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003478 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003479}
3480
3481static char getbusywaitinterval_doc[] =
3482"getbusywaitinterval() -> int\n\
3483\n\
3484Return the current busy-wait interval between successive\n\
3485calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3486
Guido van Rossum18468821994-06-20 07:49:28 +00003487static PyMethodDef moduleMethods[] =
3488{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003489 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3490 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003491#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003492 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3493 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003494#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003495 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3496 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3497 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3498 {"quit", Tkapp_Quit, METH_VARARGS},
3499 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3500 setbusywaitinterval_doc},
3501 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3502 METH_NOARGS, getbusywaitinterval_doc},
3503 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003504};
3505
Guido van Rossum7bf15641998-05-22 18:28:17 +00003506#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003507
3508static int stdin_ready = 0;
3509
Guido van Rossumad4db171998-06-13 13:56:28 +00003510#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003511static void
Fred Drake509d79a2000-07-08 04:04:38 +00003512MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003513{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003514 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003515}
Guido van Rossumad4db171998-06-13 13:56:28 +00003516#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003517
Martin v. Löwisa9656492003-03-30 08:44:58 +00003518#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003519static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003520#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003521
Guido van Rossum18468821994-06-20 07:49:28 +00003522static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003523EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003524{
Guido van Rossumad4db171998-06-13 13:56:28 +00003525#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003526 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003527#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003528#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003529 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003530#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003531 stdin_ready = 0;
3532 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003533#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003534 tfile = fileno(stdin);
3535 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003536#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003537 while (!errorInCmd && !stdin_ready) {
3538 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003539#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003540 if (_kbhit()) {
3541 stdin_ready = 1;
3542 break;
3543 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003544#endif
3545#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003546 Py_BEGIN_ALLOW_THREADS
3547 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3548 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003549
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003550 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003551
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003552 tcl_tstate = NULL;
3553 if(tcl_lock)PyThread_release_lock(tcl_lock);
3554 if (result == 0)
3555 Sleep(Tkinter_busywaitinterval);
3556 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003557#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003558 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003559#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003560
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003561 if (result < 0)
3562 break;
3563 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003564#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003565 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003566#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003567 if (errorInCmd) {
3568 errorInCmd = 0;
3569 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3570 excInCmd = valInCmd = trbInCmd = NULL;
3571 PyErr_Print();
3572 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003573#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003574 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003575#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003576 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003577}
Guido van Rossum18468821994-06-20 07:49:28 +00003578
Guido van Rossum00d93061998-05-28 23:06:38 +00003579#endif
3580
Guido van Rossum7bf15641998-05-22 18:28:17 +00003581static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003582EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003583{
Guido van Rossum00d93061998-05-28 23:06:38 +00003584#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003585 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003586#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003587 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003588#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003589 PyOS_InputHook = EventHook;
3590 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003591#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003592}
3593
3594static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003595DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003596{
Guido van Rossum00d93061998-05-28 23:06:38 +00003597#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003598 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3599 PyOS_InputHook = NULL;
3600 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003601#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003602}
3603
Barry Warsawfa701a81997-01-16 00:15:11 +00003604
3605/* all errors will be checked in one fell swoop in init_tkinter() */
3606static void
Fred Drake509d79a2000-07-08 04:04:38 +00003607ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003608{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003609 PyObject *v = PyInt_FromLong(val);
3610 if (v) {
3611 PyDict_SetItemString(d, name, v);
3612 Py_DECREF(v);
3613 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003614}
3615static void
Fred Drake509d79a2000-07-08 04:04:38 +00003616ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003617{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003618 PyObject *v = PyString_FromString(val);
3619 if (v) {
3620 PyDict_SetItemString(d, name, v);
3621 Py_DECREF(v);
3622 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003623}
3624
3625
Mark Hammond62b1ab12002-07-23 06:31:15 +00003626PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003627init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003628{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003629 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003630
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003631 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003632
3633#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003634 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003635#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003636
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003637 m = Py_InitModule("_tkinter", moduleMethods);
3638 if (m == NULL)
3639 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003640
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003641 d = PyModule_GetDict(m);
3642 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3643 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003644
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003645 ins_long(d, "READABLE", TCL_READABLE);
3646 ins_long(d, "WRITABLE", TCL_WRITABLE);
3647 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3648 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3649 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3650 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3651 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3652 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3653 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3654 ins_string(d, "TK_VERSION", TK_VERSION);
3655 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003656
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003657 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003658
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003659 Py_TYPE(&Tktt_Type) = &PyType_Type;
3660 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003661
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003662 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3663 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003664
3665#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003666 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3667 * start waking up. Note that Tcl_FindExecutable will do this, this
3668 * code must be above it! The original warning from
3669 * tkMacOSXAppInit.c is copied below.
3670 *
3671 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3672 * Tcl interpreter for now. It probably should work to do this
3673 * in the other order, but for now it doesn't seem to.
3674 *
3675 */
3676 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003677#endif
3678
3679
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003680 /* This helps the dynamic loader; in Unicode aware Tcl versions
3681 it also helps Tcl find its encodings. */
3682 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003683
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003684 if (PyErr_Occurred())
3685 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003686
Guido van Rossum43ff8681998-07-14 18:02:13 +00003687#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003688 /* This was not a good idea; through <Destroy> bindings,
3689 Tcl_Finalize() may invoke Python code but at that point the
3690 interpreter and thread state have already been destroyed! */
3691 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003692#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003693
Guido van Rossum18468821994-06-20 07:49:28 +00003694}