blob: acc0110984a7234829312bfde593076488a4b32d [file] [log] [blame]
Guido van Rossum845547d1996-06-26 18:26:04 +00001/***********************************************************
2Copyright (C) 1994 Steen Lumholt.
Guido van Rossum845547d1996-06-26 18:26:04 +00003
4 All Rights Reserved
5
Guido van Rossum845547d1996-06-26 18:26:04 +00006******************************************************************/
7
8/* _tkinter.c -- Interface to libtk.a and libtcl.a. */
Guido van Rossum18468821994-06-20 07:49:28 +00009
Guido van Rossum7ffa7611996-08-13 21:10:16 +000010/* TCL/TK VERSION INFO:
11
Antoine Pitrouc83ea132010-05-09 14:46:46 +000012 Only Tcl/Tk 8.3.1 and later are supported. Older versions are not
13 supported. Use Python 2.6 or older if you cannot upgrade your
14 Tcl/Tk libraries.
Guido van Rossuma80649b2000-03-28 20:07:05 +000015*/
Guido van Rossum7ffa7611996-08-13 21:10:16 +000016
Guido van Rossuma80649b2000-03-28 20:07:05 +000017/* XXX Further speed-up ideas, involving Tcl 8.0 features:
Guido van Rossum212643f1998-04-29 16:22:14 +000018
Guido van Rossum212643f1998-04-29 16:22:14 +000019 - Register a new Tcl type, "Python callable", which can be called more
20 efficiently and passed to Tcl_EvalObj() directly (if this is possible).
21
Guido van Rossum7ffa7611996-08-13 21:10:16 +000022*/
23
Guido van Rossum35d43371997-08-02 00:09:09 +000024
Guido van Rossum9722ad81995-09-22 23:49:28 +000025#include "Python.h"
Guido van Rossum97867b21996-08-08 19:09:53 +000026#include <ctype.h>
Guido van Rossum9722ad81995-09-22 23:49:28 +000027
Guido van Rossum00d93061998-05-28 23:06:38 +000028#ifdef WITH_THREAD
Guido van Rossum49b56061998-10-01 20:42:43 +000029#include "pythread.h"
Guido van Rossum00d93061998-05-28 23:06:38 +000030#endif
31
Guido van Rossum2a5119b1998-05-29 01:28:40 +000032#ifdef MS_WINDOWS
33#include <windows.h>
34#endif
35
Martin v. Löwis39195712003-01-04 00:33:13 +000036/* Allow using this code in Python 2.[12] */
37#ifndef PyDoc_STRVAR
Martin v. Löwiscd9a8b62003-01-21 21:52:57 +000038#define PyDoc_STRVAR(name,str) static char name[] = str
Martin v. Löwis39195712003-01-04 00:33:13 +000039#endif
40
41#ifndef PyMODINIT_FUNC
Martin v. Löwis3a57d9d2003-01-04 08:54:59 +000042#define PyMODINIT_FUNC void
Martin v. Löwis39195712003-01-04 00:33:13 +000043#endif
44
Martin v. Löwis52ae6f62003-03-30 08:26:04 +000045#ifndef PyBool_Check
46#define PyBool_Check(o) 0
47#define PyBool_FromLong PyInt_FromLong
48#endif
49
Serhiy Storchaka42035702013-08-21 21:46:12 +030050#define CHECK_SIZE(size, elemsize) \
51 ((size_t)(size) <= (size_t)INT_MAX && \
52 (size_t)(size) <= UINT_MAX / (size_t)(elemsize))
53
Martin v. Löwis71e25a02002-10-01 18:08:06 +000054/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
55 making _tkinter correct for this API means to break earlier
56 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
57 earlier versions. Once Tcl releases before 8.4 don't need to be supported
58 anymore, this should go. */
59#define USE_COMPAT_CONST
60
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000061/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
62 it always; if Tcl is not threaded, the thread functions in
63 Tcl are empty. */
64#define TCL_THREADS
65
Jack Jansencb852442001-12-09 23:15:56 +000066#ifdef TK_FRAMEWORK
67#include <Tcl/tcl.h>
68#include <Tk/tk.h>
69#else
Guido van Rossum18468821994-06-20 07:49:28 +000070#include <tcl.h>
71#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000072#endif
Guido van Rossum18468821994-06-20 07:49:28 +000073
Guilherme Polo5d64c332009-04-05 02:11:19 +000074#include "tkinter.h"
75
Jason Tishlerbbe89612002-12-31 20:30:46 +000076/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000077#ifndef CONST84_RETURN
78#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000079#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000080#define CONST
81#endif
82
Guilherme Poloc5eba1e2009-02-09 20:57:45 +000083#if TK_VERSION_HEX < 0x08030102
84#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000085#endif
86
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000087/* Unicode conversion assumes that Tcl_UniChar is two bytes.
88 We cannot test this directly, so we test UTF-8 size instead,
89 expecting that TCL_UTF_MAX is changed if Tcl ever supports
Antoine Pitrouc83ea132010-05-09 14:46:46 +000090 either UTF-16 or UCS-4.
91 Redhat 8 sets TCL_UTF_MAX to 6, and uses wchar_t for
Martin v. Löwis6f29ff32003-04-16 20:34:55 +000092 Tcl_Unichar. This is also ok as long as Python uses UCS-4,
93 as well.
94*/
95#if TCL_UTF_MAX != 3 && !(defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==6)
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +000096#error "unsupported Tcl configuration"
97#endif
98
Jack Janseneddc1442003-11-20 01:44:59 +000099#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +0000100#define HAVE_CREATEFILEHANDLER
101#endif
102
Guido van Rossum00d93061998-05-28 23:06:38 +0000103#ifdef HAVE_CREATEFILEHANDLER
104
Neal Norwitzd948a432006-01-08 01:08:55 +0000105/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
106 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
107#ifndef TCL_UNIX_FD
108# ifdef TCL_WIN_SOCKET
109# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
110# else
111# define TCL_UNIX_FD 1
112# endif
113#endif
114
Guido van Rossum00d93061998-05-28 23:06:38 +0000115/* Tcl_CreateFileHandler() changed several times; these macros deal with the
116 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
117 Unix, only because Jack added it back); when available on Windows, it only
118 applies to sockets. */
119
Guido van Rossum7bf15641998-05-22 18:28:17 +0000120#ifdef MS_WINDOWS
121#define FHANDLETYPE TCL_WIN_SOCKET
122#else
123#define FHANDLETYPE TCL_UNIX_FD
124#endif
125
Guido van Rossum00d93061998-05-28 23:06:38 +0000126/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
127 which uses this to handle Tcl events while the user is typing commands. */
128
129#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000130#define WAIT_FOR_STDIN
131#endif
132
Guido van Rossum00d93061998-05-28 23:06:38 +0000133#endif /* HAVE_CREATEFILEHANDLER */
134
Guido van Rossumad4db171998-06-13 13:56:28 +0000135#ifdef MS_WINDOWS
136#include <conio.h>
137#define WAIT_FOR_STDIN
138#endif
139
Guido van Rossum00d93061998-05-28 23:06:38 +0000140#ifdef WITH_THREAD
141
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000142/* The threading situation is complicated. Tcl is not thread-safe, except
143 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000144 So we need to use a lock around all uses of Tcl. Previously, the Python
145 interpreter lock was used for this. However, this causes problems when
146 other Python threads need to run while Tcl is blocked waiting for events.
147
148 To solve this problem, a separate lock for Tcl is introduced. Holding it
149 is incompatible with holding Python's interpreter lock. The following four
150 macros manipulate both locks together.
151
152 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
153 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
154 that could call an event handler, or otherwise affect the state of a Tcl
155 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000156 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000157 released and the lock for Tcl has been acquired.
158
Guido van Rossum5e977831998-06-15 14:03:52 +0000159 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
160 (For example, when transferring data from the Tcl interpreter result to a
161 Python string object.) This can be done by using different macros to close
162 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
163 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
164 releases the Tcl lock.
165
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000166 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000167 handlers when the handler needs to use Python. Such event handlers are
168 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000169 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000170 the Python interpreter lock, restoring the appropriate thread state, and
171 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
172 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000173 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000174
175 These locks expand to several statements and brackets; they should not be
176 used in branches of if statements and the like.
177
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000178 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
179 only valid in the thread that created it, and all Tk activity must happen in this
180 thread, also. That means that the mainloop must be invoked in the thread that
181 created the interpreter. Invoking commands from other threads is possible;
182 _tkinter will queue an event for the interpreter thread, which will then
183 execute the command and pass back the result. If the main thread is not in the
184 mainloop, and invoking commands causes an exception; if the main loop is running
185 but not processing events, the command invocation will block.
186
187 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
188 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
189 threads. So we use the Tcl TLS API.
190
Guido van Rossum00d93061998-05-28 23:06:38 +0000191*/
192
Guido van Rossum65d5b571998-12-21 19:32:43 +0000193static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000194
195#ifdef TCL_THREADS
196static Tcl_ThreadDataKey state_key;
197typedef PyThreadState *ThreadSpecificData;
198#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
199#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000200static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000201#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000202
203#define ENTER_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000204 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
205 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000206
207#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000208 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000209
Guido van Rossum62320c91998-06-15 04:36:09 +0000210#define ENTER_OVERLAP \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000211 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000212
213#define LEAVE_OVERLAP_TCL \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000214 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000215
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000216#define ENTER_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000217 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
218 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000219
220#define LEAVE_PYTHON \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000221 { PyThreadState *tstate = PyEval_SaveThread(); \
222 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000223
224#define CHECK_TCL_APPARTMENT \
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000225 if (((TkappObject *)self)->threaded && \
226 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
227 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
228 return 0; \
229 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000230
231#else
232
233#define ENTER_TCL
234#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000235#define ENTER_OVERLAP
236#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000237#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000238#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000239#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000240
241#endif
242
Guido van Rossum97867b21996-08-08 19:09:53 +0000243#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000244#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000245#endif
246
Guido van Rossum18468821994-06-20 07:49:28 +0000247/**** Tkapp Object Declaration ****/
248
Jeremy Hylton938ace62002-07-17 16:30:39 +0000249static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000250
Guido van Rossum00d93061998-05-28 23:06:38 +0000251typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000252 PyObject_HEAD
253 Tcl_Interp *interp;
254 int wantobjects;
255 int threaded; /* True if tcl_platform[threaded] */
256 Tcl_ThreadId thread_id;
257 int dispatching;
258 /* We cannot include tclInt.h, as this is internal.
259 So we cache interesting types here. */
260 Tcl_ObjType *BooleanType;
261 Tcl_ObjType *ByteArrayType;
262 Tcl_ObjType *DoubleType;
263 Tcl_ObjType *IntType;
264 Tcl_ObjType *ListType;
265 Tcl_ObjType *ProcBodyType;
266 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000267} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000268
Christian Heimese93237d2007-12-19 02:37:44 +0000269#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000270#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000271#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000272
Guido van Rossum35d43371997-08-02 00:09:09 +0000273#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimese93237d2007-12-19 02:37:44 +0000274(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000275
Barry Warsawfa701a81997-01-16 00:15:11 +0000276
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000277
Guido van Rossum18468821994-06-20 07:49:28 +0000278/**** Error Handling ****/
279
280static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000281static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000282static int errorInCmd = 0;
283static PyObject *excInCmd;
284static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000285static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000286
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000287#ifdef TKINTER_PROTECT_LOADTK
288static int tk_load_failed;
289#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000290
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000291
Guido van Rossum18468821994-06-20 07:49:28 +0000292static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000293Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000294{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000295 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
296 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000297}
298
Barry Warsawfa701a81997-01-16 00:15:11 +0000299
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000300
Guido van Rossum18468821994-06-20 07:49:28 +0000301/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000302
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000303static int Tkinter_busywaitinterval = 20;
304
Guido van Rossum00d93061998-05-28 23:06:38 +0000305#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000306#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000307
Guido van Rossum00d93061998-05-28 23:06:38 +0000308/* Millisecond sleep() for Unix platforms. */
309
310static void
Fred Drake509d79a2000-07-08 04:04:38 +0000311Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000312{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000313 /* XXX Too bad if you don't have select(). */
314 struct timeval t;
315 t.tv_sec = milli/1000;
316 t.tv_usec = (milli%1000) * 1000;
317 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000318}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000319#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000320
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000321/* Wait up to 1s for the mainloop to come up. */
322
323static int
324WaitForMainloop(TkappObject* self)
325{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000326 int i;
327 for (i = 0; i < 10; i++) {
328 if (self->dispatching)
329 return 1;
330 Py_BEGIN_ALLOW_THREADS
331 Sleep(100);
332 Py_END_ALLOW_THREADS
333 }
334 if (self->dispatching)
335 return 1;
336 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
337 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000338}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000339#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000340
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000341
Guido van Rossum18468821994-06-20 07:49:28 +0000342static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000343AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000344{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000345 if (PyString_Check(value))
346 return PyString_AsString(value);
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000347#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000348 else if (PyUnicode_Check(value)) {
349 PyObject *v = PyUnicode_AsUTF8String(value);
350 if (v == NULL)
351 return NULL;
352 if (PyList_Append(tmp, v) != 0) {
353 Py_DECREF(v);
354 return NULL;
355 }
356 Py_DECREF(v);
357 return PyString_AsString(v);
358 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +0000359#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000360 else {
361 PyObject *v = PyObject_Str(value);
362 if (v == NULL)
363 return NULL;
364 if (PyList_Append(tmp, v) != 0) {
365 Py_DECREF(v);
366 return NULL;
367 }
368 Py_DECREF(v);
369 return PyString_AsString(v);
370 }
Guido van Rossum18468821994-06-20 07:49:28 +0000371}
372
Barry Warsawfa701a81997-01-16 00:15:11 +0000373
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000374
Guido van Rossum18468821994-06-20 07:49:28 +0000375#define ARGSZ 64
376
377static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000378Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000379{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000380 PyObject *tmp = NULL;
381 char *argvStore[ARGSZ];
382 char **argv = NULL;
383 int fvStore[ARGSZ];
384 int *fv = NULL;
Serhiy Storchaka42035702013-08-21 21:46:12 +0300385 Py_ssize_t argc = 0, fvc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000386 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000387
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000388 if (!(tmp = PyList_New(0)))
389 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000390
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000391 argv = argvStore;
392 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000393
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000394 if (args == NULL)
395 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000396
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000397 else if (!PyTuple_Check(args)) {
398 argc = 1;
399 fv[0] = 0;
400 if (!(argv[0] = AsString(args, tmp)))
401 goto finally;
402 }
403 else {
404 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000405
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000406 if (argc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +0300407 if (!CHECK_SIZE(argc, sizeof(char *))) {
408 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
409 goto finally;
410 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +0300411 argv = (char **)attemptckalloc((size_t)argc * sizeof(char *));
412 fv = (int *)attemptckalloc((size_t)argc * sizeof(int));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000413 if (argv == NULL || fv == NULL) {
414 PyErr_NoMemory();
415 goto finally;
416 }
417 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000418
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000419 for (i = 0; i < argc; i++) {
420 PyObject *v = PyTuple_GetItem(args, i);
421 if (PyTuple_Check(v)) {
422 fv[i] = 1;
423 if (!(argv[i] = Merge(v)))
424 goto finally;
425 fvc++;
426 }
427 else if (v == Py_None) {
428 argc = i;
429 break;
430 }
431 else {
432 fv[i] = 0;
433 if (!(argv[i] = AsString(v, tmp)))
434 goto finally;
435 fvc++;
436 }
437 }
438 }
439 res = Tcl_Merge(argc, argv);
440 if (res == NULL)
441 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000442
Barry Warsawfa701a81997-01-16 00:15:11 +0000443 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000444 for (i = 0; i < fvc; i++)
445 if (fv[i]) {
446 ckfree(argv[i]);
447 }
448 if (argv != argvStore)
449 ckfree(FREECAST argv);
450 if (fv != fvStore)
451 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000452
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000453 Py_DECREF(tmp);
454 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000455}
456
Barry Warsawfa701a81997-01-16 00:15:11 +0000457
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000458
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200459#ifdef Py_USING_UNICODE
460static PyObject *
461unicode_FromTclStringAndSize(const char *s, Py_ssize_t size)
462{
463 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
464 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
465 /* Tcl encodes null character as \xc0\x80 */
466 if (memchr(s, '\xc0', size)) {
467 char *buf, *q;
468 const char *e = s + size;
469 PyErr_Clear();
470 q = buf = (char *)PyMem_Malloc(size);
Serhiy Storchaka5d93f402014-07-14 12:20:01 +0300471 if (buf == NULL) {
472 PyErr_NoMemory();
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200473 return NULL;
Serhiy Storchaka5d93f402014-07-14 12:20:01 +0300474 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200475 while (s != e) {
476 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
477 *q++ = '\0';
478 s += 2;
479 }
480 else
481 *q++ = *s++;
482 }
483 s = buf;
484 size = q - s;
485 r = PyUnicode_DecodeUTF8(s, size, NULL);
486 PyMem_Free(buf);
487 }
488 }
489 return r;
490}
491#endif
492
493static PyObject *
494fromTclStringAndSize(const char *s, Py_ssize_t size)
495{
496 PyObject *r;
497#ifdef Py_USING_UNICODE
498 Py_ssize_t i;
499 /* If Tcl string contains any bytes with the top bit set,
500 it's UTF-8 and we should decode it to Unicode */
501 for (i = 0; i < size; i++)
502 if (s[i] & 0x80)
503 break;
504 if (i != size) {
505 /* It isn't an ASCII string. */
506 r = unicode_FromTclStringAndSize(s, size);
507 if (r)
508 return r;
509 PyErr_Clear();
510 }
511#endif
512 r = PyString_FromStringAndSize(s, size);
513 return r;
514}
515
516static PyObject *
517fromTclString(const char *s)
518{
519 return fromTclStringAndSize(s, strlen(s));
520}
521
522
Guido van Rossum18468821994-06-20 07:49:28 +0000523static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000524Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000525{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000526 int argc;
527 char **argv;
528 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000529
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000530 if (list == NULL) {
531 Py_INCREF(Py_None);
532 return Py_None;
533 }
Guido van Rossum18468821994-06-20 07:49:28 +0000534
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000535 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
536 /* Not a list.
537 * Could be a quoted string containing funnies, e.g. {"}.
538 * Return the string itself.
539 */
540 return PyString_FromString(list);
541 }
Guido van Rossum18468821994-06-20 07:49:28 +0000542
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000543 if (argc == 0)
544 v = PyString_FromString("");
545 else if (argc == 1)
546 v = PyString_FromString(argv[0]);
547 else if ((v = PyTuple_New(argc)) != NULL) {
548 int i;
549 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000550
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000551 for (i = 0; i < argc; i++) {
552 if ((w = Split(argv[i])) == NULL) {
553 Py_DECREF(v);
554 v = NULL;
555 break;
556 }
557 PyTuple_SetItem(v, i, w);
558 }
559 }
560 Tcl_Free(FREECAST argv);
561 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000562}
563
Martin v. Löwisffad6332002-11-26 09:28:05 +0000564/* In some cases, Tcl will still return strings that are supposed to be
565 lists. SplitObj walks through a nested tuple, finding string objects that
566 need to be split. */
567
Martin v. Löwis111c1802008-06-13 07:47:47 +0000568static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000569SplitObj(PyObject *arg)
570{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000571 if (PyTuple_Check(arg)) {
572 int i, size;
573 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000574
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000575 size = PyTuple_Size(arg);
576 result = NULL;
577 /* Recursively invoke SplitObj for all tuple items.
578 If this does not return a new object, no action is
579 needed. */
580 for(i = 0; i < size; i++) {
581 elem = PyTuple_GetItem(arg, i);
582 newelem = SplitObj(elem);
583 if (!newelem) {
584 Py_XDECREF(result);
585 return NULL;
586 }
587 if (!result) {
588 int k;
589 if (newelem == elem) {
590 Py_DECREF(newelem);
591 continue;
592 }
593 result = PyTuple_New(size);
594 if (!result)
595 return NULL;
596 for(k = 0; k < i; k++) {
597 elem = PyTuple_GetItem(arg, k);
598 Py_INCREF(elem);
599 PyTuple_SetItem(result, k, elem);
600 }
601 }
602 PyTuple_SetItem(result, i, newelem);
603 }
604 if (result)
605 return result;
606 /* Fall through, returning arg. */
607 }
608 else if (PyString_Check(arg)) {
609 int argc;
610 char **argv;
611 char *list = PyString_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000612
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000613 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
614 Py_INCREF(arg);
615 return arg;
616 }
617 Tcl_Free(FREECAST argv);
618 if (argc > 1)
619 return Split(PyString_AsString(arg));
620 /* Fall through, returning arg. */
621 }
Serhiy Storchakafab65422013-07-11 20:32:48 +0300622 else if (PyUnicode_Check(arg)) {
623 int argc;
624 char **argv;
625 char *list;
626 PyObject *s = PyUnicode_AsUTF8String(arg);
627
628 if (s == NULL) {
629 Py_INCREF(arg);
630 return arg;
631 }
632 list = PyString_AsString(s);
633
634 if (list == NULL ||
635 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
636 Py_DECREF(s);
637 Py_INCREF(arg);
638 return arg;
639 }
640 Tcl_Free(FREECAST argv);
641 if (argc > 1) {
642 PyObject *v = Split(list);
643 Py_DECREF(s);
644 return v;
645 }
646 Py_DECREF(s);
647 /* Fall through, returning arg. */
648 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000649 Py_INCREF(arg);
650 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000651}
Barry Warsawfa701a81997-01-16 00:15:11 +0000652
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000653
Guido van Rossum18468821994-06-20 07:49:28 +0000654/**** Tkapp Object ****/
655
656#ifndef WITH_APPINIT
657int
Fred Drake509d79a2000-07-08 04:04:38 +0000658Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000659{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000660 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000661
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000662 if (Tcl_Init(interp) == TCL_ERROR) {
663 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
664 return TCL_ERROR;
665 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000666
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000667 _tkinter_skip_tk_init = Tcl_GetVar(interp,
668 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
669 if (_tkinter_skip_tk_init != NULL &&
670 strcmp(_tkinter_skip_tk_init, "1") == 0) {
671 return TCL_OK;
672 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000673
674#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000675 if (tk_load_failed) {
676 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
677 return TCL_ERROR;
678 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000679#endif
680
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000681 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000682#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000683 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000684#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000685 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
686 return TCL_ERROR;
687 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000688
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000689 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000690}
691#endif /* !WITH_APPINIT */
692
Guido van Rossum18468821994-06-20 07:49:28 +0000693
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000694
Barry Warsawfa701a81997-01-16 00:15:11 +0000695
696/* Initialize the Tk application; see the `main' function in
697 * `tkMain.c'.
698 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000699
Thomas Wouters58d05102000-07-24 14:43:35 +0000700static void EnableEventHook(void); /* Forward */
701static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000702
Barry Warsawfa701a81997-01-16 00:15:11 +0000703static TkappObject *
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000704Tkapp_New(char *screenName, char *baseName, char *className,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000705 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000706{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000707 TkappObject *v;
708 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000709
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000710 v = PyObject_New(TkappObject, &Tkapp_Type);
711 if (v == NULL)
712 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000713
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000714 v->interp = Tcl_CreateInterp();
715 v->wantobjects = wantobjects;
716 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
717 TCL_GLOBAL_ONLY) != NULL;
718 v->thread_id = Tcl_GetCurrentThread();
719 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000720
721#ifndef TCL_THREADS
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000722 if (v->threaded) {
723 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
724 Py_DECREF(v);
725 return 0;
726 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000727#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000728#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000729 if (v->threaded && tcl_lock) {
730 /* If Tcl is threaded, we don't need the lock. */
731 PyThread_free_lock(tcl_lock);
732 tcl_lock = NULL;
733 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000734#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000735
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000736 v->BooleanType = Tcl_GetObjType("boolean");
737 v->ByteArrayType = Tcl_GetObjType("bytearray");
738 v->DoubleType = Tcl_GetObjType("double");
739 v->IntType = Tcl_GetObjType("int");
740 v->ListType = Tcl_GetObjType("list");
741 v->ProcBodyType = Tcl_GetObjType("procbody");
742 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000743
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000744 /* Delete the 'exit' command, which can screw things up */
745 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000746
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000747 if (screenName != NULL)
748 Tcl_SetVar2(v->interp, "env", "DISPLAY",
749 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000750
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000751 if (interactive)
752 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
753 else
754 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000755
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000756 /* This is used to get the application class for Tk 4.1 and up */
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +0300757 argv0 = (char*)attemptckalloc(strlen(className) + 1);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000758 if (!argv0) {
759 PyErr_NoMemory();
760 Py_DECREF(v);
761 return NULL;
762 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000763
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000764 strcpy(argv0, className);
Antoine Pitrou44b3b542011-10-04 13:55:37 +0200765 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
766 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000767 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
768 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000769
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000770 if (! wantTk) {
771 Tcl_SetVar(v->interp,
772 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
773 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000774#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000775 else if (tk_load_failed) {
776 Tcl_SetVar(v->interp,
777 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
778 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000779#endif
David Aschere2b4b322004-02-18 05:59:53 +0000780
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000781 /* some initial arguments need to be in argv */
782 if (sync || use) {
783 char *args;
784 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000785
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000786 if (sync)
787 len += sizeof "-sync";
788 if (use)
789 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000790
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +0300791 args = (char*)attemptckalloc(len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000792 if (!args) {
793 PyErr_NoMemory();
794 Py_DECREF(v);
795 return NULL;
796 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000797
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000798 args[0] = '\0';
799 if (sync)
800 strcat(args, "-sync");
801 if (use) {
802 if (sync)
803 strcat(args, " ");
804 strcat(args, "-use ");
805 strcat(args, use);
806 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000807
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000808 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
809 ckfree(args);
810 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000811
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000812 if (Tcl_AppInit(v->interp) != TCL_OK) {
813 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000814#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000815 if (wantTk) {
816 const char *_tkinter_tk_failed;
817 _tkinter_tk_failed = Tcl_GetVar(v->interp,
818 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000819
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000820 if ( _tkinter_tk_failed != NULL &&
821 strcmp(_tkinter_tk_failed, "1") == 0) {
822 tk_load_failed = 1;
823 }
824 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +0000825#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000826 Py_DECREF((PyObject *)v);
827 return (TkappObject *)result;
828 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000829
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000830 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000831
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000832 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000833}
834
Barry Warsawfa701a81997-01-16 00:15:11 +0000835
Guilherme Polo1972d162009-03-27 21:43:08 +0000836#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000837static void
838Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000839 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000840{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000841 Py_BEGIN_ALLOW_THREADS;
842 Tcl_MutexLock(mutex);
843 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
844 Tcl_ThreadAlert(self->thread_id);
845 Tcl_ConditionWait(cond, mutex, NULL);
846 Tcl_MutexUnlock(mutex);
847 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000848}
Guilherme Polo1972d162009-03-27 21:43:08 +0000849#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000850
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000851
Guido van Rossum18468821994-06-20 07:49:28 +0000852/** Tcl Eval **/
853
Martin v. Löwisffad6332002-11-26 09:28:05 +0000854typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000855 PyObject_HEAD
856 Tcl_Obj *value;
857 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000858} PyTclObject;
859
860staticforward PyTypeObject PyTclObject_Type;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000861#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000862
863static PyObject *
864newPyTclObject(Tcl_Obj *arg)
865{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000866 PyTclObject *self;
867 self = PyObject_New(PyTclObject, &PyTclObject_Type);
868 if (self == NULL)
869 return NULL;
870 Tcl_IncrRefCount(arg);
871 self->value = arg;
872 self->string = NULL;
873 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000874}
875
876static void
877PyTclObject_dealloc(PyTclObject *self)
878{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000879 Tcl_DecrRefCount(self->value);
880 Py_XDECREF(self->string);
881 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000882}
883
884static PyObject *
885PyTclObject_str(PyTclObject *self)
886{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000887 if (self->string && PyString_Check(self->string)) {
888 Py_INCREF(self->string);
889 return self->string;
890 }
891 /* XXX Could cache value if it is an ASCII string. */
892 return PyString_FromString(Tcl_GetString(self->value));
Martin v. Löwisffad6332002-11-26 09:28:05 +0000893}
894
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000895static char*
896PyTclObject_TclString(PyObject *self)
897{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000898 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000899}
900
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000901/* Like _str, but create Unicode if necessary. */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000902PyDoc_STRVAR(PyTclObject_string__doc__,
Martin v. Löwis39195712003-01-04 00:33:13 +0000903"the string representation of this object, either as string or Unicode");
904
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000905static PyObject *
906PyTclObject_string(PyTclObject *self, void *ignored)
907{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000908 if (!self->string) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200909 int len;
910 char *s = Tcl_GetStringFromObj(self->value, &len);
911 self->string = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000912 if (!self->string)
913 return NULL;
914 }
915 Py_INCREF(self->string);
916 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000917}
918
919#ifdef Py_USING_UNICODE
Martin v. Löwis39195712003-01-04 00:33:13 +0000920PyDoc_STRVAR(PyTclObject_unicode__doc__, "convert argument to unicode");
921
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000922static PyObject *
923PyTclObject_unicode(PyTclObject *self, void *ignored)
924{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000925 char *s;
926 int len;
927 if (self->string && PyUnicode_Check(self->string)) {
928 Py_INCREF(self->string);
929 return self->string;
930 }
931 /* XXX Could chache result if it is non-ASCII. */
932 s = Tcl_GetStringFromObj(self->value, &len);
Serhiy Storchakaccffb252014-02-03 21:23:46 +0200933 return unicode_FromTclStringAndSize(s, len);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000934}
935#endif
936
Martin v. Löwisffad6332002-11-26 09:28:05 +0000937static PyObject *
938PyTclObject_repr(PyTclObject *self)
939{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000940 char buf[50];
941 PyOS_snprintf(buf, 50, "<%s object at %p>",
942 self->value->typePtr->name, self->value);
943 return PyString_FromString(buf);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000944}
945
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000946static int
947PyTclObject_cmp(PyTclObject *self, PyTclObject *other)
948{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000949 int res;
950 res = strcmp(Tcl_GetString(self->value),
951 Tcl_GetString(other->value));
952 if (res < 0) return -1;
953 if (res > 0) return 1;
954 return 0;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000955}
956
Martin v. Löwis39195712003-01-04 00:33:13 +0000957PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
958
Martin v. Löwisffad6332002-11-26 09:28:05 +0000959static PyObject*
960get_typename(PyTclObject* obj, void* ignored)
961{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000962 return PyString_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000963}
964
Martin v. Löwis39195712003-01-04 00:33:13 +0000965
Martin v. Löwisffad6332002-11-26 09:28:05 +0000966static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000967 {"typename", (getter)get_typename, NULL, get_typename__doc__},
968 {"string", (getter)PyTclObject_string, NULL,
969 PyTclObject_string__doc__},
970 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000971};
972
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000973static PyMethodDef PyTclObject_methods[] = {
Martin v. Löwise2713be2005-03-08 15:03:08 +0000974#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000975 {"__unicode__", (PyCFunction)PyTclObject_unicode, METH_NOARGS,
976 PyTclObject_unicode__doc__},
Martin v. Löwise2713be2005-03-08 15:03:08 +0000977#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000978 {0}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000979};
980
Martin v. Löwisffad6332002-11-26 09:28:05 +0000981statichere PyTypeObject PyTclObject_Type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000982 PyObject_HEAD_INIT(NULL)
983 0, /*ob_size*/
984 "_tkinter.Tcl_Obj", /*tp_name*/
985 sizeof(PyTclObject), /*tp_basicsize*/
986 0, /*tp_itemsize*/
987 /* methods */
988 (destructor)PyTclObject_dealloc, /*tp_dealloc*/
989 0, /*tp_print*/
990 0, /*tp_getattr*/
991 0, /*tp_setattr*/
992 (cmpfunc)PyTclObject_cmp, /*tp_compare*/
993 (reprfunc)PyTclObject_repr, /*tp_repr*/
994 0, /*tp_as_number*/
995 0, /*tp_as_sequence*/
996 0, /*tp_as_mapping*/
997 0, /*tp_hash*/
998 0, /*tp_call*/
999 (reprfunc)PyTclObject_str, /*tp_str*/
1000 PyObject_GenericGetAttr,/*tp_getattro*/
1001 0, /*tp_setattro*/
1002 0, /*tp_as_buffer*/
1003 Py_TPFLAGS_DEFAULT, /*tp_flags*/
1004 0, /*tp_doc*/
1005 0, /*tp_traverse*/
1006 0, /*tp_clear*/
1007 0, /*tp_richcompare*/
1008 0, /*tp_weaklistoffset*/
1009 0, /*tp_iter*/
1010 0, /*tp_iternext*/
1011 PyTclObject_methods, /*tp_methods*/
1012 0, /*tp_members*/
1013 PyTclObject_getsetlist, /*tp_getset*/
1014 0, /*tp_base*/
1015 0, /*tp_dict*/
1016 0, /*tp_descr_get*/
1017 0, /*tp_descr_set*/
1018 0, /*tp_dictoffset*/
1019 0, /*tp_init*/
1020 0, /*tp_alloc*/
1021 0, /*tp_new*/
1022 0, /*tp_free*/
1023 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +00001024};
1025
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001026#if PY_SIZE_MAX > INT_MAX
1027#define CHECK_STRING_LENGTH(s) do { \
1028 if (s != NULL && strlen(s) >= INT_MAX) { \
1029 PyErr_SetString(PyExc_OverflowError, "string is too long"); \
1030 return NULL; \
1031 } } while(0)
1032#else
1033#define CHECK_STRING_LENGTH(s)
1034#endif
1035
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001036static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +00001037AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001038{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001039 Tcl_Obj *result;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001040
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001041 if (PyString_Check(value))
1042 return Tcl_NewStringObj(PyString_AS_STRING(value),
1043 PyString_GET_SIZE(value));
1044 else if (PyBool_Check(value))
1045 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
1046 else if (PyInt_Check(value))
1047 return Tcl_NewLongObj(PyInt_AS_LONG(value));
1048 else if (PyFloat_Check(value))
1049 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
1050 else if (PyTuple_Check(value)) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001051 Tcl_Obj **argv;
1052 Py_ssize_t size, i;
1053
1054 size = PyTuple_Size(value);
Serhiy Storchaka17c01782014-09-11 10:56:59 +03001055 if (size == 0)
1056 return Tcl_NewListObj(0, NULL);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001057 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
1058 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1059 return NULL;
1060 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001061 argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001062 if(!argv)
1063 return 0;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001064 for (i = 0; i < size; i++)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001065 argv[i] = AsObj(PyTuple_GetItem(value,i));
1066 result = Tcl_NewListObj(PyTuple_Size(value), argv);
1067 ckfree(FREECAST argv);
1068 return result;
1069 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001070#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001071 else if (PyUnicode_Check(value)) {
1072 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
1073 Py_ssize_t size = PyUnicode_GET_SIZE(value);
1074 /* This #ifdef assumes that Tcl uses UCS-2.
1075 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001076#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001077 Tcl_UniChar *outbuf = NULL;
1078 Py_ssize_t i;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001079 size_t allocsize;
Serhiy Storchaka17c01782014-09-11 10:56:59 +03001080 if (size == 0)
1081 return Tcl_NewUnicodeObj((const void *)"", 0);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001082 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1083 PyErr_SetString(PyExc_OverflowError, "string is too long");
1084 return NULL;
1085 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001086 if (sizeof(Py_UNICODE) == sizeof(Tcl_UniChar))
1087 return Tcl_NewUnicodeObj(inbuf, size);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001088 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001089 if (allocsize >= size)
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001090 outbuf = (Tcl_UniChar*)attemptckalloc(allocsize);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001091 /* Else overflow occurred, and we take the next exit */
1092 if (!outbuf) {
1093 PyErr_NoMemory();
1094 return NULL;
1095 }
1096 for (i = 0; i < size; i++) {
1097 if (inbuf[i] >= 0x10000) {
1098 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka46764482013-02-18 13:00:08 +02001099 PyErr_Format(Tkinter_TclError,
1100 "character U+%x is above the range "
1101 "(U+0000-U+FFFF) allowed by Tcl",
1102 (int)inbuf[i]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001103 ckfree(FREECAST outbuf);
1104 return NULL;
1105 }
1106 outbuf[i] = inbuf[i];
1107 }
1108 result = Tcl_NewUnicodeObj(outbuf, size);
1109 ckfree(FREECAST outbuf);
1110 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001111#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001112 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001113#endif
1114
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001115 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001116#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001117 else if(PyTclObject_Check(value)) {
1118 Tcl_Obj *v = ((PyTclObject*)value)->value;
1119 Tcl_IncrRefCount(v);
1120 return v;
1121 }
1122 else {
1123 PyObject *v = PyObject_Str(value);
1124 if (!v)
1125 return 0;
1126 result = AsObj(v);
1127 Py_DECREF(v);
1128 return result;
1129 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001130}
1131
Martin v. Löwisffad6332002-11-26 09:28:05 +00001132static PyObject*
1133FromObj(PyObject* tkapp, Tcl_Obj *value)
1134{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001135 PyObject *result = NULL;
1136 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001137
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001138 if (value->typePtr == NULL) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001139 result = fromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001140 return result;
1141 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001142
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001143 if (value->typePtr == app->BooleanType) {
1144 result = value->internalRep.longValue ? Py_True : Py_False;
1145 Py_INCREF(result);
1146 return result;
1147 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001148
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001149 if (value->typePtr == app->ByteArrayType) {
1150 int size;
1151 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1152 return PyString_FromStringAndSize(data, size);
1153 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001154
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001155 if (value->typePtr == app->DoubleType) {
1156 return PyFloat_FromDouble(value->internalRep.doubleValue);
1157 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001158
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001159 if (value->typePtr == app->IntType) {
1160 return PyInt_FromLong(value->internalRep.longValue);
1161 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001162
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001163 if (value->typePtr == app->ListType) {
1164 int size;
1165 int i, status;
1166 PyObject *elem;
1167 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001168
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001169 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1170 if (status == TCL_ERROR)
1171 return Tkinter_Error(tkapp);
1172 result = PyTuple_New(size);
1173 if (!result)
1174 return NULL;
1175 for (i = 0; i < size; i++) {
1176 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1177 value, i, &tcl_elem);
1178 if (status == TCL_ERROR) {
1179 Py_DECREF(result);
1180 return Tkinter_Error(tkapp);
1181 }
1182 elem = FromObj(tkapp, tcl_elem);
1183 if (!elem) {
1184 Py_DECREF(result);
1185 return NULL;
1186 }
1187 PyTuple_SetItem(result, i, elem);
1188 }
1189 return result;
1190 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001191
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001192 if (value->typePtr == app->ProcBodyType) {
1193 /* fall through: return tcl object. */
1194 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001195
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001196 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001197#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001198#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001199 PyObject *result;
1200 int size;
1201 Tcl_UniChar *input;
1202 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001203
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001204 size = Tcl_GetCharLength(value);
1205 result = PyUnicode_FromUnicode(NULL, size);
1206 if (!result)
1207 return NULL;
1208 input = Tcl_GetUnicode(value);
1209 output = PyUnicode_AS_UNICODE(result);
1210 while (size--)
1211 *output++ = *input++;
1212 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001213#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001214 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1215 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001216#endif
1217#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001218 int size;
1219 char *c;
1220 c = Tcl_GetStringFromObj(value, &size);
1221 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001222#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001223 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001224
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001225 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001226}
1227
Guilherme Polo1972d162009-03-27 21:43:08 +00001228#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001229/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001230TCL_DECLARE_MUTEX(call_mutex)
1231
1232typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001233 Tcl_Event ev; /* Must be first */
1234 TkappObject *self;
1235 PyObject *args;
1236 int flags;
1237 PyObject **res;
1238 PyObject **exc_type, **exc_value, **exc_tb;
1239 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001240} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001241#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001242
1243void
1244Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001245{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001246 int i;
1247 for (i = 0; i < objc; i++)
1248 Tcl_DecrRefCount(objv[i]);
1249 if (objv != objStore)
1250 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001251}
Guido van Rossum18468821994-06-20 07:49:28 +00001252
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001253/* Convert Python objects to Tcl objects. This must happen in the
1254 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001255
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001256static Tcl_Obj**
1257Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1258{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001259 Tcl_Obj **objv = objStore;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001260 Py_ssize_t objc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001261 if (args == NULL)
1262 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001263
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001264 else if (!PyTuple_Check(args)) {
1265 objv[0] = AsObj(args);
1266 if (objv[0] == 0)
1267 goto finally;
1268 objc = 1;
1269 Tcl_IncrRefCount(objv[0]);
1270 }
1271 else {
1272 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001273
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001274 if (objc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001275 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1276 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1277 return NULL;
1278 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001279 objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001280 if (objv == NULL) {
1281 PyErr_NoMemory();
1282 objc = 0;
1283 goto finally;
1284 }
1285 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001286
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001287 for (i = 0; i < objc; i++) {
1288 PyObject *v = PyTuple_GetItem(args, i);
1289 if (v == Py_None) {
1290 objc = i;
1291 break;
1292 }
1293 objv[i] = AsObj(v);
1294 if (!objv[i]) {
1295 /* Reset objc, so it attempts to clear
1296 objects only up to i. */
1297 objc = i;
1298 goto finally;
1299 }
1300 Tcl_IncrRefCount(objv[i]);
1301 }
1302 }
1303 *pobjc = objc;
1304 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001305finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001306 Tkapp_CallDeallocArgs(objv, objStore, objc);
1307 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001308}
Guido van Rossum212643f1998-04-29 16:22:14 +00001309
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001310/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001311
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001312static PyObject*
1313Tkapp_CallResult(TkappObject *self)
1314{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001315 PyObject *res = NULL;
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001316 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001317 if(self->wantobjects) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001318 /* Not sure whether the IncrRef is necessary, but something
1319 may overwrite the interpreter result while we are
1320 converting it. */
1321 Tcl_IncrRefCount(value);
1322 res = FromObj((PyObject*)self, value);
1323 Tcl_DecrRefCount(value);
1324 } else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001325 int len;
1326 const char *s = Tcl_GetStringFromObj(value, &len);
1327 res = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001328 }
1329 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001330}
Guido van Rossum632de272000-03-29 00:19:50 +00001331
Guilherme Polo1972d162009-03-27 21:43:08 +00001332#ifdef WITH_THREAD
1333
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334/* Tkapp_CallProc is the event procedure that is executed in the context of
1335 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1336 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001337
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001338static int
1339Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1340{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001341 Tcl_Obj *objStore[ARGSZ];
1342 Tcl_Obj **objv;
1343 int objc;
1344 int i;
1345 ENTER_PYTHON
1346 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1347 if (!objv) {
1348 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1349 *(e->res) = NULL;
1350 }
1351 LEAVE_PYTHON
1352 if (!objv)
1353 goto done;
1354 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1355 ENTER_PYTHON
1356 if (i == TCL_ERROR) {
1357 *(e->res) = NULL;
1358 *(e->exc_type) = NULL;
1359 *(e->exc_tb) = NULL;
1360 *(e->exc_value) = PyObject_CallFunction(
1361 Tkinter_TclError, "s",
1362 Tcl_GetStringResult(e->self->interp));
1363 }
1364 else {
1365 *(e->res) = Tkapp_CallResult(e->self);
1366 }
1367 LEAVE_PYTHON
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001368
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001369 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001370done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001371 /* Wake up calling thread. */
1372 Tcl_MutexLock(&call_mutex);
1373 Tcl_ConditionNotify(e->done);
1374 Tcl_MutexUnlock(&call_mutex);
1375 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001376}
1377
Guilherme Polo1972d162009-03-27 21:43:08 +00001378#endif
1379
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001380/* This is the main entry point for calling a Tcl command.
1381 It supports three cases, with regard to threading:
1382 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1383 the context of the calling thread.
1384 2. Tcl is threaded, caller of the command is in the interpreter thread:
1385 Execute the command in the calling thread. Since the Tcl lock will
1386 not be used, we can merge that with case 1.
1387 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1388 the interpreter thread. Allocation of Tcl objects needs to occur in the
1389 interpreter thread, so we ship the PyObject* args to the target thread,
1390 and perform processing there. */
1391
1392static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001393Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001394{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001395 Tcl_Obj *objStore[ARGSZ];
1396 Tcl_Obj **objv = NULL;
1397 int objc, i;
1398 PyObject *res = NULL;
1399 TkappObject *self = (TkappObject*)selfptr;
1400 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001401
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001402 /* If args is a single tuple, replace with contents of tuple */
1403 if (1 == PyTuple_Size(args)){
1404 PyObject* item = PyTuple_GetItem(args, 0);
1405 if (PyTuple_Check(item))
1406 args = item;
1407 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001408#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001409 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1410 /* We cannot call the command directly. Instead, we must
1411 marshal the parameters to the interpreter thread. */
1412 Tkapp_CallEvent *ev;
1413 Tcl_Condition cond = NULL;
1414 PyObject *exc_type, *exc_value, *exc_tb;
1415 if (!WaitForMainloop(self))
1416 return NULL;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001417 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1418 if (ev == NULL) {
1419 PyErr_NoMemory();
1420 return NULL;
1421 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001422 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1423 ev->self = self;
1424 ev->args = args;
1425 ev->res = &res;
1426 ev->exc_type = &exc_type;
1427 ev->exc_value = &exc_value;
1428 ev->exc_tb = &exc_tb;
1429 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001430
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001431 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001432
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001433 if (res == NULL) {
1434 if (exc_type)
1435 PyErr_Restore(exc_type, exc_value, exc_tb);
1436 else
1437 PyErr_SetObject(Tkinter_TclError, exc_value);
1438 }
1439 Tcl_ConditionFinalize(&cond);
1440 }
1441 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001442#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001443 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001444
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001445 objv = Tkapp_CallArgs(args, objStore, &objc);
1446 if (!objv)
1447 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001448
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001449 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001450
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001451 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001452
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001453 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001454
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001455 if (i == TCL_ERROR)
1456 Tkinter_Error(selfptr);
1457 else
1458 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001459
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001460 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001461
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001462 Tkapp_CallDeallocArgs(objv, objStore, objc);
1463 }
1464 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001465}
1466
1467
1468static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001469Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001470{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001471 /* Could do the same here as for Tkapp_Call(), but this is not used
1472 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1473 way for the user to do what all its Global* variants do (save and
1474 reset the scope pointer, call the local version, restore the saved
1475 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001476
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001477 char *cmd;
1478 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001479
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001480 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001481
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001482 cmd = Merge(args);
1483 if (cmd) {
1484 int err;
1485 ENTER_TCL
1486 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1487 ENTER_OVERLAP
1488 if (err == TCL_ERROR)
1489 res = Tkinter_Error(self);
1490 else
1491 res = PyString_FromString(Tkapp_Result(self));
1492 LEAVE_OVERLAP_TCL
1493 ckfree(cmd);
1494 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001495
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001496 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001497}
1498
1499static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001500Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001501{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001502 char *script;
1503 PyObject *res = NULL;
1504 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001505
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001506 if (!PyArg_ParseTuple(args, "s:eval", &script))
1507 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001508
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001509 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001510 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001511
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001512 ENTER_TCL
1513 err = Tcl_Eval(Tkapp_Interp(self), script);
1514 ENTER_OVERLAP
1515 if (err == TCL_ERROR)
1516 res = Tkinter_Error(self);
1517 else
1518 res = PyString_FromString(Tkapp_Result(self));
1519 LEAVE_OVERLAP_TCL
1520 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001521}
1522
1523static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001524Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001525{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001526 char *script;
1527 PyObject *res = NULL;
1528 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001529
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001530 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1531 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001532
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001533 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001534
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001535 ENTER_TCL
1536 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1537 ENTER_OVERLAP
1538 if (err == TCL_ERROR)
1539 res = Tkinter_Error(self);
1540 else
1541 res = PyString_FromString(Tkapp_Result(self));
1542 LEAVE_OVERLAP_TCL
1543 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001544}
1545
1546static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001547Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001548{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001549 char *fileName;
1550 PyObject *res = NULL;
1551 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001552
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001553 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1554 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001555
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001556 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001557 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001558
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001559 ENTER_TCL
1560 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1561 ENTER_OVERLAP
1562 if (err == TCL_ERROR)
1563 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001564
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001565 else
1566 res = PyString_FromString(Tkapp_Result(self));
1567 LEAVE_OVERLAP_TCL
1568 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001569}
1570
1571static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001572Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001573{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001574 char *script;
1575 PyObject *res = NULL;
1576 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001577
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001578 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001579 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001580
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001581 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001582 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001583
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001584 ENTER_TCL
1585 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1586 ENTER_OVERLAP
1587 if (err == TCL_ERROR)
1588 res = Tkinter_Error(self);
1589 else
1590 res = PyString_FromString(Tkapp_Result(self));
1591 LEAVE_OVERLAP_TCL
1592 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001593}
1594
1595static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001596Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001597{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001598 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001599
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001600 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1601 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001602 CHECK_STRING_LENGTH(msg);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001603 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001604
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001605 ENTER_TCL
1606 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1607 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001608
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001609 Py_INCREF(Py_None);
1610 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001611}
1612
Barry Warsawfa701a81997-01-16 00:15:11 +00001613
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001614
Guido van Rossum18468821994-06-20 07:49:28 +00001615/** Tcl Variable **/
1616
Guilherme Polo1972d162009-03-27 21:43:08 +00001617typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1618
1619#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001620TCL_DECLARE_MUTEX(var_mutex)
1621
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001622typedef struct VarEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001623 Tcl_Event ev; /* must be first */
1624 PyObject *self;
1625 PyObject *args;
1626 int flags;
1627 EventFunc func;
1628 PyObject **res;
1629 PyObject **exc_type;
1630 PyObject **exc_val;
1631 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001632} VarEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001633#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001634
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001635static int
1636varname_converter(PyObject *in, void *_out)
1637{
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001638 char *s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001639 char **out = (char**)_out;
1640 if (PyString_Check(in)) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001641 if (PyString_Size(in) > INT_MAX) {
1642 PyErr_SetString(PyExc_OverflowError, "string is too long");
1643 return 0;
1644 }
1645 s = PyString_AsString(in);
1646 if (strlen(s) != PyString_Size(in)) {
1647 PyErr_SetString(PyExc_ValueError, "null character in string");
1648 return 0;
1649 }
1650 *out = s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001651 return 1;
1652 }
1653 if (PyTclObject_Check(in)) {
1654 *out = PyTclObject_TclString(in);
1655 return 1;
1656 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001657 PyErr_Format(PyExc_TypeError,
1658 "must be str or Tcl_Obj, not %.50s",
1659 in->ob_type->tp_name);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001660 return 0;
1661}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001662
Guilherme Polo1972d162009-03-27 21:43:08 +00001663#ifdef WITH_THREAD
1664
Martin v. Löwis111c1802008-06-13 07:47:47 +00001665static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001666var_perform(VarEvent *ev)
1667{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001668 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1669 if (!*(ev->res)) {
1670 PyObject *exc, *val, *tb;
1671 PyErr_Fetch(&exc, &val, &tb);
1672 PyErr_NormalizeException(&exc, &val, &tb);
1673 *(ev->exc_type) = exc;
1674 *(ev->exc_val) = val;
1675 Py_DECREF(tb);
1676 }
1677
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001678}
1679
1680static int
1681var_proc(VarEvent* ev, int flags)
1682{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001683 ENTER_PYTHON
1684 var_perform(ev);
1685 Tcl_MutexLock(&var_mutex);
1686 Tcl_ConditionNotify(ev->cond);
1687 Tcl_MutexUnlock(&var_mutex);
1688 LEAVE_PYTHON
1689 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001690}
1691
Guilherme Polo1972d162009-03-27 21:43:08 +00001692#endif
1693
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001694static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001695var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001696{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001697#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001698 TkappObject *self = (TkappObject*)selfptr;
1699 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1700 TkappObject *self = (TkappObject*)selfptr;
1701 VarEvent *ev;
1702 PyObject *res, *exc_type, *exc_val;
1703 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001704
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001705 /* The current thread is not the interpreter thread. Marshal
1706 the call to the interpreter thread, then wait for
1707 completion. */
1708 if (!WaitForMainloop(self))
1709 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001710
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001711 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1712 if (ev == NULL) {
1713 PyErr_NoMemory();
1714 return NULL;
1715 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001716 ev->self = selfptr;
1717 ev->args = args;
1718 ev->flags = flags;
1719 ev->func = func;
1720 ev->res = &res;
1721 ev->exc_type = &exc_type;
1722 ev->exc_val = &exc_val;
1723 ev->cond = &cond;
1724 ev->ev.proc = (Tcl_EventProc*)var_proc;
1725 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1726 Tcl_ConditionFinalize(&cond);
1727 if (!res) {
1728 PyErr_SetObject(exc_type, exc_val);
1729 Py_DECREF(exc_type);
1730 Py_DECREF(exc_val);
1731 return NULL;
1732 }
1733 return res;
1734 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001735#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001736 /* Tcl is not threaded, or this is the interpreter thread. */
1737 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001738}
1739
Guido van Rossum18468821994-06-20 07:49:28 +00001740static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001741SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001742{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001743 char *name1, *name2;
1744 PyObject *newValue;
1745 PyObject *res = NULL;
1746 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001747
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001748 switch (PyTuple_GET_SIZE(args)) {
1749 case 2:
1750 if (!PyArg_ParseTuple(args, "O&O:setvar",
1751 varname_converter, &name1, &newValue))
1752 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001753 /* XXX Acquire tcl lock??? */
1754 newval = AsObj(newValue);
1755 if (newval == NULL)
1756 return NULL;
1757 ENTER_TCL
1758 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1759 newval, flags);
1760 ENTER_OVERLAP
1761 if (!ok)
1762 Tkinter_Error(self);
1763 else {
1764 res = Py_None;
1765 Py_INCREF(res);
1766 }
1767 LEAVE_OVERLAP_TCL
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001768 break;
1769 case 3:
1770 if (!PyArg_ParseTuple(args, "ssO:setvar",
1771 &name1, &name2, &newValue))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001772 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001773 CHECK_STRING_LENGTH(name1);
1774 CHECK_STRING_LENGTH(name2);
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001775 /* XXX must hold tcl lock already??? */
1776 newval = AsObj(newValue);
1777 ENTER_TCL
1778 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1779 ENTER_OVERLAP
1780 if (!ok)
1781 Tkinter_Error(self);
1782 else {
1783 res = Py_None;
1784 Py_INCREF(res);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001785 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001786 LEAVE_OVERLAP_TCL
1787 break;
1788 default:
1789 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1790 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001791 }
1792 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001793}
1794
1795static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001796Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001797{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001798 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001799}
1800
1801static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001802Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001803{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001804 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001805}
1806
Barry Warsawfa701a81997-01-16 00:15:11 +00001807
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001808
Guido van Rossum18468821994-06-20 07:49:28 +00001809static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001810GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001811{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001812 char *name1, *name2=NULL;
1813 PyObject *res = NULL;
1814 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001815
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001816 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1817 varname_converter, &name1, &name2))
1818 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001819
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001820 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001821 ENTER_TCL
1822 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1823 ENTER_OVERLAP
1824 if (tres == NULL) {
1825 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1826 } else {
1827 if (((TkappObject*)self)->wantobjects) {
1828 res = FromObj(self, tres);
1829 }
1830 else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001831 int len;
1832 char *s = Tcl_GetStringFromObj(tres, &len);
1833 res = PyString_FromStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001834 }
1835 }
1836 LEAVE_OVERLAP_TCL
1837 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001838}
1839
1840static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001841Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001842{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001843 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001844}
1845
1846static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001847Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001848{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001849 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001850}
1851
Barry Warsawfa701a81997-01-16 00:15:11 +00001852
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001853
Guido van Rossum18468821994-06-20 07:49:28 +00001854static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001855UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001856{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001857 char *name1, *name2=NULL;
1858 int code;
1859 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001860
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001861 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1862 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001863
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001864 CHECK_STRING_LENGTH(name1);
1865 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001866 ENTER_TCL
1867 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1868 ENTER_OVERLAP
1869 if (code == TCL_ERROR)
1870 res = Tkinter_Error(self);
1871 else {
1872 Py_INCREF(Py_None);
1873 res = Py_None;
1874 }
1875 LEAVE_OVERLAP_TCL
1876 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001877}
1878
1879static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001880Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001881{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001882 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001883}
1884
1885static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001886Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001887{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001888 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001889}
1890
Barry Warsawfa701a81997-01-16 00:15:11 +00001891
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001892
Guido van Rossum18468821994-06-20 07:49:28 +00001893/** Tcl to Python **/
1894
1895static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001896Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001897{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001898 char *s;
1899 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001900
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001901 if (PyTuple_Size(args) == 1) {
1902 PyObject* o = PyTuple_GetItem(args, 0);
1903 if (PyInt_Check(o)) {
1904 Py_INCREF(o);
1905 return o;
1906 }
1907 }
1908 if (!PyArg_ParseTuple(args, "s:getint", &s))
1909 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001910 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001911 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1912 return Tkinter_Error(self);
1913 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001914}
1915
1916static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001917Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001918{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001919 char *s;
1920 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001921
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001922 if (PyTuple_Size(args) == 1) {
1923 PyObject *o = PyTuple_GetItem(args, 0);
1924 if (PyFloat_Check(o)) {
1925 Py_INCREF(o);
1926 return o;
1927 }
1928 }
1929 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1930 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001931 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001932 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1933 return Tkinter_Error(self);
1934 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001935}
1936
1937static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001938Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001939{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001940 char *s;
1941 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001942
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001943 if (PyTuple_Size(args) == 1) {
1944 PyObject *o = PyTuple_GetItem(args, 0);
1945 if (PyInt_Check(o)) {
1946 Py_INCREF(o);
1947 return o;
1948 }
1949 }
1950 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1951 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001952 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001953 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1954 return Tkinter_Error(self);
1955 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001956}
1957
1958static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001959Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001960{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001961 char *s;
1962 PyObject *res = NULL;
1963 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001964
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001965 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1966 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001967
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001968 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001969 CHECK_TCL_APPARTMENT;
1970
1971 ENTER_TCL
1972 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1973 ENTER_OVERLAP
1974 if (retval == TCL_ERROR)
1975 res = Tkinter_Error(self);
1976 else
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001977 res = PyString_FromString(Tkapp_Result(self));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001978 LEAVE_OVERLAP_TCL
1979 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001980}
1981
1982static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001983Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001984{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001985 char *s;
1986 PyObject *res = NULL;
1987 int retval;
1988 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001989
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001990 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1991 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001992
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001993 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001994 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001995
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001996 ENTER_TCL
1997 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1998 ENTER_OVERLAP
1999 if (retval == TCL_ERROR)
2000 res = Tkinter_Error(self);
2001 else
2002 res = Py_BuildValue("l", v);
2003 LEAVE_OVERLAP_TCL
2004 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002005}
2006
2007static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002008Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002009{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002010 char *s;
2011 PyObject *res = NULL;
2012 double v;
2013 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002014
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002015 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2016 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002017 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002018 CHECK_TCL_APPARTMENT;
2019 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2020 ENTER_TCL
2021 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2022 ENTER_OVERLAP
2023 PyFPE_END_PROTECT(retval)
2024 if (retval == TCL_ERROR)
2025 res = Tkinter_Error(self);
2026 else
2027 res = Py_BuildValue("d", v);
2028 LEAVE_OVERLAP_TCL
2029 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002030}
2031
2032static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002033Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002034{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002035 char *s;
2036 PyObject *res = NULL;
2037 int retval;
2038 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002039
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002040 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2041 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002042 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002043 CHECK_TCL_APPARTMENT;
2044 ENTER_TCL
2045 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2046 ENTER_OVERLAP
2047 if (retval == TCL_ERROR)
2048 res = Tkinter_Error(self);
2049 else
2050 res = Py_BuildValue("i", v);
2051 LEAVE_OVERLAP_TCL
2052 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002053}
2054
Barry Warsawfa701a81997-01-16 00:15:11 +00002055
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002056
Guido van Rossum18468821994-06-20 07:49:28 +00002057static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002058Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002059{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002060 char *list;
2061 int argc;
2062 char **argv;
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002063 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002064 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002065
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002066 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2067 return NULL;
2068 if (PyTclObject_Check(arg)) {
2069 int objc;
2070 Tcl_Obj **objv;
2071 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2072 ((PyTclObject*)arg)->value,
2073 &objc, &objv) == TCL_ERROR) {
2074 return Tkinter_Error(self);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002075 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002076 if (!(v = PyTuple_New(objc)))
2077 return NULL;
2078 for (i = 0; i < objc; i++) {
2079 PyObject *s = FromObj(self, objv[i]);
2080 if (!s || PyTuple_SetItem(v, i, s)) {
2081 Py_DECREF(v);
2082 return NULL;
2083 }
2084 }
2085 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002086 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002087 if (PyTuple_Check(arg)) {
2088 Py_INCREF(arg);
2089 return arg;
2090 }
2091
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002092 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2093 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002094
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002095 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002096 if (Tcl_SplitList(Tkapp_Interp(self), list,
2097 &argc, &argv) == TCL_ERROR) {
2098 PyMem_Free(list);
2099 return Tkinter_Error(self);
2100 }
Guido van Rossum18468821994-06-20 07:49:28 +00002101
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002102 if (!(v = PyTuple_New(argc)))
2103 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002104
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002105 for (i = 0; i < argc; i++) {
2106 PyObject *s = PyString_FromString(argv[i]);
2107 if (!s || PyTuple_SetItem(v, i, s)) {
2108 Py_DECREF(v);
2109 v = NULL;
2110 goto finally;
2111 }
2112 }
Guido van Rossum18468821994-06-20 07:49:28 +00002113
Barry Warsawfa701a81997-01-16 00:15:11 +00002114 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002115 ckfree(FREECAST argv);
2116 PyMem_Free(list);
2117 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002118}
2119
2120static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002121Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002122{
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002123 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002124 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002125
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002126 if (!PyArg_ParseTuple(args, "O:split", &arg))
2127 return NULL;
2128 if (PyTclObject_Check(arg)) {
2129 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2130 int objc;
2131 Tcl_Obj **objv;
2132 int i;
2133 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2134 &objc, &objv) == TCL_ERROR) {
2135 return FromObj(self, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002136 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002137 if (objc == 0)
2138 return PyString_FromString("");
2139 if (objc == 1)
2140 return FromObj(self, objv[0]);
2141 if (!(v = PyTuple_New(objc)))
2142 return NULL;
2143 for (i = 0; i < objc; i++) {
2144 PyObject *s = FromObj(self, objv[i]);
2145 if (!s || PyTuple_SetItem(v, i, s)) {
2146 Py_DECREF(v);
2147 return NULL;
2148 }
2149 }
2150 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002151 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002152 if (PyTuple_Check(arg))
2153 return SplitObj(arg);
2154
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002155 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2156 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002157 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002158 v = Split(list);
2159 PyMem_Free(list);
2160 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002161}
2162
2163static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002164Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002165{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002166 char *s = Merge(args);
2167 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002168
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002169 if (s) {
2170 res = PyString_FromString(s);
2171 ckfree(s);
2172 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002173
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002174 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002175}
2176
Barry Warsawfa701a81997-01-16 00:15:11 +00002177
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002178
Guido van Rossum18468821994-06-20 07:49:28 +00002179/** Tcl Command **/
2180
Guido van Rossum00d93061998-05-28 23:06:38 +00002181/* Client data struct */
2182typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002183 PyObject *self;
2184 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002185} PythonCmd_ClientData;
2186
2187static int
Fred Drake509d79a2000-07-08 04:04:38 +00002188PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002189{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002190 errorInCmd = 1;
2191 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2192 LEAVE_PYTHON
2193 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002194}
2195
Guido van Rossum18468821994-06-20 07:49:28 +00002196/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002197 * function or method.
2198 */
Guido van Rossum18468821994-06-20 07:49:28 +00002199static int
Fred Drake509d79a2000-07-08 04:04:38 +00002200PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002201{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002202 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2203 PyObject *func, *arg, *res;
2204 int i, rv;
2205 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002206
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002207 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002208
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002209 /* TBD: no error checking here since we know, via the
2210 * Tkapp_CreateCommand() that the client data is a two-tuple
2211 */
2212 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002213
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002214 /* Create argument list (argv1, ..., argvN) */
2215 if (!(arg = PyTuple_New(argc - 1)))
2216 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002217
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002218 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002219 PyObject *s = fromTclString(argv[i + 1]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002220 if (!s || PyTuple_SetItem(arg, i, s)) {
2221 Py_DECREF(arg);
2222 return PythonCmd_Error(interp);
2223 }
2224 }
2225 res = PyEval_CallObject(func, arg);
2226 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002227
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002228 if (res == NULL)
2229 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002230
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002231 obj_res = AsObj(res);
2232 if (obj_res == NULL) {
2233 Py_DECREF(res);
2234 return PythonCmd_Error(interp);
2235 }
2236 else {
2237 Tcl_SetObjResult(interp, obj_res);
2238 rv = TCL_OK;
2239 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002240
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002241 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002242
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002243 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002244
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002245 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002246}
2247
2248static void
Fred Drake509d79a2000-07-08 04:04:38 +00002249PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002250{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002251 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002252
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002253 ENTER_PYTHON
2254 Py_XDECREF(data->self);
2255 Py_XDECREF(data->func);
2256 PyMem_DEL(data);
2257 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002258}
2259
Barry Warsawfa701a81997-01-16 00:15:11 +00002260
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002261
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002262
Guilherme Polo1972d162009-03-27 21:43:08 +00002263#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002264TCL_DECLARE_MUTEX(command_mutex)
2265
2266typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002267 Tcl_Event ev;
2268 Tcl_Interp* interp;
2269 char *name;
2270 int create;
2271 int *status;
2272 ClientData *data;
2273 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002274} CommandEvent;
2275
2276static int
2277Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002278{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002279 if (ev->create)
2280 *ev->status = Tcl_CreateCommand(
2281 ev->interp, ev->name, PythonCmd,
2282 ev->data, PythonCmdDelete) == NULL;
2283 else
2284 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2285 Tcl_MutexLock(&command_mutex);
2286 Tcl_ConditionNotify(ev->done);
2287 Tcl_MutexUnlock(&command_mutex);
2288 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002289}
Guilherme Polo1972d162009-03-27 21:43:08 +00002290#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002291
2292static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002293Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002294{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002295 TkappObject *self = (TkappObject*)selfptr;
2296 PythonCmd_ClientData *data;
2297 char *cmdName;
2298 PyObject *func;
2299 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002300
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002301 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2302 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002303 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002304 if (!PyCallable_Check(func)) {
2305 PyErr_SetString(PyExc_TypeError, "command not callable");
2306 return NULL;
2307 }
Guido van Rossum18468821994-06-20 07:49:28 +00002308
Martin v. Löwisa9656492003-03-30 08:44:58 +00002309#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002310 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2311 !WaitForMainloop(self))
2312 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002313#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002314
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002315 data = PyMem_NEW(PythonCmd_ClientData, 1);
2316 if (!data)
2317 return PyErr_NoMemory();
2318 Py_INCREF(self);
2319 Py_INCREF(func);
2320 data->self = selfptr;
2321 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002322
2323#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002324 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2325 Tcl_Condition cond = NULL;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03002326 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2327 if (ev == NULL) {
2328 PyErr_NoMemory();
2329 PyMem_DEL(data);
2330 return NULL;
2331 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002332 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2333 ev->interp = self->interp;
2334 ev->create = 1;
2335 ev->name = cmdName;
2336 ev->data = (ClientData)data;
2337 ev->status = &err;
2338 ev->done = &cond;
2339 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2340 Tcl_ConditionFinalize(&cond);
2341 }
2342 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002343#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002344 {
2345 ENTER_TCL
2346 err = Tcl_CreateCommand(
2347 Tkapp_Interp(self), cmdName, PythonCmd,
2348 (ClientData)data, PythonCmdDelete) == NULL;
2349 LEAVE_TCL
2350 }
2351 if (err) {
2352 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2353 PyMem_DEL(data);
2354 return NULL;
2355 }
Guido van Rossum18468821994-06-20 07:49:28 +00002356
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002357 Py_INCREF(Py_None);
2358 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002359}
2360
Barry Warsawfa701a81997-01-16 00:15:11 +00002361
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002362
Guido van Rossum18468821994-06-20 07:49:28 +00002363static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002364Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002365{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002366 TkappObject *self = (TkappObject*)selfptr;
2367 char *cmdName;
2368 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002369
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002370 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2371 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002372 CHECK_STRING_LENGTH(cmdName);
Guilherme Polo1972d162009-03-27 21:43:08 +00002373
2374#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002375 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2376 Tcl_Condition cond = NULL;
2377 CommandEvent *ev;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03002378 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2379 if (ev == NULL) {
2380 PyErr_NoMemory();
2381 return NULL;
2382 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002383 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2384 ev->interp = self->interp;
2385 ev->create = 0;
2386 ev->name = cmdName;
2387 ev->status = &err;
2388 ev->done = &cond;
2389 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2390 &command_mutex);
2391 Tcl_ConditionFinalize(&cond);
2392 }
2393 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002394#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002395 {
2396 ENTER_TCL
2397 err = Tcl_DeleteCommand(self->interp, cmdName);
2398 LEAVE_TCL
2399 }
2400 if (err == -1) {
2401 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2402 return NULL;
2403 }
2404 Py_INCREF(Py_None);
2405 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002406}
2407
Barry Warsawfa701a81997-01-16 00:15:11 +00002408
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002409
Guido van Rossum00d93061998-05-28 23:06:38 +00002410#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002411/** File Handler **/
2412
Guido van Rossum00d93061998-05-28 23:06:38 +00002413typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002414 PyObject *func;
2415 PyObject *file;
2416 int id;
2417 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002418} FileHandler_ClientData;
2419
2420static FileHandler_ClientData *HeadFHCD;
2421
2422static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002423NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002424{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002425 FileHandler_ClientData *p;
2426 p = PyMem_NEW(FileHandler_ClientData, 1);
2427 if (p != NULL) {
2428 Py_XINCREF(func);
2429 Py_XINCREF(file);
2430 p->func = func;
2431 p->file = file;
2432 p->id = id;
2433 p->next = HeadFHCD;
2434 HeadFHCD = p;
2435 }
2436 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002437}
2438
2439static void
Fred Drake509d79a2000-07-08 04:04:38 +00002440DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002441{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002442 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002443
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002444 pp = &HeadFHCD;
2445 while ((p = *pp) != NULL) {
2446 if (p->id == id) {
2447 *pp = p->next;
2448 Py_XDECREF(p->func);
2449 Py_XDECREF(p->file);
2450 PyMem_DEL(p);
2451 }
2452 else
2453 pp = &p->next;
2454 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002455}
2456
Guido van Rossuma597dde1995-01-10 20:56:29 +00002457static void
Fred Drake509d79a2000-07-08 04:04:38 +00002458FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002459{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002460 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2461 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002462
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002463 ENTER_PYTHON
2464 func = data->func;
2465 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002466
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002467 arg = Py_BuildValue("(Oi)", file, (long) mask);
2468 res = PyEval_CallObject(func, arg);
2469 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002470
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002471 if (res == NULL) {
2472 errorInCmd = 1;
2473 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2474 }
2475 Py_XDECREF(res);
2476 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002477}
2478
Guido van Rossum18468821994-06-20 07:49:28 +00002479static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002480Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2481 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002482{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002483 FileHandler_ClientData *data;
2484 PyObject *file, *func;
2485 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002486
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002487 if (!self && Py_Py3kWarningFlag) {
2488 if (PyErr_Warn(PyExc_DeprecationWarning,
2489 "_tkinter.createfilehandler is gone in 3.x") < 0)
2490 return NULL;
2491 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002492
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002493 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2494 &file, &mask, &func))
2495 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002496
Martin v. Löwisa9656492003-03-30 08:44:58 +00002497#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002498 if (!self && !tcl_lock) {
2499 /* We don't have the Tcl lock since Tcl is threaded. */
2500 PyErr_SetString(PyExc_RuntimeError,
2501 "_tkinter.createfilehandler not supported "
2502 "for threaded Tcl");
2503 return NULL;
2504 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002505#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002506
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002507 if (self) {
2508 CHECK_TCL_APPARTMENT;
2509 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002510
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002511 tfile = PyObject_AsFileDescriptor(file);
2512 if (tfile < 0)
2513 return NULL;
2514 if (!PyCallable_Check(func)) {
2515 PyErr_SetString(PyExc_TypeError, "bad argument list");
2516 return NULL;
2517 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002518
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002519 data = NewFHCD(func, file, tfile);
2520 if (data == NULL)
2521 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002522
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002523 /* Ought to check for null Tcl_File object... */
2524 ENTER_TCL
2525 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2526 LEAVE_TCL
2527 Py_INCREF(Py_None);
2528 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002529}
2530
2531static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002532Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002533{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002534 PyObject *file;
2535 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002536
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002537 if (!self && Py_Py3kWarningFlag) {
2538 if (PyErr_Warn(PyExc_DeprecationWarning,
2539 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2540 return NULL;
2541 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002542
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002543 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2544 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002545
Martin v. Löwisa9656492003-03-30 08:44:58 +00002546#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002547 if (!self && !tcl_lock) {
2548 /* We don't have the Tcl lock since Tcl is threaded. */
2549 PyErr_SetString(PyExc_RuntimeError,
2550 "_tkinter.deletefilehandler not supported "
2551 "for threaded Tcl");
2552 return NULL;
2553 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002554#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002555
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002556 if (self) {
2557 CHECK_TCL_APPARTMENT;
2558 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002559
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002560 tfile = PyObject_AsFileDescriptor(file);
2561 if (tfile < 0)
2562 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002563
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002564 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002565
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002566 /* Ought to check for null Tcl_File object... */
2567 ENTER_TCL
2568 Tcl_DeleteFileHandler(tfile);
2569 LEAVE_TCL
2570 Py_INCREF(Py_None);
2571 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002572}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002573#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002574
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002575
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002576/**** Tktt Object (timer token) ****/
2577
Jeremy Hylton938ace62002-07-17 16:30:39 +00002578static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002579
Guido van Rossum00d93061998-05-28 23:06:38 +00002580typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002581 PyObject_HEAD
2582 Tcl_TimerToken token;
2583 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002584} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002585
2586static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002587Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002588{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002589 TkttObject *v = (TkttObject *)self;
2590 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002591
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002592 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2593 return NULL;
2594 if (v->token != NULL) {
2595 Tcl_DeleteTimerHandler(v->token);
2596 v->token = NULL;
2597 }
2598 if (func != NULL) {
2599 v->func = NULL;
2600 Py_DECREF(func);
2601 Py_DECREF(v); /* See Tktt_New() */
2602 }
2603 Py_INCREF(Py_None);
2604 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002605}
2606
2607static PyMethodDef Tktt_methods[] =
2608{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002609 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2610 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002611};
2612
2613static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002614Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002615{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002616 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002617
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002618 v = PyObject_New(TkttObject, &Tktt_Type);
2619 if (v == NULL)
2620 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002621
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002622 Py_INCREF(func);
2623 v->token = NULL;
2624 v->func = func;
2625
2626 /* Extra reference, deleted when called or when handler is deleted */
2627 Py_INCREF(v);
2628 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002629}
2630
2631static void
Fred Drake509d79a2000-07-08 04:04:38 +00002632Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002633{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002634 TkttObject *v = (TkttObject *)self;
2635 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002636
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002637 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002638
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002639 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002640}
2641
Guido van Rossum597ac201998-05-12 14:36:19 +00002642static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002643Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002644{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002645 TkttObject *v = (TkttObject *)self;
2646 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002647
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002648 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2649 v->func == NULL ? ", handler deleted" : "");
2650 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002651}
2652
2653static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002654Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002655{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002656 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002657}
2658
2659static PyTypeObject Tktt_Type =
2660{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002661 PyVarObject_HEAD_INIT(NULL, 0)
2662 "tktimertoken", /*tp_name */
2663 sizeof(TkttObject), /*tp_basicsize */
2664 0, /*tp_itemsize */
2665 Tktt_Dealloc, /*tp_dealloc */
2666 0, /*tp_print */
2667 Tktt_GetAttr, /*tp_getattr */
2668 0, /*tp_setattr */
2669 0, /*tp_compare */
2670 Tktt_Repr, /*tp_repr */
2671 0, /*tp_as_number */
2672 0, /*tp_as_sequence */
2673 0, /*tp_as_mapping */
2674 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002675};
2676
Barry Warsawfa701a81997-01-16 00:15:11 +00002677
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002678
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002679/** Timer Handler **/
2680
2681static void
Fred Drake509d79a2000-07-08 04:04:38 +00002682TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002683{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002684 TkttObject *v = (TkttObject *)clientData;
2685 PyObject *func = v->func;
2686 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002687
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002688 if (func == NULL)
2689 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002690
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002691 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002692
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002693 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002694
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002695 res = PyEval_CallObject(func, NULL);
2696 Py_DECREF(func);
2697 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002698
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002699 if (res == NULL) {
2700 errorInCmd = 1;
2701 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2702 }
2703 else
2704 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002705
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002706 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002707}
2708
2709static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002710Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002711{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002712 int milliseconds;
2713 PyObject *func;
2714 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002715
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002716 if (!self && Py_Py3kWarningFlag) {
2717 if (PyErr_Warn(PyExc_DeprecationWarning,
2718 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2719 return NULL;
2720 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002721
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002722 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2723 &milliseconds, &func))
2724 return NULL;
2725 if (!PyCallable_Check(func)) {
2726 PyErr_SetString(PyExc_TypeError, "bad argument list");
2727 return NULL;
2728 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002729
Martin v. Löwisa9656492003-03-30 08:44:58 +00002730#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002731 if (!self && !tcl_lock) {
2732 /* We don't have the Tcl lock since Tcl is threaded. */
2733 PyErr_SetString(PyExc_RuntimeError,
2734 "_tkinter.createtimerhandler not supported "
2735 "for threaded Tcl");
2736 return NULL;
2737 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002738#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002739
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002740 if (self) {
2741 CHECK_TCL_APPARTMENT;
2742 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002743
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002744 v = Tktt_New(func);
2745 if (v) {
2746 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2747 (ClientData)v);
2748 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002749
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002750 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002751}
2752
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002753
Guido van Rossum18468821994-06-20 07:49:28 +00002754/** Event Loop **/
2755
Guido van Rossum18468821994-06-20 07:49:28 +00002756static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002757Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002758{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002759 int threshold = 0;
2760 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002761#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002762 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002763#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002764
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002765 if (!self && Py_Py3kWarningFlag) {
2766 if (PyErr_Warn(PyExc_DeprecationWarning,
2767 "_tkinter.mainloop 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, "|i:mainloop", &threshold))
2772 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +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.mainloop not supported "
2779 "for threaded Tcl");
2780 return NULL;
2781 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002782#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002783
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002784 if (self) {
2785 CHECK_TCL_APPARTMENT;
2786 self->dispatching = 1;
2787 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002788
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002789 quitMainLoop = 0;
2790 while (Tk_GetNumMainWindows() > threshold &&
2791 !quitMainLoop &&
2792 !errorInCmd)
2793 {
2794 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002795
2796#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002797 if (self && self->threaded) {
2798 /* Allow other Python threads to run. */
2799 ENTER_TCL
2800 result = Tcl_DoOneEvent(0);
2801 LEAVE_TCL
2802 }
2803 else {
2804 Py_BEGIN_ALLOW_THREADS
2805 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2806 tcl_tstate = tstate;
2807 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2808 tcl_tstate = NULL;
2809 if(tcl_lock)PyThread_release_lock(tcl_lock);
2810 if (result == 0)
2811 Sleep(Tkinter_busywaitinterval);
2812 Py_END_ALLOW_THREADS
2813 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002814#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002815 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002816#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002817
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002818 if (PyErr_CheckSignals() != 0) {
2819 if (self)
2820 self->dispatching = 0;
2821 return NULL;
2822 }
2823 if (result < 0)
2824 break;
2825 }
2826 if (self)
2827 self->dispatching = 0;
2828 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002829
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002830 if (errorInCmd) {
2831 errorInCmd = 0;
2832 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2833 excInCmd = valInCmd = trbInCmd = NULL;
2834 return NULL;
2835 }
2836 Py_INCREF(Py_None);
2837 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002838}
2839
2840static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002841Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002842{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002843 int flags = 0;
2844 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002845
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002846 if (!self && Py_Py3kWarningFlag) {
2847 if (PyErr_Warn(PyExc_DeprecationWarning,
2848 "_tkinter.dooneevent is gone in 3.x") < 0)
2849 return NULL;
2850 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002851
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002852 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2853 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002854
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002855 ENTER_TCL
2856 rv = Tcl_DoOneEvent(flags);
2857 LEAVE_TCL
2858 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002859}
2860
2861static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002862Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002863{
2864
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002865 if (!self && Py_Py3kWarningFlag) {
2866 if (PyErr_Warn(PyExc_DeprecationWarning,
2867 "_tkinter.quit is gone in 3.x") < 0)
2868 return NULL;
2869 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002870
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002871 if (!PyArg_ParseTuple(args, ":quit"))
2872 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002873
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002874 quitMainLoop = 1;
2875 Py_INCREF(Py_None);
2876 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002877}
2878
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002879static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002880Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002881{
2882
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002883 if (!PyArg_ParseTuple(args, ":interpaddr"))
2884 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002885
Victor Stinner930c3c92013-09-05 00:26:15 +02002886 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002887}
2888
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002889static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002890Tkapp_TkInit(PyObject *self, PyObject *args)
2891{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002892 Tcl_Interp *interp = Tkapp_Interp(self);
2893 const char * _tk_exists = NULL;
2894 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002895
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002896#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002897 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2898 * first call failed.
2899 * To avoid the deadlock, we just refuse the second call through
2900 * a static variable.
2901 */
2902 if (tk_load_failed) {
2903 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2904 return NULL;
2905 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002906#endif
2907
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002908 /* We want to guard against calling Tk_Init() multiple times */
2909 CHECK_TCL_APPARTMENT;
2910 ENTER_TCL
2911 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2912 ENTER_OVERLAP
2913 if (err == TCL_ERROR) {
2914 /* This sets an exception, but we cannot return right
2915 away because we need to exit the overlap first. */
2916 Tkinter_Error(self);
2917 } else {
2918 _tk_exists = Tkapp_Result(self);
2919 }
2920 LEAVE_OVERLAP_TCL
2921 if (err == TCL_ERROR) {
2922 return NULL;
2923 }
2924 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2925 if (Tk_Init(interp) == TCL_ERROR) {
2926 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002927#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002928 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002929#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002930 return NULL;
2931 }
2932 }
2933 Py_INCREF(Py_None);
2934 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002935}
Barry Warsawfa701a81997-01-16 00:15:11 +00002936
Martin v. Löwisffad6332002-11-26 09:28:05 +00002937static PyObject *
2938Tkapp_WantObjects(PyObject *self, PyObject *args)
2939{
2940
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002941 int wantobjects = -1;
2942 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2943 return NULL;
2944 if (wantobjects == -1)
2945 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2946 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002947
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002948 Py_INCREF(Py_None);
2949 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002950}
2951
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002952static PyObject *
2953Tkapp_WillDispatch(PyObject *self, PyObject *args)
2954{
2955
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002956 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002957
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002958 Py_INCREF(Py_None);
2959 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002960}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002961
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03002962/* Convert Python string or any buffer compatible object to Tcl byte-array
2963 * object. Use it to pass binary data (e.g. image's data) to Tcl/Tk commands.
2964 */
2965static PyObject *
2966Tkapp_CreateByteArray(PyObject *self, PyObject *args)
2967{
2968 Py_buffer view;
2969 Tcl_Obj* obj;
2970 PyObject *res = NULL;
2971
2972 if (!PyArg_ParseTuple(args, "s*:_createbytearray", &view))
2973 return NULL;
2974
2975 if (view.len >= INT_MAX) {
2976 PyErr_SetString(PyExc_OverflowError, "string is too long");
2977 return NULL;
2978 }
2979 obj = Tcl_NewByteArrayObj(view.buf, (int)view.len);
2980 if (obj == NULL) {
2981 PyBuffer_Release(&view);
2982 return Tkinter_Error(self);
2983 }
2984 res = newPyTclObject(obj);
2985 PyBuffer_Release(&view);
2986 return res;
2987}
2988
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002989
Guido van Rossum18468821994-06-20 07:49:28 +00002990/**** Tkapp Method List ****/
2991
2992static PyMethodDef Tkapp_methods[] =
2993{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002994 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2995 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2996 {"call", Tkapp_Call, METH_VARARGS},
2997 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2998 {"eval", Tkapp_Eval, METH_VARARGS},
2999 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
3000 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
3001 {"record", Tkapp_Record, METH_VARARGS},
3002 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
3003 {"setvar", Tkapp_SetVar, METH_VARARGS},
3004 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3005 {"getvar", Tkapp_GetVar, METH_VARARGS},
3006 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3007 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3008 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3009 {"getint", Tkapp_GetInt, METH_VARARGS},
3010 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
3011 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
3012 {"exprstring", Tkapp_ExprString, METH_VARARGS},
3013 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
3014 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
3015 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
3016 {"splitlist", Tkapp_SplitList, METH_VARARGS},
3017 {"split", Tkapp_Split, METH_VARARGS},
3018 {"merge", Tkapp_Merge, METH_VARARGS},
3019 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
3020 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003021#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003022 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3023 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003024#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003025 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3026 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3027 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3028 {"quit", Tkapp_Quit, METH_VARARGS},
3029 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
3030 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03003031 {"_createbytearray", Tkapp_CreateByteArray, METH_VARARGS},
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003032 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003033};
3034
Barry Warsawfa701a81997-01-16 00:15:11 +00003035
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003036
Guido van Rossum18468821994-06-20 07:49:28 +00003037/**** Tkapp Type Methods ****/
3038
3039static void
Fred Drake509d79a2000-07-08 04:04:38 +00003040Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003041{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003042 /*CHECK_TCL_APPARTMENT;*/
3043 ENTER_TCL
3044 Tcl_DeleteInterp(Tkapp_Interp(self));
3045 LEAVE_TCL
3046 PyObject_Del(self);
3047 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003048}
3049
3050static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00003051Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00003052{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003053 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00003054}
3055
3056static PyTypeObject Tkapp_Type =
3057{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003058 PyVarObject_HEAD_INIT(NULL, 0)
3059 "tkapp", /*tp_name */
3060 sizeof(TkappObject), /*tp_basicsize */
3061 0, /*tp_itemsize */
3062 Tkapp_Dealloc, /*tp_dealloc */
3063 0, /*tp_print */
3064 Tkapp_GetAttr, /*tp_getattr */
3065 0, /*tp_setattr */
3066 0, /*tp_compare */
3067 0, /*tp_repr */
3068 0, /*tp_as_number */
3069 0, /*tp_as_sequence */
3070 0, /*tp_as_mapping */
3071 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00003072};
3073
Barry Warsawfa701a81997-01-16 00:15:11 +00003074
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003075
Guido van Rossum18468821994-06-20 07:49:28 +00003076/**** Tkinter Module ****/
3077
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003078typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003079 PyObject* tuple;
3080 int size; /* current size */
3081 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003082} FlattenContext;
3083
3084static int
3085_bump(FlattenContext* context, int size)
3086{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003087 /* expand tuple to hold (at least) size new items.
3088 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003089
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003090 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003091
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003092 if (maxsize < context->size + size)
3093 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003094
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003095 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003096
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003097 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003098}
3099
3100static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003101_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003102{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003103 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003104
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003105 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003106
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003107 if (depth > 1000) {
3108 PyErr_SetString(PyExc_ValueError,
3109 "nesting too deep in _flatten");
3110 return 0;
3111 } else if (PyList_Check(item)) {
3112 size = PyList_GET_SIZE(item);
3113 /* preallocate (assume no nesting) */
3114 if (context->size + size > context->maxsize &&
3115 !_bump(context, size))
3116 return 0;
3117 /* copy items to output tuple */
3118 for (i = 0; i < size; i++) {
3119 PyObject *o = PyList_GET_ITEM(item, i);
3120 if (PyList_Check(o) || PyTuple_Check(o)) {
3121 if (!_flatten1(context, o, depth + 1))
3122 return 0;
3123 } else if (o != Py_None) {
3124 if (context->size + 1 > context->maxsize &&
3125 !_bump(context, 1))
3126 return 0;
3127 Py_INCREF(o);
3128 PyTuple_SET_ITEM(context->tuple,
3129 context->size++, o);
3130 }
3131 }
3132 } else if (PyTuple_Check(item)) {
3133 /* same, for tuples */
3134 size = PyTuple_GET_SIZE(item);
3135 if (context->size + size > context->maxsize &&
3136 !_bump(context, size))
3137 return 0;
3138 for (i = 0; i < size; i++) {
3139 PyObject *o = PyTuple_GET_ITEM(item, i);
3140 if (PyList_Check(o) || PyTuple_Check(o)) {
3141 if (!_flatten1(context, o, depth + 1))
3142 return 0;
3143 } else if (o != Py_None) {
3144 if (context->size + 1 > context->maxsize &&
3145 !_bump(context, 1))
3146 return 0;
3147 Py_INCREF(o);
3148 PyTuple_SET_ITEM(context->tuple,
3149 context->size++, o);
3150 }
3151 }
3152 } else {
3153 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3154 return 0;
3155 }
3156 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003157}
3158
3159static PyObject *
3160Tkinter_Flatten(PyObject* self, PyObject* args)
3161{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003162 FlattenContext context;
3163 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003164
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003165 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3166 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003167
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003168 context.maxsize = PySequence_Size(item);
3169 if (context.maxsize < 0)
3170 return NULL;
3171 if (context.maxsize == 0)
3172 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003173
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003174 context.tuple = PyTuple_New(context.maxsize);
3175 if (!context.tuple)
3176 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003177
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003178 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003179
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003180 if (!_flatten1(&context, item,0))
3181 return NULL;
3182
3183 if (_PyTuple_Resize(&context.tuple, context.size))
3184 return NULL;
3185
3186 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003187}
3188
Guido van Rossum18468821994-06-20 07:49:28 +00003189static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003190Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003191{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003192 char *screenName = NULL;
3193 char *baseName = NULL;
3194 char *className = NULL;
3195 int interactive = 0;
3196 int wantobjects = 0;
3197 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3198 int sync = 0; /* pass -sync to wish */
3199 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003200
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003201 baseName = strrchr(Py_GetProgramName(), '/');
3202 if (baseName != NULL)
3203 baseName++;
3204 else
3205 baseName = Py_GetProgramName();
3206 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003207
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003208 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3209 &screenName, &baseName, &className,
3210 &interactive, &wantobjects, &wantTk,
3211 &sync, &use))
3212 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03003213 CHECK_STRING_LENGTH(screenName);
3214 CHECK_STRING_LENGTH(baseName);
3215 CHECK_STRING_LENGTH(className);
3216 CHECK_STRING_LENGTH(use);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003217
3218 return (PyObject *) Tkapp_New(screenName, baseName, className,
3219 interactive, wantobjects, wantTk,
3220 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003221}
3222
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003223static PyObject *
3224Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3225{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003226 int new_val;
3227 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3228 return NULL;
3229 if (new_val < 0) {
3230 PyErr_SetString(PyExc_ValueError,
3231 "busywaitinterval must be >= 0");
3232 return NULL;
3233 }
3234 Tkinter_busywaitinterval = new_val;
3235 Py_INCREF(Py_None);
3236 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003237}
3238
3239static char setbusywaitinterval_doc[] =
3240"setbusywaitinterval(n) -> None\n\
3241\n\
3242Set the busy-wait interval in milliseconds between successive\n\
3243calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3244It should be set to a divisor of the maximum time between\n\
3245frames in an animation.";
3246
3247static PyObject *
3248Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3249{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003250 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003251}
3252
3253static char getbusywaitinterval_doc[] =
3254"getbusywaitinterval() -> int\n\
3255\n\
3256Return the current busy-wait interval between successive\n\
3257calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3258
Guido van Rossum18468821994-06-20 07:49:28 +00003259static PyMethodDef moduleMethods[] =
3260{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003261 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3262 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003263#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003264 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3265 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003266#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003267 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3268 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3269 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3270 {"quit", Tkapp_Quit, METH_VARARGS},
3271 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3272 setbusywaitinterval_doc},
3273 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3274 METH_NOARGS, getbusywaitinterval_doc},
3275 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003276};
3277
Guido van Rossum7bf15641998-05-22 18:28:17 +00003278#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003279
3280static int stdin_ready = 0;
3281
Guido van Rossumad4db171998-06-13 13:56:28 +00003282#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003283static void
Fred Drake509d79a2000-07-08 04:04:38 +00003284MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003285{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003286 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003287}
Guido van Rossumad4db171998-06-13 13:56:28 +00003288#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003289
Martin v. Löwisa9656492003-03-30 08:44:58 +00003290#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003291static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003292#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003293
Guido van Rossum18468821994-06-20 07:49:28 +00003294static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003295EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003296{
Guido van Rossumad4db171998-06-13 13:56:28 +00003297#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003298 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003299#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003300#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003301 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003302#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003303 stdin_ready = 0;
3304 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003305#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003306 tfile = fileno(stdin);
3307 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003308#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003309 while (!errorInCmd && !stdin_ready) {
3310 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003311#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003312 if (_kbhit()) {
3313 stdin_ready = 1;
3314 break;
3315 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003316#endif
3317#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003318 Py_BEGIN_ALLOW_THREADS
3319 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3320 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003321
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003322 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003323
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003324 tcl_tstate = NULL;
3325 if(tcl_lock)PyThread_release_lock(tcl_lock);
3326 if (result == 0)
3327 Sleep(Tkinter_busywaitinterval);
3328 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003329#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003330 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003331#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003332
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003333 if (result < 0)
3334 break;
3335 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003336#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003337 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003338#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003339 if (errorInCmd) {
3340 errorInCmd = 0;
3341 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3342 excInCmd = valInCmd = trbInCmd = NULL;
3343 PyErr_Print();
3344 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003345#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003346 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003347#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003348 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003349}
Guido van Rossum18468821994-06-20 07:49:28 +00003350
Guido van Rossum00d93061998-05-28 23:06:38 +00003351#endif
3352
Guido van Rossum7bf15641998-05-22 18:28:17 +00003353static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003354EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003355{
Guido van Rossum00d93061998-05-28 23:06:38 +00003356#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003357 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003358#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003359 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003360#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003361 PyOS_InputHook = EventHook;
3362 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003363#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003364}
3365
3366static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003367DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003368{
Guido van Rossum00d93061998-05-28 23:06:38 +00003369#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003370 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3371 PyOS_InputHook = NULL;
3372 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003373#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003374}
3375
Barry Warsawfa701a81997-01-16 00:15:11 +00003376
3377/* all errors will be checked in one fell swoop in init_tkinter() */
3378static void
Fred Drake509d79a2000-07-08 04:04:38 +00003379ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003380{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003381 PyObject *v = PyInt_FromLong(val);
3382 if (v) {
3383 PyDict_SetItemString(d, name, v);
3384 Py_DECREF(v);
3385 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003386}
3387static void
Fred Drake509d79a2000-07-08 04:04:38 +00003388ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003389{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003390 PyObject *v = PyString_FromString(val);
3391 if (v) {
3392 PyDict_SetItemString(d, name, v);
3393 Py_DECREF(v);
3394 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003395}
3396
3397
Mark Hammond62b1ab12002-07-23 06:31:15 +00003398PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003399init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003400{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003401 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003402
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003403 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003404
3405#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003406 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003407#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003408
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003409 m = Py_InitModule("_tkinter", moduleMethods);
3410 if (m == NULL)
3411 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003412
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003413 d = PyModule_GetDict(m);
3414 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3415 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003416
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003417 ins_long(d, "READABLE", TCL_READABLE);
3418 ins_long(d, "WRITABLE", TCL_WRITABLE);
3419 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3420 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3421 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3422 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3423 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3424 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3425 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3426 ins_string(d, "TK_VERSION", TK_VERSION);
3427 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003428
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003429 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003430
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003431 Py_TYPE(&Tktt_Type) = &PyType_Type;
3432 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003433
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003434 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3435 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003436
3437#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003438 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3439 * start waking up. Note that Tcl_FindExecutable will do this, this
3440 * code must be above it! The original warning from
3441 * tkMacOSXAppInit.c is copied below.
3442 *
3443 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3444 * Tcl interpreter for now. It probably should work to do this
3445 * in the other order, but for now it doesn't seem to.
3446 *
3447 */
3448 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003449#endif
3450
3451
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003452 /* This helps the dynamic loader; in Unicode aware Tcl versions
3453 it also helps Tcl find its encodings. */
3454 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003455
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003456 if (PyErr_Occurred())
3457 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003458
Guido van Rossum43ff8681998-07-14 18:02:13 +00003459#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003460 /* This was not a good idea; through <Destroy> bindings,
3461 Tcl_Finalize() may invoke Python code but at that point the
3462 interpreter and thread state have already been destroyed! */
3463 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003464#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003465
Guido van Rossum18468821994-06-20 07:49:28 +00003466}