blob: 262d679055ff76ade62590d21d66b71d0b954bb6 [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 Pitrouf95a1b32010-05-09 15:52:27 +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
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +030036#define CHECK_SIZE(size, elemsize) \
37 ((size_t)(size) <= Py_MAX((size_t)INT_MAX, UINT_MAX / (size_t)(elemsize)))
38
Martin v. Löwis71e25a02002-10-01 18:08:06 +000039/* Starting with Tcl 8.4, many APIs offer const-correctness. Unfortunately,
40 making _tkinter correct for this API means to break earlier
41 versions. USE_COMPAT_CONST allows to make _tkinter work with both 8.4 and
42 earlier versions. Once Tcl releases before 8.4 don't need to be supported
43 anymore, this should go. */
44#define USE_COMPAT_CONST
45
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +000046/* If Tcl is compiled for threads, we must also define TCL_THREAD. We define
47 it always; if Tcl is not threaded, the thread functions in
48 Tcl are empty. */
49#define TCL_THREADS
50
Jack Jansencb852442001-12-09 23:15:56 +000051#ifdef TK_FRAMEWORK
52#include <Tcl/tcl.h>
53#include <Tk/tk.h>
54#else
Guido van Rossum18468821994-06-20 07:49:28 +000055#include <tcl.h>
56#include <tk.h>
Jack Jansencb852442001-12-09 23:15:56 +000057#endif
Guido van Rossum18468821994-06-20 07:49:28 +000058
Guilherme Polo2d87e422009-04-10 22:19:09 +000059#include "tkinter.h"
60
Jason Tishlerbbe89612002-12-31 20:30:46 +000061/* For Tcl 8.2 and 8.3, CONST* is not defined (except on Cygwin). */
Martin v. Löwis5b177f12002-12-30 18:14:15 +000062#ifndef CONST84_RETURN
63#define CONST84_RETURN
Jason Tishlerbbe89612002-12-31 20:30:46 +000064#undef CONST
Martin v. Löwis5b177f12002-12-30 18:14:15 +000065#define CONST
66#endif
67
Guilherme Polo66917722009-02-09 22:35:27 +000068#if TK_VERSION_HEX < 0x08030102
69#error "Tk older than 8.3.1 not supported"
Guido van Rossum00d93061998-05-28 23:06:38 +000070#endif
71
Jack Janseneddc1442003-11-20 01:44:59 +000072#if !(defined(MS_WINDOWS) || defined(__CYGWIN__))
Guido van Rossum0d2390c1997-08-14 19:57:07 +000073#define HAVE_CREATEFILEHANDLER
74#endif
75
Guido van Rossum00d93061998-05-28 23:06:38 +000076#ifdef HAVE_CREATEFILEHANDLER
77
Neal Norwitzd948a432006-01-08 01:08:55 +000078/* This bit is to ensure that TCL_UNIX_FD is defined and doesn't interfere
79 with the proper calculation of FHANDLETYPE == TCL_UNIX_FD below. */
80#ifndef TCL_UNIX_FD
81# ifdef TCL_WIN_SOCKET
82# define TCL_UNIX_FD (! TCL_WIN_SOCKET)
83# else
84# define TCL_UNIX_FD 1
85# endif
86#endif
87
Guido van Rossum00d93061998-05-28 23:06:38 +000088/* Tcl_CreateFileHandler() changed several times; these macros deal with the
89 messiness. In Tcl 8.0 and later, it is not available on Windows (and on
90 Unix, only because Jack added it back); when available on Windows, it only
91 applies to sockets. */
92
Guido van Rossum7bf15641998-05-22 18:28:17 +000093#ifdef MS_WINDOWS
94#define FHANDLETYPE TCL_WIN_SOCKET
95#else
96#define FHANDLETYPE TCL_UNIX_FD
97#endif
98
Guido van Rossum00d93061998-05-28 23:06:38 +000099/* If Tcl can wait for a Unix file descriptor, define the EventHook() routine
100 which uses this to handle Tcl events while the user is typing commands. */
101
102#if FHANDLETYPE == TCL_UNIX_FD
Guido van Rossum7bf15641998-05-22 18:28:17 +0000103#define WAIT_FOR_STDIN
104#endif
105
Guido van Rossum00d93061998-05-28 23:06:38 +0000106#endif /* HAVE_CREATEFILEHANDLER */
107
Guido van Rossumad4db171998-06-13 13:56:28 +0000108#ifdef MS_WINDOWS
109#include <conio.h>
110#define WAIT_FOR_STDIN
111#endif
112
Guido van Rossum00d93061998-05-28 23:06:38 +0000113#ifdef WITH_THREAD
114
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000115/* The threading situation is complicated. Tcl is not thread-safe, except
116 when configured with --enable-threads.
Guido van Rossum00d93061998-05-28 23:06:38 +0000117 So we need to use a lock around all uses of Tcl. Previously, the Python
118 interpreter lock was used for this. However, this causes problems when
119 other Python threads need to run while Tcl is blocked waiting for events.
120
121 To solve this problem, a separate lock for Tcl is introduced. Holding it
122 is incompatible with holding Python's interpreter lock. The following four
123 macros manipulate both locks together.
124
125 ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
126 Py_END_ALLOW_THREADS. They should be used whenever a call into Tcl is made
127 that could call an event handler, or otherwise affect the state of a Tcl
128 interpreter. These assume that the surrounding code has the Python
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000129 interpreter lock; inside the brackets, the Python interpreter lock has been
Guido van Rossum00d93061998-05-28 23:06:38 +0000130 released and the lock for Tcl has been acquired.
131
Guido van Rossum5e977831998-06-15 14:03:52 +0000132 Sometimes, it is necessary to have both the Python lock and the Tcl lock.
133 (For example, when transferring data from the Tcl interpreter result to a
134 Python string object.) This can be done by using different macros to close
135 the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
136 the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
137 releases the Tcl lock.
138
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000139 By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
Guido van Rossum00d93061998-05-28 23:06:38 +0000140 handlers when the handler needs to use Python. Such event handlers are
141 entered while the lock for Tcl is held; the event handler presumably needs
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000142 to use Python. ENTER_PYTHON releases the lock for Tcl and acquires
Guido van Rossum00d93061998-05-28 23:06:38 +0000143 the Python interpreter lock, restoring the appropriate thread state, and
144 LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
145 for Tcl. It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000146 the code between ENTER_PYTHON and LEAVE_PYTHON.
Guido van Rossum00d93061998-05-28 23:06:38 +0000147
148 These locks expand to several statements and brackets; they should not be
149 used in branches of if statements and the like.
150
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000151 If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
152 only valid in the thread that created it, and all Tk activity must happen in this
153 thread, also. That means that the mainloop must be invoked in the thread that
154 created the interpreter. Invoking commands from other threads is possible;
155 _tkinter will queue an event for the interpreter thread, which will then
156 execute the command and pass back the result. If the main thread is not in the
157 mainloop, and invoking commands causes an exception; if the main loop is running
158 but not processing events, the command invocation will block.
159
160 In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
161 anymore, since multiple Tcl interpreters may simultaneously dispatch in different
162 threads. So we use the Tcl TLS API.
163
Guido van Rossum00d93061998-05-28 23:06:38 +0000164*/
165
Guido van Rossum65d5b571998-12-21 19:32:43 +0000166static PyThread_type_lock tcl_lock = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000167
168#ifdef TCL_THREADS
169static Tcl_ThreadDataKey state_key;
170typedef PyThreadState *ThreadSpecificData;
171#define tcl_tstate (*(PyThreadState**)Tcl_GetThreadData(&state_key, sizeof(PyThreadState*)))
172#else
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000173static PyThreadState *tcl_tstate = NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000174#endif
Guido van Rossum00d93061998-05-28 23:06:38 +0000175
176#define ENTER_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 { PyThreadState *tstate = PyThreadState_Get(); Py_BEGIN_ALLOW_THREADS \
178 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate;
Guido van Rossum00d93061998-05-28 23:06:38 +0000179
180#define LEAVE_TCL \
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000181 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); Py_END_ALLOW_THREADS}
Guido van Rossum00d93061998-05-28 23:06:38 +0000182
Guido van Rossum62320c91998-06-15 04:36:09 +0000183#define ENTER_OVERLAP \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000184 Py_END_ALLOW_THREADS
Guido van Rossum62320c91998-06-15 04:36:09 +0000185
186#define LEAVE_OVERLAP_TCL \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000187 tcl_tstate = NULL; if(tcl_lock)PyThread_release_lock(tcl_lock); }
Guido van Rossum62320c91998-06-15 04:36:09 +0000188
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000189#define ENTER_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000190 { PyThreadState *tstate = tcl_tstate; tcl_tstate = NULL; \
191 if(tcl_lock)PyThread_release_lock(tcl_lock); PyEval_RestoreThread((tstate)); }
Guido van Rossum00d93061998-05-28 23:06:38 +0000192
193#define LEAVE_PYTHON \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000194 { PyThreadState *tstate = PyEval_SaveThread(); \
195 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); tcl_tstate = tstate; }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000196
197#define CHECK_TCL_APPARTMENT \
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000198 if (((TkappObject *)self)->threaded && \
199 ((TkappObject *)self)->thread_id != Tcl_GetCurrentThread()) { \
200 PyErr_SetString(PyExc_RuntimeError, "Calling Tcl from different appartment"); \
201 return 0; \
202 }
Guido van Rossum00d93061998-05-28 23:06:38 +0000203
204#else
205
206#define ENTER_TCL
207#define LEAVE_TCL
Guido van Rossum62320c91998-06-15 04:36:09 +0000208#define ENTER_OVERLAP
209#define LEAVE_OVERLAP_TCL
Guido van Rossumdc1adab1998-10-09 20:51:18 +0000210#define ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +0000211#define LEAVE_PYTHON
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000212#define CHECK_TCL_APPARTMENT
Guido van Rossum00d93061998-05-28 23:06:38 +0000213
214#endif
215
Guido van Rossum97867b21996-08-08 19:09:53 +0000216#ifndef FREECAST
Guido van Rossum7ffa7611996-08-13 21:10:16 +0000217#define FREECAST (char *)
Guido van Rossum97867b21996-08-08 19:09:53 +0000218#endif
219
Guido van Rossum18468821994-06-20 07:49:28 +0000220/**** Tkapp Object Declaration ****/
221
Jeremy Hylton938ace62002-07-17 16:30:39 +0000222static PyTypeObject Tkapp_Type;
Guido van Rossum18468821994-06-20 07:49:28 +0000223
Guido van Rossum00d93061998-05-28 23:06:38 +0000224typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000225 PyObject_HEAD
226 Tcl_Interp *interp;
227 int wantobjects;
228 int threaded; /* True if tcl_platform[threaded] */
229 Tcl_ThreadId thread_id;
230 int dispatching;
231 /* We cannot include tclInt.h, as this is internal.
232 So we cache interesting types here. */
233 Tcl_ObjType *BooleanType;
234 Tcl_ObjType *ByteArrayType;
235 Tcl_ObjType *DoubleType;
236 Tcl_ObjType *IntType;
237 Tcl_ObjType *ListType;
238 Tcl_ObjType *ProcBodyType;
239 Tcl_ObjType *StringType;
Guido van Rossum00d93061998-05-28 23:06:38 +0000240} TkappObject;
Guido van Rossum18468821994-06-20 07:49:28 +0000241
Christian Heimes90aa7642007-12-19 02:45:37 +0000242#define Tkapp_Check(v) (Py_TYPE(v) == &Tkapp_Type)
Guido van Rossum18468821994-06-20 07:49:28 +0000243#define Tkapp_Interp(v) (((TkappObject *) (v))->interp)
Guido van Rossumada6d872000-10-12 17:14:46 +0000244#define Tkapp_Result(v) Tcl_GetStringResult(Tkapp_Interp(v))
Guido van Rossum18468821994-06-20 07:49:28 +0000245
Guido van Rossum35d43371997-08-02 00:09:09 +0000246#define DEBUG_REFCNT(v) (printf("DEBUG: id=%p, refcnt=%i\n", \
Christian Heimes90aa7642007-12-19 02:45:37 +0000247(void *) v, Py_REFCNT(v)))
Guido van Rossum18468821994-06-20 07:49:28 +0000248
Barry Warsawfa701a81997-01-16 00:15:11 +0000249
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000250
Guido van Rossum18468821994-06-20 07:49:28 +0000251/**** Error Handling ****/
252
253static PyObject *Tkinter_TclError;
Guido van Rossumd308e2b1994-07-07 09:25:12 +0000254static int quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +0000255static int errorInCmd = 0;
256static PyObject *excInCmd;
257static PyObject *valInCmd;
Guido van Rossum3bbc62e1995-01-02 19:30:30 +0000258static PyObject *trbInCmd;
Guido van Rossum18468821994-06-20 07:49:28 +0000259
Guilherme Polob681df42009-02-09 22:33:59 +0000260#ifdef TKINTER_PROTECT_LOADTK
Alexandre Vassalotti21455952009-04-05 01:30:02 +0000261static int tk_load_failed = 0;
Guilherme Polob681df42009-02-09 22:33:59 +0000262#endif
Barry Warsawfa701a81997-01-16 00:15:11 +0000263
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000264
Guido van Rossum18468821994-06-20 07:49:28 +0000265static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000266Tkinter_Error(PyObject *v)
Guido van Rossum18468821994-06-20 07:49:28 +0000267{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000268 PyErr_SetString(Tkinter_TclError, Tkapp_Result(v));
269 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000270}
271
Barry Warsawfa701a81997-01-16 00:15:11 +0000272
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000273
Guido van Rossum18468821994-06-20 07:49:28 +0000274/**** Utils ****/
Guido van Rossum00d93061998-05-28 23:06:38 +0000275
Martin v. Löwis28e9ce92003-05-09 08:19:48 +0000276static int Tkinter_busywaitinterval = 20;
277
Guido van Rossum00d93061998-05-28 23:06:38 +0000278#ifdef WITH_THREAD
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000279#ifndef MS_WINDOWS
Guido van Rossum541f2411998-08-13 13:29:22 +0000280
Guido van Rossum00d93061998-05-28 23:06:38 +0000281/* Millisecond sleep() for Unix platforms. */
282
283static void
Fred Drake509d79a2000-07-08 04:04:38 +0000284Sleep(int milli)
Guido van Rossum00d93061998-05-28 23:06:38 +0000285{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000286 /* XXX Too bad if you don't have select(). */
287 struct timeval t;
288 t.tv_sec = milli/1000;
289 t.tv_usec = (milli%1000) * 1000;
290 select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t);
Guido van Rossum00d93061998-05-28 23:06:38 +0000291}
Guido van Rossum2a5119b1998-05-29 01:28:40 +0000292#endif /* MS_WINDOWS */
Guido van Rossum00d93061998-05-28 23:06:38 +0000293
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000294/* Wait up to 1s for the mainloop to come up. */
295
296static int
297WaitForMainloop(TkappObject* self)
298{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000299 int i;
300 for (i = 0; i < 10; i++) {
301 if (self->dispatching)
302 return 1;
303 Py_BEGIN_ALLOW_THREADS
304 Sleep(100);
305 Py_END_ALLOW_THREADS
306 }
307 if (self->dispatching)
308 return 1;
309 PyErr_SetString(PyExc_RuntimeError, "main thread is not in main loop");
310 return 0;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +0000311}
Martin v. Löwisa9656492003-03-30 08:44:58 +0000312#endif /* WITH_THREAD */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000313
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000314
Guido van Rossum18468821994-06-20 07:49:28 +0000315static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000316AsString(PyObject *value, PyObject *tmp)
Guido van Rossum18468821994-06-20 07:49:28 +0000317{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000318 if (PyBytes_Check(value))
319 return PyBytes_AsString(value);
Serhiy Storchaka369606d2013-09-23 23:20:07 +0300320 else if (PyUnicode_Check(value))
321 return PyUnicode_AsUTF8(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000322 else {
323 PyObject *v = PyObject_Str(value);
324 if (v == NULL)
325 return NULL;
326 if (PyList_Append(tmp, v) != 0) {
327 Py_DECREF(v);
328 return NULL;
329 }
330 Py_DECREF(v);
Serhiy Storchaka369606d2013-09-23 23:20:07 +0300331 return PyUnicode_AsUTF8(v);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000332 }
Guido van Rossum18468821994-06-20 07:49:28 +0000333}
334
Barry Warsawfa701a81997-01-16 00:15:11 +0000335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000336
Guido van Rossum18468821994-06-20 07:49:28 +0000337#define ARGSZ 64
338
339static char *
Fred Drake509d79a2000-07-08 04:04:38 +0000340Merge(PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +0000341{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000342 PyObject *tmp = NULL;
343 char *argvStore[ARGSZ];
344 char **argv = NULL;
345 int fvStore[ARGSZ];
346 int *fv = NULL;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300347 Py_ssize_t argc = 0, fvc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000348 char *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000350 if (!(tmp = PyList_New(0)))
351 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +0000352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000353 argv = argvStore;
354 fv = fvStore;
Guido van Rossum18468821994-06-20 07:49:28 +0000355
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000356 if (args == NULL)
357 argc = 0;
Barry Warsawfa701a81997-01-16 00:15:11 +0000358
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000359 else if (!PyTuple_Check(args)) {
360 argc = 1;
361 fv[0] = 0;
362 if (!(argv[0] = AsString(args, tmp)))
363 goto finally;
364 }
365 else {
366 argc = PyTuple_Size(args);
Guido van Rossum18468821994-06-20 07:49:28 +0000367
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000368 if (argc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300369 if (!CHECK_SIZE(argc, sizeof(char *))) {
370 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
371 goto finally;
372 }
373 argv = (char **)ckalloc((size_t)argc * sizeof(char *));
374 fv = (int *)ckalloc((size_t)argc * sizeof(int));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000375 if (argv == NULL || fv == NULL) {
376 PyErr_NoMemory();
377 goto finally;
378 }
379 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000380
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000381 for (i = 0; i < argc; i++) {
382 PyObject *v = PyTuple_GetItem(args, i);
383 if (PyTuple_Check(v)) {
384 fv[i] = 1;
385 if (!(argv[i] = Merge(v)))
386 goto finally;
387 fvc++;
388 }
389 else if (v == Py_None) {
390 argc = i;
391 break;
392 }
393 else {
394 fv[i] = 0;
395 if (!(argv[i] = AsString(v, tmp)))
396 goto finally;
397 fvc++;
398 }
399 }
400 }
401 res = Tcl_Merge(argc, argv);
402 if (res == NULL)
403 PyErr_SetString(Tkinter_TclError, "merge failed");
Guido van Rossum18468821994-06-20 07:49:28 +0000404
Barry Warsawfa701a81997-01-16 00:15:11 +0000405 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000406 for (i = 0; i < fvc; i++)
407 if (fv[i]) {
408 ckfree(argv[i]);
409 }
410 if (argv != argvStore)
411 ckfree(FREECAST argv);
412 if (fv != fvStore)
413 ckfree(FREECAST fv);
Guido van Rossum18468821994-06-20 07:49:28 +0000414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000415 Py_DECREF(tmp);
416 return res;
Guido van Rossum18468821994-06-20 07:49:28 +0000417}
418
Barry Warsawfa701a81997-01-16 00:15:11 +0000419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000420
Guido van Rossum18468821994-06-20 07:49:28 +0000421static PyObject *
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200422unicodeFromTclStringAndSize(const char *s, Py_ssize_t size)
423{
424 PyObject *r = PyUnicode_DecodeUTF8(s, size, NULL);
425 if (!r && PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
426 /* Tcl encodes null character as \xc0\x80 */
427 if (memchr(s, '\xc0', size)) {
428 char *buf, *q;
429 const char *e = s + size;
430 PyErr_Clear();
431 q = buf = (char *)PyMem_Malloc(size);
432 if (buf == NULL)
433 return NULL;
434 while (s != e) {
435 if (s + 1 != e && s[0] == '\xc0' && s[1] == '\x80') {
436 *q++ = '\0';
437 s += 2;
438 }
439 else
440 *q++ = *s++;
441 }
442 s = buf;
443 size = q - s;
444 r = PyUnicode_DecodeUTF8(s, size, NULL);
445 PyMem_Free(buf);
446 }
447 }
448 return r;
449}
450
451static PyObject *
452unicodeFromTclString(const char *s)
453{
454 return unicodeFromTclStringAndSize(s, strlen(s));
455}
456
457static PyObject *
458unicodeFromTclObj(Tcl_Obj *value)
459{
460 int len;
461 char *s = Tcl_GetStringFromObj(value, &len);
462 return unicodeFromTclStringAndSize(s, len);
463}
464
465
466static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +0000467Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000468{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000469 int argc;
470 char **argv;
471 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000473 if (list == NULL) {
474 Py_INCREF(Py_None);
475 return Py_None;
476 }
Guido van Rossum18468821994-06-20 07:49:28 +0000477
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000478 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
479 /* Not a list.
480 * Could be a quoted string containing funnies, e.g. {"}.
481 * Return the string itself.
482 */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200483 return unicodeFromTclString(list);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000484 }
Guido van Rossum18468821994-06-20 07:49:28 +0000485
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000486 if (argc == 0)
487 v = PyUnicode_FromString("");
488 else if (argc == 1)
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200489 v = unicodeFromTclString(argv[0]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000490 else if ((v = PyTuple_New(argc)) != NULL) {
491 int i;
492 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000494 for (i = 0; i < argc; i++) {
495 if ((w = Split(argv[i])) == NULL) {
496 Py_DECREF(v);
497 v = NULL;
498 break;
499 }
500 PyTuple_SetItem(v, i, w);
501 }
502 }
503 Tcl_Free(FREECAST argv);
504 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000505}
506
Martin v. Löwisffad6332002-11-26 09:28:05 +0000507/* In some cases, Tcl will still return strings that are supposed to be
508 lists. SplitObj walks through a nested tuple, finding string objects that
509 need to be split. */
510
Martin v. Löwis59683e82008-06-13 07:50:45 +0000511static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000512SplitObj(PyObject *arg)
513{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000514 if (PyTuple_Check(arg)) {
515 int i, size;
516 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000517
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000518 size = PyTuple_Size(arg);
519 result = NULL;
520 /* Recursively invoke SplitObj for all tuple items.
521 If this does not return a new object, no action is
522 needed. */
523 for(i = 0; i < size; i++) {
524 elem = PyTuple_GetItem(arg, i);
525 newelem = SplitObj(elem);
526 if (!newelem) {
527 Py_XDECREF(result);
528 return NULL;
529 }
530 if (!result) {
531 int k;
532 if (newelem == elem) {
533 Py_DECREF(newelem);
534 continue;
535 }
536 result = PyTuple_New(size);
537 if (!result)
538 return NULL;
539 for(k = 0; k < i; k++) {
540 elem = PyTuple_GetItem(arg, k);
541 Py_INCREF(elem);
542 PyTuple_SetItem(result, k, elem);
543 }
544 }
545 PyTuple_SetItem(result, i, newelem);
546 }
547 if (result)
548 return result;
549 /* Fall through, returning arg. */
550 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300551 else if (PyUnicode_Check(arg)) {
552 int argc;
553 char **argv;
554 char *list = PyUnicode_AsUTF8(arg);
555
556 if (list == NULL ||
557 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
558 Py_INCREF(arg);
559 return arg;
560 }
561 Tcl_Free(FREECAST argv);
562 if (argc > 1)
563 return Split(list);
564 /* Fall through, returning arg. */
565 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000566 else if (PyBytes_Check(arg)) {
567 int argc;
568 char **argv;
569 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
572 Py_INCREF(arg);
573 return arg;
574 }
575 Tcl_Free(FREECAST argv);
576 if (argc > 1)
577 return Split(PyBytes_AsString(arg));
578 /* Fall through, returning arg. */
579 }
580 Py_INCREF(arg);
581 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000582}
Barry Warsawfa701a81997-01-16 00:15:11 +0000583
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000584
Guido van Rossum18468821994-06-20 07:49:28 +0000585/**** Tkapp Object ****/
586
587#ifndef WITH_APPINIT
588int
Fred Drake509d79a2000-07-08 04:04:38 +0000589Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000590{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000592
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 if (Tcl_Init(interp) == TCL_ERROR) {
594 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
595 return TCL_ERROR;
596 }
Guilherme Polob681df42009-02-09 22:33:59 +0000597
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000598 _tkinter_skip_tk_init = Tcl_GetVar(interp,
599 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
600 if (_tkinter_skip_tk_init != NULL &&
601 strcmp(_tkinter_skip_tk_init, "1") == 0) {
602 return TCL_OK;
603 }
Guilherme Polob681df42009-02-09 22:33:59 +0000604
605#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000606 if (tk_load_failed) {
607 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
608 return TCL_ERROR;
609 }
Guilherme Polob681df42009-02-09 22:33:59 +0000610#endif
611
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000612 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000613#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000614 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000615#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000616 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
617 return TCL_ERROR;
618 }
Guilherme Polob681df42009-02-09 22:33:59 +0000619
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000620 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000621}
622#endif /* !WITH_APPINIT */
623
Guido van Rossum18468821994-06-20 07:49:28 +0000624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000625
Barry Warsawfa701a81997-01-16 00:15:11 +0000626
627/* Initialize the Tk application; see the `main' function in
628 * `tkMain.c'.
629 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000630
Thomas Wouters58d05102000-07-24 14:43:35 +0000631static void EnableEventHook(void); /* Forward */
632static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000633
Barry Warsawfa701a81997-01-16 00:15:11 +0000634static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000635Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000636 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000637{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000638 TkappObject *v;
639 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000640
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000641 v = PyObject_New(TkappObject, &Tkapp_Type);
642 if (v == NULL)
643 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000645 v->interp = Tcl_CreateInterp();
646 v->wantobjects = wantobjects;
647 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
648 TCL_GLOBAL_ONLY) != NULL;
649 v->thread_id = Tcl_GetCurrentThread();
650 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000651
652#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 if (v->threaded) {
654 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
655 Py_DECREF(v);
656 return 0;
657 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000658#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000659#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000660 if (v->threaded && tcl_lock) {
661 /* If Tcl is threaded, we don't need the lock. */
662 PyThread_free_lock(tcl_lock);
663 tcl_lock = NULL;
664 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000665#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000667 v->BooleanType = Tcl_GetObjType("boolean");
668 v->ByteArrayType = Tcl_GetObjType("bytearray");
669 v->DoubleType = Tcl_GetObjType("double");
670 v->IntType = Tcl_GetObjType("int");
671 v->ListType = Tcl_GetObjType("list");
672 v->ProcBodyType = Tcl_GetObjType("procbody");
673 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000674
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000675 /* Delete the 'exit' command, which can screw things up */
676 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000677
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000678 if (screenName != NULL)
679 Tcl_SetVar2(v->interp, "env", "DISPLAY",
680 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000682 if (interactive)
683 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
684 else
685 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000686
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000687 /* This is used to get the application class for Tk 4.1 and up */
688 argv0 = (char*)ckalloc(strlen(className) + 1);
689 if (!argv0) {
690 PyErr_NoMemory();
691 Py_DECREF(v);
692 return NULL;
693 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000694
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000695 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200696 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
697 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000698 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
699 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000700
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 if (! wantTk) {
702 Tcl_SetVar(v->interp,
703 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
704 }
Guilherme Polob681df42009-02-09 22:33:59 +0000705#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 else if (tk_load_failed) {
707 Tcl_SetVar(v->interp,
708 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
709 }
Guilherme Polob681df42009-02-09 22:33:59 +0000710#endif
David Aschere2b4b322004-02-18 05:59:53 +0000711
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000712 /* some initial arguments need to be in argv */
713 if (sync || use) {
714 char *args;
715 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000717 if (sync)
718 len += sizeof "-sync";
719 if (use)
720 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000721
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000722 args = (char*)ckalloc(len);
723 if (!args) {
724 PyErr_NoMemory();
725 Py_DECREF(v);
726 return NULL;
727 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000728
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000729 args[0] = '\0';
730 if (sync)
731 strcat(args, "-sync");
732 if (use) {
733 if (sync)
734 strcat(args, " ");
735 strcat(args, "-use ");
736 strcat(args, use);
737 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000738
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000739 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
740 ckfree(args);
741 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000743 if (Tcl_AppInit(v->interp) != TCL_OK) {
744 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000745#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000746 if (wantTk) {
747 const char *_tkinter_tk_failed;
748 _tkinter_tk_failed = Tcl_GetVar(v->interp,
749 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000750
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000751 if ( _tkinter_tk_failed != NULL &&
752 strcmp(_tkinter_tk_failed, "1") == 0) {
753 tk_load_failed = 1;
754 }
755 }
Guilherme Polob681df42009-02-09 22:33:59 +0000756#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000757 Py_DECREF((PyObject *)v);
758 return (TkappObject *)result;
759 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000760
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000761 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000762
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000763 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000764}
765
Barry Warsawfa701a81997-01-16 00:15:11 +0000766
Benjamin Peterson5879d412009-03-30 14:51:56 +0000767#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000768static void
769Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000770 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000771{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000772 Py_BEGIN_ALLOW_THREADS;
773 Tcl_MutexLock(mutex);
774 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
775 Tcl_ThreadAlert(self->thread_id);
776 Tcl_ConditionWait(cond, mutex, NULL);
777 Tcl_MutexUnlock(mutex);
778 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000779}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000780#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000781
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000782
Guido van Rossum18468821994-06-20 07:49:28 +0000783/** Tcl Eval **/
784
Martin v. Löwisffad6332002-11-26 09:28:05 +0000785typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000786 PyObject_HEAD
787 Tcl_Obj *value;
788 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000789} PyTclObject;
790
Neal Norwitz227b5332006-03-22 09:28:35 +0000791static PyTypeObject PyTclObject_Type;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000792#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000793
794static PyObject *
795newPyTclObject(Tcl_Obj *arg)
796{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000797 PyTclObject *self;
798 self = PyObject_New(PyTclObject, &PyTclObject_Type);
799 if (self == NULL)
800 return NULL;
801 Tcl_IncrRefCount(arg);
802 self->value = arg;
803 self->string = NULL;
804 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000805}
806
807static void
808PyTclObject_dealloc(PyTclObject *self)
809{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000810 Tcl_DecrRefCount(self->value);
811 Py_XDECREF(self->string);
812 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000813}
814
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000815static char*
816PyTclObject_TclString(PyObject *self)
817{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000818 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000819}
820
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000821/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000822PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000823"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000824
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000825static PyObject *
826PyTclObject_string(PyTclObject *self, void *ignored)
827{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000828 if (!self->string) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200829 self->string = unicodeFromTclObj(self->value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000830 if (!self->string)
831 return NULL;
832 }
833 Py_INCREF(self->string);
834 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000835}
836
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000837static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000838PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000839{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200840 if (self->string) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000841 Py_INCREF(self->string);
842 return self->string;
843 }
844 /* XXX Could chache result if it is non-ASCII. */
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200845 return unicodeFromTclObj(self->value);
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000846}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000847
Martin v. Löwisffad6332002-11-26 09:28:05 +0000848static PyObject *
849PyTclObject_repr(PyTclObject *self)
850{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000851 return PyUnicode_FromFormat("<%s object at %p>",
852 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000853}
854
Mark Dickinson211c6252009-02-01 10:28:51 +0000855#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
856
857static PyObject *
858PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000859{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000860 int result;
861 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000862
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000863 /* neither argument should be NULL, unless something's gone wrong */
864 if (self == NULL || other == NULL) {
865 PyErr_BadInternalCall();
866 return NULL;
867 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000868
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000869 /* both arguments should be instances of PyTclObject */
870 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
871 v = Py_NotImplemented;
872 goto finished;
873 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000874
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000875 if (self == other)
876 /* fast path when self and other are identical */
877 result = 0;
878 else
879 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
880 Tcl_GetString(((PyTclObject *)other)->value));
881 /* Convert return value to a Boolean */
882 switch (op) {
883 case Py_EQ:
884 v = TEST_COND(result == 0);
885 break;
886 case Py_NE:
887 v = TEST_COND(result != 0);
888 break;
889 case Py_LE:
890 v = TEST_COND(result <= 0);
891 break;
892 case Py_GE:
893 v = TEST_COND(result >= 0);
894 break;
895 case Py_LT:
896 v = TEST_COND(result < 0);
897 break;
898 case Py_GT:
899 v = TEST_COND(result > 0);
900 break;
901 default:
902 PyErr_BadArgument();
903 return NULL;
904 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000905 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000906 Py_INCREF(v);
907 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000908}
909
Martin v. Löwis39195712003-01-04 00:33:13 +0000910PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
911
Martin v. Löwisffad6332002-11-26 09:28:05 +0000912static PyObject*
913get_typename(PyTclObject* obj, void* ignored)
914{
Serhiy Storchaka1317e142014-02-03 21:24:07 +0200915 return unicodeFromTclString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000916}
917
Martin v. Löwis39195712003-01-04 00:33:13 +0000918
Martin v. Löwisffad6332002-11-26 09:28:05 +0000919static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000920 {"typename", (getter)get_typename, NULL, get_typename__doc__},
921 {"string", (getter)PyTclObject_string, NULL,
922 PyTclObject_string__doc__},
923 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000924};
925
Neal Norwitz227b5332006-03-22 09:28:35 +0000926static PyTypeObject PyTclObject_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000927 PyVarObject_HEAD_INIT(NULL, 0)
928 "_tkinter.Tcl_Obj", /*tp_name*/
929 sizeof(PyTclObject), /*tp_basicsize*/
930 0, /*tp_itemsize*/
931 /* methods */
932 (destructor)PyTclObject_dealloc,/*tp_dealloc*/
933 0, /*tp_print*/
934 0, /*tp_getattr*/
935 0, /*tp_setattr*/
936 0, /*tp_reserved*/
937 (reprfunc)PyTclObject_repr, /*tp_repr*/
938 0, /*tp_as_number*/
939 0, /*tp_as_sequence*/
940 0, /*tp_as_mapping*/
941 0, /*tp_hash*/
942 0, /*tp_call*/
943 (reprfunc)PyTclObject_str, /*tp_str*/
944 PyObject_GenericGetAttr, /*tp_getattro*/
945 0, /*tp_setattro*/
946 0, /*tp_as_buffer*/
947 Py_TPFLAGS_DEFAULT, /*tp_flags*/
948 0, /*tp_doc*/
949 0, /*tp_traverse*/
950 0, /*tp_clear*/
951 PyTclObject_richcompare, /*tp_richcompare*/
952 0, /*tp_weaklistoffset*/
953 0, /*tp_iter*/
954 0, /*tp_iternext*/
955 0, /*tp_methods*/
956 0, /*tp_members*/
957 PyTclObject_getsetlist, /*tp_getset*/
958 0, /*tp_base*/
959 0, /*tp_dict*/
960 0, /*tp_descr_get*/
961 0, /*tp_descr_set*/
962 0, /*tp_dictoffset*/
963 0, /*tp_init*/
964 0, /*tp_alloc*/
965 0, /*tp_new*/
966 0, /*tp_free*/
967 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000968};
969
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000970static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000971AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000972{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000973 Tcl_Obj *result;
974 long longVal;
975 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000976
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000977 if (PyBytes_Check(value))
978 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
979 PyBytes_GET_SIZE(value));
980 else if (PyBool_Check(value))
981 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
982 else if (PyLong_CheckExact(value) &&
983 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
984 !overflow)) {
985 /* If there is an overflow in the long conversion,
986 fall through to default object handling. */
987 return Tcl_NewLongObj(longVal);
988 }
989 else if (PyFloat_Check(value))
990 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
991 else if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300992 Tcl_Obj **argv;
993 Py_ssize_t size, i;
994
995 size = PyTuple_Size(value);
996 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
997 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
998 return NULL;
999 }
1000 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001001 if(!argv)
1002 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001003 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001004 argv[i] = AsObj(PyTuple_GetItem(value,i));
1005 result = Tcl_NewListObj(PyTuple_Size(value), argv);
1006 ckfree(FREECAST argv);
1007 return result;
1008 }
1009 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001010 void *inbuf;
1011 Py_ssize_t size;
1012 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001013 Tcl_UniChar *outbuf = NULL;
1014 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001015 size_t allocsize;
1016
1017 if (PyUnicode_READY(value) == -1)
1018 return NULL;
1019
1020 inbuf = PyUnicode_DATA(value);
1021 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001022 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
1023 PyErr_SetString(PyExc_OverflowError, "string is too long");
1024 return NULL;
1025 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001026 kind = PyUnicode_KIND(value);
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001027 if (kind == sizeof(Tcl_UniChar))
1028 return Tcl_NewUnicodeObj(inbuf, size);
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001029 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
1030 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001031 /* Else overflow occurred, and we take the next exit */
1032 if (!outbuf) {
1033 PyErr_NoMemory();
1034 return NULL;
1035 }
1036 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001037 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
1038 /* We cannot test for sizeof(Tcl_UniChar) directly,
1039 so we test for UTF-8 size instead. */
1040#if TCL_UTF_MAX == 3
1041 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001042 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001043 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001044 "character U+%x is above the range "
1045 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001046 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001047 ckfree(FREECAST outbuf);
1048 return NULL;
1049 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001050#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001051 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001052 }
1053 result = Tcl_NewUnicodeObj(outbuf, size);
1054 ckfree(FREECAST outbuf);
1055 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001056 }
1057 else if(PyTclObject_Check(value)) {
1058 Tcl_Obj *v = ((PyTclObject*)value)->value;
1059 Tcl_IncrRefCount(v);
1060 return v;
1061 }
1062 else {
1063 PyObject *v = PyObject_Str(value);
1064 if (!v)
1065 return 0;
1066 result = AsObj(v);
1067 Py_DECREF(v);
1068 return result;
1069 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001070}
1071
Martin v. Löwisffad6332002-11-26 09:28:05 +00001072static PyObject*
1073FromObj(PyObject* tkapp, Tcl_Obj *value)
1074{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001075 PyObject *result = NULL;
1076 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001077
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001078 if (value->typePtr == NULL) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001079 return unicodeFromTclStringAndSize(value->bytes, value->length);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001080 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001081
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001082 if (value->typePtr == app->BooleanType) {
1083 result = value->internalRep.longValue ? Py_True : Py_False;
1084 Py_INCREF(result);
1085 return result;
1086 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001087
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001088 if (value->typePtr == app->ByteArrayType) {
1089 int size;
1090 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1091 return PyBytes_FromStringAndSize(data, size);
1092 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001093
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001094 if (value->typePtr == app->DoubleType) {
1095 return PyFloat_FromDouble(value->internalRep.doubleValue);
1096 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001097
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001098 if (value->typePtr == app->IntType) {
1099 return PyLong_FromLong(value->internalRep.longValue);
1100 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001102 if (value->typePtr == app->ListType) {
1103 int size;
1104 int i, status;
1105 PyObject *elem;
1106 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001107
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001108 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1109 if (status == TCL_ERROR)
1110 return Tkinter_Error(tkapp);
1111 result = PyTuple_New(size);
1112 if (!result)
1113 return NULL;
1114 for (i = 0; i < size; i++) {
1115 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1116 value, i, &tcl_elem);
1117 if (status == TCL_ERROR) {
1118 Py_DECREF(result);
1119 return Tkinter_Error(tkapp);
1120 }
1121 elem = FromObj(tkapp, tcl_elem);
1122 if (!elem) {
1123 Py_DECREF(result);
1124 return NULL;
1125 }
1126 PyTuple_SetItem(result, i, elem);
1127 }
1128 return result;
1129 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001130
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001131 if (value->typePtr == app->ProcBodyType) {
1132 /* fall through: return tcl object. */
1133 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001134
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001135 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001136 return PyUnicode_FromKindAndData(
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001137 sizeof(Tcl_UniChar), Tcl_GetUnicode(value),
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001138 Tcl_GetCharLength(value));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001139 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001140
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001141 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001142}
1143
Benjamin Peterson5879d412009-03-30 14:51:56 +00001144#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001145/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001146TCL_DECLARE_MUTEX(call_mutex)
1147
1148typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001149 Tcl_Event ev; /* Must be first */
1150 TkappObject *self;
1151 PyObject *args;
1152 int flags;
1153 PyObject **res;
1154 PyObject **exc_type, **exc_value, **exc_tb;
1155 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001156} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001157#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001158
1159void
1160Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001161{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001162 int i;
1163 for (i = 0; i < objc; i++)
1164 Tcl_DecrRefCount(objv[i]);
1165 if (objv != objStore)
1166 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001167}
Guido van Rossum18468821994-06-20 07:49:28 +00001168
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001169/* Convert Python objects to Tcl objects. This must happen in the
1170 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001171
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001172static Tcl_Obj**
1173Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1174{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001175 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001176 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001177 if (args == NULL)
1178 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001179
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001180 else if (!PyTuple_Check(args)) {
1181 objv[0] = AsObj(args);
1182 if (objv[0] == 0)
1183 goto finally;
1184 objc = 1;
1185 Tcl_IncrRefCount(objv[0]);
1186 }
1187 else {
1188 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001189
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001190 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001191 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1192 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1193 return NULL;
1194 }
1195 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001196 if (objv == NULL) {
1197 PyErr_NoMemory();
1198 objc = 0;
1199 goto finally;
1200 }
1201 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001202
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001203 for (i = 0; i < objc; i++) {
1204 PyObject *v = PyTuple_GetItem(args, i);
1205 if (v == Py_None) {
1206 objc = i;
1207 break;
1208 }
1209 objv[i] = AsObj(v);
1210 if (!objv[i]) {
1211 /* Reset objc, so it attempts to clear
1212 objects only up to i. */
1213 objc = i;
1214 goto finally;
1215 }
1216 Tcl_IncrRefCount(objv[i]);
1217 }
1218 }
1219 *pobjc = objc;
1220 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001221finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001222 Tkapp_CallDeallocArgs(objv, objStore, objc);
1223 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001224}
Guido van Rossum212643f1998-04-29 16:22:14 +00001225
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001226/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001227
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001228static PyObject*
1229Tkapp_CallResult(TkappObject *self)
1230{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001231 PyObject *res = NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001232 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001233 if(self->wantobjects) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001234 /* Not sure whether the IncrRef is necessary, but something
1235 may overwrite the interpreter result while we are
1236 converting it. */
1237 Tcl_IncrRefCount(value);
1238 res = FromObj((PyObject*)self, value);
1239 Tcl_DecrRefCount(value);
1240 } else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001241 res = unicodeFromTclObj(value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001242 }
1243 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001244}
Guido van Rossum632de272000-03-29 00:19:50 +00001245
Benjamin Peterson5879d412009-03-30 14:51:56 +00001246#ifdef WITH_THREAD
1247
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001248/* Tkapp_CallProc is the event procedure that is executed in the context of
1249 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1250 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001251
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001252static int
1253Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1254{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001255 Tcl_Obj *objStore[ARGSZ];
1256 Tcl_Obj **objv;
1257 int objc;
1258 int i;
1259 ENTER_PYTHON
1260 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1261 if (!objv) {
1262 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1263 *(e->res) = NULL;
1264 }
1265 LEAVE_PYTHON
1266 if (!objv)
1267 goto done;
1268 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1269 ENTER_PYTHON
1270 if (i == TCL_ERROR) {
1271 *(e->res) = NULL;
1272 *(e->exc_type) = NULL;
1273 *(e->exc_tb) = NULL;
1274 *(e->exc_value) = PyObject_CallFunction(
1275 Tkinter_TclError, "s",
1276 Tcl_GetStringResult(e->self->interp));
1277 }
1278 else {
1279 *(e->res) = Tkapp_CallResult(e->self);
1280 }
1281 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001283 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001284done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001285 /* Wake up calling thread. */
1286 Tcl_MutexLock(&call_mutex);
1287 Tcl_ConditionNotify(e->done);
1288 Tcl_MutexUnlock(&call_mutex);
1289 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001290}
1291
Benjamin Peterson5879d412009-03-30 14:51:56 +00001292#endif
1293
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001294/* This is the main entry point for calling a Tcl command.
1295 It supports three cases, with regard to threading:
1296 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1297 the context of the calling thread.
1298 2. Tcl is threaded, caller of the command is in the interpreter thread:
1299 Execute the command in the calling thread. Since the Tcl lock will
1300 not be used, we can merge that with case 1.
1301 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1302 the interpreter thread. Allocation of Tcl objects needs to occur in the
1303 interpreter thread, so we ship the PyObject* args to the target thread,
1304 and perform processing there. */
1305
1306static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001307Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001308{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001309 Tcl_Obj *objStore[ARGSZ];
1310 Tcl_Obj **objv = NULL;
1311 int objc, i;
1312 PyObject *res = NULL;
1313 TkappObject *self = (TkappObject*)selfptr;
1314 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001315
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001316 /* If args is a single tuple, replace with contents of tuple */
1317 if (1 == PyTuple_Size(args)){
1318 PyObject* item = PyTuple_GetItem(args, 0);
1319 if (PyTuple_Check(item))
1320 args = item;
1321 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001322#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001323 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1324 /* We cannot call the command directly. Instead, we must
1325 marshal the parameters to the interpreter thread. */
1326 Tkapp_CallEvent *ev;
1327 Tcl_Condition cond = NULL;
1328 PyObject *exc_type, *exc_value, *exc_tb;
1329 if (!WaitForMainloop(self))
1330 return NULL;
1331 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1332 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1333 ev->self = self;
1334 ev->args = args;
1335 ev->res = &res;
1336 ev->exc_type = &exc_type;
1337 ev->exc_value = &exc_value;
1338 ev->exc_tb = &exc_tb;
1339 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001340
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001341 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001342
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001343 if (res == NULL) {
1344 if (exc_type)
1345 PyErr_Restore(exc_type, exc_value, exc_tb);
1346 else
1347 PyErr_SetObject(Tkinter_TclError, exc_value);
1348 }
1349 Tcl_ConditionFinalize(&cond);
1350 }
1351 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001352#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001353 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001354
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001355 objv = Tkapp_CallArgs(args, objStore, &objc);
1356 if (!objv)
1357 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001358
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001359 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001361 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001362
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001363 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001364
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001365 if (i == TCL_ERROR)
1366 Tkinter_Error(selfptr);
1367 else
1368 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001369
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001370 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001371
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001372 Tkapp_CallDeallocArgs(objv, objStore, objc);
1373 }
1374 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001375}
1376
1377
1378static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001379Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001380{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001381 /* Could do the same here as for Tkapp_Call(), but this is not used
1382 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1383 way for the user to do what all its Global* variants do (save and
1384 reset the scope pointer, call the local version, restore the saved
1385 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001387 char *cmd;
1388 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001389
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001390 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1391 "globalcall is deprecated and will be removed in 3.4",
1392 1) < 0)
1393 return 0;
1394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001395 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001396
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001397 cmd = Merge(args);
1398 if (cmd) {
1399 int err;
1400 ENTER_TCL
1401 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1402 ENTER_OVERLAP
1403 if (err == TCL_ERROR)
1404 res = Tkinter_Error(self);
1405 else
1406 res = PyUnicode_FromString(Tkapp_Result(self));
1407 LEAVE_OVERLAP_TCL
1408 ckfree(cmd);
1409 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001410
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001411 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001412}
1413
1414static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001415Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001416{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001417 char *script;
1418 PyObject *res = NULL;
1419 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001420
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001421 if (!PyArg_ParseTuple(args, "s:eval", &script))
1422 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001423
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001424 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001425
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001426 ENTER_TCL
1427 err = Tcl_Eval(Tkapp_Interp(self), script);
1428 ENTER_OVERLAP
1429 if (err == TCL_ERROR)
1430 res = Tkinter_Error(self);
1431 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001432 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001433 LEAVE_OVERLAP_TCL
1434 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001435}
1436
1437static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001438Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001439{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001440 char *script;
1441 PyObject *res = NULL;
1442 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001443
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001444 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1445 "globaleval is deprecated and will be removed in 3.4",
1446 1) < 0)
1447 return 0;
1448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001449 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1450 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001451
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001452 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001453
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001454 ENTER_TCL
1455 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1456 ENTER_OVERLAP
1457 if (err == TCL_ERROR)
1458 res = Tkinter_Error(self);
1459 else
1460 res = PyUnicode_FromString(Tkapp_Result(self));
1461 LEAVE_OVERLAP_TCL
1462 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001463}
1464
1465static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001466Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001467{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001468 char *fileName;
1469 PyObject *res = NULL;
1470 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001471
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001472 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1473 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001474
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001475 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001476
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001477 ENTER_TCL
1478 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1479 ENTER_OVERLAP
1480 if (err == TCL_ERROR)
1481 res = Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001482 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001483 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001484 LEAVE_OVERLAP_TCL
1485 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001486}
1487
1488static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001489Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001490{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001491 char *script;
1492 PyObject *res = NULL;
1493 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001494
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001495 if (!PyArg_ParseTuple(args, "s", &script))
1496 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001497
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001498 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001499
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001500 ENTER_TCL
1501 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1502 ENTER_OVERLAP
1503 if (err == TCL_ERROR)
1504 res = Tkinter_Error(self);
1505 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001506 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001507 LEAVE_OVERLAP_TCL
1508 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001509}
1510
1511static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001512Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001513{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001514 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001515
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001516 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1517 return NULL;
1518 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001519
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001520 ENTER_TCL
1521 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1522 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001524 Py_INCREF(Py_None);
1525 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001526}
1527
Barry Warsawfa701a81997-01-16 00:15:11 +00001528
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001529
Guido van Rossum18468821994-06-20 07:49:28 +00001530/** Tcl Variable **/
1531
Benjamin Peterson5879d412009-03-30 14:51:56 +00001532typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1533
1534#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001535TCL_DECLARE_MUTEX(var_mutex)
1536
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001537typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001538 Tcl_Event ev; /* must be first */
1539 PyObject *self;
1540 PyObject *args;
1541 int flags;
1542 EventFunc func;
1543 PyObject **res;
1544 PyObject **exc_type;
1545 PyObject **exc_val;
1546 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001547} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001548#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001549
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001550static int
1551varname_converter(PyObject *in, void *_out)
1552{
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001553 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001554 char **out = (char**)_out;
1555 if (PyBytes_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001556 if (PyBytes_Size(in) > INT_MAX) {
1557 PyErr_SetString(PyExc_OverflowError, "bytes object is too long");
1558 return 0;
1559 }
1560 s = PyBytes_AsString(in);
1561 if (strlen(s) != PyBytes_Size(in)) {
1562 PyErr_SetString(PyExc_ValueError, "null byte in bytes object");
1563 return 0;
1564 }
1565 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001566 return 1;
1567 }
1568 if (PyUnicode_Check(in)) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001569 Py_ssize_t size;
1570 s = PyUnicode_AsUTF8AndSize(in, &size);
Christian Heimesd33491e2014-02-05 00:29:17 +01001571 if (s == NULL) {
1572 return 0;
1573 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001574 if (size > INT_MAX) {
1575 PyErr_SetString(PyExc_OverflowError, "string is too long");
1576 return 0;
1577 }
1578 if (strlen(s) != size) {
1579 PyErr_SetString(PyExc_ValueError, "null character in string");
1580 return 0;
1581 }
1582 *out = s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001583 return 1;
1584 }
1585 if (PyTclObject_Check(in)) {
1586 *out = PyTclObject_TclString(in);
1587 return 1;
1588 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001589 PyErr_Format(PyExc_TypeError,
1590 "must be str, bytes or Tcl_Obj, not %.50s",
1591 in->ob_type->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001592 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001593}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001594
Benjamin Peterson5879d412009-03-30 14:51:56 +00001595#ifdef WITH_THREAD
1596
Martin v. Löwis59683e82008-06-13 07:50:45 +00001597static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001598var_perform(VarEvent *ev)
1599{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001600 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1601 if (!*(ev->res)) {
1602 PyObject *exc, *val, *tb;
1603 PyErr_Fetch(&exc, &val, &tb);
1604 PyErr_NormalizeException(&exc, &val, &tb);
1605 *(ev->exc_type) = exc;
1606 *(ev->exc_val) = val;
1607 Py_DECREF(tb);
1608 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001609
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001610}
1611
1612static int
1613var_proc(VarEvent* ev, int flags)
1614{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001615 ENTER_PYTHON
1616 var_perform(ev);
1617 Tcl_MutexLock(&var_mutex);
1618 Tcl_ConditionNotify(ev->cond);
1619 Tcl_MutexUnlock(&var_mutex);
1620 LEAVE_PYTHON
1621 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001622}
1623
Benjamin Peterson5879d412009-03-30 14:51:56 +00001624#endif
1625
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001626static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001627var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001628{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001629#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001630 TkappObject *self = (TkappObject*)selfptr;
1631 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1632 TkappObject *self = (TkappObject*)selfptr;
1633 VarEvent *ev;
1634 PyObject *res, *exc_type, *exc_val;
1635 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001637 /* The current thread is not the interpreter thread. Marshal
1638 the call to the interpreter thread, then wait for
1639 completion. */
1640 if (!WaitForMainloop(self))
1641 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001642
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001643 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001644
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001645 ev->self = selfptr;
1646 ev->args = args;
1647 ev->flags = flags;
1648 ev->func = func;
1649 ev->res = &res;
1650 ev->exc_type = &exc_type;
1651 ev->exc_val = &exc_val;
1652 ev->cond = &cond;
1653 ev->ev.proc = (Tcl_EventProc*)var_proc;
1654 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1655 Tcl_ConditionFinalize(&cond);
1656 if (!res) {
1657 PyErr_SetObject(exc_type, exc_val);
1658 Py_DECREF(exc_type);
1659 Py_DECREF(exc_val);
1660 return NULL;
1661 }
1662 return res;
1663 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001664#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001665 /* Tcl is not threaded, or this is the interpreter thread. */
1666 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001667}
1668
Guido van Rossum18468821994-06-20 07:49:28 +00001669static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001670SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001671{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001672 char *name1, *name2;
1673 PyObject *newValue;
1674 PyObject *res = NULL;
1675 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001676
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001677 switch (PyTuple_GET_SIZE(args)) {
1678 case 2:
1679 if (!PyArg_ParseTuple(args, "O&O:setvar",
1680 varname_converter, &name1, &newValue))
1681 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001682 /* XXX Acquire tcl lock??? */
1683 newval = AsObj(newValue);
1684 if (newval == NULL)
1685 return NULL;
1686 ENTER_TCL
1687 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1688 newval, flags);
1689 ENTER_OVERLAP
1690 if (!ok)
1691 Tkinter_Error(self);
1692 else {
1693 res = Py_None;
1694 Py_INCREF(res);
1695 }
1696 LEAVE_OVERLAP_TCL
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001697 break;
1698 case 3:
1699 if (!PyArg_ParseTuple(args, "ssO:setvar",
1700 &name1, &name2, &newValue))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001701 return NULL;
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001702 /* XXX must hold tcl lock already??? */
1703 newval = AsObj(newValue);
1704 ENTER_TCL
1705 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1706 ENTER_OVERLAP
1707 if (!ok)
1708 Tkinter_Error(self);
1709 else {
1710 res = Py_None;
1711 Py_INCREF(res);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001712 }
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001713 LEAVE_OVERLAP_TCL
1714 break;
1715 default:
1716 PyErr_SetString(PyExc_TypeError, "setvar requires 2 to 3 arguments");
1717 return NULL;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001718 }
1719 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001720}
1721
1722static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001723Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001724{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001725 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001726}
1727
1728static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001729Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001730{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001731 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001732}
1733
Barry Warsawfa701a81997-01-16 00:15:11 +00001734
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001735
Guido van Rossum18468821994-06-20 07:49:28 +00001736static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001737GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001738{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001739 char *name1, *name2=NULL;
1740 PyObject *res = NULL;
1741 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001742
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001743 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1744 varname_converter, &name1, &name2))
1745 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001746
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001747 ENTER_TCL
1748 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1749 ENTER_OVERLAP
1750 if (tres == NULL) {
1751 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1752 } else {
1753 if (((TkappObject*)self)->wantobjects) {
1754 res = FromObj(self, tres);
1755 }
1756 else {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001757 res = unicodeFromTclObj(tres);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001758 }
1759 }
1760 LEAVE_OVERLAP_TCL
1761 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001762}
1763
1764static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001765Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001766{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001767 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001768}
1769
1770static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001771Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001772{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001773 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001774}
1775
Barry Warsawfa701a81997-01-16 00:15:11 +00001776
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001777
Guido van Rossum18468821994-06-20 07:49:28 +00001778static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001779UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001780{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001781 char *name1, *name2=NULL;
1782 int code;
1783 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001784
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001785 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1786 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001787
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001788 ENTER_TCL
1789 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1790 ENTER_OVERLAP
1791 if (code == TCL_ERROR)
1792 res = Tkinter_Error(self);
1793 else {
1794 Py_INCREF(Py_None);
1795 res = Py_None;
1796 }
1797 LEAVE_OVERLAP_TCL
1798 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001799}
1800
1801static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001802Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001803{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001804 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001805}
1806
1807static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001808Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001809{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001810 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001811}
1812
Barry Warsawfa701a81997-01-16 00:15:11 +00001813
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001814
Guido van Rossum18468821994-06-20 07:49:28 +00001815/** Tcl to Python **/
1816
1817static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001818Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001819{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001820 char *s;
1821 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001822
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001823 if (PyTuple_Size(args) == 1) {
1824 PyObject* o = PyTuple_GetItem(args, 0);
1825 if (PyLong_Check(o)) {
1826 Py_INCREF(o);
1827 return o;
1828 }
1829 }
1830 if (!PyArg_ParseTuple(args, "s:getint", &s))
1831 return NULL;
1832 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1833 return Tkinter_Error(self);
1834 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001835}
1836
1837static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001838Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001839{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001840 char *s;
1841 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001842
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001843 if (PyTuple_Size(args) == 1) {
1844 PyObject *o = PyTuple_GetItem(args, 0);
1845 if (PyFloat_Check(o)) {
1846 Py_INCREF(o);
1847 return o;
1848 }
1849 }
1850 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1851 return NULL;
1852 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1853 return Tkinter_Error(self);
1854 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001855}
1856
1857static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001858Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001859{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001860 char *s;
1861 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001862
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001863 if (PyTuple_Size(args) == 1) {
1864 PyObject *o = PyTuple_GetItem(args, 0);
1865 if (PyLong_Check(o)) {
1866 Py_INCREF(o);
1867 return o;
1868 }
1869 }
1870 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1871 return NULL;
1872 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1873 return Tkinter_Error(self);
1874 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001875}
1876
1877static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001878Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001879{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001880 char *s;
1881 PyObject *res = NULL;
1882 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001883
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001884 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1885 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001886
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001887 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001888
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001889 ENTER_TCL
1890 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1891 ENTER_OVERLAP
1892 if (retval == TCL_ERROR)
1893 res = Tkinter_Error(self);
1894 else
Serhiy Storchaka1317e142014-02-03 21:24:07 +02001895 res = unicodeFromTclString(Tkapp_Result(self));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001896 LEAVE_OVERLAP_TCL
1897 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001898}
1899
1900static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001901Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001902{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001903 char *s;
1904 PyObject *res = NULL;
1905 int retval;
1906 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001907
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001908 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1909 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001910
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001911 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001912
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001913 ENTER_TCL
1914 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1915 ENTER_OVERLAP
1916 if (retval == TCL_ERROR)
1917 res = Tkinter_Error(self);
1918 else
1919 res = Py_BuildValue("l", v);
1920 LEAVE_OVERLAP_TCL
1921 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001922}
1923
1924static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001925Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001926{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001927 char *s;
1928 PyObject *res = NULL;
1929 double v;
1930 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001931
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001932 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1933 return NULL;
1934 CHECK_TCL_APPARTMENT;
1935 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1936 ENTER_TCL
1937 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1938 ENTER_OVERLAP
1939 PyFPE_END_PROTECT(retval)
1940 if (retval == TCL_ERROR)
1941 res = Tkinter_Error(self);
1942 else
1943 res = Py_BuildValue("d", v);
1944 LEAVE_OVERLAP_TCL
1945 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001946}
1947
1948static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001949Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001950{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001951 char *s;
1952 PyObject *res = NULL;
1953 int retval;
1954 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001955
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001956 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1957 return NULL;
1958 CHECK_TCL_APPARTMENT;
1959 ENTER_TCL
1960 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1961 ENTER_OVERLAP
1962 if (retval == TCL_ERROR)
1963 res = Tkinter_Error(self);
1964 else
1965 res = Py_BuildValue("i", v);
1966 LEAVE_OVERLAP_TCL
1967 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001968}
1969
Barry Warsawfa701a81997-01-16 00:15:11 +00001970
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001971
Guido van Rossum18468821994-06-20 07:49:28 +00001972static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001973Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001974{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001975 char *list;
1976 int argc;
1977 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001978 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001979 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001980
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001981 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1982 return NULL;
1983 if (PyTclObject_Check(arg)) {
1984 int objc;
1985 Tcl_Obj **objv;
1986 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1987 ((PyTclObject*)arg)->value,
1988 &objc, &objv) == TCL_ERROR) {
1989 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001990 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001991 if (!(v = PyTuple_New(objc)))
1992 return NULL;
1993 for (i = 0; i < objc; i++) {
1994 PyObject *s = FromObj(self, objv[i]);
1995 if (!s || PyTuple_SetItem(v, i, s)) {
1996 Py_DECREF(v);
1997 return NULL;
1998 }
1999 }
2000 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002001 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002002 if (PyTuple_Check(arg)) {
2003 Py_INCREF(arg);
2004 return arg;
2005 }
2006
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002007 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
2008 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002010 if (Tcl_SplitList(Tkapp_Interp(self), list,
2011 &argc, &argv) == TCL_ERROR) {
2012 PyMem_Free(list);
2013 return Tkinter_Error(self);
2014 }
Guido van Rossum18468821994-06-20 07:49:28 +00002015
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002016 if (!(v = PyTuple_New(argc)))
2017 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002018
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002019 for (i = 0; i < argc; i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002020 PyObject *s = unicodeFromTclString(argv[i]);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002021 if (!s || PyTuple_SetItem(v, i, s)) {
2022 Py_DECREF(v);
2023 v = NULL;
2024 goto finally;
2025 }
2026 }
Guido van Rossum18468821994-06-20 07:49:28 +00002027
Barry Warsawfa701a81997-01-16 00:15:11 +00002028 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002029 ckfree(FREECAST argv);
2030 PyMem_Free(list);
2031 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002032}
2033
2034static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002035Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002036{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002037 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002038 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00002039
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002040 if (!PyArg_ParseTuple(args, "O:split", &arg))
2041 return NULL;
2042 if (PyTclObject_Check(arg)) {
2043 Tcl_Obj *value = ((PyTclObject*)arg)->value;
2044 int objc;
2045 Tcl_Obj **objv;
2046 int i;
2047 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
2048 &objc, &objv) == TCL_ERROR) {
2049 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002050 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002051 if (objc == 0)
2052 return PyUnicode_FromString("");
2053 if (objc == 1)
2054 return FromObj(self, objv[0]);
2055 if (!(v = PyTuple_New(objc)))
2056 return NULL;
2057 for (i = 0; i < objc; i++) {
2058 PyObject *s = FromObj(self, objv[i]);
2059 if (!s || PyTuple_SetItem(v, i, s)) {
2060 Py_DECREF(v);
2061 return NULL;
2062 }
2063 }
2064 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002065 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002066 if (PyTuple_Check(arg))
2067 return SplitObj(arg);
2068
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002069 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2070 return NULL;
2071 v = Split(list);
2072 PyMem_Free(list);
2073 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002074}
2075
2076static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002077Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002078{
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03002079 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002080 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002081
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03002082 if (PyErr_WarnEx(PyExc_DeprecationWarning,
2083 "merge is deprecated and will be removed in 3.4",
2084 1) < 0)
2085 return 0;
2086
2087 s = Merge(args);
2088
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002089 if (s) {
2090 res = PyUnicode_FromString(s);
2091 ckfree(s);
2092 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002093
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002094 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002095}
2096
Barry Warsawfa701a81997-01-16 00:15:11 +00002097
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002098
Guido van Rossum18468821994-06-20 07:49:28 +00002099/** Tcl Command **/
2100
Guido van Rossum00d93061998-05-28 23:06:38 +00002101/* Client data struct */
2102typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002103 PyObject *self;
2104 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002105} PythonCmd_ClientData;
2106
2107static int
Fred Drake509d79a2000-07-08 04:04:38 +00002108PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002109{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002110 errorInCmd = 1;
2111 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2112 LEAVE_PYTHON
2113 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002114}
2115
Guido van Rossum18468821994-06-20 07:49:28 +00002116/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002117 * function or method.
2118 */
Guido van Rossum18468821994-06-20 07:49:28 +00002119static int
Fred Drake509d79a2000-07-08 04:04:38 +00002120PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002121{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002122 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002123 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002124 int i, rv;
2125 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002126
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002127 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002128
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002129 /* TBD: no error checking here since we know, via the
2130 * Tkapp_CreateCommand() that the client data is a two-tuple
2131 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002132 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002133
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002134 /* Create argument list (argv1, ..., argvN) */
2135 if (!(arg = PyTuple_New(argc - 1)))
2136 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002137
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 for (i = 0; i < (argc - 1); i++) {
Serhiy Storchaka1317e142014-02-03 21:24:07 +02002139 PyObject *s = unicodeFromTclString(argv[i + 1]);
2140 if (!s || PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002141 Py_DECREF(arg);
2142 return PythonCmd_Error(interp);
2143 }
2144 }
2145 res = PyEval_CallObject(func, arg);
2146 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002147
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002148 if (res == NULL)
2149 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002150
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002151 obj_res = AsObj(res);
2152 if (obj_res == NULL) {
2153 Py_DECREF(res);
2154 return PythonCmd_Error(interp);
2155 }
2156 else {
2157 Tcl_SetObjResult(interp, obj_res);
2158 rv = TCL_OK;
2159 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002160
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002161 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002162
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002163 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002164
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002165 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002166}
2167
2168static void
Fred Drake509d79a2000-07-08 04:04:38 +00002169PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002170{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002171 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002172
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002173 ENTER_PYTHON
2174 Py_XDECREF(data->self);
2175 Py_XDECREF(data->func);
2176 PyMem_DEL(data);
2177 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002178}
2179
Barry Warsawfa701a81997-01-16 00:15:11 +00002180
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002181
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002182
Benjamin Peterson5879d412009-03-30 14:51:56 +00002183#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002184TCL_DECLARE_MUTEX(command_mutex)
2185
2186typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002187 Tcl_Event ev;
2188 Tcl_Interp* interp;
2189 char *name;
2190 int create;
2191 int *status;
2192 ClientData *data;
2193 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002194} CommandEvent;
2195
2196static int
2197Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002198{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002199 if (ev->create)
2200 *ev->status = Tcl_CreateCommand(
2201 ev->interp, ev->name, PythonCmd,
2202 ev->data, PythonCmdDelete) == NULL;
2203 else
2204 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2205 Tcl_MutexLock(&command_mutex);
2206 Tcl_ConditionNotify(ev->done);
2207 Tcl_MutexUnlock(&command_mutex);
2208 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002209}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002210#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002211
2212static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002213Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002214{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002215 TkappObject *self = (TkappObject*)selfptr;
2216 PythonCmd_ClientData *data;
2217 char *cmdName;
2218 PyObject *func;
2219 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002221 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2222 return NULL;
2223 if (!PyCallable_Check(func)) {
2224 PyErr_SetString(PyExc_TypeError, "command not callable");
2225 return NULL;
2226 }
Guido van Rossum18468821994-06-20 07:49:28 +00002227
Martin v. Löwisa9656492003-03-30 08:44:58 +00002228#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002229 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2230 !WaitForMainloop(self))
2231 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002232#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002233
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002234 data = PyMem_NEW(PythonCmd_ClientData, 1);
2235 if (!data)
2236 return PyErr_NoMemory();
2237 Py_INCREF(self);
2238 Py_INCREF(func);
2239 data->self = selfptr;
2240 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002241#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002242 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2243 Tcl_Condition cond = NULL;
2244 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2245 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2246 ev->interp = self->interp;
2247 ev->create = 1;
2248 ev->name = cmdName;
2249 ev->data = (ClientData)data;
2250 ev->status = &err;
2251 ev->done = &cond;
2252 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2253 Tcl_ConditionFinalize(&cond);
2254 }
2255 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002256#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002257 {
2258 ENTER_TCL
2259 err = Tcl_CreateCommand(
2260 Tkapp_Interp(self), cmdName, PythonCmd,
2261 (ClientData)data, PythonCmdDelete) == NULL;
2262 LEAVE_TCL
2263 }
2264 if (err) {
2265 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2266 PyMem_DEL(data);
2267 return NULL;
2268 }
Guido van Rossum18468821994-06-20 07:49:28 +00002269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002270 Py_INCREF(Py_None);
2271 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002272}
2273
Barry Warsawfa701a81997-01-16 00:15:11 +00002274
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002275
Guido van Rossum18468821994-06-20 07:49:28 +00002276static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002277Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002278{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002279 TkappObject *self = (TkappObject*)selfptr;
2280 char *cmdName;
2281 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002282
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002283 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2284 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002285
2286#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002287 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2288 Tcl_Condition cond = NULL;
2289 CommandEvent *ev;
2290 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2291 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2292 ev->interp = self->interp;
2293 ev->create = 0;
2294 ev->name = cmdName;
2295 ev->status = &err;
2296 ev->done = &cond;
2297 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2298 &command_mutex);
2299 Tcl_ConditionFinalize(&cond);
2300 }
2301 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002302#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002303 {
2304 ENTER_TCL
2305 err = Tcl_DeleteCommand(self->interp, cmdName);
2306 LEAVE_TCL
2307 }
2308 if (err == -1) {
2309 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2310 return NULL;
2311 }
2312 Py_INCREF(Py_None);
2313 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002314}
2315
Barry Warsawfa701a81997-01-16 00:15:11 +00002316
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002317
Guido van Rossum00d93061998-05-28 23:06:38 +00002318#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002319/** File Handler **/
2320
Guido van Rossum00d93061998-05-28 23:06:38 +00002321typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002322 PyObject *func;
2323 PyObject *file;
2324 int id;
2325 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002326} FileHandler_ClientData;
2327
2328static FileHandler_ClientData *HeadFHCD;
2329
2330static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002331NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002332{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002333 FileHandler_ClientData *p;
2334 p = PyMem_NEW(FileHandler_ClientData, 1);
2335 if (p != NULL) {
2336 Py_XINCREF(func);
2337 Py_XINCREF(file);
2338 p->func = func;
2339 p->file = file;
2340 p->id = id;
2341 p->next = HeadFHCD;
2342 HeadFHCD = p;
2343 }
2344 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002345}
2346
2347static void
Fred Drake509d79a2000-07-08 04:04:38 +00002348DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002349{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002350 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002352 pp = &HeadFHCD;
2353 while ((p = *pp) != NULL) {
2354 if (p->id == id) {
2355 *pp = p->next;
2356 Py_XDECREF(p->func);
2357 Py_XDECREF(p->file);
2358 PyMem_DEL(p);
2359 }
2360 else
2361 pp = &p->next;
2362 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002363}
2364
Guido van Rossuma597dde1995-01-10 20:56:29 +00002365static void
Fred Drake509d79a2000-07-08 04:04:38 +00002366FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002367{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002368 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2369 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002370
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002371 ENTER_PYTHON
2372 func = data->func;
2373 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002374
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002375 arg = Py_BuildValue("(Oi)", file, (long) mask);
2376 res = PyEval_CallObject(func, arg);
2377 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002378
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002379 if (res == NULL) {
2380 errorInCmd = 1;
2381 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2382 }
2383 Py_XDECREF(res);
2384 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002385}
2386
Guido van Rossum18468821994-06-20 07:49:28 +00002387static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002388Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2389 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002390{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002391 FileHandler_ClientData *data;
2392 PyObject *file, *func;
2393 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002394
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002395 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2396 &file, &mask, &func))
2397 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002398
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002399 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002400
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002401 tfile = PyObject_AsFileDescriptor(file);
2402 if (tfile < 0)
2403 return NULL;
2404 if (!PyCallable_Check(func)) {
2405 PyErr_SetString(PyExc_TypeError, "bad argument list");
2406 return NULL;
2407 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002408
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002409 data = NewFHCD(func, file, tfile);
2410 if (data == NULL)
2411 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002413 /* Ought to check for null Tcl_File object... */
2414 ENTER_TCL
2415 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2416 LEAVE_TCL
2417 Py_INCREF(Py_None);
2418 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002419}
2420
2421static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002422Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002423{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002424 PyObject *file;
2425 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002426
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002427 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2428 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002429
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002430 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002431
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002432 tfile = PyObject_AsFileDescriptor(file);
2433 if (tfile < 0)
2434 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002435
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002436 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002438 /* Ought to check for null Tcl_File object... */
2439 ENTER_TCL
2440 Tcl_DeleteFileHandler(tfile);
2441 LEAVE_TCL
2442 Py_INCREF(Py_None);
2443 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002444}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002445#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002446
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002447
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002448/**** Tktt Object (timer token) ****/
2449
Jeremy Hylton938ace62002-07-17 16:30:39 +00002450static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002451
Guido van Rossum00d93061998-05-28 23:06:38 +00002452typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002453 PyObject_HEAD
2454 Tcl_TimerToken token;
2455 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002456} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002457
2458static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002459Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002460{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002461 TkttObject *v = (TkttObject *)self;
2462 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002463
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002464 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2465 return NULL;
2466 if (v->token != NULL) {
2467 Tcl_DeleteTimerHandler(v->token);
2468 v->token = NULL;
2469 }
2470 if (func != NULL) {
2471 v->func = NULL;
2472 Py_DECREF(func);
2473 Py_DECREF(v); /* See Tktt_New() */
2474 }
2475 Py_INCREF(Py_None);
2476 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002477}
2478
2479static PyMethodDef Tktt_methods[] =
2480{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002481 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2482 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002483};
2484
2485static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002486Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002487{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002488 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002489
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002490 v = PyObject_New(TkttObject, &Tktt_Type);
2491 if (v == NULL)
2492 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002493
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002494 Py_INCREF(func);
2495 v->token = NULL;
2496 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002497
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002498 /* Extra reference, deleted when called or when handler is deleted */
2499 Py_INCREF(v);
2500 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002501}
2502
2503static void
Fred Drake509d79a2000-07-08 04:04:38 +00002504Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002505{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002506 TkttObject *v = (TkttObject *)self;
2507 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002508
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002509 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002510
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002511 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002512}
2513
Guido van Rossum597ac201998-05-12 14:36:19 +00002514static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002515Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002516{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002517 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002518 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2519 v,
2520 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002521}
2522
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002523static PyTypeObject Tktt_Type =
2524{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002525 PyVarObject_HEAD_INIT(NULL, 0)
2526 "tktimertoken", /*tp_name */
2527 sizeof(TkttObject), /*tp_basicsize */
2528 0, /*tp_itemsize */
2529 Tktt_Dealloc, /*tp_dealloc */
2530 0, /*tp_print */
2531 0, /*tp_getattr */
2532 0, /*tp_setattr */
2533 0, /*tp_reserved */
2534 Tktt_Repr, /*tp_repr */
2535 0, /*tp_as_number */
2536 0, /*tp_as_sequence */
2537 0, /*tp_as_mapping */
2538 0, /*tp_hash */
2539 0, /*tp_call*/
2540 0, /*tp_str*/
2541 0, /*tp_getattro*/
2542 0, /*tp_setattro*/
2543 0, /*tp_as_buffer*/
2544 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2545 0, /*tp_doc*/
2546 0, /*tp_traverse*/
2547 0, /*tp_clear*/
2548 0, /*tp_richcompare*/
2549 0, /*tp_weaklistoffset*/
2550 0, /*tp_iter*/
2551 0, /*tp_iternext*/
2552 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002553};
2554
Barry Warsawfa701a81997-01-16 00:15:11 +00002555
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002556
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002557/** Timer Handler **/
2558
2559static void
Fred Drake509d79a2000-07-08 04:04:38 +00002560TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002561{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002562 TkttObject *v = (TkttObject *)clientData;
2563 PyObject *func = v->func;
2564 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002565
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002566 if (func == NULL)
2567 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002568
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002569 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002570
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002571 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002573 res = PyEval_CallObject(func, NULL);
2574 Py_DECREF(func);
2575 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002576
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002577 if (res == NULL) {
2578 errorInCmd = 1;
2579 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2580 }
2581 else
2582 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002583
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002584 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002585}
2586
2587static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002588Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002589{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002590 int milliseconds;
2591 PyObject *func;
2592 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002593
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002594 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2595 &milliseconds, &func))
2596 return NULL;
2597 if (!PyCallable_Check(func)) {
2598 PyErr_SetString(PyExc_TypeError, "bad argument list");
2599 return NULL;
2600 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002601
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002602 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002603
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002604 v = Tktt_New(func);
2605 if (v) {
2606 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2607 (ClientData)v);
2608 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002609
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002610 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002611}
2612
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002613
Guido van Rossum18468821994-06-20 07:49:28 +00002614/** Event Loop **/
2615
Guido van Rossum18468821994-06-20 07:49:28 +00002616static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002617Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002618{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002619 int threshold = 0;
2620 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002621#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002622 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002623#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002624
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002625 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2626 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002627
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002628 CHECK_TCL_APPARTMENT;
2629 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002630
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002631 quitMainLoop = 0;
2632 while (Tk_GetNumMainWindows() > threshold &&
2633 !quitMainLoop &&
2634 !errorInCmd)
2635 {
2636 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002637
2638#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002639 if (self->threaded) {
2640 /* Allow other Python threads to run. */
2641 ENTER_TCL
2642 result = Tcl_DoOneEvent(0);
2643 LEAVE_TCL
2644 }
2645 else {
2646 Py_BEGIN_ALLOW_THREADS
2647 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2648 tcl_tstate = tstate;
2649 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2650 tcl_tstate = NULL;
2651 if(tcl_lock)PyThread_release_lock(tcl_lock);
2652 if (result == 0)
2653 Sleep(Tkinter_busywaitinterval);
2654 Py_END_ALLOW_THREADS
2655 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002656#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002657 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002658#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002659
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002660 if (PyErr_CheckSignals() != 0) {
2661 self->dispatching = 0;
2662 return NULL;
2663 }
2664 if (result < 0)
2665 break;
2666 }
2667 self->dispatching = 0;
2668 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002669
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002670 if (errorInCmd) {
2671 errorInCmd = 0;
2672 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2673 excInCmd = valInCmd = trbInCmd = NULL;
2674 return NULL;
2675 }
2676 Py_INCREF(Py_None);
2677 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002678}
2679
2680static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002681Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002682{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002683 int flags = 0;
2684 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002685
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002686 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2687 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002688
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002689 ENTER_TCL
2690 rv = Tcl_DoOneEvent(flags);
2691 LEAVE_TCL
2692 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002693}
2694
2695static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002696Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002697{
2698
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002699 if (!PyArg_ParseTuple(args, ":quit"))
2700 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002701
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002702 quitMainLoop = 1;
2703 Py_INCREF(Py_None);
2704 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002705}
2706
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002707static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002708Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002709{
2710
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002711 if (!PyArg_ParseTuple(args, ":interpaddr"))
2712 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002713
Victor Stinnere1040e22013-09-05 00:22:24 +02002714 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002715}
2716
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002717static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002718Tkapp_TkInit(PyObject *self, PyObject *args)
2719{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002720 Tcl_Interp *interp = Tkapp_Interp(self);
2721 const char * _tk_exists = NULL;
2722 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002723
Guilherme Polob681df42009-02-09 22:33:59 +00002724#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002725 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2726 * first call failed.
2727 * To avoid the deadlock, we just refuse the second call through
2728 * a static variable.
2729 */
2730 if (tk_load_failed) {
2731 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2732 return NULL;
2733 }
Guilherme Polob681df42009-02-09 22:33:59 +00002734#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002735
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002736 /* We want to guard against calling Tk_Init() multiple times */
2737 CHECK_TCL_APPARTMENT;
2738 ENTER_TCL
2739 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2740 ENTER_OVERLAP
2741 if (err == TCL_ERROR) {
2742 /* This sets an exception, but we cannot return right
2743 away because we need to exit the overlap first. */
2744 Tkinter_Error(self);
2745 } else {
2746 _tk_exists = Tkapp_Result(self);
2747 }
2748 LEAVE_OVERLAP_TCL
2749 if (err == TCL_ERROR) {
2750 return NULL;
2751 }
2752 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2753 if (Tk_Init(interp) == TCL_ERROR) {
2754 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002755#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002756 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002757#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002758 return NULL;
2759 }
2760 }
2761 Py_INCREF(Py_None);
2762 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002763}
Barry Warsawfa701a81997-01-16 00:15:11 +00002764
Martin v. Löwisffad6332002-11-26 09:28:05 +00002765static PyObject *
2766Tkapp_WantObjects(PyObject *self, PyObject *args)
2767{
2768
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002769 int wantobjects = -1;
2770 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2771 return NULL;
2772 if (wantobjects == -1)
2773 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2774 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002775
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002776 Py_INCREF(Py_None);
2777 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002778}
2779
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002780static PyObject *
2781Tkapp_WillDispatch(PyObject *self, PyObject *args)
2782{
2783
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002784 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002785
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002786 Py_INCREF(Py_None);
2787 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002788}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002789
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002790
Guido van Rossum18468821994-06-20 07:49:28 +00002791/**** Tkapp Method List ****/
2792
2793static PyMethodDef Tkapp_methods[] =
2794{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002795 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2796 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2797 {"call", Tkapp_Call, METH_VARARGS},
2798 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2799 {"eval", Tkapp_Eval, METH_VARARGS},
2800 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2801 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2802 {"record", Tkapp_Record, METH_VARARGS},
2803 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2804 {"setvar", Tkapp_SetVar, METH_VARARGS},
2805 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2806 {"getvar", Tkapp_GetVar, METH_VARARGS},
2807 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2808 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2809 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2810 {"getint", Tkapp_GetInt, METH_VARARGS},
2811 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2812 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2813 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2814 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2815 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2816 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2817 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2818 {"split", Tkapp_Split, METH_VARARGS},
2819 {"merge", Tkapp_Merge, METH_VARARGS},
2820 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2821 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002822#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002823 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2824 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002825#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002826 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2827 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2828 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2829 {"quit", Tkapp_Quit, METH_VARARGS},
2830 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2831 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2832 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002833};
2834
Barry Warsawfa701a81997-01-16 00:15:11 +00002835
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002836
Guido van Rossum18468821994-06-20 07:49:28 +00002837/**** Tkapp Type Methods ****/
2838
2839static void
Fred Drake509d79a2000-07-08 04:04:38 +00002840Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002841{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002842 /*CHECK_TCL_APPARTMENT;*/
2843 ENTER_TCL
2844 Tcl_DeleteInterp(Tkapp_Interp(self));
2845 LEAVE_TCL
2846 PyObject_Del(self);
2847 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002848}
2849
Guido van Rossum18468821994-06-20 07:49:28 +00002850static PyTypeObject Tkapp_Type =
2851{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002852 PyVarObject_HEAD_INIT(NULL, 0)
2853 "tkapp", /*tp_name */
2854 sizeof(TkappObject), /*tp_basicsize */
2855 0, /*tp_itemsize */
2856 Tkapp_Dealloc, /*tp_dealloc */
2857 0, /*tp_print */
2858 0, /*tp_getattr */
2859 0, /*tp_setattr */
2860 0, /*tp_reserved */
2861 0, /*tp_repr */
2862 0, /*tp_as_number */
2863 0, /*tp_as_sequence */
2864 0, /*tp_as_mapping */
2865 0, /*tp_hash */
2866 0, /*tp_call*/
2867 0, /*tp_str*/
2868 0, /*tp_getattro*/
2869 0, /*tp_setattro*/
2870 0, /*tp_as_buffer*/
2871 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2872 0, /*tp_doc*/
2873 0, /*tp_traverse*/
2874 0, /*tp_clear*/
2875 0, /*tp_richcompare*/
2876 0, /*tp_weaklistoffset*/
2877 0, /*tp_iter*/
2878 0, /*tp_iternext*/
2879 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002880};
2881
Barry Warsawfa701a81997-01-16 00:15:11 +00002882
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002883
Guido van Rossum18468821994-06-20 07:49:28 +00002884/**** Tkinter Module ****/
2885
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002886typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002887 PyObject* tuple;
2888 int size; /* current size */
2889 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002890} FlattenContext;
2891
2892static int
2893_bump(FlattenContext* context, int size)
2894{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002895 /* expand tuple to hold (at least) size new items.
2896 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002897
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002898 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002899
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002900 if (maxsize < context->size + size)
2901 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002902
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002903 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002904
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002905 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002906}
2907
2908static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002909_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002910{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002911 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002912
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002913 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002914
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002915 if (depth > 1000) {
2916 PyErr_SetString(PyExc_ValueError,
2917 "nesting too deep in _flatten");
2918 return 0;
2919 } else if (PyList_Check(item)) {
2920 size = PyList_GET_SIZE(item);
2921 /* preallocate (assume no nesting) */
2922 if (context->size + size > context->maxsize &&
2923 !_bump(context, size))
2924 return 0;
2925 /* copy items to output tuple */
2926 for (i = 0; i < size; i++) {
2927 PyObject *o = PyList_GET_ITEM(item, i);
2928 if (PyList_Check(o) || PyTuple_Check(o)) {
2929 if (!_flatten1(context, o, depth + 1))
2930 return 0;
2931 } else if (o != Py_None) {
2932 if (context->size + 1 > context->maxsize &&
2933 !_bump(context, 1))
2934 return 0;
2935 Py_INCREF(o);
2936 PyTuple_SET_ITEM(context->tuple,
2937 context->size++, o);
2938 }
2939 }
2940 } else if (PyTuple_Check(item)) {
2941 /* same, for tuples */
2942 size = PyTuple_GET_SIZE(item);
2943 if (context->size + size > context->maxsize &&
2944 !_bump(context, size))
2945 return 0;
2946 for (i = 0; i < size; i++) {
2947 PyObject *o = PyTuple_GET_ITEM(item, i);
2948 if (PyList_Check(o) || PyTuple_Check(o)) {
2949 if (!_flatten1(context, o, depth + 1))
2950 return 0;
2951 } else if (o != Py_None) {
2952 if (context->size + 1 > context->maxsize &&
2953 !_bump(context, 1))
2954 return 0;
2955 Py_INCREF(o);
2956 PyTuple_SET_ITEM(context->tuple,
2957 context->size++, o);
2958 }
2959 }
2960 } else {
2961 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2962 return 0;
2963 }
2964 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002965}
2966
2967static PyObject *
2968Tkinter_Flatten(PyObject* self, PyObject* args)
2969{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002970 FlattenContext context;
2971 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002972
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002973 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2974 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002975
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002976 context.maxsize = PySequence_Size(item);
2977 if (context.maxsize < 0)
2978 return NULL;
2979 if (context.maxsize == 0)
2980 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002981
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002982 context.tuple = PyTuple_New(context.maxsize);
2983 if (!context.tuple)
2984 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002985
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002986 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002987
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002988 if (!_flatten1(&context, item,0))
2989 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002990
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002991 if (_PyTuple_Resize(&context.tuple, context.size))
2992 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002993
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002994 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002995}
2996
Guido van Rossum18468821994-06-20 07:49:28 +00002997static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002998Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002999{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003000 char *screenName = NULL;
3001 char *baseName = NULL; /* XXX this is not used anymore;
3002 try getting rid of it. */
3003 char *className = NULL;
3004 int interactive = 0;
3005 int wantobjects = 0;
3006 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
3007 int sync = 0; /* pass -sync to wish */
3008 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00003009
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003010 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00003011
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003012 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
3013 &screenName, &baseName, &className,
3014 &interactive, &wantobjects, &wantTk,
3015 &sync, &use))
3016 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003017
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003018 return (PyObject *) Tkapp_New(screenName, className,
3019 interactive, wantobjects, wantTk,
3020 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00003021}
3022
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003023static PyObject *
3024Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
3025{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003026 int new_val;
3027 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
3028 return NULL;
3029 if (new_val < 0) {
3030 PyErr_SetString(PyExc_ValueError,
3031 "busywaitinterval must be >= 0");
3032 return NULL;
3033 }
3034 Tkinter_busywaitinterval = new_val;
3035 Py_INCREF(Py_None);
3036 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003037}
3038
3039static char setbusywaitinterval_doc[] =
3040"setbusywaitinterval(n) -> None\n\
3041\n\
3042Set the busy-wait interval in milliseconds between successive\n\
3043calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
3044It should be set to a divisor of the maximum time between\n\
3045frames in an animation.";
3046
3047static PyObject *
3048Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3049{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003050 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003051}
3052
3053static char getbusywaitinterval_doc[] =
3054"getbusywaitinterval() -> int\n\
3055\n\
3056Return the current busy-wait interval between successive\n\
3057calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3058
Guido van Rossum18468821994-06-20 07:49:28 +00003059static PyMethodDef moduleMethods[] =
3060{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003061 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3062 {"create", Tkinter_Create, METH_VARARGS},
3063 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3064 setbusywaitinterval_doc},
3065 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3066 METH_NOARGS, getbusywaitinterval_doc},
3067 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003068};
3069
Guido van Rossum7bf15641998-05-22 18:28:17 +00003070#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003071
3072static int stdin_ready = 0;
3073
Guido van Rossumad4db171998-06-13 13:56:28 +00003074#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003075static void
Fred Drake509d79a2000-07-08 04:04:38 +00003076MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003077{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003078 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003079}
Guido van Rossumad4db171998-06-13 13:56:28 +00003080#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003081
Martin v. Löwisa9656492003-03-30 08:44:58 +00003082#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003083static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003084#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003085
Guido van Rossum18468821994-06-20 07:49:28 +00003086static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003087EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003088{
Guido van Rossumad4db171998-06-13 13:56:28 +00003089#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003090 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003091#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003092#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003093 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003094#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003095 stdin_ready = 0;
3096 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003097#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003098 tfile = fileno(stdin);
3099 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003100#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003101 while (!errorInCmd && !stdin_ready) {
3102 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003103#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003104 if (_kbhit()) {
3105 stdin_ready = 1;
3106 break;
3107 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003108#endif
3109#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003110 Py_BEGIN_ALLOW_THREADS
3111 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3112 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003114 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003115
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003116 tcl_tstate = NULL;
3117 if(tcl_lock)PyThread_release_lock(tcl_lock);
3118 if (result == 0)
3119 Sleep(Tkinter_busywaitinterval);
3120 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003121#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003122 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003123#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003124
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003125 if (result < 0)
3126 break;
3127 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003128#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003129 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003130#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003131 if (errorInCmd) {
3132 errorInCmd = 0;
3133 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3134 excInCmd = valInCmd = trbInCmd = NULL;
3135 PyErr_Print();
3136 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003137#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003138 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003139#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003140 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003141}
Guido van Rossum18468821994-06-20 07:49:28 +00003142
Guido van Rossum00d93061998-05-28 23:06:38 +00003143#endif
3144
Guido van Rossum7bf15641998-05-22 18:28:17 +00003145static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003146EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003147{
Guido van Rossum00d93061998-05-28 23:06:38 +00003148#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003149 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003150#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003151 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003152#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003153 PyOS_InputHook = EventHook;
3154 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003155#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003156}
3157
3158static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003159DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003160{
Guido van Rossum00d93061998-05-28 23:06:38 +00003161#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003162 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3163 PyOS_InputHook = NULL;
3164 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003165#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003166}
3167
Barry Warsawfa701a81997-01-16 00:15:11 +00003168
3169/* all errors will be checked in one fell swoop in init_tkinter() */
3170static void
Fred Drake509d79a2000-07-08 04:04:38 +00003171ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003172{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003173 PyObject *v = PyLong_FromLong(val);
3174 if (v) {
3175 PyDict_SetItemString(d, name, v);
3176 Py_DECREF(v);
3177 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003178}
3179static void
Fred Drake509d79a2000-07-08 04:04:38 +00003180ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003181{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003182 PyObject *v = PyUnicode_FromString(val);
3183 if (v) {
3184 PyDict_SetItemString(d, name, v);
3185 Py_DECREF(v);
3186 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003187}
3188
3189
Martin v. Löwis1a214512008-06-11 05:26:20 +00003190static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003191 PyModuleDef_HEAD_INIT,
3192 "_tkinter",
3193 NULL,
3194 -1,
3195 moduleMethods,
3196 NULL,
3197 NULL,
3198 NULL,
3199 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003200};
3201
Mark Hammond62b1ab12002-07-23 06:31:15 +00003202PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003203PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003204{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003205 PyObject *m, *d, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00003206
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003207 if (PyType_Ready(&Tkapp_Type) < 0)
3208 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003209
3210#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003211 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003212#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003213
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003214 m = PyModule_Create(&_tkintermodule);
3215 if (m == NULL)
3216 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003217
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003218 d = PyModule_GetDict(m);
3219 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3220 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003221
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003222 ins_long(d, "READABLE", TCL_READABLE);
3223 ins_long(d, "WRITABLE", TCL_WRITABLE);
3224 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3225 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3226 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3227 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3228 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3229 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3230 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3231 ins_string(d, "TK_VERSION", TK_VERSION);
3232 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003233
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003234 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003235
Jesus Ceaef86d122012-07-19 21:18:07 +02003236 if (PyType_Ready(&Tktt_Type) < 0) {
3237 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003238 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003239 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003240 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003241
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003242 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3243 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003244
3245#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003246 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3247 * start waking up. Note that Tcl_FindExecutable will do this, this
3248 * code must be above it! The original warning from
3249 * tkMacOSXAppInit.c is copied below.
3250 *
3251 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3252 * Tcl interpreter for now. It probably should work to do this
3253 * in the other order, but for now it doesn't seem to.
3254 *
3255 */
3256 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003257#endif
3258
3259
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003260 /* This helps the dynamic loader; in Unicode aware Tcl versions
3261 it also helps Tcl find its encodings. */
3262 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3263 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003264 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003265 if (cexe)
3266 Tcl_FindExecutable(PyBytes_AsString(cexe));
3267 Py_XDECREF(cexe);
3268 Py_DECREF(uexe);
3269 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003270
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003271 if (PyErr_Occurred()) {
3272 Py_DECREF(m);
3273 return NULL;
3274 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003275
Guido van Rossum43ff8681998-07-14 18:02:13 +00003276#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003277 /* This was not a good idea; through <Destroy> bindings,
3278 Tcl_Finalize() may invoke Python code but at that point the
3279 interpreter and thread state have already been destroyed! */
3280 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003281#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003282 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003283}