blob: d0a4464716b838b9c9854ac06730ec9b90d60ce5 [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);
1055 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
1056 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1057 return NULL;
1058 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001059 argv = (Tcl_Obj **) attemptckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001060 if(!argv)
1061 return 0;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001062 for (i = 0; i < size; i++)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001063 argv[i] = AsObj(PyTuple_GetItem(value,i));
1064 result = Tcl_NewListObj(PyTuple_Size(value), argv);
1065 ckfree(FREECAST argv);
1066 return result;
1067 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001068#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001069 else if (PyUnicode_Check(value)) {
1070 Py_UNICODE *inbuf = PyUnicode_AS_UNICODE(value);
1071 Py_ssize_t size = PyUnicode_GET_SIZE(value);
1072 /* This #ifdef assumes that Tcl uses UCS-2.
1073 See TCL_UTF_MAX test above. */
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001074#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX == 3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001075 Tcl_UniChar *outbuf = NULL;
1076 Py_ssize_t i;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001077 size_t allocsize;
1078 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1079 PyErr_SetString(PyExc_OverflowError, "string is too long");
1080 return NULL;
1081 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001082 if (sizeof(Py_UNICODE) == sizeof(Tcl_UniChar))
1083 return Tcl_NewUnicodeObj(inbuf, size);
Serhiy Storchaka42035702013-08-21 21:46:12 +03001084 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001085 if (allocsize >= size)
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001086 outbuf = (Tcl_UniChar*)attemptckalloc(allocsize);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001087 /* Else overflow occurred, and we take the next exit */
1088 if (!outbuf) {
1089 PyErr_NoMemory();
1090 return NULL;
1091 }
1092 for (i = 0; i < size; i++) {
1093 if (inbuf[i] >= 0x10000) {
1094 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka46764482013-02-18 13:00:08 +02001095 PyErr_Format(Tkinter_TclError,
1096 "character U+%x is above the range "
1097 "(U+0000-U+FFFF) allowed by Tcl",
1098 (int)inbuf[i]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001099 ckfree(FREECAST outbuf);
1100 return NULL;
1101 }
1102 outbuf[i] = inbuf[i];
1103 }
1104 result = Tcl_NewUnicodeObj(outbuf, size);
1105 ckfree(FREECAST outbuf);
1106 return result;
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001107#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001108 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwis3c6d6f22002-10-01 18:50:56 +00001109#endif
1110
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001111 }
Martin v. Löwis339d0f72001-08-17 18:39:25 +00001112#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001113 else if(PyTclObject_Check(value)) {
1114 Tcl_Obj *v = ((PyTclObject*)value)->value;
1115 Tcl_IncrRefCount(v);
1116 return v;
1117 }
1118 else {
1119 PyObject *v = PyObject_Str(value);
1120 if (!v)
1121 return 0;
1122 result = AsObj(v);
1123 Py_DECREF(v);
1124 return result;
1125 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001126}
1127
Martin v. Löwisffad6332002-11-26 09:28:05 +00001128static PyObject*
1129FromObj(PyObject* tkapp, Tcl_Obj *value)
1130{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001131 PyObject *result = NULL;
1132 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001133
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001134 if (value->typePtr == NULL) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001135 result = fromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001136 return result;
1137 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001138
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001139 if (value->typePtr == app->BooleanType) {
1140 result = value->internalRep.longValue ? Py_True : Py_False;
1141 Py_INCREF(result);
1142 return result;
1143 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001144
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001145 if (value->typePtr == app->ByteArrayType) {
1146 int size;
1147 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1148 return PyString_FromStringAndSize(data, size);
1149 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001150
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001151 if (value->typePtr == app->DoubleType) {
1152 return PyFloat_FromDouble(value->internalRep.doubleValue);
1153 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001154
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001155 if (value->typePtr == app->IntType) {
1156 return PyInt_FromLong(value->internalRep.longValue);
1157 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001158
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001159 if (value->typePtr == app->ListType) {
1160 int size;
1161 int i, status;
1162 PyObject *elem;
1163 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001164
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001165 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1166 if (status == TCL_ERROR)
1167 return Tkinter_Error(tkapp);
1168 result = PyTuple_New(size);
1169 if (!result)
1170 return NULL;
1171 for (i = 0; i < size; i++) {
1172 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1173 value, i, &tcl_elem);
1174 if (status == TCL_ERROR) {
1175 Py_DECREF(result);
1176 return Tkinter_Error(tkapp);
1177 }
1178 elem = FromObj(tkapp, tcl_elem);
1179 if (!elem) {
1180 Py_DECREF(result);
1181 return NULL;
1182 }
1183 PyTuple_SetItem(result, i, elem);
1184 }
1185 return result;
1186 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001187
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001188 if (value->typePtr == app->ProcBodyType) {
1189 /* fall through: return tcl object. */
1190 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001191
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001192 if (value->typePtr == app->StringType) {
Martin v. Löwisffad6332002-11-26 09:28:05 +00001193#ifdef Py_USING_UNICODE
Martin v. Löwis6f29ff32003-04-16 20:34:55 +00001194#if defined(Py_UNICODE_WIDE) && TCL_UTF_MAX==3
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001195 PyObject *result;
1196 int size;
1197 Tcl_UniChar *input;
1198 Py_UNICODE *output;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001199
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001200 size = Tcl_GetCharLength(value);
1201 result = PyUnicode_FromUnicode(NULL, size);
1202 if (!result)
1203 return NULL;
1204 input = Tcl_GetUnicode(value);
1205 output = PyUnicode_AS_UNICODE(result);
1206 while (size--)
1207 *output++ = *input++;
1208 return result;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001209#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001210 return PyUnicode_FromUnicode(Tcl_GetUnicode(value),
1211 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001212#endif
1213#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001214 int size;
1215 char *c;
1216 c = Tcl_GetStringFromObj(value, &size);
1217 return PyString_FromStringAndSize(c, size);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001218#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001219 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001220
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001221 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001222}
1223
Guilherme Polo1972d162009-03-27 21:43:08 +00001224#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001225/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001226TCL_DECLARE_MUTEX(call_mutex)
1227
1228typedef struct Tkapp_CallEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001229 Tcl_Event ev; /* Must be first */
1230 TkappObject *self;
1231 PyObject *args;
1232 int flags;
1233 PyObject **res;
1234 PyObject **exc_type, **exc_value, **exc_tb;
1235 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001236} Tkapp_CallEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001237#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001238
1239void
1240Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001241{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001242 int i;
1243 for (i = 0; i < objc; i++)
1244 Tcl_DecrRefCount(objv[i]);
1245 if (objv != objStore)
1246 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001247}
Guido van Rossum18468821994-06-20 07:49:28 +00001248
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001249/* Convert Python objects to Tcl objects. This must happen in the
1250 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001251
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001252static Tcl_Obj**
1253Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1254{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001255 Tcl_Obj **objv = objStore;
Serhiy Storchaka42035702013-08-21 21:46:12 +03001256 Py_ssize_t objc = 0, i;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001257 if (args == NULL)
1258 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001259
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001260 else if (!PyTuple_Check(args)) {
1261 objv[0] = AsObj(args);
1262 if (objv[0] == 0)
1263 goto finally;
1264 objc = 1;
1265 Tcl_IncrRefCount(objv[0]);
1266 }
1267 else {
1268 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001269
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001270 if (objc > ARGSZ) {
Serhiy Storchaka42035702013-08-21 21:46:12 +03001271 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1272 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1273 return NULL;
1274 }
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001275 objv = (Tcl_Obj **)attemptckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001276 if (objv == NULL) {
1277 PyErr_NoMemory();
1278 objc = 0;
1279 goto finally;
1280 }
1281 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001282
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001283 for (i = 0; i < objc; i++) {
1284 PyObject *v = PyTuple_GetItem(args, i);
1285 if (v == Py_None) {
1286 objc = i;
1287 break;
1288 }
1289 objv[i] = AsObj(v);
1290 if (!objv[i]) {
1291 /* Reset objc, so it attempts to clear
1292 objects only up to i. */
1293 objc = i;
1294 goto finally;
1295 }
1296 Tcl_IncrRefCount(objv[i]);
1297 }
1298 }
1299 *pobjc = objc;
1300 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001301finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001302 Tkapp_CallDeallocArgs(objv, objStore, objc);
1303 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001304}
Guido van Rossum212643f1998-04-29 16:22:14 +00001305
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001306/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001307
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001308static PyObject*
1309Tkapp_CallResult(TkappObject *self)
1310{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001311 PyObject *res = NULL;
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001312 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001313 if(self->wantobjects) {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001314 /* Not sure whether the IncrRef is necessary, but something
1315 may overwrite the interpreter result while we are
1316 converting it. */
1317 Tcl_IncrRefCount(value);
1318 res = FromObj((PyObject*)self, value);
1319 Tcl_DecrRefCount(value);
1320 } else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001321 int len;
1322 const char *s = Tcl_GetStringFromObj(value, &len);
1323 res = fromTclStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001324 }
1325 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001326}
Guido van Rossum632de272000-03-29 00:19:50 +00001327
Guilherme Polo1972d162009-03-27 21:43:08 +00001328#ifdef WITH_THREAD
1329
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001330/* Tkapp_CallProc is the event procedure that is executed in the context of
1331 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1332 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001333
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001334static int
1335Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1336{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001337 Tcl_Obj *objStore[ARGSZ];
1338 Tcl_Obj **objv;
1339 int objc;
1340 int i;
1341 ENTER_PYTHON
1342 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1343 if (!objv) {
1344 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1345 *(e->res) = NULL;
1346 }
1347 LEAVE_PYTHON
1348 if (!objv)
1349 goto done;
1350 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1351 ENTER_PYTHON
1352 if (i == TCL_ERROR) {
1353 *(e->res) = NULL;
1354 *(e->exc_type) = NULL;
1355 *(e->exc_tb) = NULL;
1356 *(e->exc_value) = PyObject_CallFunction(
1357 Tkinter_TclError, "s",
1358 Tcl_GetStringResult(e->self->interp));
1359 }
1360 else {
1361 *(e->res) = Tkapp_CallResult(e->self);
1362 }
1363 LEAVE_PYTHON
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001364
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001365 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo14ff18d2009-02-06 22:26:22 +00001366done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001367 /* Wake up calling thread. */
1368 Tcl_MutexLock(&call_mutex);
1369 Tcl_ConditionNotify(e->done);
1370 Tcl_MutexUnlock(&call_mutex);
1371 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001372}
1373
Guilherme Polo1972d162009-03-27 21:43:08 +00001374#endif
1375
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001376/* This is the main entry point for calling a Tcl command.
1377 It supports three cases, with regard to threading:
1378 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1379 the context of the calling thread.
1380 2. Tcl is threaded, caller of the command is in the interpreter thread:
1381 Execute the command in the calling thread. Since the Tcl lock will
1382 not be used, we can merge that with case 1.
1383 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1384 the interpreter thread. Allocation of Tcl objects needs to occur in the
1385 interpreter thread, so we ship the PyObject* args to the target thread,
1386 and perform processing there. */
1387
1388static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001389Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001390{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001391 Tcl_Obj *objStore[ARGSZ];
1392 Tcl_Obj **objv = NULL;
1393 int objc, i;
1394 PyObject *res = NULL;
1395 TkappObject *self = (TkappObject*)selfptr;
1396 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001397
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001398 /* If args is a single tuple, replace with contents of tuple */
1399 if (1 == PyTuple_Size(args)){
1400 PyObject* item = PyTuple_GetItem(args, 0);
1401 if (PyTuple_Check(item))
1402 args = item;
1403 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001404#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001405 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1406 /* We cannot call the command directly. Instead, we must
1407 marshal the parameters to the interpreter thread. */
1408 Tkapp_CallEvent *ev;
1409 Tcl_Condition cond = NULL;
1410 PyObject *exc_type, *exc_value, *exc_tb;
1411 if (!WaitForMainloop(self))
1412 return NULL;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001413 ev = (Tkapp_CallEvent*)attemptckalloc(sizeof(Tkapp_CallEvent));
1414 if (ev == NULL) {
1415 PyErr_NoMemory();
1416 return NULL;
1417 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001418 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1419 ev->self = self;
1420 ev->args = args;
1421 ev->res = &res;
1422 ev->exc_type = &exc_type;
1423 ev->exc_value = &exc_value;
1424 ev->exc_tb = &exc_tb;
1425 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001426
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001427 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001428
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001429 if (res == NULL) {
1430 if (exc_type)
1431 PyErr_Restore(exc_type, exc_value, exc_tb);
1432 else
1433 PyErr_SetObject(Tkinter_TclError, exc_value);
1434 }
1435 Tcl_ConditionFinalize(&cond);
1436 }
1437 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001438#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001439 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001440
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001441 objv = Tkapp_CallArgs(args, objStore, &objc);
1442 if (!objv)
1443 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001444
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001445 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001446
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001447 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001448
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001449 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001450
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001451 if (i == TCL_ERROR)
1452 Tkinter_Error(selfptr);
1453 else
1454 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001455
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001456 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001457
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001458 Tkapp_CallDeallocArgs(objv, objStore, objc);
1459 }
1460 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001461}
1462
1463
1464static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001465Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001466{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001467 /* Could do the same here as for Tkapp_Call(), but this is not used
1468 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1469 way for the user to do what all its Global* variants do (save and
1470 reset the scope pointer, call the local version, restore the saved
1471 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001472
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001473 char *cmd;
1474 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001475
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001476 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001477
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001478 cmd = Merge(args);
1479 if (cmd) {
1480 int err;
1481 ENTER_TCL
1482 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1483 ENTER_OVERLAP
1484 if (err == TCL_ERROR)
1485 res = Tkinter_Error(self);
1486 else
1487 res = PyString_FromString(Tkapp_Result(self));
1488 LEAVE_OVERLAP_TCL
1489 ckfree(cmd);
1490 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001491
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001492 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001493}
1494
1495static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001496Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001497{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001498 char *script;
1499 PyObject *res = NULL;
1500 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001501
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001502 if (!PyArg_ParseTuple(args, "s:eval", &script))
1503 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001504
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001505 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001506 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001507
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001508 ENTER_TCL
1509 err = Tcl_Eval(Tkapp_Interp(self), script);
1510 ENTER_OVERLAP
1511 if (err == TCL_ERROR)
1512 res = Tkinter_Error(self);
1513 else
1514 res = PyString_FromString(Tkapp_Result(self));
1515 LEAVE_OVERLAP_TCL
1516 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001517}
1518
1519static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001520Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001521{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001522 char *script;
1523 PyObject *res = NULL;
1524 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001525
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001526 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1527 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001528
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001529 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001530
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001531 ENTER_TCL
1532 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1533 ENTER_OVERLAP
1534 if (err == TCL_ERROR)
1535 res = Tkinter_Error(self);
1536 else
1537 res = PyString_FromString(Tkapp_Result(self));
1538 LEAVE_OVERLAP_TCL
1539 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001540}
1541
1542static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001543Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001544{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001545 char *fileName;
1546 PyObject *res = NULL;
1547 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001548
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001549 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1550 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001551
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001552 CHECK_STRING_LENGTH(fileName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001553 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001554
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001555 ENTER_TCL
1556 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1557 ENTER_OVERLAP
1558 if (err == TCL_ERROR)
1559 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001560
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001561 else
1562 res = PyString_FromString(Tkapp_Result(self));
1563 LEAVE_OVERLAP_TCL
1564 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001565}
1566
1567static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001568Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001569{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001570 char *script;
1571 PyObject *res = NULL;
1572 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001573
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001574 if (!PyArg_ParseTuple(args, "s:record", &script))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001575 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001576
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001577 CHECK_STRING_LENGTH(script);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001578 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001579
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001580 ENTER_TCL
1581 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1582 ENTER_OVERLAP
1583 if (err == TCL_ERROR)
1584 res = Tkinter_Error(self);
1585 else
1586 res = PyString_FromString(Tkapp_Result(self));
1587 LEAVE_OVERLAP_TCL
1588 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001589}
1590
1591static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001592Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001593{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001594 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001595
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001596 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1597 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001598 CHECK_STRING_LENGTH(msg);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001599 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001600
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001601 ENTER_TCL
1602 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1603 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001604
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001605 Py_INCREF(Py_None);
1606 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001607}
1608
Barry Warsawfa701a81997-01-16 00:15:11 +00001609
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001610
Guido van Rossum18468821994-06-20 07:49:28 +00001611/** Tcl Variable **/
1612
Guilherme Polo1972d162009-03-27 21:43:08 +00001613typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1614
1615#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001616TCL_DECLARE_MUTEX(var_mutex)
1617
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001618typedef struct VarEvent {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001619 Tcl_Event ev; /* must be first */
1620 PyObject *self;
1621 PyObject *args;
1622 int flags;
1623 EventFunc func;
1624 PyObject **res;
1625 PyObject **exc_type;
1626 PyObject **exc_val;
1627 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001628} VarEvent;
Guilherme Polo1972d162009-03-27 21:43:08 +00001629#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001630
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001631static int
1632varname_converter(PyObject *in, void *_out)
1633{
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001634 char *s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001635 char **out = (char**)_out;
1636 if (PyString_Check(in)) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001637 if (PyString_Size(in) > INT_MAX) {
1638 PyErr_SetString(PyExc_OverflowError, "string is too long");
1639 return 0;
1640 }
1641 s = PyString_AsString(in);
1642 if (strlen(s) != PyString_Size(in)) {
1643 PyErr_SetString(PyExc_ValueError, "null character in string");
1644 return 0;
1645 }
1646 *out = s;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001647 return 1;
1648 }
1649 if (PyTclObject_Check(in)) {
1650 *out = PyTclObject_TclString(in);
1651 return 1;
1652 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001653 PyErr_Format(PyExc_TypeError,
1654 "must be str or Tcl_Obj, not %.50s",
1655 in->ob_type->tp_name);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001656 return 0;
1657}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001658
Guilherme Polo1972d162009-03-27 21:43:08 +00001659#ifdef WITH_THREAD
1660
Martin v. Löwis111c1802008-06-13 07:47:47 +00001661static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001662var_perform(VarEvent *ev)
1663{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001664 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1665 if (!*(ev->res)) {
1666 PyObject *exc, *val, *tb;
1667 PyErr_Fetch(&exc, &val, &tb);
1668 PyErr_NormalizeException(&exc, &val, &tb);
1669 *(ev->exc_type) = exc;
1670 *(ev->exc_val) = val;
1671 Py_DECREF(tb);
1672 }
1673
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001674}
1675
1676static int
1677var_proc(VarEvent* ev, int flags)
1678{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001679 ENTER_PYTHON
1680 var_perform(ev);
1681 Tcl_MutexLock(&var_mutex);
1682 Tcl_ConditionNotify(ev->cond);
1683 Tcl_MutexUnlock(&var_mutex);
1684 LEAVE_PYTHON
1685 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001686}
1687
Guilherme Polo1972d162009-03-27 21:43:08 +00001688#endif
1689
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001690static PyObject*
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00001691var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001692{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001693#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001694 TkappObject *self = (TkappObject*)selfptr;
1695 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1696 TkappObject *self = (TkappObject*)selfptr;
1697 VarEvent *ev;
1698 PyObject *res, *exc_type, *exc_val;
1699 Tcl_Condition cond = NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001700
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001701 /* The current thread is not the interpreter thread. Marshal
1702 the call to the interpreter thread, then wait for
1703 completion. */
1704 if (!WaitForMainloop(self))
1705 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001706
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03001707 ev = (VarEvent*)attemptckalloc(sizeof(VarEvent));
1708 if (ev == NULL) {
1709 PyErr_NoMemory();
1710 return NULL;
1711 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001712 ev->self = selfptr;
1713 ev->args = args;
1714 ev->flags = flags;
1715 ev->func = func;
1716 ev->res = &res;
1717 ev->exc_type = &exc_type;
1718 ev->exc_val = &exc_val;
1719 ev->cond = &cond;
1720 ev->ev.proc = (Tcl_EventProc*)var_proc;
1721 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1722 Tcl_ConditionFinalize(&cond);
1723 if (!res) {
1724 PyErr_SetObject(exc_type, exc_val);
1725 Py_DECREF(exc_type);
1726 Py_DECREF(exc_val);
1727 return NULL;
1728 }
1729 return res;
1730 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001731#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001732 /* Tcl is not threaded, or this is the interpreter thread. */
1733 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001734}
1735
Guido van Rossum18468821994-06-20 07:49:28 +00001736static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001737SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001738{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001739 char *name1, *name2;
1740 PyObject *newValue;
1741 PyObject *res = NULL;
1742 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001743
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001744 switch (PyTuple_GET_SIZE(args)) {
1745 case 2:
1746 if (!PyArg_ParseTuple(args, "O&O:setvar",
1747 varname_converter, &name1, &newValue))
1748 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001749 /* XXX Acquire tcl lock??? */
1750 newval = AsObj(newValue);
1751 if (newval == NULL)
1752 return NULL;
1753 ENTER_TCL
1754 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1755 newval, flags);
1756 ENTER_OVERLAP
1757 if (!ok)
1758 Tkinter_Error(self);
1759 else {
1760 res = Py_None;
1761 Py_INCREF(res);
1762 }
1763 LEAVE_OVERLAP_TCL
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001764 break;
1765 case 3:
1766 if (!PyArg_ParseTuple(args, "ssO:setvar",
1767 &name1, &name2, &newValue))
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001768 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001769 CHECK_STRING_LENGTH(name1);
1770 CHECK_STRING_LENGTH(name2);
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001771 /* XXX must hold tcl lock already??? */
1772 newval = AsObj(newValue);
1773 ENTER_TCL
1774 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1775 ENTER_OVERLAP
1776 if (!ok)
1777 Tkinter_Error(self);
1778 else {
1779 res = Py_None;
1780 Py_INCREF(res);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001781 }
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001782 LEAVE_OVERLAP_TCL
1783 break;
1784 default:
1785 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1786 return NULL;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001787 }
1788 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001789}
1790
1791static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001792Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001793{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001794 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001795}
1796
1797static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001798Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001799{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001800 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001801}
1802
Barry Warsawfa701a81997-01-16 00:15:11 +00001803
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001804
Guido van Rossum18468821994-06-20 07:49:28 +00001805static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001806GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001807{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001808 char *name1, *name2=NULL;
1809 PyObject *res = NULL;
1810 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001811
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001812 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1813 varname_converter, &name1, &name2))
1814 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001815
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001816 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001817 ENTER_TCL
1818 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1819 ENTER_OVERLAP
1820 if (tres == NULL) {
1821 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1822 } else {
1823 if (((TkappObject*)self)->wantobjects) {
1824 res = FromObj(self, tres);
1825 }
1826 else {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001827 int len;
1828 char *s = Tcl_GetStringFromObj(tres, &len);
1829 res = PyString_FromStringAndSize(s, len);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001830 }
1831 }
1832 LEAVE_OVERLAP_TCL
1833 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001834}
1835
1836static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001837Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001838{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001839 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001840}
1841
1842static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001843Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001844{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001845 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001846}
1847
Barry Warsawfa701a81997-01-16 00:15:11 +00001848
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001849
Guido van Rossum18468821994-06-20 07:49:28 +00001850static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001851UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001852{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001853 char *name1, *name2=NULL;
1854 int code;
1855 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001856
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001857 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1858 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001859
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001860 CHECK_STRING_LENGTH(name1);
1861 CHECK_STRING_LENGTH(name2);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001862 ENTER_TCL
1863 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1864 ENTER_OVERLAP
1865 if (code == TCL_ERROR)
1866 res = Tkinter_Error(self);
1867 else {
1868 Py_INCREF(Py_None);
1869 res = Py_None;
1870 }
1871 LEAVE_OVERLAP_TCL
1872 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001873}
1874
1875static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001876Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001877{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001878 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001879}
1880
1881static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001882Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001883{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001884 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001885}
1886
Barry Warsawfa701a81997-01-16 00:15:11 +00001887
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001888
Guido van Rossum18468821994-06-20 07:49:28 +00001889/** Tcl to Python **/
1890
1891static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001892Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001893{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001894 char *s;
1895 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001896
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001897 if (PyTuple_Size(args) == 1) {
1898 PyObject* o = PyTuple_GetItem(args, 0);
1899 if (PyInt_Check(o)) {
1900 Py_INCREF(o);
1901 return o;
1902 }
1903 }
1904 if (!PyArg_ParseTuple(args, "s:getint", &s))
1905 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001906 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001907 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1908 return Tkinter_Error(self);
1909 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001910}
1911
1912static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001913Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001914{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001915 char *s;
1916 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001917
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001918 if (PyTuple_Size(args) == 1) {
1919 PyObject *o = PyTuple_GetItem(args, 0);
1920 if (PyFloat_Check(o)) {
1921 Py_INCREF(o);
1922 return o;
1923 }
1924 }
1925 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1926 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001927 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001928 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1929 return Tkinter_Error(self);
1930 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001931}
1932
1933static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001934Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001935{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001936 char *s;
1937 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001938
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001939 if (PyTuple_Size(args) == 1) {
1940 PyObject *o = PyTuple_GetItem(args, 0);
1941 if (PyInt_Check(o)) {
1942 Py_INCREF(o);
1943 return o;
1944 }
1945 }
1946 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1947 return NULL;
Serhiy Storchaka529a6392014-05-30 14:28:21 +03001948 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001949 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1950 return Tkinter_Error(self);
1951 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001952}
1953
1954static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001955Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001956{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001957 char *s;
1958 PyObject *res = NULL;
1959 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001960
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001961 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1962 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001963
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001964 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001965 CHECK_TCL_APPARTMENT;
1966
1967 ENTER_TCL
1968 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1969 ENTER_OVERLAP
1970 if (retval == TCL_ERROR)
1971 res = Tkinter_Error(self);
1972 else
Serhiy Storchakaccffb252014-02-03 21:23:46 +02001973 res = PyString_FromString(Tkapp_Result(self));
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001974 LEAVE_OVERLAP_TCL
1975 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001976}
1977
1978static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001979Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001980{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001981 char *s;
1982 PyObject *res = NULL;
1983 int retval;
1984 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001985
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001986 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1987 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001988
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03001989 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001990 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001991
Antoine Pitrouc83ea132010-05-09 14:46:46 +00001992 ENTER_TCL
1993 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1994 ENTER_OVERLAP
1995 if (retval == TCL_ERROR)
1996 res = Tkinter_Error(self);
1997 else
1998 res = Py_BuildValue("l", v);
1999 LEAVE_OVERLAP_TCL
2000 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002001}
2002
2003static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002004Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002005{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002006 char *s;
2007 PyObject *res = NULL;
2008 double v;
2009 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00002010
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002011 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
2012 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002013 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002014 CHECK_TCL_APPARTMENT;
2015 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
2016 ENTER_TCL
2017 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
2018 ENTER_OVERLAP
2019 PyFPE_END_PROTECT(retval)
2020 if (retval == TCL_ERROR)
2021 res = Tkinter_Error(self);
2022 else
2023 res = Py_BuildValue("d", v);
2024 LEAVE_OVERLAP_TCL
2025 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002026}
2027
2028static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002029Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002030{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002031 char *s;
2032 PyObject *res = NULL;
2033 int retval;
2034 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00002035
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002036 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
2037 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002038 CHECK_STRING_LENGTH(s);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002039 CHECK_TCL_APPARTMENT;
2040 ENTER_TCL
2041 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
2042 ENTER_OVERLAP
2043 if (retval == TCL_ERROR)
2044 res = Tkinter_Error(self);
2045 else
2046 res = Py_BuildValue("i", v);
2047 LEAVE_OVERLAP_TCL
2048 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002049}
2050
Barry Warsawfa701a81997-01-16 00:15:11 +00002051
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002052
Guido van Rossum18468821994-06-20 07:49:28 +00002053static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002054Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002055{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002056 char *list;
2057 int argc;
2058 char **argv;
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002059 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002060 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00002061
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002062 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
2063 return NULL;
2064 if (PyTclObject_Check(arg)) {
2065 int objc;
2066 Tcl_Obj **objv;
2067 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
2068 ((PyTclObject*)arg)->value,
2069 &objc, &objv) == TCL_ERROR) {
2070 return Tkinter_Error(self);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002071 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002072 if (!(v = PyTuple_New(objc)))
2073 return NULL;
2074 for (i = 0; i < objc; i++) {
2075 PyObject *s = FromObj(self, objv[i]);
2076 if (!s || PyTuple_SetItem(v, i, s)) {
2077 Py_DECREF(v);
2078 return NULL;
2079 }
2080 }
2081 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002082 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002083 if (PyTuple_Check(arg)) {
2084 Py_INCREF(arg);
2085 return arg;
2086 }
2087
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002088 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2089 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002090
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002091 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002092 if (Tcl_SplitList(Tkapp_Interp(self), list,
2093 &argc, &argv) == TCL_ERROR) {
2094 PyMem_Free(list);
2095 return Tkinter_Error(self);
2096 }
Guido van Rossum18468821994-06-20 07:49:28 +00002097
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002098 if (!(v = PyTuple_New(argc)))
2099 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002100
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002101 for (i = 0; i < argc; i++) {
2102 PyObject *s = PyString_FromString(argv[i]);
2103 if (!s || PyTuple_SetItem(v, i, s)) {
2104 Py_DECREF(v);
2105 v = NULL;
2106 goto finally;
2107 }
2108 }
Guido van Rossum18468821994-06-20 07:49:28 +00002109
Barry Warsawfa701a81997-01-16 00:15:11 +00002110 finally:
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002111 ckfree(FREECAST argv);
2112 PyMem_Free(list);
2113 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002114}
2115
2116static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002117Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002118{
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002119 PyObject *arg, *v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002120 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002121
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002122 if (!PyArg_ParseTuple(args, "O:split", &arg))
2123 return NULL;
2124 if (PyTclObject_Check(arg)) {
2125 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2126 int objc;
2127 Tcl_Obj **objv;
2128 int i;
2129 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2130 &objc, &objv) == TCL_ERROR) {
2131 return FromObj(self, value);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002132 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002133 if (objc == 0)
2134 return PyString_FromString("");
2135 if (objc == 1)
2136 return FromObj(self, objv[0]);
2137 if (!(v = PyTuple_New(objc)))
2138 return NULL;
2139 for (i = 0; i < objc; i++) {
2140 PyObject *s = FromObj(self, objv[i]);
2141 if (!s || PyTuple_SetItem(v, i, s)) {
2142 Py_DECREF(v);
2143 return NULL;
2144 }
2145 }
2146 return v;
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002147 }
Serhiy Storchaka2ac1c1a2013-08-22 17:42:45 +03002148 if (PyTuple_Check(arg))
2149 return SplitObj(arg);
2150
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002151 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2152 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002153 CHECK_STRING_LENGTH(list);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002154 v = Split(list);
2155 PyMem_Free(list);
2156 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002157}
2158
2159static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002160Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002161{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002162 char *s = Merge(args);
2163 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002164
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002165 if (s) {
2166 res = PyString_FromString(s);
2167 ckfree(s);
2168 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002169
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002170 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002171}
2172
Barry Warsawfa701a81997-01-16 00:15:11 +00002173
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002174
Guido van Rossum18468821994-06-20 07:49:28 +00002175/** Tcl Command **/
2176
Guido van Rossum00d93061998-05-28 23:06:38 +00002177/* Client data struct */
2178typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002179 PyObject *self;
2180 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002181} PythonCmd_ClientData;
2182
2183static int
Fred Drake509d79a2000-07-08 04:04:38 +00002184PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002185{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002186 errorInCmd = 1;
2187 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2188 LEAVE_PYTHON
2189 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002190}
2191
Guido van Rossum18468821994-06-20 07:49:28 +00002192/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002193 * function or method.
2194 */
Guido van Rossum18468821994-06-20 07:49:28 +00002195static int
Fred Drake509d79a2000-07-08 04:04:38 +00002196PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002197{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002198 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
2199 PyObject *func, *arg, *res;
2200 int i, rv;
2201 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002202
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002203 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002204
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002205 /* TBD: no error checking here since we know, via the
2206 * Tkapp_CreateCommand() that the client data is a two-tuple
2207 */
2208 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002209
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002210 /* Create argument list (argv1, ..., argvN) */
2211 if (!(arg = PyTuple_New(argc - 1)))
2212 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002213
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002214 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchakaccffb252014-02-03 21:23:46 +02002215 PyObject *s = fromTclString(argv[i + 1]);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002216 if (!s || PyTuple_SetItem(arg, i, s)) {
2217 Py_DECREF(arg);
2218 return PythonCmd_Error(interp);
2219 }
2220 }
2221 res = PyEval_CallObject(func, arg);
2222 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002223
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002224 if (res == NULL)
2225 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002226
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002227 obj_res = AsObj(res);
2228 if (obj_res == NULL) {
2229 Py_DECREF(res);
2230 return PythonCmd_Error(interp);
2231 }
2232 else {
2233 Tcl_SetObjResult(interp, obj_res);
2234 rv = TCL_OK;
2235 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002236
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002237 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002238
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002239 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002240
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002241 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002242}
2243
2244static void
Fred Drake509d79a2000-07-08 04:04:38 +00002245PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002246{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002247 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002248
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002249 ENTER_PYTHON
2250 Py_XDECREF(data->self);
2251 Py_XDECREF(data->func);
2252 PyMem_DEL(data);
2253 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002254}
2255
Barry Warsawfa701a81997-01-16 00:15:11 +00002256
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002257
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002258
Guilherme Polo1972d162009-03-27 21:43:08 +00002259#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002260TCL_DECLARE_MUTEX(command_mutex)
2261
2262typedef struct CommandEvent{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002263 Tcl_Event ev;
2264 Tcl_Interp* interp;
2265 char *name;
2266 int create;
2267 int *status;
2268 ClientData *data;
2269 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002270} CommandEvent;
2271
2272static int
2273Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002274{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002275 if (ev->create)
2276 *ev->status = Tcl_CreateCommand(
2277 ev->interp, ev->name, PythonCmd,
2278 ev->data, PythonCmdDelete) == NULL;
2279 else
2280 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2281 Tcl_MutexLock(&command_mutex);
2282 Tcl_ConditionNotify(ev->done);
2283 Tcl_MutexUnlock(&command_mutex);
2284 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002285}
Guilherme Polo1972d162009-03-27 21:43:08 +00002286#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002287
2288static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002289Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002290{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002291 TkappObject *self = (TkappObject*)selfptr;
2292 PythonCmd_ClientData *data;
2293 char *cmdName;
2294 PyObject *func;
2295 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002296
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002297 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2298 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002299 CHECK_STRING_LENGTH(cmdName);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002300 if (!PyCallable_Check(func)) {
2301 PyErr_SetString(PyExc_TypeError, "command not callable");
2302 return NULL;
2303 }
Guido van Rossum18468821994-06-20 07:49:28 +00002304
Martin v. Löwisa9656492003-03-30 08:44:58 +00002305#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002306 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2307 !WaitForMainloop(self))
2308 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002309#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002310
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002311 data = PyMem_NEW(PythonCmd_ClientData, 1);
2312 if (!data)
2313 return PyErr_NoMemory();
2314 Py_INCREF(self);
2315 Py_INCREF(func);
2316 data->self = selfptr;
2317 data->func = func;
Guilherme Polo1972d162009-03-27 21:43:08 +00002318
2319#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002320 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2321 Tcl_Condition cond = NULL;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03002322 CommandEvent *ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2323 if (ev == NULL) {
2324 PyErr_NoMemory();
2325 PyMem_DEL(data);
2326 return NULL;
2327 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002328 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2329 ev->interp = self->interp;
2330 ev->create = 1;
2331 ev->name = cmdName;
2332 ev->data = (ClientData)data;
2333 ev->status = &err;
2334 ev->done = &cond;
2335 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2336 Tcl_ConditionFinalize(&cond);
2337 }
2338 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002339#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002340 {
2341 ENTER_TCL
2342 err = Tcl_CreateCommand(
2343 Tkapp_Interp(self), cmdName, PythonCmd,
2344 (ClientData)data, PythonCmdDelete) == NULL;
2345 LEAVE_TCL
2346 }
2347 if (err) {
2348 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2349 PyMem_DEL(data);
2350 return NULL;
2351 }
Guido van Rossum18468821994-06-20 07:49:28 +00002352
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002353 Py_INCREF(Py_None);
2354 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002355}
2356
Barry Warsawfa701a81997-01-16 00:15:11 +00002357
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002358
Guido van Rossum18468821994-06-20 07:49:28 +00002359static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002360Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002361{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002362 TkappObject *self = (TkappObject*)selfptr;
2363 char *cmdName;
2364 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002365
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002366 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2367 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03002368 CHECK_STRING_LENGTH(cmdName);
Guilherme Polo1972d162009-03-27 21:43:08 +00002369
2370#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002371 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2372 Tcl_Condition cond = NULL;
2373 CommandEvent *ev;
Serhiy Storchaka1c09c0e2014-09-11 10:38:08 +03002374 ev = (CommandEvent*)attemptckalloc(sizeof(CommandEvent));
2375 if (ev == NULL) {
2376 PyErr_NoMemory();
2377 return NULL;
2378 }
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002379 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2380 ev->interp = self->interp;
2381 ev->create = 0;
2382 ev->name = cmdName;
2383 ev->status = &err;
2384 ev->done = &cond;
2385 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2386 &command_mutex);
2387 Tcl_ConditionFinalize(&cond);
2388 }
2389 else
Guilherme Polo1972d162009-03-27 21:43:08 +00002390#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002391 {
2392 ENTER_TCL
2393 err = Tcl_DeleteCommand(self->interp, cmdName);
2394 LEAVE_TCL
2395 }
2396 if (err == -1) {
2397 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2398 return NULL;
2399 }
2400 Py_INCREF(Py_None);
2401 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002402}
2403
Barry Warsawfa701a81997-01-16 00:15:11 +00002404
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002405
Guido van Rossum00d93061998-05-28 23:06:38 +00002406#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002407/** File Handler **/
2408
Guido van Rossum00d93061998-05-28 23:06:38 +00002409typedef struct _fhcdata {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002410 PyObject *func;
2411 PyObject *file;
2412 int id;
2413 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002414} FileHandler_ClientData;
2415
2416static FileHandler_ClientData *HeadFHCD;
2417
2418static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002419NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002420{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002421 FileHandler_ClientData *p;
2422 p = PyMem_NEW(FileHandler_ClientData, 1);
2423 if (p != NULL) {
2424 Py_XINCREF(func);
2425 Py_XINCREF(file);
2426 p->func = func;
2427 p->file = file;
2428 p->id = id;
2429 p->next = HeadFHCD;
2430 HeadFHCD = p;
2431 }
2432 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002433}
2434
2435static void
Fred Drake509d79a2000-07-08 04:04:38 +00002436DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002437{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002438 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002439
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002440 pp = &HeadFHCD;
2441 while ((p = *pp) != NULL) {
2442 if (p->id == id) {
2443 *pp = p->next;
2444 Py_XDECREF(p->func);
2445 Py_XDECREF(p->file);
2446 PyMem_DEL(p);
2447 }
2448 else
2449 pp = &p->next;
2450 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002451}
2452
Guido van Rossuma597dde1995-01-10 20:56:29 +00002453static void
Fred Drake509d79a2000-07-08 04:04:38 +00002454FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002455{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002456 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2457 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002458
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002459 ENTER_PYTHON
2460 func = data->func;
2461 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002462
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002463 arg = Py_BuildValue("(Oi)", file, (long) mask);
2464 res = PyEval_CallObject(func, arg);
2465 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002466
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002467 if (res == NULL) {
2468 errorInCmd = 1;
2469 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2470 }
2471 Py_XDECREF(res);
2472 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002473}
2474
Guido van Rossum18468821994-06-20 07:49:28 +00002475static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002476Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2477 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002478{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002479 FileHandler_ClientData *data;
2480 PyObject *file, *func;
2481 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002482
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002483 if (!self && Py_Py3kWarningFlag) {
2484 if (PyErr_Warn(PyExc_DeprecationWarning,
2485 "_tkinter.createfilehandler is gone in 3.x") < 0)
2486 return NULL;
2487 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002488
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002489 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2490 &file, &mask, &func))
2491 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002492
Martin v. Löwisa9656492003-03-30 08:44:58 +00002493#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002494 if (!self && !tcl_lock) {
2495 /* We don't have the Tcl lock since Tcl is threaded. */
2496 PyErr_SetString(PyExc_RuntimeError,
2497 "_tkinter.createfilehandler not supported "
2498 "for threaded Tcl");
2499 return NULL;
2500 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002501#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002502
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002503 if (self) {
2504 CHECK_TCL_APPARTMENT;
2505 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002506
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002507 tfile = PyObject_AsFileDescriptor(file);
2508 if (tfile < 0)
2509 return NULL;
2510 if (!PyCallable_Check(func)) {
2511 PyErr_SetString(PyExc_TypeError, "bad argument list");
2512 return NULL;
2513 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002514
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002515 data = NewFHCD(func, file, tfile);
2516 if (data == NULL)
2517 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002518
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002519 /* Ought to check for null Tcl_File object... */
2520 ENTER_TCL
2521 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2522 LEAVE_TCL
2523 Py_INCREF(Py_None);
2524 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002525}
2526
2527static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002528Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002529{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002530 PyObject *file;
2531 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002532
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002533 if (!self && Py_Py3kWarningFlag) {
2534 if (PyErr_Warn(PyExc_DeprecationWarning,
2535 "_tkinter.deletefilehandler is gone in 3.x") < 0)
2536 return NULL;
2537 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002538
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002539 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2540 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002541
Martin v. Löwisa9656492003-03-30 08:44:58 +00002542#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002543 if (!self && !tcl_lock) {
2544 /* We don't have the Tcl lock since Tcl is threaded. */
2545 PyErr_SetString(PyExc_RuntimeError,
2546 "_tkinter.deletefilehandler not supported "
2547 "for threaded Tcl");
2548 return NULL;
2549 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002550#endif
Neal Norwitz12e22172003-03-03 21:16:39 +00002551
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002552 if (self) {
2553 CHECK_TCL_APPARTMENT;
2554 }
Neal Norwitz12e22172003-03-03 21:16:39 +00002555
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002556 tfile = PyObject_AsFileDescriptor(file);
2557 if (tfile < 0)
2558 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002559
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002560 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002561
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002562 /* Ought to check for null Tcl_File object... */
2563 ENTER_TCL
2564 Tcl_DeleteFileHandler(tfile);
2565 LEAVE_TCL
2566 Py_INCREF(Py_None);
2567 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002568}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002569#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002570
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002571
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002572/**** Tktt Object (timer token) ****/
2573
Jeremy Hylton938ace62002-07-17 16:30:39 +00002574static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002575
Guido van Rossum00d93061998-05-28 23:06:38 +00002576typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002577 PyObject_HEAD
2578 Tcl_TimerToken token;
2579 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002580} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002581
2582static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002583Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002584{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002585 TkttObject *v = (TkttObject *)self;
2586 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002587
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002588 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2589 return NULL;
2590 if (v->token != NULL) {
2591 Tcl_DeleteTimerHandler(v->token);
2592 v->token = NULL;
2593 }
2594 if (func != NULL) {
2595 v->func = NULL;
2596 Py_DECREF(func);
2597 Py_DECREF(v); /* See Tktt_New() */
2598 }
2599 Py_INCREF(Py_None);
2600 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002601}
2602
2603static PyMethodDef Tktt_methods[] =
2604{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002605 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2606 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002607};
2608
2609static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002610Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002611{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002612 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002613
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002614 v = PyObject_New(TkttObject, &Tktt_Type);
2615 if (v == NULL)
2616 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002617
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002618 Py_INCREF(func);
2619 v->token = NULL;
2620 v->func = func;
2621
2622 /* Extra reference, deleted when called or when handler is deleted */
2623 Py_INCREF(v);
2624 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002625}
2626
2627static void
Fred Drake509d79a2000-07-08 04:04:38 +00002628Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002629{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002630 TkttObject *v = (TkttObject *)self;
2631 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002632
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002633 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002634
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002635 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002636}
2637
Guido van Rossum597ac201998-05-12 14:36:19 +00002638static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002639Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002640{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002641 TkttObject *v = (TkttObject *)self;
2642 char buf[100];
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002643
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002644 PyOS_snprintf(buf, sizeof(buf), "<tktimertoken at %p%s>", v,
2645 v->func == NULL ? ", handler deleted" : "");
2646 return PyString_FromString(buf);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002647}
2648
2649static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00002650Tktt_GetAttr(PyObject *self, char *name)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002651{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002652 return Py_FindMethod(Tktt_methods, self, name);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002653}
2654
2655static PyTypeObject Tktt_Type =
2656{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002657 PyVarObject_HEAD_INIT(NULL, 0)
2658 "tktimertoken", /*tp_name */
2659 sizeof(TkttObject), /*tp_basicsize */
2660 0, /*tp_itemsize */
2661 Tktt_Dealloc, /*tp_dealloc */
2662 0, /*tp_print */
2663 Tktt_GetAttr, /*tp_getattr */
2664 0, /*tp_setattr */
2665 0, /*tp_compare */
2666 Tktt_Repr, /*tp_repr */
2667 0, /*tp_as_number */
2668 0, /*tp_as_sequence */
2669 0, /*tp_as_mapping */
2670 0, /*tp_hash */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002671};
2672
Barry Warsawfa701a81997-01-16 00:15:11 +00002673
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002674
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002675/** Timer Handler **/
2676
2677static void
Fred Drake509d79a2000-07-08 04:04:38 +00002678TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002679{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002680 TkttObject *v = (TkttObject *)clientData;
2681 PyObject *func = v->func;
2682 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002683
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002684 if (func == NULL)
2685 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002686
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002687 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002688
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002689 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002690
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002691 res = PyEval_CallObject(func, NULL);
2692 Py_DECREF(func);
2693 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002694
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002695 if (res == NULL) {
2696 errorInCmd = 1;
2697 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2698 }
2699 else
2700 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002701
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002702 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002703}
2704
2705static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002706Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002707{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002708 int milliseconds;
2709 PyObject *func;
2710 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002711
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002712 if (!self && Py_Py3kWarningFlag) {
2713 if (PyErr_Warn(PyExc_DeprecationWarning,
2714 "_tkinter.createtimerhandler is gone in 3.x") < 0)
2715 return NULL;
2716 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002717
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002718 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2719 &milliseconds, &func))
2720 return NULL;
2721 if (!PyCallable_Check(func)) {
2722 PyErr_SetString(PyExc_TypeError, "bad argument list");
2723 return NULL;
2724 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002725
Martin v. Löwisa9656492003-03-30 08:44:58 +00002726#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002727 if (!self && !tcl_lock) {
2728 /* We don't have the Tcl lock since Tcl is threaded. */
2729 PyErr_SetString(PyExc_RuntimeError,
2730 "_tkinter.createtimerhandler not supported "
2731 "for threaded Tcl");
2732 return NULL;
2733 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002734#endif
Martin v. Löwis7f134892003-03-03 10:40:01 +00002735
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002736 if (self) {
2737 CHECK_TCL_APPARTMENT;
2738 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002739
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002740 v = Tktt_New(func);
2741 if (v) {
2742 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2743 (ClientData)v);
2744 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002745
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002746 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002747}
2748
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002749
Guido van Rossum18468821994-06-20 07:49:28 +00002750/** Event Loop **/
2751
Guido van Rossum18468821994-06-20 07:49:28 +00002752static PyObject *
Andrew M. Kuchling36f6d772006-06-03 19:02:35 +00002753Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002754{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002755 int threshold = 0;
2756 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002757#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002758 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002759#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002760
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002761 if (!self && Py_Py3kWarningFlag) {
2762 if (PyErr_Warn(PyExc_DeprecationWarning,
2763 "_tkinter.mainloop is gone in 3.x") < 0)
2764 return NULL;
2765 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002766
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002767 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2768 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002769
Martin v. Löwisa9656492003-03-30 08:44:58 +00002770#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002771 if (!self && !tcl_lock) {
2772 /* We don't have the Tcl lock since Tcl is threaded. */
2773 PyErr_SetString(PyExc_RuntimeError,
2774 "_tkinter.mainloop not supported "
2775 "for threaded Tcl");
2776 return NULL;
2777 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00002778#endif
Martin v. Löwis6a759d92003-01-04 08:36:57 +00002779
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002780 if (self) {
2781 CHECK_TCL_APPARTMENT;
2782 self->dispatching = 1;
2783 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002784
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002785 quitMainLoop = 0;
2786 while (Tk_GetNumMainWindows() > threshold &&
2787 !quitMainLoop &&
2788 !errorInCmd)
2789 {
2790 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002791
2792#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002793 if (self && self->threaded) {
2794 /* Allow other Python threads to run. */
2795 ENTER_TCL
2796 result = Tcl_DoOneEvent(0);
2797 LEAVE_TCL
2798 }
2799 else {
2800 Py_BEGIN_ALLOW_THREADS
2801 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2802 tcl_tstate = tstate;
2803 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2804 tcl_tstate = NULL;
2805 if(tcl_lock)PyThread_release_lock(tcl_lock);
2806 if (result == 0)
2807 Sleep(Tkinter_busywaitinterval);
2808 Py_END_ALLOW_THREADS
2809 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002810#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002811 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002812#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002813
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002814 if (PyErr_CheckSignals() != 0) {
2815 if (self)
2816 self->dispatching = 0;
2817 return NULL;
2818 }
2819 if (result < 0)
2820 break;
2821 }
2822 if (self)
2823 self->dispatching = 0;
2824 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002825
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002826 if (errorInCmd) {
2827 errorInCmd = 0;
2828 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2829 excInCmd = valInCmd = trbInCmd = NULL;
2830 return NULL;
2831 }
2832 Py_INCREF(Py_None);
2833 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002834}
2835
2836static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002837Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002838{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002839 int flags = 0;
2840 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002841
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002842 if (!self && Py_Py3kWarningFlag) {
2843 if (PyErr_Warn(PyExc_DeprecationWarning,
2844 "_tkinter.dooneevent is gone in 3.x") < 0)
2845 return NULL;
2846 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002847
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002848 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2849 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002850
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002851 ENTER_TCL
2852 rv = Tcl_DoOneEvent(flags);
2853 LEAVE_TCL
2854 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002855}
2856
2857static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002858Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002859{
2860
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002861 if (!self && Py_Py3kWarningFlag) {
2862 if (PyErr_Warn(PyExc_DeprecationWarning,
2863 "_tkinter.quit is gone in 3.x") < 0)
2864 return NULL;
2865 }
Guilherme Poloe7f14032009-01-03 21:51:09 +00002866
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002867 if (!PyArg_ParseTuple(args, ":quit"))
2868 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002869
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002870 quitMainLoop = 1;
2871 Py_INCREF(Py_None);
2872 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002873}
2874
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002875static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002876Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002877{
2878
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002879 if (!PyArg_ParseTuple(args, ":interpaddr"))
2880 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002881
Victor Stinner930c3c92013-09-05 00:26:15 +02002882 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002883}
2884
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002885static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002886Tkapp_TkInit(PyObject *self, PyObject *args)
2887{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002888 Tcl_Interp *interp = Tkapp_Interp(self);
2889 const char * _tk_exists = NULL;
2890 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002891
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002892#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002893 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2894 * first call failed.
2895 * To avoid the deadlock, we just refuse the second call through
2896 * a static variable.
2897 */
2898 if (tk_load_failed) {
2899 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2900 return NULL;
2901 }
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002902#endif
2903
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002904 /* We want to guard against calling Tk_Init() multiple times */
2905 CHECK_TCL_APPARTMENT;
2906 ENTER_TCL
2907 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2908 ENTER_OVERLAP
2909 if (err == TCL_ERROR) {
2910 /* This sets an exception, but we cannot return right
2911 away because we need to exit the overlap first. */
2912 Tkinter_Error(self);
2913 } else {
2914 _tk_exists = Tkapp_Result(self);
2915 }
2916 LEAVE_OVERLAP_TCL
2917 if (err == TCL_ERROR) {
2918 return NULL;
2919 }
2920 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2921 if (Tk_Init(interp) == TCL_ERROR) {
2922 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002923#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002924 tk_load_failed = 1;
Guilherme Poloa66cf5b2009-02-09 20:50:27 +00002925#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002926 return NULL;
2927 }
2928 }
2929 Py_INCREF(Py_None);
2930 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002931}
Barry Warsawfa701a81997-01-16 00:15:11 +00002932
Martin v. Löwisffad6332002-11-26 09:28:05 +00002933static PyObject *
2934Tkapp_WantObjects(PyObject *self, PyObject *args)
2935{
2936
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002937 int wantobjects = -1;
2938 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2939 return NULL;
2940 if (wantobjects == -1)
2941 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2942 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002943
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002944 Py_INCREF(Py_None);
2945 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002946}
2947
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002948static PyObject *
2949Tkapp_WillDispatch(PyObject *self, PyObject *args)
2950{
2951
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002952 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002953
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002954 Py_INCREF(Py_None);
2955 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002956}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002957
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03002958/* Convert Python string or any buffer compatible object to Tcl byte-array
2959 * object. Use it to pass binary data (e.g. image's data) to Tcl/Tk commands.
2960 */
2961static PyObject *
2962Tkapp_CreateByteArray(PyObject *self, PyObject *args)
2963{
2964 Py_buffer view;
2965 Tcl_Obj* obj;
2966 PyObject *res = NULL;
2967
2968 if (!PyArg_ParseTuple(args, "s*:_createbytearray", &view))
2969 return NULL;
2970
2971 if (view.len >= INT_MAX) {
2972 PyErr_SetString(PyExc_OverflowError, "string is too long");
2973 return NULL;
2974 }
2975 obj = Tcl_NewByteArrayObj(view.buf, (int)view.len);
2976 if (obj == NULL) {
2977 PyBuffer_Release(&view);
2978 return Tkinter_Error(self);
2979 }
2980 res = newPyTclObject(obj);
2981 PyBuffer_Release(&view);
2982 return res;
2983}
2984
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002985
Guido van Rossum18468821994-06-20 07:49:28 +00002986/**** Tkapp Method List ****/
2987
2988static PyMethodDef Tkapp_methods[] =
2989{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00002990 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2991 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2992 {"call", Tkapp_Call, METH_VARARGS},
2993 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2994 {"eval", Tkapp_Eval, METH_VARARGS},
2995 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2996 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2997 {"record", Tkapp_Record, METH_VARARGS},
2998 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2999 {"setvar", Tkapp_SetVar, METH_VARARGS},
3000 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
3001 {"getvar", Tkapp_GetVar, METH_VARARGS},
3002 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
3003 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
3004 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
3005 {"getint", Tkapp_GetInt, METH_VARARGS},
3006 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
3007 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
3008 {"exprstring", Tkapp_ExprString, METH_VARARGS},
3009 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
3010 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
3011 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
3012 {"splitlist", Tkapp_SplitList, METH_VARARGS},
3013 {"split", Tkapp_Split, METH_VARARGS},
3014 {"merge", Tkapp_Merge, METH_VARARGS},
3015 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
3016 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003017#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003018 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3019 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003020#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003021 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3022 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3023 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3024 {"quit", Tkapp_Quit, METH_VARARGS},
3025 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
3026 {"loadtk", Tkapp_TkInit, METH_NOARGS},
Serhiy Storchaka04fa7042014-07-31 07:48:14 +03003027 {"_createbytearray", Tkapp_CreateByteArray, METH_VARARGS},
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003028 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003029};
3030
Barry Warsawfa701a81997-01-16 00:15:11 +00003031
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003032
Guido van Rossum18468821994-06-20 07:49:28 +00003033/**** Tkapp Type Methods ****/
3034
3035static void
Fred Drake509d79a2000-07-08 04:04:38 +00003036Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00003037{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003038 /*CHECK_TCL_APPARTMENT;*/
3039 ENTER_TCL
3040 Tcl_DeleteInterp(Tkapp_Interp(self));
3041 LEAVE_TCL
3042 PyObject_Del(self);
3043 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00003044}
3045
3046static PyObject *
Martin v. Löwis1d519e42006-02-27 23:10:11 +00003047Tkapp_GetAttr(PyObject *self, char *name)
Guido van Rossum18468821994-06-20 07:49:28 +00003048{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003049 return Py_FindMethod(Tkapp_methods, self, name);
Guido van Rossum18468821994-06-20 07:49:28 +00003050}
3051
3052static PyTypeObject Tkapp_Type =
3053{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003054 PyVarObject_HEAD_INIT(NULL, 0)
3055 "tkapp", /*tp_name */
3056 sizeof(TkappObject), /*tp_basicsize */
3057 0, /*tp_itemsize */
3058 Tkapp_Dealloc, /*tp_dealloc */
3059 0, /*tp_print */
3060 Tkapp_GetAttr, /*tp_getattr */
3061 0, /*tp_setattr */
3062 0, /*tp_compare */
3063 0, /*tp_repr */
3064 0, /*tp_as_number */
3065 0, /*tp_as_sequence */
3066 0, /*tp_as_mapping */
3067 0, /*tp_hash */
Guido van Rossum18468821994-06-20 07:49:28 +00003068};
3069
Barry Warsawfa701a81997-01-16 00:15:11 +00003070
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003071
Guido van Rossum18468821994-06-20 07:49:28 +00003072/**** Tkinter Module ****/
3073
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003074typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003075 PyObject* tuple;
3076 int size; /* current size */
3077 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003078} FlattenContext;
3079
3080static int
3081_bump(FlattenContext* context, int size)
3082{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003083 /* expand tuple to hold (at least) size new items.
3084 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003085
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003086 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003087
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003088 if (maxsize < context->size + size)
3089 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003090
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003091 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003092
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003093 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003094}
3095
3096static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00003097_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003098{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003099 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003100
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003101 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003102
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003103 if (depth > 1000) {
3104 PyErr_SetString(PyExc_ValueError,
3105 "nesting too deep in _flatten");
3106 return 0;
3107 } else if (PyList_Check(item)) {
3108 size = PyList_GET_SIZE(item);
3109 /* preallocate (assume no nesting) */
3110 if (context->size + size > context->maxsize &&
3111 !_bump(context, size))
3112 return 0;
3113 /* copy items to output tuple */
3114 for (i = 0; i < size; i++) {
3115 PyObject *o = PyList_GET_ITEM(item, i);
3116 if (PyList_Check(o) || PyTuple_Check(o)) {
3117 if (!_flatten1(context, o, depth + 1))
3118 return 0;
3119 } else if (o != Py_None) {
3120 if (context->size + 1 > context->maxsize &&
3121 !_bump(context, 1))
3122 return 0;
3123 Py_INCREF(o);
3124 PyTuple_SET_ITEM(context->tuple,
3125 context->size++, o);
3126 }
3127 }
3128 } else if (PyTuple_Check(item)) {
3129 /* same, for tuples */
3130 size = PyTuple_GET_SIZE(item);
3131 if (context->size + size > context->maxsize &&
3132 !_bump(context, size))
3133 return 0;
3134 for (i = 0; i < size; i++) {
3135 PyObject *o = PyTuple_GET_ITEM(item, i);
3136 if (PyList_Check(o) || PyTuple_Check(o)) {
3137 if (!_flatten1(context, o, depth + 1))
3138 return 0;
3139 } else if (o != Py_None) {
3140 if (context->size + 1 > context->maxsize &&
3141 !_bump(context, 1))
3142 return 0;
3143 Py_INCREF(o);
3144 PyTuple_SET_ITEM(context->tuple,
3145 context->size++, o);
3146 }
3147 }
3148 } else {
3149 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
3150 return 0;
3151 }
3152 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003153}
3154
3155static PyObject *
3156Tkinter_Flatten(PyObject* self, PyObject* args)
3157{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003158 FlattenContext context;
3159 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003160
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003161 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
3162 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003163
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003164 context.maxsize = PySequence_Size(item);
3165 if (context.maxsize < 0)
3166 return NULL;
3167 if (context.maxsize == 0)
3168 return PyTuple_New(0);
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003169
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003170 context.tuple = PyTuple_New(context.maxsize);
3171 if (!context.tuple)
3172 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003173
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003174 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003175
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003176 if (!_flatten1(&context, item,0))
3177 return NULL;
3178
3179 if (_PyTuple_Resize(&context.tuple, context.size))
3180 return NULL;
3181
3182 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00003183}
3184
Guido van Rossum18468821994-06-20 07:49:28 +00003185static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003186Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00003187{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003188 char *screenName = NULL;
3189 char *baseName = NULL;
3190 char *className = NULL;
3191 int interactive = 0;
3192 int wantobjects = 0;
3193 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3194 int sync = 0; /* pass -sync to wish */
3195 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003196
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003197 baseName = strrchr(Py_GetProgramName(), '/');
3198 if (baseName != NULL)
3199 baseName++;
3200 else
3201 baseName = Py_GetProgramName();
3202 className = "Tk";
Guido van Rossum18468821994-06-20 07:49:28 +00003203
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003204 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3205 &screenName, &baseName, &className,
3206 &interactive, &wantobjects, &wantTk,
3207 &sync, &use))
3208 return NULL;
Serhiy Storchaka2a0220b2014-05-30 14:23:52 +03003209 CHECK_STRING_LENGTH(screenName);
3210 CHECK_STRING_LENGTH(baseName);
3211 CHECK_STRING_LENGTH(className);
3212 CHECK_STRING_LENGTH(use);
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003213
3214 return (PyObject *) Tkapp_New(screenName, baseName, className,
3215 interactive, wantobjects, wantTk,
3216 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003217}
3218
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003219static PyObject *
3220Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3221{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003222 int new_val;
3223 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3224 return NULL;
3225 if (new_val < 0) {
3226 PyErr_SetString(PyExc_ValueError,
3227 "busywaitinterval must be >= 0");
3228 return NULL;
3229 }
3230 Tkinter_busywaitinterval = new_val;
3231 Py_INCREF(Py_None);
3232 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003233}
3234
3235static char setbusywaitinterval_doc[] =
3236"setbusywaitinterval(n) -> None\n\
3237\n\
3238Set the busy-wait interval in milliseconds between successive\n\
3239calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3240It should be set to a divisor of the maximum time between\n\
3241frames in an animation.";
3242
3243static PyObject *
3244Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3245{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003246 return PyInt_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003247}
3248
3249static char getbusywaitinterval_doc[] =
3250"getbusywaitinterval() -> int\n\
3251\n\
3252Return the current busy-wait interval between successive\n\
3253calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3254
Guido van Rossum18468821994-06-20 07:49:28 +00003255static PyMethodDef moduleMethods[] =
3256{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003257 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3258 {"create", Tkinter_Create, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00003259#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003260 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
3261 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00003262#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003263 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
3264 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
3265 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
3266 {"quit", Tkapp_Quit, METH_VARARGS},
3267 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3268 setbusywaitinterval_doc},
3269 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3270 METH_NOARGS, getbusywaitinterval_doc},
3271 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003272};
3273
Guido van Rossum7bf15641998-05-22 18:28:17 +00003274#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003275
3276static int stdin_ready = 0;
3277
Guido van Rossumad4db171998-06-13 13:56:28 +00003278#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003279static void
Fred Drake509d79a2000-07-08 04:04:38 +00003280MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003281{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003282 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003283}
Guido van Rossumad4db171998-06-13 13:56:28 +00003284#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003285
Martin v. Löwisa9656492003-03-30 08:44:58 +00003286#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003287static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003288#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003289
Guido van Rossum18468821994-06-20 07:49:28 +00003290static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003291EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003292{
Guido van Rossumad4db171998-06-13 13:56:28 +00003293#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003294 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003295#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003296#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003297 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003298#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003299 stdin_ready = 0;
3300 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003301#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003302 tfile = fileno(stdin);
3303 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003304#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003305 while (!errorInCmd && !stdin_ready) {
3306 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003307#ifdef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003308 if (_kbhit()) {
3309 stdin_ready = 1;
3310 break;
3311 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003312#endif
3313#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003314 Py_BEGIN_ALLOW_THREADS
3315 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3316 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003317
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003318 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003319
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003320 tcl_tstate = NULL;
3321 if(tcl_lock)PyThread_release_lock(tcl_lock);
3322 if (result == 0)
3323 Sleep(Tkinter_busywaitinterval);
3324 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003325#else
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003326 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003327#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003328
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003329 if (result < 0)
3330 break;
3331 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003332#ifndef MS_WINDOWS
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003333 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003334#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003335 if (errorInCmd) {
3336 errorInCmd = 0;
3337 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3338 excInCmd = valInCmd = trbInCmd = NULL;
3339 PyErr_Print();
3340 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003341#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003342 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003343#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003344 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003345}
Guido van Rossum18468821994-06-20 07:49:28 +00003346
Guido van Rossum00d93061998-05-28 23:06:38 +00003347#endif
3348
Guido van Rossum7bf15641998-05-22 18:28:17 +00003349static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003350EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003351{
Guido van Rossum00d93061998-05-28 23:06:38 +00003352#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003353 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003354#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003355 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003356#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003357 PyOS_InputHook = EventHook;
3358 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003359#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003360}
3361
3362static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003363DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003364{
Guido van Rossum00d93061998-05-28 23:06:38 +00003365#ifdef WAIT_FOR_STDIN
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003366 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3367 PyOS_InputHook = NULL;
3368 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003369#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003370}
3371
Barry Warsawfa701a81997-01-16 00:15:11 +00003372
3373/* all errors will be checked in one fell swoop in init_tkinter() */
3374static void
Fred Drake509d79a2000-07-08 04:04:38 +00003375ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003376{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003377 PyObject *v = PyInt_FromLong(val);
3378 if (v) {
3379 PyDict_SetItemString(d, name, v);
3380 Py_DECREF(v);
3381 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003382}
3383static void
Fred Drake509d79a2000-07-08 04:04:38 +00003384ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003385{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003386 PyObject *v = PyString_FromString(val);
3387 if (v) {
3388 PyDict_SetItemString(d, name, v);
3389 Py_DECREF(v);
3390 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003391}
3392
3393
Mark Hammond62b1ab12002-07-23 06:31:15 +00003394PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003395init_tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003396{
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003397 PyObject *m, *d;
Guido van Rossum18468821994-06-20 07:49:28 +00003398
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003399 Py_TYPE(&Tkapp_Type) = &PyType_Type;
Guido van Rossum00d93061998-05-28 23:06:38 +00003400
3401#ifdef WITH_THREAD
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003402 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003403#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003404
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003405 m = Py_InitModule("_tkinter", moduleMethods);
3406 if (m == NULL)
3407 return;
Guido van Rossum18468821994-06-20 07:49:28 +00003408
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003409 d = PyModule_GetDict(m);
3410 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3411 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003412
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003413 ins_long(d, "READABLE", TCL_READABLE);
3414 ins_long(d, "WRITABLE", TCL_WRITABLE);
3415 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3416 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3417 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3418 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3419 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3420 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3421 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3422 ins_string(d, "TK_VERSION", TK_VERSION);
3423 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003424
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003425 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003426
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003427 Py_TYPE(&Tktt_Type) = &PyType_Type;
3428 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003429
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003430 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3431 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003432
3433#ifdef TK_AQUA
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003434 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3435 * start waking up. Note that Tcl_FindExecutable will do this, this
3436 * code must be above it! The original warning from
3437 * tkMacOSXAppInit.c is copied below.
3438 *
3439 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3440 * Tcl interpreter for now. It probably should work to do this
3441 * in the other order, but for now it doesn't seem to.
3442 *
3443 */
3444 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003445#endif
3446
3447
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003448 /* This helps the dynamic loader; in Unicode aware Tcl versions
3449 it also helps Tcl find its encodings. */
3450 Tcl_FindExecutable(Py_GetProgramName());
Guido van Rossume187b0e2000-03-27 21:46:29 +00003451
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003452 if (PyErr_Occurred())
3453 return;
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003454
Guido van Rossum43ff8681998-07-14 18:02:13 +00003455#if 0
Antoine Pitrouc83ea132010-05-09 14:46:46 +00003456 /* This was not a good idea; through <Destroy> bindings,
3457 Tcl_Finalize() may invoke Python code but at that point the
3458 interpreter and thread state have already been destroyed! */
3459 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003460#endif
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003461
Guido van Rossum18468821994-06-20 07:49:28 +00003462}