blob: 6bf0b69164269c815e3321654c5ed00a6f2226f6 [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 *
Fred Drake509d79a2000-07-08 04:04:38 +0000422Split(char *list)
Guido van Rossum18468821994-06-20 07:49:28 +0000423{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000424 int argc;
425 char **argv;
426 PyObject *v;
Guido van Rossum18468821994-06-20 07:49:28 +0000427
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000428 if (list == NULL) {
429 Py_INCREF(Py_None);
430 return Py_None;
431 }
Guido van Rossum18468821994-06-20 07:49:28 +0000432
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000433 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
434 /* Not a list.
435 * Could be a quoted string containing funnies, e.g. {"}.
436 * Return the string itself.
437 */
438 return PyUnicode_FromString(list);
439 }
Guido van Rossum18468821994-06-20 07:49:28 +0000440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000441 if (argc == 0)
442 v = PyUnicode_FromString("");
443 else if (argc == 1)
444 v = PyUnicode_FromString(argv[0]);
445 else if ((v = PyTuple_New(argc)) != NULL) {
446 int i;
447 PyObject *w;
Guido van Rossum18468821994-06-20 07:49:28 +0000448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000449 for (i = 0; i < argc; i++) {
450 if ((w = Split(argv[i])) == NULL) {
451 Py_DECREF(v);
452 v = NULL;
453 break;
454 }
455 PyTuple_SetItem(v, i, w);
456 }
457 }
458 Tcl_Free(FREECAST argv);
459 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000460}
461
Martin v. Löwisffad6332002-11-26 09:28:05 +0000462/* In some cases, Tcl will still return strings that are supposed to be
463 lists. SplitObj walks through a nested tuple, finding string objects that
464 need to be split. */
465
Martin v. Löwis59683e82008-06-13 07:50:45 +0000466static PyObject *
Martin v. Löwisffad6332002-11-26 09:28:05 +0000467SplitObj(PyObject *arg)
468{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000469 if (PyTuple_Check(arg)) {
470 int i, size;
471 PyObject *elem, *newelem, *result;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000472
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000473 size = PyTuple_Size(arg);
474 result = NULL;
475 /* Recursively invoke SplitObj for all tuple items.
476 If this does not return a new object, no action is
477 needed. */
478 for(i = 0; i < size; i++) {
479 elem = PyTuple_GetItem(arg, i);
480 newelem = SplitObj(elem);
481 if (!newelem) {
482 Py_XDECREF(result);
483 return NULL;
484 }
485 if (!result) {
486 int k;
487 if (newelem == elem) {
488 Py_DECREF(newelem);
489 continue;
490 }
491 result = PyTuple_New(size);
492 if (!result)
493 return NULL;
494 for(k = 0; k < i; k++) {
495 elem = PyTuple_GetItem(arg, k);
496 Py_INCREF(elem);
497 PyTuple_SetItem(result, k, elem);
498 }
499 }
500 PyTuple_SetItem(result, i, newelem);
501 }
502 if (result)
503 return result;
504 /* Fall through, returning arg. */
505 }
Serhiy Storchaka275d5fd2013-07-11 20:34:47 +0300506 else if (PyUnicode_Check(arg)) {
507 int argc;
508 char **argv;
509 char *list = PyUnicode_AsUTF8(arg);
510
511 if (list == NULL ||
512 Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
513 Py_INCREF(arg);
514 return arg;
515 }
516 Tcl_Free(FREECAST argv);
517 if (argc > 1)
518 return Split(list);
519 /* Fall through, returning arg. */
520 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000521 else if (PyBytes_Check(arg)) {
522 int argc;
523 char **argv;
524 char *list = PyBytes_AsString(arg);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000525
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000526 if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) {
527 Py_INCREF(arg);
528 return arg;
529 }
530 Tcl_Free(FREECAST argv);
531 if (argc > 1)
532 return Split(PyBytes_AsString(arg));
533 /* Fall through, returning arg. */
534 }
535 Py_INCREF(arg);
536 return arg;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000537}
Barry Warsawfa701a81997-01-16 00:15:11 +0000538
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000539
Guido van Rossum18468821994-06-20 07:49:28 +0000540/**** Tkapp Object ****/
541
542#ifndef WITH_APPINIT
543int
Fred Drake509d79a2000-07-08 04:04:38 +0000544Tcl_AppInit(Tcl_Interp *interp)
Guido van Rossum18468821994-06-20 07:49:28 +0000545{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000546 const char * _tkinter_skip_tk_init;
Guido van Rossumec22c921996-02-25 04:50:29 +0000547
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000548 if (Tcl_Init(interp) == TCL_ERROR) {
549 PySys_WriteStderr("Tcl_Init error: %s\n", Tcl_GetStringResult(interp));
550 return TCL_ERROR;
551 }
Guilherme Polob681df42009-02-09 22:33:59 +0000552
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000553 _tkinter_skip_tk_init = Tcl_GetVar(interp,
554 "_tkinter_skip_tk_init", TCL_GLOBAL_ONLY);
555 if (_tkinter_skip_tk_init != NULL &&
556 strcmp(_tkinter_skip_tk_init, "1") == 0) {
557 return TCL_OK;
558 }
Guilherme Polob681df42009-02-09 22:33:59 +0000559
560#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000561 if (tk_load_failed) {
562 PySys_WriteStderr("Tk_Init error: %s\n", TKINTER_LOADTK_ERRMSG);
563 return TCL_ERROR;
564 }
Guilherme Polob681df42009-02-09 22:33:59 +0000565#endif
566
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 if (Tk_Init(interp) == TCL_ERROR) {
Guilherme Polob681df42009-02-09 22:33:59 +0000568#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000569 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +0000570#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 PySys_WriteStderr("Tk_Init error: %s\n", Tcl_GetStringResult(interp));
572 return TCL_ERROR;
573 }
Guilherme Polob681df42009-02-09 22:33:59 +0000574
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 return TCL_OK;
Guido van Rossum18468821994-06-20 07:49:28 +0000576}
577#endif /* !WITH_APPINIT */
578
Guido van Rossum18468821994-06-20 07:49:28 +0000579
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000580
Barry Warsawfa701a81997-01-16 00:15:11 +0000581
582/* Initialize the Tk application; see the `main' function in
583 * `tkMain.c'.
584 */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000585
Thomas Wouters58d05102000-07-24 14:43:35 +0000586static void EnableEventHook(void); /* Forward */
587static void DisableEventHook(void); /* Forward */
Guido van Rossum7bf15641998-05-22 18:28:17 +0000588
Barry Warsawfa701a81997-01-16 00:15:11 +0000589static TkappObject *
Martin v. Löwisb9279bc2008-04-05 19:47:23 +0000590Tkapp_New(char *screenName, char *className,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000591 int interactive, int wantobjects, int wantTk, int sync, char *use)
Barry Warsawfa701a81997-01-16 00:15:11 +0000592{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000593 TkappObject *v;
594 char *argv0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000595
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000596 v = PyObject_New(TkappObject, &Tkapp_Type);
597 if (v == NULL)
598 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +0000599
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000600 v->interp = Tcl_CreateInterp();
601 v->wantobjects = wantobjects;
602 v->threaded = Tcl_GetVar2Ex(v->interp, "tcl_platform", "threaded",
603 TCL_GLOBAL_ONLY) != NULL;
604 v->thread_id = Tcl_GetCurrentThread();
605 v->dispatching = 0;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000606
607#ifndef TCL_THREADS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000608 if (v->threaded) {
609 PyErr_SetString(PyExc_RuntimeError, "Tcl is threaded but _tkinter is not");
610 Py_DECREF(v);
611 return 0;
612 }
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000613#endif
Martin v. Löwisa9656492003-03-30 08:44:58 +0000614#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000615 if (v->threaded && tcl_lock) {
616 /* If Tcl is threaded, we don't need the lock. */
617 PyThread_free_lock(tcl_lock);
618 tcl_lock = NULL;
619 }
Martin v. Löwisa9656492003-03-30 08:44:58 +0000620#endif
Guido van Rossumdfd428d1996-02-25 04:46:40 +0000621
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000622 v->BooleanType = Tcl_GetObjType("boolean");
623 v->ByteArrayType = Tcl_GetObjType("bytearray");
624 v->DoubleType = Tcl_GetObjType("double");
625 v->IntType = Tcl_GetObjType("int");
626 v->ListType = Tcl_GetObjType("list");
627 v->ProcBodyType = Tcl_GetObjType("procbody");
628 v->StringType = Tcl_GetObjType("string");
Martin v. Löwis4ec2e702002-11-26 22:12:12 +0000629
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000630 /* Delete the 'exit' command, which can screw things up */
631 Tcl_DeleteCommand(v->interp, "exit");
Guido van Rossum1c0d3151998-02-19 21:28:49 +0000632
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000633 if (screenName != NULL)
634 Tcl_SetVar2(v->interp, "env", "DISPLAY",
635 screenName, TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000637 if (interactive)
638 Tcl_SetVar(v->interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY);
639 else
640 Tcl_SetVar(v->interp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +0000641
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000642 /* This is used to get the application class for Tk 4.1 and up */
643 argv0 = (char*)ckalloc(strlen(className) + 1);
644 if (!argv0) {
645 PyErr_NoMemory();
646 Py_DECREF(v);
647 return NULL;
648 }
Guido van Rossum97867b21996-08-08 19:09:53 +0000649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000650 strcpy(argv0, className);
Antoine Pitroued8ba142011-10-04 13:50:21 +0200651 if (Py_ISUPPER(Py_CHARMASK(argv0[0])))
652 argv0[0] = Py_TOLOWER(Py_CHARMASK(argv0[0]));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000653 Tcl_SetVar(v->interp, "argv0", argv0, TCL_GLOBAL_ONLY);
654 ckfree(argv0);
Guido van Rossum18468821994-06-20 07:49:28 +0000655
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000656 if (! wantTk) {
657 Tcl_SetVar(v->interp,
658 "_tkinter_skip_tk_init", "1", TCL_GLOBAL_ONLY);
659 }
Guilherme Polob681df42009-02-09 22:33:59 +0000660#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000661 else if (tk_load_failed) {
662 Tcl_SetVar(v->interp,
663 "_tkinter_tk_failed", "1", TCL_GLOBAL_ONLY);
664 }
Guilherme Polob681df42009-02-09 22:33:59 +0000665#endif
David Aschere2b4b322004-02-18 05:59:53 +0000666
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000667 /* some initial arguments need to be in argv */
668 if (sync || use) {
669 char *args;
670 int len = 0;
Tim Peters51fa3b72004-08-04 02:16:48 +0000671
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000672 if (sync)
673 len += sizeof "-sync";
674 if (use)
675 len += strlen(use) + sizeof "-use ";
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000676
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000677 args = (char*)ckalloc(len);
678 if (!args) {
679 PyErr_NoMemory();
680 Py_DECREF(v);
681 return NULL;
682 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000683
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000684 args[0] = '\0';
685 if (sync)
686 strcat(args, "-sync");
687 if (use) {
688 if (sync)
689 strcat(args, " ");
690 strcat(args, "-use ");
691 strcat(args, use);
692 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000693
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000694 Tcl_SetVar(v->interp, "argv", args, TCL_GLOBAL_ONLY);
695 ckfree(args);
696 }
Martin v. Löwis1fa649f2004-08-03 18:45:31 +0000697
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000698 if (Tcl_AppInit(v->interp) != TCL_OK) {
699 PyObject *result = Tkinter_Error((PyObject *)v);
Guilherme Polob681df42009-02-09 22:33:59 +0000700#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000701 if (wantTk) {
702 const char *_tkinter_tk_failed;
703 _tkinter_tk_failed = Tcl_GetVar(v->interp,
704 "_tkinter_tk_failed", TCL_GLOBAL_ONLY);
Guilherme Polob681df42009-02-09 22:33:59 +0000705
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000706 if ( _tkinter_tk_failed != NULL &&
707 strcmp(_tkinter_tk_failed, "1") == 0) {
708 tk_load_failed = 1;
709 }
710 }
Guilherme Polob681df42009-02-09 22:33:59 +0000711#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000712 Py_DECREF((PyObject *)v);
713 return (TkappObject *)result;
714 }
Barry Warsawfa701a81997-01-16 00:15:11 +0000715
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000716 EnableEventHook();
Guido van Rossum7bf15641998-05-22 18:28:17 +0000717
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000718 return v;
Guido van Rossum18468821994-06-20 07:49:28 +0000719}
720
Barry Warsawfa701a81997-01-16 00:15:11 +0000721
Benjamin Peterson5879d412009-03-30 14:51:56 +0000722#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000723static void
724Tkapp_ThreadSend(TkappObject *self, Tcl_Event *ev,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000725 Tcl_Condition *cond, Tcl_Mutex *mutex)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000726{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000727 Py_BEGIN_ALLOW_THREADS;
728 Tcl_MutexLock(mutex);
729 Tcl_ThreadQueueEvent(self->thread_id, ev, TCL_QUEUE_TAIL);
730 Tcl_ThreadAlert(self->thread_id);
731 Tcl_ConditionWait(cond, mutex, NULL);
732 Tcl_MutexUnlock(mutex);
733 Py_END_ALLOW_THREADS
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000734}
Benjamin Peterson5879d412009-03-30 14:51:56 +0000735#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +0000736
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000737
Guido van Rossum18468821994-06-20 07:49:28 +0000738/** Tcl Eval **/
739
Martin v. Löwisffad6332002-11-26 09:28:05 +0000740typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000741 PyObject_HEAD
742 Tcl_Obj *value;
743 PyObject *string; /* This cannot cause cycles. */
Martin v. Löwisffad6332002-11-26 09:28:05 +0000744} PyTclObject;
745
Neal Norwitz227b5332006-03-22 09:28:35 +0000746static PyTypeObject PyTclObject_Type;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000747#define PyTclObject_Check(v) ((v)->ob_type == &PyTclObject_Type)
Martin v. Löwisffad6332002-11-26 09:28:05 +0000748
749static PyObject *
750newPyTclObject(Tcl_Obj *arg)
751{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000752 PyTclObject *self;
753 self = PyObject_New(PyTclObject, &PyTclObject_Type);
754 if (self == NULL)
755 return NULL;
756 Tcl_IncrRefCount(arg);
757 self->value = arg;
758 self->string = NULL;
759 return (PyObject*)self;
Martin v. Löwisffad6332002-11-26 09:28:05 +0000760}
761
762static void
763PyTclObject_dealloc(PyTclObject *self)
764{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000765 Tcl_DecrRefCount(self->value);
766 Py_XDECREF(self->string);
767 PyObject_Del(self);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000768}
769
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000770static char*
771PyTclObject_TclString(PyObject *self)
772{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000773 return Tcl_GetString(((PyTclObject*)self)->value);
Martin v. Löwis1869ec52003-05-01 05:47:00 +0000774}
775
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000776/* Like _str, but create Unicode if necessary. */
Guido van Rossum82c0dfa2007-11-21 20:09:18 +0000777PyDoc_STRVAR(PyTclObject_string__doc__,
Christian Heimesb2b62622007-11-22 05:56:35 +0000778"the string representation of this object, either as str or bytes");
Martin v. Löwis39195712003-01-04 00:33:13 +0000779
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000780static PyObject *
781PyTclObject_string(PyTclObject *self, void *ignored)
782{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000783 char *s;
784 int len;
785 if (!self->string) {
786 s = Tcl_GetStringFromObj(self->value, &len);
787 self->string = PyUnicode_FromStringAndSize(s, len);
788 if (!self->string)
789 return NULL;
790 }
791 Py_INCREF(self->string);
792 return self->string;
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000793}
794
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000795static PyObject *
Walter Dörwald6720d912007-07-12 12:12:25 +0000796PyTclObject_str(PyTclObject *self, void *ignored)
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000797{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000798 char *s;
799 int len;
800 if (self->string && PyUnicode_Check(self->string)) {
801 Py_INCREF(self->string);
802 return self->string;
803 }
804 /* XXX Could chache result if it is non-ASCII. */
805 s = Tcl_GetStringFromObj(self->value, &len);
806 return PyUnicode_DecodeUTF8(s, len, "strict");
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000807}
Martin v. Löwis25c7b502003-01-04 00:08:09 +0000808
Martin v. Löwisffad6332002-11-26 09:28:05 +0000809static PyObject *
810PyTclObject_repr(PyTclObject *self)
811{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000812 return PyUnicode_FromFormat("<%s object at %p>",
813 self->value->typePtr->name, self->value);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000814}
815
Mark Dickinson211c6252009-02-01 10:28:51 +0000816#define TEST_COND(cond) ((cond) ? Py_True : Py_False)
817
818static PyObject *
819PyTclObject_richcompare(PyObject *self, PyObject *other, int op)
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000820{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000821 int result;
822 PyObject *v;
Mark Dickinson211c6252009-02-01 10:28:51 +0000823
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000824 /* neither argument should be NULL, unless something's gone wrong */
825 if (self == NULL || other == NULL) {
826 PyErr_BadInternalCall();
827 return NULL;
828 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000829
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000830 /* both arguments should be instances of PyTclObject */
831 if (!PyTclObject_Check(self) || !PyTclObject_Check(other)) {
832 v = Py_NotImplemented;
833 goto finished;
834 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000835
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000836 if (self == other)
837 /* fast path when self and other are identical */
838 result = 0;
839 else
840 result = strcmp(Tcl_GetString(((PyTclObject *)self)->value),
841 Tcl_GetString(((PyTclObject *)other)->value));
842 /* Convert return value to a Boolean */
843 switch (op) {
844 case Py_EQ:
845 v = TEST_COND(result == 0);
846 break;
847 case Py_NE:
848 v = TEST_COND(result != 0);
849 break;
850 case Py_LE:
851 v = TEST_COND(result <= 0);
852 break;
853 case Py_GE:
854 v = TEST_COND(result >= 0);
855 break;
856 case Py_LT:
857 v = TEST_COND(result < 0);
858 break;
859 case Py_GT:
860 v = TEST_COND(result > 0);
861 break;
862 default:
863 PyErr_BadArgument();
864 return NULL;
865 }
Mark Dickinson211c6252009-02-01 10:28:51 +0000866 finished:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000867 Py_INCREF(v);
868 return v;
Martin v. Löwisdd6cd652003-05-03 09:45:12 +0000869}
870
Martin v. Löwis39195712003-01-04 00:33:13 +0000871PyDoc_STRVAR(get_typename__doc__, "name of the Tcl type");
872
Martin v. Löwisffad6332002-11-26 09:28:05 +0000873static PyObject*
874get_typename(PyTclObject* obj, void* ignored)
875{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000876 return PyUnicode_FromString(obj->value->typePtr->name);
Martin v. Löwisffad6332002-11-26 09:28:05 +0000877}
878
Martin v. Löwis39195712003-01-04 00:33:13 +0000879
Martin v. Löwisffad6332002-11-26 09:28:05 +0000880static PyGetSetDef PyTclObject_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000881 {"typename", (getter)get_typename, NULL, get_typename__doc__},
882 {"string", (getter)PyTclObject_string, NULL,
883 PyTclObject_string__doc__},
884 {0},
Martin v. Löwisffad6332002-11-26 09:28:05 +0000885};
886
Neal Norwitz227b5332006-03-22 09:28:35 +0000887static PyTypeObject PyTclObject_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000888 PyVarObject_HEAD_INIT(NULL, 0)
889 "_tkinter.Tcl_Obj", /*tp_name*/
890 sizeof(PyTclObject), /*tp_basicsize*/
891 0, /*tp_itemsize*/
892 /* methods */
893 (destructor)PyTclObject_dealloc,/*tp_dealloc*/
894 0, /*tp_print*/
895 0, /*tp_getattr*/
896 0, /*tp_setattr*/
897 0, /*tp_reserved*/
898 (reprfunc)PyTclObject_repr, /*tp_repr*/
899 0, /*tp_as_number*/
900 0, /*tp_as_sequence*/
901 0, /*tp_as_mapping*/
902 0, /*tp_hash*/
903 0, /*tp_call*/
904 (reprfunc)PyTclObject_str, /*tp_str*/
905 PyObject_GenericGetAttr, /*tp_getattro*/
906 0, /*tp_setattro*/
907 0, /*tp_as_buffer*/
908 Py_TPFLAGS_DEFAULT, /*tp_flags*/
909 0, /*tp_doc*/
910 0, /*tp_traverse*/
911 0, /*tp_clear*/
912 PyTclObject_richcompare, /*tp_richcompare*/
913 0, /*tp_weaklistoffset*/
914 0, /*tp_iter*/
915 0, /*tp_iternext*/
916 0, /*tp_methods*/
917 0, /*tp_members*/
918 PyTclObject_getsetlist, /*tp_getset*/
919 0, /*tp_base*/
920 0, /*tp_dict*/
921 0, /*tp_descr_get*/
922 0, /*tp_descr_set*/
923 0, /*tp_dictoffset*/
924 0, /*tp_init*/
925 0, /*tp_alloc*/
926 0, /*tp_new*/
927 0, /*tp_free*/
928 0, /*tp_is_gc*/
Martin v. Löwisffad6332002-11-26 09:28:05 +0000929};
930
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000931static Tcl_Obj*
Fred Drake509d79a2000-07-08 04:04:38 +0000932AsObj(PyObject *value)
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000933{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000934 Tcl_Obj *result;
935 long longVal;
936 int overflow;
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +0000937
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000938 if (PyBytes_Check(value))
939 return Tcl_NewStringObj(PyBytes_AS_STRING(value),
940 PyBytes_GET_SIZE(value));
941 else if (PyBool_Check(value))
942 return Tcl_NewBooleanObj(PyObject_IsTrue(value));
943 else if (PyLong_CheckExact(value) &&
944 ((longVal = PyLong_AsLongAndOverflow(value, &overflow)),
945 !overflow)) {
946 /* If there is an overflow in the long conversion,
947 fall through to default object handling. */
948 return Tcl_NewLongObj(longVal);
949 }
950 else if (PyFloat_Check(value))
951 return Tcl_NewDoubleObj(PyFloat_AS_DOUBLE(value));
952 else if (PyTuple_Check(value)) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300953 Tcl_Obj **argv;
954 Py_ssize_t size, i;
955
956 size = PyTuple_Size(value);
957 if (!CHECK_SIZE(size, sizeof(Tcl_Obj *))) {
958 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
959 return NULL;
960 }
961 argv = (Tcl_Obj **) ckalloc(((size_t)size) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000962 if(!argv)
963 return 0;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300964 for (i = 0; i < size; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000965 argv[i] = AsObj(PyTuple_GetItem(value,i));
966 result = Tcl_NewListObj(PyTuple_Size(value), argv);
967 ckfree(FREECAST argv);
968 return result;
969 }
970 else if (PyUnicode_Check(value)) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200971 void *inbuf;
972 Py_ssize_t size;
973 int kind;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000974 Tcl_UniChar *outbuf = NULL;
975 Py_ssize_t i;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200976 size_t allocsize;
977
978 if (PyUnicode_READY(value) == -1)
979 return NULL;
980
981 inbuf = PyUnicode_DATA(value);
982 size = PyUnicode_GET_LENGTH(value);
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +0300983 if (!CHECK_SIZE(size, sizeof(Tcl_UniChar))) {
984 PyErr_SetString(PyExc_OverflowError, "string is too long");
985 return NULL;
986 }
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200987 kind = PyUnicode_KIND(value);
988 allocsize = ((size_t)size) * sizeof(Tcl_UniChar);
989 outbuf = (Tcl_UniChar*)ckalloc(allocsize);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000990 /* Else overflow occurred, and we take the next exit */
991 if (!outbuf) {
992 PyErr_NoMemory();
993 return NULL;
994 }
995 for (i = 0; i < size; i++) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200996 Py_UCS4 ch = PyUnicode_READ(kind, inbuf, i);
997 /* We cannot test for sizeof(Tcl_UniChar) directly,
998 so we test for UTF-8 size instead. */
999#if TCL_UTF_MAX == 3
1000 if (ch >= 0x10000) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001001 /* Tcl doesn't do UTF-16, yet. */
Serhiy Storchaka59f5dee2013-02-18 13:01:52 +02001002 PyErr_Format(Tkinter_TclError,
Victor Stinner7ab41922011-11-04 00:36:46 +01001003 "character U+%x is above the range "
1004 "(U+0000-U+FFFF) allowed by Tcl",
Victor Stinner3d7acb02011-11-04 09:49:24 +01001005 ch);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001006 ckfree(FREECAST outbuf);
1007 return NULL;
1008 }
Andrew Svetlov80823d72012-07-22 13:56:54 +03001009#endif
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001010 outbuf[i] = ch;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001011 }
1012 result = Tcl_NewUnicodeObj(outbuf, size);
1013 ckfree(FREECAST outbuf);
1014 return result;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001015 }
1016 else if(PyTclObject_Check(value)) {
1017 Tcl_Obj *v = ((PyTclObject*)value)->value;
1018 Tcl_IncrRefCount(v);
1019 return v;
1020 }
1021 else {
1022 PyObject *v = PyObject_Str(value);
1023 if (!v)
1024 return 0;
1025 result = AsObj(v);
1026 Py_DECREF(v);
1027 return result;
1028 }
Guido van Rossuma1f0a8f2000-03-31 00:51:37 +00001029}
1030
Martin v. Löwisffad6332002-11-26 09:28:05 +00001031static PyObject*
1032FromObj(PyObject* tkapp, Tcl_Obj *value)
1033{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001034 PyObject *result = NULL;
1035 TkappObject *app = (TkappObject*)tkapp;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001037 if (value->typePtr == NULL) {
1038 return PyUnicode_FromStringAndSize(value->bytes,
1039 value->length);
1040 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001041
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001042 if (value->typePtr == app->BooleanType) {
1043 result = value->internalRep.longValue ? Py_True : Py_False;
1044 Py_INCREF(result);
1045 return result;
1046 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001047
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001048 if (value->typePtr == app->ByteArrayType) {
1049 int size;
1050 char *data = (char*)Tcl_GetByteArrayFromObj(value, &size);
1051 return PyBytes_FromStringAndSize(data, size);
1052 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001053
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001054 if (value->typePtr == app->DoubleType) {
1055 return PyFloat_FromDouble(value->internalRep.doubleValue);
1056 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001057
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001058 if (value->typePtr == app->IntType) {
1059 return PyLong_FromLong(value->internalRep.longValue);
1060 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001061
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001062 if (value->typePtr == app->ListType) {
1063 int size;
1064 int i, status;
1065 PyObject *elem;
1066 Tcl_Obj *tcl_elem;
Martin v. Löwisffad6332002-11-26 09:28:05 +00001067
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001068 status = Tcl_ListObjLength(Tkapp_Interp(tkapp), value, &size);
1069 if (status == TCL_ERROR)
1070 return Tkinter_Error(tkapp);
1071 result = PyTuple_New(size);
1072 if (!result)
1073 return NULL;
1074 for (i = 0; i < size; i++) {
1075 status = Tcl_ListObjIndex(Tkapp_Interp(tkapp),
1076 value, i, &tcl_elem);
1077 if (status == TCL_ERROR) {
1078 Py_DECREF(result);
1079 return Tkinter_Error(tkapp);
1080 }
1081 elem = FromObj(tkapp, tcl_elem);
1082 if (!elem) {
1083 Py_DECREF(result);
1084 return NULL;
1085 }
1086 PyTuple_SetItem(result, i, elem);
1087 }
1088 return result;
1089 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001090
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001091 if (value->typePtr == app->ProcBodyType) {
1092 /* fall through: return tcl object. */
1093 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001094
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001095 if (value->typePtr == app->StringType) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001096#if TCL_UTF_MAX==3
1097 return PyUnicode_FromKindAndData(
1098 PyUnicode_2BYTE_KIND, Tcl_GetUnicode(value),
1099 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001100#else
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02001101 return PyUnicode_FromKindAndData(
1102 PyUnicode_4BYTE_KIND, Tcl_GetUnicode(value),
1103 Tcl_GetCharLength(value));
Martin v. Löwisffad6332002-11-26 09:28:05 +00001104#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001105 }
Martin v. Löwisffad6332002-11-26 09:28:05 +00001106
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001107 return newPyTclObject(value);
Martin v. Löwisffad6332002-11-26 09:28:05 +00001108}
1109
Benjamin Peterson5879d412009-03-30 14:51:56 +00001110#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001111/* This mutex synchronizes inter-thread command calls. */
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001112TCL_DECLARE_MUTEX(call_mutex)
1113
1114typedef struct Tkapp_CallEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001115 Tcl_Event ev; /* Must be first */
1116 TkappObject *self;
1117 PyObject *args;
1118 int flags;
1119 PyObject **res;
1120 PyObject **exc_type, **exc_value, **exc_tb;
1121 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001122} Tkapp_CallEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001123#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001124
1125void
1126Tkapp_CallDeallocArgs(Tcl_Obj** objv, Tcl_Obj** objStore, int objc)
Guido van Rossum18468821994-06-20 07:49:28 +00001127{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001128 int i;
1129 for (i = 0; i < objc; i++)
1130 Tcl_DecrRefCount(objv[i]);
1131 if (objv != objStore)
1132 ckfree(FREECAST objv);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001133}
Guido van Rossum18468821994-06-20 07:49:28 +00001134
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001135/* Convert Python objects to Tcl objects. This must happen in the
1136 interpreter thread, which may or may not be the calling thread. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001137
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001138static Tcl_Obj**
1139Tkapp_CallArgs(PyObject *args, Tcl_Obj** objStore, int *pobjc)
1140{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001141 Tcl_Obj **objv = objStore;
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001142 Py_ssize_t objc = 0, i;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001143 if (args == NULL)
1144 /* do nothing */;
Barry Warsawfa701a81997-01-16 00:15:11 +00001145
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001146 else if (!PyTuple_Check(args)) {
1147 objv[0] = AsObj(args);
1148 if (objv[0] == 0)
1149 goto finally;
1150 objc = 1;
1151 Tcl_IncrRefCount(objv[0]);
1152 }
1153 else {
1154 objc = PyTuple_Size(args);
Guido van Rossum212643f1998-04-29 16:22:14 +00001155
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001156 if (objc > ARGSZ) {
Serhiy Storchaka9e6b9752013-08-21 21:38:21 +03001157 if (!CHECK_SIZE(objc, sizeof(Tcl_Obj *))) {
1158 PyErr_SetString(PyExc_OverflowError, "tuple is too long");
1159 return NULL;
1160 }
1161 objv = (Tcl_Obj **)ckalloc(((size_t)objc) * sizeof(Tcl_Obj *));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001162 if (objv == NULL) {
1163 PyErr_NoMemory();
1164 objc = 0;
1165 goto finally;
1166 }
1167 }
Guido van Rossum212643f1998-04-29 16:22:14 +00001168
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001169 for (i = 0; i < objc; i++) {
1170 PyObject *v = PyTuple_GetItem(args, i);
1171 if (v == Py_None) {
1172 objc = i;
1173 break;
1174 }
1175 objv[i] = AsObj(v);
1176 if (!objv[i]) {
1177 /* Reset objc, so it attempts to clear
1178 objects only up to i. */
1179 objc = i;
1180 goto finally;
1181 }
1182 Tcl_IncrRefCount(objv[i]);
1183 }
1184 }
1185 *pobjc = objc;
1186 return objv;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001187finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001188 Tkapp_CallDeallocArgs(objv, objStore, objc);
1189 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001190}
Guido van Rossum212643f1998-04-29 16:22:14 +00001191
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001192/* Convert the results of a command call into a Python objects. */
Guido van Rossum632de272000-03-29 00:19:50 +00001193
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001194static PyObject*
1195Tkapp_CallResult(TkappObject *self)
1196{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001197 PyObject *res = NULL;
1198 if(self->wantobjects) {
1199 Tcl_Obj *value = Tcl_GetObjResult(self->interp);
1200 /* Not sure whether the IncrRef is necessary, but something
1201 may overwrite the interpreter result while we are
1202 converting it. */
1203 Tcl_IncrRefCount(value);
1204 res = FromObj((PyObject*)self, value);
1205 Tcl_DecrRefCount(value);
1206 } else {
Serhiy Storchaka31f477c2013-09-20 23:21:44 +03001207 res = PyUnicode_FromString(Tcl_GetStringResult(self->interp));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001208 }
1209 return res;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001210}
Guido van Rossum632de272000-03-29 00:19:50 +00001211
Benjamin Peterson5879d412009-03-30 14:51:56 +00001212#ifdef WITH_THREAD
1213
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001214/* Tkapp_CallProc is the event procedure that is executed in the context of
1215 the Tcl interpreter thread. Initially, it holds the Tcl lock, and doesn't
1216 hold the Python lock. */
Barry Warsawfa701a81997-01-16 00:15:11 +00001217
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001218static int
1219Tkapp_CallProc(Tkapp_CallEvent *e, int flags)
1220{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001221 Tcl_Obj *objStore[ARGSZ];
1222 Tcl_Obj **objv;
1223 int objc;
1224 int i;
1225 ENTER_PYTHON
1226 objv = Tkapp_CallArgs(e->args, objStore, &objc);
1227 if (!objv) {
1228 PyErr_Fetch(e->exc_type, e->exc_value, e->exc_tb);
1229 *(e->res) = NULL;
1230 }
1231 LEAVE_PYTHON
1232 if (!objv)
1233 goto done;
1234 i = Tcl_EvalObjv(e->self->interp, objc, objv, e->flags);
1235 ENTER_PYTHON
1236 if (i == TCL_ERROR) {
1237 *(e->res) = NULL;
1238 *(e->exc_type) = NULL;
1239 *(e->exc_tb) = NULL;
1240 *(e->exc_value) = PyObject_CallFunction(
1241 Tkinter_TclError, "s",
1242 Tcl_GetStringResult(e->self->interp));
1243 }
1244 else {
1245 *(e->res) = Tkapp_CallResult(e->self);
1246 }
1247 LEAVE_PYTHON
Guilherme Polo491aee22009-02-06 23:16:11 +00001248
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001249 Tkapp_CallDeallocArgs(objv, objStore, objc);
Guilherme Polo491aee22009-02-06 23:16:11 +00001250done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001251 /* Wake up calling thread. */
1252 Tcl_MutexLock(&call_mutex);
1253 Tcl_ConditionNotify(e->done);
1254 Tcl_MutexUnlock(&call_mutex);
1255 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001256}
1257
Benjamin Peterson5879d412009-03-30 14:51:56 +00001258#endif
1259
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001260/* This is the main entry point for calling a Tcl command.
1261 It supports three cases, with regard to threading:
1262 1. Tcl is not threaded: Must have the Tcl lock, then can invoke command in
1263 the context of the calling thread.
1264 2. Tcl is threaded, caller of the command is in the interpreter thread:
1265 Execute the command in the calling thread. Since the Tcl lock will
1266 not be used, we can merge that with case 1.
1267 3. Tcl is threaded, caller is in a different thread: Must queue an event to
1268 the interpreter thread. Allocation of Tcl objects needs to occur in the
1269 interpreter thread, so we ship the PyObject* args to the target thread,
1270 and perform processing there. */
1271
1272static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001273Tkapp_Call(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001274{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001275 Tcl_Obj *objStore[ARGSZ];
1276 Tcl_Obj **objv = NULL;
1277 int objc, i;
1278 PyObject *res = NULL;
1279 TkappObject *self = (TkappObject*)selfptr;
1280 int flags = TCL_EVAL_DIRECT | TCL_EVAL_GLOBAL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001282 /* If args is a single tuple, replace with contents of tuple */
1283 if (1 == PyTuple_Size(args)){
1284 PyObject* item = PyTuple_GetItem(args, 0);
1285 if (PyTuple_Check(item))
1286 args = item;
1287 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001288#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001289 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1290 /* We cannot call the command directly. Instead, we must
1291 marshal the parameters to the interpreter thread. */
1292 Tkapp_CallEvent *ev;
1293 Tcl_Condition cond = NULL;
1294 PyObject *exc_type, *exc_value, *exc_tb;
1295 if (!WaitForMainloop(self))
1296 return NULL;
1297 ev = (Tkapp_CallEvent*)ckalloc(sizeof(Tkapp_CallEvent));
1298 ev->ev.proc = (Tcl_EventProc*)Tkapp_CallProc;
1299 ev->self = self;
1300 ev->args = args;
1301 ev->res = &res;
1302 ev->exc_type = &exc_type;
1303 ev->exc_value = &exc_value;
1304 ev->exc_tb = &exc_tb;
1305 ev->done = &cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001306
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001307 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &call_mutex);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001308
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001309 if (res == NULL) {
1310 if (exc_type)
1311 PyErr_Restore(exc_type, exc_value, exc_tb);
1312 else
1313 PyErr_SetObject(Tkinter_TclError, exc_value);
1314 }
1315 Tcl_ConditionFinalize(&cond);
1316 }
1317 else
Martin v. Löwisa9656492003-03-30 08:44:58 +00001318#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001319 {
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001320
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001321 objv = Tkapp_CallArgs(args, objStore, &objc);
1322 if (!objv)
1323 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001324
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001325 ENTER_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001326
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001327 i = Tcl_EvalObjv(self->interp, objc, objv, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001328
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001329 ENTER_OVERLAP
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001330
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001331 if (i == TCL_ERROR)
1332 Tkinter_Error(selfptr);
1333 else
1334 res = Tkapp_CallResult(self);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001335
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001336 LEAVE_OVERLAP_TCL
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001337
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001338 Tkapp_CallDeallocArgs(objv, objStore, objc);
1339 }
1340 return res;
Barry Warsawfa701a81997-01-16 00:15:11 +00001341}
1342
1343
1344static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001345Tkapp_GlobalCall(PyObject *self, PyObject *args)
Barry Warsawfa701a81997-01-16 00:15:11 +00001346{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001347 /* Could do the same here as for Tkapp_Call(), but this is not used
1348 much, so I can't be bothered. Unfortunately Tcl doesn't export a
1349 way for the user to do what all its Global* variants do (save and
1350 reset the scope pointer, call the local version, restore the saved
1351 scope pointer). */
Guido van Rossum212643f1998-04-29 16:22:14 +00001352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001353 char *cmd;
1354 PyObject *res = NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001355
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001356 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1357 "globalcall is deprecated and will be removed in 3.4",
1358 1) < 0)
1359 return 0;
1360
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001361 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001362
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001363 cmd = Merge(args);
1364 if (cmd) {
1365 int err;
1366 ENTER_TCL
1367 err = Tcl_GlobalEval(Tkapp_Interp(self), cmd);
1368 ENTER_OVERLAP
1369 if (err == TCL_ERROR)
1370 res = Tkinter_Error(self);
1371 else
1372 res = PyUnicode_FromString(Tkapp_Result(self));
1373 LEAVE_OVERLAP_TCL
1374 ckfree(cmd);
1375 }
Barry Warsawfa701a81997-01-16 00:15:11 +00001376
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001377 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001378}
1379
1380static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001381Tkapp_Eval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001382{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001383 char *script;
1384 PyObject *res = NULL;
1385 int err;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001387 if (!PyArg_ParseTuple(args, "s:eval", &script))
1388 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00001389
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001390 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001391
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001392 ENTER_TCL
1393 err = Tcl_Eval(Tkapp_Interp(self), script);
1394 ENTER_OVERLAP
1395 if (err == TCL_ERROR)
1396 res = Tkinter_Error(self);
1397 else
1398 res = PyUnicode_FromString(Tkapp_Result(self));
1399 LEAVE_OVERLAP_TCL
1400 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001401}
1402
1403static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001404Tkapp_GlobalEval(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001405{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001406 char *script;
1407 PyObject *res = NULL;
1408 int err;
Guido van Rossum62320c91998-06-15 04:36:09 +00001409
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03001410 if (PyErr_WarnEx(PyExc_DeprecationWarning,
1411 "globaleval is deprecated and will be removed in 3.4",
1412 1) < 0)
1413 return 0;
1414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001415 if (!PyArg_ParseTuple(args, "s:globaleval", &script))
1416 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001417
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001418 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001419
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001420 ENTER_TCL
1421 err = Tcl_GlobalEval(Tkapp_Interp(self), script);
1422 ENTER_OVERLAP
1423 if (err == TCL_ERROR)
1424 res = Tkinter_Error(self);
1425 else
1426 res = PyUnicode_FromString(Tkapp_Result(self));
1427 LEAVE_OVERLAP_TCL
1428 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001429}
1430
1431static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001432Tkapp_EvalFile(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001433{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001434 char *fileName;
1435 PyObject *res = NULL;
1436 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001437
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001438 if (!PyArg_ParseTuple(args, "s:evalfile", &fileName))
1439 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001441 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001442
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001443 ENTER_TCL
1444 err = Tcl_EvalFile(Tkapp_Interp(self), fileName);
1445 ENTER_OVERLAP
1446 if (err == TCL_ERROR)
1447 res = Tkinter_Error(self);
Guido van Rossum18468821994-06-20 07:49:28 +00001448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001449 else
1450 res = PyUnicode_FromString(Tkapp_Result(self));
1451 LEAVE_OVERLAP_TCL
1452 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001453}
1454
1455static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001456Tkapp_Record(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001457{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001458 char *script;
1459 PyObject *res = NULL;
1460 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00001461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001462 if (!PyArg_ParseTuple(args, "s", &script))
1463 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001464
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001465 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001466
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001467 ENTER_TCL
1468 err = Tcl_RecordAndEval(Tkapp_Interp(self), script, TCL_NO_EVAL);
1469 ENTER_OVERLAP
1470 if (err == TCL_ERROR)
1471 res = Tkinter_Error(self);
1472 else
1473 res = PyUnicode_FromString(Tkapp_Result(self));
1474 LEAVE_OVERLAP_TCL
1475 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001476}
1477
1478static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001479Tkapp_AddErrorInfo(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001480{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001481 char *msg;
Guido van Rossum18468821994-06-20 07:49:28 +00001482
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001483 if (!PyArg_ParseTuple(args, "s:adderrorinfo", &msg))
1484 return NULL;
1485 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001486
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001487 ENTER_TCL
1488 Tcl_AddErrorInfo(Tkapp_Interp(self), msg);
1489 LEAVE_TCL
Guido van Rossum18468821994-06-20 07:49:28 +00001490
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001491 Py_INCREF(Py_None);
1492 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00001493}
1494
Barry Warsawfa701a81997-01-16 00:15:11 +00001495
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001496
Guido van Rossum18468821994-06-20 07:49:28 +00001497/** Tcl Variable **/
1498
Benjamin Peterson5879d412009-03-30 14:51:56 +00001499typedef PyObject* (*EventFunc)(PyObject*, PyObject *args, int flags);
1500
1501#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001502TCL_DECLARE_MUTEX(var_mutex)
1503
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001504typedef struct VarEvent {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001505 Tcl_Event ev; /* must be first */
1506 PyObject *self;
1507 PyObject *args;
1508 int flags;
1509 EventFunc func;
1510 PyObject **res;
1511 PyObject **exc_type;
1512 PyObject **exc_val;
1513 Tcl_Condition *cond;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001514} VarEvent;
Benjamin Peterson5879d412009-03-30 14:51:56 +00001515#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001516
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001517static int
1518varname_converter(PyObject *in, void *_out)
1519{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001520 char **out = (char**)_out;
1521 if (PyBytes_Check(in)) {
1522 *out = PyBytes_AsString(in);
1523 return 1;
1524 }
1525 if (PyUnicode_Check(in)) {
1526 *out = _PyUnicode_AsString(in);
1527 return 1;
1528 }
1529 if (PyTclObject_Check(in)) {
1530 *out = PyTclObject_TclString(in);
1531 return 1;
1532 }
1533 /* XXX: Should give diagnostics. */
1534 return 0;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001535}
Martin v. Löwis1869ec52003-05-01 05:47:00 +00001536
Benjamin Peterson5879d412009-03-30 14:51:56 +00001537#ifdef WITH_THREAD
1538
Martin v. Löwis59683e82008-06-13 07:50:45 +00001539static void
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001540var_perform(VarEvent *ev)
1541{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001542 *(ev->res) = ev->func(ev->self, ev->args, ev->flags);
1543 if (!*(ev->res)) {
1544 PyObject *exc, *val, *tb;
1545 PyErr_Fetch(&exc, &val, &tb);
1546 PyErr_NormalizeException(&exc, &val, &tb);
1547 *(ev->exc_type) = exc;
1548 *(ev->exc_val) = val;
1549 Py_DECREF(tb);
1550 }
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001551
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001552}
1553
1554static int
1555var_proc(VarEvent* ev, int flags)
1556{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001557 ENTER_PYTHON
1558 var_perform(ev);
1559 Tcl_MutexLock(&var_mutex);
1560 Tcl_ConditionNotify(ev->cond);
1561 Tcl_MutexUnlock(&var_mutex);
1562 LEAVE_PYTHON
1563 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001564}
1565
Benjamin Peterson5879d412009-03-30 14:51:56 +00001566#endif
1567
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001568static PyObject*
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00001569var_invoke(EventFunc func, PyObject *selfptr, PyObject *args, int flags)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001570{
Martin v. Löwisa9656492003-03-30 08:44:58 +00001571#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001572 TkappObject *self = (TkappObject*)selfptr;
1573 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
1574 TkappObject *self = (TkappObject*)selfptr;
1575 VarEvent *ev;
1576 PyObject *res, *exc_type, *exc_val;
1577 Tcl_Condition cond = NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001579 /* The current thread is not the interpreter thread. Marshal
1580 the call to the interpreter thread, then wait for
1581 completion. */
1582 if (!WaitForMainloop(self))
1583 return NULL;
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001584
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001585 ev = (VarEvent*)ckalloc(sizeof(VarEvent));
Martin v. Löwisee24e9c2003-04-15 20:33:20 +00001586
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001587 ev->self = selfptr;
1588 ev->args = args;
1589 ev->flags = flags;
1590 ev->func = func;
1591 ev->res = &res;
1592 ev->exc_type = &exc_type;
1593 ev->exc_val = &exc_val;
1594 ev->cond = &cond;
1595 ev->ev.proc = (Tcl_EventProc*)var_proc;
1596 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &var_mutex);
1597 Tcl_ConditionFinalize(&cond);
1598 if (!res) {
1599 PyErr_SetObject(exc_type, exc_val);
1600 Py_DECREF(exc_type);
1601 Py_DECREF(exc_val);
1602 return NULL;
1603 }
1604 return res;
1605 }
Martin v. Löwisa9656492003-03-30 08:44:58 +00001606#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001607 /* Tcl is not threaded, or this is the interpreter thread. */
1608 return func(selfptr, args, flags);
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001609}
1610
Guido van Rossum18468821994-06-20 07:49:28 +00001611static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001612SetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001613{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001614 char *name1, *name2;
1615 PyObject *newValue;
1616 PyObject *res = NULL;
1617 Tcl_Obj *newval, *ok;
Guido van Rossum18468821994-06-20 07:49:28 +00001618
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001619 if (PyArg_ParseTuple(args, "O&O:setvar",
1620 varname_converter, &name1, &newValue)) {
1621 /* XXX Acquire tcl lock??? */
1622 newval = AsObj(newValue);
1623 if (newval == NULL)
1624 return NULL;
1625 ENTER_TCL
1626 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, NULL,
1627 newval, flags);
1628 ENTER_OVERLAP
1629 if (!ok)
1630 Tkinter_Error(self);
1631 else {
1632 res = Py_None;
1633 Py_INCREF(res);
1634 }
1635 LEAVE_OVERLAP_TCL
1636 }
1637 else {
1638 PyErr_Clear();
1639 if (PyArg_ParseTuple(args, "ssO:setvar",
1640 &name1, &name2, &newValue)) {
1641 /* XXX must hold tcl lock already??? */
1642 newval = AsObj(newValue);
1643 ENTER_TCL
1644 ok = Tcl_SetVar2Ex(Tkapp_Interp(self), name1, name2, newval, flags);
1645 ENTER_OVERLAP
1646 if (!ok)
1647 Tkinter_Error(self);
1648 else {
1649 res = Py_None;
1650 Py_INCREF(res);
1651 }
1652 LEAVE_OVERLAP_TCL
1653 }
1654 else {
1655 return NULL;
1656 }
1657 }
1658 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001659}
1660
1661static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001662Tkapp_SetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001663{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001664 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001665}
1666
1667static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001668Tkapp_GlobalSetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001669{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001670 return var_invoke(SetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001671}
1672
Barry Warsawfa701a81997-01-16 00:15:11 +00001673
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001674
Guido van Rossum18468821994-06-20 07:49:28 +00001675static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001676GetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001677{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001678 char *name1, *name2=NULL;
1679 PyObject *res = NULL;
1680 Tcl_Obj *tres;
Guido van Rossum18468821994-06-20 07:49:28 +00001681
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001682 if (!PyArg_ParseTuple(args, "O&|s:getvar",
1683 varname_converter, &name1, &name2))
1684 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001685
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001686 ENTER_TCL
1687 tres = Tcl_GetVar2Ex(Tkapp_Interp(self), name1, name2, flags);
1688 ENTER_OVERLAP
1689 if (tres == NULL) {
1690 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
1691 } else {
1692 if (((TkappObject*)self)->wantobjects) {
1693 res = FromObj(self, tres);
1694 }
1695 else {
1696 res = PyUnicode_FromString(Tcl_GetString(tres));
1697 }
1698 }
1699 LEAVE_OVERLAP_TCL
1700 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001701}
1702
1703static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001704Tkapp_GetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001705{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001706 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001707}
1708
1709static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001710Tkapp_GlobalGetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001711{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001712 return var_invoke(GetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001713}
1714
Barry Warsawfa701a81997-01-16 00:15:11 +00001715
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001716
Guido van Rossum18468821994-06-20 07:49:28 +00001717static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001718UnsetVar(PyObject *self, PyObject *args, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00001719{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001720 char *name1, *name2=NULL;
1721 int code;
1722 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001723
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001724 if (!PyArg_ParseTuple(args, "s|s:unsetvar", &name1, &name2))
1725 return NULL;
Guido van Rossum35d43371997-08-02 00:09:09 +00001726
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001727 ENTER_TCL
1728 code = Tcl_UnsetVar2(Tkapp_Interp(self), name1, name2, flags);
1729 ENTER_OVERLAP
1730 if (code == TCL_ERROR)
1731 res = Tkinter_Error(self);
1732 else {
1733 Py_INCREF(Py_None);
1734 res = Py_None;
1735 }
1736 LEAVE_OVERLAP_TCL
1737 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001738}
1739
1740static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001741Tkapp_UnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001742{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001743 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG);
Guido van Rossum18468821994-06-20 07:49:28 +00001744}
1745
1746static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001747Tkapp_GlobalUnsetVar(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001748{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001749 return var_invoke(UnsetVar, self, args, TCL_LEAVE_ERR_MSG | TCL_GLOBAL_ONLY);
Guido van Rossum18468821994-06-20 07:49:28 +00001750}
1751
Barry Warsawfa701a81997-01-16 00:15:11 +00001752
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001753
Guido van Rossum18468821994-06-20 07:49:28 +00001754/** Tcl to Python **/
1755
1756static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001757Tkapp_GetInt(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001758{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001759 char *s;
1760 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001761
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001762 if (PyTuple_Size(args) == 1) {
1763 PyObject* o = PyTuple_GetItem(args, 0);
1764 if (PyLong_Check(o)) {
1765 Py_INCREF(o);
1766 return o;
1767 }
1768 }
1769 if (!PyArg_ParseTuple(args, "s:getint", &s))
1770 return NULL;
1771 if (Tcl_GetInt(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1772 return Tkinter_Error(self);
1773 return Py_BuildValue("i", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001774}
1775
1776static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001777Tkapp_GetDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001778{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001779 char *s;
1780 double v;
Guido van Rossum18468821994-06-20 07:49:28 +00001781
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001782 if (PyTuple_Size(args) == 1) {
1783 PyObject *o = PyTuple_GetItem(args, 0);
1784 if (PyFloat_Check(o)) {
1785 Py_INCREF(o);
1786 return o;
1787 }
1788 }
1789 if (!PyArg_ParseTuple(args, "s:getdouble", &s))
1790 return NULL;
1791 if (Tcl_GetDouble(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1792 return Tkinter_Error(self);
1793 return Py_BuildValue("d", v);
Guido van Rossum18468821994-06-20 07:49:28 +00001794}
1795
1796static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001797Tkapp_GetBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001798{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001799 char *s;
1800 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001801
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001802 if (PyTuple_Size(args) == 1) {
1803 PyObject *o = PyTuple_GetItem(args, 0);
1804 if (PyLong_Check(o)) {
1805 Py_INCREF(o);
1806 return o;
1807 }
1808 }
1809 if (!PyArg_ParseTuple(args, "s:getboolean", &s))
1810 return NULL;
1811 if (Tcl_GetBoolean(Tkapp_Interp(self), s, &v) == TCL_ERROR)
1812 return Tkinter_Error(self);
1813 return PyBool_FromLong(v);
Guido van Rossum18468821994-06-20 07:49:28 +00001814}
1815
1816static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001817Tkapp_ExprString(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001818{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001819 char *s;
1820 PyObject *res = NULL;
1821 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001822
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001823 if (!PyArg_ParseTuple(args, "s:exprstring", &s))
1824 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00001825
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001826 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001827
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001828 ENTER_TCL
1829 retval = Tcl_ExprString(Tkapp_Interp(self), s);
1830 ENTER_OVERLAP
1831 if (retval == TCL_ERROR)
1832 res = Tkinter_Error(self);
1833 else
1834 res = Py_BuildValue("s", Tkapp_Result(self));
1835 LEAVE_OVERLAP_TCL
1836 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001837}
1838
1839static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001840Tkapp_ExprLong(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001841{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001842 char *s;
1843 PyObject *res = NULL;
1844 int retval;
1845 long v;
Guido van Rossum18468821994-06-20 07:49:28 +00001846
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001847 if (!PyArg_ParseTuple(args, "s:exprlong", &s))
1848 return NULL;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001849
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001850 CHECK_TCL_APPARTMENT;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001851
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001852 ENTER_TCL
1853 retval = Tcl_ExprLong(Tkapp_Interp(self), s, &v);
1854 ENTER_OVERLAP
1855 if (retval == TCL_ERROR)
1856 res = Tkinter_Error(self);
1857 else
1858 res = Py_BuildValue("l", v);
1859 LEAVE_OVERLAP_TCL
1860 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001861}
1862
1863static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001864Tkapp_ExprDouble(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001865{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001866 char *s;
1867 PyObject *res = NULL;
1868 double v;
1869 int retval;
Guido van Rossum18468821994-06-20 07:49:28 +00001870
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001871 if (!PyArg_ParseTuple(args, "s:exprdouble", &s))
1872 return NULL;
1873 CHECK_TCL_APPARTMENT;
1874 PyFPE_START_PROTECT("Tkapp_ExprDouble", return 0)
1875 ENTER_TCL
1876 retval = Tcl_ExprDouble(Tkapp_Interp(self), s, &v);
1877 ENTER_OVERLAP
1878 PyFPE_END_PROTECT(retval)
1879 if (retval == TCL_ERROR)
1880 res = Tkinter_Error(self);
1881 else
1882 res = Py_BuildValue("d", v);
1883 LEAVE_OVERLAP_TCL
1884 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001885}
1886
1887static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001888Tkapp_ExprBoolean(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001889{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001890 char *s;
1891 PyObject *res = NULL;
1892 int retval;
1893 int v;
Guido van Rossum18468821994-06-20 07:49:28 +00001894
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001895 if (!PyArg_ParseTuple(args, "s:exprboolean", &s))
1896 return NULL;
1897 CHECK_TCL_APPARTMENT;
1898 ENTER_TCL
1899 retval = Tcl_ExprBoolean(Tkapp_Interp(self), s, &v);
1900 ENTER_OVERLAP
1901 if (retval == TCL_ERROR)
1902 res = Tkinter_Error(self);
1903 else
1904 res = Py_BuildValue("i", v);
1905 LEAVE_OVERLAP_TCL
1906 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00001907}
1908
Barry Warsawfa701a81997-01-16 00:15:11 +00001909
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001910
Guido van Rossum18468821994-06-20 07:49:28 +00001911static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001912Tkapp_SplitList(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001913{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001914 char *list;
1915 int argc;
1916 char **argv;
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001917 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001918 int i;
Guido van Rossum18468821994-06-20 07:49:28 +00001919
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001920 if (!PyArg_ParseTuple(args, "O:splitlist", &arg))
1921 return NULL;
1922 if (PyTclObject_Check(arg)) {
1923 int objc;
1924 Tcl_Obj **objv;
1925 if (Tcl_ListObjGetElements(Tkapp_Interp(self),
1926 ((PyTclObject*)arg)->value,
1927 &objc, &objv) == TCL_ERROR) {
1928 return Tkinter_Error(self);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001929 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001930 if (!(v = PyTuple_New(objc)))
1931 return NULL;
1932 for (i = 0; i < objc; i++) {
1933 PyObject *s = FromObj(self, objv[i]);
1934 if (!s || PyTuple_SetItem(v, i, s)) {
1935 Py_DECREF(v);
1936 return NULL;
1937 }
1938 }
1939 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001940 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001941 if (PyTuple_Check(arg)) {
1942 Py_INCREF(arg);
1943 return arg;
1944 }
1945
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001946 if (!PyArg_ParseTuple(args, "et:splitlist", "utf-8", &list))
1947 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00001948
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001949 if (Tcl_SplitList(Tkapp_Interp(self), list,
1950 &argc, &argv) == TCL_ERROR) {
1951 PyMem_Free(list);
1952 return Tkinter_Error(self);
1953 }
Guido van Rossum18468821994-06-20 07:49:28 +00001954
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001955 if (!(v = PyTuple_New(argc)))
1956 goto finally;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00001957
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001958 for (i = 0; i < argc; i++) {
1959 PyObject *s = PyUnicode_FromString(argv[i]);
1960 if (!s || PyTuple_SetItem(v, i, s)) {
1961 Py_DECREF(v);
1962 v = NULL;
1963 goto finally;
1964 }
1965 }
Guido van Rossum18468821994-06-20 07:49:28 +00001966
Barry Warsawfa701a81997-01-16 00:15:11 +00001967 finally:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001968 ckfree(FREECAST argv);
1969 PyMem_Free(list);
1970 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00001971}
1972
1973static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00001974Tkapp_Split(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00001975{
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001976 PyObject *arg, *v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001977 char *list;
Guido van Rossum18468821994-06-20 07:49:28 +00001978
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001979 if (!PyArg_ParseTuple(args, "O:split", &arg))
1980 return NULL;
1981 if (PyTclObject_Check(arg)) {
1982 Tcl_Obj *value = ((PyTclObject*)arg)->value;
1983 int objc;
1984 Tcl_Obj **objv;
1985 int i;
1986 if (Tcl_ListObjGetElements(Tkapp_Interp(self), value,
1987 &objc, &objv) == TCL_ERROR) {
1988 return FromObj(self, value);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00001989 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03001990 if (objc == 0)
1991 return PyUnicode_FromString("");
1992 if (objc == 1)
1993 return FromObj(self, objv[0]);
1994 if (!(v = PyTuple_New(objc)))
1995 return NULL;
1996 for (i = 0; i < objc; i++) {
1997 PyObject *s = FromObj(self, objv[i]);
1998 if (!s || PyTuple_SetItem(v, i, s)) {
1999 Py_DECREF(v);
2000 return NULL;
2001 }
2002 }
2003 return v;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002004 }
Serhiy Storchaka203eb312013-08-22 17:40:31 +03002005 if (PyTuple_Check(arg))
2006 return SplitObj(arg);
2007
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002008 if (!PyArg_ParseTuple(args, "et:split", "utf-8", &list))
2009 return NULL;
2010 v = Split(list);
2011 PyMem_Free(list);
2012 return v;
Guido van Rossum18468821994-06-20 07:49:28 +00002013}
2014
2015static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002016Tkapp_Merge(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002017{
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03002018 char *s;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002019 PyObject *res = NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002020
Andrew Svetlov9e892bb2012-03-31 19:36:39 +03002021 if (PyErr_WarnEx(PyExc_DeprecationWarning,
2022 "merge is deprecated and will be removed in 3.4",
2023 1) < 0)
2024 return 0;
2025
2026 s = Merge(args);
2027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002028 if (s) {
2029 res = PyUnicode_FromString(s);
2030 ckfree(s);
2031 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002032
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002033 return res;
Guido van Rossum18468821994-06-20 07:49:28 +00002034}
2035
Barry Warsawfa701a81997-01-16 00:15:11 +00002036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002037
Guido van Rossum18468821994-06-20 07:49:28 +00002038/** Tcl Command **/
2039
Guido van Rossum00d93061998-05-28 23:06:38 +00002040/* Client data struct */
2041typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002042 PyObject *self;
2043 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002044} PythonCmd_ClientData;
2045
2046static int
Fred Drake509d79a2000-07-08 04:04:38 +00002047PythonCmd_Error(Tcl_Interp *interp)
Guido van Rossum00d93061998-05-28 23:06:38 +00002048{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002049 errorInCmd = 1;
2050 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2051 LEAVE_PYTHON
2052 return TCL_ERROR;
Guido van Rossum00d93061998-05-28 23:06:38 +00002053}
2054
Guido van Rossum18468821994-06-20 07:49:28 +00002055/* This is the Tcl command that acts as a wrapper for Python
Barry Warsawfa701a81997-01-16 00:15:11 +00002056 * function or method.
2057 */
Guido van Rossum18468821994-06-20 07:49:28 +00002058static int
Fred Drake509d79a2000-07-08 04:04:38 +00002059PythonCmd(ClientData clientData, Tcl_Interp *interp, int argc, char *argv[])
Guido van Rossum18468821994-06-20 07:49:28 +00002060{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002061 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Brett Cannonb94767f2011-02-22 20:15:44 +00002062 PyObject *func, *arg, *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002063 int i, rv;
2064 Tcl_Obj *obj_res;
Guido van Rossum18468821994-06-20 07:49:28 +00002065
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002066 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002067
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002068 /* TBD: no error checking here since we know, via the
2069 * Tkapp_CreateCommand() that the client data is a two-tuple
2070 */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002071 func = data->func;
Guido van Rossum18468821994-06-20 07:49:28 +00002072
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002073 /* Create argument list (argv1, ..., argvN) */
2074 if (!(arg = PyTuple_New(argc - 1)))
2075 return PythonCmd_Error(interp);
Guido van Rossumd308e2b1994-07-07 09:25:12 +00002076
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002077 for (i = 0; i < (argc - 1); i++) {
2078 PyObject *s = PyUnicode_FromString(argv[i + 1]);
Kurt B. Kaisere1478062011-05-11 12:24:17 -04002079 if (!s) {
2080 /* Is Tk leaking 0xC080 in %A - a "modified" utf-8 null? */
2081 if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError) &&
2082 !strcmp(argv[i + 1], "\xC0\x80")) {
2083 PyErr_Clear();
2084 /* Convert to "strict" utf-8 null */
2085 s = PyUnicode_FromString("\0");
2086 } else {
2087 Py_DECREF(arg);
2088 return PythonCmd_Error(interp);
2089 }
2090 }
2091 if (PyTuple_SetItem(arg, i, s)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002092 Py_DECREF(arg);
2093 return PythonCmd_Error(interp);
2094 }
2095 }
2096 res = PyEval_CallObject(func, arg);
2097 Py_DECREF(arg);
Guido van Rossum18468821994-06-20 07:49:28 +00002098
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002099 if (res == NULL)
2100 return PythonCmd_Error(interp);
Guido van Rossum18468821994-06-20 07:49:28 +00002101
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002102 obj_res = AsObj(res);
2103 if (obj_res == NULL) {
2104 Py_DECREF(res);
2105 return PythonCmd_Error(interp);
2106 }
2107 else {
2108 Tcl_SetObjResult(interp, obj_res);
2109 rv = TCL_OK;
2110 }
Guido van Rossum2834b972000-10-06 16:58:26 +00002111
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002112 Py_DECREF(res);
Barry Warsawfa701a81997-01-16 00:15:11 +00002113
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002114 LEAVE_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002115
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002116 return rv;
Guido van Rossum18468821994-06-20 07:49:28 +00002117}
2118
2119static void
Fred Drake509d79a2000-07-08 04:04:38 +00002120PythonCmdDelete(ClientData clientData)
Guido van Rossum18468821994-06-20 07:49:28 +00002121{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002122 PythonCmd_ClientData *data = (PythonCmd_ClientData *)clientData;
Guido van Rossum00d93061998-05-28 23:06:38 +00002123
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002124 ENTER_PYTHON
2125 Py_XDECREF(data->self);
2126 Py_XDECREF(data->func);
2127 PyMem_DEL(data);
2128 LEAVE_PYTHON
Guido van Rossum18468821994-06-20 07:49:28 +00002129}
2130
Barry Warsawfa701a81997-01-16 00:15:11 +00002131
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002132
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002133
Benjamin Peterson5879d412009-03-30 14:51:56 +00002134#ifdef WITH_THREAD
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002135TCL_DECLARE_MUTEX(command_mutex)
2136
2137typedef struct CommandEvent{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002138 Tcl_Event ev;
2139 Tcl_Interp* interp;
2140 char *name;
2141 int create;
2142 int *status;
2143 ClientData *data;
2144 Tcl_Condition *done;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002145} CommandEvent;
2146
2147static int
2148Tkapp_CommandProc(CommandEvent *ev, int flags)
Guido van Rossum18468821994-06-20 07:49:28 +00002149{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002150 if (ev->create)
2151 *ev->status = Tcl_CreateCommand(
2152 ev->interp, ev->name, PythonCmd,
2153 ev->data, PythonCmdDelete) == NULL;
2154 else
2155 *ev->status = Tcl_DeleteCommand(ev->interp, ev->name);
2156 Tcl_MutexLock(&command_mutex);
2157 Tcl_ConditionNotify(ev->done);
2158 Tcl_MutexUnlock(&command_mutex);
2159 return 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002160}
Benjamin Peterson5879d412009-03-30 14:51:56 +00002161#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002162
2163static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002164Tkapp_CreateCommand(PyObject *selfptr, PyObject *args)
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002165{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002166 TkappObject *self = (TkappObject*)selfptr;
2167 PythonCmd_ClientData *data;
2168 char *cmdName;
2169 PyObject *func;
2170 int err;
Guido van Rossum35d43371997-08-02 00:09:09 +00002171
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002172 if (!PyArg_ParseTuple(args, "sO:createcommand", &cmdName, &func))
2173 return NULL;
2174 if (!PyCallable_Check(func)) {
2175 PyErr_SetString(PyExc_TypeError, "command not callable");
2176 return NULL;
2177 }
Guido van Rossum18468821994-06-20 07:49:28 +00002178
Martin v. Löwisa9656492003-03-30 08:44:58 +00002179#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002180 if (self->threaded && self->thread_id != Tcl_GetCurrentThread() &&
2181 !WaitForMainloop(self))
2182 return NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00002183#endif
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002184
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002185 data = PyMem_NEW(PythonCmd_ClientData, 1);
2186 if (!data)
2187 return PyErr_NoMemory();
2188 Py_INCREF(self);
2189 Py_INCREF(func);
2190 data->self = selfptr;
2191 data->func = func;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002192#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002193 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2194 Tcl_Condition cond = NULL;
2195 CommandEvent *ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2196 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2197 ev->interp = self->interp;
2198 ev->create = 1;
2199 ev->name = cmdName;
2200 ev->data = (ClientData)data;
2201 ev->status = &err;
2202 ev->done = &cond;
2203 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond, &command_mutex);
2204 Tcl_ConditionFinalize(&cond);
2205 }
2206 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002207#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002208 {
2209 ENTER_TCL
2210 err = Tcl_CreateCommand(
2211 Tkapp_Interp(self), cmdName, PythonCmd,
2212 (ClientData)data, PythonCmdDelete) == NULL;
2213 LEAVE_TCL
2214 }
2215 if (err) {
2216 PyErr_SetString(Tkinter_TclError, "can't create Tcl command");
2217 PyMem_DEL(data);
2218 return NULL;
2219 }
Guido van Rossum18468821994-06-20 07:49:28 +00002220
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002221 Py_INCREF(Py_None);
2222 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002223}
2224
Barry Warsawfa701a81997-01-16 00:15:11 +00002225
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002226
Guido van Rossum18468821994-06-20 07:49:28 +00002227static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002228Tkapp_DeleteCommand(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002229{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002230 TkappObject *self = (TkappObject*)selfptr;
2231 char *cmdName;
2232 int err;
Guido van Rossum18468821994-06-20 07:49:28 +00002233
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002234 if (!PyArg_ParseTuple(args, "s:deletecommand", &cmdName))
2235 return NULL;
Benjamin Peterson5879d412009-03-30 14:51:56 +00002236
2237#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002238 if (self->threaded && self->thread_id != Tcl_GetCurrentThread()) {
2239 Tcl_Condition cond = NULL;
2240 CommandEvent *ev;
2241 ev = (CommandEvent*)ckalloc(sizeof(CommandEvent));
2242 ev->ev.proc = (Tcl_EventProc*)Tkapp_CommandProc;
2243 ev->interp = self->interp;
2244 ev->create = 0;
2245 ev->name = cmdName;
2246 ev->status = &err;
2247 ev->done = &cond;
2248 Tkapp_ThreadSend(self, (Tcl_Event*)ev, &cond,
2249 &command_mutex);
2250 Tcl_ConditionFinalize(&cond);
2251 }
2252 else
Benjamin Peterson5879d412009-03-30 14:51:56 +00002253#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002254 {
2255 ENTER_TCL
2256 err = Tcl_DeleteCommand(self->interp, cmdName);
2257 LEAVE_TCL
2258 }
2259 if (err == -1) {
2260 PyErr_SetString(Tkinter_TclError, "can't delete Tcl command");
2261 return NULL;
2262 }
2263 Py_INCREF(Py_None);
2264 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002265}
2266
Barry Warsawfa701a81997-01-16 00:15:11 +00002267
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002268
Guido van Rossum00d93061998-05-28 23:06:38 +00002269#ifdef HAVE_CREATEFILEHANDLER
Guido van Rossum18468821994-06-20 07:49:28 +00002270/** File Handler **/
2271
Guido van Rossum00d93061998-05-28 23:06:38 +00002272typedef struct _fhcdata {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002273 PyObject *func;
2274 PyObject *file;
2275 int id;
2276 struct _fhcdata *next;
Guido van Rossum00d93061998-05-28 23:06:38 +00002277} FileHandler_ClientData;
2278
2279static FileHandler_ClientData *HeadFHCD;
2280
2281static FileHandler_ClientData *
Fred Drake509d79a2000-07-08 04:04:38 +00002282NewFHCD(PyObject *func, PyObject *file, int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002283{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002284 FileHandler_ClientData *p;
2285 p = PyMem_NEW(FileHandler_ClientData, 1);
2286 if (p != NULL) {
2287 Py_XINCREF(func);
2288 Py_XINCREF(file);
2289 p->func = func;
2290 p->file = file;
2291 p->id = id;
2292 p->next = HeadFHCD;
2293 HeadFHCD = p;
2294 }
2295 return p;
Guido van Rossum00d93061998-05-28 23:06:38 +00002296}
2297
2298static void
Fred Drake509d79a2000-07-08 04:04:38 +00002299DeleteFHCD(int id)
Guido van Rossum00d93061998-05-28 23:06:38 +00002300{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002301 FileHandler_ClientData *p, **pp;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002302
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002303 pp = &HeadFHCD;
2304 while ((p = *pp) != NULL) {
2305 if (p->id == id) {
2306 *pp = p->next;
2307 Py_XDECREF(p->func);
2308 Py_XDECREF(p->file);
2309 PyMem_DEL(p);
2310 }
2311 else
2312 pp = &p->next;
2313 }
Guido van Rossum00d93061998-05-28 23:06:38 +00002314}
2315
Guido van Rossuma597dde1995-01-10 20:56:29 +00002316static void
Fred Drake509d79a2000-07-08 04:04:38 +00002317FileHandler(ClientData clientData, int mask)
Guido van Rossum18468821994-06-20 07:49:28 +00002318{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002319 FileHandler_ClientData *data = (FileHandler_ClientData *)clientData;
2320 PyObject *func, *file, *arg, *res;
Guido van Rossum18468821994-06-20 07:49:28 +00002321
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002322 ENTER_PYTHON
2323 func = data->func;
2324 file = data->file;
Guido van Rossum18468821994-06-20 07:49:28 +00002325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002326 arg = Py_BuildValue("(Oi)", file, (long) mask);
2327 res = PyEval_CallObject(func, arg);
2328 Py_DECREF(arg);
Barry Warsawfa701a81997-01-16 00:15:11 +00002329
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002330 if (res == NULL) {
2331 errorInCmd = 1;
2332 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2333 }
2334 Py_XDECREF(res);
2335 LEAVE_PYTHON
Guido van Rossum9bb4fd61994-08-09 14:15:19 +00002336}
2337
Guido van Rossum18468821994-06-20 07:49:28 +00002338static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002339Tkapp_CreateFileHandler(PyObject *self, PyObject *args)
2340 /* args is (file, mask, func) */
Guido van Rossum18468821994-06-20 07:49:28 +00002341{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002342 FileHandler_ClientData *data;
2343 PyObject *file, *func;
2344 int mask, tfile;
Guido van Rossum18468821994-06-20 07:49:28 +00002345
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002346 if (!PyArg_ParseTuple(args, "OiO:createfilehandler",
2347 &file, &mask, &func))
2348 return NULL;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002349
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002350 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002351
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002352 tfile = PyObject_AsFileDescriptor(file);
2353 if (tfile < 0)
2354 return NULL;
2355 if (!PyCallable_Check(func)) {
2356 PyErr_SetString(PyExc_TypeError, "bad argument list");
2357 return NULL;
2358 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002359
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002360 data = NewFHCD(func, file, tfile);
2361 if (data == NULL)
2362 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002364 /* Ought to check for null Tcl_File object... */
2365 ENTER_TCL
2366 Tcl_CreateFileHandler(tfile, mask, FileHandler, (ClientData) data);
2367 LEAVE_TCL
2368 Py_INCREF(Py_None);
2369 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002370}
2371
2372static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002373Tkapp_DeleteFileHandler(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002374{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002375 PyObject *file;
2376 int tfile;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002377
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002378 if (!PyArg_ParseTuple(args, "O:deletefilehandler", &file))
2379 return NULL;
Neal Norwitz12e22172003-03-03 21:16:39 +00002380
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002381 CHECK_TCL_APPARTMENT;
Neal Norwitz12e22172003-03-03 21:16:39 +00002382
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002383 tfile = PyObject_AsFileDescriptor(file);
2384 if (tfile < 0)
2385 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002386
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002387 DeleteFHCD(tfile);
Guido van Rossum18468821994-06-20 07:49:28 +00002388
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002389 /* Ought to check for null Tcl_File object... */
2390 ENTER_TCL
2391 Tcl_DeleteFileHandler(tfile);
2392 LEAVE_TCL
2393 Py_INCREF(Py_None);
2394 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002395}
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002396#endif /* HAVE_CREATEFILEHANDLER */
Guido van Rossum18468821994-06-20 07:49:28 +00002397
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002398
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002399/**** Tktt Object (timer token) ****/
2400
Jeremy Hylton938ace62002-07-17 16:30:39 +00002401static PyTypeObject Tktt_Type;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002402
Guido van Rossum00d93061998-05-28 23:06:38 +00002403typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002404 PyObject_HEAD
2405 Tcl_TimerToken token;
2406 PyObject *func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002407} TkttObject;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002408
2409static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002410Tktt_DeleteTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002411{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002412 TkttObject *v = (TkttObject *)self;
2413 PyObject *func = v->func;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002414
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002415 if (!PyArg_ParseTuple(args, ":deletetimerhandler"))
2416 return NULL;
2417 if (v->token != NULL) {
2418 Tcl_DeleteTimerHandler(v->token);
2419 v->token = NULL;
2420 }
2421 if (func != NULL) {
2422 v->func = NULL;
2423 Py_DECREF(func);
2424 Py_DECREF(v); /* See Tktt_New() */
2425 }
2426 Py_INCREF(Py_None);
2427 return Py_None;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002428}
2429
2430static PyMethodDef Tktt_methods[] =
2431{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002432 {"deletetimerhandler", Tktt_DeleteTimerHandler, METH_VARARGS},
2433 {NULL, NULL}
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002434};
2435
2436static TkttObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002437Tktt_New(PyObject *func)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002438{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002439 TkttObject *v;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002440
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002441 v = PyObject_New(TkttObject, &Tktt_Type);
2442 if (v == NULL)
2443 return NULL;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002444
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002445 Py_INCREF(func);
2446 v->token = NULL;
2447 v->func = func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002448
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002449 /* Extra reference, deleted when called or when handler is deleted */
2450 Py_INCREF(v);
2451 return v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002452}
2453
2454static void
Fred Drake509d79a2000-07-08 04:04:38 +00002455Tktt_Dealloc(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002456{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002457 TkttObject *v = (TkttObject *)self;
2458 PyObject *func = v->func;
Guido van Rossum00d93061998-05-28 23:06:38 +00002459
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002460 Py_XDECREF(func);
Guido van Rossum00d93061998-05-28 23:06:38 +00002461
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002462 PyObject_Del(self);
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002463}
2464
Guido van Rossum597ac201998-05-12 14:36:19 +00002465static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002466Tktt_Repr(PyObject *self)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002467{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002468 TkttObject *v = (TkttObject *)self;
Victor Stinner6ced7c42011-03-21 18:15:42 +01002469 return PyUnicode_FromFormat("<tktimertoken at %p%s>",
2470 v,
2471 v->func == NULL ? ", handler deleted" : "");
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002472}
2473
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002474static PyTypeObject Tktt_Type =
2475{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002476 PyVarObject_HEAD_INIT(NULL, 0)
2477 "tktimertoken", /*tp_name */
2478 sizeof(TkttObject), /*tp_basicsize */
2479 0, /*tp_itemsize */
2480 Tktt_Dealloc, /*tp_dealloc */
2481 0, /*tp_print */
2482 0, /*tp_getattr */
2483 0, /*tp_setattr */
2484 0, /*tp_reserved */
2485 Tktt_Repr, /*tp_repr */
2486 0, /*tp_as_number */
2487 0, /*tp_as_sequence */
2488 0, /*tp_as_mapping */
2489 0, /*tp_hash */
2490 0, /*tp_call*/
2491 0, /*tp_str*/
2492 0, /*tp_getattro*/
2493 0, /*tp_setattro*/
2494 0, /*tp_as_buffer*/
2495 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2496 0, /*tp_doc*/
2497 0, /*tp_traverse*/
2498 0, /*tp_clear*/
2499 0, /*tp_richcompare*/
2500 0, /*tp_weaklistoffset*/
2501 0, /*tp_iter*/
2502 0, /*tp_iternext*/
2503 Tktt_methods, /*tp_methods*/
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002504};
2505
Barry Warsawfa701a81997-01-16 00:15:11 +00002506
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002507
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002508/** Timer Handler **/
2509
2510static void
Fred Drake509d79a2000-07-08 04:04:38 +00002511TimerHandler(ClientData clientData)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002512{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002513 TkttObject *v = (TkttObject *)clientData;
2514 PyObject *func = v->func;
2515 PyObject *res;
Guido van Rossum00d93061998-05-28 23:06:38 +00002516
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002517 if (func == NULL)
2518 return;
Guido van Rossum00d93061998-05-28 23:06:38 +00002519
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002520 v->func = NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00002521
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002522 ENTER_PYTHON
Guido van Rossum00d93061998-05-28 23:06:38 +00002523
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002524 res = PyEval_CallObject(func, NULL);
2525 Py_DECREF(func);
2526 Py_DECREF(v); /* See Tktt_New() */
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002527
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002528 if (res == NULL) {
2529 errorInCmd = 1;
2530 PyErr_Fetch(&excInCmd, &valInCmd, &trbInCmd);
2531 }
2532 else
2533 Py_DECREF(res);
Guido van Rossum00d93061998-05-28 23:06:38 +00002534
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002535 LEAVE_PYTHON
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002536}
2537
2538static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002539Tkapp_CreateTimerHandler(PyObject *self, PyObject *args)
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002540{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002541 int milliseconds;
2542 PyObject *func;
2543 TkttObject *v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002544
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002545 if (!PyArg_ParseTuple(args, "iO:createtimerhandler",
2546 &milliseconds, &func))
2547 return NULL;
2548 if (!PyCallable_Check(func)) {
2549 PyErr_SetString(PyExc_TypeError, "bad argument list");
2550 return NULL;
2551 }
Martin v. Löwis7f134892003-03-03 10:40:01 +00002552
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002553 CHECK_TCL_APPARTMENT;
Martin v. Löwis7f134892003-03-03 10:40:01 +00002554
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002555 v = Tktt_New(func);
2556 if (v) {
2557 v->token = Tcl_CreateTimerHandler(milliseconds, TimerHandler,
2558 (ClientData)v);
2559 }
Barry Warsawfa701a81997-01-16 00:15:11 +00002560
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002561 return (PyObject *) v;
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002562}
2563
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002564
Guido van Rossum18468821994-06-20 07:49:28 +00002565/** Event Loop **/
2566
Guido van Rossum18468821994-06-20 07:49:28 +00002567static PyObject *
Thomas Wouters73e5a5b2006-06-08 15:35:45 +00002568Tkapp_MainLoop(PyObject *selfptr, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002569{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002570 int threshold = 0;
2571 TkappObject *self = (TkappObject*)selfptr;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002572#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002573 PyThreadState *tstate = PyThreadState_Get();
Guido van Rossumdc1adab1998-10-09 20:51:18 +00002574#endif
Guido van Rossumf34cadd1994-11-10 22:50:21 +00002575
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002576 if (!PyArg_ParseTuple(args, "|i:mainloop", &threshold))
2577 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002578
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002579 CHECK_TCL_APPARTMENT;
2580 self->dispatching = 1;
Martin v. Löwisb5bfb9f2002-12-12 17:07:58 +00002581
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002582 quitMainLoop = 0;
2583 while (Tk_GetNumMainWindows() > threshold &&
2584 !quitMainLoop &&
2585 !errorInCmd)
2586 {
2587 int result;
Guido van Rossum00d93061998-05-28 23:06:38 +00002588
2589#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002590 if (self->threaded) {
2591 /* Allow other Python threads to run. */
2592 ENTER_TCL
2593 result = Tcl_DoOneEvent(0);
2594 LEAVE_TCL
2595 }
2596 else {
2597 Py_BEGIN_ALLOW_THREADS
2598 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
2599 tcl_tstate = tstate;
2600 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
2601 tcl_tstate = NULL;
2602 if(tcl_lock)PyThread_release_lock(tcl_lock);
2603 if (result == 0)
2604 Sleep(Tkinter_busywaitinterval);
2605 Py_END_ALLOW_THREADS
2606 }
Guido van Rossum5b020781997-08-19 01:00:50 +00002607#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002608 result = Tcl_DoOneEvent(0);
Guido van Rossum5b020781997-08-19 01:00:50 +00002609#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00002610
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002611 if (PyErr_CheckSignals() != 0) {
2612 self->dispatching = 0;
2613 return NULL;
2614 }
2615 if (result < 0)
2616 break;
2617 }
2618 self->dispatching = 0;
2619 quitMainLoop = 0;
Guido van Rossum18468821994-06-20 07:49:28 +00002620
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002621 if (errorInCmd) {
2622 errorInCmd = 0;
2623 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
2624 excInCmd = valInCmd = trbInCmd = NULL;
2625 return NULL;
2626 }
2627 Py_INCREF(Py_None);
2628 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002629}
2630
2631static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002632Tkapp_DoOneEvent(PyObject *self, PyObject *args)
Guido van Rossum062cfb01995-01-10 17:42:51 +00002633{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002634 int flags = 0;
2635 int rv;
Guido van Rossum062cfb01995-01-10 17:42:51 +00002636
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002637 if (!PyArg_ParseTuple(args, "|i:dooneevent", &flags))
2638 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002639
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002640 ENTER_TCL
2641 rv = Tcl_DoOneEvent(flags);
2642 LEAVE_TCL
2643 return Py_BuildValue("i", rv);
Guido van Rossum062cfb01995-01-10 17:42:51 +00002644}
2645
2646static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002647Tkapp_Quit(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002648{
2649
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002650 if (!PyArg_ParseTuple(args, ":quit"))
2651 return NULL;
Barry Warsawfa701a81997-01-16 00:15:11 +00002652
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002653 quitMainLoop = 1;
2654 Py_INCREF(Py_None);
2655 return Py_None;
Guido van Rossum18468821994-06-20 07:49:28 +00002656}
2657
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002658static PyObject *
Fred Drake509d79a2000-07-08 04:04:38 +00002659Tkapp_InterpAddr(PyObject *self, PyObject *args)
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002660{
2661
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002662 if (!PyArg_ParseTuple(args, ":interpaddr"))
2663 return NULL;
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002664
Victor Stinnere1040e22013-09-05 00:22:24 +02002665 return PyLong_FromVoidPtr(Tkapp_Interp(self));
Guido van Rossum9d1b7ae1998-04-29 16:17:01 +00002666}
2667
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002668static PyObject *
David Aschere2b4b322004-02-18 05:59:53 +00002669Tkapp_TkInit(PyObject *self, PyObject *args)
2670{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002671 Tcl_Interp *interp = Tkapp_Interp(self);
2672 const char * _tk_exists = NULL;
2673 int err;
David Aschere2b4b322004-02-18 05:59:53 +00002674
Guilherme Polob681df42009-02-09 22:33:59 +00002675#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002676 /* Up to Tk 8.4.13, Tk_Init deadlocks on the second call when the
2677 * first call failed.
2678 * To avoid the deadlock, we just refuse the second call through
2679 * a static variable.
2680 */
2681 if (tk_load_failed) {
2682 PyErr_SetString(Tkinter_TclError, TKINTER_LOADTK_ERRMSG);
2683 return NULL;
2684 }
Guilherme Polob681df42009-02-09 22:33:59 +00002685#endif
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002686
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002687 /* We want to guard against calling Tk_Init() multiple times */
2688 CHECK_TCL_APPARTMENT;
2689 ENTER_TCL
2690 err = Tcl_Eval(Tkapp_Interp(self), "info exists tk_version");
2691 ENTER_OVERLAP
2692 if (err == TCL_ERROR) {
2693 /* This sets an exception, but we cannot return right
2694 away because we need to exit the overlap first. */
2695 Tkinter_Error(self);
2696 } else {
2697 _tk_exists = Tkapp_Result(self);
2698 }
2699 LEAVE_OVERLAP_TCL
2700 if (err == TCL_ERROR) {
2701 return NULL;
2702 }
2703 if (_tk_exists == NULL || strcmp(_tk_exists, "1") != 0) {
2704 if (Tk_Init(interp) == TCL_ERROR) {
2705 PyErr_SetString(Tkinter_TclError, Tcl_GetStringResult(Tkapp_Interp(self)));
Guilherme Polob681df42009-02-09 22:33:59 +00002706#ifdef TKINTER_PROTECT_LOADTK
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002707 tk_load_failed = 1;
Guilherme Polob681df42009-02-09 22:33:59 +00002708#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002709 return NULL;
2710 }
2711 }
2712 Py_INCREF(Py_None);
2713 return Py_None;
David Aschere2b4b322004-02-18 05:59:53 +00002714}
Barry Warsawfa701a81997-01-16 00:15:11 +00002715
Martin v. Löwisffad6332002-11-26 09:28:05 +00002716static PyObject *
2717Tkapp_WantObjects(PyObject *self, PyObject *args)
2718{
2719
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002720 int wantobjects = -1;
2721 if (!PyArg_ParseTuple(args, "|i:wantobjects", &wantobjects))
2722 return NULL;
2723 if (wantobjects == -1)
2724 return PyBool_FromLong(((TkappObject*)self)->wantobjects);
2725 ((TkappObject*)self)->wantobjects = wantobjects;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002726
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002727 Py_INCREF(Py_None);
2728 return Py_None;
Martin v. Löwisffad6332002-11-26 09:28:05 +00002729}
2730
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002731static PyObject *
2732Tkapp_WillDispatch(PyObject *self, PyObject *args)
2733{
2734
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002735 ((TkappObject*)self)->dispatching = 1;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002736
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002737 Py_INCREF(Py_None);
2738 return Py_None;
Martin v. Löwis5b26abb2002-12-28 09:23:09 +00002739}
Martin v. Löwisffad6332002-11-26 09:28:05 +00002740
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002741
Guido van Rossum18468821994-06-20 07:49:28 +00002742/**** Tkapp Method List ****/
2743
2744static PyMethodDef Tkapp_methods[] =
2745{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002746 {"willdispatch", Tkapp_WillDispatch, METH_NOARGS},
2747 {"wantobjects", Tkapp_WantObjects, METH_VARARGS},
2748 {"call", Tkapp_Call, METH_VARARGS},
2749 {"globalcall", Tkapp_GlobalCall, METH_VARARGS},
2750 {"eval", Tkapp_Eval, METH_VARARGS},
2751 {"globaleval", Tkapp_GlobalEval, METH_VARARGS},
2752 {"evalfile", Tkapp_EvalFile, METH_VARARGS},
2753 {"record", Tkapp_Record, METH_VARARGS},
2754 {"adderrorinfo", Tkapp_AddErrorInfo, METH_VARARGS},
2755 {"setvar", Tkapp_SetVar, METH_VARARGS},
2756 {"globalsetvar", Tkapp_GlobalSetVar, METH_VARARGS},
2757 {"getvar", Tkapp_GetVar, METH_VARARGS},
2758 {"globalgetvar", Tkapp_GlobalGetVar, METH_VARARGS},
2759 {"unsetvar", Tkapp_UnsetVar, METH_VARARGS},
2760 {"globalunsetvar", Tkapp_GlobalUnsetVar, METH_VARARGS},
2761 {"getint", Tkapp_GetInt, METH_VARARGS},
2762 {"getdouble", Tkapp_GetDouble, METH_VARARGS},
2763 {"getboolean", Tkapp_GetBoolean, METH_VARARGS},
2764 {"exprstring", Tkapp_ExprString, METH_VARARGS},
2765 {"exprlong", Tkapp_ExprLong, METH_VARARGS},
2766 {"exprdouble", Tkapp_ExprDouble, METH_VARARGS},
2767 {"exprboolean", Tkapp_ExprBoolean, METH_VARARGS},
2768 {"splitlist", Tkapp_SplitList, METH_VARARGS},
2769 {"split", Tkapp_Split, METH_VARARGS},
2770 {"merge", Tkapp_Merge, METH_VARARGS},
2771 {"createcommand", Tkapp_CreateCommand, METH_VARARGS},
2772 {"deletecommand", Tkapp_DeleteCommand, METH_VARARGS},
Guido van Rossum0d2390c1997-08-14 19:57:07 +00002773#ifdef HAVE_CREATEFILEHANDLER
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002774 {"createfilehandler", Tkapp_CreateFileHandler, METH_VARARGS},
2775 {"deletefilehandler", Tkapp_DeleteFileHandler, METH_VARARGS},
Guido van Rossum02c04671997-08-07 00:12:22 +00002776#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002777 {"createtimerhandler", Tkapp_CreateTimerHandler, METH_VARARGS},
2778 {"mainloop", Tkapp_MainLoop, METH_VARARGS},
2779 {"dooneevent", Tkapp_DoOneEvent, METH_VARARGS},
2780 {"quit", Tkapp_Quit, METH_VARARGS},
2781 {"interpaddr", Tkapp_InterpAddr, METH_VARARGS},
2782 {"loadtk", Tkapp_TkInit, METH_NOARGS},
2783 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00002784};
2785
Barry Warsawfa701a81997-01-16 00:15:11 +00002786
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002787
Guido van Rossum18468821994-06-20 07:49:28 +00002788/**** Tkapp Type Methods ****/
2789
2790static void
Fred Drake509d79a2000-07-08 04:04:38 +00002791Tkapp_Dealloc(PyObject *self)
Guido van Rossum18468821994-06-20 07:49:28 +00002792{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002793 /*CHECK_TCL_APPARTMENT;*/
2794 ENTER_TCL
2795 Tcl_DeleteInterp(Tkapp_Interp(self));
2796 LEAVE_TCL
2797 PyObject_Del(self);
2798 DisableEventHook();
Guido van Rossum18468821994-06-20 07:49:28 +00002799}
2800
Guido van Rossum18468821994-06-20 07:49:28 +00002801static PyTypeObject Tkapp_Type =
2802{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002803 PyVarObject_HEAD_INIT(NULL, 0)
2804 "tkapp", /*tp_name */
2805 sizeof(TkappObject), /*tp_basicsize */
2806 0, /*tp_itemsize */
2807 Tkapp_Dealloc, /*tp_dealloc */
2808 0, /*tp_print */
2809 0, /*tp_getattr */
2810 0, /*tp_setattr */
2811 0, /*tp_reserved */
2812 0, /*tp_repr */
2813 0, /*tp_as_number */
2814 0, /*tp_as_sequence */
2815 0, /*tp_as_mapping */
2816 0, /*tp_hash */
2817 0, /*tp_call*/
2818 0, /*tp_str*/
2819 0, /*tp_getattro*/
2820 0, /*tp_setattro*/
2821 0, /*tp_as_buffer*/
2822 Py_TPFLAGS_DEFAULT, /*tp_flags*/
2823 0, /*tp_doc*/
2824 0, /*tp_traverse*/
2825 0, /*tp_clear*/
2826 0, /*tp_richcompare*/
2827 0, /*tp_weaklistoffset*/
2828 0, /*tp_iter*/
2829 0, /*tp_iternext*/
2830 Tkapp_methods, /*tp_methods*/
Guido van Rossum18468821994-06-20 07:49:28 +00002831};
2832
Barry Warsawfa701a81997-01-16 00:15:11 +00002833
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002834
Guido van Rossum18468821994-06-20 07:49:28 +00002835/**** Tkinter Module ****/
2836
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002837typedef struct {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002838 PyObject* tuple;
2839 int size; /* current size */
2840 int maxsize; /* allocated size */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002841} FlattenContext;
2842
2843static int
2844_bump(FlattenContext* context, int size)
2845{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002846 /* expand tuple to hold (at least) size new items.
2847 return true if successful, false if an exception was raised */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002848
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002849 int maxsize = context->maxsize * 2;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002850
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002851 if (maxsize < context->size + size)
2852 maxsize = context->size + size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002853
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002854 context->maxsize = maxsize;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002855
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002856 return _PyTuple_Resize(&context->tuple, maxsize) >= 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002857}
2858
2859static int
Andrew M. Kuchling288e97b2000-06-19 00:55:09 +00002860_flatten1(FlattenContext* context, PyObject* item, int depth)
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002861{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002862 /* add tuple or list to argument tuple (recursively) */
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002863
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002864 int i, size;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002865
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002866 if (depth > 1000) {
2867 PyErr_SetString(PyExc_ValueError,
2868 "nesting too deep in _flatten");
2869 return 0;
2870 } else if (PyList_Check(item)) {
2871 size = PyList_GET_SIZE(item);
2872 /* preallocate (assume no nesting) */
2873 if (context->size + size > context->maxsize &&
2874 !_bump(context, size))
2875 return 0;
2876 /* copy items to output tuple */
2877 for (i = 0; i < size; i++) {
2878 PyObject *o = PyList_GET_ITEM(item, i);
2879 if (PyList_Check(o) || PyTuple_Check(o)) {
2880 if (!_flatten1(context, o, depth + 1))
2881 return 0;
2882 } else if (o != Py_None) {
2883 if (context->size + 1 > context->maxsize &&
2884 !_bump(context, 1))
2885 return 0;
2886 Py_INCREF(o);
2887 PyTuple_SET_ITEM(context->tuple,
2888 context->size++, o);
2889 }
2890 }
2891 } else if (PyTuple_Check(item)) {
2892 /* same, for tuples */
2893 size = PyTuple_GET_SIZE(item);
2894 if (context->size + size > context->maxsize &&
2895 !_bump(context, size))
2896 return 0;
2897 for (i = 0; i < size; i++) {
2898 PyObject *o = PyTuple_GET_ITEM(item, i);
2899 if (PyList_Check(o) || PyTuple_Check(o)) {
2900 if (!_flatten1(context, o, depth + 1))
2901 return 0;
2902 } else if (o != Py_None) {
2903 if (context->size + 1 > context->maxsize &&
2904 !_bump(context, 1))
2905 return 0;
2906 Py_INCREF(o);
2907 PyTuple_SET_ITEM(context->tuple,
2908 context->size++, o);
2909 }
2910 }
2911 } else {
2912 PyErr_SetString(PyExc_TypeError, "argument must be sequence");
2913 return 0;
2914 }
2915 return 1;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002916}
2917
2918static PyObject *
2919Tkinter_Flatten(PyObject* self, PyObject* args)
2920{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002921 FlattenContext context;
2922 PyObject* item;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002923
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002924 if (!PyArg_ParseTuple(args, "O:_flatten", &item))
2925 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002926
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002927 context.maxsize = PySequence_Size(item);
2928 if (context.maxsize < 0)
2929 return NULL;
2930 if (context.maxsize == 0)
2931 return PyTuple_New(0);
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002932
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002933 context.tuple = PyTuple_New(context.maxsize);
2934 if (!context.tuple)
2935 return NULL;
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002936
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002937 context.size = 0;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002938
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002939 if (!_flatten1(&context, item,0))
2940 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002941
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002942 if (_PyTuple_Resize(&context.tuple, context.size))
2943 return NULL;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002944
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002945 return context.tuple;
Andrew M. Kuchlinge475e702000-06-18 18:45:50 +00002946}
2947
Guido van Rossum18468821994-06-20 07:49:28 +00002948static PyObject *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00002949Tkinter_Create(PyObject *self, PyObject *args)
Guido van Rossum18468821994-06-20 07:49:28 +00002950{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002951 char *screenName = NULL;
2952 char *baseName = NULL; /* XXX this is not used anymore;
2953 try getting rid of it. */
2954 char *className = NULL;
2955 int interactive = 0;
2956 int wantobjects = 0;
2957 int wantTk = 1; /* If false, then Tk_Init() doesn't get called */
2958 int sync = 0; /* pass -sync to wish */
2959 char *use = NULL; /* pass -use to wish */
Guido van Rossum18468821994-06-20 07:49:28 +00002960
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002961 className = "Tk";
Guido van Rossum82c0dfa2007-11-21 20:09:18 +00002962
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002963 if (!PyArg_ParseTuple(args, "|zssiiiiz:create",
2964 &screenName, &baseName, &className,
2965 &interactive, &wantobjects, &wantTk,
2966 &sync, &use))
2967 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00002968
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002969 return (PyObject *) Tkapp_New(screenName, className,
2970 interactive, wantobjects, wantTk,
2971 sync, use);
Guido van Rossum18468821994-06-20 07:49:28 +00002972}
2973
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002974static PyObject *
2975Tkinter_setbusywaitinterval(PyObject *self, PyObject *args)
2976{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00002977 int new_val;
2978 if (!PyArg_ParseTuple(args, "i:setbusywaitinterval", &new_val))
2979 return NULL;
2980 if (new_val < 0) {
2981 PyErr_SetString(PyExc_ValueError,
2982 "busywaitinterval must be >= 0");
2983 return NULL;
2984 }
2985 Tkinter_busywaitinterval = new_val;
2986 Py_INCREF(Py_None);
2987 return Py_None;
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00002988}
2989
2990static char setbusywaitinterval_doc[] =
2991"setbusywaitinterval(n) -> None\n\
2992\n\
2993Set the busy-wait interval in milliseconds between successive\n\
2994calls to Tcl_DoOneEvent in a threaded Python interpreter.\n\
2995It should be set to a divisor of the maximum time between\n\
2996frames in an animation.";
2997
2998static PyObject *
2999Tkinter_getbusywaitinterval(PyObject *self, PyObject *args)
3000{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003001 return PyLong_FromLong(Tkinter_busywaitinterval);
Martin v. Löwis28e9ce92003-05-09 08:19:48 +00003002}
3003
3004static char getbusywaitinterval_doc[] =
3005"getbusywaitinterval() -> int\n\
3006\n\
3007Return the current busy-wait interval between successive\n\
3008calls to Tcl_DoOneEvent in a threaded Python interpreter.";
3009
Guido van Rossum18468821994-06-20 07:49:28 +00003010static PyMethodDef moduleMethods[] =
3011{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003012 {"_flatten", Tkinter_Flatten, METH_VARARGS},
3013 {"create", Tkinter_Create, METH_VARARGS},
3014 {"setbusywaitinterval",Tkinter_setbusywaitinterval, METH_VARARGS,
3015 setbusywaitinterval_doc},
3016 {"getbusywaitinterval",(PyCFunction)Tkinter_getbusywaitinterval,
3017 METH_NOARGS, getbusywaitinterval_doc},
3018 {NULL, NULL}
Guido van Rossum18468821994-06-20 07:49:28 +00003019};
3020
Guido van Rossum7bf15641998-05-22 18:28:17 +00003021#ifdef WAIT_FOR_STDIN
Guido van Rossum7bf15641998-05-22 18:28:17 +00003022
3023static int stdin_ready = 0;
3024
Guido van Rossumad4db171998-06-13 13:56:28 +00003025#ifndef MS_WINDOWS
Guido van Rossum7bf15641998-05-22 18:28:17 +00003026static void
Fred Drake509d79a2000-07-08 04:04:38 +00003027MyFileProc(void *clientData, int mask)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003028{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003029 stdin_ready = 1;
Guido van Rossum7bf15641998-05-22 18:28:17 +00003030}
Guido van Rossumad4db171998-06-13 13:56:28 +00003031#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003032
Martin v. Löwisa9656492003-03-30 08:44:58 +00003033#ifdef WITH_THREAD
Guido van Rossum00d93061998-05-28 23:06:38 +00003034static PyThreadState *event_tstate = NULL;
Martin v. Löwisa9656492003-03-30 08:44:58 +00003035#endif
Guido van Rossum0e8457c1997-10-07 18:51:41 +00003036
Guido van Rossum18468821994-06-20 07:49:28 +00003037static int
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003038EventHook(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003039{
Guido van Rossumad4db171998-06-13 13:56:28 +00003040#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003041 int tfile;
Guido van Rossumad4db171998-06-13 13:56:28 +00003042#endif
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003043#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003044 PyEval_RestoreThread(event_tstate);
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003045#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003046 stdin_ready = 0;
3047 errorInCmd = 0;
Guido van Rossumad4db171998-06-13 13:56:28 +00003048#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003049 tfile = fileno(stdin);
3050 Tcl_CreateFileHandler(tfile, TCL_READABLE, MyFileProc, NULL);
Guido van Rossumad4db171998-06-13 13:56:28 +00003051#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003052 while (!errorInCmd && !stdin_ready) {
3053 int result;
Guido van Rossumad4db171998-06-13 13:56:28 +00003054#ifdef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003055 if (_kbhit()) {
3056 stdin_ready = 1;
3057 break;
3058 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003059#endif
3060#if defined(WITH_THREAD) || defined(MS_WINDOWS)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003061 Py_BEGIN_ALLOW_THREADS
3062 if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1);
3063 tcl_tstate = event_tstate;
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003064
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003065 result = Tcl_DoOneEvent(TCL_DONT_WAIT);
Guido van Rossumdc1adab1998-10-09 20:51:18 +00003066
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003067 tcl_tstate = NULL;
3068 if(tcl_lock)PyThread_release_lock(tcl_lock);
3069 if (result == 0)
3070 Sleep(Tkinter_busywaitinterval);
3071 Py_END_ALLOW_THREADS
Guido van Rossum00d93061998-05-28 23:06:38 +00003072#else
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003073 result = Tcl_DoOneEvent(0);
Guido van Rossum7bf15641998-05-22 18:28:17 +00003074#endif
Guido van Rossum00d93061998-05-28 23:06:38 +00003075
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003076 if (result < 0)
3077 break;
3078 }
Guido van Rossumad4db171998-06-13 13:56:28 +00003079#ifndef MS_WINDOWS
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003080 Tcl_DeleteFileHandler(tfile);
Guido van Rossumad4db171998-06-13 13:56:28 +00003081#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003082 if (errorInCmd) {
3083 errorInCmd = 0;
3084 PyErr_Restore(excInCmd, valInCmd, trbInCmd);
3085 excInCmd = valInCmd = trbInCmd = NULL;
3086 PyErr_Print();
3087 }
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003088#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003089 PyEval_SaveThread();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003090#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003091 return 0;
Guido van Rossum18468821994-06-20 07:49:28 +00003092}
Guido van Rossum18468821994-06-20 07:49:28 +00003093
Guido van Rossum00d93061998-05-28 23:06:38 +00003094#endif
3095
Guido van Rossum7bf15641998-05-22 18:28:17 +00003096static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003097EnableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003098{
Guido van Rossum00d93061998-05-28 23:06:38 +00003099#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003100 if (PyOS_InputHook == NULL) {
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003101#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003102 event_tstate = PyThreadState_Get();
Guido van Rossume9bc62d1998-11-17 03:45:24 +00003103#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003104 PyOS_InputHook = EventHook;
3105 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003106#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003107}
3108
3109static void
Thomas Woutersf3f33dc2000-07-21 06:00:07 +00003110DisableEventHook(void)
Guido van Rossum7bf15641998-05-22 18:28:17 +00003111{
Guido van Rossum00d93061998-05-28 23:06:38 +00003112#ifdef WAIT_FOR_STDIN
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003113 if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) {
3114 PyOS_InputHook = NULL;
3115 }
Guido van Rossum00d93061998-05-28 23:06:38 +00003116#endif
Guido van Rossum7bf15641998-05-22 18:28:17 +00003117}
3118
Barry Warsawfa701a81997-01-16 00:15:11 +00003119
3120/* all errors will be checked in one fell swoop in init_tkinter() */
3121static void
Fred Drake509d79a2000-07-08 04:04:38 +00003122ins_long(PyObject *d, char *name, long val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003123{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003124 PyObject *v = PyLong_FromLong(val);
3125 if (v) {
3126 PyDict_SetItemString(d, name, v);
3127 Py_DECREF(v);
3128 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003129}
3130static void
Fred Drake509d79a2000-07-08 04:04:38 +00003131ins_string(PyObject *d, char *name, char *val)
Barry Warsawfa701a81997-01-16 00:15:11 +00003132{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003133 PyObject *v = PyUnicode_FromString(val);
3134 if (v) {
3135 PyDict_SetItemString(d, name, v);
3136 Py_DECREF(v);
3137 }
Barry Warsawfa701a81997-01-16 00:15:11 +00003138}
3139
3140
Martin v. Löwis1a214512008-06-11 05:26:20 +00003141static struct PyModuleDef _tkintermodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003142 PyModuleDef_HEAD_INIT,
3143 "_tkinter",
3144 NULL,
3145 -1,
3146 moduleMethods,
3147 NULL,
3148 NULL,
3149 NULL,
3150 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +00003151};
3152
Mark Hammond62b1ab12002-07-23 06:31:15 +00003153PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +00003154PyInit__tkinter(void)
Guido van Rossum18468821994-06-20 07:49:28 +00003155{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003156 PyObject *m, *d, *uexe, *cexe;
Guido van Rossum18468821994-06-20 07:49:28 +00003157
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003158 if (PyType_Ready(&Tkapp_Type) < 0)
3159 return NULL;
Guido van Rossum00d93061998-05-28 23:06:38 +00003160
3161#ifdef WITH_THREAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003162 tcl_lock = PyThread_allocate_lock();
Guido van Rossum00d93061998-05-28 23:06:38 +00003163#endif
Guido van Rossumae92f011996-08-21 19:03:36 +00003164
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003165 m = PyModule_Create(&_tkintermodule);
3166 if (m == NULL)
3167 return NULL;
Guido van Rossum18468821994-06-20 07:49:28 +00003168
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003169 d = PyModule_GetDict(m);
3170 Tkinter_TclError = PyErr_NewException("_tkinter.TclError", NULL, NULL);
3171 PyDict_SetItemString(d, "TclError", Tkinter_TclError);
Guido van Rossum18468821994-06-20 07:49:28 +00003172
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003173 ins_long(d, "READABLE", TCL_READABLE);
3174 ins_long(d, "WRITABLE", TCL_WRITABLE);
3175 ins_long(d, "EXCEPTION", TCL_EXCEPTION);
3176 ins_long(d, "WINDOW_EVENTS", TCL_WINDOW_EVENTS);
3177 ins_long(d, "FILE_EVENTS", TCL_FILE_EVENTS);
3178 ins_long(d, "TIMER_EVENTS", TCL_TIMER_EVENTS);
3179 ins_long(d, "IDLE_EVENTS", TCL_IDLE_EVENTS);
3180 ins_long(d, "ALL_EVENTS", TCL_ALL_EVENTS);
3181 ins_long(d, "DONT_WAIT", TCL_DONT_WAIT);
3182 ins_string(d, "TK_VERSION", TK_VERSION);
3183 ins_string(d, "TCL_VERSION", TCL_VERSION);
Guido van Rossum18468821994-06-20 07:49:28 +00003184
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003185 PyDict_SetItemString(d, "TkappType", (PyObject *)&Tkapp_Type);
Guido van Rossum00d93061998-05-28 23:06:38 +00003186
Jesus Ceaef86d122012-07-19 21:18:07 +02003187 if (PyType_Ready(&Tktt_Type) < 0) {
3188 Py_DECREF(m);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003189 return NULL;
Jesus Ceaef86d122012-07-19 21:18:07 +02003190 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003191 PyDict_SetItemString(d, "TkttType", (PyObject *)&Tktt_Type);
Guido van Rossum83551bf1997-09-13 00:44:23 +00003192
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003193 Py_TYPE(&PyTclObject_Type) = &PyType_Type;
3194 PyDict_SetItemString(d, "Tcl_Obj", (PyObject *)&PyTclObject_Type);
Jack Jansencb852442001-12-09 23:15:56 +00003195
3196#ifdef TK_AQUA
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003197 /* Tk_MacOSXSetupTkNotifier must be called before Tcl's subsystems
3198 * start waking up. Note that Tcl_FindExecutable will do this, this
3199 * code must be above it! The original warning from
3200 * tkMacOSXAppInit.c is copied below.
3201 *
3202 * NB - You have to swap in the Tk Notifier BEFORE you start up the
3203 * Tcl interpreter for now. It probably should work to do this
3204 * in the other order, but for now it doesn't seem to.
3205 *
3206 */
3207 Tk_MacOSXSetupTkNotifier();
Jack Jansencb852442001-12-09 23:15:56 +00003208#endif
3209
3210
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003211 /* This helps the dynamic loader; in Unicode aware Tcl versions
3212 it also helps Tcl find its encodings. */
3213 uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
3214 if (uexe) {
Victor Stinnerae6265f2010-05-15 16:27:27 +00003215 cexe = PyUnicode_EncodeFSDefault(uexe);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003216 if (cexe)
3217 Tcl_FindExecutable(PyBytes_AsString(cexe));
3218 Py_XDECREF(cexe);
3219 Py_DECREF(uexe);
3220 }
Guido van Rossume187b0e2000-03-27 21:46:29 +00003221
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003222 if (PyErr_Occurred()) {
3223 Py_DECREF(m);
3224 return NULL;
3225 }
Guido van Rossum07e9fbf1998-02-06 22:35:46 +00003226
Guido van Rossum43ff8681998-07-14 18:02:13 +00003227#if 0
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003228 /* This was not a good idea; through <Destroy> bindings,
3229 Tcl_Finalize() may invoke Python code but at that point the
3230 interpreter and thread state have already been destroyed! */
3231 Py_AtExit(Tcl_Finalize);
Guido van Rossum26216371998-04-20 18:47:52 +00003232#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +00003233 return m;
Guido van Rossum18468821994-06-20 07:49:28 +00003234}